[lld] r221822 - [mach-o] Support linker synthesized mach_header symbols.

Nick Kledzik kledzik at apple.com
Wed Nov 12 14:21:57 PST 2014


Author: kledzik
Date: Wed Nov 12 16:21:56 2014
New Revision: 221822

URL: http://llvm.org/viewvc/llvm-project?rev=221822&view=rev
Log:
[mach-o] Support linker synthesized mach_header symbols.

On darwin in final linked images, the __TEXT segment covers that start of the
file.  That means in memory a process can see the mach_header (and load commands)
for every loaded image in a process.  There are APIs that take and return the
mach_header addresses as a way to specify a particular loaded image.

For completeness, any code can get the address of the mach_header of the image
it is in by using &__dso_handle.  In addition there are mach-o type specific
symbols like __mh_execute_header.

The linker needs to supply a definition for any of these symbols if used.  But
the address the symbol it resolves to is not in any section.  Instead it is the
address of the start of the __TEXT segment.

I needed to make a small change to SimpleFileNode to not override
resetNextIndex() because the Driver creates a SimpleFileNode to hold the
internal/implicit files that the context/writer can create. For some reason
SimpleFileNode overrode resetNextIndex() to do nothing instead of reseting
the index (which mach-o needs if the internal file is an archive).

Added:
    lld/trunk/test/mach-o/dso_handle.yaml
    lld/trunk/test/mach-o/mh_bundle_header.yaml
    lld/trunk/test/mach-o/mh_dylib_header.yaml
Modified:
    lld/trunk/include/lld/Core/DefinedAtom.h
    lld/trunk/include/lld/Core/InputGraph.h
    lld/trunk/lib/Core/DefinedAtom.cpp
    lld/trunk/lib/ReaderWriter/MachO/ExecutableAtoms.hpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
    lld/trunk/lib/ReaderWriter/MachO/WriterMachO.cpp
    lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp

Modified: lld/trunk/include/lld/Core/DefinedAtom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/DefinedAtom.h?rev=221822&r1=221821&r2=221822&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/DefinedAtom.h (original)
+++ lld/trunk/include/lld/Core/DefinedAtom.h Wed Nov 12 16:21:56 2014
@@ -143,6 +143,7 @@ public:
     typeTLVInitialData,     // initial data for a TLV [Darwin]
     typeTLVInitialZeroFill, // TLV initial zero fill data [Darwin]
     typeTLVInitializerPtr,  // pointer to thread local initializer [Darwin]
+    typeMachHeader,         // atom representing mach_header [Darwin]
     typeThreadZeroFill,     // Uninitialized thread local data(TBSS) [ELF]
     typeThreadData,         // Initialized thread local data(TDATA) [ELF]
     typeRONote,             // Identifies readonly note sections [ELF]

Modified: lld/trunk/include/lld/Core/InputGraph.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/InputGraph.h?rev=221822&r1=221821&r2=221822&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/InputGraph.h (original)
+++ lld/trunk/include/lld/Core/InputGraph.h Wed Nov 12 16:21:56 2014
@@ -296,9 +296,6 @@ public:
       return make_error_code(InputGraphError::no_more_files);
     return *_files[_nextFileIndex++];
   }
-
-  // Do nothing here.
-  void resetNextIndex() override {}
 };
 } // namespace lld
 

Modified: lld/trunk/lib/Core/DefinedAtom.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/DefinedAtom.cpp?rev=221822&r1=221821&r2=221822&view=diff
==============================================================================
--- lld/trunk/lib/Core/DefinedAtom.cpp (original)
+++ lld/trunk/lib/Core/DefinedAtom.cpp Wed Nov 12 16:21:56 2014
@@ -28,6 +28,7 @@ DefinedAtom::ContentPermissions DefinedA
   case typeBranchShim:
   case typeStub:
   case typeStubHelper:
+  case typeMachHeader:
     return permR_X;
 
   case typeConstant:

Modified: lld/trunk/lib/ReaderWriter/MachO/ExecutableAtoms.hpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ExecutableAtoms.hpp?rev=221822&r1=221821&r2=221822&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ExecutableAtoms.hpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ExecutableAtoms.hpp Wed Nov 12 16:21:56 2014
@@ -10,8 +10,11 @@
 #ifndef LLD_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H
 #define LLD_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H
 
+#include "Atoms.h"
+
 #include "llvm/Support/MachO.h"
 
+#include "lld/Core/ArchiveLibraryFile.h"
 #include "lld/Core/DefinedAtom.h"
 #include "lld/Core/File.h"
 #include "lld/Core/LinkingContext.h"
@@ -58,8 +61,75 @@ private:
 };
 
 
+//
+// MachHeaderAliasFile lazily instantiates the magic symbols that mark the start
+// of the mach_header for final linked images.
+//
+class MachHeaderAliasFile : public ArchiveLibraryFile {
+public:
+  MachHeaderAliasFile(const MachOLinkingContext &context)
+      : ArchiveLibraryFile("mach_header symbols") {
+      switch (context.outputMachOType()) {
+      case llvm::MachO::MH_EXECUTE:
+        _machHeaderSymbolName = "__mh_execute_header";
+        break;
+      case llvm::MachO::MH_DYLIB:
+        _machHeaderSymbolName = "__mh_dylib_header";
+        break;
+      case llvm::MachO::MH_BUNDLE:
+        _machHeaderSymbolName = "__mh_bundle_header";
+        break;
+      case llvm::MachO::MH_DYLINKER:
+        _machHeaderSymbolName = "__mh_dylinker_header";
+        break;
+      case llvm::MachO::MH_PRELOAD:
+        _machHeaderSymbolName = "__mh_preload_header";
+        break;
+      default:
+        llvm_unreachable("no mach_header symbol for file type");
+      }
+  }
+
+  std::error_code
+  parseAllMembers(std::vector<std::unique_ptr<File>> &result) const override {
+    return std::error_code();
+  }
+
+  const File *find(StringRef sym, bool dataSymbolOnly) const override {
+    if (sym.equals("___dso_handle") || sym.equals(_machHeaderSymbolName)) {
+      _definedAtoms._atoms.push_back(new (_alloc) MachODefinedAtom(
+          *this, sym, DefinedAtom::scopeLinkageUnit,
+          DefinedAtom::typeMachHeader, DefinedAtom::mergeNo, false, false,
+          ArrayRef<uint8_t>()));
+      return this;
+    }
+    return nullptr;
+  }
+
+  const atom_collection<DefinedAtom> &defined() const override {
+    return _definedAtoms;
+  }
+  const atom_collection<UndefinedAtom> &undefined() const override {
+    return _undefinedAtoms;
+  }
 
+  const atom_collection<SharedLibraryAtom> &sharedLibrary() const override {
+    return _sharedLibraryAtoms;
+  }
 
+  const atom_collection<AbsoluteAtom> &absolute() const override {
+    return _absoluteAtoms;
+  }
+
+
+private:
+  mutable atom_collection_vector<DefinedAtom> _definedAtoms;
+  atom_collection_vector<UndefinedAtom> _undefinedAtoms;
+  atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
+  atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
+  StringRef _machHeaderSymbolName;
+  mutable llvm::BumpPtrAllocator _alloc;
+};
 
 } // namespace mach_o
 } // namespace lld

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp?rev=221822&r1=221821&r2=221822&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp Wed Nov 12 16:21:56 2014
@@ -167,6 +167,7 @@ private:
   DylibPathToInfo               _dylibInfo;
   const DefinedAtom            *_entryAtom;
   AtomToIndex                   _atomToSymbolIndex;
+  std::vector<const Atom *>     _machHeaderAliasAtoms;
 };
 
 
@@ -331,7 +332,10 @@ void Util::appendAtom(SectionInfo *sect,
 
 void Util::assignAtomsToSections(const lld::File &atomFile) {
   for (const DefinedAtom *atom : atomFile.defined()) {
-    appendAtom(sectionForAtom(atom), atom);
+    if (atom->contentType() == DefinedAtom::typeMachHeader)
+      _machHeaderAliasAtoms.push_back(atom);
+    else
+      appendAtom(sectionForAtom(atom), atom);
   }
 }
 
@@ -653,6 +657,14 @@ void Util::buildAtomToAddressMap() {
               << " name=" << info.atom->name() << "\n");
     }
   }
+  for (const Atom *atom : _machHeaderAliasAtoms) {
+    _atomToAddress[atom] = _context.baseAddress();
+    DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
+              << "   address="
+              << llvm::format("0x%016X", _atomToAddress[atom])
+              << " atom=" << atom
+              << " name=" << atom->name() << "\n");
+  }
 }
 
 uint16_t Util::descBits(const DefinedAtom* atom) {

Modified: lld/trunk/lib/ReaderWriter/MachO/WriterMachO.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/WriterMachO.cpp?rev=221822&r1=221821&r2=221822&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/WriterMachO.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/WriterMachO.cpp Wed Nov 12 16:21:56 2014
@@ -52,6 +52,9 @@ public:
     // If this can link with dylibs, need helper function (dyld_stub_binder).
     if (_context.needsStubsPass())
       r.emplace_back(new StubHelperFile(_context));
+    // Final linked images can access a symbol for their mach_header.
+    if (_context.outputMachOType() != llvm::MachO::MH_OBJECT)
+      r.emplace_back(new MachHeaderAliasFile(_context));
 
     return true;
   }

Modified: lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp?rev=221822&r1=221821&r2=221822&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp (original)
+++ lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp Wed Nov 12 16:21:56 2014
@@ -447,6 +447,7 @@ template <> struct ScalarEnumerationTrai
     io.enumCase(value, "tlv-zero-fill",   DefinedAtom::typeTLVInitialZeroFill);
     io.enumCase(value, "tlv-initializer-ptr",
                                           DefinedAtom::typeTLVInitializerPtr);
+    io.enumCase(value, "mach_header",     DefinedAtom::typeMachHeader);
     io.enumCase(value, "thread-data",     DefinedAtom::typeThreadData);
     io.enumCase(value, "thread-zero-fill",DefinedAtom::typeThreadZeroFill);
     io.enumCase(value, "ro-note",         DefinedAtom::typeRONote);

Added: lld/trunk/test/mach-o/dso_handle.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/dso_handle.yaml?rev=221822&view=auto
==============================================================================
--- lld/trunk/test/mach-o/dso_handle.yaml (added)
+++ lld/trunk/test/mach-o/dso_handle.yaml Wed Nov 12 16:21:56 2014
@@ -0,0 +1,62 @@
+# RUN: lld -flavor darwin -arch x86_64  %s  %p/Inputs/libSystem.yaml -o %t1
+# RUN: llvm-nm -m -n %t1 | FileCheck %s
+#
+# RUN: lld -flavor darwin -arch x86_64  %s %p/Inputs/libSystem.yaml -dead_strip -o %t2
+# RUN: llvm-nm -m -n %t2 | FileCheck %s
+#
+# RUN: lld -flavor darwin -arch x86_64  %s %p/Inputs/libSystem.yaml -dylib -o %t3
+# RUN: llvm-nm -m -n %t3 | FileCheck %s
+#
+# RUN: lld -flavor darwin -arch x86_64  %s %p/Inputs/libSystem.yaml -bundle -o %t4
+# RUN: llvm-nm -m -n %t4 | FileCheck %s
+#
+# Test that ___dso_handle symbol is available for executables, bundles, and dylibs
+#
+
+--- !mach-o
+arch:            x86_64
+file-type:       MH_OBJECT
+flags:           [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+sections:
+  - segment:         __TEXT
+    section:         __text
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+    address:         0x0000000000000000
+    content:         [ 0x55, 0x48, 0x89, 0xE5, 0x31, 0xC0, 0x5D, 0xC3 ]
+  - segment:         __DATA
+    section:         __data
+    type:            S_REGULAR
+    attributes:      [  ]
+    alignment:       3
+    address:         0x0000000000000008
+    content:         [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+    relocations:
+      - offset:          0x00000000
+        type:            X86_64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          2
+global-symbols:
+  - name:            _d
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            2
+    value:           0x0000000000000008
+  - name:            _main
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            1
+    value:           0x0000000000000000
+undefined-symbols:
+  - name:            ___dso_handle
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+
+
+...
+
+# CHECK_NOT:	___dso_handle
+# CHECK:      _main

Added: lld/trunk/test/mach-o/mh_bundle_header.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/mh_bundle_header.yaml?rev=221822&view=auto
==============================================================================
--- lld/trunk/test/mach-o/mh_bundle_header.yaml (added)
+++ lld/trunk/test/mach-o/mh_bundle_header.yaml Wed Nov 12 16:21:56 2014
@@ -0,0 +1,53 @@
+# RUN: lld -flavor darwin -arch x86_64  %s -bundle -o %t %p/Inputs/libSystem.yaml
+# RUN: llvm-nm -m -n %t | FileCheck %s
+#
+# Test that __mh_bundle_header symbol is available for bundles
+#
+
+--- !mach-o
+arch:            x86_64
+file-type:       MH_OBJECT
+flags:           [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+sections:
+  - segment:         __TEXT
+    section:         __text
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+    address:         0x0000000000000000
+    content:         [ 0x55, 0x48, 0x89, 0xE5, 0x31, 0xC0, 0x5D, 0xC3 ]
+  - segment:         __DATA
+    section:         __data
+    type:            S_REGULAR
+    attributes:      [  ]
+    alignment:       3
+    address:         0x0000000000000008
+    content:         [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+    relocations:
+      - offset:          0x00000000
+        type:            X86_64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          2
+global-symbols:
+  - name:            _d
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            2
+    value:           0x0000000000000008
+  - name:            _foo
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            1
+    value:           0x0000000000000000
+undefined-symbols:
+  - name:            __mh_bundle_header
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+
+
+...
+
+# CHECK_NOT:	__mh_bundle_header
+# CHECK:      _foo

Added: lld/trunk/test/mach-o/mh_dylib_header.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/mh_dylib_header.yaml?rev=221822&view=auto
==============================================================================
--- lld/trunk/test/mach-o/mh_dylib_header.yaml (added)
+++ lld/trunk/test/mach-o/mh_dylib_header.yaml Wed Nov 12 16:21:56 2014
@@ -0,0 +1,53 @@
+# RUN: lld -flavor darwin -arch x86_64  %s -dylib -o %t %p/Inputs/libSystem.yaml
+# RUN: llvm-nm -m -n %t | FileCheck %s
+#
+# Test that __mh_dylib_header symbol is available for dylibs
+#
+
+--- !mach-o
+arch:            x86_64
+file-type:       MH_OBJECT
+flags:           [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+sections:
+  - segment:         __TEXT
+    section:         __text
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+    address:         0x0000000000000000
+    content:         [ 0x55, 0x48, 0x89, 0xE5, 0x31, 0xC0, 0x5D, 0xC3 ]
+  - segment:         __DATA
+    section:         __data
+    type:            S_REGULAR
+    attributes:      [  ]
+    alignment:       3
+    address:         0x0000000000000008
+    content:         [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+    relocations:
+      - offset:          0x00000000
+        type:            X86_64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          2
+global-symbols:
+  - name:            _d
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            2
+    value:           0x0000000000000008
+  - name:            _foo
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            1
+    value:           0x0000000000000000
+undefined-symbols:
+  - name:            __mh_dylib_header
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+
+
+...
+
+# CHECK_NOT:	__mh_dylib_header
+# CHECK:      _foo





More information about the llvm-commits mailing list