summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter
diff options
context:
space:
mode:
authorNick Kledzik <kledzik@apple.com>2014-11-12 22:21:56 +0000
committerNick Kledzik <kledzik@apple.com>2014-11-12 22:21:56 +0000
commit16cfa60cbd8c792228fc9d112c5bcc1b7eb55743 (patch)
tree5424bf9cf159e408381f570d0aa5634be8391cf7 /lld/lib/ReaderWriter
parent0140aa8756d5a8fa58a0a02b306aa685d22caa42 (diff)
downloadbcm5719-llvm-16cfa60cbd8c792228fc9d112c5bcc1b7eb55743.tar.gz
bcm5719-llvm-16cfa60cbd8c792228fc9d112c5bcc1b7eb55743.zip
[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). llvm-svn: 221822
Diffstat (limited to 'lld/lib/ReaderWriter')
-rw-r--r--lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp70
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp14
-rw-r--r--lld/lib/ReaderWriter/MachO/WriterMachO.cpp3
-rw-r--r--lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp1
4 files changed, 87 insertions, 1 deletions
diff --git a/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp b/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp
index f0788fa3da1..693a428d0df 100644
--- a/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp
+++ b/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp
@@ -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
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
index 8333d099ccc..780c9c02fc8 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
@@ -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, const DefinedAtom *atom) {
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) {
diff --git a/lld/lib/ReaderWriter/MachO/WriterMachO.cpp b/lld/lib/ReaderWriter/MachO/WriterMachO.cpp
index 17102df6349..a0e9d434c9a 100644
--- a/lld/lib/ReaderWriter/MachO/WriterMachO.cpp
+++ b/lld/lib/ReaderWriter/MachO/WriterMachO.cpp
@@ -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;
}
diff --git a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
index 72537b94cd3..6993ee4a099 100644
--- a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
+++ b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
@@ -447,6 +447,7 @@ template <> struct ScalarEnumerationTraits<lld::DefinedAtom::ContentType> {
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);
OpenPOWER on IntegriCloud