diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h --- a/lld/MachO/Config.h +++ b/lld/MachO/Config.h @@ -92,6 +92,7 @@ bool emitBitcodeBundle = false; bool emitEncryptionInfo = false; bool timeTraceEnabled = false; + bool dataConst = false; uint32_t headerPad; uint32_t dylibCompatibilityVersion = 0; uint32_t dylibCurrentVersion = 0; diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -557,6 +557,33 @@ } } +// LD64 gives precedence to command-line renames via -rename_section and +// -rename_segment + +static void initializeSectionRenameMap() { + if (config->dataConst) { + for (StringRef s : + {section_names::got, section_names::authGot, section_names::authPtr, + section_names::nonLazySymbolPtr, section_names::const_, + section_names::cfString, section_names::moduleInitFunc, + section_names::moduleTermFunc, section_names::objcClassList, + section_names::objcNonLazyClassList, section_names::objcCatList, + section_names::objcNonLazyCatList, section_names::objcProtoList, + section_names::objcImageInfo}) + config->sectionRenameMap[{segment_names::data, s}] = { + segment_names::dataConst, s}; + } + + // Note: ld64 handles all renames above this line textually. For + // renames below this line, ld64 reassigns internal section-id enums. + // We will endeavor to do them all textually + config->sectionRenameMap[{segment_names::text, section_names::staticInit}] = { + segment_names::text, section_names::text}; + config->sectionRenameMap[{segment_names::import, section_names::pointers}] = { + config->dataConst ? segment_names::dataConst : segment_names::data, + section_names::nonLazySymbolPtr}; +} + static inline char toLowerDash(char x) { if (x >= 'A' && x <= 'Z') return x - 'A' + 'a'; @@ -773,6 +800,26 @@ return prot; } +static bool dataConstDefault(const InputArgList &args) { + switch (config->outputType) { + case MH_EXECUTE: + return !args.hasArg(OPT_no_pie); + case MH_BUNDLE: + // FIXME: return false when -final_name ... + // has prefix "/System/Library/UserEventPlugins/" + // or matches "/usr/libexec/locationd" "/usr/libexec/terminusd" + return true; + case MH_DYLIB: + return true; + case MH_OBJECT: + case MH_PRELOAD: + return false; + default: + llvm_unreachable("output type to determine data-const"); + } + return false; +} + void SymbolPatterns::clear() { literals.clear(); globs.clear(); @@ -1018,6 +1065,9 @@ parseDylibVersion(args, OPT_compatibility_version); config->dylibCurrentVersion = parseDylibVersion(args, OPT_current_version); + config->dataConst = + args.hasFlag(OPT_data_const, OPT_no_data_const, dataConstDefault(args)); + initializeSectionRenameMap(); // Reject every special character except '.' and '$' // TODO(gkm): verify that this is the proper set of invalid chars StringRef invalidNameChars("!\"#%&'()*+,-/:;<=>?@[\\]^`{|}~"); diff --git a/lld/MachO/MergedOutputSection.cpp b/lld/MachO/MergedOutputSection.cpp --- a/lld/MachO/MergedOutputSection.cpp +++ b/lld/MachO/MergedOutputSection.cpp @@ -10,6 +10,7 @@ #include "lld/Common/ErrorHandler.h" #include "lld/Common/Memory.h" #include "llvm/BinaryFormat/MachO.h" +#include "llvm/Support/ScopedPrinter.h" using namespace llvm; using namespace llvm::MachO; @@ -55,8 +56,9 @@ void MergedOutputSection::mergeFlags(uint32_t inputFlags) { uint8_t sectionFlag = SECTION_TYPE & inputFlags; if (sectionFlag != (SECTION_TYPE & flags)) - error("Cannot add merge section; inconsistent type flags " + - Twine(sectionFlag)); + error("Cannot add merge section; inconsistent type: old=0x" + + llvm::to_hexString(SECTION_TYPE & flags) + ", new=0x" + + llvm::to_hexString(sectionFlag)); uint32_t inconsistentFlags = S_ATTR_DEBUG | S_ATTR_STRIP_STATIC_SYMS | S_ATTR_NO_DEAD_STRIP | S_ATTR_LIVE_SUPPORT; diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td --- a/lld/MachO/Options.td +++ b/lld/MachO/Options.td @@ -635,6 +635,16 @@ HelpText<"Show where and why symbols move, as specified by -move_to_ro_segment, -move_to_rw_segment, -rename_section, and -rename_segment">, Flags<[HelpHidden]>, Group; +def data_const : Flag<["-"], "data_const">, + HelpText<"Force migration of readonly data into __DATA_CONST segment">, + Group; +def no_data_const : Flag<["-"], "no_data_const">, + HelpText<"Block migration of readonly data away from __DATA segment">, + Group; +def text_exec : Flag<["-"], "text_exec">, + HelpText<"Rename __segment TEXT to __TEXT_EXEC for sections __text and __stubs">, + Flags<[HelpHidden]>, + Group; def section_order : MultiArg<["-"], "section_order", 2>, MetaVarName<" ">, HelpText<"With -preload, specify layout sequence of colon-separated in ">, @@ -1134,14 +1144,6 @@ HelpText<"This option is undocumented in ld64">, Flags<[HelpHidden]>, Group; -def data_const : Flag<["-"], "data_const">, - HelpText<"This option is undocumented in ld64">, - Flags<[HelpHidden]>, - Group; -def no_data_const : Flag<["-"], "no_data_const">, - HelpText<"This option is undocumented in ld64">, - Flags<[HelpHidden]>, - Group; def data_in_code_info : Flag<["-"], "data_in_code_info">, HelpText<"This option is undocumented in ld64">, Flags<[HelpHidden]>, @@ -1286,10 +1288,6 @@ HelpText<"This option is undocumented in ld64">, Flags<[HelpHidden]>, Group; -def text_exec : Flag<["-"], "text_exec">, - HelpText<"This option is undocumented in ld64">, - Flags<[HelpHidden]>, - Group; def threaded_starts_section : Flag<["-"], "threaded_starts_section">, HelpText<"This option is undocumented in ld64">, Flags<[HelpHidden]>, diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -774,7 +774,8 @@ .Case(section_names::unwindInfo, std::numeric_limits::max() - 1) .Case(section_names::ehFrame, std::numeric_limits::max()) .Default(0); - } else if (segname == segment_names::data) { + } else if (segname == segment_names::data || + segname == segment_names::dataConst) { // For each thread spawned, dyld will initialize its TLVs by copying the // address range from the start of the first thread-local data section to // the end of the last one. We therefore arrange these sections contiguously diff --git a/lld/test/MachO/builtin-rename.s b/lld/test/MachO/builtin-rename.s new file mode 100644 --- /dev/null +++ b/lld/test/MachO/builtin-rename.s @@ -0,0 +1,142 @@ +# REQUIRES: x86 +# RUN: rm -fr %t +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o 2>/dev/null +# RUN: %lld -o %t-ydata %t.o -lSystem +# RUN: %lld -no_data_const -o %t-ndata %t.o -lSystem +# RUN: %lld -no_pie -o %t-ndata %t.o -lSystem + +## Check that section and segment renames happen +# RUN: llvm-objdump --syms %t-ydata | \ +# RUN: FileCheck %s --check-prefixes=CHECK,YDATA +# RUN: llvm-objdump --syms %t-ndata | \ +# RUN: Filecheck %s --check-prefixes=CHECK,NDATA + +# CHECK-LABEL: {{^}}SYMBOL TABLE: + +# CHECK-DAG: __TEXT,__text __TEXT__StaticInit + +# NDATA-DAG: __DATA,__auth_got __DATA__auth_got +# NDATA-DAG: __DATA,__auth_ptr __DATA__auth_ptr +# NDATA-DAG: __DATA,__nl_symbol_ptr __DATA__nl_symbol_ptr +# NDATA-DAG: __DATA,__const __DATA__const +# NDATA-DAG: __DATA,__cfstring __DATA__cfstring +# NDATA-DAG: __DATA,__mod_init_func __DATA__mod_init_func +# NDATA-DAG: __DATA,__mod_term_func __DATA__mod_term_func +# NDATA-DAG: __DATA,__objc_classlist __DATA__objc_classlist +# NDATA-DAG: __DATA,__objc_nlclslist __DATA__objc_nlclslist +# NDATA-DAG: __DATA,__objc_catlist __DATA__objc_catlist +# NDATA-DAG: __DATA,__objc_nlcatlist __DATA__objc_nlcatlist +# NDATA-DAG: __DATA,__objc_protolist __DATA__objc_protolist +# NDATA-DAG: __DATA,__objc_imageinfo __DATA__objc_imageinfo +# NDATA-DAG: __DATA,__nl_symbol_ptr __IMPORT__pointers + +# YDATA-DAG: __DATA_CONST,__auth_got __DATA__auth_got +# YDATA-DAG: __DATA_CONST,__auth_ptr __DATA__auth_ptr +# YDATA-DAG: __DATA_CONST,__nl_symbol_ptr __DATA__nl_symbol_ptr +# YDATA-DAG: __DATA_CONST,__const __DATA__const +# YDATA-DAG: __DATA_CONST,__cfstring __DATA__cfstring +# YDATA-DAG: __DATA_CONST,__mod_init_func __DATA__mod_init_func +# YDATA-DAG: __DATA_CONST,__mod_term_func __DATA__mod_term_func +# YDATA-DAG: __DATA_CONST,__objc_classlist __DATA__objc_classlist +# YDATA-DAG: __DATA_CONST,__objc_nlclslist __DATA__objc_nlclslist +# YDATA-DAG: __DATA_CONST,__objc_catlist __DATA__objc_catlist +# YDATA-DAG: __DATA_CONST,__objc_nlcatlist __DATA__objc_nlcatlist +# YDATA-DAG: __DATA_CONST,__objc_protolist __DATA__objc_protolist +# YDATA-DAG: __DATA_CONST,__objc_imageinfo __DATA__objc_imageinfo +# YDATA-DAG: __DATA_CONST,__nl_symbol_ptr __IMPORT__pointers + + +.section __DATA,__auth_got +.global __DATA__auth_got +__DATA__auth_got: + .space 8 + +.section __DATA,__auth_ptr +.global __DATA__auth_ptr +__DATA__auth_ptr: + .space 8 + +.section __DATA,__nl_symbol_ptr +.global __DATA__nl_symbol_ptr +__DATA__nl_symbol_ptr: + .space 8 + +.section __DATA,__const +.global __DATA__const +__DATA__const: + .space 8 + +.section __DATA,__cfstring +.global __DATA__cfstring +__DATA__cfstring: + .space 8 + +# FIXME: error: conflicts with synthetic section ... +# FIXME: we can't explicitly define syms in synthetic sections +# COM: .section __DATA,__got +# COM: .global __DATA__got +# COM: __DATA__got: +# COM: .space 8 + +.section __DATA,__mod_init_func,mod_init_funcs +.global __DATA__mod_init_func +__DATA__mod_init_func: + .space 8 + +.section __DATA,__mod_term_func,mod_term_funcs +.global __DATA__mod_term_func +__DATA__mod_term_func: + .space 8 + +.section __DATA,__objc_classlist +.global __DATA__objc_classlist +__DATA__objc_classlist: + .space 8 + +.section __DATA,__objc_nlclslist +.global __DATA__objc_nlclslist +__DATA__objc_nlclslist: + .space 8 + +.section __DATA,__objc_catlist +.global __DATA__objc_catlist +__DATA__objc_catlist: + .space 8 + +.section __DATA,__objc_nlcatlist +.global __DATA__objc_nlcatlist +__DATA__objc_nlcatlist: + .space 8 + +.section __DATA,__objc_protolist +.global __DATA__objc_protolist +__DATA__objc_protolist: + .space 8 + +.section __DATA,__objc_imageinfo +.global __DATA__objc_imageinfo +__DATA__objc_imageinfo: + .space 8 + +# FIXME: error: conflicts with synthetic section ... +# FIXME: we can't explicitly define syms in synthetic sections +# COM: .section __DATA,__la_symbol_ptr,lazy_symbol_pointers +# COM: .global __DATA__la_symbol_ptr +# COM: __DATA__la_symbol_ptr: +# COM: .space 8 + +.section __IMPORT,__pointers,non_lazy_symbol_pointers +.global __IMPORT__pointers +__IMPORT__pointers: + .space 8 + +.section __TEXT,__StaticInit +.section __TEXT,__StaticInit +.global __TEXT__StaticInit +__TEXT__StaticInit: + .space 8 + +.text +.global _main +_main: + ret diff --git a/lld/test/MachO/load-command-sequence.s b/lld/test/MachO/load-command-sequence.s --- a/lld/test/MachO/load-command-sequence.s +++ b/lld/test/MachO/load-command-sequence.s @@ -28,14 +28,14 @@ # COMMON: segname __TEXT # COMMON: cmd LC_SEGMENT_64 # COMMON: segname __DATA_CONST +# COMMON: sectname __const +# COMMON: segname __DATA_CONST # COMMON: sectname __got # COMMON: segname __DATA_CONST # COMMON: cmd LC_SEGMENT_64 # COMMON: segname __DATA # COMMON: sectname __data # COMMON: segname __DATA -# COMMON: sectname __const -# COMMON: segname __DATA # COMMON: cmd LC_SEGMENT_64 # COMMON: segname __LINKEDIT # COMMON: cmd LC_DYLD_INFO_ONLY diff --git a/lld/test/MachO/local-got.s b/lld/test/MachO/local-got.s --- a/lld/test/MachO/local-got.s +++ b/lld/test/MachO/local-got.s @@ -8,7 +8,7 @@ # RUN: %lld -lSystem -o %t/test %t/test.o -L%t -lhello # RUN: llvm-objdump --macho --full-contents --rebase --bind %t/test | FileCheck %s --check-prefixes=CHECK,PIE --match-full-lines -# RUN: %lld -no_pie -lSystem -o %t/test %t/test.o -L%t -lhello +# RUN: %lld -no_pie -data_const -lSystem -o %t/test %t/test.o -L%t -lhello # RUN: llvm-objdump --macho --full-contents --rebase --bind %t/test | FileCheck %s --check-prefixes=CHECK,NO-PIE --match-full-lines ## Check that the GOT references the cstrings. --full-contents displays the diff --git a/lld/test/MachO/x86-64-relocs.s b/lld/test/MachO/x86-64-relocs.s --- a/lld/test/MachO/x86-64-relocs.s +++ b/lld/test/MachO/x86-64-relocs.s @@ -20,7 +20,7 @@ # CHECK-NEXT: [[#%x, CSTRING_ADDR + 22 - LSTR_OFF]] # RUN: llvm-objdump --section=__const --full-contents %t | FileCheck %s --check-prefix=NONPCREL -# NONPCREL: Contents of section __DATA,__const: +# NONPCREL: Contents of section __DATA_CONST,__const: # NONPCREL-NEXT: 100001000 18040000 01000000 18040000 01000000 .section __TEXT,__text diff --git a/lld/test/MachO/x86-64-stubs.s b/lld/test/MachO/x86-64-stubs.s --- a/lld/test/MachO/x86-64-stubs.s +++ b/lld/test/MachO/x86-64-stubs.s @@ -12,7 +12,7 @@ # RUN: -o %t/libgoodbye.dylib # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t/dylink-lazy.o -# RUN: %lld -no_pie -o %t/dylink-lazy-no-pie \ +# RUN: %lld -no_pie -data_const -o %t/dylink-lazy-no-pie \ # RUN: -L%t -lhello -lgoodbye %t/dylink-lazy.o -lSystem ## When looking at the __stubs section alone, we are unable to easily tell which