Support `#pragma clang section` directives on MachO targets
rdar://59560986 Differential Revision: https://reviews.llvm.org/D97233
This commit is contained in:
parent
ceaedfb5fc
commit
7f6e331645
|
@ -3091,6 +3091,8 @@ def err_only_annotate_after_access_spec : Error<
|
|||
|
||||
def err_attribute_section_invalid_for_target : Error<
|
||||
"argument to %select{'code_seg'|'section'}1 attribute is not valid for this target: %0">;
|
||||
def err_pragma_section_invalid_for_target : Error<
|
||||
"argument to #pragma section is not valid for this target: %0">;
|
||||
def warn_attribute_section_drectve : Warning<
|
||||
"#pragma %0(\".drectve\") has undefined behavior, "
|
||||
"use #pragma comment(linker, ...) instead">, InGroup<MicrosoftDrectveSection>;
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Frontend/OpenMP/OMPGridValues.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/VersionTuple.h"
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
@ -1115,15 +1116,15 @@ public:
|
|||
/// checking on attribute((section("foo"))) specifiers.
|
||||
///
|
||||
/// In this case, "foo" is passed in to be checked. If the section
|
||||
/// specifier is invalid, the backend should return a non-empty string
|
||||
/// that indicates the problem.
|
||||
/// specifier is invalid, the backend should return an Error that indicates
|
||||
/// the problem.
|
||||
///
|
||||
/// This hook is a simple quality of implementation feature to catch errors
|
||||
/// and give good diagnostics in cases when the assembler or code generator
|
||||
/// would otherwise reject the section specifier.
|
||||
///
|
||||
virtual std::string isValidSectionSpecifier(StringRef SR) const {
|
||||
return "";
|
||||
virtual llvm::Error isValidSectionSpecifier(StringRef SR) const {
|
||||
return llvm::Error::success();
|
||||
}
|
||||
|
||||
/// Set forced language options.
|
||||
|
|
|
@ -114,7 +114,7 @@ public:
|
|||
this->MCountName = "\01mcount";
|
||||
}
|
||||
|
||||
std::string isValidSectionSpecifier(StringRef SR) const override {
|
||||
llvm::Error isValidSectionSpecifier(StringRef SR) const override {
|
||||
// Let MCSectionMachO validate this.
|
||||
StringRef Segment, Section;
|
||||
unsigned TAA, StubSize;
|
||||
|
|
|
@ -301,6 +301,14 @@ void Sema::ActOnPragmaClangSection(SourceLocation PragmaLoc, PragmaClangSectionA
|
|||
return;
|
||||
}
|
||||
|
||||
if (llvm::Error E =
|
||||
Context.getTargetInfo().isValidSectionSpecifier(SecName)) {
|
||||
Diag(PragmaLoc, diag::err_pragma_section_invalid_for_target)
|
||||
<< toString(std::move(E));
|
||||
CSec->Valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (UnifySection(SecName, SectionFlags, PragmaLoc))
|
||||
return;
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/IR/Assumptions.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
|
@ -3052,10 +3053,10 @@ SectionAttr *Sema::mergeSectionAttr(Decl *D, const AttributeCommonInfo &CI,
|
|||
}
|
||||
|
||||
bool Sema::checkSectionName(SourceLocation LiteralLoc, StringRef SecName) {
|
||||
std::string Error = Context.getTargetInfo().isValidSectionSpecifier(SecName);
|
||||
if (!Error.empty()) {
|
||||
Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) << Error
|
||||
<< 1 /*'section'*/;
|
||||
if (llvm::Error E =
|
||||
Context.getTargetInfo().isValidSectionSpecifier(SecName)) {
|
||||
Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target)
|
||||
<< toString(std::move(E)) << 1 /*'section'*/;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -3073,10 +3074,9 @@ static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
|
|||
return;
|
||||
|
||||
// If the target wants to validate the section specifier, make it happen.
|
||||
std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(Str);
|
||||
if (!Error.empty()) {
|
||||
if (llvm::Error E = S.Context.getTargetInfo().isValidSectionSpecifier(Str)) {
|
||||
S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target)
|
||||
<< Error;
|
||||
<< toString(std::move(E));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3095,11 +3095,10 @@ static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
|
|||
// `#pragma code_seg("segname")` uses checkSectionName() instead.
|
||||
static bool checkCodeSegName(Sema &S, SourceLocation LiteralLoc,
|
||||
StringRef CodeSegName) {
|
||||
std::string Error =
|
||||
S.Context.getTargetInfo().isValidSectionSpecifier(CodeSegName);
|
||||
if (!Error.empty()) {
|
||||
if (llvm::Error E =
|
||||
S.Context.getTargetInfo().isValidSectionSpecifier(CodeSegName)) {
|
||||
S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target)
|
||||
<< Error << 0 /*'code-seg'*/;
|
||||
<< toString(std::move(E)) << 0 /*'code-seg'*/;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
// RUN: %clang_cc1 -emit-llvm -triple arm-none-eabi -o - %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -emit-llvm -triple arm-none-eabi -o - %s | FileCheck %s --check-prefixes=CHECK,ELF
|
||||
// RUN: %clang_cc1 -emit-llvm -triple arm64-apple-ios -o - %s | FileCheck %s --check-prefixes=CHECK,MACHO
|
||||
// Test that global variables, statics and functions are attached section-attributes
|
||||
// as per '#pragma clang section' directives.
|
||||
|
||||
extern "C" {
|
||||
// test with names for each section
|
||||
#ifdef __MACH__
|
||||
#pragma clang section bss = "__BSS,__mybss1" data = "__DATA,__mydata1" rodata = "__RODATA,__myrodata1"
|
||||
#pragma clang section text = "__TEXT,__mytext1"
|
||||
#else
|
||||
#pragma clang section bss="my_bss.1" data="my_data.1" rodata="my_rodata.1"
|
||||
#pragma clang section text="my_text.1"
|
||||
#endif
|
||||
int a; // my_bss.1
|
||||
int b = 1; // my_data.1
|
||||
int c[4]; // my_bss.1
|
||||
|
@ -19,7 +25,11 @@ int foo(void) { // my_text.1
|
|||
static int g[2]; // my_bss.1
|
||||
#pragma clang section bss=""
|
||||
int h; // default - .bss
|
||||
#ifdef __MACH__
|
||||
#pragma clang section data = "" bss = "__BSS,__mybss2" text = "__TEXT,__mytext2"
|
||||
#else
|
||||
#pragma clang section data="" bss="my_bss.2" text="my_text.2"
|
||||
#endif
|
||||
int i = 0; // my_bss.2
|
||||
extern const int j;
|
||||
const int j = 4; // default - .rodata
|
||||
|
@ -29,7 +39,11 @@ int goo(void) { // my_text.2
|
|||
static int lstat_h; // my_bss.2
|
||||
return zoo(g, &lstat_h);
|
||||
}
|
||||
#ifdef __MACH__
|
||||
#pragma clang section rodata = "__RODATA,__myrodata2" data = "__DATA,__mydata2" relro = "__RELRO,__myrelro2"
|
||||
#else
|
||||
#pragma clang section rodata="my_rodata.2" data="my_data.2" relro="my_relro.2"
|
||||
#endif
|
||||
int l = 5; // my_data.2
|
||||
extern const int m;
|
||||
const int m = 6; // my_rodata.2
|
||||
|
@ -65,19 +79,26 @@ int hoo(void) {
|
|||
//CHECK: @n ={{.*}} global i32 0, align 4
|
||||
//CHECK: @o ={{.*}} global i32 6, align 4
|
||||
//CHECK: @p ={{.*}} constant i32 7, align 4
|
||||
//CHECK: @_ZL5fptrs = internal constant [2 x i32 ()*] [i32 ()* @foo, i32 ()* @goo], align 4 #3
|
||||
//CHECK: @_ZL5fptrs = internal constant [2 x i32 ()*] [i32 ()* @foo, i32 ()* @goo], align {{4|8}} #3
|
||||
|
||||
//CHECK: define{{.*}} i32 @foo() #5 {
|
||||
//CHECK: define{{.*}} i32 @goo() #6 {
|
||||
//CHECK: declare i32 @zoo(i32*, i32*) #7
|
||||
//CHECK: define{{.*}} i32 @hoo() #8 {
|
||||
|
||||
//CHECK: attributes #0 = { "bss-section"="my_bss.1" "data-section"="my_data.1" "rodata-section"="my_rodata.1" }
|
||||
//CHECK: attributes #1 = { "data-section"="my_data.1" "rodata-section"="my_rodata.1" }
|
||||
//CHECK: attributes #2 = { "bss-section"="my_bss.2" "rodata-section"="my_rodata.1" }
|
||||
//CHECK: attributes #3 = { "bss-section"="my_bss.2" "data-section"="my_data.2" "relro-section"="my_relro.2" "rodata-section"="my_rodata.2" }
|
||||
//CHECK: attributes #4 = { "relro-section"="my_relro.2" }
|
||||
//CHECK: attributes #5 = { {{.*"implicit-section-name"="my_text.1".*}} }
|
||||
//CHECK: attributes #6 = { {{.*"implicit-section-name"="my_text.2".*}} }
|
||||
//ELF: attributes #0 = { "bss-section"="my_bss.1" "data-section"="my_data.1" "rodata-section"="my_rodata.1" }
|
||||
//ELF: attributes #1 = { "data-section"="my_data.1" "rodata-section"="my_rodata.1" }
|
||||
//ELF: attributes #2 = { "bss-section"="my_bss.2" "rodata-section"="my_rodata.1" }
|
||||
//ELF: attributes #3 = { "bss-section"="my_bss.2" "data-section"="my_data.2" "relro-section"="my_relro.2" "rodata-section"="my_rodata.2" }
|
||||
//ELF: attributes #4 = { "relro-section"="my_relro.2" }
|
||||
//ELF: attributes #5 = { {{.*"implicit-section-name"="my_text.1".*}} }
|
||||
//ELF: attributes #6 = { {{.*"implicit-section-name"="my_text.2".*}} }
|
||||
//MACHO: attributes #0 = { "bss-section"="__BSS,__mybss1" "data-section"="__DATA,__mydata1" "rodata-section"="__RODATA,__myrodata1" }
|
||||
//MACHO: attributes #1 = { "data-section"="__DATA,__mydata1" "rodata-section"="__RODATA,__myrodata1" }
|
||||
//MACHO: attributes #2 = { "bss-section"="__BSS,__mybss2" "rodata-section"="__RODATA,__myrodata1" }
|
||||
//MACHO: attributes #3 = { "bss-section"="__BSS,__mybss2" "data-section"="__DATA,__mydata2" "relro-section"="__RELRO,__myrelro2" "rodata-section"="__RODATA,__myrodata2" }
|
||||
//MACHO: attributes #4 = { "relro-section"="__RELRO,__myrelro2" }
|
||||
//MACHO: attributes #5 = { {{.*"implicit-section-name"="__TEXT,__mytext1".*}} }
|
||||
//MACHO: attributes #6 = { {{.*"implicit-section-name"="__TEXT,__mytext2".*}} }
|
||||
//CHECK-NOT: attributes #7 = { {{.*"implicit-section-name".*}} }
|
||||
//CHECK-NOT: attributes #8 = { {{.*"implicit-section-name".*}} }
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s -triple arm64-apple-ios
|
||||
|
||||
#pragma clang section bss = "" data = "" rodata = "" text = ""
|
||||
#pragma clang section bss = "" data = "" rodata = "" text = "__TEXT,__text"
|
||||
#pragma clang section bss = "" data = "" rodata = "" text = "badname" // expected-error {{argument to #pragma section is not valid for this target: mach-o section specifier requires a segment and section separated by a comma}}
|
||||
#pragma clang section bss = "" data = "" rodata = "" text = "__TEXT,__namethatiswaytoolong" // expected-error {{argument to #pragma section is not valid for this target: mach-o section specifier requires a section whose length is between 1 and 16 characters}}
|
||||
#pragma clang section
|
||||
|
||||
int a;
|
|
@ -59,14 +59,14 @@ public:
|
|||
/// appear after a .section directive in a mach-o flavored .s file. If
|
||||
/// successful, this fills in the specified Out parameters and returns an
|
||||
/// empty string. When an invalid section specifier is present, this returns
|
||||
/// a string indicating the problem. If no TAA was parsed, TAA is not altered,
|
||||
/// an Error indicating the problem. If no TAA was parsed, TAA is not altered,
|
||||
/// and TAAWasSet becomes false.
|
||||
static std::string ParseSectionSpecifier(StringRef Spec, // In.
|
||||
StringRef &Segment, // Out.
|
||||
StringRef &Section, // Out.
|
||||
unsigned &TAA, // Out.
|
||||
bool &TAAParsed, // Out.
|
||||
unsigned &StubSize); // Out.
|
||||
static Error ParseSectionSpecifier(StringRef Spec, // In.
|
||||
StringRef &Segment, // Out.
|
||||
StringRef &Section, // Out.
|
||||
unsigned &TAA, // Out.
|
||||
bool &TAAParsed, // Out.
|
||||
unsigned &StubSize); // Out.
|
||||
|
||||
void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
|
||||
raw_ostream &OS,
|
||||
|
|
|
@ -1129,13 +1129,12 @@ void TargetLoweringObjectFileMachO::emitModuleMetadata(MCStreamer &Streamer,
|
|||
StringRef Segment, Section;
|
||||
unsigned TAA = 0, StubSize = 0;
|
||||
bool TAAParsed;
|
||||
std::string ErrorCode =
|
||||
MCSectionMachO::ParseSectionSpecifier(SectionVal, Segment, Section,
|
||||
TAA, TAAParsed, StubSize);
|
||||
if (!ErrorCode.empty())
|
||||
if (Error E = MCSectionMachO::ParseSectionSpecifier(
|
||||
SectionVal, Segment, Section, TAA, TAAParsed, StubSize)) {
|
||||
// If invalid, report the error with report_fatal_error.
|
||||
report_fatal_error("Invalid section specifier '" + Section + "': " +
|
||||
ErrorCode + ".");
|
||||
report_fatal_error("Invalid section specifier '" + Section +
|
||||
"': " + toString(std::move(E)) + ".");
|
||||
}
|
||||
|
||||
// Get the section.
|
||||
MCSectionMachO *S = getContext().getMachOSection(
|
||||
|
@ -1159,6 +1158,14 @@ static void checkMachOComdat(const GlobalValue *GV) {
|
|||
|
||||
MCSection *TargetLoweringObjectFileMachO::getExplicitSectionGlobal(
|
||||
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
|
||||
|
||||
StringRef SectionName = GO->getSection();
|
||||
|
||||
const Function *F = dyn_cast<Function>(GO);
|
||||
if (F && F->hasFnAttribute("implicit-section-name")) {
|
||||
SectionName = F->getFnAttribute("implicit-section-name").getValueAsString();
|
||||
}
|
||||
|
||||
// Parse the section specifier and create it if valid.
|
||||
StringRef Segment, Section;
|
||||
unsigned TAA = 0, StubSize = 0;
|
||||
|
@ -1166,14 +1173,12 @@ MCSection *TargetLoweringObjectFileMachO::getExplicitSectionGlobal(
|
|||
|
||||
checkMachOComdat(GO);
|
||||
|
||||
std::string ErrorCode =
|
||||
MCSectionMachO::ParseSectionSpecifier(GO->getSection(), Segment, Section,
|
||||
TAA, TAAParsed, StubSize);
|
||||
if (!ErrorCode.empty()) {
|
||||
if (Error E = MCSectionMachO::ParseSectionSpecifier(
|
||||
SectionName, Segment, Section, TAA, TAAParsed, StubSize)) {
|
||||
// If invalid, report the error with report_fatal_error.
|
||||
report_fatal_error("Global variable '" + GO->getName() +
|
||||
"' has an invalid section specifier '" +
|
||||
GO->getSection() + "': " + ErrorCode + ".");
|
||||
GO->getSection() + "': " + toString(std::move(E)) + ".");
|
||||
}
|
||||
|
||||
// Get the section.
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/MC/SectionKind.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/SMLoc.h"
|
||||
|
@ -689,12 +690,9 @@ bool DarwinAsmParser::parseDirectiveSection(StringRef, SMLoc) {
|
|||
unsigned StubSize;
|
||||
unsigned TAA;
|
||||
bool TAAParsed;
|
||||
std::string ErrorStr =
|
||||
MCSectionMachO::ParseSectionSpecifier(SectionSpec, Segment, Section,
|
||||
TAA, TAAParsed, StubSize);
|
||||
|
||||
if (!ErrorStr.empty())
|
||||
return Error(Loc, ErrorStr);
|
||||
if (class Error E = MCSectionMachO::ParseSectionSpecifier(
|
||||
SectionSpec, Segment, Section, TAA, TAAParsed, StubSize))
|
||||
return Error(Loc, toString(std::move(E)));
|
||||
|
||||
// Issue a warning if the target is not powerpc and Section is a *coal* section.
|
||||
Triple TT = getParser().getContext().getObjectFileInfo()->getTargetTriple();
|
||||
|
|
|
@ -174,12 +174,12 @@ bool MCSectionMachO::isVirtualSection() const {
|
|||
/// flavored .s file. If successful, this fills in the specified Out
|
||||
/// parameters and returns an empty string. When an invalid section
|
||||
/// specifier is present, this returns a string indicating the problem.
|
||||
std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In.
|
||||
StringRef &Segment, // Out.
|
||||
StringRef &Section, // Out.
|
||||
unsigned &TAA, // Out.
|
||||
bool &TAAParsed, // Out.
|
||||
unsigned &StubSize) { // Out.
|
||||
Error MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In.
|
||||
StringRef &Segment, // Out.
|
||||
StringRef &Section, // Out.
|
||||
unsigned &TAA, // Out.
|
||||
bool &TAAParsed, // Out.
|
||||
unsigned &StubSize) { // Out.
|
||||
TAAParsed = false;
|
||||
|
||||
SmallVector<StringRef, 5> SplitSpec;
|
||||
|
@ -194,25 +194,23 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In.
|
|||
StringRef Attrs = GetEmptyOrTrim(3);
|
||||
StringRef StubSizeStr = GetEmptyOrTrim(4);
|
||||
|
||||
// Verify that the segment is present and not too long.
|
||||
if (Segment.empty() || Segment.size() > 16)
|
||||
return "mach-o section specifier requires a segment whose length is "
|
||||
"between 1 and 16 characters";
|
||||
|
||||
// Verify that the section is present and not too long.
|
||||
// Verify that the section is present.
|
||||
if (Section.empty())
|
||||
return "mach-o section specifier requires a segment and section "
|
||||
"separated by a comma";
|
||||
return createStringError(inconvertibleErrorCode(),
|
||||
"mach-o section specifier requires a segment "
|
||||
"and section separated by a comma");
|
||||
|
||||
// Verify that the section is not too long.
|
||||
if (Section.size() > 16)
|
||||
return "mach-o section specifier requires a section whose length is "
|
||||
"between 1 and 16 characters";
|
||||
return createStringError(inconvertibleErrorCode(),
|
||||
"mach-o section specifier requires a section "
|
||||
"whose length is between 1 and 16 characters");
|
||||
|
||||
// If there is no comma after the section, we're done.
|
||||
TAA = 0;
|
||||
StubSize = 0;
|
||||
if (SectionType.empty())
|
||||
return "";
|
||||
return Error::success();
|
||||
|
||||
// Figure out which section type it is.
|
||||
auto TypeDescriptor =
|
||||
|
@ -223,7 +221,9 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In.
|
|||
|
||||
// If we didn't find the section type, reject it.
|
||||
if (TypeDescriptor == std::end(SectionTypeDescriptors))
|
||||
return "mach-o section specifier uses an unknown section type";
|
||||
return createStringError(inconvertibleErrorCode(),
|
||||
"mach-o section specifier uses an unknown "
|
||||
"section type");
|
||||
|
||||
// Remember the TypeID.
|
||||
TAA = TypeDescriptor - std::begin(SectionTypeDescriptors);
|
||||
|
@ -233,9 +233,10 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In.
|
|||
if (Attrs.empty()) {
|
||||
// S_SYMBOL_STUBS always require a symbol stub size specifier.
|
||||
if (TAA == MachO::S_SYMBOL_STUBS)
|
||||
return "mach-o section specifier of type 'symbol_stubs' requires a size "
|
||||
"specifier";
|
||||
return "";
|
||||
return createStringError(inconvertibleErrorCode(),
|
||||
"mach-o section specifier of type "
|
||||
"'symbol_stubs' requires a size specifier");
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
// The attribute list is a '+' separated list of attributes.
|
||||
|
@ -249,7 +250,9 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In.
|
|||
return SectionAttr.trim() == Descriptor.AssemblerName;
|
||||
});
|
||||
if (AttrDescriptorI == std::end(SectionAttrDescriptors))
|
||||
return "mach-o section specifier has invalid attribute";
|
||||
return createStringError(inconvertibleErrorCode(),
|
||||
"mach-o section specifier has invalid "
|
||||
"attribute");
|
||||
|
||||
TAA |= AttrDescriptorI->AttrFlag;
|
||||
}
|
||||
|
@ -258,19 +261,24 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In.
|
|||
if (StubSizeStr.empty()) {
|
||||
// S_SYMBOL_STUBS always require a symbol stub size specifier.
|
||||
if (TAA == MachO::S_SYMBOL_STUBS)
|
||||
return "mach-o section specifier of type 'symbol_stubs' requires a size "
|
||||
"specifier";
|
||||
return "";
|
||||
return createStringError(inconvertibleErrorCode(),
|
||||
"mach-o section specifier of type "
|
||||
"'symbol_stubs' requires a size specifier");
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
// If we have a stub size spec, we must have a sectiontype of S_SYMBOL_STUBS.
|
||||
if ((TAA & MachO::SECTION_TYPE) != MachO::S_SYMBOL_STUBS)
|
||||
return "mach-o section specifier cannot have a stub size specified because "
|
||||
"it does not have type 'symbol_stubs'";
|
||||
return createStringError(inconvertibleErrorCode(),
|
||||
"mach-o section specifier cannot have a stub "
|
||||
"size specified because it does not have type "
|
||||
"'symbol_stubs'");
|
||||
|
||||
// Convert the stub size from a string to an integer.
|
||||
if (StubSizeStr.getAsInteger(0, StubSize))
|
||||
return "mach-o section specifier has a malformed stub size";
|
||||
return createStringError(inconvertibleErrorCode(),
|
||||
"mach-o section specifier has a malformed "
|
||||
"stub size");
|
||||
|
||||
return "";
|
||||
return Error::success();
|
||||
}
|
||||
|
|
|
@ -1919,9 +1919,8 @@ bool ModuleAddressSanitizer::shouldInstrumentGlobal(GlobalVariable *G) const {
|
|||
StringRef ParsedSegment, ParsedSection;
|
||||
unsigned TAA = 0, StubSize = 0;
|
||||
bool TAAParsed;
|
||||
std::string ErrorCode = MCSectionMachO::ParseSectionSpecifier(
|
||||
Section, ParsedSegment, ParsedSection, TAA, TAAParsed, StubSize);
|
||||
assert(ErrorCode.empty() && "Invalid section specifier.");
|
||||
cantFail(MCSectionMachO::ParseSectionSpecifier(
|
||||
Section, ParsedSegment, ParsedSection, TAA, TAAParsed, StubSize));
|
||||
|
||||
// Ignore the globals from the __OBJC section. The ObjC runtime assumes
|
||||
// those conform to /usr/lib/objc/runtime.h, so we can't add redzones to
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
;RUN: llc -mtriple=arm64-apple-ios %s -o - | FileCheck %s
|
||||
|
||||
define dso_local void @foo() #0 {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
attributes #0 = { "implicit-section-name"="__TEXT,__mytext" }
|
||||
|
||||
; CHECK: .section __TEXT,__mytext
|
||||
; CHECK-NEXT: .globl _foo
|
Loading…
Reference in New Issue