[llvm-commits] [lld] r156100 - in /lld/trunk: include/lld/Reader/ include/lld/Reader/Reader.h lib/CMakeLists.txt lib/Reader/ lib/Reader/CMakeLists.txt lib/Reader/COFFReader.cpp tools/lld-core/CMakeLists.txt tools/lld-core/lld-core.cpp
Michael J. Spencer
bigcheesegs at gmail.com
Thu May 3 13:52:23 PDT 2012
Author: mspencer
Date: Thu May 3 15:52:22 2012
New Revision: 156100
URL: http://llvm.org/viewvc/llvm-project?rev=156100&view=rev
Log:
Add COFF reader.
There are no tests for this yet because I still need to finish the
YAML -> COFF converter so we don't get binary files checked in.
Added:
lld/trunk/include/lld/Reader/
lld/trunk/include/lld/Reader/Reader.h
lld/trunk/lib/Reader/
lld/trunk/lib/Reader/CMakeLists.txt
lld/trunk/lib/Reader/COFFReader.cpp
Modified:
lld/trunk/lib/CMakeLists.txt
lld/trunk/tools/lld-core/CMakeLists.txt
lld/trunk/tools/lld-core/lld-core.cpp
Added: lld/trunk/include/lld/Reader/Reader.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Reader/Reader.h?rev=156100&view=auto
==============================================================================
--- lld/trunk/include/lld/Reader/Reader.h (added)
+++ lld/trunk/include/lld/Reader/Reader.h Thu May 3 15:52:22 2012
@@ -0,0 +1,29 @@
+//===- Reader.h - Create object file readers ------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_READER_H_
+#define LLD_READER_READER_H_
+
+#include "llvm/ADT/OwningPtr.h"
+
+#include <memory>
+
+namespace llvm {
+ class error_code;
+ class MemoryBuffer;
+}
+
+namespace lld {
+ class File;
+
+ llvm::error_code parseCOFFObjectFile(std::unique_ptr<llvm::MemoryBuffer> MB,
+ std::unique_ptr<File> &Result);
+}
+
+#endif
Modified: lld/trunk/lib/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/CMakeLists.txt?rev=156100&r1=156099&r2=156100&view=diff
==============================================================================
--- lld/trunk/lib/CMakeLists.txt (original)
+++ lld/trunk/lib/CMakeLists.txt Thu May 3 15:52:22 2012
@@ -1,3 +1,4 @@
add_subdirectory(Core)
add_subdirectory(Passes)
add_subdirectory(Platforms)
+add_subdirectory(Reader)
Added: lld/trunk/lib/Reader/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Reader/CMakeLists.txt?rev=156100&view=auto
==============================================================================
--- lld/trunk/lib/Reader/CMakeLists.txt (added)
+++ lld/trunk/lib/Reader/CMakeLists.txt Thu May 3 15:52:22 2012
@@ -0,0 +1,3 @@
+add_lld_library(lldReader
+ COFFReader.cpp
+ )
Added: lld/trunk/lib/Reader/COFFReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Reader/COFFReader.cpp?rev=156100&view=auto
==============================================================================
--- lld/trunk/lib/Reader/COFFReader.cpp (added)
+++ lld/trunk/lib/Reader/COFFReader.cpp Thu May 3 15:52:22 2012
@@ -0,0 +1,366 @@
+//===- COFFReader.h - PECOFF Object File Reader ---------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/Reader/Reader.h"
+#include "lld/Core/File.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Object/COFF.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>
+
+using namespace lld;
+using llvm::object::coff_symbol;
+
+class COFFAbsoluteAtom : public AbsoluteAtom {
+public:
+ COFFAbsoluteAtom(const File &F, llvm::StringRef N, uint64_t V)
+ : OwningFile(F)
+ , Name(N)
+ , Value(V)
+ {}
+
+ virtual const class File& file() const {
+ return OwningFile;
+ }
+
+ virtual llvm::StringRef name() const {
+ return Name;
+ }
+
+ virtual uint64_t value() const {
+ return Value;
+ }
+
+private:
+ const File &OwningFile;
+ llvm::StringRef Name;
+ uint64_t Value;
+};
+
+class COFFUndefinedAtom : public UndefinedAtom {
+public:
+ COFFUndefinedAtom(const File &F, llvm::StringRef N)
+ : OwningFile(F)
+ , Name(N)
+ {}
+
+ virtual const class File& file() const {
+ return OwningFile;
+ }
+
+ virtual llvm::StringRef name() const {
+ return Name;
+ }
+
+ virtual CanBeNull canBeNull() const {
+ return CanBeNull::canBeNullNever;
+ }
+
+private:
+ const File &OwningFile;
+ llvm::StringRef Name;
+};
+
+class COFFDefinedAtom : public DefinedAtom {
+public:
+ COFFDefinedAtom( const File &F
+ , llvm::StringRef N
+ , const llvm::object::coff_symbol *Symb
+ , const llvm::object::coff_section *Sec
+ , llvm::ArrayRef<uint8_t> D)
+ : OwningFile(F)
+ , Name(N)
+ , Symbol(Symb)
+ , Section(Sec)
+ , Data(D)
+ {}
+
+ virtual const class File& file() const {
+ return OwningFile;
+ }
+
+ virtual llvm::StringRef name() const {
+ return Name;
+ }
+
+ virtual uint64_t ordinal() const {
+ return reinterpret_cast<intptr_t>(Symbol);
+ }
+
+ virtual uint64_t size() const {
+ return Data.size();
+ }
+
+ virtual Scope scope() const {
+ if (!Symbol)
+ return scopeTranslationUnit;
+ switch (Symbol->StorageClass) {
+ case llvm::COFF::IMAGE_SYM_CLASS_EXTERNAL:
+ return scopeGlobal;
+ case llvm::COFF::IMAGE_SYM_CLASS_STATIC:
+ return scopeTranslationUnit;
+ }
+ llvm_unreachable("Unknown scope!");
+ }
+
+ virtual Interposable interposable() const {
+ return interposeNo;
+ }
+
+ virtual Merge merge() const {
+ return mergeNo;
+ }
+
+ virtual ContentType contentType() const {
+ if (Section->Characteristics & llvm::COFF::IMAGE_SCN_CNT_CODE)
+ return typeCode;
+ if (Section->Characteristics & llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
+ return typeData;
+ if (Section->Characteristics & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
+ return typeZeroFill;
+ return typeUnknown;
+ }
+
+ virtual Alignment alignment() const {
+ return Alignment(1);
+ }
+
+ virtual SectionChoice sectionChoice() const {
+ return sectionBasedOnContent;
+ }
+
+ virtual llvm::StringRef customSectionName() const {
+ return "";
+ }
+
+ virtual DeadStripKind deadStrip() const {
+ return deadStripNormal;
+ }
+
+ virtual ContentPermissions permissions() const {
+ if ( Section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_READ
+ && Section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_WRITE)
+ return permRW_;
+ if ( Section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_READ
+ && Section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_EXECUTE)
+ return permR_X;
+ if (Section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_READ)
+ return permR__;
+ return perm___;
+ }
+
+ virtual bool isThumb() const {
+ return false;
+ }
+
+ virtual bool isAlias() const {
+ return false;
+ }
+
+ virtual llvm::ArrayRef<uint8_t> rawContent() const {
+ return Data;
+ }
+
+ virtual reference_iterator begin() const {
+ return reference_iterator(*this, nullptr);
+ }
+
+ virtual reference_iterator end() const {
+ return reference_iterator(*this, nullptr);
+ }
+
+private:
+ virtual const Reference* derefIterator(const void* iter) const {
+ return nullptr;
+ }
+
+ virtual void incrementIterator(const void*& iter) const {
+
+ }
+
+ const File &OwningFile;
+ llvm::StringRef Name;
+ const llvm::object::coff_symbol *Symbol;
+ const llvm::object::coff_section *Section;
+ llvm::ArrayRef<uint8_t> Data;
+};
+
+class COFFReader : public File {
+public:
+ COFFReader(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);
+ if (EC)
+ return;
+
+ Obj.reset(llvm::dyn_cast<const llvm::object::COFFObjectFile>(Bin.get()));
+ if (Obj)
+ Bin.take();
+ else {
+ EC = make_error_code(llvm::object::object_error::invalid_file_type);
+ return;
+ }
+
+ const llvm::object::coff_file_header *Header = nullptr;
+ if ((EC = Obj->getHeader(Header)))
+ return;
+
+ // Assign each symbol to the section it's in. If it does not belong to a
+ // section, create an atom for it now.
+ std::map< const llvm::object::coff_section*
+ , std::vector<const llvm::object::coff_symbol*>> SectionSymbols;
+
+ for (uint32_t i = 0, e = Header->NumberOfSymbols; i != e; ++i) {
+ const llvm::object::coff_symbol *Symb;
+ if ((EC = Obj->getSymbol(i, Symb)))
+ return;
+ llvm::StringRef Name;
+ if ((EC = Obj->getSymbolName(Symb, Name)))
+ return;
+ int16_t SectionIndex = Symb->SectionNumber;
+ assert(SectionIndex != llvm::COFF::IMAGE_SYM_DEBUG &&
+ "Cannot atomize IMAGE_SYM_DEBUG!");
+ if (SectionIndex == llvm::COFF::IMAGE_SYM_ABSOLUTE) {
+ // Create an absolute atom.
+ AbsoluteAtoms._atoms.push_back(
+ new (AtomStorage.Allocate<COFFAbsoluteAtom>())
+ COFFAbsoluteAtom(*this, Name, Symb->Value));
+ } else if (SectionIndex == llvm::COFF::IMAGE_SYM_UNDEFINED) {
+ // Create an undefined atom.
+ UndefinedAtoms._atoms.push_back(
+ new (AtomStorage.Allocate<COFFUndefinedAtom>())
+ COFFUndefinedAtom(*this, Name));
+ } else {
+ // This is actually a defined symbol. Add it to its section's list of
+ // symbols.
+ uint8_t SC = Symb->StorageClass;
+ // If Symb->Value actually means section offset.
+ if ( SC == llvm::COFF::IMAGE_SYM_CLASS_EXTERNAL
+ || SC == llvm::COFF::IMAGE_SYM_CLASS_STATIC
+ || SC == llvm::COFF::IMAGE_SYM_CLASS_FUNCTION) {
+ const llvm::object::coff_section *Sec;
+ if ((EC = Obj->getSection(SectionIndex, Sec)))
+ return;
+ assert(Sec && "SectionIndex > 0, Sec must be non-null!");
+ SectionSymbols[Sec].push_back(Symb);
+ } else {
+ llvm::errs() << "Unable to create atom for: " << Name << "\n";
+ EC = llvm::object::object_error::parse_failed;
+ return;
+ }
+ }
+ // Skip aux symbols.
+ i += Symb->NumberOfAuxSymbols;
+ }
+
+ // For each section, sort its symbols by address, then create a defined atom
+ // for each range.
+ for (auto i = SectionSymbols.begin(), e = SectionSymbols.end();
+ i != e; ++i) {
+ auto &Symbs = i->second;
+ // Sort symbols by position.
+ std::stable_sort(Symbs.begin(), Symbs.end(),
+ // For some reason MSVC fails to allow the lambda in this context with a
+ // "illegal use of local type in type instantiation". MSVC is clearly
+ // wrong here. Force a conversion to function pointer to work around.
+ static_cast<bool(*)(const coff_symbol*, const coff_symbol*)>(
+ [](const coff_symbol *A, const coff_symbol *B) -> bool {
+ return A->Value < B->Value;
+ }));
+
+ if (Symbs.empty()) {
+ // Create an atom for the entire section.
+ llvm::ArrayRef<uint8_t> Data;
+ DefinedAtoms._atoms.push_back(
+ new (AtomStorage.Allocate<COFFDefinedAtom>())
+ COFFDefinedAtom(*this, "", nullptr, i->first, Data));
+ continue;
+ }
+
+ llvm::ArrayRef<uint8_t> SecData;
+ if ((EC = Obj->getSectionContents(i->first, SecData)))
+ return;
+
+ // Create an unnamed atom if the first atom isn't at the start of the
+ // section.
+ if (Symbs[0]->Value != 0) {
+ uint64_t Size = Symbs[0]->Value;
+ llvm::ArrayRef<uint8_t> Data(SecData.data(), Size);
+ DefinedAtoms._atoms.push_back(
+ new (AtomStorage.Allocate<COFFDefinedAtom>())
+ COFFDefinedAtom(*this, "", nullptr, i->first, Data));
+ }
+
+ for (auto si = Symbs.begin(), se = Symbs.end(); si != se; ++si) {
+ // if this is the last symbol, take up the remaining data.
+ llvm::ArrayRef<uint8_t> Data;
+ if (si + 1 == se) {
+ Data = llvm::ArrayRef<uint8_t>( SecData.data() + (*si)->Value
+ , SecData.end());
+ } else {
+ Data = llvm::ArrayRef<uint8_t>( SecData.data() + (*si)->Value
+ , (*(si + 1))->Value - (*si)->Value);
+ }
+ llvm::StringRef Name;
+ if ((EC = Obj->getSymbolName(*si, Name)))
+ return;
+ DefinedAtoms._atoms.push_back(
+ new (AtomStorage.Allocate<COFFDefinedAtom>())
+ COFFDefinedAtom(*this, Name, *si, i->first, Data));
+ }
+ }
+ }
+
+ virtual void addAtom(const Atom&) {
+ llvm_unreachable("cannot add atoms to native .obj files");
+ }
+
+ 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;
+ }
+
+private:
+ std::unique_ptr<const llvm::object::COFFObjectFile> Obj;
+ atom_collection_vector<DefinedAtom> DefinedAtoms;
+ atom_collection_vector<UndefinedAtom> UndefinedAtoms;
+ atom_collection_vector<SharedLibraryAtom> SharedLibraryAtoms;
+ atom_collection_vector<AbsoluteAtom> AbsoluteAtoms;
+ 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;
+}
Modified: lld/trunk/tools/lld-core/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/tools/lld-core/CMakeLists.txt?rev=156100&r1=156099&r2=156100&view=diff
==============================================================================
--- lld/trunk/tools/lld-core/CMakeLists.txt (original)
+++ lld/trunk/tools/lld-core/CMakeLists.txt Thu May 3 15:52:22 2012
@@ -1,11 +1,13 @@
set(LLVM_USED_LIBS
lldCore
+ lldReader
lldPasses
lldDarwinPlatform
)
set(LLVM_LINK_COMPONENTS
support
+ Object
)
add_lld_executable(lld-core
Modified: lld/trunk/tools/lld-core/lld-core.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/tools/lld-core/lld-core.cpp?rev=156100&r1=156099&r2=156100&view=diff
==============================================================================
--- lld/trunk/tools/lld-core/lld-core.cpp (original)
+++ lld/trunk/tools/lld-core/lld-core.cpp Thu May 3 15:52:22 2012
@@ -15,6 +15,7 @@
#include "lld/Core/Resolver.h"
#include "lld/Core/YamlReader.h"
#include "lld/Core/YamlWriter.h"
+#include "lld/Reader/Reader.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/CommandLine.h"
@@ -348,10 +349,9 @@
} // anon namespace
-llvm::cl::opt<std::string>
-cmdLineInputFilePath(llvm::cl::Positional,
- llvm::cl::desc("<input file>"),
- llvm::cl::init("-"));
+llvm::cl::list<std::string>
+cmdLineInputFilePaths(llvm::cl::Positional,
+ llvm::cl::desc("<input file>"));
llvm::cl::opt<std::string>
cmdLineOutputFilePath("o",
@@ -421,6 +421,9 @@
// parse options
llvm::cl::ParseCommandLineOptions(argc, argv);
+ if (cmdLineInputFilePaths.empty())
+ cmdLineInputFilePaths.emplace_back("-");
+
// create platform for testing
Platform* platform = nullptr;
switch ( platformSelected ) {
@@ -434,9 +437,23 @@
// read input YAML doc into object file(s)
std::vector<std::unique_ptr<const File>> files;
- if (error(yaml::parseObjectTextFileOrSTDIN(cmdLineInputFilePath,
- *platform, files))) {
- return 1;
+ for (auto path : cmdLineInputFilePaths) {
+ OwningPtr<llvm::MemoryBuffer> ofile;
+ if (error(llvm::MemoryBuffer::getFileOrSTDIN(path, ofile)))
+ return 1;
+ std::unique_ptr<llvm::MemoryBuffer> file(ofile.take());
+ if (llvm::sys::fs::identify_magic(file->getBuffer())
+ == llvm::sys::fs::file_magic::coff_object) {
+ std::unique_ptr<File> f;
+ if (error(parseCOFFObjectFile(std::move(file), f)))
+ return 1;
+ files.push_back(std::move(f));
+ } else {
+ if (error(yaml::parseObjectText( file.release()
+ , *platform
+ , files)))
+ return 1;
+ }
}
// create options for resolving
More information about the llvm-commits
mailing list