[lld] 27b426b - [lld-macho] Implement builtin section renaming

Greg McGary via llvm-commits llvm-commits at lists.llvm.org
Mon May 3 21:47:08 PDT 2021


Author: Greg McGary
Date: 2021-05-03T21:26:51-07:00
New Revision: 27b426b0c8ab388fa7729c0ca2fe1d97141bcb72

URL: https://github.com/llvm/llvm-project/commit/27b426b0c8ab388fa7729c0ca2fe1d97141bcb72
DIFF: https://github.com/llvm/llvm-project/commit/27b426b0c8ab388fa7729c0ca2fe1d97141bcb72.diff

LOG: [lld-macho] Implement builtin section renaming

ld64 automatically renames many sections depending on output type and assorted flags. Here, we implement the most common configs. We can add more obscure flags and behaviors as needed.

Depends on D101393

Differential Revision: https://reviews.llvm.org/D101395

Added: 
    lld/test/MachO/builtin-rename.s

Modified: 
    lld/MachO/Config.h
    lld/MachO/Driver.cpp
    lld/MachO/MergedOutputSection.cpp
    lld/MachO/MergedOutputSection.h
    lld/MachO/Options.td
    lld/MachO/Writer.cpp
    lld/test/MachO/load-command-sequence.s
    lld/test/MachO/local-got.s
    lld/test/MachO/x86-64-relocs.s
    lld/test/MachO/x86-64-stubs.s

Removed: 
    


################################################################################
diff  --git a/lld/MachO/Config.h b/lld/MachO/Config.h
index fdd3e6c921219..eff3ff53f3bce 100644
--- a/lld/MachO/Config.h
+++ b/lld/MachO/Config.h
@@ -92,6 +92,7 @@ struct Configuration {
   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
index e3d266b46596c..133d3ba6e8e4c 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -558,6 +558,33 @@ static void replaceCommonSymbols() {
   }
 }
 
+static void initializeSectionRenameMap() {
+  if (config->dataConst) {
+    SmallVector<StringRef> v{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};
+    for (StringRef s : v)
+      config->sectionRenameMap[{segment_names::data, s}] = {
+          segment_names::dataConst, s};
+  }
+  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';
@@ -757,6 +784,26 @@ static uint32_t parseProtection(StringRef protStr) {
   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:
+    return false;
+  default:
+    llvm_unreachable(
+        "unsupported output type for determining data-const default");
+  }
+  return false;
+}
+
 void SymbolPatterns::clear() {
   literals.clear();
   globs.clear();
@@ -1002,6 +1049,11 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
       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));
+  // Populate config->sectionRenameMap with builtin default renames.
+  // Options -rename_section and -rename_segment are able to override.
+  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
index 9a74925ce9670..c0e4d68a7503c 100644
--- a/lld/MachO/MergedOutputSection.cpp
+++ b/lld/MachO/MergedOutputSection.cpp
@@ -7,9 +7,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "MergedOutputSection.h"
+#include "OutputSegment.h"
 #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;
@@ -21,8 +23,8 @@ void MergedOutputSection::mergeInput(InputSection *input) {
     align = input->align;
     flags = input->flags;
   } else {
-    mergeFlags(input->flags);
     align = std::max(align, input->align);
+    mergeFlags(input);
   }
 
   inputs.push_back(input);
@@ -52,21 +54,25 @@ void MergedOutputSection::writeTo(uint8_t *buf) const {
 // TODO: this is most likely wrong; reconsider how section flags
 // are actually merged. The logic presented here was written without
 // any form of informed research.
-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));
+void MergedOutputSection::mergeFlags(InputSection *input) {
+  uint8_t baseType = flags & SECTION_TYPE;
+  uint8_t inputType = input->flags & SECTION_TYPE;
+  if (baseType != inputType)
+    error("Cannot merge section " + input->name + " (type=0x" +
+          to_hexString(inputType) + ") into " + name + " (type=0x" +
+          to_hexString(baseType) + "): inconsistent types");
 
-  uint32_t inconsistentFlags = S_ATTR_DEBUG | S_ATTR_STRIP_STATIC_SYMS |
-                               S_ATTR_NO_DEAD_STRIP | S_ATTR_LIVE_SUPPORT;
-  if ((inputFlags ^ flags) & inconsistentFlags)
-    error("Cannot add merge section; cannot merge inconsistent flags");
+  constexpr uint32_t strictFlags = S_ATTR_DEBUG | S_ATTR_STRIP_STATIC_SYMS |
+                                   S_ATTR_NO_DEAD_STRIP | S_ATTR_LIVE_SUPPORT;
+  if ((input->flags ^ flags) & strictFlags)
+    error("Cannot merge section " + input->name + " (flags=0x" +
+          to_hexString(input->flags) + ") into " + name + " (flags=0x" +
+          to_hexString(flags) + "): strict flags 
diff er");
 
   // Negate pure instruction presence if any section isn't pure.
-  uint32_t pureMask = ~S_ATTR_PURE_INSTRUCTIONS | (inputFlags & flags);
+  uint32_t pureMask = ~S_ATTR_PURE_INSTRUCTIONS | (input->flags & flags);
 
   // Merge the rest
-  flags |= inputFlags;
+  flags |= input->flags;
   flags &= pureMask;
 }

diff  --git a/lld/MachO/MergedOutputSection.h b/lld/MachO/MergedOutputSection.h
index 279a7e0f75cd7..0f55546c13591 100644
--- a/lld/MachO/MergedOutputSection.h
+++ b/lld/MachO/MergedOutputSection.h
@@ -44,7 +44,7 @@ class MergedOutputSection : public OutputSection {
   }
 
 private:
-  void mergeFlags(uint32_t inputFlags);
+  void mergeFlags(InputSection *input);
 
   size_t size = 0;
   uint64_t fileSize = 0;

diff  --git a/lld/MachO/Options.td b/lld/MachO/Options.td
index 344e8b2b4ce56..d950559ed2b86 100644
--- a/lld/MachO/Options.td
+++ b/lld/MachO/Options.td
@@ -635,6 +635,16 @@ def trace_symbol_layout : Flag<["-"], "trace_symbol_layout">,
     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<grp_rare>;
+def data_const : Flag<["-"], "data_const">,
+    HelpText<"Force migration of readonly data into __DATA_CONST segment">,
+    Group<grp_rare>;
+def no_data_const : Flag<["-"], "no_data_const">,
+    HelpText<"Block migration of readonly data away from __DATA segment">,
+    Group<grp_rare>;
+def text_exec : Flag<["-"], "text_exec">,
+    HelpText<"Rename __segment TEXT to __TEXT_EXEC for sections __text and __stubs">,
+    Flags<[HelpHidden]>,
+    Group<grp_rare>;
 def section_order : MultiArg<["-"], "section_order", 2>,
     MetaVarName<"<segment> <sections>">,
     HelpText<"With -preload, specify layout sequence of colon-separated <sections> in <segment>">,
@@ -1134,14 +1144,6 @@ def classic_linker : Flag<["-"], "classic_linker">,
     HelpText<"This option is undocumented in ld64">,
     Flags<[HelpHidden]>,
     Group<grp_undocumented>;
-def data_const : Flag<["-"], "data_const">,
-    HelpText<"This option is undocumented in ld64">,
-    Flags<[HelpHidden]>,
-    Group<grp_undocumented>;
-def no_data_const : Flag<["-"], "no_data_const">,
-    HelpText<"This option is undocumented in ld64">,
-    Flags<[HelpHidden]>,
-    Group<grp_undocumented>;
 def data_in_code_info : Flag<["-"], "data_in_code_info">,
     HelpText<"This option is undocumented in ld64">,
     Flags<[HelpHidden]>,
@@ -1286,10 +1288,6 @@ def source_version : Flag<["-"], "source_version">,
     HelpText<"This option is undocumented in ld64">,
     Flags<[HelpHidden]>,
     Group<grp_undocumented>;
-def text_exec : Flag<["-"], "text_exec">,
-    HelpText<"This option is undocumented in ld64">,
-    Flags<[HelpHidden]>,
-    Group<grp_undocumented>;
 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
index 5c4465e2a24ee..a4da569006cf2 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -774,7 +774,8 @@ static int sectionOrder(OutputSection *osec) {
         .Case(section_names::unwindInfo, std::numeric_limits<int>::max() - 1)
         .Case(section_names::ehFrame, std::numeric_limits<int>::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
index 0000000000000..5cae3e01297b1
--- /dev/null
+++ b/lld/test/MachO/builtin-rename.s
@@ -0,0 +1,170 @@
+# REQUIRES: x86
+# RUN: rm -rf %t; split-file %s %t
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin \
+# RUN:     %t/main.s -o %t/main.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin \
+# RUN:     %t/renames.s -o %t/renames.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin \
+# RUN:     %t/error.s -o %t/error.o
+
+# RUN: not %lld            -o %t/error %t/main.o %t/error.o -lSystem 2>&1 | \
+# RUN:     FileCheck %s --check-prefix=ERROR
+
+## Check the error diagnostic for merging mismatched section types
+# ERROR: Cannot merge section __pointers (type=0x0) into __nl_symbol_ptr (type=0x6): inconsistent types
+
+## Check that section and segment renames happen as expected
+# RUN: %lld                -o %t/ydata %t/main.o %t/renames.o -lSystem
+# RUN: %lld -no_data_const -o %t/ndata %t/main.o %t/renames.o -lSystem
+# RUN: %lld -no_pie        -o %t/nopie %t/main.o %t/renames.o -lSystem
+
+# 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
+# RUN: llvm-objdump --syms %t/nopie | \
+# 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
+
+#--- renames.s
+.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
+
+#--- error.s
+
+.section __DATA,__nl_symbol_ptr
+.global __DATA__nl_symbol_ptr
+__DATA__nl_symbol_ptr:
+  .space 8
+
+.section __IMPORT,__pointers
+.global __IMPORT__pointers
+__IMPORT__pointers:
+  .space 8
+
+#--- main.s
+.text
+.global _main
+_main:
+  ret

diff  --git a/lld/test/MachO/load-command-sequence.s b/lld/test/MachO/load-command-sequence.s
index 734b7d1c65957..028b0ed8a7149 100644
--- 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
index ef231f085000f..42a417e4c5056 100644
--- 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
index 8e94744540011..76f677b72623f 100644
--- 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
index 905ace572d630..384bf56499164 100644
--- 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


        


More information about the llvm-commits mailing list