[lld] 9ab49ae - [lld/mac] Implement -sectalign

Nico Weber via llvm-commits llvm-commits at lists.llvm.org
Tue May 11 10:31:52 PDT 2021


Author: Nico Weber
Date: 2021-05-11T13:31:32-04:00
New Revision: 9ab49ae55dd7b928c2b806adccf6d07a89e59102

URL: https://github.com/llvm/llvm-project/commit/9ab49ae55dd7b928c2b806adccf6d07a89e59102
DIFF: https://github.com/llvm/llvm-project/commit/9ab49ae55dd7b928c2b806adccf6d07a89e59102.diff

LOG: [lld/mac] Implement -sectalign

clang sometimes passes this flag along (see D68351), so we should implement it.

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

Added: 
    lld/test/MachO/sectalign.s

Modified: 
    lld/MachO/Config.h
    lld/MachO/Driver.cpp
    lld/MachO/Options.td
    lld/MachO/OutputSegment.cpp

Removed: 
    


################################################################################
diff  --git a/lld/MachO/Config.h b/lld/MachO/Config.h
index 077762c850840..471d5dae73117 100644
--- a/lld/MachO/Config.h
+++ b/lld/MachO/Config.h
@@ -51,6 +51,12 @@ enum class UndefinedSymbolTreatment {
   dynamic_lookup,
 };
 
+struct SectionAlign {
+  llvm::StringRef segName;
+  llvm::StringRef sectName;
+  uint32_t align;
+};
+
 struct SegmentProtection {
   llvm::StringRef name;
   uint32_t maxProt;
@@ -115,8 +121,9 @@ struct Configuration {
   std::vector<llvm::StringRef> runtimePaths;
   std::vector<std::string> astPaths;
   std::vector<Symbol *> explicitUndefineds;
-  // There are typically very few custom segmentProtections, so use a vector
-  // instead of a map.
+  // There are typically few custom sectionAlignments or segmentProtections,
+  // so use a vector instead of a map.
+  std::vector<SectionAlign> sectionAlignments;
   std::vector<SegmentProtection> segmentProtections;
 
   llvm::DenseMap<llvm::StringRef, SymbolPriorityEntry> priorities;

diff  --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index a5d74853d3e79..58a6036da3dfa 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -751,6 +751,30 @@ static uint32_t parseProtection(StringRef protStr) {
   return prot;
 }
 
+static std::vector<SectionAlign> parseSectAlign(const opt::InputArgList &args) {
+  std::vector<SectionAlign> sectAligns;
+  for (const Arg *arg : args.filtered(OPT_sectalign)) {
+    StringRef segName = arg->getValue(0);
+    StringRef sectName = arg->getValue(1);
+    StringRef alignStr = arg->getValue(2);
+    if (alignStr.startswith("0x") || alignStr.startswith("0X"))
+      alignStr = alignStr.drop_front(2);
+    uint32_t align;
+    if (alignStr.getAsInteger(16, align)) {
+      error("-sectalign: failed to parse '" + StringRef(arg->getValue(2)) +
+            "' as number");
+      continue;
+    }
+    if (!isPowerOf2_32(align)) {
+      error("-sectalign: '" + StringRef(arg->getValue(2)) +
+            "' (in base 16) not a power of two");
+      continue;
+    }
+    sectAligns.push_back({segName, sectName, align});
+  }
+  return sectAligns;
+}
+
 static bool dataConstDefault(const InputArgList &args) {
   switch (config->outputType) {
   case MH_EXECUTE:
@@ -1039,6 +1063,8 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
         validName(arg->getValue(1));
   }
 
+  config->sectionAlignments = parseSectAlign(args);
+
   for (const Arg *arg : args.filtered(OPT_segprot)) {
     StringRef segName = arg->getValue(0);
     uint32_t maxProt = parseProtection(arg->getValue(1));

diff  --git a/lld/MachO/Options.td b/lld/MachO/Options.td
index d950559ed2b86..44fddc72a11a9 100644
--- a/lld/MachO/Options.td
+++ b/lld/MachO/Options.td
@@ -778,7 +778,6 @@ def segalign : Separate<["-"], "segalign">,
 def sectalign : MultiArg<["-"], "sectalign", 3>,
     MetaVarName<"<segment> <section> <boundary>">,
     HelpText<"Align <section> within <segment> to hex power-of-2 <boundary>">,
-    Flags<[HelpHidden]>,
     Group<grp_rare>;
 def stack_addr : Separate<["-"], "stack_addr">,
     MetaVarName<"<address>">,

diff  --git a/lld/MachO/OutputSegment.cpp b/lld/MachO/OutputSegment.cpp
index a561a5a6037d9..d860ac8d59818 100644
--- a/lld/MachO/OutputSegment.cpp
+++ b/lld/MachO/OutputSegment.cpp
@@ -52,6 +52,10 @@ size_t OutputSegment::numNonHiddenSections() const {
 void OutputSegment::addOutputSection(OutputSection *osec) {
   osec->parent = this;
   sections.push_back(osec);
+
+  for (const SectionAlign &sectAlign : config->sectionAlignments)
+    if (sectAlign.segName == name && sectAlign.sectName == osec->name)
+      osec->align = sectAlign.align;
 }
 
 static DenseMap<StringRef, OutputSegment *> nameToOutputSegment;

diff  --git a/lld/test/MachO/sectalign.s b/lld/test/MachO/sectalign.s
new file mode 100644
index 0000000000000..9eb8bf328ea43
--- /dev/null
+++ b/lld/test/MachO/sectalign.s
@@ -0,0 +1,42 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o
+
+# RUN: not %lld -dylib -o %t %t.o -sectalign __TEXT __text asdf 2>&1 \
+# RUN:     | FileCheck --check-prefix=NONUM -DNUM=asdf %s
+# RUN: not %lld -dylib -o %t %t.o -sectalign __TEXT __text 0x0X4 2>&1 \
+# RUN:     | FileCheck --check-prefix=NONUM -DNUM=0x0X4 %s
+# NONUM: error: -sectalign: failed to parse '[[NUM]]' as number
+
+# RUN: not %lld -dylib -o %t %t.o -sectalign __TEXT __text 16 2>&1 \
+# RUN:     | FileCheck --check-prefix=NOPOW -DNUM=16 %s
+# RUN: not %lld -dylib -o %t %t.o -sectalign __TEXT __text 0x16 2>&1 \
+# RUN:     | FileCheck --check-prefix=NOPOW -DNUM=0x16 %s
+# RUN: not %lld -dylib -o %t %t.o -sectalign __TEXT __text 0 2>&1 \
+# RUN:     | FileCheck --check-prefix=NOPOW -DNUM=0 %s
+# NOPOW:  error: -sectalign: '[[NUM]]' (in base 16) not a power of two
+
+## __DATA_CONST tests that the flag applies to names after section renaming.
+# RUN: %lld -dylib -o %t %t.o -sectalign __TEXT __text 20 \
+# RUN:                        -sectalign __DATA_CONST __const 0x40
+# RUN: llvm-readobj --section-headers %t \
+# RUN:     | FileCheck -DSECT=__text -DSEG=__TEXT -DALIGN=5 %s
+# RUN: llvm-readobj --section-headers %t \
+# RUN:     | FileCheck -DSECT=__const -DSEG=__DATA_CONST -DALIGN=6 %s
+
+# RUN: %lld -dylib -o %t %t.o -rename_section __TEXT __text __TxT __foo \
+# RUN:                        -sectalign __TxT __foo 0x40
+# RUN: llvm-readobj --section-headers %t \
+# RUN:     | FileCheck -DSECT=__foo -DSEG=__TxT -DALIGN=6 %s
+
+# CHECK:      Name: [[SECT]]
+# CHECK-NEXT: Segment: [[SEG]]
+# CHECK-NEXT: Address:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: Alignment: [[ALIGN]]
+
+.section __TEXT,__text
+.space 1
+
+.section __DATA,__const
+.space 1


        


More information about the llvm-commits mailing list