summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
diff options
context:
space:
mode:
authorNick Kledzik <kledzik@apple.com>2013-12-19 21:58:00 +0000
committerNick Kledzik <kledzik@apple.com>2013-12-19 21:58:00 +0000
commite555277780fc1bfd3c1fccf6b6ab905cc89c993a (patch)
tree88b653613f4cbd836edb0d36dfb28187e917a729 /lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
parent61a57138c281ecc7ed40e9c9068b3fb5ee8c4b11 (diff)
downloadbcm5719-llvm-e555277780fc1bfd3c1fccf6b6ab905cc89c993a.tar.gz
bcm5719-llvm-e555277780fc1bfd3c1fccf6b6ab905cc89c993a.zip
[lld] Introduce registry and Reference kind tuple
The main changes are in: include/lld/Core/Reference.h include/lld/ReaderWriter/Reader.h Everything else is details to support the main change. 1) Registration based Readers Previously, lld had a tangled interdependency with all the Readers. It would have been impossible to make a streamlined linker (say for a JIT) which just supported one file format and one architecture (no yaml, no archives, etc). The old model also required a LinkingContext to read an object file, which would have made .o inspection tools awkward. The new model is that there is a global Registry object. You programmatically register the Readers you want with the registry object. Whenever you need to read/parse a file, you ask the registry to do it, and the registry tries each registered reader. For ease of use with the existing lld code base, there is one Registry object inside the LinkingContext object. 2) Changing kind value to be a tuple Beside Readers, the registry also keeps track of the mapping for Reference Kind values to and from strings. Along with that, this patch also fixes an ambiguity with the previous Reference::Kind values. The problem was that we wanted to reuse existing relocation type values as Reference::Kind values. But then how can the YAML write know how to convert a value to a string? The fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace (e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and a 16-bit value. This tuple system allows conversion to and from strings with no ambiguities. llvm-svn: 197727
Diffstat (limited to 'lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp')
-rw-r--r--lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp459
1 files changed, 242 insertions, 217 deletions
diff --git a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
index 95c1acf897a..bc5c7cc8f10 100644
--- a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
+++ b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
@@ -59,11 +59,13 @@ private:
typedef std::map<const coff_section *, SymbolVectorT> SectionToSymbolsT;
typedef std::map<const StringRef, Atom *> SymbolNameToAtomT;
typedef std::map<const coff_section *, vector<COFFDefinedFileAtom *> >
- SectionToAtomsT;
+ SectionToAtomsT;
public:
- FileCOFF(const PECOFFLinkingContext &context,
- std::unique_ptr<MemoryBuffer> mb, error_code &ec);
+ typedef const std::map<std::string, std::string> StringMap;
+
+ FileCOFF(std::unique_ptr<MemoryBuffer> mb, StringMap &altNames,
+ error_code &ec);
virtual const atom_collection<DefinedAtom> &defined() const {
return _definedAtoms;
@@ -81,11 +83,10 @@ public:
return _absoluteAtoms;
}
- virtual const LinkingContext &getLinkingContext() const { return _context; }
-
StringRef getLinkerDirectives() const { return _directives; }
private:
+
error_code readSymbolTable(vector<const coff_symbol *> &result);
void createAbsoluteAtoms(const SymbolVectorT &symbols,
@@ -95,16 +96,19 @@ private:
vector<const UndefinedAtom *> &result);
error_code createDefinedSymbols(const SymbolVectorT &symbols,
+ StringMap &altNames,
vector<const DefinedAtom *> &result);
error_code cacheSectionAttributes();
error_code
- AtomizeDefinedSymbolsInSection(const coff_section *section,
- vector<const coff_symbol *> &symbols,
- vector<COFFDefinedFileAtom *> &atoms);
+ AtomizeDefinedSymbolsInSection(const coff_section *section,
+ StringMap &altNames,
+ vector<const coff_symbol *> &symbols,
+ vector<COFFDefinedFileAtom *> &atoms);
error_code AtomizeDefinedSymbols(SectionToSymbolsT &definedSymbols,
+ StringMap &altNames,
vector<const DefinedAtom *> &definedAtoms);
error_code findAtomAt(const coff_section *section, uint32_t targetAddress,
@@ -153,10 +157,9 @@ private:
// the section.
std::map<const coff_section *,
std::map<uint32_t, std::vector<COFFDefinedAtom *> > >
- _definedAtomLocations;
+ _definedAtomLocations;
mutable llvm::BumpPtrAllocator _alloc;
- const PECOFFLinkingContext &_context;
uint64_t _ordinal;
};
@@ -173,34 +176,6 @@ private:
llvm::BumpPtrAllocator _alloc;
};
-class ReaderCOFF : public Reader {
-public:
- explicit ReaderCOFF(PECOFFLinkingContext &context)
- : Reader(context), _PECOFFLinkingContext(context) {}
-
- error_code parseFile(std::unique_ptr<MemoryBuffer> &mb,
- std::vector<std::unique_ptr<File> > &result) const;
-
-private:
- error_code handleDirectiveSection(StringRef directives) const;
-
- ErrorOr<std::string>
- writeResToTemporaryFile(std::unique_ptr<MemoryBuffer> mb) const;
-
- ErrorOr<std::string>
- convertResourceFileToCOFF(std::unique_ptr<MemoryBuffer> mb) const;
-
- error_code convertAndParseResourceFile(
- std::unique_ptr<MemoryBuffer> &mb,
- std::vector<std::unique_ptr<File> > &result) const;
-
- error_code parseCOFFFile(std::unique_ptr<MemoryBuffer> &mb,
- std::vector<std::unique_ptr<File> > &result) const;
-
- PECOFFLinkingContext &_PECOFFLinkingContext;
- mutable BumpPtrStringSaver _stringSaver;
-};
-
// Converts the COFF symbol attribute to the LLD's atom attribute.
Atom::Scope getScope(const coff_symbol *symbol) {
switch (symbol->StorageClass) {
@@ -278,10 +253,9 @@ DefinedAtom::Merge getMerge(const coff_aux_section_definition *auxsym) {
}
}
-FileCOFF::FileCOFF(const PECOFFLinkingContext &context,
- std::unique_ptr<MemoryBuffer> mb, error_code &ec)
- : File(mb->getBufferIdentifier(), kindObject), _context(context),
- _ordinal(0) {
+FileCOFF::FileCOFF(std::unique_ptr<MemoryBuffer> mb, StringMap &altNames,
+ error_code &ec)
+ : File(mb->getBufferIdentifier(), kindObject), _ordinal(0) {
OwningPtr<llvm::object::Binary> bin;
ec = llvm::object::createBinary(mb.release(), bin);
if (ec)
@@ -304,7 +278,7 @@ FileCOFF::FileCOFF(const PECOFFLinkingContext &context,
createAbsoluteAtoms(symbols, _absoluteAtoms._atoms);
if ((ec = createUndefinedAtoms(symbols, _undefinedAtoms._atoms)))
return;
- if ((ec = createDefinedSymbols(symbols, _definedAtoms._atoms)))
+ if ((ec = createDefinedSymbols(symbols, altNames, _definedAtoms._atoms)))
return;
if ((ec = addRelocationReferenceToAtoms()))
@@ -427,6 +401,7 @@ FileCOFF::createUndefinedAtoms(const SymbolVectorT &symbols,
/// the other two, because in order to create the atom for the defined symbol
/// we need to know the adjacent symbols.
error_code FileCOFF::createDefinedSymbols(const SymbolVectorT &symbols,
+ StringMap &altNames,
vector<const DefinedAtom *> &result) {
// A defined atom can be merged if its section attribute allows its contents
// to be merged. In COFF, it's not very easy to get the section attribute
@@ -499,7 +474,7 @@ error_code FileCOFF::createDefinedSymbols(const SymbolVectorT &symbols,
}
// Atomize the defined symbols.
- if (error_code ec = AtomizeDefinedSymbols(definedSymbols, result))
+ if (error_code ec = AtomizeDefinedSymbols(definedSymbols, altNames, result))
return ec;
return error_code::success();
@@ -552,17 +527,19 @@ error_code FileCOFF::cacheSectionAttributes() {
/// assumed to have been defined in the \p section.
error_code
FileCOFF::AtomizeDefinedSymbolsInSection(const coff_section *section,
+ StringMap &altNames,
vector<const coff_symbol *> &symbols,
vector<COFFDefinedFileAtom *> &atoms) {
- // Sort symbols by position.
+ // Sort symbols by position.
std::stable_sort(
symbols.begin(), symbols.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; }));
+ static_cast<bool(*)(const coff_symbol *, const coff_symbol *)>(
+ [](const coff_symbol * a, const coff_symbol * b)->bool {
+ return a->Value < b->Value;
+ }));
StringRef sectionName;
if (error_code ec = _obj->getSectionName(section, sectionName))
@@ -626,12 +603,10 @@ FileCOFF::AtomizeDefinedSymbolsInSection(const coff_section *section,
// if this is the last symbol, take up the remaining data.
const uint8_t *end = (si + 1 == se) ? secData.data() + secData.size()
: secData.data() + (*(si + 1))->Value;
- StringRef symbolName = _symbolName[*si];
- StringRef alias = _context.getAlternateName(symbolName);
-
- if (!alias.empty()) {
+ auto pos = altNames.find(_symbolName[*si]);
+ if (pos != altNames.end()) {
auto *atom = new (_alloc) COFFDefinedAtom(
- *this, alias, sectionName, getScope(*si), type, isComdat, perms,
+ *this, pos->second, sectionName, getScope(*si), type, isComdat, perms,
DefinedAtom::mergeAsWeak, ArrayRef<uint8_t>(), _ordinal++);
atoms.push_back(atom);
_symbolAtom[*si] = atom;
@@ -655,6 +630,7 @@ FileCOFF::AtomizeDefinedSymbolsInSection(const coff_section *section,
error_code
FileCOFF::AtomizeDefinedSymbols(SectionToSymbolsT &definedSymbols,
+ StringMap &altNames,
vector<const DefinedAtom *> &definedAtoms) {
// For each section, make atoms for all the symbols defined in the
// section, and append the atoms to the result objects.
@@ -662,7 +638,8 @@ FileCOFF::AtomizeDefinedSymbols(SectionToSymbolsT &definedSymbols,
const coff_section *section = i.first;
vector<const coff_symbol *> &symbols = i.second;
vector<COFFDefinedFileAtom *> atoms;
- if (error_code ec = AtomizeDefinedSymbolsInSection(section, symbols, atoms))
+ if (error_code ec =
+ AtomizeDefinedSymbolsInSection(section, altNames, symbols, atoms))
return ec;
// Connect atoms with layout-before/layout-after edges.
@@ -815,127 +792,6 @@ error_code FileCOFF::maybeReadLinkerDirectives() {
return error_code::success();
}
-error_code
-ReaderCOFF::parseFile(std::unique_ptr<MemoryBuffer> &mb,
- std::vector<std::unique_ptr<File> > &result) const {
- StringRef magic(mb->getBufferStart(), mb->getBufferSize());
-
- // The input file should be a resource file, an archive file, a regular COFF
- // file, or an import library member file. Try to parse in that order. If
- // the input file does not start with a known magic, parseCOFFImportLibrary
- // will return an error object.
- llvm::sys::fs::file_magic fileType = llvm::sys::fs::identify_magic(magic);
-
- if (fileType == llvm::sys::fs::file_magic::windows_resource)
- return convertAndParseResourceFile(mb, result);
- if (fileType == llvm::sys::fs::file_magic::coff_import_library)
- return lld::pecoff::parseCOFFImportLibrary(_context, mb, result);
- return parseCOFFFile(mb, result);
-}
-
-// Interpret the contents of .drectve section. If exists, the section contains
-// a string containing command line options. The linker is expected to
-// interpret the options as if they were given via the command line.
-//
-// The section mainly contains /defaultlib (-l in Unix), but can contain any
-// options as long as they are valid.
-error_code ReaderCOFF::handleDirectiveSection(StringRef directives) const {
- DEBUG(llvm::dbgs() << ".drectve: " << directives << "\n");
-
- // Split the string into tokens, as the shell would do for argv.
- SmallVector<const char *, 16> tokens;
- tokens.push_back("link"); // argv[0] is the command name. Will be ignored.
- llvm::cl::TokenizeWindowsCommandLine(directives, _stringSaver, tokens);
- tokens.push_back(nullptr);
-
- // Calls the command line parser to interpret the token string as if they
- // were given via the command line.
- int argc = tokens.size() - 1;
- const char **argv = &tokens[0];
- std::string errorMessage;
- llvm::raw_string_ostream stream(errorMessage);
- bool parseFailed = !WinLinkDriver::parse(argc, argv, _PECOFFLinkingContext,
- stream, /*isDirective*/ true);
- stream.flush();
-
- // Print error message if error.
- if (parseFailed) {
- llvm::errs() << "Failed to parse '" << directives << "'\n"
- << "Reason: " << errorMessage;
- return make_error_code(llvm::object::object_error::invalid_file_type);
- }
- if (!errorMessage.empty()) {
- llvm::errs() << "lld warning: " << errorMessage << "\n";
- }
- return error_code::success();
-}
-
-ErrorOr<std::string>
-ReaderCOFF::writeResToTemporaryFile(std::unique_ptr<MemoryBuffer> mb) const {
- // Get a temporary file path for .res file.
- SmallString<128> tempFilePath;
- if (error_code ec =
- llvm::sys::fs::createTemporaryFile("tmp", "res", tempFilePath))
- return ec;
-
- // Write the memory buffer contents to .res file, so that we can run
- // cvtres.exe on it.
- OwningPtr<llvm::FileOutputBuffer> buffer;
- if (error_code ec = llvm::FileOutputBuffer::create(
- tempFilePath.str(), mb->getBufferSize(), buffer))
- return ec;
- memcpy(buffer->getBufferStart(), mb->getBufferStart(), mb->getBufferSize());
- if (error_code ec = buffer->commit())
- return ec;
-
- // Convert SmallString -> StringRef -> std::string.
- return tempFilePath.str().str();
-}
-
-ErrorOr<std::string>
-ReaderCOFF::convertResourceFileToCOFF(std::unique_ptr<MemoryBuffer> mb) const {
- // Write the resource file to a temporary file.
- ErrorOr<std::string> inFilePath = writeResToTemporaryFile(std::move(mb));
- if (!inFilePath)
- return error_code(inFilePath);
- llvm::FileRemover inFileRemover(*inFilePath);
-
- // Create an output file path.
- SmallString<128> outFilePath;
- if (error_code ec =
- llvm::sys::fs::createTemporaryFile("tmp", "obj", outFilePath))
- return ec;
- std::string outFileArg = ("/out:" + outFilePath).str();
-
- // Construct CVTRES.EXE command line and execute it.
- std::string program = "cvtres.exe";
- std::string programPath = llvm::sys::FindProgramByName(program);
- if (programPath.empty()) {
- llvm::errs() << "Unable to find " << program << " in PATH\n";
- return llvm::errc::broken_pipe;
- }
- std::vector<const char *> args;
- args.push_back(programPath.c_str());
- args.push_back("/machine:x86");
- args.push_back("/readonly");
- args.push_back("/nologo");
- args.push_back(outFileArg.c_str());
- args.push_back(inFilePath->c_str());
- args.push_back(nullptr);
-
- DEBUG({
- for (const char **p = &args[0]; *p; ++p)
- llvm::dbgs() << *p << " ";
- llvm::dbgs() << "\n";
- });
-
- if (llvm::sys::ExecuteAndWait(programPath.c_str(), &args[0]) != 0) {
- llvm::errs() << program << " failed\n";
- return llvm::errc::broken_pipe;
- }
- return outFilePath.str().str();
-}
-
// Convert .res file to .coff file and then parse it. Resource file is a file
// containing various types of data, such as icons, translation texts,
// etc. "cvtres.exe" command reads an RC file to create a COFF file which
@@ -943,57 +799,226 @@ ReaderCOFF::convertResourceFileToCOFF(std::unique_ptr<MemoryBuffer> mb) const {
//
// The linker is not capable to handle RC files directly. Instead, it runs
// cvtres.exe on RC files and then then link its outputs.
-error_code ReaderCOFF::convertAndParseResourceFile(
- std::unique_ptr<MemoryBuffer> &mb,
- std::vector<std::unique_ptr<File> > &result) const {
- // Convert an RC to a COFF
- ErrorOr<std::string> coffFilePath = convertResourceFileToCOFF(std::move(mb));
- if (!coffFilePath)
- return error_code(coffFilePath);
- llvm::FileRemover coffFileRemover(*coffFilePath);
-
- // Read and parse the COFF
- OwningPtr<MemoryBuffer> opmb;
- if (error_code ec = MemoryBuffer::getFile(*coffFilePath, opmb))
- return ec;
- std::unique_ptr<MemoryBuffer> newmb(opmb.take());
- return parseCOFFFile(newmb, result);
-}
+class ResourceFileReader : public Reader {
+public:
+ virtual bool canParse(file_magic magic, StringRef ext,
+ const MemoryBuffer &) const {
+ return (magic == llvm::sys::fs::file_magic::windows_resource);
+ }
-error_code
-ReaderCOFF::parseCOFFFile(std::unique_ptr<MemoryBuffer> &mb,
- std::vector<std::unique_ptr<File> > &result) const {
- // Parse the memory buffer as PECOFF file.
- error_code ec;
- std::unique_ptr<FileCOFF> file(
- new FileCOFF(_PECOFFLinkingContext, std::move(mb), ec));
- if (ec)
- return ec;
+ virtual error_code
+ parseFile(std::unique_ptr<MemoryBuffer> &mb, const class Registry &,
+ std::vector<std::unique_ptr<File> > &result) const {
+ // Convert RC file to COFF
+ ErrorOr<std::string> coffPath = convertResourceFileToCOFF(std::move(mb));
+ if (!coffPath)
+ return error_code(coffPath);
+ llvm::FileRemover coffFileRemover(*coffPath);
+
+ // Read and parse the COFF
+ OwningPtr<MemoryBuffer> opmb;
+ if (error_code ec = MemoryBuffer::getFile(*coffPath, opmb))
+ return ec;
+ std::unique_ptr<MemoryBuffer> newmb(opmb.take());
+ error_code ec;
+ FileCOFF::StringMap emptyMap;
+ std::unique_ptr<FileCOFF> file(
+ new FileCOFF(std::move(newmb), emptyMap, ec));
+ if (ec)
+ return ec;
+ result.push_back(std::move(file));
+ return error_code::success();
+ }
+
+private:
+ static ErrorOr<std::string>
+ writeResToTemporaryFile(std::unique_ptr<MemoryBuffer> mb) {
+ // Get a temporary file path for .res file.
+ SmallString<128> tempFilePath;
+ if (error_code ec =
+ llvm::sys::fs::createTemporaryFile("tmp", "res", tempFilePath))
+ return ec;
+
+ // Write the memory buffer contents to .res file, so that we can run
+ // cvtres.exe on it.
+ OwningPtr<llvm::FileOutputBuffer> buffer;
+ if (error_code ec = llvm::FileOutputBuffer::create(
+ tempFilePath.str(), mb->getBufferSize(), buffer))
+ return ec;
+ memcpy(buffer->getBufferStart(), mb->getBufferStart(), mb->getBufferSize());
+ if (error_code ec = buffer->commit())
+ return ec;
+
+ // Convert SmallString -> StringRef -> std::string.
+ return tempFilePath.str().str();
+ }
- DEBUG({
- llvm::dbgs() << "Defined atoms:\n";
- for (const auto &atom : file->defined()) {
- llvm::dbgs() << " " << atom->name() << "\n";
- for (const Reference *ref : *atom)
- llvm::dbgs() << " @" << ref->offsetInAtom() << " -> "
- << ref->target()->name() << "\n";
+ static ErrorOr<std::string>
+ convertResourceFileToCOFF(std::unique_ptr<MemoryBuffer> mb) {
+ // Write the resource file to a temporary file.
+ ErrorOr<std::string> inFilePath = writeResToTemporaryFile(std::move(mb));
+ if (!inFilePath)
+ return error_code(inFilePath);
+ llvm::FileRemover inFileRemover(*inFilePath);
+
+ // Create an output file path.
+ SmallString<128> outFilePath;
+ if (error_code ec =
+ llvm::sys::fs::createTemporaryFile("tmp", "obj", outFilePath))
+ return ec;
+ std::string outFileArg = ("/out:" + outFilePath).str();
+
+ // Construct CVTRES.EXE command line and execute it.
+ std::string program = "cvtres.exe";
+ std::string programPath = llvm::sys::FindProgramByName(program);
+ if (programPath.empty()) {
+ llvm::errs() << "Unable to find " << program << " in PATH\n";
+ return llvm::errc::broken_pipe;
+ }
+ std::vector<const char *> args;
+ args.push_back(programPath.c_str());
+ args.push_back("/machine:x86");
+ args.push_back("/readonly");
+ args.push_back("/nologo");
+ args.push_back(outFileArg.c_str());
+ args.push_back(inFilePath->c_str());
+ args.push_back(nullptr);
+
+ DEBUG({
+ for (const char **p = &args[0]; *p; ++p)
+ llvm::dbgs() << *p << " ";
+ llvm::dbgs() << "\n";
+ });
+
+ if (llvm::sys::ExecuteAndWait(programPath.c_str(), &args[0]) != 0) {
+ llvm::errs() << program << " failed\n";
+ return llvm::errc::broken_pipe;
}
- });
+ return outFilePath.str().str();
+ }
+};
+
+class COFFObjectReader : public Reader {
+public:
+ COFFObjectReader(PECOFFLinkingContext &ctx) : _context(ctx) {}
+
+ virtual bool canParse(file_magic magic, StringRef ext,
+ const MemoryBuffer &) const {
+ return (magic == llvm::sys::fs::file_magic::coff_object);
+ }
- // Interpret .drectve section if the section has contents.
- StringRef directives = file->getLinkerDirectives();
- if (!directives.empty())
- if (error_code ec = handleDirectiveSection(directives))
+ virtual error_code
+ parseFile(std::unique_ptr<MemoryBuffer> &mb, const Registry &registry,
+ std::vector<std::unique_ptr<File> > &result) const {
+ // Parse the memory buffer as PECOFF file.
+ error_code ec;
+ std::unique_ptr<FileCOFF> file(
+ new FileCOFF(std::move(mb), _context.alternateNames(), ec));
+ if (ec)
return ec;
- result.push_back(std::move(file));
- return error_code::success();
-}
+ // Interpret .drectve section if the section has contents.
+ StringRef directives = file->getLinkerDirectives();
+ if (!directives.empty())
+ if (error_code ec2 = handleDirectiveSection(registry, directives))
+ return ec2;
+
+ result.push_back(std::move(file));
+ return error_code::success();
+ }
+
+private:
+ // Interpret the contents of .drectve section. If exists, the section contains
+ // a string containing command line options. The linker is expected to
+ // interpret the options as if they were given via the command line.
+ //
+ // The section mainly contains /defaultlib (-l in Unix), but can contain any
+ // options as long as they are valid.
+ error_code handleDirectiveSection(const Registry &registry,
+ StringRef directives) const {
+ DEBUG(llvm::dbgs() << ".drectve: " << directives << "\n");
+
+ // Split the string into tokens, as the shell would do for argv.
+ SmallVector<const char *, 16> tokens;
+ tokens.push_back("link"); // argv[0] is the command name. Will be ignored.
+ llvm::cl::TokenizeWindowsCommandLine(directives, _stringSaver, tokens);
+ tokens.push_back(nullptr);
+
+ // Calls the command line parser to interpret the token string as if they
+ // were given via the command line.
+ int argc = tokens.size() - 1;
+ const char **argv = &tokens[0];
+ std::string errorMessage;
+ llvm::raw_string_ostream stream(errorMessage);
+ bool parseFailed = !WinLinkDriver::parse(argc, argv, _context, stream,
+ /*isDirective*/ true);
+ stream.flush();
+ // Print error message if error.
+ if (parseFailed) {
+ llvm::errs() << "Failed to parse '" << directives << "'\n"
+ << "Reason: " << errorMessage;
+ return make_error_code(llvm::object::object_error::invalid_file_type);
+ }
+ if (!errorMessage.empty()) {
+ llvm::errs() << "lld warning: " << errorMessage << "\n";
+ }
+ return error_code::success();
+ }
+
+ PECOFFLinkingContext &_context;
+ mutable BumpPtrStringSaver _stringSaver;
+};
+
+using namespace llvm::COFF;
+
+const Registry::KindStrings kindStringsI386[] = {
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_I386_ABSOLUTE),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_I386_DIR16),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_I386_REL16),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_I386_DIR32),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_I386_DIR32NB),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_I386_SEG12),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_I386_SECTION),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_I386_SECREL),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_I386_TOKEN),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_I386_SECREL7),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_I386_REL32), LLD_KIND_STRING_END
+};
+
+const Registry::KindStrings kindStringsAMD64[] = {
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_ABSOLUTE),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_ADDR64),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_ADDR32),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_ADDR32NB),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_REL32),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_REL32_1),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_REL32_2),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_REL32_3),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_REL32_4),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_REL32_5),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_SECTION),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_SECREL),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_SECREL7),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_TOKEN),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_SREL32),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_PAIR),
+ LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_SSPAN32), LLD_KIND_STRING_END
+};
} // end namespace anonymous
namespace lld {
-std::unique_ptr<Reader> createReaderPECOFF(PECOFFLinkingContext &context) {
- return std::unique_ptr<Reader>(new ReaderCOFF(context));
+
+void Registry::addSupportCOFFObjects(PECOFFLinkingContext &ctx) {
+ add(std::unique_ptr<Reader>(new COFFObjectReader(ctx)));
+ addKindTable(Reference::KindNamespace::COFF, Reference::KindArch::x86,
+ kindStringsI386);
+ addKindTable(Reference::KindNamespace::COFF, Reference::KindArch::x86_64,
+ kindStringsAMD64);
}
+
+void Registry::addSupportWindowsResourceFiles() {
+ add(std::unique_ptr<Reader>(new ResourceFileReader()));
+}
+
}
OpenPOWER on IntegriCloud