summaryrefslogtreecommitdiffstats
path: root/lld/lib
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2014-12-12 07:31:09 +0000
committerRui Ueyama <ruiu@google.com>2014-12-12 07:31:09 +0000
commit1d510428e8d110e9f1f4dcf3f2f0ea189948f330 (patch)
tree018a03c36d7c5fac2e806fdd884e376259377a5d /lld/lib
parentadb3864744c20a7d4046718d2e0486cab2a02b06 (diff)
downloadbcm5719-llvm-1d510428e8d110e9f1f4dcf3f2f0ea189948f330.tar.gz
bcm5719-llvm-1d510428e8d110e9f1f4dcf3f2f0ea189948f330.zip
Separate file parsing from File's constructors.
This is a second patch for InputGraph cleanup. Sorry about the size of the patch, but what I did in this patch is basically moving code from constructor to a new method, parse(), so the amount of new code is small. This has no change in functionality. We've discussed the issue that we have too many classes to represent a concept of "file". We have File subclasses that represent files read from disk. In addition to that, we have bunch of InputElement subclasses (that are part of InputGraph) that represent command line arguments for input file names. InputElement is a wrapper for File. InputElement has parseFile method. The method instantiates a File. The File's constructor reads a file from disk and parses that. Because parseFile method is called from multiple worker threads, file parsing is processed in parallel. In other words, one reason why we needed the wrapper classes is because a File would start reading a file as soon as it is instantiated. So, the reason why we have too many classes here is at least partly because of the design flaw of File class. Just like threads in a good threading library, we need to separate instantiation from "start" method, so that we can instantiate File objects when we need them (which should be very fast because it involves only one mmap() and no real file IO) and use them directly instead of the wrapper classes. Later, we call parse() on each file in parallel to let them do actual file IO. In this design, we can eliminate a reason to have the wrapper classes. In order to minimize the size of the patch, I didn't go so far as to replace the wrapper classes with File classes. The wrapper classes are still there. In this patch, we call parse() immediately after instantiating a File, so this really has no change in functionality. Eventually the call of parse() should be moved to Driver::link(). That'll be done in another patch. llvm-svn: 224102
Diffstat (limited to 'lld/lib')
-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
18 files changed, 422 insertions, 368 deletions
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