diff options
Diffstat (limited to 'lld/lib')
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 // |