summaryrefslogtreecommitdiffstats
path: root/lld/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lld/lib')
-rw-r--r--lld/lib/CMakeLists.txt3
-rw-r--r--lld/lib/Core/CMakeLists.txt8
-rw-r--r--lld/lib/Core/InputFiles.cpp6
-rw-r--r--lld/lib/Core/Resolver.cpp50
-rw-r--r--lld/lib/Core/SymbolTable.cpp6
-rw-r--r--lld/lib/Passes/GOTPass.cpp24
-rw-r--r--lld/lib/Passes/StubsPass.cpp26
-rw-r--r--lld/lib/Platforms/CMakeLists.txt1
-rw-r--r--lld/lib/Platforms/Darwin/CMakeLists.txt5
-rw-r--r--lld/lib/Platforms/Darwin/DarwinPlatform.cpp180
-rw-r--r--lld/lib/Platforms/Darwin/DarwinPlatform.h61
-rw-r--r--lld/lib/Platforms/Darwin/DarwinReferenceKinds.cpp90
-rw-r--r--lld/lib/Platforms/Darwin/DarwinReferenceKinds.h54
-rw-r--r--lld/lib/Platforms/Darwin/ExecutableAtoms.hpp84
-rw-r--r--lld/lib/Platforms/Darwin/ExecutableWriter.h35
-rw-r--r--lld/lib/Reader/CMakeLists.txt3
-rw-r--r--lld/lib/ReaderWriter/CMakeLists.txt9
-rw-r--r--lld/lib/ReaderWriter/ELF/CMakeLists.txt4
-rw-r--r--lld/lib/ReaderWriter/ELF/ReaderELF.cpp41
-rw-r--r--lld/lib/ReaderWriter/ELF/WriterELF.cpp35
-rw-r--r--lld/lib/ReaderWriter/MachO/CMakeLists.txt4
-rw-r--r--lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp50
-rw-r--r--lld/lib/ReaderWriter/MachO/GOTPass.hpp51
-rw-r--r--lld/lib/ReaderWriter/MachO/MachOFormat.hpp (renamed from lld/lib/Platforms/Darwin/MachOFormat.hpp)46
-rw-r--r--lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp103
-rw-r--r--lld/lib/ReaderWriter/MachO/ReferenceKinds.h77
-rw-r--r--lld/lib/ReaderWriter/MachO/SimpleAtoms.hpp (renamed from lld/lib/Platforms/Darwin/SimpleAtoms.hpp)12
-rw-r--r--lld/lib/ReaderWriter/MachO/StubAtoms.hpp (renamed from lld/lib/Platforms/Darwin/StubAtoms.hpp)30
-rw-r--r--lld/lib/ReaderWriter/MachO/StubsPass.hpp145
-rw-r--r--lld/lib/ReaderWriter/MachO/WriterMachO.cpp (renamed from lld/lib/Platforms/Darwin/ExecutableWriter.cpp)412
-rw-r--r--lld/lib/ReaderWriter/Native/CMakeLists.txt4
-rw-r--r--lld/lib/ReaderWriter/Native/NativeFileFormat.h (renamed from lld/lib/Core/NativeFileFormat.h)8
-rw-r--r--lld/lib/ReaderWriter/Native/ReaderNative.cpp (renamed from lld/lib/Core/NativeReader.cpp)204
-rw-r--r--lld/lib/ReaderWriter/Native/WriterNative.cpp (renamed from lld/lib/Core/NativeWriter.cpp)70
-rw-r--r--lld/lib/ReaderWriter/PECOFF/CMakeLists.txt4
-rw-r--r--lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp (renamed from lld/lib/Reader/COFFReader.cpp)50
-rw-r--r--lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp35
-rw-r--r--lld/lib/ReaderWriter/Reader.cpp42
-rw-r--r--lld/lib/ReaderWriter/Writer.cpp (renamed from lld/lib/Core/Platform.cpp)16
-rw-r--r--lld/lib/ReaderWriter/YAML/CMakeLists.txt5
-rw-r--r--lld/lib/ReaderWriter/YAML/ReaderYAML.cpp (renamed from lld/lib/Core/YamlReader.cpp)93
-rw-r--r--lld/lib/ReaderWriter/YAML/WriterYAML.cpp (renamed from lld/lib/Core/YamlWriter.cpp)83
-rw-r--r--lld/lib/ReaderWriter/YAML/YamlKeyValues.cpp (renamed from lld/lib/Core/YamlKeyValues.cpp)2
-rw-r--r--lld/lib/ReaderWriter/YAML/YamlKeyValues.h (renamed from lld/lib/Core/YamlKeyValues.h)2
44 files changed, 1343 insertions, 930 deletions
diff --git a/lld/lib/CMakeLists.txt b/lld/lib/CMakeLists.txt
index 2ce187cf1d6..6a0bf989e0a 100644
--- a/lld/lib/CMakeLists.txt
+++ b/lld/lib/CMakeLists.txt
@@ -1,4 +1,3 @@
add_subdirectory(Core)
add_subdirectory(Passes)
-add_subdirectory(Platforms)
-add_subdirectory(Reader)
+add_subdirectory(ReaderWriter)
diff --git a/lld/lib/Core/CMakeLists.txt b/lld/lib/Core/CMakeLists.txt
index 076d3351504..1a38b39d2a3 100644
--- a/lld/lib/Core/CMakeLists.txt
+++ b/lld/lib/Core/CMakeLists.txt
@@ -2,14 +2,6 @@ add_lld_library(lldCore
Error.cpp
File.cpp
InputFiles.cpp
- NativeFileFormat.h
- NativeReader.cpp
- NativeWriter.cpp
- Platform.cpp
Resolver.cpp
SymbolTable.cpp
- YamlKeyValues.cpp
- YamlKeyValues.h
- YamlReader.cpp
- YamlWriter.cpp
)
diff --git a/lld/lib/Core/InputFiles.cpp b/lld/lib/Core/InputFiles.cpp
index e9a423d9a30..78c8405c5ed 100644
--- a/lld/lib/Core/InputFiles.cpp
+++ b/lld/lib/Core/InputFiles.cpp
@@ -35,6 +35,12 @@ void InputFiles::appendFile(const File &file) {
_files.push_back(&file);
}
+void InputFiles::appendFiles(std::vector<std::unique_ptr<File>> &files) {
+ for (std::unique_ptr<File> &f : files) {
+ _files.push_back(f.release());
+ }
+}
+
bool InputFiles::searchLibraries(StringRef name, bool searchSharedLibs,
bool searchArchives, bool dataSymbolOnly,
diff --git a/lld/lib/Core/Resolver.cpp b/lld/lib/Core/Resolver.cpp
index f16a67a94fe..d50a772fed3 100644
--- a/lld/lib/Core/Resolver.cpp
+++ b/lld/lib/Core/Resolver.cpp
@@ -7,15 +7,17 @@
//
//===----------------------------------------------------------------------===//
-#include "lld/Core/LLVM.h"
-#include "lld/Core/Resolver.h"
#include "lld/Core/Atom.h"
#include "lld/Core/File.h"
+#include "lld/Core/LLVM.h"
#include "lld/Core/InputFiles.h"
#include "lld/Core/LLVM.h"
+#include "lld/Core/Resolver.h"
#include "lld/Core/SymbolTable.h"
#include "lld/Core/UndefinedAtom.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/ErrorHandling.h"
@@ -65,6 +67,8 @@ private:
// add all atoms from all initial .o files
void Resolver::buildInitialAtomList() {
+ DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Resolver initial atom list:\n");
+
// each input files contributes initial atoms
_atoms.reserve(1024);
_inputFiles.forEachInitialAtom(*this);
@@ -79,7 +83,14 @@ void Resolver::doFile(const File &file) {
void Resolver::doUndefinedAtom(const class UndefinedAtom& atom) {
- // add to list of known atoms
+ DEBUG_WITH_TYPE("resolver", llvm::dbgs()
+ << " UndefinedAtom: "
+ << llvm::format("0x%09lX", &atom)
+ << ", name="
+ << atom.name()
+ << "\n");
+
+ // add to list of known atoms
_atoms.push_back(&atom);
// tell symbol table
@@ -89,6 +100,13 @@ void Resolver::doUndefinedAtom(const class UndefinedAtom& atom) {
// called on each atom when a file is added
void Resolver::doDefinedAtom(const DefinedAtom &atom) {
+ DEBUG_WITH_TYPE("resolver", llvm::dbgs()
+ << " DefinedAtom: "
+ << llvm::format("0x%09lX", &atom)
+ << ", name="
+ << atom.name()
+ << "\n");
+
// add to list of known atoms
_atoms.push_back(&atom);
@@ -97,7 +115,7 @@ void Resolver::doDefinedAtom(const DefinedAtom &atom) {
// tell symbol table about non-static atoms
_symbolTable.add(atom);
}
-
+
if (_options.deadCodeStripping()) {
// add to set of dead-strip-roots, all symbols that
// the compiler marks as don't strip
@@ -107,6 +125,13 @@ void Resolver::doDefinedAtom(const DefinedAtom &atom) {
}
void Resolver::doSharedLibraryAtom(const SharedLibraryAtom& atom) {
+ DEBUG_WITH_TYPE("resolver", llvm::dbgs()
+ << " SharedLibraryAtom: "
+ << llvm::format("0x%09lX", &atom)
+ << ", name="
+ << atom.name()
+ << "\n");
+
// add to list of known atoms
_atoms.push_back(&atom);
@@ -115,6 +140,13 @@ void Resolver::doSharedLibraryAtom(const SharedLibraryAtom& atom) {
}
void Resolver::doAbsoluteAtom(const AbsoluteAtom& atom) {
+ DEBUG_WITH_TYPE("resolver", llvm::dbgs()
+ << " AbsoluteAtom: "
+ << llvm::format("0x%09lX", &atom)
+ << ", name="
+ << atom.name()
+ << "\n");
+
// add to list of known atoms
_atoms.push_back(&atom);
@@ -159,7 +191,7 @@ void Resolver::resolveUndefines() {
_symbolTable.tentativeDefinitions(tentDefNames);
for ( StringRef tentDefName : tentDefNames ) {
// Load for previous tentative may also have loaded
- // something that overrode this tentative, so always check.
+ // something that overrode this tentative, so always check.
const Atom *curAtom = _symbolTable.findByName(tentDefName);
assert(curAtom != nullptr);
if (const DefinedAtom* curDefAtom = dyn_cast<DefinedAtom>(curAtom)) {
@@ -228,7 +260,7 @@ void Resolver::deadStripOptimize() {
_deadStripRoots.insert(defAtom);
}
}
-
+
// Or, use list of names that are dead stip roots.
const std::vector<StringRef> &names = _options.deadStripRootNames();
for ( const StringRef &name : names ) {
@@ -332,7 +364,13 @@ void Resolver::MergedFile::addAtom(const Atom& atom) {
}
void Resolver::MergedFile::addAtoms(std::vector<const Atom*>& all) {
+ DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Resolver final atom list:\n");
for ( const Atom *atom : all ) {
+ DEBUG_WITH_TYPE("resolver", llvm::dbgs()
+ << llvm::format(" 0x%09lX", atom)
+ << ", name="
+ << atom->name()
+ << "\n");
this->addAtom(*atom);
}
}
diff --git a/lld/lib/Core/SymbolTable.cpp b/lld/lib/Core/SymbolTable.cpp
index 0bfe6da6a78..8707fbeb421 100644
--- a/lld/lib/Core/SymbolTable.cpp
+++ b/lld/lib/Core/SymbolTable.cpp
@@ -173,7 +173,7 @@ void SymbolTable::addByName(const Atom & newAtom) {
else {
if ( _options.warnIfCoalesableAtomsHaveDifferentCanBeNull() ) {
// FIXME: need diagonstics interface for writing warning messages
- llvm::errs() << "lld warning: undefined symbol "
+ llvm::errs() << "lld warning: undefined symbol "
<< existingUndef->name()
<< " has different weakness in "
<< existingUndef->file().path()
@@ -198,7 +198,7 @@ void SymbolTable::addByName(const Atom & newAtom) {
useNew = false;
if ( _options.warnIfCoalesableAtomsHaveDifferentLoadName() ) {
// FIXME: need diagonstics interface for writing warning messages
- llvm::errs() << "lld warning: shared library symbol "
+ llvm::errs() << "lld warning: shared library symbol "
<< curShLib->name()
<< " has different load path in "
<< curShLib->file().path()
@@ -210,7 +210,7 @@ void SymbolTable::addByName(const Atom & newAtom) {
useNew = false;
if ( _options.warnIfCoalesableAtomsHaveDifferentCanBeNull() ) {
// FIXME: need diagonstics interface for writing warning messages
- llvm::errs() << "lld warning: shared library symbol "
+ llvm::errs() << "lld warning: shared library symbol "
<< curShLib->name()
<< " has different weakness in "
<< curShLib->file().path()
diff --git a/lld/lib/Passes/GOTPass.cpp b/lld/lib/Passes/GOTPass.cpp
index 9bbd08a2b1e..52b70e3c356 100644
--- a/lld/lib/Passes/GOTPass.cpp
+++ b/lld/lib/Passes/GOTPass.cpp
@@ -24,9 +24,9 @@
// is in the same linkage unit and does not need to be interposable, and
// the GOT use is just a load (not some other operation), this pass can
// transform that load into an LEA (add). This optimizes away one memory load
-// at runtime that could stall the pipeline. This optimization only works
+// which at runtime that could stall the pipeline. This optimization only works
// for architectures in which a (GOT) load instruction can be change to an
-// LEA instruction that is the same size. The platform method isGOTAccess()
+// LEA instruction that is the same size. The method isGOTAccess()
// should only return true for "canBypassGOT" if this optimization is supported.
//
//===----------------------------------------------------------------------===//
@@ -35,23 +35,21 @@
#include "lld/Core/File.h"
#include "lld/Core/LLVM.h"
#include "lld/Core/Pass.h"
-#include "lld/Core/Platform.h"
#include "lld/Core/Reference.h"
-
#include "llvm/ADT/DenseMap.h"
namespace lld {
-void GOTPass::perform() {
+void GOTPass::perform(File& mergedFile) {
// Use map so all pointers to same symbol use same GOT entry.
llvm::DenseMap<const Atom*, const DefinedAtom*> targetToGOT;
// Scan all references in all atoms.
- for(const DefinedAtom *atom : _file.defined()) {
+ for(const DefinedAtom *atom : mergedFile.defined()) {
for (const Reference *ref : *atom) {
// Look at instructions accessing the GOT.
bool canBypassGOT;
- if ( _platform.isGOTAccess(ref->kind(), canBypassGOT) ) {
+ if ( this->isGOTAccess(ref->kind(), canBypassGOT) ) {
const Atom* target = ref->target();
assert(target != nullptr);
const DefinedAtom* defTarget = dyn_cast<DefinedAtom>(target);
@@ -72,14 +70,14 @@ void GOTPass::perform() {
// GOT to be by-passed, do that optimization and don't create
// GOT entry.
replaceTargetWithGOTAtom = !canBypassGOT;
- }
+ }
if ( replaceTargetWithGOTAtom ) {
// Replace the target with a reference to a GOT entry.
const DefinedAtom* gotEntry = nullptr;
auto pos = targetToGOT.find(target);
if ( pos == targetToGOT.end() ) {
// This is no existing GOT entry. Create a new one.
- gotEntry = _platform.makeGOTEntry(*target, _file);
+ gotEntry = this->makeGOTEntry(*target);
assert(gotEntry != nullptr);
assert(gotEntry->contentType() == DefinedAtom::typeGOT);
targetToGOT[target] = gotEntry;
@@ -92,16 +90,16 @@ void GOTPass::perform() {
// Switch reference to GOT atom.
(const_cast<Reference*>(ref))->setTarget(gotEntry);
}
- // Platform needs to update reference kind to reflect
- // that target is a GOT entry or a direct accesss.
- _platform.updateReferenceToGOT(ref, replaceTargetWithGOTAtom);
+ // Update reference kind to reflect
+ // that target is now a GOT entry or a direct accesss.
+ this->updateReferenceToGOT(ref, replaceTargetWithGOTAtom);
}
}
}
// add all created GOT Atoms to master file
for (auto it=targetToGOT.begin(), end=targetToGOT.end(); it != end; ++it) {
- _file.addAtom(*it->second);
+ mergedFile.addAtom(*it->second);
}
diff --git a/lld/lib/Passes/StubsPass.cpp b/lld/lib/Passes/StubsPass.cpp
index b81d0a27a39..c468959d2cc 100644
--- a/lld/lib/Passes/StubsPass.cpp
+++ b/lld/lib/Passes/StubsPass.cpp
@@ -7,10 +7,10 @@
//
//===----------------------------------------------------------------------===//
//
-// This linker pass updates call sites which have references to shared library
+// This linker pass updates call-sites which have references to shared library
// atoms to instead have a reference to a stub (PLT entry) for the specified
-// symbol. The platform object does the work of creating the platform-specific
-// StubAtom.
+// symbol. Each file format defines a subclass of StubsPass which implements
+// the abstract methods for creating the file format specific StubAtoms.
//
//===----------------------------------------------------------------------===//
@@ -18,30 +18,28 @@
#include "lld/Core/File.h"
#include "lld/Core/LLVM.h"
#include "lld/Core/Pass.h"
-#include "lld/Core/Platform.h"
#include "lld/Core/Reference.h"
-
#include "llvm/ADT/DenseMap.h"
namespace lld {
-void StubsPass::perform() {
+void StubsPass::perform(File& mergedFile) {
// Skip this pass if output format uses text relocations instead of stubs.
- if ( !_platform.noTextRelocs() )
+ if ( ! this->noTextRelocs() )
return;
// Scan all references in all atoms.
- for(const DefinedAtom *atom : _file.defined()) {
+ for(const DefinedAtom *atom : mergedFile.defined()) {
for (const Reference *ref : *atom) {
// Look at call-sites.
- if ( _platform.isCallSite(ref->kind()) ) {
+ if (this->isCallSite(ref->kind()) ) {
const Atom* target = ref->target();
assert(target != nullptr);
bool replaceCalleeWithStub = false;
if ( target->definition() == Atom::definitionSharedLibrary ) {
// Calls to shared libraries go through stubs.
replaceCalleeWithStub = true;
- }
+ }
else if (const DefinedAtom* defTarget =
dyn_cast<DefinedAtom>(target)) {
if ( defTarget->interposable() != DefinedAtom::interposeNo ) {
@@ -52,8 +50,8 @@ void StubsPass::perform() {
}
}
if ( replaceCalleeWithStub ) {
- // Ask platform to make stub and other support atoms.
- const DefinedAtom* stub = _platform.getStub(*target, _file);
+ // Make file-format specific stub and other support atoms.
+ const DefinedAtom* stub = this->getStub(*target);
assert(stub != nullptr);
// Switch call site to reference stub atom instead.
(const_cast<Reference*>(ref))->setTarget(stub);
@@ -62,8 +60,8 @@ void StubsPass::perform() {
}
}
- // Tell platform to add all created stubs and support Atoms to file.
- _platform.addStubAtoms(_file);
+ // Add all created stubs and support Atoms.
+ this->addStubAtoms(mergedFile);
}
diff --git a/lld/lib/Platforms/CMakeLists.txt b/lld/lib/Platforms/CMakeLists.txt
deleted file mode 100644
index 6bb912c33a2..00000000000
--- a/lld/lib/Platforms/CMakeLists.txt
+++ /dev/null
@@ -1 +0,0 @@
-add_subdirectory(Darwin)
diff --git a/lld/lib/Platforms/Darwin/CMakeLists.txt b/lld/lib/Platforms/Darwin/CMakeLists.txt
deleted file mode 100644
index 99dafc1cc83..00000000000
--- a/lld/lib/Platforms/Darwin/CMakeLists.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-add_lld_library(lldDarwinPlatform
- DarwinPlatform.cpp
- DarwinReferenceKinds.cpp
- ExecutableWriter.cpp
- )
diff --git a/lld/lib/Platforms/Darwin/DarwinPlatform.cpp b/lld/lib/Platforms/Darwin/DarwinPlatform.cpp
deleted file mode 100644
index 3fdc039095a..00000000000
--- a/lld/lib/Platforms/Darwin/DarwinPlatform.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-//===- Platforms/Darwin/DarwinPlatform.cpp --------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "DarwinPlatform.h"
-#include "MachOFormat.hpp"
-#include "StubAtoms.hpp"
-#include "ExecutableAtoms.hpp"
-#include "DarwinReferenceKinds.h"
-#include "ExecutableWriter.h"
-
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reference.h"
-#include "lld/Core/InputFiles.h"
-
-#include "llvm/Support/ErrorHandling.h"
-
-namespace lld {
-
-Platform *createDarwinPlatform() {
- return new darwin::DarwinPlatform();
-}
-
-
-namespace darwin {
-
-DarwinPlatform::DarwinPlatform()
- : _helperCommonAtom(nullptr), _cRuntimeFile(nullptr) {
-}
-
-void DarwinPlatform::addFiles(InputFiles &inputFiles) {
- _cRuntimeFile = new CRuntimeFile();
- inputFiles.prependFile(*_cRuntimeFile);
-}
-
-Reference::Kind DarwinPlatform::kindFromString(StringRef kindName) {
- return ReferenceKind::fromString(kindName);
-}
-
-
-StringRef DarwinPlatform::kindToString(Reference::Kind kindValue) {
- return ReferenceKind::toString(kindValue);
-}
-
-bool DarwinPlatform::noTextRelocs() {
- return true;
-}
-
-
-bool DarwinPlatform::isCallSite(Reference::Kind kind) {
- return ReferenceKind::isCallSite(kind);
-}
-
-
-bool DarwinPlatform::isGOTAccess(Reference::Kind, bool& canBypassGOT) {
- return false;
-}
-
-
-void DarwinPlatform::updateReferenceToGOT(const Reference*, bool nowGOT) {
-}
-
-
-const DefinedAtom* DarwinPlatform::getStub(const Atom& target, File& file) {
- auto pos = _targetToStub.find(&target);
- if ( pos != _targetToStub.end() ) {
- // Reuse an existing stub.
- assert(pos->second != nullptr);
- return pos->second;
- }
- else {
- // There is no existing stub, so create a new one.
- if ( _helperCommonAtom == nullptr ) {
- // Lazily create common helper code and data.
- _helperCacheAtom = new X86_64NonLazyPointerAtom(file);
- _stubBinderAtom = new StubBinderAtom(file);
- _helperBinderAtom = new X86_64NonLazyPointerAtom(file, *_stubBinderAtom);
- _helperCommonAtom = new X86_64StubHelperCommonAtom(file,
- *_helperCacheAtom, *_helperBinderAtom);
- }
- const DefinedAtom* helper = new X86_64StubHelperAtom(file,
- *_helperCommonAtom);
- _stubHelperAtoms.push_back(helper);
- const DefinedAtom* lp = new X86_64LazyPointerAtom(file, *helper, target);
- assert(lp->contentType() == DefinedAtom::typeLazyPointer);
- const DefinedAtom* stub = new X86_64StubAtom(file, *lp);
- assert(stub->contentType() == DefinedAtom::typeStub);
- _targetToStub[&target] = stub;
- _lazyPointers.push_back(lp);
- return stub;
- }
-}
-
-
-void DarwinPlatform::addStubAtoms(File &file) {
- // Add all stubs to master file.
- for (auto it=_targetToStub.begin(), end=_targetToStub.end(); it != end; ++it) {
- file.addAtom(*it->second);
- }
- // Add helper code atoms.
- file.addAtom(*_helperCommonAtom);
- for (const DefinedAtom *lp : _stubHelperAtoms) {
- file.addAtom(*lp);
- }
- // Add GOT slots used for lazy binding.
- file.addAtom(*_helperBinderAtom);
- file.addAtom(*_helperCacheAtom);
- // Add all lazy pointers to master file.
- for (const DefinedAtom *lp : _lazyPointers) {
- file.addAtom(*lp);
- }
- // Add sharedlibrary atom
- file.addAtom(*_stubBinderAtom);
-}
-
-
-const DefinedAtom* DarwinPlatform::makeGOTEntry(const Atom&, File&) {
- return nullptr;
-}
-
-void DarwinPlatform::applyFixup(Reference::Kind kind, uint64_t addend,
- uint8_t* location, uint64_t fixupAddress,
- uint64_t targetAddress) {
- //fprintf(stderr, "applyFixup(kind=%s, addend=0x%0llX, "
- // "fixupAddress=0x%0llX, targetAddress=0x%0llX\n",
- // kindToString(kind).data(), addend,
- // fixupAddress, targetAddress);
- if ( ReferenceKind::isRipRel32(kind) ) {
- // compute rip relative value and update.
- int32_t* loc32 = reinterpret_cast<int32_t*>(location);
- *loc32 = (targetAddress - (fixupAddress+4)) + addend;
- }
- else if ( kind == ReferenceKind::pointer64 ) {
- uint64_t* loc64 = reinterpret_cast<uint64_t*>(location);
- *loc64 = targetAddress + addend;
- }
-}
-
-void DarwinPlatform::writeExecutable(const lld::File &file, raw_ostream &out) {
- lld::darwin::writeExecutable(file, *this, out);
-}
-
-
-uint64_t DarwinPlatform::pageZeroSize() {
- return 0x100000000;
-}
-
-
-void DarwinPlatform::initializeMachHeader(const lld::File& file,
- mach_header& mh) {
- // FIXME: Need to get cpu info from file object
- mh.magic = MAGIC_64;
- mh.cputype = CPU_TYPE_X86_64;
- mh.cpusubtype = CPU_SUBTYPE_X86_64_ALL;
- mh.filetype = MH_EXECUTE;
- mh.ncmds = 0;
- mh.sizeofcmds = 0;
- mh.flags = 0;
- mh.reserved = 0;
-}
-
-const Atom *DarwinPlatform::mainAtom() {
- assert(_cRuntimeFile != nullptr);
- const Atom *result = _cRuntimeFile->mainAtom();
- assert(result != nullptr);
- if ( result->definition() == Atom::definitionUndefined )
- llvm::report_fatal_error("_main not found");
- return _cRuntimeFile->mainAtom();
-}
-
-
-
-} // namespace darwin
-} // namespace lld
diff --git a/lld/lib/Platforms/Darwin/DarwinPlatform.h b/lld/lib/Platforms/Darwin/DarwinPlatform.h
deleted file mode 100644
index c05fb9c2bbb..00000000000
--- a/lld/lib/Platforms/Darwin/DarwinPlatform.h
+++ /dev/null
@@ -1,61 +0,0 @@
-//===- Platform/DarwinPlatform.h - Darwin Platform Implementation ---------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_PLATFORM_DARWIN_PLATFORM_H_
-#define LLD_PLATFORM_DARWIN_PLATFORM_H_
-
-#include "lld/Core/Platform.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseMap.h"
-
-namespace lld {
-namespace darwin {
-
-class DarwinPlatform : public Platform {
-public:
- DarwinPlatform();
-
-/// @name Platform methods
-/// @{
- virtual void addFiles(InputFiles&);
- virtual Reference::Kind kindFromString(llvm::StringRef);
- virtual llvm::StringRef kindToString(Reference::Kind);
- virtual bool noTextRelocs();
- virtual bool isCallSite(Reference::Kind);
- virtual bool isGOTAccess(Reference::Kind, bool& canBypassGOT);
- virtual void updateReferenceToGOT(const Reference*, bool targetIsNowGOT);
- virtual const DefinedAtom* getStub(const Atom&, File&);
- virtual void addStubAtoms(File &file);
- virtual const DefinedAtom* makeGOTEntry(const Atom&, File&);
- virtual void applyFixup(Reference::Kind, uint64_t addend, uint8_t*,
- uint64_t fixupAddress, uint64_t targetAddress);
- virtual void writeExecutable(const lld::File &, raw_ostream &out);
-/// @}
-/// @name Darwin specific methods
-/// @{
- uint64_t pageZeroSize();
- void initializeMachHeader(const lld::File& file, class mach_header& mh);
- const Atom *mainAtom();
-/// @}
-
-private:
- llvm::DenseMap<const Atom*, const DefinedAtom*> _targetToStub;
- std::vector<const DefinedAtom*> _lazyPointers;
- std::vector<const DefinedAtom*> _stubHelperAtoms;
- const SharedLibraryAtom *_stubBinderAtom;
- const DefinedAtom* _helperCommonAtom;
- const DefinedAtom* _helperCacheAtom;
- const DefinedAtom* _helperBinderAtom;
- class CRuntimeFile *_cRuntimeFile;
-};
-
-} // namespace darwin
-} // namespace lld
-
-#endif // LLD_PLATFORM_DARWIN_PLATFORM_H_
diff --git a/lld/lib/Platforms/Darwin/DarwinReferenceKinds.cpp b/lld/lib/Platforms/Darwin/DarwinReferenceKinds.cpp
deleted file mode 100644
index 3cc676c6884..00000000000
--- a/lld/lib/Platforms/Darwin/DarwinReferenceKinds.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-//===- Platforms/Darwin/DarwinReferenceKinds.cpp --------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-
-#include "DarwinReferenceKinds.h"
-#include "llvm/ADT/StringRef.h"
-
-
-namespace lld {
-namespace darwin {
-
-
-struct Mapping {
- const char* string;
- Reference::Kind value;
- uint32_t flags;
-};
-
-enum {
- flagsNone = 0x0000,
- flagsIsCallSite = 0x0001,
- flagsUsesGOT = 0x0002,
- flagsisGOTLoad = 0x0006,
- flags32RipRel = 0x1000,
-};
-
-
-static const Mapping sKindMappings[] = {
- { "none", ReferenceKind::none, flagsNone },
- { "call32", ReferenceKind::call32, flagsIsCallSite | flags32RipRel },
- { "pcrel32", ReferenceKind::pcRel32, flags32RipRel },
- { "gotLoad32", ReferenceKind::gotLoad32, flagsisGOTLoad | flags32RipRel },
- { "gotUse32", ReferenceKind::gotUse32, flagsUsesGOT | flags32RipRel },
- { "lea32wasGot", ReferenceKind::lea32WasGot, flags32RipRel },
- { "lazyTarget", ReferenceKind::lazyTarget, flagsNone },
- { "lazyImm", ReferenceKind::lazyImm, flagsNone },
- { "gotTarget", ReferenceKind::gotTarget, flagsNone },
- { "pointer64", ReferenceKind::pointer64, flagsNone },
- { NULL, ReferenceKind::none, flagsNone }
-};
-
-
-Reference::Kind ReferenceKind::fromString(StringRef kindName) {
- for (const Mapping* p = sKindMappings; p->string != NULL; ++p) {
- if ( kindName.equals(p->string) )
- return p->value;
- }
- assert(0 && "unknown darwin reference kind");
- return ReferenceKind::none;
-}
-
-StringRef ReferenceKind::toString(Reference::Kind kindValue) {
- for (const Mapping* p = sKindMappings; p->string != NULL; ++p) {
- if ( kindValue == p->value)
- return p->string;
- }
- return StringRef("???");
-}
-
-bool ReferenceKind::isCallSite(Reference::Kind kindValue) {
- for (const Mapping* p = sKindMappings; p->string != NULL; ++p) {
- if ( kindValue == p->value )
- return (p->flags & flagsIsCallSite);
- }
- return false;
-}
-
-bool ReferenceKind::isRipRel32(Reference::Kind kindValue) {
- for (const Mapping* p = sKindMappings; p->string != NULL; ++p) {
- if ( kindValue == p->value )
- return (p->flags & flags32RipRel);
- }
- return false;
-}
-
-
-
-
-
-} // namespace darwin
-} // namespace lld
-
-
-
diff --git a/lld/lib/Platforms/Darwin/DarwinReferenceKinds.h b/lld/lib/Platforms/Darwin/DarwinReferenceKinds.h
deleted file mode 100644
index 9cb254235cf..00000000000
--- a/lld/lib/Platforms/Darwin/DarwinReferenceKinds.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//===- Platforms/Darwin/DarwinReferenceKinds.h ----------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-
-#include "lld/Core/LLVM.h"
-#include "lld/Core/Reference.h"
-
-
-#ifndef LLD_PLATFORM_DARWIN_REFERENCE_KINDS_H_
-#define LLD_PLATFORM_DARWIN_REFERENCE_KINDS_H_
-
-namespace lld {
-namespace darwin {
-
-
-class ReferenceKind {
-public:
- enum {
- none = 0,
- call32 = 1,
- pcRel32 = 2,
- gotLoad32 = 3,
- gotUse32 = 4,
- lea32WasGot = 5,
- lazyTarget = 6,
- lazyImm = 7,
- gotTarget = 8,
- pointer64 = 9,
- };
-
- static Reference::Kind fromString(StringRef kindName);
-
- static StringRef toString(Reference::Kind kindValue);
-
- static bool isCallSite(Reference::Kind kindValue);
-
- static bool isRipRel32(Reference::Kind kindValue);
-};
-
-
-
-} // namespace darwin
-} // namespace lld
-
-
-
-#endif // LLD_PLATFORM_DARWIN_REFERENCE_KINDS_H_
-
diff --git a/lld/lib/Platforms/Darwin/ExecutableAtoms.hpp b/lld/lib/Platforms/Darwin/ExecutableAtoms.hpp
deleted file mode 100644
index 31bd181ccb3..00000000000
--- a/lld/lib/Platforms/Darwin/ExecutableAtoms.hpp
+++ /dev/null
@@ -1,84 +0,0 @@
-//===- Platforms/Darwin/x86_64StubAtom.hpp --------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_PLATFORM_DARWIN_EXECUTABLE_ATOM_H_
-#define LLD_PLATFORM_DARWIN_EXECUTABLE_ATOM_H_
-
-
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/UndefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reference.h"
-
-#include "DarwinReferenceKinds.h"
-#include "SimpleAtoms.hpp"
-
-namespace lld {
-namespace darwin {
-
-
-//
-// EntryPointReferenceAtom is used to:
-// 1) Require "_main" is defined.
-// 2) Give Darwin Platform a pointer to the atom named "_main"
-//
-class EntryPointReferenceAtom : public SimpleDefinedAtom {
-public:
- EntryPointReferenceAtom(const File &file)
- : SimpleDefinedAtom(file)
- , _mainUndefAtom(file, "_main") {
- this->addReference(ReferenceKind::none, 0, &_mainUndefAtom, 0);
- }
-
- virtual ContentType contentType() const {
- return DefinedAtom::typeCode;
- }
-
- virtual uint64_t size() const {
- return 0;
- }
-
- virtual ContentPermissions permissions() const {
- return DefinedAtom::permR_X;
- }
-
- virtual ArrayRef<uint8_t> rawContent() const {
- return ArrayRef<uint8_t>();
- }
-private:
- friend class CRuntimeFile;
- SimpleUndefinedAtom _mainUndefAtom;
-};
-
-
-class CRuntimeFile : public SimpleFile {
-public:
- CRuntimeFile()
- : SimpleFile("C runtime")
- , _atom(*this) {
- this->addAtom(_atom);
- this->addAtom(_atom._mainUndefAtom);
- }
-
- const Atom *mainAtom() {
- const Reference *ref = *(_atom.begin());
- return ref->target();
- }
-
-private:
- EntryPointReferenceAtom _atom;
-};
-
-
-
-} // namespace darwin
-} // namespace lld
-
-
-#endif // LLD_PLATFORM_DARWIN_EXECUTABLE_ATOM_H_
diff --git a/lld/lib/Platforms/Darwin/ExecutableWriter.h b/lld/lib/Platforms/Darwin/ExecutableWriter.h
deleted file mode 100644
index 5980f85b6ad..00000000000
--- a/lld/lib/Platforms/Darwin/ExecutableWriter.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//===- Platforms/Darwin/ExecutableWriter.h --------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-
-#include "lld/Core/LLVM.h"
-
-
-#ifndef LLD_PLATFORM_DARWIN_EXECUTABLE_WRITER_H_
-#define LLD_PLATFORM_DARWIN_EXECUTABLE_WRITER_H_
-
-namespace lld {
-
-class File;
-
-namespace darwin {
-
-class DarwinPlatform;
-
-void writeExecutable(const lld::File &file, DarwinPlatform &platform,
- raw_ostream &out);
-
-
-} // namespace darwin
-} // namespace lld
-
-
-
-#endif // LLD_PLATFORM_DARWIN_EXECUTABLE_WRITER_H_
-
diff --git a/lld/lib/Reader/CMakeLists.txt b/lld/lib/Reader/CMakeLists.txt
deleted file mode 100644
index c8f2421649c..00000000000
--- a/lld/lib/Reader/CMakeLists.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-add_lld_library(lldReader
- COFFReader.cpp
- )
diff --git a/lld/lib/ReaderWriter/CMakeLists.txt b/lld/lib/ReaderWriter/CMakeLists.txt
new file mode 100644
index 00000000000..85ec90bc60f
--- /dev/null
+++ b/lld/lib/ReaderWriter/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_subdirectory(ELF)
+add_subdirectory(MachO)
+add_subdirectory(Native)
+add_subdirectory(PECOFF)
+add_subdirectory(YAML)
+add_lld_library(lldReaderWriter
+ Reader.cpp
+ Writer.cpp
+ )
diff --git a/lld/lib/ReaderWriter/ELF/CMakeLists.txt b/lld/lib/ReaderWriter/ELF/CMakeLists.txt
new file mode 100644
index 00000000000..4a28b631915
--- /dev/null
+++ b/lld/lib/ReaderWriter/ELF/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_lld_library(lldELF
+ ReaderELF.cpp
+ WriterELF.cpp
+ )
diff --git a/lld/lib/ReaderWriter/ELF/ReaderELF.cpp b/lld/lib/ReaderWriter/ELF/ReaderELF.cpp
new file mode 100644
index 00000000000..ba23990ea0a
--- /dev/null
+++ b/lld/lib/ReaderWriter/ELF/ReaderELF.cpp
@@ -0,0 +1,41 @@
+//===- lib/ReaderWriter/ELF/ReaderELF.cpp --------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/ReaderELF.h"
+#include "lld/Core/File.h"
+
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Memory.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
+
+#include <map>
+#include <vector>
+
+
+namespace lld {
+
+ReaderOptionsELF::ReaderOptionsELF() {
+}
+
+ReaderOptionsELF::~ReaderOptionsELF() {
+}
+
+
+
+Reader* createReaderELF(const ReaderOptionsELF &options) {
+ assert(0 && "ELF Reader not yet implemented");
+ return nullptr;
+}
+
+
+} // namespace
+
diff --git a/lld/lib/ReaderWriter/ELF/WriterELF.cpp b/lld/lib/ReaderWriter/ELF/WriterELF.cpp
new file mode 100644
index 00000000000..fe445b6f08e
--- /dev/null
+++ b/lld/lib/ReaderWriter/ELF/WriterELF.cpp
@@ -0,0 +1,35 @@
+//===- lib/ReaderWriter/ELF/WriterELF.cpp ---------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/WriterELF.h"
+
+#include "llvm/Support/Debug.h"
+
+
+namespace lld {
+namespace elf {
+
+// define ELF writer class here
+
+
+} // namespace elf
+
+Writer* createWriterELF(const WriterOptionsELF &options) {
+ assert(0 && "ELF support not implemented yet");
+ return nullptr;
+}
+
+WriterOptionsELF::WriterOptionsELF() {
+}
+
+WriterOptionsELF::~WriterOptionsELF() {
+}
+
+} // namespace lld
+
diff --git a/lld/lib/ReaderWriter/MachO/CMakeLists.txt b/lld/lib/ReaderWriter/MachO/CMakeLists.txt
new file mode 100644
index 00000000000..c6a1059802c
--- /dev/null
+++ b/lld/lib/ReaderWriter/MachO/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_lld_library(lldMachO
+ WriterMachO.cpp
+ ReferenceKinds.cpp
+ )
diff --git a/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp b/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp
new file mode 100644
index 00000000000..ac80059624c
--- /dev/null
+++ b/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp
@@ -0,0 +1,50 @@
+//===- lib/ReaderWriter/MachO/ExecutableAtoms.hpp -------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_MACHO_EXECUTABLE_ATOM_H_
+#define LLD_READER_WRITER_MACHO_EXECUTABLE_ATOM_H_
+
+
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/UndefinedAtom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/Reference.h"
+
+#include "lld/ReaderWriter/WriterMachO.h"
+
+#include "SimpleAtoms.hpp"
+
+namespace lld {
+namespace mach_o {
+
+
+//
+// CRuntimeFile adds an UndefinedAtom for "_main" so that the Resolving
+// phase will fail if "_main" is undefined.
+//
+class CRuntimeFile : public SimpleFile {
+public:
+ CRuntimeFile(const WriterOptionsMachO &options)
+ : SimpleFile("C runtime"), _undefMain(*this, "_main") {
+ // only main executables need _main
+ if ( options.outputKind() == WriterOptionsMachO::outputDynamicExecutable)
+ this->addAtom(_undefMain);
+ }
+
+private:
+ SimpleUndefinedAtom _undefMain;
+};
+
+
+
+} // namespace mach_o
+} // namespace lld
+
+
+#endif // LLD_READER_WRITER_MACHO_EXECUTABLE_ATOM_H_
diff --git a/lld/lib/ReaderWriter/MachO/GOTPass.hpp b/lld/lib/ReaderWriter/MachO/GOTPass.hpp
new file mode 100644
index 00000000000..6a7c451e448
--- /dev/null
+++ b/lld/lib/ReaderWriter/MachO/GOTPass.hpp
@@ -0,0 +1,51 @@
+//===- lib/ReaderWriter/MachO/GOTPass.hpp ---------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_MACHO_GOT_PASS_H_
+#define LLD_READER_WRITER_MACHO_GOT_PASS_H_
+
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/SharedLibraryAtom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/Reference.h"
+#include "lld/Core/Pass.h"
+
+#include "ReferenceKinds.h"
+#include "StubAtoms.hpp"
+
+namespace lld {
+namespace mach_o {
+
+
+class GOTPass : public lld::GOTPass {
+public:
+ virtual bool noTextRelocs() {
+ return true;
+ }
+
+ virtual bool isGOTAccess(Reference::Kind, bool& canBypassGOT) {
+ return false;
+ }
+
+ virtual void updateReferenceToGOT(const Reference*, bool targetIsNowGOT) {
+
+ }
+
+ virtual const DefinedAtom* makeGOTEntry(const Atom&) {
+ return nullptr;
+ }
+
+};
+
+
+} // namespace mach_o
+} // namespace lld
+
+
+#endif // LLD_READER_WRITER_MACHO_GOT_PASS_H_
diff --git a/lld/lib/Platforms/Darwin/MachOFormat.hpp b/lld/lib/ReaderWriter/MachO/MachOFormat.hpp
index 55340aa6145..e6a04e1dd74 100644
--- a/lld/lib/Platforms/Darwin/MachOFormat.hpp
+++ b/lld/lib/ReaderWriter/MachO/MachOFormat.hpp
@@ -1,4 +1,4 @@
-//===- Platforms/Darwin/MachOFormat.hpp -----------------------------------===//
+//===- lib/ReaderWriter/MachO/MachOFormat.hpp -----------------------------===//
//
// The LLVM Linker
//
@@ -15,22 +15,22 @@
//
#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Memory.h"
-
-#ifndef LLD_PLATFORM_DARWIN_MACHO_FORMAT_H_
-#define LLD_PLATFORM_DARWIN_MACHO_FORMAT_H_
+#ifndef LLD_READER_WRITER_MACHO_FORMAT_H_
+#define LLD_READER_WRITER_MACHO_FORMAT_H_
namespace lld {
-namespace darwin {
+namespace mach_o {
class load_command {
public:
uint32_t cmd;
uint32_t cmdsize;
- void write(raw_ostream& out) {
- out.write((char*)&cmd, cmdsize);
+ void copyTo(uint8_t* to, bool swap=false) {
+ ::memcpy(to, (uint8_t*)&cmd, cmdsize);
}
};
@@ -50,9 +50,13 @@ enum {
};
enum {
- MH_EXECUTE = 0x2,
- MH_DYLIB = 0x6,
- MH_BUNDLE = 0x8
+ MH_OBJECT = 0x1,
+ MH_EXECUTE = 0x2,
+ MH_DYLIB = 0x6,
+ MH_DYLINKER = 0x7,
+ MH_BUNDLE = 0x8,
+ MH_DYLIB_STUB = 0x9,
+ MH_KEXT_BUNDLE= 0xB
};
@@ -65,14 +69,14 @@ public:
uint32_t ncmds;
uint32_t sizeofcmds;
uint32_t flags;
- uint32_t reserved;
+ uint32_t reserved;
uint64_t size() {
return (magic == 0xfeedfacf) ? 32 : 28;
}
- void write(raw_ostream& out) {
- out.write((char*)&magic, this->size());
+ void copyTo(uint8_t* to, bool swap=false) {
+ ::memcpy(to, (char*)&magic, this->size());
}
void recordLoadCommand(const class load_command* lc) {
@@ -140,7 +144,11 @@ public:
// The segment_command_64 load commands has a nsect trailing
// section_64 records appended to the end.
static segment_command_64* make(unsigned sectCount) {
- unsigned size = sizeof(segment_command_64) + sectCount* sizeof(section_64);
+ // Compute size in portable way. Can't use offsetof() in non-POD class.
+ // Can't use zero size sections[] array above.
+ // So, since sizeof() already includes one section_64, subtract it off.
+ unsigned size = sizeof(segment_command_64)
+ + ((int)sectCount -1) * sizeof(section_64);
segment_command_64* result = reinterpret_cast<segment_command_64*>
(::calloc(1, size));
result->cmd = LC_SEGMENT_64;
@@ -194,8 +202,8 @@ public:
uint16_t n_desc;
uint64_t n_value;
- void write(raw_ostream& out) {
- out.write((char*)&n_strx, 16);
+ void copyTo(uint8_t* to, bool swap=false) {
+ ::memcpy(to, (uint8_t*)&n_strx, 16);
}
@@ -337,10 +345,10 @@ enum {
-} // namespace darwin
+} // namespace mach_o
} // namespace lld
-#endif // LLD_PLATFORM_DARWIN_MACHO_FORMAT_H_
+#endif // LLD_READER_WRITER_MACHO_FORMAT_H_
diff --git a/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp b/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp
new file mode 100644
index 00000000000..a0b3dbfa5c6
--- /dev/null
+++ b/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp
@@ -0,0 +1,103 @@
+//===- lib/FileFormat/MachO/ReferenceKinds.cpp ----------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "ReferenceKinds.h"
+
+#include "llvm/ADT/StringRef.h"
+
+
+namespace lld {
+namespace mach_o {
+
+
+struct Mapping {
+ const char* string;
+ Reference::Kind value;
+ uint32_t flags;
+};
+
+enum {
+ flagsNone = 0x0000,
+ flagsIsCallSite = 0x0001,
+ flagsUsesGOT = 0x0002,
+ flagsisGOTLoad = 0x0006,
+ flags32RipRel = 0x1000,
+};
+
+
+static const Mapping sKindMappingsx86_64[] = {
+ { "none", ReferenceKind::x86_64_none, flagsNone },
+ { "call32", ReferenceKind::x86_64_call32, flagsIsCallSite | flags32RipRel },
+ { "pcrel32", ReferenceKind::x86_64_pcRel32, flags32RipRel },
+ { "gotLoad32", ReferenceKind::x86_64_gotLoad32, flagsisGOTLoad | flags32RipRel },
+ { "gotUse32", ReferenceKind::x86_64_gotUse32, flagsUsesGOT | flags32RipRel },
+ { "lea32wasGot", ReferenceKind::x86_64_lea32WasGot, flags32RipRel },
+ { "lazyTarget", ReferenceKind::x86_64_lazyTarget, flagsNone },
+ { "lazyImm", ReferenceKind::x86_64_lazyImm, flagsNone },
+ { "gotTarget", ReferenceKind::x86_64_gotTarget, flagsNone },
+ { "pointer64", ReferenceKind::x86_64_pointer64, flagsNone },
+ { NULL, ReferenceKind::x86_64_none, flagsNone }
+};
+
+
+Reference::Kind ReferenceKind::fromString(StringRef kindName) {
+ for (const Mapping* p = sKindMappingsx86_64; p->string != NULL; ++p) {
+ if ( kindName.equals(p->string) )
+ return p->value;
+ }
+ assert(0 && "unknown darwin reference kind");
+ return 0;
+}
+
+StringRef ReferenceKind::toString(Reference::Kind kindValue) {
+ for (const Mapping* p = sKindMappingsx86_64; p->string != NULL; ++p) {
+ if ( kindValue == p->value)
+ return p->string;
+ }
+ return StringRef("???");
+}
+
+static const Mapping* mappingsForArch(WriterOptionsMachO::Architecture arch) {
+ switch ( arch ) {
+ case WriterOptionsMachO::arch_x86_64:
+ return sKindMappingsx86_64;
+ case WriterOptionsMachO::arch_x86:
+ case WriterOptionsMachO::arch_arm:
+ assert(0 && "references table not yet implemented for arch");
+ return nullptr;
+ }
+}
+
+bool ReferenceKind::isCallSite(WriterOptionsMachO::Architecture arch,
+ Reference::Kind kindValue) {
+ for (const Mapping* p = mappingsForArch(arch); p->string != NULL; ++p) {
+ if ( kindValue == p->value )
+ return (p->flags & flagsIsCallSite);
+ }
+ return false;
+}
+
+bool ReferenceKind::isRipRel32(Reference::Kind kindValue) {
+ for (const Mapping* p = sKindMappingsx86_64; p->string != NULL; ++p) {
+ if ( kindValue == p->value )
+ return (p->flags & flags32RipRel);
+ }
+ return false;
+}
+
+
+
+
+
+} // namespace mach_o
+} // namespace lld
+
+
+
diff --git a/lld/lib/ReaderWriter/MachO/ReferenceKinds.h b/lld/lib/ReaderWriter/MachO/ReferenceKinds.h
new file mode 100644
index 00000000000..8680b346c2d
--- /dev/null
+++ b/lld/lib/ReaderWriter/MachO/ReferenceKinds.h
@@ -0,0 +1,77 @@
+//===- lib/FileFormat/MachO/ReferenceKinds.h ------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "lld/Core/LLVM.h"
+#include "lld/Core/Reference.h"
+#include "lld/ReaderWriter/WriterMachO.h"
+
+#ifndef LLD_READER_WRITER_MACHO_REFERENCE_KINDS_H_
+#define LLD_READER_WRITER_MACHO_REFERENCE_KINDS_H_
+
+namespace lld {
+namespace mach_o {
+
+
+class ReferenceKind {
+public:
+ // x86_64 Reference Kinds
+ enum {
+ x86_64_none = 0,
+ x86_64_call32 = 1,
+ x86_64_pcRel32 = 2,
+ x86_64_gotLoad32 = 3,
+ x86_64_gotUse32 = 4,
+ x86_64_lea32WasGot = 5,
+ x86_64_lazyTarget = 6,
+ x86_64_lazyImm = 7,
+ x86_64_gotTarget = 8,
+ x86_64_pointer64 = 9,
+ };
+
+ // x86 Reference Kinds
+ enum {
+ x86_none = 0,
+ x86_call32 = 1,
+ x86_pointer32 = 2,
+ x86_lazyTarget = 3,
+ x86_lazyImm = 4,
+ // FIXME
+ };
+
+ // ARM Reference Kinds
+ enum {
+ arm_none = 0,
+ arm_br22 = 1,
+ arm_pointer32 = 2,
+ arm_lazyTarget = 3,
+ arm_lazyImm = 4,
+ // FIXME
+ };
+
+ static bool isCallSite(WriterOptionsMachO::Architecture arch,
+ Reference::Kind kindValue);
+
+ static bool isRipRel32(Reference::Kind kindValue);
+
+
+ static Reference::Kind fromString(StringRef kindName);
+ static StringRef toString(Reference::Kind kindValue);
+
+};
+
+
+
+} // namespace mach_o
+} // namespace lld
+
+
+
+#endif // LLD_READER_WRITER_MACHO_REFERENCE_KINDS_H_
+
diff --git a/lld/lib/Platforms/Darwin/SimpleAtoms.hpp b/lld/lib/ReaderWriter/MachO/SimpleAtoms.hpp
index f9c7aa0130d..498793f4746 100644
--- a/lld/lib/Platforms/Darwin/SimpleAtoms.hpp
+++ b/lld/lib/ReaderWriter/MachO/SimpleAtoms.hpp
@@ -1,4 +1,4 @@
-//===- Platforms/Darwin/x86_64StubAtom.hpp --------------------------------===//
+//===- lib/ReaderWriter/MachO/SimpleAtoms.hpp -----------------------------===//
//
// The LLVM Linker
//
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLD_PLATFORM_DARWIN_SIMPLE_ATOM_H_
-#define LLD_PLATFORM_DARWIN_SIMPLE_ATOM_H_
+#ifndef LLD_READER_WRITER_MACHO_SIMPLE_ATOM_H_
+#define LLD_READER_WRITER_MACHO_SIMPLE_ATOM_H_
#include <vector>
@@ -18,7 +18,7 @@
#include "lld/Core/Reference.h"
namespace lld {
-namespace darwin {
+namespace mach_o {
//
@@ -240,8 +240,8 @@ private:
-} // namespace darwin
+} // namespace mach_o
} // namespace lld
-#endif // LLD_PLATFORM_DARWIN_SIMPLE_ATOM_H_
+#endif // LLD_READER_WRITER_MACHO_SIMPLE_ATOM_H_
diff --git a/lld/lib/Platforms/Darwin/StubAtoms.hpp b/lld/lib/ReaderWriter/MachO/StubAtoms.hpp
index 1023d42010e..3e6bbe19737 100644
--- a/lld/lib/Platforms/Darwin/StubAtoms.hpp
+++ b/lld/lib/ReaderWriter/MachO/StubAtoms.hpp
@@ -1,4 +1,4 @@
-//===- Platforms/Darwin/x86_64StubAtom.hpp --------------------------------===//
+//===- lib/ReaderWriter/MachO/StubAtoms.hpp -------------------------------===//
//
// The LLVM Linker
//
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLD_PLATFORM_DARWIN_X86_64_STUB_ATOM_H_
-#define LLD_PLATFORM_DARWIN_X86_64_STUB_ATOM_H_
+#ifndef LLD_READER_WRITER_MACHO_STUB_ATOM_H_
+#define LLD_READER_WRITER_MACHO_STUB_ATOM_H_
#include "llvm/ADT/ArrayRef.h"
@@ -17,11 +17,11 @@
#include "lld/Core/File.h"
#include "lld/Core/Reference.h"
-#include "DarwinReferenceKinds.h"
+#include "ReferenceKinds.h"
#include "SimpleAtoms.hpp"
namespace lld {
-namespace darwin {
+namespace mach_o {
//
@@ -31,7 +31,7 @@ class X86_64StubAtom : public SimpleDefinedAtom {
public:
X86_64StubAtom(const File &file, const Atom &lazyPointer)
: SimpleDefinedAtom(file) {
- this->addReference(ReferenceKind::pcRel32, 2, &lazyPointer, 0);
+ this->addReference(ReferenceKind::x86_64_pcRel32, 2, &lazyPointer, 0);
}
virtual ContentType contentType() const {
@@ -64,8 +64,8 @@ public:
X86_64StubHelperCommonAtom(const File &file, const Atom &cache,
const Atom &binder)
: SimpleDefinedAtom(file) {
- this->addReference(ReferenceKind::pcRel32, 3, &cache, 0);
- this->addReference(ReferenceKind::pcRel32, 11, &binder, 0);
+ this->addReference(ReferenceKind::x86_64_pcRel32, 3, &cache, 0);
+ this->addReference(ReferenceKind::x86_64_pcRel32, 11, &binder, 0);
}
virtual ContentType contentType() const {
@@ -101,8 +101,8 @@ class X86_64StubHelperAtom : public SimpleDefinedAtom {
public:
X86_64StubHelperAtom(const File &file, const Atom &helperCommon)
: SimpleDefinedAtom(file) {
- this->addReference(ReferenceKind::lazyImm, 1, nullptr, 0);
- this->addReference(ReferenceKind::pcRel32, 6, &helperCommon, 0);
+ this->addReference(ReferenceKind::x86_64_lazyImm, 1, nullptr, 0);
+ this->addReference(ReferenceKind::x86_64_pcRel32, 6, &helperCommon, 0);
}
virtual ContentType contentType() const {
@@ -136,8 +136,8 @@ public:
X86_64LazyPointerAtom(const File &file, const Atom &helper,
const Atom &shlib)
: SimpleDefinedAtom(file) {
- this->addReference(ReferenceKind::pointer64, 0, &helper, 0);
- this->addReference(ReferenceKind::lazyTarget, 0, &shlib, 0);
+ this->addReference(ReferenceKind::x86_64_pointer64, 0, &helper, 0);
+ this->addReference(ReferenceKind::x86_64_lazyTarget, 0, &shlib, 0);
}
virtual ContentType contentType() const {
@@ -172,7 +172,7 @@ public:
X86_64NonLazyPointerAtom(const File &file, const Atom &shlib)
: SimpleDefinedAtom(file) {
- this->addReference(ReferenceKind::pointer64, 0, &shlib, 0);
+ this->addReference(ReferenceKind::x86_64_pointer64, 0, &shlib, 0);
}
virtual ContentType contentType() const {
@@ -226,8 +226,8 @@ private:
-} // namespace darwin
+} // namespace mach_o
} // namespace lld
-#endif // LLD_PLATFORM_DARWIN_X86_64_STUB_ATOM_H_
+#endif // LLD_READER_WRITER_MACHO_STUB_ATOM_H_
diff --git a/lld/lib/ReaderWriter/MachO/StubsPass.hpp b/lld/lib/ReaderWriter/MachO/StubsPass.hpp
new file mode 100644
index 00000000000..34beaa220a6
--- /dev/null
+++ b/lld/lib/ReaderWriter/MachO/StubsPass.hpp
@@ -0,0 +1,145 @@
+//===- lib/ReaderWriter/MachO/StubsPass.hpp -------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_MACHO_STUBS_PASS_H_
+#define LLD_READER_WRITER_MACHO_STUBS_PASS_H_
+
+#include "llvm/ADT/DenseMap.h"
+
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/SharedLibraryAtom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/Reference.h"
+#include "lld/Core/Pass.h"
+
+#include "ReferenceKinds.h"
+#include "SimpleAtoms.hpp"
+#include "StubAtoms.hpp"
+
+namespace lld {
+namespace mach_o {
+
+
+class StubsPass : public lld::StubsPass {
+public:
+ StubsPass(const WriterOptionsMachO &options) : _options(options) {
+ }
+
+ virtual bool noTextRelocs() {
+ return _options.noTextRelocations();
+ }
+
+ virtual bool isCallSite(Reference::Kind kind) {
+ return ReferenceKind::isCallSite(_options.architecture(), kind);
+ }
+
+ virtual const DefinedAtom* getStub(const Atom& target) {
+ auto pos = _targetToStub.find(&target);
+ if ( pos != _targetToStub.end() ) {
+ // Reuse an existing stub.
+ assert(pos->second != nullptr);
+ return pos->second;
+ }
+ else {
+ // There is no existing stub, so create a new one.
+ return this->makeStub(target);
+ }
+ }
+
+ const DefinedAtom* makeStub(const Atom& target) {
+ switch ( _options.architecture() ) {
+ case WriterOptionsMachO::arch_x86_64:
+ return makeStub_x86_64(target);
+
+ case WriterOptionsMachO::arch_x86:
+ return makeStub_x86(target);
+
+ case WriterOptionsMachO::arch_arm:
+ return makeStub_arm(target);
+ }
+ }
+
+ const DefinedAtom* makeStub_x86_64(const Atom& target) {
+ if ( _helperCommonAtom == nullptr ) {
+ // Lazily create common helper code and data.
+ _helperCacheAtom = new X86_64NonLazyPointerAtom(_file);
+ _binderAtom = new StubBinderAtom(_file);
+ _helperBinderAtom = new X86_64NonLazyPointerAtom(_file, *_binderAtom);
+ _helperCommonAtom = new X86_64StubHelperCommonAtom(_file,
+ *_helperCacheAtom, *_helperBinderAtom);
+ }
+ const DefinedAtom* helper = new X86_64StubHelperAtom(_file,
+ *_helperCommonAtom);
+ _stubHelperAtoms.push_back(helper);
+ const DefinedAtom* lp = new X86_64LazyPointerAtom(_file, *helper, target);
+ assert(lp->contentType() == DefinedAtom::typeLazyPointer);
+ _lazyPointers.push_back(lp);
+ const DefinedAtom* stub = new X86_64StubAtom(_file, *lp);
+ assert(stub->contentType() == DefinedAtom::typeStub);
+ _targetToStub[&target] = stub;
+ return stub;
+ }
+
+ const DefinedAtom* makeStub_x86(const Atom& target) {
+ assert(0 && "stubs not yet implemented for x86");
+ return nullptr;
+ }
+
+ const DefinedAtom* makeStub_arm(const Atom& target) {
+ assert(0 && "stubs not yet implemented for arm");
+ return nullptr;
+ }
+
+
+ virtual void addStubAtoms(File &mergedFile) {
+ // Add all stubs to master file.
+ for (auto it : _targetToStub) {
+ mergedFile.addAtom(*it.second);
+ }
+ // Add helper code atoms.
+ mergedFile.addAtom(*_helperCommonAtom);
+ for (const DefinedAtom *lp : _stubHelperAtoms) {
+ mergedFile.addAtom(*lp);
+ }
+ // Add GOT slots used for lazy binding.
+ mergedFile.addAtom(*_helperBinderAtom);
+ mergedFile.addAtom(*_helperCacheAtom);
+ // Add all lazy pointers to master file.
+ for (const DefinedAtom *lp : _lazyPointers) {
+ mergedFile.addAtom(*lp);
+ }
+ // Add sharedlibrary atom
+ mergedFile.addAtom(*_binderAtom);
+ }
+
+private:
+
+ class File : public SimpleFile {
+ public:
+ File() : SimpleFile("MachO Stubs pass") {
+ }
+ };
+
+ const WriterOptionsMachO &_options;
+ File _file;
+ llvm::DenseMap<const Atom*, const DefinedAtom*> _targetToStub;
+ std::vector<const DefinedAtom*> _lazyPointers;
+ std::vector<const DefinedAtom*> _stubHelperAtoms;
+ const SharedLibraryAtom *_binderAtom;
+ const DefinedAtom* _helperCommonAtom;
+ const DefinedAtom* _helperCacheAtom;
+ const DefinedAtom* _helperBinderAtom;
+};
+
+
+} // namespace mach_o
+} // namespace lld
+
+
+#endif // LLD_READER_WRITER_MACHO_STUBS_PASS_H_
diff --git a/lld/lib/Platforms/Darwin/ExecutableWriter.cpp b/lld/lib/ReaderWriter/MachO/WriterMachO.cpp
index 42c62a55f76..3d91a8a5040 100644
--- a/lld/lib/Platforms/Darwin/ExecutableWriter.cpp
+++ b/lld/lib/ReaderWriter/MachO/WriterMachO.cpp
@@ -1,4 +1,4 @@
-//===- Platforms/Darwin/ExecutableWriter.cpp ------------------------------===//
+//===- lib/ReaderWriter/MachO/WriterMachO.cpp -----------------------------===//
//
// The LLVM Linker
//
@@ -7,33 +7,42 @@
//
//===----------------------------------------------------------------------===//
-#include "ExecutableWriter.h"
-#include "MachOFormat.hpp"
-#include "DarwinReferenceKinds.h"
-#include "DarwinPlatform.h"
-
-#include <vector>
-#include <map>
-
-#include <string.h>
+#include "lld/ReaderWriter/WriterMachO.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+//#include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallVector.h"
#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/SharedLibraryAtom.h"
#include "lld/Core/File.h"
+#include "lld/Core/InputFiles.h"
#include "lld/Core/Reference.h"
+#include "lld/Core/SharedLibraryAtom.h"
+
+#include <vector>
+#include <map>
+#include <string.h>
+
+#include "MachOFormat.hpp"
+#include "ReferenceKinds.h"
+#include "ExecutableAtoms.hpp"
+#include "GOTPass.hpp"
+#include "StubsPass.hpp"
namespace lld {
-namespace darwin {
+namespace mach_o {
//
// A mach-o file consists of some meta data (header and load commands),
@@ -66,8 +75,7 @@ class Chunk {
public:
virtual StringRef segmentName() const = 0;
virtual bool occupiesNoDiskSpace();
- virtual void write(raw_ostream &out) = 0;
- static void writeZeros(uint64_t amount, raw_ostream &out);
+ virtual void write(uint8_t *fileBuffer) = 0;
void assignFileOffset(uint64_t &curOff, uint64_t &curAddr);
virtual const char* info() = 0;
uint64_t size() const;
@@ -95,11 +103,11 @@ protected:
class SectionChunk : public Chunk {
public:
static SectionChunk* make(DefinedAtom::ContentType,
- DarwinPlatform &platform,
+ const WriterOptionsMachO &options,
class MachOWriter &writer);
virtual StringRef segmentName() const;
virtual bool occupiesNoDiskSpace();
- virtual void write(raw_ostream &out);
+ virtual void write(uint8_t *fileBuffer);
virtual const char* info();
StringRef sectionName();
uint32_t flags() const;
@@ -117,16 +125,20 @@ private:
SectionChunk(StringRef seg,
StringRef sect,
uint32_t flags,
- DarwinPlatform &platform,
+ const WriterOptionsMachO &options,
class MachOWriter &writer);
- StringRef _segmentName;
- StringRef _sectionName;
- DarwinPlatform &_platform;
- class MachOWriter &_writer;
- uint32_t _flags;
- uint32_t _permissions;
- std::vector<AtomInfo> _atoms;
+ void applyFixup(Reference::Kind kind, uint64_t addend,
+ uint8_t* location, uint64_t fixupAddress,
+ uint64_t targetAddress);
+
+ StringRef _segmentName;
+ StringRef _sectionName;
+ const WriterOptionsMachO &_options;
+ class MachOWriter &_writer;
+ uint32_t _flags;
+ uint32_t _permissions;
+ std::vector<AtomInfo> _atoms;
};
@@ -137,14 +149,17 @@ private:
//
class MachHeaderChunk : public Chunk {
public:
- MachHeaderChunk(DarwinPlatform &plat, const File &file);
+ MachHeaderChunk(const WriterOptionsMachO &options,
+ const File &file);
virtual StringRef segmentName() const;
- virtual void write(raw_ostream &out);
+ virtual void write(uint8_t *fileBuffer);
virtual const char* info();
void recordLoadCommand(load_command*);
uint64_t loadCommandsSize();
private:
+ uint32_t filetype(WriterOptionsMachO::OutputKind kind);
+
mach_header _mh;
};
@@ -158,10 +173,10 @@ private:
class LoadCommandsChunk : public Chunk {
public:
LoadCommandsChunk(MachHeaderChunk&,
- DarwinPlatform&,
+ const WriterOptionsMachO &options,
class MachOWriter&);
virtual StringRef segmentName() const;
- virtual void write(raw_ostream &out);
+ virtual void write(uint8_t *fileBuffer);
virtual const char* info();
void computeSize(const lld::File &file);
void addSection(SectionChunk*);
@@ -183,7 +198,7 @@ private:
};
MachHeaderChunk &_mh;
- DarwinPlatform &_platform;
+ const WriterOptionsMachO &_options;
class MachOWriter &_writer;
segment_command_64 *_linkEditSegment;
symtab_command *_symbolTableLoadCommand;
@@ -204,7 +219,7 @@ class LoadCommandPaddingChunk : public Chunk {
public:
LoadCommandPaddingChunk(LoadCommandsChunk&);
virtual StringRef segmentName() const;
- virtual void write(raw_ostream &out);
+ virtual void write(uint8_t *fileBuffer);
virtual const char* info();
void computeSize();
private:
@@ -234,7 +249,7 @@ public:
class DyldInfoChunk : public LinkEditChunk {
public:
DyldInfoChunk(class MachOWriter &);
- virtual void write(raw_ostream &out);
+ virtual void write(uint8_t *fileBuffer);
protected:
void append_byte(uint8_t);
@@ -283,7 +298,7 @@ private:
class SymbolTableChunk : public LinkEditChunk {
public:
SymbolTableChunk(class SymbolStringsChunk&);
- virtual void write(raw_ostream &out);
+ virtual void write(uint8_t *fileBuffer);
virtual void computeSize(const lld::File &file,
const std::vector<SectionChunk*>&);
virtual const char* info();
@@ -307,7 +322,7 @@ private:
class SymbolStringsChunk : public LinkEditChunk {
public:
SymbolStringsChunk();
- virtual void write(raw_ostream &out);
+ virtual void write(uint8_t *fileBuffer);
virtual void computeSize(const lld::File &file,
const std::vector<SectionChunk*>&);
virtual const char* info();
@@ -321,14 +336,16 @@ private:
//
// A MachOWriter manages all the Chunks that comprise a mach-o executable.
//
-class MachOWriter {
+class MachOWriter : public Writer {
public:
- MachOWriter(DarwinPlatform &platform);
- void build(const lld::File &file);
- void write(raw_ostream &out);
+ MachOWriter(const WriterOptionsMachO &options);
+
+ virtual error_code writeFile(const lld::File &file, StringRef path);
+ virtual StubsPass *stubPass();
+ virtual GOTPass *gotPass();
+ virtual void addFiles(InputFiles&);
uint64_t addressOfAtom(const Atom *atom);
- void zeroFill(int64_t amount, raw_ostream &out);
void findSegment(StringRef segmentName, uint32_t *segIndex,
uint64_t *segStartAddr, uint64_t *segEndAddr);
@@ -338,6 +355,7 @@ private:
friend class LoadCommandsChunk;
friend class LazyBindingInfoChunk;
+ void build(const lld::File &file);
void createChunks(const lld::File &file);
void buildAtomToAddressMap();
void assignFileOffsets();
@@ -349,7 +367,10 @@ private:
typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
- DarwinPlatform &_platform;
+ const WriterOptionsMachO &_options;
+ StubsPass _stubsPass;
+ GOTPass _gotPass;
+ CRuntimeFile _cRuntimeFile;
LoadCommandsChunk *_loadCommandsChunk;
LoadCommandPaddingChunk *_paddingChunk;
AtomToAddress _atomToAddress;
@@ -360,6 +381,7 @@ private:
LazyBindingInfoChunk *_lazyBindingInfo;
SymbolTableChunk *_symbolTableChunk;
SymbolStringsChunk *_stringsChunk;
+ const DefinedAtom *_mainAtom;
uint64_t _linkEditStartOffset;
uint64_t _linkEditStartAddress;
};
@@ -394,12 +416,6 @@ uint64_t Chunk::fileOffset() const {
return _fileOffset;
}
-
-void Chunk::writeZeros(uint64_t amount, raw_ostream &out) {
- for( int i=amount; i > 0; --i)
- out.write('\0');
-}
-
uint64_t Chunk::alignTo(uint64_t value, uint8_t align2) {
uint64_t align = 1 << align2;
return ( (value + (align-1)) & (-align) );
@@ -420,11 +436,13 @@ void Chunk::assignFileOffset(uint64_t &curOffset, uint64_t &curAddress) {
curOffset = _fileOffset + _size;
curAddress = _address + _size;
}
- DEBUG(llvm::dbgs() << " fileOffset=0x";
- llvm::dbgs().write_hex(_fileOffset);
- llvm::dbgs() << " address=0x";
- llvm::dbgs().write_hex(_address);
- llvm::dbgs() << " info=" << this->info() << "\n");
+
+ DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
+ << " fileOffset="
+ << llvm::format("0x%08X", _fileOffset)
+ << " address="
+ << llvm::format("0x%016X", _address)
+ << " info=" << this->info() << "\n");
}
@@ -434,46 +452,46 @@ void Chunk::assignFileOffset(uint64_t &curOffset, uint64_t &curAddress) {
//===----------------------------------------------------------------------===//
SectionChunk::SectionChunk(StringRef seg, StringRef sect,
- uint32_t flags, DarwinPlatform &platform,
+ uint32_t flags, const WriterOptionsMachO &options,
MachOWriter &writer)
- : _segmentName(seg), _sectionName(sect), _platform(platform),
+ : _segmentName(seg), _sectionName(sect), _options(options),
_writer(writer), _flags(flags), _permissions(0) {
}
SectionChunk* SectionChunk::make(DefinedAtom::ContentType type,
- DarwinPlatform &platform,
+ const WriterOptionsMachO &options,
MachOWriter &writer) {
switch ( type ) {
case DefinedAtom::typeCode:
return new SectionChunk("__TEXT", "__text",
S_REGULAR | S_ATTR_PURE_INSTRUCTIONS,
- platform, writer);
+ options, writer);
break;
case DefinedAtom::typeCString:
return new SectionChunk("__TEXT", "__cstring",
S_CSTRING_LITERALS,
- platform, writer);
+ options, writer);
break;
case DefinedAtom::typeStub:
return new SectionChunk("__TEXT", "__stubs",
S_SYMBOL_STUBS | S_ATTR_PURE_INSTRUCTIONS,
- platform, writer);
+ options, writer);
break;
case DefinedAtom::typeStubHelper:
return new SectionChunk("__TEXT", "__stub_helper",
S_REGULAR | S_ATTR_PURE_INSTRUCTIONS,
- platform, writer);
+ options, writer);
break;
case DefinedAtom::typeLazyPointer:
return new SectionChunk("__DATA", "__la_symbol_ptr",
S_LAZY_SYMBOL_POINTERS,
- platform, writer);
+ options, writer);
break;
case DefinedAtom::typeGOT:
return new SectionChunk("__DATA", "__got",
S_NON_LAZY_SYMBOL_POINTERS,
- platform, writer);
+ options, writer);
break;
default:
assert(0 && "TO DO: add support for more sections");
@@ -542,46 +560,67 @@ void SectionChunk::appendAtom(const DefinedAtom *atom) {
}
-void SectionChunk::write(raw_ostream &out) {
- assert( out.tell() == _fileOffset);
- SmallVector<uint8_t, 1024> buffer;
+void SectionChunk::write(uint8_t *chunkBuffer) {
// Each section's content is just its atoms' content.
for (const AtomInfo &atomInfo : _atoms ) {
- uint64_t atomFileOffset = _fileOffset + atomInfo.offsetInSection;
- if ( atomFileOffset != out.tell() ) {
- // Need to add alignment padding before this atom starts.
- assert(atomFileOffset > out.tell());
- this->writeZeros(atomFileOffset - out.tell(), out);
- }
- // Copy raw content of atom.
+ // Copy raw content of atom to file buffer.
ArrayRef<uint8_t> content = atomInfo.atom->rawContent();
uint64_t contentSize = content.size();
- buffer.resize(contentSize);
if ( contentSize == 0 )
continue;
- ::memcpy(buffer.data(), content.data(), content.size());
+ uint8_t* atomContent = chunkBuffer + atomInfo.offsetInSection;
+ ::memcpy(atomContent, content.data(), contentSize);
+ // Apply fixups to file buffer
for (const Reference *ref : *atomInfo.atom) {
uint32_t offset = ref->offsetInAtom();
uint64_t targetAddress = 0;
if ( ref->target() != nullptr )
targetAddress = _writer.addressOfAtom(ref->target());
uint64_t fixupAddress = _writer.addressOfAtom(atomInfo.atom) + offset;
- _platform.applyFixup(ref->kind(), ref->addend(), &buffer[offset],
+ this->applyFixup(ref->kind(), ref->addend(), &atomContent[offset],
fixupAddress, targetAddress);
}
- for( uint8_t byte : buffer) {
- out.write(byte);
- }
}
}
+
+
+void SectionChunk::applyFixup(Reference::Kind kind, uint64_t addend,
+ uint8_t* location, uint64_t fixupAddress,
+ uint64_t targetAddress) {
+ //fprintf(stderr, "applyFixup(kind=%s, addend=0x%0llX, "
+ // "fixupAddress=0x%0llX, targetAddress=0x%0llX\n",
+ // kindToString(kind).data(), addend,
+ // fixupAddress, targetAddress);
+ if ( ReferenceKind::isRipRel32(kind) ) {
+ // compute rip relative value and update.
+ int32_t* loc32 = reinterpret_cast<int32_t*>(location);
+ *loc32 = (targetAddress - (fixupAddress+4)) + addend;
+ }
+ else if ( kind == ReferenceKind::x86_64_pointer64 ) {
+ uint64_t* loc64 = reinterpret_cast<uint64_t*>(location);
+ *loc64 = targetAddress + addend;
+ }
+}
+
+
+
//===----------------------------------------------------------------------===//
// MachHeaderChunk
//===----------------------------------------------------------------------===//
-MachHeaderChunk::MachHeaderChunk(DarwinPlatform &platform, const File &file) {
- // Let platform convert file info to mach-o cpu type and subtype.
- platform.initializeMachHeader(file, _mh);
+MachHeaderChunk::MachHeaderChunk(const WriterOptionsMachO &options,
+ const File &file) {
+ // Set up mach_header based on options
+ _mh.magic = MAGIC_64;
+ _mh.cputype = options.cpuType();
+ _mh.cpusubtype = options.cpuSubtype();
+ _mh.filetype = this->filetype(options.outputKind());
+ _mh.ncmds = 0;
+ _mh.sizeofcmds = 0;
+ _mh.flags = 0;
+ _mh.reserved = 0;
+
_size = _mh.size();
}
@@ -590,9 +629,8 @@ StringRef MachHeaderChunk::segmentName() const {
return StringRef("__TEXT");
}
-void MachHeaderChunk::write(raw_ostream &out) {
- assert( out.tell() == _fileOffset);
- _mh.write(out);
+void MachHeaderChunk::write(uint8_t *chunkBuffer) {
+ _mh.copyTo(chunkBuffer);
}
const char* MachHeaderChunk::info() {
@@ -607,6 +645,20 @@ uint64_t MachHeaderChunk::loadCommandsSize() {
return _mh.sizeofcmds;
}
+uint32_t MachHeaderChunk::filetype(WriterOptionsMachO::OutputKind kind) {
+ switch ( kind ) {
+ case WriterOptionsMachO::outputDynamicExecutable:
+ return MH_EXECUTE;
+ case WriterOptionsMachO::outputDylib:
+ return MH_DYLIB;
+ case WriterOptionsMachO::outputBundle:
+ return MH_BUNDLE;
+ case WriterOptionsMachO::outputObjectFile:
+ return MH_OBJECT;
+ }
+ assert(0 && "file outputkind not supported");
+}
+
//===----------------------------------------------------------------------===//
@@ -614,9 +666,9 @@ uint64_t MachHeaderChunk::loadCommandsSize() {
//===----------------------------------------------------------------------===//
LoadCommandsChunk::LoadCommandsChunk(MachHeaderChunk &mh,
- DarwinPlatform& platform,
+ const WriterOptionsMachO &options,
MachOWriter& writer)
- : _mh(mh), _platform(platform), _writer(writer),
+ : _mh(mh), _options(options), _writer(writer),
_linkEditSegment(nullptr), _symbolTableLoadCommand(nullptr),
_entryPointLoadCommand(nullptr), _dyldInfoLoadCommand(nullptr) {
}
@@ -626,10 +678,12 @@ StringRef LoadCommandsChunk::segmentName() const {
return StringRef("__TEXT");
}
-void LoadCommandsChunk::write(raw_ostream &out) {
- assert( out.tell() == _fileOffset);
+void LoadCommandsChunk::write(uint8_t *chunkBuffer) {
+ uint8_t* p = chunkBuffer;
for ( load_command* lc : _loadCmds ) {
- lc->write(out);
+ assert( ((uintptr_t)p & 0x3) == 0);
+ lc->copyTo(p);
+ p += lc->cmdsize;
}
}
@@ -660,7 +714,7 @@ uint32_t LoadCommandsChunk::permissionsFromSections(
void LoadCommandsChunk::computeSize(const lld::File &file) {
// Main executables have a __PAGEZERO segment.
- uint64_t pageZeroSize = _platform.pageZeroSize();
+ uint64_t pageZeroSize = _options.pageZeroSize();
if ( pageZeroSize != 0 ) {
segment_command_64* pzSegCmd = segment_command_64::make(0);
strcpy(pzSegCmd->segname, "__PAGEZERO");
@@ -741,10 +795,12 @@ void LoadCommandsChunk::computeSize(const lld::File &file) {
_dyldInfoLoadCommand = dyld_info_command::make();
this->addLoadCommand(_dyldInfoLoadCommand);
- // Add entry point load command
- _entryPointLoadCommand = entry_point_command::make();
- this->addLoadCommand(_entryPointLoadCommand);
-
+ // Add entry point load command to main executables
+ if (_options.outputKind() == WriterOptionsMachO::outputDynamicExecutable) {
+ _entryPointLoadCommand = entry_point_command::make();
+ this->addLoadCommand(_entryPointLoadCommand);
+ }
+
// Compute total size.
_size = _mh.loadCommandsSize();
}
@@ -812,7 +868,7 @@ void LoadCommandsChunk::updateLoadCommandContent(const lld::File &file) {
// Update entry point
if ( _entryPointLoadCommand != nullptr ) {
- const Atom *mainAtom = _platform.mainAtom();
+ const Atom *mainAtom = _writer._mainAtom;
assert(mainAtom != nullptr);
uint32_t entryOffset = _writer.addressOfAtom(mainAtom) - _mh.address();
_entryPointLoadCommand->entryoff = entryOffset;
@@ -844,10 +900,8 @@ StringRef LoadCommandPaddingChunk::segmentName() const {
return StringRef("__TEXT");
}
-void LoadCommandPaddingChunk::write(raw_ostream &out) {
- assert( out.tell() == _fileOffset);
+void LoadCommandPaddingChunk::write(uint8_t *chunkBuffer) {
// Zero fill padding.
- this->writeZeros(_size, out);
}
const char* LoadCommandPaddingChunk::info() {
@@ -899,11 +953,8 @@ DyldInfoChunk::DyldInfoChunk(MachOWriter &writer)
: _writer(writer) {
}
-void DyldInfoChunk::write(raw_ostream &out) {
- assert( out.tell() == _fileOffset);
- for ( uint8_t byte : _bytes ) {
- out.write(byte);
- }
+void DyldInfoChunk::write(uint8_t *chunkBuffer) {
+ ::memcpy(chunkBuffer, &_bytes[0], _bytes.size());
}
void DyldInfoChunk::append_byte(uint8_t b) {
@@ -967,7 +1018,7 @@ void BindingInfoChunk::computeSize(const lld::File &file,
const SharedLibraryAtom *shlTarget
= dyn_cast<SharedLibraryAtom>(target);
if ( shlTarget != nullptr ) {
- assert(ref->kind() == ReferenceKind::pointer64);
+ assert(ref->kind() == ReferenceKind::x86_64_pointer64);
targetName = shlTarget->name();
ordinal = 1;
}
@@ -1029,12 +1080,12 @@ const char* LazyBindingInfoChunk::info() {
void LazyBindingInfoChunk::updateHelper(const DefinedAtom *lazyPointerAtom,
uint32_t offset) {
for (const Reference *ref : *lazyPointerAtom ) {
- if ( ref->kind() != ReferenceKind::pointer64 )
+ if ( ref->kind() != ReferenceKind::x86_64_pointer64 )
continue;
const DefinedAtom *helperAtom = dyn_cast<DefinedAtom>(ref->target());
assert(helperAtom != nullptr);
for (const Reference *href : *helperAtom ) {
- if ( href->kind() == ReferenceKind::lazyImm ) {
+ if ( href->kind() == ReferenceKind::x86_64_lazyImm ) {
(const_cast<Reference*>(href))->setAddend(offset);
return;
}
@@ -1084,7 +1135,7 @@ void LazyBindingInfoChunk::computeSize(const lld::File &file,
int flags = 0;
StringRef name;
for (const Reference *ref : *lazyPointerAtom ) {
- if ( ref->kind() == ReferenceKind::lazyTarget ) {
+ if ( ref->kind() == ReferenceKind::x86_64_lazyTarget ) {
const Atom *shlib = ref->target();
assert(shlib != nullptr);
name = shlib->name();
@@ -1111,16 +1162,19 @@ SymbolTableChunk::SymbolTableChunk(SymbolStringsChunk& str)
: _stringsChunk(str) {
}
-void SymbolTableChunk::write(raw_ostream &out) {
- assert( out.tell() == _fileOffset);
+void SymbolTableChunk::write(uint8_t *chunkBuffer) {
+ uint8_t *p = chunkBuffer;
for ( nlist_64 &sym : _globalDefinedsymbols ) {
- sym.write(out);
+ sym.copyTo(p);
+ p += sizeof(nlist_64);
}
for ( nlist_64 &sym : _localDefinedsymbols ) {
- sym.write(out);
+ sym.copyTo(p);
+ p += sizeof(nlist_64);
}
for ( nlist_64 &sym : _undefinedsymbols ) {
- sym.write(out);
+ sym.copyTo(p);
+ p += sizeof(nlist_64);
}
}
@@ -1196,11 +1250,8 @@ SymbolStringsChunk::SymbolStringsChunk() {
}
-void SymbolStringsChunk::write(raw_ostream &out) {
- assert( out.tell() == _fileOffset);
- for ( char c : _strings ) {
- out.write(c);
- }
+void SymbolStringsChunk::write(uint8_t *chunkBuffer) {
+ ::memcpy(chunkBuffer, &_strings[0], _strings.size());
}
const char* SymbolStringsChunk::info() {
@@ -1225,9 +1276,10 @@ uint32_t SymbolStringsChunk::stringIndex(StringRef str) {
// MachOWriter
//===----------------------------------------------------------------------===//
-MachOWriter::MachOWriter(DarwinPlatform &platform)
- : _platform(platform), _bindingInfo(nullptr), _lazyBindingInfo(nullptr),
- _symbolTableChunk(nullptr), _stringsChunk(nullptr),
+MachOWriter::MachOWriter(const WriterOptionsMachO &options)
+ : _options(options), _stubsPass(options), _cRuntimeFile(options),
+ _bindingInfo(nullptr), _lazyBindingInfo(nullptr),
+ _symbolTableChunk(nullptr), _stringsChunk(nullptr), _mainAtom(nullptr),
_linkEditStartOffset(0), _linkEditStartAddress(0) {
}
@@ -1266,7 +1318,7 @@ void MachOWriter::createChunks(const lld::File &file) {
DefinedAtom::ContentType type = atom->contentType();
auto pos = map.find(type);
if ( pos == map.end() ) {
- SectionChunk *chunk = SectionChunk::make(type, _platform, *this);
+ SectionChunk *chunk = SectionChunk::make(type, _options, *this);
map[type] = chunk;
chunk->appendAtom(atom);
}
@@ -1279,10 +1331,10 @@ void MachOWriter::createChunks(const lld::File &file) {
// Make chunks in __TEXT for mach_header and load commands at start.
- MachHeaderChunk *mhc = new MachHeaderChunk(_platform, file);
+ MachHeaderChunk *mhc = new MachHeaderChunk(_options, file);
_chunks.push_back(mhc);
- _loadCommandsChunk = new LoadCommandsChunk(*mhc, _platform, *this);
+ _loadCommandsChunk = new LoadCommandsChunk(*mhc, _options, *this);
_chunks.push_back(_loadCommandsChunk);
_paddingChunk = new LoadCommandPaddingChunk(*_loadCommandsChunk);
@@ -1313,19 +1365,28 @@ void MachOWriter::addLinkEditChunk(LinkEditChunk *chunk) {
void MachOWriter::buildAtomToAddressMap() {
- DEBUG(llvm::dbgs() << "assign atom addresses:\n");
+ DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
+ << "assign atom addresses:\n");
+ const bool lookForMain =
+ (_options.outputKind() == WriterOptionsMachO::outputDynamicExecutable);
for (SectionChunk *chunk : _sectionChunks ) {
for (const SectionChunk::AtomInfo &info : chunk->atoms() ) {
_atomToAddress[info.atom] = chunk->address() + info.offsetInSection;
- DEBUG(llvm::dbgs() << " address=0x";
- llvm::dbgs().write_hex(_atomToAddress[info.atom]);
- llvm::dbgs() << " atom=" << info.atom;
- llvm::dbgs() << " name=" << info.atom->name() << "\n");
+ if ( lookForMain
+ && (info.atom->contentType() == DefinedAtom::typeCode)
+ && (info.atom->size() != 0)
+ && info.atom->name().equals("_main") ) {
+ _mainAtom = info.atom;
+ }
+ DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
+ << " address="
+ << llvm::format("0x%016X", _atomToAddress[info.atom])
+ << " atom=" << info.atom
+ << " name=" << info.atom->name() << "\n");
}
}
}
-
//void MachOWriter::dump() {
// for ( Chunk *chunk : _chunks ) {
// fprintf(stderr, "size=0x%08llX, fileOffset=0x%08llX, address=0x%08llX %s\n",
@@ -1334,9 +1395,10 @@ void MachOWriter::buildAtomToAddressMap() {
//}
void MachOWriter::assignFileOffsets() {
- DEBUG(llvm::dbgs() << "assign file offsets:\n");
+ DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
+ << "assign file offsets:\n");
uint64_t offset = 0;
- uint64_t address = _platform.pageZeroSize();
+ uint64_t address = _options.pageZeroSize();
for ( Chunk *chunk : _chunks ) {
if ( chunk->segmentName().equals("__LINKEDIT") ) {
_linkEditStartOffset = Chunk::alignTo(offset, 12);
@@ -1348,7 +1410,8 @@ void MachOWriter::assignFileOffsets() {
}
void MachOWriter::assignLinkEditFileOffsets() {
- DEBUG(llvm::dbgs() << "assign LINKEDIT file offsets:\n");
+ DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
+ << "assign LINKEDIT file offsets:\n");
uint64_t offset = _linkEditStartOffset;
uint64_t address = _linkEditStartAddress;
for ( Chunk *chunk : _linkEditChunks ) {
@@ -1373,7 +1436,7 @@ void MachOWriter::findSegment(StringRef segmentName, uint32_t *segIndex,
const uint64_t kInvalidAddress = (uint64_t)(-1);
StringRef lastSegName("__TEXT");
*segIndex = 0;
- if ( _platform.pageZeroSize() != 0 ) {
+ if ( _options.pageZeroSize() != 0 ) {
*segIndex = 1;
}
*segStartAddr = kInvalidAddress;
@@ -1393,43 +1456,78 @@ void MachOWriter::findSegment(StringRef segmentName, uint32_t *segIndex,
*segEndAddr = chunkEndAddr;
}
}
-
}
}
-void MachOWriter::zeroFill(int64_t amount, raw_ostream &out) {
- for( int i=amount; i > 0; --i)
- out.write('\0');
+//
+// Creates a mach-o final linked image from the given atom graph and writes
+// it to the supplied output stream.
+//
+error_code MachOWriter::writeFile(const lld::File &file, StringRef path) {
+ this->build(file);
+
+// FIXME: re-enable when FileOutputBuffer is in LLVMSupport.a
+#if 0
+ uint64_t totalSize = _chunks.back()->fileOffset() + _chunks.back()->size();
+
+ OwningPtr<llvm::FileOutputBuffer> buffer;
+ error_code ec = llvm::FileOutputBuffer::create(path,
+ totalSize, buffer,
+ llvm::FileOutputBuffer::F_executable);
+ if ( ec )
+ return ec;
+
+ DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs() << "writeFile:\n");
+ for ( Chunk *chunk : _chunks ) {
+ DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
+ << " fileOffset="
+ << llvm::format("0x%08X", chunk->fileOffset())
+ << " chunk="
+ << chunk->info()
+ << "\n");
+ chunk->write(buffer->getBufferStart()+chunk->fileOffset());
+ }
+
+ return buffer->commit();
+#else
+ return error_code::success();
+#endif
}
-void MachOWriter::write(raw_ostream &out) {
- for ( Chunk *chunk : _chunks ) {
- if ( out.tell() != chunk->fileOffset() ) {
- // Assume just alignment padding to start of next section.
- assert( out.tell() < chunk->fileOffset() );
- uint64_t padding = chunk->fileOffset() - out.tell();
- chunk->writeZeros(padding, out);
- }
- chunk->write(out);
- }
+StubsPass *MachOWriter::stubPass() {
+ return &_stubsPass;
+}
+
+GOTPass *MachOWriter::gotPass() {
+ return &_gotPass;
}
+void MachOWriter::addFiles(InputFiles &inputFiles) {
+ inputFiles.prependFile(_cRuntimeFile);
+}
-//
-// Creates a mach-o final linked image from the given atom graph and writes
-// it to the supplied output stream.
-//
-void writeExecutable(const lld::File &file, DarwinPlatform &platform,
- raw_ostream &out) {
- MachOWriter writer(platform);
- writer.build(file);
- writer.write(out);
+
+} // namespace mach_o
+
+Writer* createWriterMachO(const WriterOptionsMachO &options) {
+ return new lld::mach_o::MachOWriter(options);
+}
+
+WriterOptionsMachO::WriterOptionsMachO()
+ : _outputkind(outputDynamicExecutable),
+ _archName("x86_64"),
+ _architecture(arch_x86_64),
+ _pageZeroSize(0x10000000),
+ _cpuType(mach_o::CPU_TYPE_X86_64),
+ _cpuSubtype(mach_o::CPU_SUBTYPE_X86_64_ALL),
+ _noTextRelocations(true) {
}
+WriterOptionsMachO::~WriterOptionsMachO() {
+}
-} // namespace darwin
} // namespace lld
diff --git a/lld/lib/ReaderWriter/Native/CMakeLists.txt b/lld/lib/ReaderWriter/Native/CMakeLists.txt
new file mode 100644
index 00000000000..8862750aea0
--- /dev/null
+++ b/lld/lib/ReaderWriter/Native/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_lld_library(lldNative
+ ReaderNative.cpp
+ WriterNative.cpp
+ )
diff --git a/lld/lib/Core/NativeFileFormat.h b/lld/lib/ReaderWriter/Native/NativeFileFormat.h
index f4e495246a5..43731f18a60 100644
--- a/lld/lib/Core/NativeFileFormat.h
+++ b/lld/lib/ReaderWriter/Native/NativeFileFormat.h
@@ -1,4 +1,4 @@
-//===- Core/NativeFileFormat.h - Describes native object file -------------===//
+//===- lib/ReaderWriter/Native/NativeFileFormat.h -------------------------===//
//
// The LLVM Linker
//
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLD_CORE_NATIVE_FILE_FORMAT_H_
-#define LLD_CORE_NATIVE_FILE_FORMAT_H_
+#ifndef LLD_READER_WRITER_NATIVE_FILE_FORMAT_H_
+#define LLD_READER_WRITER_NATIVE_FILE_FORMAT_H_
#include "llvm/Support/DataTypes.h"
@@ -240,4 +240,4 @@ struct NativeReferenceIvarsV2 {
} // namespace lld
-#endif // LLD_CORE_NATIVE_FILE_FORMAT_H_
+#endif // LLD_READER_WRITER_NATIVE_FILE_FORMAT_H_
diff --git a/lld/lib/Core/NativeReader.cpp b/lld/lib/ReaderWriter/Native/ReaderNative.cpp
index 29086148ebc..b617a4fb9ae 100644
--- a/lld/lib/Core/NativeReader.cpp
+++ b/lld/lib/ReaderWriter/Native/ReaderNative.cpp
@@ -1,4 +1,4 @@
-//===- Core/NativeReader.cpp - reads native object file ------------------===//
+//===- lib/ReaderWriter/Native/ReaderNative.cpp ---------------------------===//
//
// The LLVM Linker
//
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "NativeFileFormat.h"
+#include "lld/ReaderWriter/ReaderNative.h"
#include "lld/Core/Atom.h"
#include "lld/Core/Error.h"
@@ -16,16 +16,22 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "NativeFileFormat.h"
#include <vector>
#include <memory>
namespace lld {
+namespace native {
// forward reference
-class NativeFile;
+class File;
//
// An object of this class is instantied for each NativeDefinedAtomIvarsV1
@@ -33,11 +39,11 @@ class NativeFile;
//
class NativeDefinedAtomV1 : public DefinedAtom {
public:
- NativeDefinedAtomV1(const NativeFile& f,
+ NativeDefinedAtomV1(const File& f,
const NativeDefinedAtomIvarsV1* ivarData)
: _file(&f), _ivarData(ivarData) { }
- virtual const class File& file() const;
+ virtual const class lld::File& file() const;
virtual uint64_t ordinal() const;
@@ -103,8 +109,8 @@ public:
private:
const NativeAtomAttributesV1& attributes() const;
- const NativeFile* _file;
- const NativeDefinedAtomIvarsV1* _ivarData;
+ const File *_file;
+ const NativeDefinedAtomIvarsV1 *_ivarData;
};
@@ -115,11 +121,11 @@ private:
//
class NativeUndefinedAtomV1 : public UndefinedAtom {
public:
- NativeUndefinedAtomV1(const NativeFile& f,
+ NativeUndefinedAtomV1(const File& f,
const NativeUndefinedAtomIvarsV1* ivarData)
: _file(&f), _ivarData(ivarData) { }
- virtual const File& file() const;
+ virtual const lld::File& file() const;
virtual StringRef name() const;
virtual CanBeNull canBeNull() const {
@@ -128,8 +134,8 @@ public:
private:
- const NativeFile* _file;
- const NativeUndefinedAtomIvarsV1* _ivarData;
+ const File *_file;
+ const NativeUndefinedAtomIvarsV1 *_ivarData;
};
@@ -139,11 +145,11 @@ private:
//
class NativeSharedLibraryAtomV1 : public SharedLibraryAtom {
public:
- NativeSharedLibraryAtomV1(const NativeFile& f,
+ NativeSharedLibraryAtomV1(const File& f,
const NativeSharedLibraryAtomIvarsV1* ivarData)
: _file(&f), _ivarData(ivarData) { }
- virtual const File& file() const;
+ virtual const lld::File& file() const;
virtual StringRef name() const;
virtual StringRef loadName() const;
@@ -152,8 +158,8 @@ public:
}
private:
- const NativeFile* _file;
- const NativeSharedLibraryAtomIvarsV1* _ivarData;
+ const File *_file;
+ const NativeSharedLibraryAtomIvarsV1 *_ivarData;
};
@@ -163,11 +169,11 @@ private:
//
class NativeAbsoluteAtomV1 : public AbsoluteAtom {
public:
- NativeAbsoluteAtomV1(const NativeFile& f,
+ NativeAbsoluteAtomV1(const File& f,
const NativeAbsoluteAtomIvarsV1* ivarData)
: _file(&f), _ivarData(ivarData) { }
- virtual const File& file() const;
+ virtual const lld::File& file() const;
virtual StringRef name() const;
virtual uint64_t value() const {
@@ -175,8 +181,8 @@ public:
}
private:
- const NativeFile* _file;
- const NativeAbsoluteAtomIvarsV1* _ivarData;
+ const File *_file;
+ const NativeAbsoluteAtomIvarsV1 *_ivarData;
};
@@ -187,7 +193,7 @@ private:
//
class NativeReferenceV1 : public Reference {
public:
- NativeReferenceV1(const NativeFile& f,
+ NativeReferenceV1(const File& f,
const NativeReferenceIvarsV1* ivarData)
: _file(&f), _ivarData(ivarData) { }
@@ -216,8 +222,8 @@ private:
memcpy(niv, _ivarData, sizeof(NativeReferenceIvarsV1));
}
- const NativeFile* _file;
- const NativeReferenceIvarsV1* _ivarData;
+ const File *_file;
+ const NativeReferenceIvarsV1 *_ivarData;
};
@@ -225,14 +231,14 @@ private:
//
// lld::File object for native llvm object file
//
-class NativeFile : public File {
+class File : public lld::File {
public:
/// Instantiates a File object from a native object file. Ownership
/// of the MemoryBuffer is transfered to the resulting File object.
- static error_code make(std::unique_ptr<llvm::MemoryBuffer> mb,
+ static error_code make(std::unique_ptr<llvm::MemoryBuffer> &mb,
StringRef path,
- std::unique_ptr<File> &result) {
+ std::vector<std::unique_ptr<lld::File>> &result) {
const uint8_t* const base =
reinterpret_cast<const uint8_t*>(mb->getBufferStart());
const NativeFileHeader* const header =
@@ -248,8 +254,14 @@ public:
if ( header->fileSize > fileSize )
return make_error_code(native_reader_error::file_too_short);
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " Native File Header:"
+ << " fileSize=" << header->fileSize
+ << " chunkCount=" << header->chunkCount
+ << "\n");
+
// instantiate NativeFile object and add values to it as found
- std::unique_ptr<NativeFile> file(new NativeFile(std::move(mb), path));
+ std::unique_ptr<File> file(new File(std::move(mb), path));
// process each chunk
for(uint32_t i=0; i < header->chunkCount; ++i) {
@@ -298,14 +310,32 @@ public:
if ( ec ) {
return ec;
}
- // TO DO: validate enough chunks were used
+ }
+ // TO DO: validate enough chunks were used
+
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " ReaderNative DefinedAtoms:\n");
+ for (const DefinedAtom *a : file->defined() ) {
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << llvm::format(" 0x%09lX", a)
+ << ", name=" << a->name()
+ << ", size=" << a->size()
+ << "\n");
+ for (const Reference *r : *a ) {
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " offset="
+ << llvm::format("0x%03X", r->offsetInAtom())
+ << ", kind=" << r->kind()
+ << ", target=" << r->target()
+ << "\n");
+ }
}
- result.reset(file.release());
+ result.push_back(std::move(file));
return make_error_code(native_reader_error::success);
}
- virtual ~NativeFile() {
+ virtual ~File() {
// _buffer is automatically deleted because of OwningPtr<>
// All other ivar pointers are pointers into the MemoryBuffer, except
@@ -371,14 +401,26 @@ private:
this->_definedAtoms._arrayEnd = atomsEnd;
this->_definedAtoms._elementSize = atomSize;
this->_definedAtoms._elementCount = chunk->elementCount;
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " chunk DefinedAtomsV1: "
+ << " count=" << chunk->elementCount
+ << " chunkSize=" << chunk->fileSize
+ << "\n");
return make_error_code(native_reader_error::success);
}
+
+
// set up pointers to attributes array
error_code processAttributesV1(const uint8_t *base,
const NativeChunk *chunk) {
this->_attributes = base + chunk->fileOffset;
this->_attributesMaxOffset = chunk->fileSize;
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " chunk AttributesV1: "
+ << " count=" << chunk->elementCount
+ << " chunkSize=" << chunk->fileSize
+ << "\n");
return make_error_code(native_reader_error::success);
}
@@ -409,6 +451,11 @@ private:
this->_undefinedAtoms._arrayEnd = atomsEnd;
this->_undefinedAtoms._elementSize = atomSize;
this->_undefinedAtoms._elementCount = chunk->elementCount;
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " chunk UndefinedAtomsV1:"
+ << " count=" << chunk->elementCount
+ << " chunkSize=" << chunk->fileSize
+ << "\n");
return make_error_code(native_reader_error::success);
}
@@ -440,6 +487,11 @@ private:
this->_sharedLibraryAtoms._arrayEnd = atomsEnd;
this->_sharedLibraryAtoms._elementSize = atomSize;
this->_sharedLibraryAtoms._elementCount = chunk->elementCount;
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " chunk SharedLibraryAtomsV1:"
+ << " count=" << chunk->elementCount
+ << " chunkSize=" << chunk->fileSize
+ << "\n");
return make_error_code(native_reader_error::success);
}
@@ -471,6 +523,11 @@ private:
this->_absoluteAtoms._arrayEnd = atomsEnd;
this->_absoluteAtoms._elementSize = atomSize;
this->_absoluteAtoms._elementCount = chunk->elementCount;
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " chunk AbsoluteAtomsV1: "
+ << " count=" << chunk->elementCount
+ << " chunkSize=" << chunk->fileSize
+ << "\n");
return make_error_code(native_reader_error::success);
}
@@ -506,6 +563,11 @@ private:
this->_references.arrayEnd = refsEnd;
this->_references.elementSize = refSize;
this->_references.elementCount = chunk->elementCount;
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " chunk ReferencesV1: "
+ << " count=" << chunk->elementCount
+ << " chunkSize=" << chunk->fileSize
+ << "\n");
return make_error_code(native_reader_error::success);
}
@@ -550,6 +612,11 @@ private:
}
return make_error_code(native_reader_error::file_malformed);
}
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " chunk Targets Table: "
+ << " count=" << chunk->elementCount
+ << " chunkSize=" << chunk->fileSize
+ << "\n");
return make_error_code(native_reader_error::success);
}
@@ -560,6 +627,11 @@ private:
this->_addends = reinterpret_cast<const Reference::Addend*>
(base + chunk->fileOffset);
this->_addendsMaxIndex = chunk->elementCount;
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " chunk Addends: "
+ << " count=" << chunk->elementCount
+ << " chunkSize=" << chunk->fileSize
+ << "\n");
return make_error_code(native_reader_error::success);
}
@@ -568,6 +640,10 @@ private:
const NativeChunk *chunk) {
this->_strings = reinterpret_cast<const char*>(base + chunk->fileOffset);
this->_stringsMaxOffset = chunk->fileSize;
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " chunk Strings: "
+ << " chunkSize=" << chunk->fileSize
+ << "\n");
return make_error_code(native_reader_error::success);
}
@@ -576,6 +652,10 @@ private:
const NativeChunk *chunk) {
this->_contentStart = base + chunk->fileOffset;
this->_contentEnd = base + chunk->fileOffset + chunk->fileSize;
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " chunk content: "
+ << " chunkSize=" << chunk->fileSize
+ << "\n");
return make_error_code(native_reader_error::success);
}
@@ -624,9 +704,9 @@ private:
// private constructor, only called by make()
- NativeFile(std::unique_ptr<llvm::MemoryBuffer> mb, StringRef path) :
- File(path),
- _buffer(std::move(mb)), // NativeFile now takes ownership of buffer
+ File(std::unique_ptr<llvm::MemoryBuffer> mb, StringRef path) :
+ lld::File(path),
+ _buffer(std::move(mb)), // Reader now takes ownership of buffer
_header(nullptr),
_targetsTable(nullptr),
_targetsTableCount(0),
@@ -701,7 +781,7 @@ private:
};
-inline const class File& NativeDefinedAtomV1::file() const {
+inline const class lld::File& NativeDefinedAtomV1::file() const {
return *_file;
}
@@ -754,7 +834,7 @@ void NativeDefinedAtomV1::incrementIterator(const void*& it) const {
it = reinterpret_cast<const void*>(index);
}
-inline const class File& NativeUndefinedAtomV1::file() const {
+inline const class lld::File& NativeUndefinedAtomV1::file() const {
return *_file;
}
@@ -765,7 +845,7 @@ inline StringRef NativeUndefinedAtomV1::name() const {
-inline const class File& NativeSharedLibraryAtomV1::file() const {
+inline const class lld::File& NativeSharedLibraryAtomV1::file() const {
return *_file;
}
@@ -779,7 +859,7 @@ inline StringRef NativeSharedLibraryAtomV1::loadName() const {
-inline const class File& NativeAbsoluteAtomV1::file() const {
+inline const class lld::File& NativeAbsoluteAtomV1::file() const {
return *_file;
}
@@ -806,34 +886,44 @@ inline void NativeReferenceV1::setTarget(const Atom* newAtom) {
}
inline void NativeReferenceV1::setAddend(Addend a) {
+ // Do nothing if addend value is not being changed.
+ if ( this->addend() == a )
+ return;
assert(0 && "setAddend() not supported");
}
-//
-// Instantiate an lld::File from the given native object file buffer
-//
-error_code parseNativeObjectFile(std::unique_ptr<llvm::MemoryBuffer> mb,
- StringRef path,
- std::unique_ptr<File> &result) {
- return NativeFile::make(std::move(mb), path, result);
-}
+class Reader : public lld::Reader {
+public:
+ Reader(const ReaderOptionsNative &options) : _options(options) {
+ }
+
+ virtual error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
+ std::vector<std::unique_ptr<lld::File>> &result) {
+ return File::make(mb, mb->getBufferIdentifier(), result);
+ }
+private:
+ const ReaderOptionsNative &_options;
+};
-//
-// Instantiate an lld::File from the given native object file path
-//
-error_code parseNativeObjectFileOrSTDIN(StringRef path,
- std::unique_ptr<File>& result) {
- OwningPtr<llvm::MemoryBuffer> mb;
- error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, mb);
- if ( ec )
- return ec;
-
- return parseNativeObjectFile( std::unique_ptr<llvm::MemoryBuffer>(mb.take())
- , path
- , result);
+
+} // namespace native
+
+Reader* createReaderNative(const ReaderOptionsNative &options) {
+ return new lld::native::Reader(options);
+}
+
+ReaderOptionsNative::ReaderOptionsNative() {
}
+ReaderOptionsNative::~ReaderOptionsNative() {
+}
+
+
} // namespace lld
+
+
+
+
diff --git a/lld/lib/Core/NativeWriter.cpp b/lld/lib/ReaderWriter/Native/WriterNative.cpp
index 5c7fc05d03e..e3dc04351de 100644
--- a/lld/lib/Core/NativeWriter.cpp
+++ b/lld/lib/ReaderWriter/Native/WriterNative.cpp
@@ -1,4 +1,4 @@
-//===- Core/NativeWriter.cpp - Creates a native object file ---------------===//
+//===- lib/ReaderWriter/Native/WriterNative.cpp ---------------------------===//
//
// The LLVM Linker
//
@@ -7,26 +7,31 @@
//
//===----------------------------------------------------------------------===//
-#include "lld/Core/NativeWriter.h"
-#include "NativeFileFormat.h"
+#include "lld/ReaderWriter/WriterNative.h"
#include "lld/Core/File.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
+
+#include "NativeFileFormat.h"
#include <vector>
namespace lld {
-
+namespace native {
///
/// Class for writing native object files.
///
-class NativeWriter {
+class Writer : public lld::Writer {
public:
- /// construct writer for an lld::File object
- NativeWriter(const lld::File& file) : _file(file) {
+ Writer(const WriterOptionsNative &options) : _options(options) {
+ }
+
+ virtual error_code writeFile(const lld::File &file, StringRef outPath) {
// reserve first byte for unnamed atoms
_stringPool.push_back('\0');
// visit all atoms
@@ -43,12 +48,25 @@ public:
this->addIVarsForAbsoluteAtom(*absAtom);
}
-
-
// construct file header based on atom information accumulated
- makeHeader();
+ this->makeHeader();
+
+ std::string errorInfo;
+ llvm::raw_fd_ostream out(outPath.data(), errorInfo,
+ llvm::raw_fd_ostream::F_Binary);
+ if (!errorInfo.empty())
+ return error_code::success(); // FIXME
+
+ this->write(out);
+
+ return error_code::success();
+ }
+
+ virtual ~Writer() {
}
+private:
+
// write the lld::File in native format to the specified stream
void write(raw_ostream &out) {
assert( out.tell() == 0 );
@@ -113,8 +131,6 @@ public:
}
}
-private:
-
void addIVarsForDefinedAtom(const DefinedAtom& atom) {
_definedAtomIndex[&atom] = _definedAtomIvars.size();
NativeDefinedAtomIvarsV1 ivar;
@@ -426,7 +442,7 @@ private:
if ( pos != _targetsTableIndex.end() ) {
return pos->second;
}
- uint32_t result = _targetsTableIndex.size();
+ uint32_t result = _targetsTableIndex.size();
_targetsTableIndex[target] = result;
return result;
}
@@ -507,7 +523,7 @@ private:
typedef llvm::DenseMap<const Atom*, uint32_t> TargetToIndex;
typedef llvm::DenseMap<Reference::Addend, uint32_t> AddendToIndex;
- const lld::File& _file;
+ const WriterOptionsNative &_options;
NativeFileHeader* _headerBuffer;
size_t _headerBufferSize;
std::vector<char> _stringPool;
@@ -529,27 +545,19 @@ private:
};
+} // namespace native
+Writer* createWriterNative(const WriterOptionsNative &options) {
+ return new lld::native::Writer(options);
+}
-
-/// writeNativeObjectFile - writes the lld::File object in native object
-/// file format to the specified stream.
-int writeNativeObjectFile(const File &file, raw_ostream &out) {
- NativeWriter writer(file);
- writer.write(out);
- return 0;
+WriterOptionsNative::WriterOptionsNative() {
}
-/// writeNativeObjectFile - writes the lld::File object in native object
-/// file format to the specified file path.
-int writeNativeObjectFile(const File &file, StringRef path) {
- std::string errorInfo;
- llvm::raw_fd_ostream out( path.data()
- , errorInfo
- , llvm::raw_fd_ostream::F_Binary);
- if (!errorInfo.empty())
- return -1;
- return writeNativeObjectFile(file, out);
+WriterOptionsNative::~WriterOptionsNative() {
}
+
} // namespace lld
+
+
diff --git a/lld/lib/ReaderWriter/PECOFF/CMakeLists.txt b/lld/lib/ReaderWriter/PECOFF/CMakeLists.txt
new file mode 100644
index 00000000000..a08b5ec4bfb
--- /dev/null
+++ b/lld/lib/ReaderWriter/PECOFF/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_lld_library(lldPECOFF
+ ReaderCOFF.cpp
+ WriterPECOFF.cpp
+ )
diff --git a/lld/lib/Reader/COFFReader.cpp b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
index 3df6f73f2a9..a43c8380c28 100644
--- a/lld/lib/Reader/COFFReader.cpp
+++ b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
@@ -1,4 +1,4 @@
-//===- COFFReader.h - PECOFF Object File Reader ---------------------------===//
+//===- lib/ReaderWriter/PECOFF/ReaderCOFF.cpp -----------------------------===//
//
// The LLVM Linker
//
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "lld/Reader/Reader.h"
+#include "lld/ReaderWriter/ReaderPECOFF.h"
#include "lld/Core/File.h"
#include "llvm/ADT/ArrayRef.h"
@@ -199,9 +199,9 @@ private:
llvm::ArrayRef<uint8_t> Data;
};
-class COFFReader : public File {
+class FileCOFF : public File {
public:
- COFFReader(std::unique_ptr<llvm::MemoryBuffer> MB, llvm::error_code &EC)
+ FileCOFF(std::unique_ptr<llvm::MemoryBuffer> MB, llvm::error_code &EC)
: File(MB->getBufferIdentifier()) {
llvm::OwningPtr<llvm::object::Binary> Bin;
EC = llvm::object::createBinary(MB.release(), Bin);
@@ -331,15 +331,15 @@ public:
virtual const atom_collection<DefinedAtom> &defined() const {
return DefinedAtoms;
}
-
+
virtual const atom_collection<UndefinedAtom> &undefined() const {
return UndefinedAtoms;
}
-
+
virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
return SharedLibraryAtoms;
}
-
+
virtual const atom_collection<AbsoluteAtom> &absolute() const {
return AbsoluteAtoms;
}
@@ -353,12 +353,32 @@ private:
llvm::BumpPtrAllocator AtomStorage;
};
-llvm::error_code
-lld::parseCOFFObjectFile(std::unique_ptr<llvm::MemoryBuffer> MB,
- std::unique_ptr<File> &Result) {
- llvm::error_code EC;
- Result.reset(new COFFReader(std::move(MB), EC));
- if (EC)
- Result.release();
- return EC;
+
+
+class ReaderCOFF : public Reader {
+public:
+ ReaderCOFF(const ReaderOptionsPECOFF &options) : _options(options) {
+ }
+
+ error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
+ std::vector<std::unique_ptr<File>> &result) {
+ llvm::error_code ec;
+ std::unique_ptr<File> f(new FileCOFF(std::move(mb), ec));
+ if (ec) {
+ return ec;
+ }
+
+ result.push_back(std::move(f));
+ return error_code::success();
+ }
+private:
+ const ReaderOptionsPECOFF &_options;
+};
+
+
+
+Reader* createReaderPECOFF(const ReaderOptionsPECOFF &options) {
+ return new ReaderCOFF(options);
}
+
+
diff --git a/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp b/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
new file mode 100644
index 00000000000..8fec44e777b
--- /dev/null
+++ b/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
@@ -0,0 +1,35 @@
+//===- lib/ReaderWriter/PECOFF/WriterPECOFF.cpp ---------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/WriterPECOFF.h"
+
+#include "llvm/Support/Debug.h"
+
+
+namespace lld {
+namespace pe_coff {
+
+// define PE/COFF writer class here
+
+
+} // namespace pe_coff
+
+Writer* createWriterPECOFF(const WriterOptionsPECOFF &options) {
+ assert(0 && "PE/COFF support not implemented yet");
+ return nullptr;
+}
+
+WriterOptionsPECOFF::WriterOptionsPECOFF() {
+}
+
+WriterOptionsPECOFF::~WriterOptionsPECOFF() {
+}
+
+} // namespace lld
+
diff --git a/lld/lib/ReaderWriter/Reader.cpp b/lld/lib/ReaderWriter/Reader.cpp
new file mode 100644
index 00000000000..f4395e8ff38
--- /dev/null
+++ b/lld/lib/ReaderWriter/Reader.cpp
@@ -0,0 +1,42 @@
+//===- lib/ReaderWriter/Reader.cpp ----------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/Reader.h"
+
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/system_error.h"
+
+
+namespace lld {
+
+Reader::Reader() {
+}
+
+Reader::~Reader() {
+}
+
+error_code Reader::readFile(StringRef path,
+ std::vector<std::unique_ptr<File>> &result) {
+ OwningPtr<llvm::MemoryBuffer> opmb;
+ if ( error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, opmb) )
+ return ec;
+
+ std::unique_ptr<MemoryBuffer> mb(opmb.take());
+ return this->parseFile(std::move(mb), result);
+}
+
+
+
+ReaderOptions::ReaderOptions() {
+}
+
+} // namespace lld
+
diff --git a/lld/lib/Core/Platform.cpp b/lld/lib/ReaderWriter/Writer.cpp
index 430668d1200..93dbcf5f967 100644
--- a/lld/lib/Core/Platform.cpp
+++ b/lld/lib/ReaderWriter/Writer.cpp
@@ -1,4 +1,4 @@
-//===- Core/Platform.cpp - Base class ------------------------------------===//
+//===- lib/ReaderWriter/Writer.cpp ----------------------------------------===//
//
// The LLVM Linker
//
@@ -7,13 +7,19 @@
//
//===----------------------------------------------------------------------===//
-#include "lld/Core/Platform.h"
+#include "lld/ReaderWriter/Writer.h"
-namespace lld {
-Platform::Platform() {}
+namespace lld {
-Platform::~Platform() {}
+Writer::Writer() {
+}
+Writer::~Writer() {
+}
+WriterOptions::WriterOptions() {
}
+
+} // namespace lld
+
diff --git a/lld/lib/ReaderWriter/YAML/CMakeLists.txt b/lld/lib/ReaderWriter/YAML/CMakeLists.txt
new file mode 100644
index 00000000000..ecd07030cb4
--- /dev/null
+++ b/lld/lib/ReaderWriter/YAML/CMakeLists.txt
@@ -0,0 +1,5 @@
+add_lld_library(lldYAML
+ YamlKeyValues.cpp
+ ReaderYAML.cpp
+ WriterYAML.cpp
+ )
diff --git a/lld/lib/Core/YamlReader.cpp b/lld/lib/ReaderWriter/YAML/ReaderYAML.cpp
index 87f1e142355..8da77713698 100644
--- a/lld/lib/Core/YamlReader.cpp
+++ b/lld/lib/ReaderWriter/YAML/ReaderYAML.cpp
@@ -1,4 +1,4 @@
-//===- Core/YamlReader.cpp - Reads YAML encode object files ---------------===//
+//===- lib/ReaderWriter/YAML/ReaderYAML.cpp - Reads YAML object files -----===//
//
// The LLVM Linker
//
@@ -7,15 +7,14 @@
//
//===----------------------------------------------------------------------===//
-#include "lld/Core/YamlReader.h"
-#include "YamlKeyValues.h"
-#include "lld/Core/Atom.h"
+#include "lld/ReaderWriter/ReaderYAML.h"
+
#include "lld/Core/AbsoluteAtom.h"
+#include "lld/Core/ArchiveLibraryFile.h"
+#include "lld/Core/Atom.h"
#include "lld/Core/Error.h"
#include "lld/Core/File.h"
-#include "lld/Core/ArchiveLibraryFile.h"
#include "lld/Core/LLVM.h"
-#include "lld/Core/Platform.h"
#include "lld/Core/Reference.h"
#include "lld/Core/SharedLibraryAtom.h"
#include "lld/Core/UndefinedAtom.h"
@@ -26,17 +25,19 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/system_error.h"
#include "llvm/Support/YAMLParser.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/Debug.h"
#include <cstring>
#include <vector>
+#include "YamlKeyValues.h"
+
namespace lld {
namespace yaml {
@@ -536,7 +537,7 @@ const File *YAMLFile::find(StringRef name, bool dataSymbolOnly) const {
///
class YAMLState {
public:
- YAMLState(Platform &platform, llvm::yaml::Stream *s, YAMLFile *f);
+ YAMLState(const ReaderOptionsYAML &opts, llvm::yaml::Stream *s, YAMLFile *f);
void parse(llvm::yaml::Node *node, StringRef keyword,
llvm::yaml::Node *keywordNode=nullptr);
@@ -605,7 +606,7 @@ private:
static const Transistion _s_transistions[];
- Platform &_platform;
+ const ReaderOptionsYAML &_options;
error_code _error;
llvm::yaml::Stream *_stream;
YAMLFile *_file;
@@ -685,8 +686,9 @@ const YAMLState::Transistion YAMLState::_s_transistions[] = {
-YAMLState::YAMLState(Platform &platform, Stream *stream, YAMLFile *file)
- : _platform(platform)
+YAMLState::YAMLState(const ReaderOptionsYAML &opts, Stream *stream,
+ YAMLFile *file)
+ : _options(opts)
, _error(make_error_code(yaml_reader_error::success))
, _stream(stream)
, _file(file)
@@ -870,7 +872,7 @@ const char* YAMLState::stateName(State s) {
void YAMLState::moveToState(State newState) {
if ( newState == _state )
return;
- DEBUG(llvm::dbgs() << "moveToState(" << stateName(newState)
+ DEBUG_WITH_TYPE("objtxt", llvm::dbgs() << "moveToState(" << stateName(newState)
<< "), _state=" << stateName(_state) << "\n");
if ( newState == inArch ) {
@@ -896,7 +898,8 @@ void YAMLState::moveToState(State newState) {
void YAMLState::returnToState(State prevState, Node *node) {
if ( prevState == _state )
return;
- DEBUG(llvm::dbgs() << "returnToState(" << stateName(prevState)
+ DEBUG_WITH_TYPE("objtxt", llvm::dbgs()
+ << "returnToState(" << stateName(prevState)
<< "), _state=" << stateName(_state) << "\n");
// If done with an atom, instantiate an object for it.
if ( (_state == inAtom) && (prevState == inAtoms) )
@@ -913,9 +916,9 @@ void YAMLState::returnToState(State prevState, Node *node) {
StringRef YAMLState::extractString(ScalarNode *node) {
llvm::SmallString<32> storage;
StringRef str = node->getValue(storage);
- if ( str.data() == storage.begin() ) {
+ //if ( str.data() == storage.begin() ) {
str = _file->copyString(str);
- }
+ //}
return str;
}
@@ -1056,7 +1059,7 @@ void YAMLState::parseFixUpOffset(ScalarNode *node) {
void YAMLState::parseFixUpKind(ScalarNode *node) {
llvm::SmallString<32> storage;
- _ref._kind = _platform.kindFromString(node->getValue(storage));
+ _ref._kind = _options.kindFromString(node->getValue(storage));
_hasDefinedAtomAttributes = true;
}
@@ -1116,7 +1119,7 @@ void YAMLState::parseAtomValue(ScalarNode *node) {
//
void YAMLState::parse(Node *node, StringRef keyword, Node *keywordNode) {
using namespace llvm::yaml;
- DEBUG(llvm::dbgs() << "parse(" << keyword << "), _state="
+ DEBUG_WITH_TYPE("objtxt", llvm::dbgs() << "parse(" << keyword << "), _state="
<< stateName(_state) << "\n");
if ( _error )
return;
@@ -1196,17 +1199,17 @@ void YAMLState::parse(Node *node, StringRef keyword, Node *keywordNode) {
/// parseObjectText - Parse the specified YAML formatted MemoryBuffer
/// into lld::File object(s) and append each to the specified vector<File*>.
-error_code parseObjectText( llvm::MemoryBuffer *mb
- , Platform& platform
- , std::vector<std::unique_ptr<const File>> &result) {
+error_code parseFile(std::unique_ptr<MemoryBuffer> &mb,
+ const ReaderOptionsYAML &options,
+ std::vector<std::unique_ptr<File>> &result) {
llvm::SourceMgr srcMgr;
llvm::yaml::Stream stream(mb->getBuffer(), srcMgr);
for (llvm::yaml::Document &d : stream) {
- std::unique_ptr<YAMLFile> curFile(new YAMLFile);
+ std::unique_ptr<yaml::YAMLFile> curFile(new yaml::YAMLFile);
if (llvm::isa<llvm::yaml::NullNode>(d.getRoot()))
continue; // Empty files are allowed.
- YAMLState yamlState(platform, &stream, curFile.get());
+ yaml::YAMLState yamlState(options, &stream, curFile.get());
yamlState.parse(d.getRoot(), StringRef("<root>"));
if ( stream.failed() )
@@ -1225,19 +1228,37 @@ error_code parseObjectText( llvm::MemoryBuffer *mb
-//
-// Fill in vector<File*> from path to input text file.
-//
-error_code
-parseObjectTextFileOrSTDIN( StringRef path
- , Platform& platform
- , std::vector<std::unique_ptr<const File>>& result) {
- OwningPtr<llvm::MemoryBuffer> mb;
- if (error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, mb))
- return ec;
-
- return parseObjectText(mb.take(), platform, result);
+} // namespace yaml
+
+
+
+class ReaderYAML: public Reader {
+public:
+ ReaderYAML(const ReaderOptionsYAML &options) : _options(options) {
+ }
+
+ error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
+ std::vector<std::unique_ptr<File>> &result) {
+ return lld::yaml::parseFile(mb, _options, result);
+ }
+
+private:
+ const ReaderOptionsYAML &_options;
+};
+
+
+
+Reader* createReaderYAML(const ReaderOptionsYAML &options) {
+ return new ReaderYAML(options);
}
-} // namespace yaml
+ReaderOptionsYAML::ReaderOptionsYAML() {
+}
+
+ReaderOptionsYAML::~ReaderOptionsYAML() {
+}
+
+
+
+
} // namespace lld
diff --git a/lld/lib/Core/YamlWriter.cpp b/lld/lib/ReaderWriter/YAML/WriterYAML.cpp
index f3b348282b8..7b69f7822f4 100644
--- a/lld/lib/Core/YamlWriter.cpp
+++ b/lld/lib/ReaderWriter/YAML/WriterYAML.cpp
@@ -1,4 +1,4 @@
-//===- Core/YamlWriter.cpp - Writes YAML ----------------------------------===//
+//===- lib/ReaderWriter/YAML/WriterYAML.cpp - Writes YAML object files ----===//
//
// The LLVM Linker
//
@@ -7,11 +7,10 @@
//
//===----------------------------------------------------------------------===//
-#include "lld/Core/YamlWriter.h"
-#include "YamlKeyValues.h"
+#include "lld/ReaderWriter/WriterYAML.h"
+
#include "lld/Core/Atom.h"
#include "lld/Core/File.h"
-#include "lld/Core/Platform.h"
#include "lld/Core/Reference.h"
#include "llvm/ADT/ArrayRef.h"
@@ -25,12 +24,13 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
+#include "YamlKeyValues.h"
+
#include <vector>
namespace lld {
namespace yaml {
-namespace {
///
/// In most cases, atoms names are unambiguous, so references can just
/// use the atom name as the target (e.g. target: foo). But in a few
@@ -125,8 +125,9 @@ private:
///
class AtomWriter {
public:
- AtomWriter(const File& file, Platform& platform, RefNameBuilder& rnb)
- : _file(file), _platform(platform), _rnb(rnb), _firstAtom(true) { }
+ AtomWriter(const File& file, const WriterOptionsYAML &options,
+ RefNameBuilder& rnb)
+ : _file(file), _options(options), _rnb(rnb), _firstAtom(true) { }
void write(raw_ostream &out) {
@@ -295,7 +296,7 @@ public:
out << " "
<< "kind:"
<< spacePadding(strlen("kind"))
- << _platform.kindToString(ref->kind())
+ << _options.kindToString(ref->kind())
<< "\n";
const Atom* target = ref->target();
if (target != nullptr) {
@@ -436,28 +437,62 @@ private:
return 'A' + nibble - 0x0A;
}
- const File& _file;
- Platform& _platform;
- RefNameBuilder& _rnb;
- bool _firstAtom;
+ const File &_file;
+ const WriterOptionsYAML &_options;
+ RefNameBuilder &_rnb;
+ bool _firstAtom;
};
-} // anonymous namespace
-///
-/// writeObjectText - writes the lld::File object as in YAML
-/// format to the specified stream.
-///
-void writeObjectText(const File &file, Platform &platform, raw_ostream &out) {
- // Figure what ref-name labels are needed
- RefNameBuilder rnb(file);
+class Writer : public lld::Writer {
+public:
+ Writer(const WriterOptionsYAML &options) : _options(options) {
+ }
+
+ virtual error_code writeFile(const lld::File &file, StringRef path) {
+ // Create stream to path.
+ std::string errorInfo;
+ llvm::raw_fd_ostream out(path.data(), errorInfo);
+ if (!errorInfo.empty())
+ return llvm::make_error_code(llvm::errc::no_such_file_or_directory);
+
+ // Figure what ref-name labels are needed.
+ RefNameBuilder rnb(file);
+
+ // Write out all atoms.
+ AtomWriter writer(file, _options, rnb);
+ writer.write(out);
+ return error_code::success();
+ }
+
+ virtual StubsPass *stubPass() {
+ return _options.stubPass();
+ }
+
+ virtual GOTPass *gotPass() {
+ return _options.gotPass();
+ }
+
+
+private:
+ const WriterOptionsYAML &_options;
+};
- // Write out all atoms
- AtomWriter writer(file, platform, rnb);
- writer.write(out);
-}
} // namespace yaml
+
+
+Writer* createWriterYAML(const WriterOptionsYAML &options) {
+ return new lld::yaml::Writer(options);
+}
+
+WriterOptionsYAML::WriterOptionsYAML() {
+}
+
+WriterOptionsYAML::~WriterOptionsYAML() {
+}
+
+
} // namespace lld
diff --git a/lld/lib/Core/YamlKeyValues.cpp b/lld/lib/ReaderWriter/YAML/YamlKeyValues.cpp
index 3eab4e6d9c5..46120ad6716 100644
--- a/lld/lib/Core/YamlKeyValues.cpp
+++ b/lld/lib/ReaderWriter/YAML/YamlKeyValues.cpp
@@ -1,4 +1,4 @@
-//===- Core/YamlKeyValues.cpp - Reads YAML --------------------------------===//
+//===- lib/ReaderWriter/YAML/YamlKeyValues.cpp ----------------------------===//
//
// The LLVM Linker
//
diff --git a/lld/lib/Core/YamlKeyValues.h b/lld/lib/ReaderWriter/YAML/YamlKeyValues.h
index ecb3d2e239a..9f0e964cba5 100644
--- a/lld/lib/Core/YamlKeyValues.h
+++ b/lld/lib/ReaderWriter/YAML/YamlKeyValues.h
@@ -1,4 +1,4 @@
-//===- Core/YamlKeyValues.h - Reads YAML ----------------------------------===//
+//===- lib/ReaderWriter/YAML/YamlKeyValues.h ------------------------------===//
//
// The LLVM Linker
//
OpenPOWER on IntegriCloud