summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/include/lld/Core/File.h21
-rw-r--r--lld/include/lld/ReaderWriter/MachOLinkingContext.h1
-rw-r--r--lld/lib/ReaderWriter/ELF/AArch64/AArch64ELFFile.h5
-rw-r--r--lld/lib/ReaderWriter/ELF/DynamicFile.h92
-rw-r--r--lld/lib/ReaderWriter/ELF/ELFFile.h10
-rw-r--r--lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFFile.h5
-rw-r--r--lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.h9
-rw-r--r--lld/lib/ReaderWriter/ELF/PPC/PPCELFFile.h13
-rw-r--r--lld/lib/ReaderWriter/ELF/X86/X86ELFFile.h5
-rw-r--r--lld/lib/ReaderWriter/ELF/X86_64/X86_64ELFFile.h5
-rw-r--r--lld/lib/ReaderWriter/FileArchive.cpp33
-rw-r--r--lld/lib/ReaderWriter/MachO/File.h49
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFile.h10
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp47
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp55
-rw-r--r--lld/lib/ReaderWriter/Native/ReaderNative.cpp71
-rw-r--r--lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp331
-rw-r--r--lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp35
-rw-r--r--lld/lib/ReaderWriter/Reader.cpp14
-rw-r--r--lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp1
20 files changed, 443 insertions, 369 deletions
diff --git a/lld/include/lld/Core/File.h b/lld/include/lld/Core/File.h
index 9fedd69f823..321956b7147 100644
--- a/lld/include/lld/Core/File.h
+++ b/lld/include/lld/Core/File.h
@@ -16,6 +16,7 @@
#include "lld/Core/SharedLibraryAtom.h"
#include "lld/Core/UndefinedAtom.h"
#include "lld/Core/range.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/Support/ErrorHandling.h"
#include <functional>
#include <vector>
@@ -153,9 +154,26 @@ public:
/// all AbsoluteAtoms in this File.
virtual const atom_collection<AbsoluteAtom> &absolute() const = 0;
+ /// \brief Subclasses should override this method to parse the
+ /// memory buffer passed to this file's constructor.
+ virtual std::error_code doParse() { return std::error_code(); }
+
+ /// \brief If a file is parsed using a different method than doParse(),
+ /// one must use this method to set the last error status, so that
+ /// doParse will not be called twice. Only YAML reader uses this
+ /// (because YAML reader does not read blobs but structured data).
+ void setLastError(std::error_code err) { _lastError = err; }
+
+ std::error_code parse() {
+ if (!_lastError.hasValue())
+ _lastError = doParse();
+ return _lastError.getValue();
+ }
+
protected:
/// \brief only subclasses of File can be instantiated
- File(StringRef p, Kind kind) : _path(p), _kind(kind), _ordinal(UINT64_MAX) {}
+ File(StringRef p, Kind kind)
+ : _path(p), _kind(kind), _ordinal(UINT64_MAX) {}
/// \brief This is a convenience class for File subclasses which manage their
/// atoms as a simple std::vector<>.
@@ -211,6 +229,7 @@ protected:
static atom_collection_empty<UndefinedAtom> _noUndefinedAtoms;
static atom_collection_empty<SharedLibraryAtom> _noSharedLibraryAtoms;
static atom_collection_empty<AbsoluteAtom> _noAbsoluteAtoms;
+ llvm::Optional<std::error_code> _lastError;
mutable llvm::BumpPtrAllocator _allocator;
private:
diff --git a/lld/include/lld/ReaderWriter/MachOLinkingContext.h b/lld/include/lld/ReaderWriter/MachOLinkingContext.h
index ddc3af24657..ff248fe9614 100644
--- a/lld/include/lld/ReaderWriter/MachOLinkingContext.h
+++ b/lld/include/lld/ReaderWriter/MachOLinkingContext.h
@@ -26,6 +26,7 @@ namespace lld {
namespace mach_o {
class ArchHandler;
class MachODylibFile;
+class MachOFile;
}
class MachOLinkingContext : public LinkingContext {
diff --git a/lld/lib/ReaderWriter/ELF/AArch64/AArch64ELFFile.h b/lld/lib/ReaderWriter/ELF/AArch64/AArch64ELFFile.h
index 09da41d99e8..2f099dc9180 100644
--- a/lld/lib/ReaderWriter/ELF/AArch64/AArch64ELFFile.h
+++ b/lld/lib/ReaderWriter/ELF/AArch64/AArch64ELFFile.h
@@ -24,11 +24,8 @@ public:
static ErrorOr<std::unique_ptr<AArch64ELFFile>>
create(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings) {
- std::unique_ptr<AArch64ELFFile<ELFT>> file(
+ return std::unique_ptr<AArch64ELFFile<ELFT>>(
new AArch64ELFFile<ELFT>(std::move(mb), atomizeStrings));
- if (std::error_code ec = file->parse())
- return ec;
- return std::move(file);
}
};
diff --git a/lld/lib/ReaderWriter/ELF/DynamicFile.h b/lld/lib/ReaderWriter/ELF/DynamicFile.h
index 55b257e906e..73211c7d308 100644
--- a/lld/lib/ReaderWriter/ELF/DynamicFile.h
+++ b/lld/lib/ReaderWriter/ELF/DynamicFile.h
@@ -55,8 +55,51 @@ public:
*this, name, _soname, sym->second._symbol);
}
+ std::error_code doParse() override {
+ std::error_code ec;
+ _objFile.reset(
+ new llvm::object::ELFFile<ELFT>(_mb.release()->getBuffer(), ec));
+ if (ec)
+ return ec;
+
+ llvm::object::ELFFile<ELFT> &obj = *_objFile;
+
+ _soname = obj.getLoadName();
+ if (_soname.empty())
+ _soname = llvm::sys::path::filename(path());
+
+ // Create a map from names to dynamic symbol table entries.
+ // TODO: This should use the object file's build in hash table instead if
+ // it exists.
+ for (auto i = obj.begin_dynamic_symbols(), e = obj.end_dynamic_symbols();
+ i != e; ++i) {
+ auto name = obj.getSymbolName(i);
+ if ((ec = name.getError()))
+ return ec;
+
+ // TODO: Add absolute symbols
+ if (i->st_shndx == llvm::ELF::SHN_ABS)
+ continue;
+
+ if (i->st_shndx == llvm::ELF::SHN_UNDEF) {
+ if (!_useShlibUndefines)
+ continue;
+ // Create an undefined atom.
+ if (!name->empty()) {
+ auto *newAtom = new (_alloc) ELFUndefinedAtom<ELFT>(*this, *name, &*i);
+ _undefinedAtoms._atoms.push_back(newAtom);
+ }
+ continue;
+ }
+ _nameToSym[*name]._symbol = &*i;
+ }
+ return std::error_code();
+ }
+
private:
- DynamicFile(StringRef name) : SharedLibraryFile(name) {}
+ DynamicFile(std::unique_ptr<MemoryBuffer> mb, bool useShlibUndefines)
+ : SharedLibraryFile(mb->getBufferIdentifier()),
+ _mb(std::move(mb)), _useShlibUndefines(useShlibUndefines) {}
mutable llvm::BumpPtrAllocator _alloc;
std::unique_ptr<llvm::object::ELFFile<ELFT>> _objFile;
@@ -73,6 +116,8 @@ private:
const SharedLibraryAtom *_atom;
};
+ std::unique_ptr<MemoryBuffer> _mb;
+ bool _useShlibUndefines;
mutable std::unordered_map<StringRef, SymAtomPair> _nameToSym;
};
@@ -80,49 +125,8 @@ template <class ELFT>
ErrorOr<std::unique_ptr<DynamicFile<ELFT>>>
DynamicFile<ELFT>::create(std::unique_ptr<llvm::MemoryBuffer> mb,
bool useShlibUndefines) {
- std::unique_ptr<DynamicFile> file(new DynamicFile(mb->getBufferIdentifier()));
-
- std::error_code ec;
- file->_objFile.reset(
- new llvm::object::ELFFile<ELFT>(mb.release()->getBuffer(), ec));
-
- if (ec)
- return ec;
-
- llvm::object::ELFFile<ELFT> &obj = *file->_objFile;
-
- file->_soname = obj.getLoadName();
- if (file->_soname.empty())
- file->_soname = llvm::sys::path::filename(file->path());
-
- // Create a map from names to dynamic symbol table entries.
- // TODO: This should use the object file's build in hash table instead if
- // it exists.
- for (auto i = obj.begin_dynamic_symbols(), e = obj.end_dynamic_symbols();
- i != e; ++i) {
- auto name = obj.getSymbolName(i);
- if ((ec = name.getError()))
- return ec;
-
- // TODO: Add absolute symbols
- if (i->st_shndx == llvm::ELF::SHN_ABS)
- continue;
-
- if (i->st_shndx == llvm::ELF::SHN_UNDEF) {
- if (!useShlibUndefines)
- continue;
- // Create an undefined atom.
- if (!name->empty()) {
- auto *newAtom =
- new (file->_alloc) ELFUndefinedAtom<ELFT>(*file.get(), *name, &*i);
- file->_undefinedAtoms._atoms.push_back(newAtom);
- }
- continue;
- }
- file->_nameToSym[*name]._symbol = &*i;
- }
-
- return std::move(file);
+ return std::unique_ptr<DynamicFile>(
+ new DynamicFile(std::move(mb), useShlibUndefines));
}
} // end namespace elf
diff --git a/lld/lib/ReaderWriter/ELF/ELFFile.h b/lld/lib/ReaderWriter/ELF/ELFFile.h
index b1fc8861943..8ca4c2de7f1 100644
--- a/lld/lib/ReaderWriter/ELF/ELFFile.h
+++ b/lld/lib/ReaderWriter/ELF/ELFFile.h
@@ -122,7 +122,7 @@ public:
: File(mb->getBufferIdentifier(), kindObject), _mb(std::move(mb)),
_ordinal(0), _doStringsMerge(atomizeStrings) {}
- virtual std::error_code parse();
+ virtual std::error_code doParse() override;
static ErrorOr<std::unique_ptr<ELFFile>>
create(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings);
@@ -417,19 +417,15 @@ public:
template <class ELFT>
ErrorOr<std::unique_ptr<ELFFile<ELFT>>>
ELFFile<ELFT>::create(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings) {
- std::error_code ec;
std::unique_ptr<ELFFile<ELFT>> file(
new ELFFile<ELFT>(std::move(mb), atomizeStrings));
- if (std::error_code ec = file->parse())
- return ec;
return std::move(file);
}
template <class ELFT>
-std::error_code ELFFile<ELFT>::parse() {
+std::error_code ELFFile<ELFT>::doParse() {
std::error_code ec;
- _objFile.reset(
- new llvm::object::ELFFile<ELFT>(_mb.release()->getBuffer(), ec));
+ _objFile.reset(new llvm::object::ELFFile<ELFT>(_mb.release()->getBuffer(), ec));
if (ec)
return ec;
diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFFile.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFFile.h
index e892a206297..03bfe7fddde 100644
--- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFFile.h
+++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFFile.h
@@ -119,11 +119,8 @@ public:
static ErrorOr<std::unique_ptr<HexagonELFFile>>
create(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings) {
- std::unique_ptr<HexagonELFFile<ELFT>> file(
+ return std::unique_ptr<HexagonELFFile<ELFT>>(
new HexagonELFFile<ELFT>(std::move(mb), atomizeStrings));
- if (std::error_code ec = file->parse())
- return ec;
- return std::move(file);
}
virtual bool isCommonSymbol(const Elf_Sym *symbol) const {
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.h b/lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.h
index 6526b0307ad..dd874f755fc 100644
--- a/lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.h
+++ b/lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.h
@@ -85,11 +85,8 @@ public:
static ErrorOr<std::unique_ptr<MipsELFFile>>
create(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings) {
- std::unique_ptr<MipsELFFile<ELFT>> file(
+ return std::unique_ptr<MipsELFFile<ELFT>>(
new MipsELFFile<ELFT>(std::move(mb), atomizeStrings));
- if (std::error_code ec = file->parse())
- return ec;
- return std::move(file);
}
bool isPIC() const {
@@ -103,8 +100,8 @@ public:
uint64_t getTPOffset() const { return *_tpOff; }
uint64_t getDTPOffset() const { return *_dtpOff; }
- std::error_code parse() override {
- if (std::error_code ec = ELFFile<ELFT>::parse())
+ std::error_code doParse() override {
+ if (std::error_code ec = ELFFile<ELFT>::doParse())
return ec;
// Retrieve some auxiliary data like GP value, TLS section address etc
// from the object file.
diff --git a/lld/lib/ReaderWriter/ELF/PPC/PPCELFFile.h b/lld/lib/ReaderWriter/ELF/PPC/PPCELFFile.h
index dd97b9a65e3..bbcd49eb9ae 100644
--- a/lld/lib/ReaderWriter/ELF/PPC/PPCELFFile.h
+++ b/lld/lib/ReaderWriter/ELF/PPC/PPCELFFile.h
@@ -19,11 +19,14 @@ class PPCLinkingContext;
template <class ELFT> class PPCELFFile : public ELFFile<ELFT> {
public:
- PPCELFFile(StringRef name) : ELFFile<ELFT>(name) {}
-
- PPCELFFile(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings,
- TargetHandlerBase *handler, std::error_code &ec)
- : ELFFile<ELFT>(std::move(mb), atomizeStrings, handler, ec) {}
+ PPCELFFile(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings)
+ : ELFFile<ELFT>(std::move(mb), atomizeStrings) {}
+
+ static ErrorOr<std::unique_ptr<PPCELFFile>>
+ create(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings) {
+ return std::unique_ptr<PPCELFFile<ELFT>>(
+ new PPCELFFile<ELFT>(std::move(mb), atomizeStrings));
+ }
};
template <class ELFT> class PPCDynamicFile : public DynamicFile<ELFT> {
diff --git a/lld/lib/ReaderWriter/ELF/X86/X86ELFFile.h b/lld/lib/ReaderWriter/ELF/X86/X86ELFFile.h
index 516e9a204ad..cee2509e796 100644
--- a/lld/lib/ReaderWriter/ELF/X86/X86ELFFile.h
+++ b/lld/lib/ReaderWriter/ELF/X86/X86ELFFile.h
@@ -24,11 +24,8 @@ public:
static ErrorOr<std::unique_ptr<X86ELFFile>>
create(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings) {
- std::unique_ptr<X86ELFFile<ELFT>> file(
+ return std::unique_ptr<X86ELFFile<ELFT>>(
new X86ELFFile<ELFT>(std::move(mb), atomizeStrings));
- if (std::error_code ec = file->parse())
- return ec;
- return std::move(file);
}
};
diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64ELFFile.h b/lld/lib/ReaderWriter/ELF/X86_64/X86_64ELFFile.h
index 24854e58046..bf1721c8ae3 100644
--- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64ELFFile.h
+++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64ELFFile.h
@@ -24,11 +24,8 @@ public:
static ErrorOr<std::unique_ptr<X86_64ELFFile>>
create(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings) {
- std::unique_ptr<X86_64ELFFile<ELFT>> file(
+ return std::unique_ptr<X86_64ELFFile<ELFT>>(
new X86_64ELFFile<ELFT>(std::move(mb), atomizeStrings));
- if (std::error_code ec = file->parse())
- return ec;
- return std::move(file);
}
};
diff --git a/lld/lib/ReaderWriter/FileArchive.cpp b/lld/lib/ReaderWriter/FileArchive.cpp
index a76399e57d0..20a9a1c0b88 100644
--- a/lld/lib/ReaderWriter/FileArchive.cpp
+++ b/lld/lib/ReaderWriter/FileArchive.cpp
@@ -33,12 +33,22 @@ namespace {
/// \brief The FileArchive class represents an Archive Library file
class FileArchive : public lld::ArchiveLibraryFile {
public:
- FileArchive(const Registry &registry, Archive *archive, StringRef path,
- bool isWholeArchive, bool logLoading)
- : ArchiveLibraryFile(path), _registry(registry),
- _archive(std::move(archive)), _isWholeArchive(isWholeArchive),
+ FileArchive(std::unique_ptr<MemoryBuffer> &mb, const Registry &reg,
+ StringRef path, bool logLoading)
+ : ArchiveLibraryFile(path), _mb(mb), _registry(reg),
_logLoading(logLoading) {}
+ std::error_code doParse() override {
+ // Make Archive object which will be owned by FileArchive object.
+ std::error_code ec;
+ _archive.reset(new Archive(_mb->getMemBufferRef(), ec));
+ if (ec)
+ return ec;
+ if ((ec = buildTableOfContents()))
+ return ec;
+ return std::error_code();
+ }
+
virtual ~FileArchive() {}
/// \brief Check if any member of the archive contains an Atom with the
@@ -204,6 +214,7 @@ private:
typedef std::unordered_map<StringRef, Archive::child_iterator> MemberMap;
typedef std::set<const char *> InstantiatedSet;
+ std::unique_ptr<MemoryBuffer> &_mb;
const Registry &_registry;
std::unique_ptr<Archive> _archive;
mutable MemberMap _symbolMemberMap;
@@ -229,20 +240,8 @@ public:
std::error_code
parseFile(std::unique_ptr<MemoryBuffer> &mb, const Registry &reg,
std::vector<std::unique_ptr<File>> &result) const override {
- MemoryBuffer &buff = *mb;
- // Make Archive object which will be owned by FileArchive object.
- std::error_code ec;
- Archive *archive = new Archive(mb->getMemBufferRef(), ec);
- if (ec)
- return ec;
- StringRef path = buff.getBufferIdentifier();
- // Construct FileArchive object.
std::unique_ptr<FileArchive> file(
- new FileArchive(reg, archive, path, false, _logLoading));
- ec = file->buildTableOfContents();
- if (ec)
- return ec;
-
+ new FileArchive(mb, reg, mb->getBufferIdentifier(), _logLoading));
result.push_back(std::move(file));
return std::error_code();
}
diff --git a/lld/lib/ReaderWriter/MachO/File.h b/lld/lib/ReaderWriter/MachO/File.h
index 9f3979b7863..8d9d4517b76 100644
--- a/lld/lib/ReaderWriter/MachO/File.h
+++ b/lld/lib/ReaderWriter/MachO/File.h
@@ -24,6 +24,9 @@ using lld::mach_o::normalized::Section;
class MachOFile : public SimpleFile {
public:
+ MachOFile(MemoryBuffer *mb, MachOLinkingContext *ctx)
+ : SimpleFile(mb->getBufferIdentifier()), _mb(mb), _ctx(ctx) {}
+
MachOFile(StringRef path) : SimpleFile(path) {}
void addDefinedAtom(StringRef name, Atom::Scope scope,
@@ -172,6 +175,19 @@ public:
visitor(offAndAtom.atom, offAndAtom.offset);
}
+ std::error_code doParse() override {
+ // Convert binary file to normalized mach-o.
+ std::unique_ptr<MemoryBuffer>mb(_mb);
+ auto normFile = normalized::readBinary(mb, _ctx->arch());
+ mb.release();
+ if (std::error_code ec = normFile.getError())
+ return ec;
+ // Convert normalized mach-o to atoms.
+ if (std::error_code ec = normalized::normalizedObjectToAtoms(
+ this, **normFile, false))
+ return ec;
+ return std::error_code();
+ }
private:
struct SectionOffsetAndAtom { uint64_t offset; MachODefinedAtom *atom; };
@@ -190,17 +206,18 @@ private:
std::vector<SectionOffsetAndAtom>> SectionToAtoms;
typedef llvm::StringMap<const lld::Atom *> NameToAtom;
+ MemoryBuffer *_mb;
+ MachOLinkingContext *_ctx;
SectionToAtoms _sectionAtoms;
NameToAtom _undefAtoms;
};
class MachODylibFile : public SharedLibraryFile {
public:
- MachODylibFile(StringRef path, StringRef installName, uint32_t compatVersion,
- uint32_t currentVersion)
- : SharedLibraryFile(path), _installName(installName),
- _currentVersion(currentVersion), _compatVersion(compatVersion) {
- }
+ MachODylibFile(MemoryBuffer *mb, MachOLinkingContext *ctx)
+ : SharedLibraryFile(mb->getBufferIdentifier()), _mb(mb), _ctx(ctx) {}
+
+ MachODylibFile(StringRef path) : SharedLibraryFile(path) {}
const SharedLibraryAtom *exports(StringRef name, bool isData) const override {
// Pass down _installName so that if this requested symbol
@@ -241,11 +258,13 @@ public:
}
StringRef installName() { return _installName; }
-
uint32_t currentVersion() { return _currentVersion; }
-
uint32_t compatVersion() { return _compatVersion; }
+ void setInstallName(StringRef name) { _installName = name; }
+ void setCompatVersion(uint32_t version) { _compatVersion = version; }
+ void setCurrentVersion(uint32_t version) { _currentVersion = version; }
+
typedef std::function<MachODylibFile *(StringRef)> FindDylib;
void loadReExportedDylibs(FindDylib find) {
@@ -254,6 +273,20 @@ public:
}
}
+ std::error_code doParse() override {
+ // Convert binary file to normalized mach-o.
+ std::unique_ptr<MemoryBuffer>mb(_mb);
+ auto normFile = normalized::readBinary(mb, _ctx->arch());
+ mb.release();
+ if (std::error_code ec = normFile.getError())
+ return ec;
+ // Convert normalized mach-o to atoms.
+ if (std::error_code ec = normalized::normalizedDylibToAtoms(
+ this, **normFile, false))
+ return ec;
+ return std::error_code();
+ }
+
private:
const SharedLibraryAtom *exports(StringRef name,
StringRef installName) const {
@@ -295,6 +328,8 @@ private:
bool weakDef;
};
+ MemoryBuffer *_mb;
+ MachOLinkingContext *_ctx;
StringRef _installName;
uint32_t _currentVersion;
uint32_t _compatVersion;
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h b/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h
index 64b8231eb2b..70bcde2dea2 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h
@@ -285,6 +285,16 @@ readYaml(std::unique_ptr<MemoryBuffer> &mb);
/// Writes a yaml encoded mach-o files given an in-memory normalized view.
std::error_code writeYaml(const NormalizedFile &file, raw_ostream &out);
+std::error_code
+normalizedObjectToAtoms(MachOFile *file,
+ const NormalizedFile &normalizedFile,
+ bool copyRefs);
+
+std::error_code
+normalizedDylibToAtoms(MachODylibFile *file,
+ const NormalizedFile &normalizedFile,
+ bool copyRefs);
+
/// Takes in-memory normalized dylib or object and parses it into lld::File
ErrorOr<std::unique_ptr<lld::File>>
normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path,
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
index a05fa750326..0b3f76c19cb 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
@@ -505,16 +505,14 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb,
return std::move(f);
}
-class MachOReader : public Reader {
+class MachOObjectReader : public Reader {
public:
- MachOReader(MachOLinkingContext &ctx) : _ctx(ctx) {}
+ MachOObjectReader(MachOLinkingContext &ctx) : _ctx(ctx) {}
bool canParse(file_magic magic, StringRef ext,
const MemoryBuffer &mb) const override {
switch (magic) {
case llvm::sys::fs::file_magic::macho_object:
- case llvm::sys::fs::file_magic::macho_dynamically_linked_shared_lib:
- case llvm::sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub:
return (mb.getBufferSize() > 32);
default:
return false;
@@ -524,30 +522,49 @@ public:
std::error_code
parseFile(std::unique_ptr<MemoryBuffer> &mb, const Registry &registry,
std::vector<std::unique_ptr<File>> &result) const override {
- // Convert binary file to normalized mach-o.
- auto normFile = readBinary(mb, _ctx.arch());
- if (std::error_code ec = normFile.getError())
- return ec;
- // Convert normalized mach-o to atoms.
- auto file = normalizedToAtoms(**normFile, mb->getBufferIdentifier(), false);
- if (std::error_code ec = file.getError())
- return ec;
+ auto *file = new MachOFile(mb.get(), &_ctx);
+ result.push_back(std::unique_ptr<MachOFile>(file));
+ return std::error_code();
+ }
- result.push_back(std::move(*file));
+private:
+ MachOLinkingContext &_ctx;
+};
+class MachODylibReader : public Reader {
+public:
+ MachODylibReader(MachOLinkingContext &ctx) : _ctx(ctx) {}
+
+ bool canParse(file_magic magic, StringRef ext,
+ const MemoryBuffer &mb) const override {
+ switch (magic) {
+ case llvm::sys::fs::file_magic::macho_dynamically_linked_shared_lib:
+ case llvm::sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub:
+ return (mb.getBufferSize() > 32);
+ default:
+ return false;
+ }
+ }
+
+ std::error_code
+ parseFile(std::unique_ptr<MemoryBuffer> &mb, const Registry &registry,
+ std::vector<std::unique_ptr<File>> &result) const override {
+ auto *file = new MachODylibFile(mb.get(), &_ctx);
+ result.push_back(std::unique_ptr<MachODylibFile>(file));
return std::error_code();
}
+
private:
MachOLinkingContext &_ctx;
};
-
} // namespace normalized
} // namespace mach_o
void Registry::addSupportMachOObjects(MachOLinkingContext &ctx) {
MachOLinkingContext::Arch arch = ctx.arch();
- add(std::unique_ptr<Reader>(new mach_o::normalized::MachOReader(ctx)));
+ add(std::unique_ptr<Reader>(new mach_o::normalized::MachOObjectReader(ctx)));
+ add(std::unique_ptr<Reader>(new mach_o::normalized::MachODylibReader(ctx)));
addKindTable(Reference::KindNamespace::mach_o, ctx.archHandler().kindArch(),
ctx.archHandler().kindStrings());
add(std::unique_ptr<YamlIOTaggedDocumentHandler>(
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
index 7465fb2e613..1c22ecf1127 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
@@ -712,9 +712,32 @@ std::error_code addEHFrameReferences(const NormalizedFile &normalizedFile,
/// Converts normalized mach-o file into an lld::File and lld::Atoms.
ErrorOr<std::unique_ptr<lld::File>>
-normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
- bool copyRefs) {
+objectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
+ bool copyRefs) {
std::unique_ptr<MachOFile> file(new MachOFile(path));
+ if (std::error_code ec = normalizedObjectToAtoms(
+ file.get(), normalizedFile, copyRefs))
+ return ec;
+ return std::unique_ptr<File>(std::move(file));
+}
+
+ErrorOr<std::unique_ptr<lld::File>>
+dylibToAtoms(const NormalizedFile &normalizedFile, StringRef path,
+ bool copyRefs) {
+ // Instantiate SharedLibraryFile object.
+ std::unique_ptr<MachODylibFile> file(new MachODylibFile(path));
+ normalizedDylibToAtoms(file.get(), normalizedFile, copyRefs);
+ return std::unique_ptr<File>(std::move(file));
+}
+
+} // anonymous namespace
+
+namespace normalized {
+
+std::error_code
+normalizedObjectToAtoms(MachOFile *file,
+ const NormalizedFile &normalizedFile,
+ bool copyRefs) {
bool scatterable = ((normalizedFile.flags & MH_SUBSECTIONS_VIA_SYMBOLS) != 0);
// Create atoms from each section.
@@ -811,18 +834,17 @@ normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
for (const DefinedAtom* defAtom : file->defined()) {
reinterpret_cast<const SimpleDefinedAtom*>(defAtom)->sortReferences();
}
-
- return std::unique_ptr<File>(std::move(file));
+ return std::error_code();
}
-ErrorOr<std::unique_ptr<lld::File>>
-normalizedDylibToAtoms(const NormalizedFile &normalizedFile, StringRef path,
+std::error_code
+normalizedDylibToAtoms(MachODylibFile *file,
+ const NormalizedFile &normalizedFile,
bool copyRefs) {
- // Instantiate SharedLibraryFile object.
- std::unique_ptr<MachODylibFile> file(
- new MachODylibFile(path, normalizedFile.installName,
- normalizedFile.compatVersion,
- normalizedFile.currentVersion));
+ file->setInstallName(normalizedFile.installName);
+ file->setCompatVersion(normalizedFile.compatVersion);
+ file->setCurrentVersion(normalizedFile.currentVersion);
+
// Tell MachODylibFile object about all symbols it exports.
if (!normalizedFile.exportInfo.empty()) {
// If exports trie exists, use it instead of traditional symbol table.
@@ -843,14 +865,9 @@ normalizedDylibToAtoms(const NormalizedFile &normalizedFile, StringRef path,
if (dep.kind == llvm::MachO::LC_REEXPORT_DYLIB)
file->addReExportedDylib(dep.path);
}
-
- return std::unique_ptr<File>(std::move(file));
+ return std::error_code();
}
-} // anonymous namespace
-
-namespace normalized {
-
void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
StringRef &segmentName,
StringRef &sectionName,
@@ -881,9 +898,9 @@ normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path,
switch (normalizedFile.fileType) {
case MH_DYLIB:
case MH_DYLIB_STUB:
- return normalizedDylibToAtoms(normalizedFile, path, copyRefs);
+ return dylibToAtoms(normalizedFile, path, copyRefs);
case MH_OBJECT:
- return normalizedObjectToAtoms(normalizedFile, path, copyRefs);
+ return objectToAtoms(normalizedFile, path, copyRefs);
default:
llvm_unreachable("unhandled MachO file type!");
}
diff --git a/lld/lib/ReaderWriter/Native/ReaderNative.cpp b/lld/lib/ReaderWriter/Native/ReaderNative.cpp
index 3c7846b1ae3..c29fc4543f2 100644
--- a/lld/lib/ReaderWriter/Native/ReaderNative.cpp
+++ b/lld/lib/ReaderWriter/Native/ReaderNative.cpp
@@ -259,14 +259,21 @@ private:
//
class File : public lld::File {
public:
+ File(std::unique_ptr<MemoryBuffer> mb)
+ : lld::File(mb->getBufferIdentifier(), kindObject),
+ _mb(std::move(mb)), // Reader now takes ownership of buffer
+ _header(nullptr), _targetsTable(nullptr), _targetsTableCount(0),
+ _strings(nullptr), _stringsMaxOffset(0), _addends(nullptr),
+ _addendsMaxIndex(0), _contentStart(nullptr), _contentEnd(nullptr) {
+ _header =
+ reinterpret_cast<const NativeFileHeader *>(_mb->getBufferStart());
+ }
- /// Instantiates a File object from a native object file. Ownership
- /// of the MemoryBuffer is transferred to the resulting File object.
- static std::error_code make(std::unique_ptr<MemoryBuffer> mb,
- std::vector<std::unique_ptr<lld::File>> &result) {
+ /// Parses a File object from a native object file.
+ std::error_code doParse() override {
const uint8_t *const base =
- reinterpret_cast<const uint8_t *>(mb->getBufferStart());
- StringRef path(mb->getBufferIdentifier());
+ reinterpret_cast<const uint8_t *>(_mb->getBufferStart());
+ StringRef path(_mb->getBufferIdentifier());
const NativeFileHeader *const header =
reinterpret_cast<const NativeFileHeader *>(base);
const NativeChunk *const chunks =
@@ -277,7 +284,7 @@ public:
return make_error_code(NativeReaderError::unknown_file_format);
// make sure mapped file contains all needed data
- const size_t fileSize = mb->getBufferSize();
+ const size_t fileSize = _mb->getBufferSize();
if (header->fileSize > fileSize)
return make_error_code(NativeReaderError::file_too_short);
@@ -286,9 +293,6 @@ public:
<< header->fileSize << " chunkCount="
<< header->chunkCount << "\n");
- // instantiate NativeFile object and add values to it as found
- std::unique_ptr<File> file(new File(std::move(mb), path));
-
// process each chunk
for (uint32_t i = 0; i < header->chunkCount; ++i) {
std::error_code ec;
@@ -301,40 +305,40 @@ public:
// process chunk, based on signature
switch ( chunk->signature ) {
case NCS_DefinedAtomsV1:
- ec = file->processDefinedAtomsV1(base, chunk);
+ ec = processDefinedAtomsV1(base, chunk);
break;
case NCS_AttributesArrayV1:
- ec = file->processAttributesV1(base, chunk);
+ ec = processAttributesV1(base, chunk);
break;
case NCS_UndefinedAtomsV1:
- ec = file->processUndefinedAtomsV1(base, chunk);
+ ec = processUndefinedAtomsV1(base, chunk);
break;
case NCS_SharedLibraryAtomsV1:
- ec = file->processSharedLibraryAtomsV1(base, chunk);
+ ec = processSharedLibraryAtomsV1(base, chunk);
break;
case NCS_AbsoluteAtomsV1:
- ec = file->processAbsoluteAtomsV1(base, chunk);
+ ec = processAbsoluteAtomsV1(base, chunk);
break;
case NCS_AbsoluteAttributesV1:
- ec = file->processAbsoluteAttributesV1(base, chunk);
+ ec = processAbsoluteAttributesV1(base, chunk);
break;
case NCS_ReferencesArrayV1:
- ec = file->processReferencesV1(base, chunk);
+ ec = processReferencesV1(base, chunk);
break;
case NCS_ReferencesArrayV2:
- ec = file->processReferencesV2(base, chunk);
+ ec = processReferencesV2(base, chunk);
break;
case NCS_TargetsTable:
- ec = file->processTargetsTable(base, chunk);
+ ec = processTargetsTable(base, chunk);
break;
case NCS_AddendsTable:
- ec = file->processAddendsTable(base, chunk);
+ ec = processAddendsTable(base, chunk);
break;
case NCS_Content:
- ec = file->processContent(base, chunk);
+ ec = processContent(base, chunk);
break;
case NCS_Strings:
- ec = file->processStrings(base, chunk);
+ ec = processStrings(base, chunk);
break;
default:
return make_error_code(NativeReaderError::unknown_chunk_type);
@@ -347,7 +351,7 @@ public:
DEBUG_WITH_TYPE("ReaderNative", {
llvm::dbgs() << " ReaderNative DefinedAtoms:\n";
- for (const DefinedAtom *a : file->defined()) {
+ for (const DefinedAtom *a : defined()) {
llvm::dbgs() << llvm::format(" 0x%09lX", a)
<< ", name=" << a->name()
<< ", size=" << a->size() << "\n";
@@ -359,12 +363,11 @@ public:
}
}
});
- result.push_back(std::move(file));
return make_error_code(NativeReaderError::success);
}
virtual ~File() {
- // _buffer is automatically deleted because of std::unique_ptr<>
+ // _mb is automatically deleted because of std::unique_ptr<>
// All other ivar pointers are pointers into the MemoryBuffer, except
// the _definedAtoms array which was allocated to contain an array
@@ -785,17 +788,6 @@ private:
_targetsTable[index] = newAtom;
}
- // private constructor, only called by make()
- File(std::unique_ptr<MemoryBuffer> mb, StringRef path)
- : lld::File(path, kindObject),
- _buffer(std::move(mb)), // Reader now takes ownership of buffer
- _header(nullptr), _targetsTable(nullptr), _targetsTableCount(0),
- _strings(nullptr), _stringsMaxOffset(0), _addends(nullptr),
- _addendsMaxIndex(0), _contentStart(nullptr), _contentEnd(nullptr) {
- _header =
- reinterpret_cast<const NativeFileHeader *>(_buffer->getBufferStart());
- }
-
template <typename T>
class AtomArray : public File::atom_collection<T> {
public:
@@ -836,7 +828,7 @@ private:
uint32_t elementCount;
};
- std::unique_ptr<MemoryBuffer> _buffer;
+ std::unique_ptr<MemoryBuffer> _mb;
const NativeFileHeader* _header;
AtomArray<DefinedAtom> _definedAtoms;
AtomArray<UndefinedAtom> _undefinedAtoms;
@@ -1009,9 +1001,12 @@ public:
virtual std::error_code
parseFile(std::unique_ptr<MemoryBuffer> &mb, const class Registry &,
std::vector<std::unique_ptr<File>> &result) const override {
- return lld::native::File::make(std::move(mb), result);
+ auto *file = new lld::native::File(std::move(mb));
+ result.push_back(std::unique_ptr<File>(file));
+ return std::error_code();
}
};
+
}
void Registry::addSupportNativeObjects() {
diff --git a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
index 889cbbe6906..6a908a74c24 100644
--- a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
+++ b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
@@ -55,6 +55,21 @@ using namespace lld;
namespace {
+class BumpPtrStringSaver : public llvm::cl::StringSaver {
+public:
+ const char *SaveString(const char *str) override {
+ size_t len = strlen(str);
+ std::lock_guard<std::mutex> lock(_allocMutex);
+ char *copy = _alloc.Allocate<char>(len + 1);
+ memcpy(copy, str, len + 1);
+ return copy;
+ }
+
+private:
+ llvm::BumpPtrAllocator _alloc;
+ std::mutex _allocMutex;
+};
+
class FileCOFF : public File {
private:
typedef std::vector<llvm::object::COFFSymbolRef> SymbolVectorT;
@@ -66,10 +81,12 @@ private:
public:
typedef const std::map<std::string, std::string> StringMap;
- FileCOFF(std::unique_ptr<MemoryBuffer> mb, std::error_code &ec);
+ FileCOFF(std::unique_ptr<MemoryBuffer> mb, PECOFFLinkingContext &ctx)
+ : File(mb->getBufferIdentifier(), kindObject), _mb(std::move(mb)),
+ _compatibleWithSEH(false), _ordinal(0),
+ _machineType(llvm::COFF::MT_Invalid), _ctx(ctx) {}
- std::error_code parse();
- StringRef getLinkerDirectives() const { return _directives; }
+ std::error_code doParse() override;
bool isCompatibleWithSEH() const { return _compatibleWithSEH; }
llvm::COFF::MachineTypes getMachineType() { return _machineType; }
@@ -98,6 +115,11 @@ public:
_undefinedAtoms._atoms.push_back(new (_alloc) COFFUndefinedAtom(*this, sym));
}
+ AliasAtom *createAlias(StringRef name, const DefinedAtom *target);
+ void createAlternateNameAtoms();
+ std::error_code parseDirectiveSection(
+ StringRef directives, std::set<StringRef> *undefinedSymbols);
+
mutable llvm::BumpPtrAllocator _alloc;
private:
@@ -155,9 +177,6 @@ private:
// The target type of the object.
Reference::KindArch _referenceArch;
- // The contents of .drectve section.
- StringRef _directives;
-
// True if the object has "@feat.00" symbol.
bool _compatibleWithSEH;
@@ -192,21 +211,8 @@ private:
uint64_t _ordinal;
llvm::COFF::MachineTypes _machineType;
-};
-
-class BumpPtrStringSaver : public llvm::cl::StringSaver {
-public:
- const char *SaveString(const char *str) override {
- size_t len = strlen(str);
- std::lock_guard<std::mutex> lock(_allocMutex);
- char *copy = _alloc.Allocate<char>(len + 1);
- memcpy(copy, str, len + 1);
- return copy;
- }
-
-private:
- llvm::BumpPtrAllocator _alloc;
- std::mutex _allocMutex;
+ PECOFFLinkingContext &_ctx;
+ mutable BumpPtrStringSaver _stringSaver;
};
// Converts the COFF symbol attribute to the LLD's atom attribute.
@@ -290,33 +296,54 @@ DefinedAtom::Merge getMerge(const coff_aux_section_definition *auxsym) {
}
}
-FileCOFF::FileCOFF(std::unique_ptr<MemoryBuffer> mb, std::error_code &ec)
- : File(mb->getBufferIdentifier(), kindObject), _mb(std::move(mb)),
- _compatibleWithSEH(false), _ordinal(0),
- _machineType(llvm::COFF::MT_Invalid) {
+StringRef getMachineName(llvm::COFF::MachineTypes Type) {
+ switch (Type) {
+ default: llvm_unreachable("unsupported machine type");
+ case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
+ return "ARM";
+ case llvm::COFF::IMAGE_FILE_MACHINE_I386:
+ return "X86";
+ case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
+ return "X64";
+ }
+}
+
+std::error_code FileCOFF::doParse() {
auto binaryOrErr = llvm::object::createBinary(_mb->getMemBufferRef());
- if ((ec = binaryOrErr.getError()))
- return;
+ if (std::error_code ec = binaryOrErr.getError())
+ return ec;
std::unique_ptr<llvm::object::Binary> bin = std::move(binaryOrErr.get());
_obj.reset(dyn_cast<const llvm::object::COFFObjectFile>(bin.get()));
- if (!_obj) {
- ec = make_error_code(llvm::object::object_error::invalid_file_type);
- return;
- }
+ if (!_obj)
+ return make_error_code(llvm::object::object_error::invalid_file_type);
bin.release();
_machineType = static_cast<llvm::COFF::MachineTypes>(_obj->getMachine());
+ if (getMachineType() != llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
+ getMachineType() != _ctx.getMachineType()) {
+ llvm::errs() << "module machine type '"
+ << getMachineName(getMachineType())
+ << "' conflicts with target machine type '"
+ << getMachineName(_ctx.getMachineType()) << "'\n";
+ return NativeReaderError::conflicting_target_machine;
+ }
+
+ // The set to contain the symbols specified as arguments of
+ // /INCLUDE option.
+ std::set<StringRef> undefinedSymbols;
+
+ // Interpret .drectve section if the section has contents.
// Read .drectve section if exists.
ArrayRef<uint8_t> directives;
- if ((ec = getSectionContents(".drectve", directives)))
- return;
+ if (std::error_code ec = getSectionContents(".drectve", directives))
+ return ec;
if (!directives.empty())
- _directives = ArrayRefToString(directives);
-}
+ if (std::error_code ec = parseDirectiveSection(
+ ArrayRefToString(directives), &undefinedSymbols))
+ return ec;
-std::error_code FileCOFF::parse() {
if (std::error_code ec = getReferenceArch(_referenceArch))
return ec;
@@ -329,7 +356,7 @@ std::error_code FileCOFF::parse() {
createAbsoluteAtoms(symbols, _absoluteAtoms._atoms);
if (std::error_code ec =
- createUndefinedAtoms(symbols, _undefinedAtoms._atoms))
+ createUndefinedAtoms(symbols, _undefinedAtoms._atoms))
return ec;
if (std::error_code ec = createDefinedSymbols(symbols, _definedAtoms._atoms))
return ec;
@@ -337,6 +364,37 @@ std::error_code FileCOFF::parse() {
return ec;
if (std::error_code ec = maybeCreateSXDataAtoms())
return ec;
+
+ // Check for /SAFESEH.
+ if (_ctx.requireSEH() && !isCompatibleWithSEH()) {
+ llvm::errs() << "/SAFESEH is specified, but "
+ << _mb->getBufferIdentifier()
+ << " is not compatible with SEH.\n";
+ return llvm::object::object_error::parse_failed;
+ }
+
+ // Add /INCLUDE'ed symbols to the file as if they existed in the
+ // file as undefined symbols.
+ for (StringRef sym : undefinedSymbols)
+ addUndefinedSymbol(sym);
+
+ // One can define alias symbols using /alternatename:<sym>=<sym> option.
+ // The mapping for /alternatename is in the context object. This helper
+ // function iterate over defined atoms and create alias atoms if needed.
+ createAlternateNameAtoms();
+
+ // Acquire the mutex to mutate _ctx.
+ std::lock_guard<std::recursive_mutex> lock(_ctx.getMutex());
+
+ // In order to emit SEH table, all input files need to be compatible with
+ // SEH. Disable SEH if the file being read is not compatible.
+ if (!isCompatibleWithSEH())
+ _ctx.setSafeSEH(false);
+
+ if (_ctx.deadStrip())
+ for (StringRef sym : undefinedSymbols)
+ _ctx.addDeadStripRoot(sym);
+
return std::error_code();
}
@@ -804,6 +862,67 @@ std::error_code FileCOFF::getSectionContents(StringRef sectionName,
return std::error_code();
}
+AliasAtom *FileCOFF::createAlias(StringRef name,
+ const DefinedAtom *target) {
+ AliasAtom *alias = new (_alloc) AliasAtom(*this, name);
+ alias->addReference(Reference::KindNamespace::all, Reference::KindArch::all,
+ Reference::kindLayoutAfter, 0, target, 0);
+ alias->setMerge(DefinedAtom::mergeAsWeak);
+ if (target->contentType() == DefinedAtom::typeCode)
+ alias->setDeadStrip(DefinedAtom::deadStripNever);
+ return alias;
+}
+
+void FileCOFF::createAlternateNameAtoms() {
+ std::vector<AliasAtom *> aliases;
+ for (const DefinedAtom *atom : defined()) {
+ auto it = _ctx.alternateNames().find(atom->name());
+ if (it != _ctx.alternateNames().end())
+ aliases.push_back(createAlias(it->second, atom));
+ }
+ for (AliasAtom *alias : aliases)
+ addDefinedAtom(alias);
+}
+
+// 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.
+std::error_code
+FileCOFF::parseDirectiveSection(StringRef directives,
+ std::set<StringRef> *undefinedSymbols) {
+ 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, _ctx, stream,
+ /*isDirective*/ true,
+ undefinedSymbols);
+ stream.flush();
+ // Print error message if error.
+ if (parseFailed) {
+ auto msg = Twine("Failed to parse '") + directives + "'\n"
+ + "Reason: " + errorMessage;
+ return make_dynamic_error_code(msg);
+ }
+ if (!errorMessage.empty()) {
+ llvm::errs() << "lld warning: " << errorMessage << "\n";
+ }
+ return std::error_code();
+}
+
/// Returns the target machine type of the current object file.
std::error_code FileCOFF::getReferenceArch(Reference::KindArch &result) {
switch (_obj->getMachine()) {
@@ -945,18 +1064,6 @@ StringRef FileCOFF::ArrayRefToString(ArrayRef<uint8_t> array) {
return StringRef(*contents).trim();
}
-StringRef getMachineName(llvm::COFF::MachineTypes Type) {
- switch (Type) {
- default: llvm_unreachable("unsupported machine type");
- case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
- return "ARM";
- case llvm::COFF::IMAGE_FILE_MACHINE_I386:
- return "X86";
- case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
- return "X64";
- }
-}
-
class COFFObjectReader : public Reader {
public:
COFFObjectReader(PECOFFLinkingContext &ctx) : _ctx(ctx) {}
@@ -967,136 +1074,16 @@ public:
}
std::error_code
- parseFile(std::unique_ptr<MemoryBuffer> &mb, const Registry &registry,
+ parseFile(std::unique_ptr<MemoryBuffer> &mb, const Registry &,
std::vector<std::unique_ptr<File>> &result) const override {
// Parse the memory buffer as PECOFF file.
- const char *mbName = mb->getBufferIdentifier();
- std::error_code ec;
- std::unique_ptr<FileCOFF> file(new FileCOFF(std::move(mb), ec));
- if (ec)
- return ec;
-
- if (file->getMachineType() != llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
- file->getMachineType() != _ctx.getMachineType()) {
- llvm::errs() << "module machine type '"
- << getMachineName(file->getMachineType())
- << "' conflicts with target machine type '"
- << getMachineName(_ctx.getMachineType()) << "'\n";
- return NativeReaderError::conflicting_target_machine;
- }
-
- // The set to contain the symbols specified as arguments of
- // /INCLUDE option.
- std::set<StringRef> undefinedSymbols;
-
- // Interpret .drectve section if the section has contents.
- StringRef directives = file->getLinkerDirectives();
- if (!directives.empty())
- if (std::error_code ec = handleDirectiveSection(
- directives, &undefinedSymbols))
- return ec;
-
- if (std::error_code ec = file->parse())
- return ec;
-
- // Check for /SAFESEH.
- if (_ctx.requireSEH() && !file->isCompatibleWithSEH()) {
- llvm::errs() << "/SAFESEH is specified, but " << mbName
- << " is not compatible with SEH.\n";
- return llvm::object::object_error::parse_failed;
- }
-
- // Add /INCLUDE'ed symbols to the file as if they existed in the
- // file as undefined symbols.
- for (StringRef sym : undefinedSymbols)
- file->addUndefinedSymbol(sym);
-
- // One can define alias symbols using /alternatename:<sym>=<sym> option.
- // The mapping for /alternatename is in the context object. This helper
- // function iterate over defined atoms and create alias atoms if needed.
- createAlternateNameAtoms(*file);
-
- // Acquire the mutex to mutate _ctx.
- std::lock_guard<std::recursive_mutex> lock(_ctx.getMutex());
-
- // In order to emit SEH table, all input files need to be compatible with
- // SEH. Disable SEH if the file being read is not compatible.
- if (!file->isCompatibleWithSEH())
- _ctx.setSafeSEH(false);
-
- if (_ctx.deadStrip())
- for (StringRef sym : undefinedSymbols)
- _ctx.addDeadStripRoot(sym);
-
- result.push_back(std::move(file));
+ auto *file = new FileCOFF(std::move(mb), _ctx);
+ result.push_back(std::unique_ptr<File>(file));
return std::error_code();
}
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.
- std::error_code handleDirectiveSection(StringRef directives,
- std::set<StringRef> *undefinedSymbols) 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, _ctx, stream,
- /*isDirective*/ true,
- undefinedSymbols);
- stream.flush();
- // Print error message if error.
- if (parseFailed) {
- auto msg = Twine("Failed to parse '") + directives + "'\n"
- + "Reason: " + errorMessage;
- return make_dynamic_error_code(msg);
- }
- if (!errorMessage.empty()) {
- llvm::errs() << "lld warning: " << errorMessage << "\n";
- }
- return std::error_code();
- }
-
- AliasAtom *createAlias(FileCOFF &file, StringRef name,
- const DefinedAtom *target) const {
- AliasAtom *alias = new (file._alloc) AliasAtom(file, name);
- alias->addReference(Reference::KindNamespace::all, Reference::KindArch::all,
- Reference::kindLayoutAfter, 0, target, 0);
- alias->setMerge(DefinedAtom::mergeAsWeak);
- if (target->contentType() == DefinedAtom::typeCode)
- alias->setDeadStrip(DefinedAtom::deadStripNever);
- return alias;
- }
-
- // Iterates over defined atoms and create alias atoms if needed.
- void createAlternateNameAtoms(FileCOFF &file) const {
- std::vector<AliasAtom *> aliases;
- for (const DefinedAtom *atom : file.defined()) {
- auto it = _ctx.alternateNames().find(atom->name());
- if (it != _ctx.alternateNames().end())
- aliases.push_back(createAlias(file, it->second, atom));
- }
- for (AliasAtom *alias : aliases) {
- file.addDefinedAtom(alias);
- }
- }
-
PECOFFLinkingContext &_ctx;
- mutable BumpPtrStringSaver _stringSaver;
};
using namespace llvm::COFF;
diff --git a/lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp b/lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp
index 258887ac0bc..e511ef2d40e 100644
--- a/lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp
+++ b/lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp
@@ -197,31 +197,31 @@ private:
class FileImportLibrary : public File {
public:
- FileImportLibrary(std::unique_ptr<MemoryBuffer> mb, std::error_code &ec,
- MachineTypes machine)
- : File(mb->getBufferIdentifier(), kindSharedLibrary), _machine(machine) {
- const char *buf = mb->getBufferStart();
- const char *end = mb->getBufferEnd();
+ FileImportLibrary(std::unique_ptr<MemoryBuffer> mb, MachineTypes machine)
+ : File(mb->getBufferIdentifier(), kindSharedLibrary),
+ _mb(std::move(mb)), _machine(machine) {}
+
+ std::error_code doParse() override {
+ const char *buf = _mb->getBufferStart();
+ const char *end = _mb->getBufferEnd();
// The size of the string that follows the header.
uint32_t dataSize = *reinterpret_cast<const support::ulittle32_t *>(
- buf + offsetof(COFF::ImportHeader, SizeOfData));
+ buf + offsetof(COFF::ImportHeader, SizeOfData));
// Check if the total size is valid.
- if (std::size_t(end - buf) != sizeof(COFF::ImportHeader) + dataSize) {
- ec = make_error_code(NativeReaderError::unknown_file_format);
- return;
- }
+ if (std::size_t(end - buf) != sizeof(COFF::ImportHeader) + dataSize)
+ return make_error_code(NativeReaderError::unknown_file_format);
uint16_t hint = *reinterpret_cast<const support::ulittle16_t *>(
- buf + offsetof(COFF::ImportHeader, OrdinalHint));
+ buf + offsetof(COFF::ImportHeader, OrdinalHint));
StringRef symbolName(buf + sizeof(COFF::ImportHeader));
StringRef dllName(buf + sizeof(COFF::ImportHeader) + symbolName.size() + 1);
// TypeInfo is a bitfield. The least significant 2 bits are import
// type, followed by 3 bit import name type.
uint16_t typeInfo = *reinterpret_cast<const support::ulittle16_t *>(
- buf + offsetof(COFF::ImportHeader, TypeInfo));
+ buf + offsetof(COFF::ImportHeader, TypeInfo));
int type = typeInfo & 0x3;
int nameType = (typeInfo >> 2) & 0x7;
@@ -235,7 +235,7 @@ public:
if (type == llvm::COFF::IMPORT_CODE)
addFuncAtom(symbolName, dllName, dataAtom);
- ec = std::error_code();
+ return std::error_code();
}
const atom_collection<DefinedAtom> &defined() const override {
@@ -309,6 +309,7 @@ private:
return *str;
}
+ std::unique_ptr<MemoryBuffer> _mb;
MachineTypes _machine;
};
@@ -326,12 +327,8 @@ public:
std::error_code
parseFile(std::unique_ptr<MemoryBuffer> &mb, const class Registry &,
std::vector<std::unique_ptr<File> > &result) const override {
- std::error_code ec;
- auto file = std::unique_ptr<File>(
- new FileImportLibrary(std::move(mb), ec, _machine));
- if (ec)
- return ec;
- result.push_back(std::move(file));
+ auto *file = new FileImportLibrary(std::move(mb), _machine);
+ result.push_back(std::unique_ptr<File>(file));
return std::error_code();
}
diff --git a/lld/lib/ReaderWriter/Reader.cpp b/lld/lib/ReaderWriter/Reader.cpp
index f7077199c0b..a730d0d216f 100644
--- a/lld/lib/ReaderWriter/Reader.cpp
+++ b/lld/lib/ReaderWriter/Reader.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "lld/Core/File.h"
#include "lld/ReaderWriter/Reader.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Errc.h"
@@ -38,9 +39,16 @@ Registry::parseFile(std::unique_ptr<MemoryBuffer> &mb,
StringRef extension = llvm::sys::path::extension(mb->getBufferIdentifier());
// Ask each registered reader if it can handle this file type or extension.
- for (const std::unique_ptr<Reader> &reader : _readers)
- if (reader->canParse(fileType, extension, *mb))
- return reader->parseFile(mb, *this, result);
+ for (const std::unique_ptr<Reader> &reader : _readers) {
+ if (!reader->canParse(fileType, extension, *mb))
+ continue;
+ if (std::error_code ec = reader->parseFile(mb, *this, result))
+ return ec;
+ for (std::unique_ptr<File> &file : result)
+ if (std::error_code ec = file->parse())
+ return ec;
+ return std::error_code();
+ }
// No Reader could parse this file.
return make_error_code(llvm::errc::executable_format_error);
diff --git a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
index f41f978d7c6..3b03cdc4a41 100644
--- a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
+++ b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
@@ -1351,6 +1351,7 @@ public:
for (const File *file : createdFiles) {
// Note: parseFile() should return vector of *const* File
File *f = const_cast<File *>(file);
+ f->setLastError(std::error_code());
result.emplace_back(f);
}
return make_error_code(lld::YamlReaderError::success);
OpenPOWER on IntegriCloud