[lld] r220348 - [mach-o] Support missing MH_SUBSECTIONS_VIA_SYMBOLS

Nick Kledzik kledzik at apple.com
Tue Oct 21 16:45:37 PDT 2014


Author: kledzik
Date: Tue Oct 21 18:45:37 2014
New Revision: 220348

URL: http://llvm.org/viewvc/llvm-project?rev=220348&view=rev
Log:
[mach-o] Support missing MH_SUBSECTIONS_VIA_SYMBOLS

All compiler generated mach-o object files are marked with MH_SUBSECTIONS_VIA_SYMBOLS.
But hand written assembly files need to opt-in if they are written correctly.
The flag means the linker can break up a sections at symbol addresses and
dead strip or re-order functions.

This change recognizes object files without the flag and marks its atoms as
not dead strippable and adds a layout-after chain of references so that the
atoms cannot be re-ordered.

Added:
    lld/trunk/test/mach-o/arm-subsections-via-symbols.yaml
Modified:
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
    lld/trunk/test/mach-o/parse-data-relocs-x86_64.yaml

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h?rev=220348&r1=220347&r2=220348&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h Tue Oct 21 18:45:37 2014
@@ -134,7 +134,7 @@ public:
                            const normalized::Relocation &reloc2,
                            const DefinedAtom *inAtom,
                            uint32_t offsetInAtom,
-                           uint64_t fixupAddress, bool swap,
+                           uint64_t fixupAddress, bool swap, bool scatterable,
                            FindAtomBySectionAndAddress atomFromAddress,
                            FindAtomBySymbolIndex atomFromSymbolIndex,
                            Reference::KindValue *kind, 

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp?rev=220348&r1=220347&r2=220348&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp Tue Oct 21 18:45:37 2014
@@ -77,7 +77,7 @@ public:
                            const normalized::Relocation &reloc2,
                            const DefinedAtom *inAtom,
                            uint32_t offsetInAtom,
-                           uint64_t fixupAddress, bool swap,
+                           uint64_t fixupAddress, bool swap, bool scatterable,
                            FindAtomBySectionAndAddress atomFromAddress,
                            FindAtomBySymbolIndex atomFromSymbolIndex,
                            Reference::KindValue *kind,
@@ -627,6 +627,7 @@ ArchHandler_arm::getPairReferenceInfo(co
                                      const DefinedAtom *inAtom,
                                      uint32_t offsetInAtom,
                                      uint64_t fixupAddress, bool swap,
+                                     bool scatterable,
                                      FindAtomBySectionAndAddress atomFromAddr,
                                      FindAtomBySymbolIndex atomFromSymbolIndex,
                                      Reference::KindValue *kind,
@@ -795,7 +796,7 @@ ArchHandler_arm::getPairReferenceInfo(co
     ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom);
     if (ec)
       return ec;
-    if (fromTarget != inAtom)
+    if (scatterable && (fromTarget != inAtom))
       return make_dynamic_error_code(Twine("SECTDIFF relocation where "
                                            "subtrahend label is not in atom"));
     *kind = delta32;

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp?rev=220348&r1=220347&r2=220348&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp Tue Oct 21 18:45:37 2014
@@ -120,7 +120,7 @@ public:
                            const normalized::Relocation &reloc2,
                            const DefinedAtom *inAtom,
                            uint32_t offsetInAtom,
-                           uint64_t fixupAddress, bool swap,
+                           uint64_t fixupAddress, bool swap, bool scatterable,
                            FindAtomBySectionAndAddress atomFromAddress,
                            FindAtomBySymbolIndex atomFromSymbolIndex,
                            Reference::KindValue *kind,
@@ -418,7 +418,7 @@ std::error_code ArchHandler_arm64::getRe
 std::error_code ArchHandler_arm64::getPairReferenceInfo(
     const normalized::Relocation &reloc1, const normalized::Relocation &reloc2,
     const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress,
-    bool swap, FindAtomBySectionAndAddress atomFromAddress,
+    bool swap, bool scatterable, FindAtomBySectionAndAddress atomFromAddress,
     FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind,
     const lld::Atom **target, Reference::Addend *addend) {
   const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp?rev=220348&r1=220347&r2=220348&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp Tue Oct 21 18:45:37 2014
@@ -80,7 +80,7 @@ public:
                            const normalized::Relocation &reloc2,
                            const DefinedAtom *inAtom,
                            uint32_t offsetInAtom,
-                           uint64_t fixupAddress, bool swap,
+                           uint64_t fixupAddress, bool swap, bool scatterable,
                            FindAtomBySectionAndAddress atomFromAddress,
                            FindAtomBySymbolIndex atomFromSymbolIndex,
                            Reference::KindValue *kind,
@@ -337,6 +337,7 @@ ArchHandler_x86::getPairReferenceInfo(co
                                       const DefinedAtom *inAtom,
                                       uint32_t offsetInAtom,
                                       uint64_t fixupAddress, bool swap,
+                                      bool scatterable,
                                       FindAtomBySectionAndAddress atomFromAddr,
                                       FindAtomBySymbolIndex atomFromSymbolIndex,
                                       Reference::KindValue *kind,

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp?rev=220348&r1=220347&r2=220348&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp Tue Oct 21 18:45:37 2014
@@ -122,7 +122,7 @@ public:
                            const normalized::Relocation &reloc2,
                            const DefinedAtom *inAtom,
                            uint32_t offsetInAtom,
-                           uint64_t fixupAddress, bool swap,
+                           uint64_t fixupAddress, bool swap, bool scatterable,
                            FindAtomBySectionAndAddress atomFromAddress,
                            FindAtomBySymbolIndex atomFromSymbolIndex,
                            Reference::KindValue *kind, 
@@ -401,6 +401,7 @@ ArchHandler_x86_64::getPairReferenceInfo
                                    const DefinedAtom *inAtom,
                                    uint32_t offsetInAtom,
                                    uint64_t fixupAddress, bool swap,
+                                   bool scatterable,
                                    FindAtomBySectionAndAddress atomFromAddress,
                                    FindAtomBySymbolIndex atomFromSymbolIndex,
                                    Reference::KindValue *kind, 

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp?rev=220348&r1=220347&r2=220348&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp Tue Oct 21 18:45:37 2014
@@ -220,12 +220,12 @@ void appendSymbolsInSection(const std::v
 void atomFromSymbol(DefinedAtom::ContentType atomType, const Section &section,
                     MachOFile &file, uint64_t symbolAddr, StringRef symbolName,
                     uint16_t symbolDescFlags, Atom::Scope symbolScope,
-                    uint64_t nextSymbolAddr, bool copyRefs) {
+                    uint64_t nextSymbolAddr, bool scatterable, bool copyRefs) {
   // Mach-O symbol table does have size in it. Instead the size is the
   // difference between this and the next symbol.
   uint64_t size = nextSymbolAddr - symbolAddr;
   uint64_t offset = symbolAddr - section.address;
-  bool noDeadStrip = (symbolDescFlags & N_NO_DEAD_STRIP);
+  bool noDeadStrip = (symbolDescFlags & N_NO_DEAD_STRIP) || !scatterable;
   if (section.type == llvm::MachO::S_ZEROFILL) {
     file.addZeroFillDefinedAtom(symbolName, symbolScope, offset, size,
                                 noDeadStrip, copyRefs, &section);
@@ -256,7 +256,8 @@ void atomFromSymbol(DefinedAtom::Content
 std::error_code processSymboledSection(DefinedAtom::ContentType atomType,
                                        const Section &section,
                                        const NormalizedFile &normalizedFile,
-                                       MachOFile &file, bool copyRefs) {
+                                       MachOFile &file, bool scatterable,
+                                       bool copyRefs) {
   // Find section's index.
   uint32_t sectIndex = 1;
   for (auto &sect : normalizedFile.sections) {
@@ -309,13 +310,14 @@ std::error_code processSymboledSection(D
     // Section has no symbols, put all content in one anoymous atom.
     atomFromSymbol(atomType, section, file, section.address, StringRef(),
                   0, Atom::scopeTranslationUnit,
-                  section.address + section.content.size(), copyRefs);
+                  section.address + section.content.size(),
+                  scatterable, copyRefs);
   }
   else if (symbols.front()->value != section.address) {
     // Section has anonymous content before first symbol.
     atomFromSymbol(atomType, section, file, section.address, StringRef(),
                    0, Atom::scopeTranslationUnit, symbols.front()->value,
-                   copyRefs);
+                   scatterable, copyRefs);
   }
 
   const Symbol *lastSym = nullptr;
@@ -328,7 +330,7 @@ std::error_code processSymboledSection(D
           || !lastSym->name.startswith("ltmp")) {
         atomFromSymbol(atomType, section, file, lastSym->value, lastSym->name,
                        lastSym->desc, atomScope(lastSym->scope), sym->value,
-                       copyRefs);
+                       scatterable, copyRefs);
       }
     }
     lastSym = sym;
@@ -336,8 +338,23 @@ std::error_code processSymboledSection(D
   if (lastSym != nullptr) {
     atomFromSymbol(atomType, section, file, lastSym->value, lastSym->name,
                    lastSym->desc, atomScope(lastSym->scope),
-                   section.address + section.content.size(), copyRefs);
+                   section.address + section.content.size(),
+                   scatterable, copyRefs);
   }
+
+  // If object built without .subsections_via_symbols, add reference chain.
+  if (!scatterable) {
+    MachODefinedAtom *prevAtom = nullptr;
+    file.eachAtomInSection(section,
+                           [&](MachODefinedAtom *atom, uint64_t offset)->void {
+      if (prevAtom)
+        prevAtom->addReference(0, Reference::kindLayoutAfter, atom, 0,
+                               Reference::KindArch::all,
+                               Reference::KindNamespace::all);
+      prevAtom = atom;
+    });
+  }
+
   return std::error_code();
 }
 
@@ -345,7 +362,8 @@ std::error_code processSection(DefinedAt
                                const Section &section,
                                bool customSectionName,
                                const NormalizedFile &normalizedFile,
-                               MachOFile &file, bool copyRefs) {
+                               MachOFile &file, bool scatterable,
+                               bool copyRefs) {
   const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
   const bool swap = !MachOLinkingContext::isHostEndian(normalizedFile.arch);
 
@@ -368,7 +386,7 @@ std::error_code processSection(DefinedAt
   if (atomizeModel == atomizeAtSymbols) {
     // Break section up into atoms each with a fixed size.
     return processSymboledSection(atomType, section, normalizedFile, file,
-                                                                      copyRefs);
+                                  scatterable, copyRefs);
   } else {
     const uint32_t *cfi;
     unsigned int size;
@@ -483,6 +501,7 @@ findAtomCoveringAddress(const Normalized
 // creates corresponding lld::Reference objects.
 std::error_code convertRelocs(const Section &section,
                               const NormalizedFile &normalizedFile,
+                              bool scatterable,
                               MachOFile &file,
                               ArchHandler &handler) {
   // Utility function for ArchHandler to find atom by its address.
@@ -577,9 +596,10 @@ std::error_code convertRelocs(const Sect
     if (handler.isPairedReloc(reloc)) {
      // Handle paired relocations together.
      relocErr = handler.getPairReferenceInfo(reloc, *++it, inAtom,
-                                              offsetInAtom, fixupAddress, swap,
-                                              atomByAddr, atomBySymbol, &kind,
-                                               &target, &addend);
+                                             offsetInAtom, fixupAddress, swap,
+                                             scatterable, atomByAddr,
+                                             atomBySymbol, &kind,
+                                             &target, &addend);
     }
     else {
       // Use ArchHandler to convert relocation record into information
@@ -697,6 +717,8 @@ ErrorOr<std::unique_ptr<lld::File>>
 normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
                         bool copyRefs) {
   std::unique_ptr<MachOFile> file(new MachOFile(path));
+  bool scatterable = ((normalizedFile.flags & MH_SUBSECTIONS_VIA_SYMBOLS) != 0);
+
   // Create atoms from each section.
   for (auto &sect : normalizedFile.sections) {
     if (isDebugInfoSection(sect))
@@ -706,7 +728,7 @@ normalizedObjectToAtoms(const Normalized
                                                             customSectionName);
     if (std::error_code ec =
             processSection(atomType, sect, customSectionName, normalizedFile,
-                           *file, copyRefs))
+                           *file, scatterable, copyRefs))
       return ec;
   }
   // Create atoms from undefined symbols.
@@ -726,7 +748,8 @@ normalizedObjectToAtoms(const Normalized
   for (auto &sect : normalizedFile.sections) {
     if (isDebugInfoSection(sect))
       continue;
-    if (std::error_code ec = convertRelocs(sect, normalizedFile, *file, *handler))
+    if (std::error_code ec = convertRelocs(sect, normalizedFile, scatterable,
+                                           *file, *handler))
         return ec;
   }
 

Added: lld/trunk/test/mach-o/arm-subsections-via-symbols.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/arm-subsections-via-symbols.yaml?rev=220348&view=auto
==============================================================================
--- lld/trunk/test/mach-o/arm-subsections-via-symbols.yaml (added)
+++ lld/trunk/test/mach-o/arm-subsections-via-symbols.yaml Tue Oct 21 18:45:37 2014
@@ -0,0 +1,60 @@
+# RUN: lld -flavor darwin -arch armv7 %s -r -print_atoms -o %t | FileCheck %s
+#
+# Test that assembly written without .subsections_via_symbols is parsed so
+# that atoms are non-dead-strip and there is a layout-after references
+# chaining atoms together.
+#
+
+--- !mach-o
+arch:            armv7
+file-type:       MH_OBJECT
+flags:           [  ]
+has-UUID:        false
+OS:              unknown
+sections:
+  - segment:         __TEXT
+    section:         __text
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+    alignment:       2
+    address:         0x0000000000000000
+    content:         [ 0x04, 0x10, 0x9F, 0xE5, 0x04, 0x20, 0x9F, 0xE5, 
+                       0x1E, 0xFF, 0x2F, 0xE1, 0x78, 0x56, 0x34, 0x12, 
+                       0x21, 0x43, 0x65, 0x87 ]
+local-symbols:
+  - name:            constants1
+    type:            N_SECT
+    sect:            1
+    value:           0x000000000000000C
+  - name:            constants2
+    type:            N_SECT
+    sect:            1
+    value:           0x0000000000000010
+global-symbols:
+  - name:            _foo
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            1
+    value:           0x0000000000000000
+...
+
+
+# CHECK:defined-atoms:
+# CHECK:  - name:            _foo
+# CHECK:    scope:           global
+# CHECK:    content:         [ 04, 10, 9F, E5, 04, 20, 9F, E5, 1E, FF, 2F, E1 ]
+# CHECK:    dead-strip:      never
+# CHECK:    references:
+# CHECK:      - kind:            layout-after
+# CHECK:        offset:          0
+# CHECK:        target:          constants1
+# CHECK:  - name:            constants1
+# CHECK:    content:         [ 78, 56, 34, 12 ]
+# CHECK:    dead-strip:      never
+# CHECK:    references:
+# CHECK:      - kind:            layout-after
+# CHECK:        offset:          0
+# CHECK:        target:          constants2
+# CHECK:  - name:            constants2
+# CHECK:    content:         [ 21, 43, 65, 87 ]
+# CHECK:    dead-strip:      never

Modified: lld/trunk/test/mach-o/parse-data-relocs-x86_64.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/parse-data-relocs-x86_64.yaml?rev=220348&r1=220347&r2=220348&view=diff
==============================================================================
--- lld/trunk/test/mach-o/parse-data-relocs-x86_64.yaml (original)
+++ lld/trunk/test/mach-o/parse-data-relocs-x86_64.yaml Tue Oct 21 18:45:37 2014
@@ -1,3 +1,4 @@
+
 # RUN: lld -flavor darwin -arch x86_64 -r %s -o %t -print_atoms | FileCheck %s \
 # RUN: && lld -flavor darwin -arch x86_64 %t -r -print_atoms -o %t2  | FileCheck %s
 #
@@ -36,7 +37,7 @@
 --- !mach-o
 arch:            x86_64
 file-type:       MH_OBJECT
-flags:           [  ]
+flags:           [ MH_SUBSECTIONS_VIA_SYMBOLS ]
 has-UUID:        false
 OS:              unknown
 sections:        





More information about the llvm-commits mailing list