summaryrefslogtreecommitdiffstats
path: root/lld/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lld/lib')
-rw-r--r--lld/lib/Core/Error.cpp33
-rw-r--r--lld/lib/Core/TODO.txt18
-rw-r--r--lld/lib/Driver/CoreDriver.cpp1
-rw-r--r--lld/lib/Driver/DarwinLdDriver.cpp1
-rw-r--r--lld/lib/Driver/GnuLdDriver.cpp4
-rw-r--r--lld/lib/Driver/GnuLdOptions.td2
-rw-r--r--lld/lib/Driver/WinLinkDriver.cpp1
-rw-r--r--lld/lib/ReaderWriter/CMakeLists.txt1
-rw-r--r--lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp3
-rw-r--r--lld/lib/ReaderWriter/Native/CMakeLists.txt7
-rw-r--r--lld/lib/ReaderWriter/Native/NativeFileFormat.h258
-rw-r--r--lld/lib/ReaderWriter/Native/ReaderNative.cpp881
-rw-r--r--lld/lib/ReaderWriter/Native/WriterNative.cpp566
-rw-r--r--lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp9
-rw-r--r--lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp2
15 files changed, 6 insertions, 1781 deletions
diff --git a/lld/lib/Core/Error.cpp b/lld/lib/Core/Error.cpp
index 24809c3869e..e1734283f55 100644
--- a/lld/lib/Core/Error.cpp
+++ b/lld/lib/Core/Error.cpp
@@ -16,39 +16,6 @@
using namespace lld;
-class _NativeReaderErrorCategory : public std::error_category {
-public:
- const char* name() const LLVM_NOEXCEPT override {
- return "lld.native.reader";
- }
-
- std::string message(int ev) const override {
- switch (static_cast<NativeReaderError>(ev)) {
- case NativeReaderError::success:
- return "Success";
- case NativeReaderError::unknown_file_format:
- return "Unknown file format";
- case NativeReaderError::file_too_short:
- return "file truncated";
- case NativeReaderError::file_malformed:
- return "file malformed";
- case NativeReaderError::memory_error:
- return "out of memory";
- case NativeReaderError::unknown_chunk_type:
- return "unknown chunk type";
- case NativeReaderError::conflicting_target_machine:
- return "conflicting target machine";
- }
- llvm_unreachable("An enumerator of NativeReaderError does not have a "
- "message defined.");
- }
-};
-
-const std::error_category &lld::native_reader_category() {
- static _NativeReaderErrorCategory o;
- return o;
-}
-
class _YamlReaderErrorCategory : public std::error_category {
public:
const char* name() const LLVM_NOEXCEPT override {
diff --git a/lld/lib/Core/TODO.txt b/lld/lib/Core/TODO.txt
deleted file mode 100644
index 196a3e02c2f..00000000000
--- a/lld/lib/Core/TODO.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-lib/Core
-~~~~~~~~
-
-* Add endianness support to the native reader and writer.
-
-* The NativeReader has lots of similar code for converting arrays of ivar
- data in mapped memory into arrays of objects. The commonality can be
- factored out, maybe templatized.
-
-* The NativeFileFormat.h is old school C structs and constants. We scope
- things better by defining constants used with a struct inside the struct
- declaration.
-
-* The native reader and writer currently just blast in memory enumeration
- values (e.g. DefinedAtom::Scope) into a byte in the disk format. To support
- future changes to the enumerations, there should be a translation layer
- to map disk values to in-memory values.
-
diff --git a/lld/lib/Driver/CoreDriver.cpp b/lld/lib/Driver/CoreDriver.cpp
index b8adee55746..825475ba894 100644
--- a/lld/lib/Driver/CoreDriver.cpp
+++ b/lld/lib/Driver/CoreDriver.cpp
@@ -77,7 +77,6 @@ bool CoreDriver::link(int argc, const char *argv[], raw_ostream &diagnostics) {
CoreLinkingContext ctx;
// Register possible input file parsers.
- ctx.registry().addSupportNativeObjects();
ctx.registry().addSupportYamlFiles();
ctx.registry().addKindTable(Reference::KindNamespace::testing,
Reference::KindArch::all, coreKindStrings);
diff --git a/lld/lib/Driver/DarwinLdDriver.cpp b/lld/lib/Driver/DarwinLdDriver.cpp
index 62afac8abb2..992f8adc8c0 100644
--- a/lld/lib/Driver/DarwinLdDriver.cpp
+++ b/lld/lib/Driver/DarwinLdDriver.cpp
@@ -544,7 +544,6 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
if (!ctx.doNothing()) {
ctx.registry().addSupportMachOObjects(ctx);
ctx.registry().addSupportArchives(ctx.logInputFiles());
- ctx.registry().addSupportNativeObjects();
ctx.registry().addSupportYamlFiles();
}
diff --git a/lld/lib/Driver/GnuLdDriver.cpp b/lld/lib/Driver/GnuLdDriver.cpp
index 7a1f674ec82..7f8d2473a75 100644
--- a/lld/lib/Driver/GnuLdDriver.cpp
+++ b/lld/lib/Driver/GnuLdDriver.cpp
@@ -645,7 +645,6 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
ctx->registry().addSupportELFObjects(*ctx);
ctx->registry().addSupportArchives(ctx->logInputFiles());
ctx->registry().addSupportYamlFiles();
- ctx->registry().addSupportNativeObjects();
if (ctx->allowLinkWithDynamicLibraries())
ctx->registry().addSupportELFDynamicSharedObjects(*ctx);
@@ -752,9 +751,6 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
case LinkingContext::OutputFileType::YAML:
ctx->setOutputPath("-");
break;
- case LinkingContext::OutputFileType::Native:
- ctx->setOutputPath("a.native");
- break;
default:
ctx->setOutputPath("a.out");
break;
diff --git a/lld/lib/Driver/GnuLdOptions.td b/lld/lib/Driver/GnuLdOptions.td
index 6cd26fa3164..b8b3fb69425 100644
--- a/lld/lib/Driver/GnuLdOptions.td
+++ b/lld/lib/Driver/GnuLdOptions.td
@@ -313,7 +313,7 @@ def stats : Flag<["--"], "stats">,
def grp_extns : OptionGroup<"opts">,
HelpText<"Extensions">;
def output_filetype: Separate<["--"], "output-filetype">,
- HelpText<"Specify what type of output file that lld creates, YAML/Native">,
+ HelpText<"Specify yaml to create an output in YAML format">,
Group<grp_extns>;
def alias_output_filetype: Joined<["--"], "output-filetype=">,
Alias<output_filetype>;
diff --git a/lld/lib/Driver/WinLinkDriver.cpp b/lld/lib/Driver/WinLinkDriver.cpp
index 6ee7a5a004b..7bc26bb24b0 100644
--- a/lld/lib/Driver/WinLinkDriver.cpp
+++ b/lld/lib/Driver/WinLinkDriver.cpp
@@ -862,7 +862,6 @@ bool WinLinkDriver::linkPECOFF(int argc, const char **argv, raw_ostream &diag) {
ctx.registry().addSupportCOFFObjects(ctx);
ctx.registry().addSupportCOFFImportLibraries(ctx);
ctx.registry().addSupportArchives(ctx.logInputFiles());
- ctx.registry().addSupportNativeObjects();
ctx.registry().addSupportYamlFiles();
std::vector<const char *> newargv = processLinkEnv(ctx, argc, argv);
diff --git a/lld/lib/ReaderWriter/CMakeLists.txt b/lld/lib/ReaderWriter/CMakeLists.txt
index 1fd19eb73a7..0f5df9490f7 100644
--- a/lld/lib/ReaderWriter/CMakeLists.txt
+++ b/lld/lib/ReaderWriter/CMakeLists.txt
@@ -1,6 +1,5 @@
add_subdirectory(ELF)
add_subdirectory(MachO)
-add_subdirectory(Native)
add_subdirectory(PECOFF)
add_subdirectory(YAML)
diff --git a/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp b/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
index 040a412d49f..5e734b2f88c 100644
--- a/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
+++ b/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
@@ -75,9 +75,6 @@ bool ELFLinkingContext::validateImpl(raw_ostream &diagnostics) {
case LinkingContext::OutputFileType::YAML:
_writer = createWriterYAML(*this);
break;
- case LinkingContext::OutputFileType::Native:
- llvm_unreachable("Unimplemented");
- break;
default:
_writer = createWriterELF(*this);
break;
diff --git a/lld/lib/ReaderWriter/Native/CMakeLists.txt b/lld/lib/ReaderWriter/Native/CMakeLists.txt
deleted file mode 100644
index e15f3d60e89..00000000000
--- a/lld/lib/ReaderWriter/Native/CMakeLists.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-add_llvm_library(lldNative
- ReaderNative.cpp
- WriterNative.cpp
- LINK_LIBS
- lldCore
- LLVMSupport
- )
diff --git a/lld/lib/ReaderWriter/Native/NativeFileFormat.h b/lld/lib/ReaderWriter/Native/NativeFileFormat.h
deleted file mode 100644
index dec893baa9a..00000000000
--- a/lld/lib/ReaderWriter/Native/NativeFileFormat.h
+++ /dev/null
@@ -1,258 +0,0 @@
-//===- lib/ReaderWriter/Native/NativeFileFormat.h -------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_NATIVE_NATIVE_FILE_FORMAT_H
-#define LLD_READER_WRITER_NATIVE_NATIVE_FILE_FORMAT_H
-
-#include "llvm/Support/DataTypes.h"
-#include <cstdint>
-
-namespace lld {
-
-//
-// Overview:
-//
-// The number one design goal of this file format is enable the linker to
-// read object files into in-memory Atom objects extremely quickly.
-// The second design goal is to enable future modifications to the
-// Atom attribute model.
-//
-// The llvm native object file format is not like traditional object file
-// formats (e.g. ELF, COFF, mach-o). There is no symbol table and no
-// sections. Instead the file is essentially an array of archived Atoms.
-// It is *not* serialized Atoms which would require deserialization into
-// in memory objects. Instead it is an array of read-only info about each
-// Atom. The NativeReader bulk creates in-memory Atoms which just have
-// an ivar which points to the read-only info for that Atom. No additional
-// processing is done to construct the in-memory Atoms. All Atom attribute
-// getter methods are virtual calls which dig up the info they need from the
-// ivar data.
-//
-// To support the gradual evolution of Atom attributes, the Atom read-only
-// data is versioned. The NativeReader chooses which in-memory Atom class
-// to use based on the version. What this means is that if new attributes
-// are added (or changed) in the Atom model, a new native atom class and
-// read-only atom info struct needs to be defined. Then, all the existing
-// native reader atom classes need to be modified to do their best effort
-// to map their old style read-only data to the new Atom model. At some point
-// some classes to support old versions may be dropped.
-//
-//
-// Details:
-//
-// The native object file format consists of a header that specifies the
-// endianness of the file and the architecture along with a list of "chunks"
-// in the file. A Chunk is simply a tagged range of the file. There is
-// one chunk for the array of atom infos. There is another chunk for the
-// string pool, and another for the content pool.
-//
-// It turns out there most atoms have very similar sets of attributes, only
-// the name and content attribute vary. To exploit this fact to reduce the file
-// size, the atom read-only info contains just the name and content info plus
-// a reference to which attribute set it uses. The attribute sets are stored
-// in another chunk.
-//
-
-
-//
-// An entry in the NativeFileHeader that describes one chunk of the file.
-//
-struct NativeChunk {
- uint32_t signature;
- uint32_t fileOffset;
- uint32_t fileSize;
- uint32_t elementCount;
-};
-
-
-//
-// The header in a native object file
-//
-struct NativeFileHeader {
- uint8_t magic[16];
- uint32_t endian;
- uint32_t architecture;
- uint32_t fileSize;
- uint32_t chunkCount;
- // NativeChunk chunks[]
-};
-
-//
-// Possible values for NativeChunk.signature field
-//
-enum NativeChunkSignatures {
- NCS_DefinedAtomsV1 = 1,
- NCS_AttributesArrayV1 = 2,
- NCS_AbsoluteAttributesV1 = 12,
- NCS_UndefinedAtomsV1 = 3,
- NCS_SharedLibraryAtomsV1 = 4,
- NCS_AbsoluteAtomsV1 = 5,
- NCS_Strings = 6,
- NCS_ReferencesArrayV1 = 7,
- NCS_ReferencesArrayV2 = 8,
- NCS_TargetsTable = 9,
- NCS_AddendsTable = 10,
- NCS_Content = 11,
-};
-
-//
-// The 16-bytes at the start of a native object file
-//
-#define NATIVE_FILE_HEADER_MAGIC "llvm nat obj v1 "
-
-//
-// Possible values for the NativeFileHeader.endian field
-//
-enum {
- NFH_BigEndian = 0x42696745,
- NFH_LittleEndian = 0x4574696c
-};
-
-
-//
-// Possible values for the NativeFileHeader.architecture field
-//
-enum {
- NFA_x86 = 1,
- NFA_x86_64 = 2,
- NFA_armv6 = 3,
- NFA_armv7 = 4,
-};
-
-
-//
-// The NCS_DefinedAtomsV1 chunk contains an array of these structs
-//
-struct NativeDefinedAtomIvarsV1 {
- uint32_t nameOffset;
- uint32_t attributesOffset;
- uint32_t referencesStartIndex;
- uint32_t referencesCount;
- uint32_t contentOffset;
- uint32_t contentSize;
- uint64_t sectionSize;
-};
-
-
-//
-// The NCS_AttributesArrayV1 chunk contains an array of these structs
-//
-struct NativeAtomAttributesV1 {
- uint32_t sectionNameOffset;
- uint16_t align;
- uint16_t alignModulus;
- uint8_t scope;
- uint8_t interposable;
- uint8_t merge;
- uint8_t contentType;
- uint8_t sectionChoice;
- uint8_t deadStrip;
- uint8_t dynamicExport;
- uint8_t permissions;
- uint8_t alias;
- uint8_t codeModel;
-};
-
-
-
-//
-// The NCS_UndefinedAtomsV1 chunk contains an array of these structs
-//
-struct NativeUndefinedAtomIvarsV1 {
- uint32_t nameOffset;
- uint32_t flags;
- uint32_t fallbackNameOffset;
-};
-
-
-//
-// The NCS_SharedLibraryAtomsV1 chunk contains an array of these structs
-//
-struct NativeSharedLibraryAtomIvarsV1 {
- uint64_t size;
- uint32_t nameOffset;
- uint32_t loadNameOffset;
- uint32_t type;
- uint32_t flags;
-};
-
-
-
-//
-// The NCS_AbsoluteAtomsV1 chunk contains an array of these structs
-//
-struct NativeAbsoluteAtomIvarsV1 {
- uint32_t nameOffset;
- uint32_t attributesOffset;
- uint32_t reserved;
- uint64_t value;
-};
-
-
-
-//
-// The NCS_ReferencesArrayV1 chunk contains an array of these structs
-//
-struct NativeReferenceIvarsV1 {
- enum {
- noTarget = UINT16_MAX
- };
- uint32_t offsetInAtom;
- uint16_t kindValue;
- uint8_t kindNamespace;
- uint8_t kindArch;
- uint16_t targetIndex;
- uint16_t addendIndex;
-};
-
-
-//
-// The NCS_ReferencesArrayV2 chunk contains an array of these structs
-//
-struct NativeReferenceIvarsV2 {
- enum : unsigned {
- noTarget = UINT32_MAX
- };
- uint64_t offsetInAtom;
- int64_t addend;
- uint16_t kindValue;
- uint8_t kindNamespace;
- uint8_t kindArch;
- uint32_t targetIndex;
- uint32_t tag;
-};
-
-
-//
-// The NCS_TargetsTable chunk contains an array of uint32_t entries.
-// The C++ class Reference has a target() method that returns a
-// pointer to another Atom. We can't have pointers in object files,
-// so instead NativeReferenceIvarsV1 contains an index to the target.
-// The index is into this NCS_TargetsTable of uint32_t entries.
-// The values in this table are the index of the (target) atom in this file.
-// For DefinedAtoms the value is from 0 to NCS_DefinedAtomsV1.elementCount.
-// For UndefinedAtoms the value is from NCS_DefinedAtomsV1.elementCount to
-// NCS_DefinedAtomsV1.elementCount+NCS_UndefinedAtomsV1.elementCount.
-//
-
-
-//
-// The NCS_AddendsTable chunk contains an array of int64_t entries.
-// If we allocated space for addends directly in NativeReferenceIvarsV1
-// it would double the size of that struct. But since addends are rare,
-// we instead just keep a pool of addends and have NativeReferenceIvarsV1
-// (if it needs an addend) just store the index (into the pool) of the
-// addend it needs.
-//
-
-
-
-} // namespace lld
-
-#endif // LLD_READER_WRITER_NATIVE_NATIVE_FILE_FORMAT_H
diff --git a/lld/lib/ReaderWriter/Native/ReaderNative.cpp b/lld/lib/ReaderWriter/Native/ReaderNative.cpp
deleted file mode 100644
index 2e40892771d..00000000000
--- a/lld/lib/ReaderWriter/Native/ReaderNative.cpp
+++ /dev/null
@@ -1,881 +0,0 @@
-//===- lib/ReaderWriter/Native/ReaderNative.cpp ---------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "NativeFileFormat.h"
-#include "lld/Core/Atom.h"
-#include "lld/Core/Error.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reader.h"
-#include "lld/Core/Simple.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <memory>
-#include <vector>
-
-namespace lld {
-namespace native {
-
-// forward reference
-class File;
-
-//
-// An object of this class is instantied for each NativeDefinedAtomIvarsV1
-// struct in the NCS_DefinedAtomsV1 chunk.
-//
-class NativeDefinedAtomV1 : public DefinedAtom {
-public:
- NativeDefinedAtomV1(const File& f,
- const NativeDefinedAtomIvarsV1* ivarData)
- : _file(&f), _ivarData(ivarData) { }
-
- const lld::File& file() const override;
-
- uint64_t ordinal() const override;
-
- StringRef name() const override;
-
- uint64_t size() const override { return _ivarData->contentSize; }
-
- uint64_t sectionSize() const override { return _ivarData->sectionSize; }
-
- DefinedAtom::Scope scope() const override {
- return (DefinedAtom::Scope)(attributes().scope);
- }
-
- DefinedAtom::Interposable interposable() const override {
- return (DefinedAtom::Interposable)(attributes().interposable);
- }
-
- DefinedAtom::Merge merge() const override {
- return (DefinedAtom::Merge)(attributes().merge);
- }
-
- DefinedAtom::ContentType contentType() const override {
- const NativeAtomAttributesV1& attr = attributes();
- return (DefinedAtom::ContentType)(attr.contentType);
- }
-
- DefinedAtom::Alignment alignment() const override {
- return DefinedAtom::Alignment(attributes().align,
- attributes().alignModulus);
- }
-
- DefinedAtom::SectionChoice sectionChoice() const override {
- return (DefinedAtom::SectionChoice)(attributes().sectionChoice);
- }
-
- StringRef customSectionName() const override;
-
- DefinedAtom::DeadStripKind deadStrip() const override {
- return (DefinedAtom::DeadStripKind)(attributes().deadStrip);
- }
-
- DynamicExport dynamicExport() const override {
- return (DynamicExport)attributes().dynamicExport;
- }
-
- DefinedAtom::CodeModel codeModel() const override {
- return DefinedAtom::CodeModel(attributes().codeModel);
- }
-
- DefinedAtom::ContentPermissions permissions() const override {
- return (DefinedAtom::ContentPermissions)(attributes().permissions);
- }
-
- ArrayRef<uint8_t> rawContent() const override;
-
- reference_iterator begin() const override;
-
- reference_iterator end() const override;
-
- const Reference* derefIterator(const void*) const override;
-
- void incrementIterator(const void*& it) const override;
-
-private:
- const NativeAtomAttributesV1& attributes() const;
-
- const File *_file;
- const NativeDefinedAtomIvarsV1 *_ivarData;
-};
-
-
-
-//
-// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
-// struct in the NCS_UndefinedAtomsV1 chunk.
-//
-class NativeUndefinedAtomV1 : public UndefinedAtom {
-public:
- NativeUndefinedAtomV1(const File& f,
- const NativeUndefinedAtomIvarsV1* ivarData)
- : _file(&f), _ivarData(ivarData) { }
-
- const lld::File& file() const override;
- StringRef name() const override;
-
- CanBeNull canBeNull() const override {
- return (CanBeNull)(_ivarData->flags & 0x3);
- }
-
- const UndefinedAtom *fallback() const override;
-
-private:
- const File *_file;
- const NativeUndefinedAtomIvarsV1 *_ivarData;
- mutable std::unique_ptr<const SimpleUndefinedAtom> _fallback;
-};
-
-
-//
-// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
-// struct in the NCS_SharedLibraryAtomsV1 chunk.
-//
-class NativeSharedLibraryAtomV1 : public SharedLibraryAtom {
-public:
- NativeSharedLibraryAtomV1(const File& f,
- const NativeSharedLibraryAtomIvarsV1* ivarData)
- : _file(&f), _ivarData(ivarData) { }
-
- const lld::File& file() const override;
- StringRef name() const override;
- StringRef loadName() const override;
-
- bool canBeNullAtRuntime() const override {
- return (_ivarData->flags & 0x1);
- }
-
- Type type() const override {
- return (Type)_ivarData->type;
- }
-
- uint64_t size() const override {
- return _ivarData->size;
- }
-
-private:
- const File *_file;
- const NativeSharedLibraryAtomIvarsV1 *_ivarData;
-};
-
-
-//
-// An object of this class is instantied for each NativeAbsoluteAtomIvarsV1
-// struct in the NCS_AbsoluteAtomsV1 chunk.
-//
-class NativeAbsoluteAtomV1 : public AbsoluteAtom {
-public:
- NativeAbsoluteAtomV1(const File& f,
- const NativeAbsoluteAtomIvarsV1* ivarData)
- : _file(&f), _ivarData(ivarData) { }
-
- const lld::File& file() const override;
- StringRef name() const override;
- Scope scope() const override {
- const NativeAtomAttributesV1& attr = absAttributes();
- return (Scope)(attr.scope);
- }
- uint64_t value() const override {
- return _ivarData->value;
- }
-
-private:
- const NativeAtomAttributesV1& absAttributes() const;
- const File *_file;
- const NativeAbsoluteAtomIvarsV1 *_ivarData;
-};
-
-
-//
-// An object of this class is instantied for each NativeReferenceIvarsV1
-// struct in the NCS_ReferencesArrayV1 chunk.
-//
-class NativeReferenceV1 : public Reference {
-public:
- NativeReferenceV1(const File &f, const NativeReferenceIvarsV1 *ivarData)
- : Reference((KindNamespace)ivarData->kindNamespace,
- (KindArch)ivarData->kindArch, ivarData->kindValue),
- _file(&f), _ivarData(ivarData) {}
-
- uint64_t offsetInAtom() const override {
- return _ivarData->offsetInAtom;
- }
-
- const Atom* target() const override;
- Addend addend() const override;
- void setTarget(const Atom* newAtom) override;
- void setAddend(Addend a) override;
-
-private:
- const File *_file;
- const NativeReferenceIvarsV1 *_ivarData;
-};
-
-
-//
-// An object of this class is instantied for each NativeReferenceIvarsV1
-// struct in the NCS_ReferencesArrayV1 chunk.
-//
-class NativeReferenceV2 : public Reference {
-public:
- NativeReferenceV2(const File &f, const NativeReferenceIvarsV2 *ivarData)
- : Reference((KindNamespace)ivarData->kindNamespace,
- (KindArch)ivarData->kindArch, ivarData->kindValue),
- _file(&f), _ivarData(ivarData) {}
-
- uint64_t offsetInAtom() const override {
- return _ivarData->offsetInAtom;
- }
-
- const Atom* target() const override;
- Addend addend() const override;
- void setTarget(const Atom* newAtom) override;
- void setAddend(Addend a) override;
- uint32_t tag() const override;
-
-private:
- const File *_file;
- const NativeReferenceIvarsV2 *_ivarData;
-};
-
-
-//
-// lld::File object for native llvm object file
-//
-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());
- }
-
- /// 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());
- const NativeFileHeader *const header =
- reinterpret_cast<const NativeFileHeader *>(base);
- const NativeChunk *const chunks =
- reinterpret_cast<const NativeChunk *>(base + sizeof(NativeFileHeader));
- // make sure magic matches
- if (memcmp(header->magic, NATIVE_FILE_HEADER_MAGIC,
- sizeof(header->magic)) != 0)
- return make_error_code(NativeReaderError::unknown_file_format);
-
- // make sure mapped file contains all needed data
- const size_t fileSize = _mb->getBufferSize();
- if (header->fileSize > fileSize)
- return make_error_code(NativeReaderError::file_too_short);
-
- DEBUG_WITH_TYPE("ReaderNative",
- llvm::dbgs() << " Native File Header:" << " fileSize="
- << header->fileSize << " chunkCount="
- << header->chunkCount << "\n");
-
- // process each chunk
- for (uint32_t i = 0; i < header->chunkCount; ++i) {
- std::error_code ec;
- const NativeChunk* chunk = &chunks[i];
- // sanity check chunk is within file
- if ( chunk->fileOffset > fileSize )
- return make_error_code(NativeReaderError::file_malformed);
- if ( (chunk->fileOffset + chunk->fileSize) > fileSize)
- return make_error_code(NativeReaderError::file_malformed);
- // process chunk, based on signature
- switch ( chunk->signature ) {
- case NCS_DefinedAtomsV1:
- ec = processDefinedAtomsV1(base, chunk);
- break;
- case NCS_AttributesArrayV1:
- ec = processAttributesV1(base, chunk);
- break;
- case NCS_UndefinedAtomsV1:
- ec = processUndefinedAtomsV1(base, chunk);
- break;
- case NCS_SharedLibraryAtomsV1:
- ec = processSharedLibraryAtomsV1(base, chunk);
- break;
- case NCS_AbsoluteAtomsV1:
- ec = processAbsoluteAtomsV1(base, chunk);
- break;
- case NCS_AbsoluteAttributesV1:
- ec = processAbsoluteAttributesV1(base, chunk);
- break;
- case NCS_ReferencesArrayV1:
- ec = processReferencesV1(base, chunk);
- break;
- case NCS_ReferencesArrayV2:
- ec = processReferencesV2(base, chunk);
- break;
- case NCS_TargetsTable:
- ec = processTargetsTable(base, chunk);
- break;
- case NCS_AddendsTable:
- ec = processAddendsTable(base, chunk);
- break;
- case NCS_Content:
- ec = processContent(base, chunk);
- break;
- case NCS_Strings:
- ec = processStrings(base, chunk);
- break;
- default:
- return make_error_code(NativeReaderError::unknown_chunk_type);
- }
- if ( ec ) {
- return ec;
- }
- }
- // TO DO: validate enough chunks were used
-
- DEBUG_WITH_TYPE("ReaderNative", {
- llvm::dbgs() << " ReaderNative DefinedAtoms:\n";
- for (const DefinedAtom *a : defined()) {
- llvm::dbgs() << llvm::format(" 0x%09lX", a)
- << ", name=" << a->name()
- << ", size=" << a->size() << "\n";
- for (const Reference *r : *a) {
- llvm::dbgs() << " offset="
- << llvm::format("0x%03X", r->offsetInAtom())
- << ", kind=" << r->kindValue()
- << ", target=" << r->target() << "\n";
- }
- }
- });
- return make_error_code(NativeReaderError::success);
- }
-
- virtual ~File() {
- // _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
- // of Atom objects. The atoms have empty destructors, so it is ok
- // to just delete the memory.
- delete _referencesV1.arrayStart;
- delete _referencesV2.arrayStart;
- delete [] _targetsTable;
- }
-
- const AtomVector<DefinedAtom> &defined() const override {
- return _definedAtoms;
- }
- const AtomVector<UndefinedAtom> &undefined() const override {
- return _undefinedAtoms;
- }
- const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
- return _sharedLibraryAtoms;
- }
- const AtomVector<AbsoluteAtom> &absolute() const override {
- return _absoluteAtoms;
- }
-
-private:
- friend NativeDefinedAtomV1;
- friend NativeUndefinedAtomV1;
- friend NativeSharedLibraryAtomV1;
- friend NativeAbsoluteAtomV1;
- friend NativeReferenceV1;
- friend NativeReferenceV2;
- template <typename T> class AtomArray;
-
- // instantiate array of BASeT from IvarsT data in file
- template <typename BaseT, typename AtomT, typename IvarsT>
- std::error_code processAtoms(AtomVector<BaseT> &result, const uint8_t *base,
- const NativeChunk *chunk) {
- std::vector<const BaseT *> vec(chunk->elementCount);
- const size_t ivarElementSize = chunk->fileSize / chunk->elementCount;
- if (ivarElementSize != sizeof(IvarsT))
- return make_error_code(NativeReaderError::file_malformed);
- auto *ivar = reinterpret_cast<const IvarsT *>(base + chunk->fileOffset);
- for (size_t i = 0; i < chunk->elementCount; ++i)
- vec[i] = new (_alloc) AtomT(*this, ivar++);
- result = std::move(vec);
- return make_error_code(NativeReaderError::success);
- }
-
- // instantiate array of DefinedAtoms from v1 ivar data in file
- std::error_code processDefinedAtomsV1(const uint8_t *base,
- const NativeChunk *chunk) {
- return processAtoms<DefinedAtom, NativeDefinedAtomV1,
- NativeDefinedAtomIvarsV1>(this->_definedAtoms, base,
- chunk);
- }
-
- // set up pointers to attributes array
- std::error_code processAttributesV1(const uint8_t *base,
- const NativeChunk *chunk) {
- this->_attributes = base + chunk->fileOffset;
- this->_attributesMaxOffset = chunk->fileSize;
- DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
- << " chunk AttributesV1: "
- << " count=" << chunk->elementCount
- << " chunkSize=" << chunk->fileSize
- << "\n");
- return make_error_code(NativeReaderError::success);
- }
-
- // set up pointers to attributes array
- std::error_code processAbsoluteAttributesV1(const uint8_t *base,
- const NativeChunk *chunk) {
- this->_absAttributes = base + chunk->fileOffset;
- this->_absAbsoluteMaxOffset = chunk->fileSize;
- DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
- << " chunk AbsoluteAttributesV1: "
- << " count=" << chunk->elementCount
- << " chunkSize=" << chunk->fileSize
- << "\n");
- return make_error_code(NativeReaderError::success);
- }
-
- // instantiate array of UndefinedAtoms from v1 ivar data in file
- std::error_code processUndefinedAtomsV1(const uint8_t *base,
- const NativeChunk *chunk) {
- return processAtoms<UndefinedAtom, NativeUndefinedAtomV1,
- NativeUndefinedAtomIvarsV1>(this->_undefinedAtoms, base,
- chunk);
- }
-
-
- // instantiate array of ShareLibraryAtoms from v1 ivar data in file
- std::error_code processSharedLibraryAtomsV1(const uint8_t *base,
- const NativeChunk *chunk) {
- return processAtoms<SharedLibraryAtom, NativeSharedLibraryAtomV1,
- NativeSharedLibraryAtomIvarsV1>(
- this->_sharedLibraryAtoms, base, chunk);
- }
-
-
- // instantiate array of AbsoluteAtoms from v1 ivar data in file
- std::error_code processAbsoluteAtomsV1(const uint8_t *base,
- const NativeChunk *chunk) {
- return processAtoms<AbsoluteAtom, NativeAbsoluteAtomV1,
- NativeAbsoluteAtomIvarsV1>(this->_absoluteAtoms, base,
- chunk);
- }
-
- template <class T, class U>
- std::error_code
- processReferences(const uint8_t *base, const NativeChunk *chunk,
- uint8_t *&refsStart, uint8_t *&refsEnd) const {
- if (chunk->elementCount == 0)
- return make_error_code(NativeReaderError::success);
- size_t refsArraySize = chunk->elementCount * sizeof(T);
- refsStart = reinterpret_cast<uint8_t *>(
- operator new(refsArraySize, std::nothrow));
- if (refsStart == nullptr)
- return make_error_code(NativeReaderError::memory_error);
- const size_t ivarElementSize = chunk->fileSize / chunk->elementCount;
- if (ivarElementSize != sizeof(U))
- return make_error_code(NativeReaderError::file_malformed);
- refsEnd = refsStart + refsArraySize;
- const U* ivarData = reinterpret_cast<const U *>(base + chunk->fileOffset);
- for (uint8_t *s = refsStart; s != refsEnd; s += sizeof(T), ++ivarData) {
- T *atomAllocSpace = reinterpret_cast<T *>(s);
- new (atomAllocSpace) T(*this, ivarData);
- }
- return make_error_code(NativeReaderError::success);
- }
-
- // instantiate array of References from v1 ivar data in file
- std::error_code processReferencesV1(const uint8_t *base,
- const NativeChunk *chunk) {
- uint8_t *refsStart, *refsEnd;
- if (std::error_code ec =
- processReferences<NativeReferenceV1, NativeReferenceIvarsV1>(
- base, chunk, refsStart, refsEnd))
- return ec;
- this->_referencesV1.arrayStart = refsStart;
- this->_referencesV1.arrayEnd = refsEnd;
- this->_referencesV1.elementSize = sizeof(NativeReferenceV1);
- this->_referencesV1.elementCount = chunk->elementCount;
- DEBUG_WITH_TYPE("ReaderNative", {
- llvm::dbgs() << " chunk ReferencesV1: "
- << " count=" << chunk->elementCount
- << " chunkSize=" << chunk->fileSize << "\n";
- });
- return make_error_code(NativeReaderError::success);
- }
-
- // instantiate array of References from v2 ivar data in file
- std::error_code processReferencesV2(const uint8_t *base,
- const NativeChunk *chunk) {
- uint8_t *refsStart, *refsEnd;
- if (std::error_code ec =
- processReferences<NativeReferenceV2, NativeReferenceIvarsV2>(
- base, chunk, refsStart, refsEnd))
- return ec;
- this->_referencesV2.arrayStart = refsStart;
- this->_referencesV2.arrayEnd = refsEnd;
- this->_referencesV2.elementSize = sizeof(NativeReferenceV2);
- this->_referencesV2.elementCount = chunk->elementCount;
- DEBUG_WITH_TYPE("ReaderNative", {
- llvm::dbgs() << " chunk ReferencesV2: "
- << " count=" << chunk->elementCount
- << " chunkSize=" << chunk->fileSize << "\n";
- });
- return make_error_code(NativeReaderError::success);
- }
-
- // set up pointers to target table
- std::error_code processTargetsTable(const uint8_t *base,
- const NativeChunk *chunk) {
- const uint32_t* targetIndexes = reinterpret_cast<const uint32_t*>
- (base + chunk->fileOffset);
- this->_targetsTableCount = chunk->elementCount;
- this->_targetsTable = new const Atom*[chunk->elementCount];
- for (uint32_t i=0; i < chunk->elementCount; ++i) {
- const uint32_t index = targetIndexes[i];
- if (index < _definedAtoms.size()) {
- this->_targetsTable[i] = _definedAtoms[index];
- continue;
- }
- const uint32_t undefIndex = index - _definedAtoms.size();
- if (undefIndex < _undefinedAtoms.size()) {
- this->_targetsTable[i] = _undefinedAtoms[index];
- continue;
- }
- const uint32_t slIndex = undefIndex - _undefinedAtoms.size();
- if (slIndex < _sharedLibraryAtoms.size()) {
- this->_targetsTable[i] = _sharedLibraryAtoms[slIndex];
- continue;
- }
- const uint32_t abIndex = slIndex - _sharedLibraryAtoms.size();
- if (abIndex < _absoluteAtoms.size()) {
- this->_targetsTable[i] = _absoluteAtoms[abIndex];
- continue;
- }
- return make_error_code(NativeReaderError::file_malformed);
- }
- DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
- << " chunk Targets Table: "
- << " count=" << chunk->elementCount
- << " chunkSize=" << chunk->fileSize
- << "\n");
- return make_error_code(NativeReaderError::success);
- }
-
-
- // set up pointers to addend pool in file
- std::error_code processAddendsTable(const uint8_t *base,
- const NativeChunk *chunk) {
- this->_addends = reinterpret_cast<const Reference::Addend*>
- (base + chunk->fileOffset);
- this->_addendsMaxIndex = chunk->elementCount;
- DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
- << " chunk Addends: "
- << " count=" << chunk->elementCount
- << " chunkSize=" << chunk->fileSize
- << "\n");
- return make_error_code(NativeReaderError::success);
- }
-
- // set up pointers to string pool in file
- std::error_code processStrings(const uint8_t *base,
- const NativeChunk *chunk) {
- this->_strings = reinterpret_cast<const char*>(base + chunk->fileOffset);
- this->_stringsMaxOffset = chunk->fileSize;
- DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
- << " chunk Strings: "
- << " chunkSize=" << chunk->fileSize
- << "\n");
- return make_error_code(NativeReaderError::success);
- }
-
- // set up pointers to content area in file
- std::error_code processContent(const uint8_t *base,
- const NativeChunk *chunk) {
- this->_contentStart = base + chunk->fileOffset;
- this->_contentEnd = base + chunk->fileOffset + chunk->fileSize;
- DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
- << " chunk content: "
- << " chunkSize=" << chunk->fileSize
- << "\n");
- return make_error_code(NativeReaderError::success);
- }
-
- StringRef string(uint32_t offset) const {
- assert(offset < _stringsMaxOffset);
- return StringRef(&_strings[offset]);
- }
-
- Reference::Addend addend(uint32_t index) const {
- if ( index == 0 )
- return 0; // addend index zero is used to mean "no addend"
- assert(index <= _addendsMaxIndex);
- return _addends[index-1]; // one-based indexing
- }
-
- const NativeAtomAttributesV1& attribute(uint32_t off) const {
- assert(off < _attributesMaxOffset);
- return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + off);
- }
-
- const NativeAtomAttributesV1& absAttribute(uint32_t off) const {
- assert(off < _absAbsoluteMaxOffset);
- return *reinterpret_cast<const NativeAtomAttributesV1*>(_absAttributes + off);
- }
-
- const uint8_t* content(uint32_t offset, uint32_t size) const {
- const uint8_t* result = _contentStart + offset;
- assert((result+size) <= _contentEnd);
- return result;
- }
-
- const Reference* referenceByIndex(uintptr_t index) const {
- if (index < _referencesV1.elementCount) {
- return reinterpret_cast<const NativeReferenceV1*>(
- _referencesV1.arrayStart + index * _referencesV1.elementSize);
- }
- assert(index < _referencesV2.elementCount);
- return reinterpret_cast<const NativeReferenceV2*>(
- _referencesV2.arrayStart + index * _referencesV2.elementSize);
- }
-
- const Atom* targetV1(uint16_t index) const {
- if ( index == NativeReferenceIvarsV1::noTarget )
- return nullptr;
- assert(index < _targetsTableCount);
- return _targetsTable[index];
- }
-
- void setTargetV1(uint16_t index, const Atom* newAtom) const {
- assert(index != NativeReferenceIvarsV1::noTarget);
- assert(index > _targetsTableCount);
- _targetsTable[index] = newAtom;
- }
-
- const Atom* targetV2(uint32_t index) const {
- if (index == NativeReferenceIvarsV2::noTarget)
- return nullptr;
- assert(index < _targetsTableCount);
- return _targetsTable[index];
- }
-
- void setTargetV2(uint32_t index, const Atom* newAtom) const {
- assert(index != NativeReferenceIvarsV2::noTarget);
- assert(index > _targetsTableCount);
- _targetsTable[index] = newAtom;
- }
-
- struct IvarArray {
- IvarArray() :
- arrayStart(nullptr),
- arrayEnd(nullptr),
- elementSize(0),
- elementCount(0) { }
-
- const uint8_t* arrayStart;
- const uint8_t* arrayEnd;
- uint32_t elementSize;
- uint32_t elementCount;
- };
-
- std::unique_ptr<MemoryBuffer> _mb;
- const NativeFileHeader* _header;
- AtomVector<DefinedAtom> _definedAtoms;
- AtomVector<UndefinedAtom> _undefinedAtoms;
- AtomVector<SharedLibraryAtom> _sharedLibraryAtoms;
- AtomVector<AbsoluteAtom> _absoluteAtoms;
- const uint8_t* _absAttributes;
- uint32_t _absAbsoluteMaxOffset;
- const uint8_t* _attributes;
- uint32_t _attributesMaxOffset;
- IvarArray _referencesV1;
- IvarArray _referencesV2;
- const Atom** _targetsTable;
- uint32_t _targetsTableCount;
- const char* _strings;
- uint32_t _stringsMaxOffset;
- const Reference::Addend* _addends;
- uint32_t _addendsMaxIndex;
- const uint8_t *_contentStart;
- const uint8_t *_contentEnd;
- llvm::BumpPtrAllocator _alloc;
-};
-
-inline const lld::File &NativeDefinedAtomV1::file() const {
- return *_file;
-}
-
-inline uint64_t NativeDefinedAtomV1::ordinal() const {
- const uint8_t* p = reinterpret_cast<const uint8_t*>(_ivarData);
- auto *start = reinterpret_cast<const NativeDefinedAtomV1 *>(
- _file->_definedAtoms[0]);
- const uint8_t *startp = reinterpret_cast<const uint8_t *>(start->_ivarData);
- return p - startp;
-}
-
-inline StringRef NativeDefinedAtomV1::name() const {
- return _file->string(_ivarData->nameOffset);
-}
-
-inline const NativeAtomAttributesV1& NativeDefinedAtomV1::attributes() const {
- return _file->attribute(_ivarData->attributesOffset);
-}
-
-inline ArrayRef<uint8_t> NativeDefinedAtomV1::rawContent() const {
- if (!occupiesDiskSpace())
- return ArrayRef<uint8_t>();
- const uint8_t* p = _file->content(_ivarData->contentOffset,
- _ivarData->contentSize);
- return ArrayRef<uint8_t>(p, _ivarData->contentSize);
-}
-
-inline StringRef NativeDefinedAtomV1::customSectionName() const {
- uint32_t offset = attributes().sectionNameOffset;
- return _file->string(offset);
-}
-
-DefinedAtom::reference_iterator NativeDefinedAtomV1::begin() const {
- uintptr_t index = _ivarData->referencesStartIndex;
- const void* it = reinterpret_cast<const void*>(index);
- return reference_iterator(*this, it);
-}
-
-DefinedAtom::reference_iterator NativeDefinedAtomV1::end() const {
- uintptr_t index = _ivarData->referencesStartIndex+_ivarData->referencesCount;
- const void* it = reinterpret_cast<const void*>(index);
- return reference_iterator(*this, it);
-}
-
-const Reference* NativeDefinedAtomV1::derefIterator(const void* it) const {
- uintptr_t index = reinterpret_cast<uintptr_t>(it);
- return _file->referenceByIndex(index);
-}
-
-void NativeDefinedAtomV1::incrementIterator(const void*& it) const {
- uintptr_t index = reinterpret_cast<uintptr_t>(it);
- ++index;
- it = reinterpret_cast<const void*>(index);
-}
-
-inline const lld::File& NativeUndefinedAtomV1::file() const {
- return *_file;
-}
-
-inline StringRef NativeUndefinedAtomV1::name() const {
- return _file->string(_ivarData->nameOffset);
-}
-
-inline const UndefinedAtom *NativeUndefinedAtomV1::fallback() const {
- if (!_ivarData->fallbackNameOffset)
- return nullptr;
- if (!_fallback)
- _fallback.reset(new SimpleUndefinedAtom(
- *_file, _file->string(_ivarData->fallbackNameOffset)));
- return _fallback.get();
-}
-
-inline const lld::File& NativeSharedLibraryAtomV1::file() const {
- return *_file;
-}
-
-inline StringRef NativeSharedLibraryAtomV1::name() const {
- return _file->string(_ivarData->nameOffset);
-}
-
-inline StringRef NativeSharedLibraryAtomV1::loadName() const {
- return _file->string(_ivarData->loadNameOffset);
-}
-
-
-
-inline const lld::File& NativeAbsoluteAtomV1::file() const {
- return *_file;
-}
-
-inline StringRef NativeAbsoluteAtomV1::name() const {
- return _file->string(_ivarData->nameOffset);
-}
-
-inline const NativeAtomAttributesV1& NativeAbsoluteAtomV1::absAttributes() const {
- return _file->absAttribute(_ivarData->attributesOffset);
-}
-
-inline const Atom* NativeReferenceV1::target() const {
- return _file->targetV1(_ivarData->targetIndex);
-}
-
-inline Reference::Addend NativeReferenceV1::addend() const {
- return _file->addend(_ivarData->addendIndex);
-}
-
-inline void NativeReferenceV1::setTarget(const Atom* newAtom) {
- return _file->setTargetV1(_ivarData->targetIndex, newAtom);
-}
-
-inline void NativeReferenceV1::setAddend(Addend a) {
- // Do nothing if addend value is not being changed.
- if (addend() == a)
- return;
- llvm_unreachable("setAddend() not supported");
-}
-
-inline const Atom* NativeReferenceV2::target() const {
- return _file->targetV2(_ivarData->targetIndex);
-}
-
-inline Reference::Addend NativeReferenceV2::addend() const {
- return _ivarData->addend;
-}
-
-inline void NativeReferenceV2::setTarget(const Atom* newAtom) {
- return _file->setTargetV2(_ivarData->targetIndex, newAtom);
-}
-
-inline void NativeReferenceV2::setAddend(Addend a) {
- // Do nothing if addend value is not being changed.
- if (addend() == a)
- return;
- llvm_unreachable("setAddend() not supported");
-}
-
-uint32_t NativeReferenceV2::tag() const { return _ivarData->tag; }
-
-} // end namespace native
-
-namespace {
-
-class NativeReader : public Reader {
-public:
- bool canParse(file_magic magic, const MemoryBuffer &mb) const override {
- const NativeFileHeader *const header =
- reinterpret_cast<const NativeFileHeader *>(mb.getBufferStart());
- return (memcmp(header->magic, NATIVE_FILE_HEADER_MAGIC,
- sizeof(header->magic)) == 0);
- }
-
- virtual std::error_code
- loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
- std::vector<std::unique_ptr<File>> &result) const override {
- auto *file = new lld::native::File(std::move(mb));
- result.push_back(std::unique_ptr<File>(file));
- return std::error_code();
- }
-};
-
-}
-
-void Registry::addSupportNativeObjects() {
- add(std::unique_ptr<Reader>(new NativeReader()));
-}
-
-} // end namespace lld
diff --git a/lld/lib/ReaderWriter/Native/WriterNative.cpp b/lld/lib/ReaderWriter/Native/WriterNative.cpp
deleted file mode 100644
index dbaeea2f2fb..00000000000
--- a/lld/lib/ReaderWriter/Native/WriterNative.cpp
+++ /dev/null
@@ -1,566 +0,0 @@
-//===- lib/ReaderWriter/Native/WriterNative.cpp ---------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "NativeFileFormat.h"
-#include "lld/Core/File.h"
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/Writer.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cstdint>
-#include <set>
-#include <system_error>
-#include <vector>
-
-namespace lld {
-namespace native {
-
-///
-/// Class for writing native object files.
-///
-class Writer : public lld::Writer {
-public:
- std::error_code writeFile(const lld::File &file, StringRef outPath) override {
- // reserve first byte for unnamed atoms
- _stringPool.push_back('\0');
- // visit all atoms
- for ( const DefinedAtom *defAtom : file.defined() ) {
- this->addIVarsForDefinedAtom(*defAtom);
- // We are trying to process all atoms, but the defined() iterator does not
- // return group children. So, when a group parent is found, we need to
- // handle each child atom.
- if (defAtom->isGroupParent()) {
- for (const Reference *r : *defAtom) {
- if (r->kindNamespace() != lld::Reference::KindNamespace::all)
- continue;
- if (r->kindValue() == lld::Reference::kindGroupChild) {
- const DefinedAtom *target = dyn_cast<DefinedAtom>(r->target());
- assert(target && "Internal Error: kindGroupChild references need "
- "to be associated with Defined Atoms only");
- this->addIVarsForDefinedAtom(*target);
- }
- }
- }
- }
- for ( const UndefinedAtom *undefAtom : file.undefined() ) {
- this->addIVarsForUndefinedAtom(*undefAtom);
- }
- for ( const SharedLibraryAtom *shlibAtom : file.sharedLibrary() ) {
- this->addIVarsForSharedLibraryAtom(*shlibAtom);
- }
- for ( const AbsoluteAtom *absAtom : file.absolute() ) {
- this->addIVarsForAbsoluteAtom(*absAtom);
- }
-
- maybeConvertReferencesToV1();
-
- // construct file header based on atom information accumulated
- this->makeHeader();
-
- std::error_code ec;
- llvm::raw_fd_ostream out(outPath, ec, llvm::sys::fs::F_None);
- if (ec)
- return ec;
-
- this->write(out);
-
- return std::error_code();
- }
-
- virtual ~Writer() {
- }
-
-private:
-
- // write the lld::File in native format to the specified stream
- void write(raw_ostream &out) {
- assert(out.tell() == 0);
- out.write((char*)_headerBuffer, _headerBufferSize);
-
- writeChunk(out, _definedAtomIvars, NCS_DefinedAtomsV1);
- writeChunk(out, _attributes, NCS_AttributesArrayV1);
- writeChunk(out, _undefinedAtomIvars, NCS_UndefinedAtomsV1);
- writeChunk(out, _sharedLibraryAtomIvars, NCS_SharedLibraryAtomsV1);
- writeChunk(out, _absoluteAtomIvars, NCS_AbsoluteAtomsV1);
- writeChunk(out, _absAttributes, NCS_AbsoluteAttributesV1);
- writeChunk(out, _stringPool, NCS_Strings);
- writeChunk(out, _referencesV1, NCS_ReferencesArrayV1);
- writeChunk(out, _referencesV2, NCS_ReferencesArrayV2);
-
- if (!_targetsTableIndex.empty()) {
- assert(out.tell() == findChunk(NCS_TargetsTable).fileOffset);
- writeTargetTable(out);
- }
-
- if (!_addendsTableIndex.empty()) {
- assert(out.tell() == findChunk(NCS_AddendsTable).fileOffset);
- writeAddendTable(out);
- }
-
- writeChunk(out, _contentPool, NCS_Content);
- }
-
- template<class T>
- void writeChunk(raw_ostream &out, std::vector<T> &vector, uint32_t signature) {
- if (vector.empty())
- return;
- assert(out.tell() == findChunk(signature).fileOffset);
- out.write((char*)&vector[0], vector.size() * sizeof(T));
- }
-
- void addIVarsForDefinedAtom(const DefinedAtom& atom) {
- _definedAtomIndex[&atom] = _definedAtomIvars.size();
- NativeDefinedAtomIvarsV1 ivar;
- unsigned refsCount;
- ivar.nameOffset = getNameOffset(atom);
- ivar.attributesOffset = getAttributeOffset(atom);
- ivar.referencesStartIndex = getReferencesIndex(atom, refsCount);
- ivar.referencesCount = refsCount;
- ivar.contentOffset = getContentOffset(atom);
- ivar.contentSize = atom.size();
- ivar.sectionSize = atom.sectionSize();
- _definedAtomIvars.push_back(ivar);
- }
-
- void addIVarsForUndefinedAtom(const UndefinedAtom& atom) {
- _undefinedAtomIndex[&atom] = _undefinedAtomIvars.size();
- NativeUndefinedAtomIvarsV1 ivar;
- ivar.nameOffset = getNameOffset(atom);
- ivar.flags = (atom.canBeNull() & 0x03);
- ivar.fallbackNameOffset = 0;
- if (atom.fallback())
- ivar.fallbackNameOffset = getNameOffset(*atom.fallback());
- _undefinedAtomIvars.push_back(ivar);
- }
-
- void addIVarsForSharedLibraryAtom(const SharedLibraryAtom& atom) {
- _sharedLibraryAtomIndex[&atom] = _sharedLibraryAtomIvars.size();
- NativeSharedLibraryAtomIvarsV1 ivar;
- ivar.size = atom.size();
- ivar.nameOffset = getNameOffset(atom);
- ivar.loadNameOffset = getSharedLibraryNameOffset(atom.loadName());
- ivar.type = (uint32_t)atom.type();
- ivar.flags = atom.canBeNullAtRuntime();
- _sharedLibraryAtomIvars.push_back(ivar);
- }
-
- void addIVarsForAbsoluteAtom(const AbsoluteAtom& atom) {
- _absoluteAtomIndex[&atom] = _absoluteAtomIvars.size();
- NativeAbsoluteAtomIvarsV1 ivar;
- ivar.nameOffset = getNameOffset(atom);
- ivar.attributesOffset = getAttributeOffset(atom);
- ivar.reserved = 0;
- ivar.value = atom.value();
- _absoluteAtomIvars.push_back(ivar);
- }
-
- void convertReferencesToV1() {
- for (const NativeReferenceIvarsV2 &v2 : _referencesV2) {
- NativeReferenceIvarsV1 v1;
- v1.offsetInAtom = v2.offsetInAtom;
- v1.kindNamespace = v2.kindNamespace;
- v1.kindArch = v2.kindArch;
- v1.kindValue = v2.kindValue;
- v1.targetIndex = (v2.targetIndex == NativeReferenceIvarsV2::noTarget) ?
- (uint16_t)NativeReferenceIvarsV1::noTarget : v2.targetIndex;
- v1.addendIndex = this->getAddendIndex(v2.addend);
- _referencesV1.push_back(v1);
- }
- _referencesV2.clear();
- }
-
- bool canConvertReferenceToV1(const NativeReferenceIvarsV2 &ref) {
- bool validOffset = (ref.offsetInAtom == NativeReferenceIvarsV2::noTarget) ||
- ref.offsetInAtom < NativeReferenceIvarsV1::noTarget;
- return validOffset && ref.targetIndex < UINT16_MAX;
- }
-
- // Convert vector of NativeReferenceIvarsV2 to NativeReferenceIvarsV1 if
- // possible.
- void maybeConvertReferencesToV1() {
- std::set<int64_t> addends;
- for (const NativeReferenceIvarsV2 &ref : _referencesV2) {
- if (!canConvertReferenceToV1(ref))
- return;
- addends.insert(ref.addend);
- if (addends.size() >= UINT16_MAX)
- return;
- }
- convertReferencesToV1();
- }
-
- // fill out native file header and chunk directory
- void makeHeader() {
- const bool hasDefines = !_definedAtomIvars.empty();
- const bool hasUndefines = !_undefinedAtomIvars.empty();
- const bool hasSharedLibraries = !_sharedLibraryAtomIvars.empty();
- const bool hasAbsolutes = !_absoluteAtomIvars.empty();
- const bool hasReferencesV1 = !_referencesV1.empty();
- const bool hasReferencesV2 = !_referencesV2.empty();
- const bool hasTargetsTable = !_targetsTableIndex.empty();
- const bool hasAddendTable = !_addendsTableIndex.empty();
- const bool hasContent = !_contentPool.empty();
-
- int chunkCount = 1; // always have string pool chunk
- if ( hasDefines ) chunkCount += 2;
- if ( hasUndefines ) ++chunkCount;
- if ( hasSharedLibraries ) ++chunkCount;
- if ( hasAbsolutes ) chunkCount += 2;
- if ( hasReferencesV1 ) ++chunkCount;
- if ( hasReferencesV2 ) ++chunkCount;
- if ( hasTargetsTable ) ++chunkCount;
- if ( hasAddendTable ) ++chunkCount;
- if ( hasContent ) ++chunkCount;
-
- _headerBufferSize = sizeof(NativeFileHeader)
- + chunkCount*sizeof(NativeChunk);
- _headerBuffer = reinterpret_cast<NativeFileHeader*>
- (operator new(_headerBufferSize, std::nothrow));
- NativeChunk *chunks =
- reinterpret_cast<NativeChunk*>(reinterpret_cast<char*>(_headerBuffer)
- + sizeof(NativeFileHeader));
- memcpy(_headerBuffer->magic, NATIVE_FILE_HEADER_MAGIC,
- sizeof(_headerBuffer->magic));
- _headerBuffer->endian = NFH_LittleEndian;
- _headerBuffer->architecture = 0;
- _headerBuffer->fileSize = 0;
- _headerBuffer->chunkCount = chunkCount;
-
- // create chunk for defined atom ivar array
- int nextIndex = 0;
- uint32_t nextFileOffset = _headerBufferSize;
- if (hasDefines) {
- fillChunkHeader(chunks[nextIndex++], nextFileOffset, _definedAtomIvars,
- NCS_DefinedAtomsV1);
-
- // create chunk for attributes
- fillChunkHeader(chunks[nextIndex++], nextFileOffset, _attributes,
- NCS_AttributesArrayV1);
- }
-
- // create chunk for undefined atom array
- if (hasUndefines)
- fillChunkHeader(chunks[nextIndex++], nextFileOffset, _undefinedAtomIvars,
- NCS_UndefinedAtomsV1);
-
- // create chunk for shared library atom array
- if (hasSharedLibraries)
- fillChunkHeader(chunks[nextIndex++], nextFileOffset,
- _sharedLibraryAtomIvars, NCS_SharedLibraryAtomsV1);
-
- // create chunk for shared library atom array
- if (hasAbsolutes) {
- fillChunkHeader(chunks[nextIndex++], nextFileOffset, _absoluteAtomIvars,
- NCS_AbsoluteAtomsV1);
-
- // create chunk for attributes
- fillChunkHeader(chunks[nextIndex++], nextFileOffset, _absAttributes,
- NCS_AbsoluteAttributesV1);
- }
-
- // create chunk for symbol strings
- // pad end of string pool to 4-bytes
- while ((_stringPool.size() % 4) != 0)
- _stringPool.push_back('\0');
- fillChunkHeader(chunks[nextIndex++], nextFileOffset, _stringPool,
- NCS_Strings);
-
- // create chunk for referencesV2
- if (hasReferencesV1)
- fillChunkHeader(chunks[nextIndex++], nextFileOffset, _referencesV1,
- NCS_ReferencesArrayV1);
-
- // create chunk for referencesV2
- if (hasReferencesV2)
- fillChunkHeader(chunks[nextIndex++], nextFileOffset, _referencesV2,
- NCS_ReferencesArrayV2);
-
- // create chunk for target table
- if (hasTargetsTable) {
- NativeChunk& cht = chunks[nextIndex++];
- cht.signature = NCS_TargetsTable;
- cht.fileOffset = nextFileOffset;
- cht.fileSize = _targetsTableIndex.size() * sizeof(uint32_t);
- cht.elementCount = _targetsTableIndex.size();
- nextFileOffset = cht.fileOffset + cht.fileSize;
- }
-
- // create chunk for addend table
- if (hasAddendTable) {
- NativeChunk& chad = chunks[nextIndex++];
- chad.signature = NCS_AddendsTable;
- chad.fileOffset = nextFileOffset;
- chad.fileSize = _addendsTableIndex.size() * sizeof(Reference::Addend);
- chad.elementCount = _addendsTableIndex.size();
- nextFileOffset = chad.fileOffset + chad.fileSize;
- }
-
- // create chunk for content
- if (hasContent)
- fillChunkHeader(chunks[nextIndex++], nextFileOffset, _contentPool,
- NCS_Content);
-
- _headerBuffer->fileSize = nextFileOffset;
- }
-
- template<class T>
- void fillChunkHeader(NativeChunk &chunk, uint32_t &nextFileOffset,
- const std::vector<T> &data, uint32_t signature) {
- chunk.signature = signature;
- chunk.fileOffset = nextFileOffset;
- chunk.fileSize = data.size() * sizeof(T);
- chunk.elementCount = data.size();
- nextFileOffset = chunk.fileOffset + chunk.fileSize;
- }
-
- // scan header to find particular chunk
- NativeChunk& findChunk(uint32_t signature) {
- const uint32_t chunkCount = _headerBuffer->chunkCount;
- NativeChunk* chunks =
- reinterpret_cast<NativeChunk*>(reinterpret_cast<char*>(_headerBuffer)
- + sizeof(NativeFileHeader));
- for (uint32_t i=0; i < chunkCount; ++i) {
- if ( chunks[i].signature == signature )
- return chunks[i];
- }
- llvm_unreachable("findChunk() signature not found");
- }
-
- // append atom name to string pool and return offset
- uint32_t getNameOffset(const Atom& atom) {
- return this->getNameOffset(atom.name());
- }
-
- // check if name is already in pool or append and return offset
- uint32_t getSharedLibraryNameOffset(StringRef name) {
- assert(!name.empty());
- // look to see if this library name was used by another atom
- for (auto &it : _sharedLibraryNames)
- if (name.equals(it.first))
- return it.second;
- // first use of this library name
- uint32_t result = this->getNameOffset(name);
- _sharedLibraryNames.push_back(std::make_pair(name, result));
- return result;
- }
-
- // append atom name to string pool and return offset
- uint32_t getNameOffset(StringRef name) {
- if ( name.empty() )
- return 0;
- uint32_t result = _stringPool.size();
- _stringPool.insert(_stringPool.end(), name.begin(), name.end());
- _stringPool.push_back(0);
- return result;
- }
-
- // append atom cotent to content pool and return offset
- uint32_t getContentOffset(const DefinedAtom& atom) {
- if (!atom.occupiesDiskSpace())
- return 0;
- uint32_t result = _contentPool.size();
- ArrayRef<uint8_t> cont = atom.rawContent();
- _contentPool.insert(_contentPool.end(), cont.begin(), cont.end());
- return result;
- }
-
- // reuse existing attributes entry or create a new one and return offet
- uint32_t getAttributeOffset(const DefinedAtom& atom) {
- NativeAtomAttributesV1 attrs = computeAttributesV1(atom);
- return getOrPushAttribute(_attributes, attrs);
- }
-
- uint32_t getAttributeOffset(const AbsoluteAtom& atom) {
- NativeAtomAttributesV1 attrs = computeAbsoluteAttributes(atom);
- return getOrPushAttribute(_absAttributes, attrs);
- }
-
- uint32_t getOrPushAttribute(std::vector<NativeAtomAttributesV1> &dest,
- const NativeAtomAttributesV1 &attrs) {
- for (size_t i = 0, e = dest.size(); i < e; ++i) {
- if (!memcmp(&dest[i], &attrs, sizeof(attrs))) {
- // found that this set of attributes already used, so re-use
- return i * sizeof(attrs);
- }
- }
- // append new attribute set to end
- uint32_t result = dest.size() * sizeof(attrs);
- dest.push_back(attrs);
- return result;
- }
-
- uint32_t sectionNameOffset(const DefinedAtom& atom) {
- // if section based on content, then no custom section name available
- if (atom.sectionChoice() == DefinedAtom::sectionBasedOnContent)
- return 0;
- StringRef name = atom.customSectionName();
- assert(!name.empty());
- // look to see if this section name was used by another atom
- for (auto &it : _sectionNames)
- if (name.equals(it.first))
- return it.second;
- // first use of this section name
- uint32_t result = this->getNameOffset(name);
- _sectionNames.push_back(std::make_pair(name, result));
- return result;
- }
-
- NativeAtomAttributesV1 computeAttributesV1(const DefinedAtom& atom) {
- NativeAtomAttributesV1 attrs;
- attrs.sectionNameOffset = sectionNameOffset(atom);
- attrs.align = atom.alignment().value;
- attrs.alignModulus = atom.alignment().modulus;
- attrs.scope = atom.scope();
- attrs.interposable = atom.interposable();
- attrs.merge = atom.merge();
- attrs.contentType = atom.contentType();
- attrs.sectionChoice = atom.sectionChoice();
- attrs.deadStrip = atom.deadStrip();
- attrs.dynamicExport = atom.dynamicExport();
- attrs.codeModel = atom.codeModel();
- attrs.permissions = atom.permissions();
- return attrs;
- }
-
- NativeAtomAttributesV1 computeAbsoluteAttributes(const AbsoluteAtom& atom) {
- NativeAtomAttributesV1 attrs;
- attrs.scope = atom.scope();
- return attrs;
- }
-
- // add references for this atom in a contiguous block in NCS_ReferencesArrayV2
- uint32_t getReferencesIndex(const DefinedAtom& atom, unsigned& refsCount) {
- size_t startRefSize = _referencesV2.size();
- uint32_t result = startRefSize;
- for (const Reference *ref : atom) {
- NativeReferenceIvarsV2 nref;
- nref.offsetInAtom = ref->offsetInAtom();
- nref.kindNamespace = (uint8_t)ref->kindNamespace();
- nref.kindArch = (uint8_t)ref->kindArch();
- nref.kindValue = ref->kindValue();
- nref.targetIndex = this->getTargetIndex(ref->target());
- nref.addend = ref->addend();
- nref.tag = ref->tag();
- _referencesV2.push_back(nref);
- }
- refsCount = _referencesV2.size() - startRefSize;
- return (refsCount == 0) ? 0 : result;
- }
-
- uint32_t getTargetIndex(const Atom* target) {
- if ( target == nullptr )
- return NativeReferenceIvarsV2::noTarget;
- TargetToIndex::const_iterator pos = _targetsTableIndex.find(target);
- if ( pos != _targetsTableIndex.end() ) {
- return pos->second;
- }
- uint32_t result = _targetsTableIndex.size();
- _targetsTableIndex[target] = result;
- return result;
- }
-
- void writeTargetTable(raw_ostream &out) {
- // Build table of target indexes
- uint32_t maxTargetIndex = _targetsTableIndex.size();
- assert(maxTargetIndex > 0);
- std::vector<uint32_t> targetIndexes(maxTargetIndex);
- for (auto &it : _targetsTableIndex) {
- const Atom* atom = it.first;
- uint32_t targetIndex = it.second;
- assert(targetIndex < maxTargetIndex);
-
- TargetToIndex::iterator pos = _definedAtomIndex.find(atom);
- if (pos != _definedAtomIndex.end()) {
- targetIndexes[targetIndex] = pos->second;
- continue;
- }
- uint32_t base = _definedAtomIvars.size();
-
- pos = _undefinedAtomIndex.find(atom);
- if (pos != _undefinedAtomIndex.end()) {
- targetIndexes[targetIndex] = pos->second + base;
- continue;
- }
- base += _undefinedAtomIndex.size();
-
- pos = _sharedLibraryAtomIndex.find(atom);
- if (pos != _sharedLibraryAtomIndex.end()) {
- targetIndexes[targetIndex] = pos->second + base;
- continue;
- }
- base += _sharedLibraryAtomIndex.size();
-
- pos = _absoluteAtomIndex.find(atom);
- assert(pos != _absoluteAtomIndex.end());
- targetIndexes[targetIndex] = pos->second + base;
- }
- // write table
- out.write((char*)&targetIndexes[0], maxTargetIndex * sizeof(uint32_t));
- }
-
- uint32_t getAddendIndex(Reference::Addend addend) {
- if ( addend == 0 )
- return 0; // addend index zero is used to mean "no addend"
- AddendToIndex::const_iterator pos = _addendsTableIndex.find(addend);
- if ( pos != _addendsTableIndex.end() ) {
- return pos->second;
- }
- uint32_t result = _addendsTableIndex.size() + 1; // one-based index
- _addendsTableIndex[addend] = result;
- return result;
- }
-
- void writeAddendTable(raw_ostream &out) {
- // Build table of addends
- uint32_t maxAddendIndex = _addendsTableIndex.size();
- std::vector<Reference::Addend> addends(maxAddendIndex);
- for (auto &it : _addendsTableIndex) {
- Reference::Addend addend = it.first;
- uint32_t index = it.second;
- assert(index <= maxAddendIndex);
- addends[index-1] = addend;
- }
- // write table
- out.write((char*)&addends[0], maxAddendIndex*sizeof(Reference::Addend));
- }
-
- typedef std::vector<std::pair<StringRef, uint32_t>> NameToOffsetVector;
-
- typedef llvm::DenseMap<const Atom*, uint32_t> TargetToIndex;
- typedef llvm::DenseMap<Reference::Addend, uint32_t> AddendToIndex;
-
- NativeFileHeader* _headerBuffer;
- size_t _headerBufferSize;
- std::vector<char> _stringPool;
- std::vector<uint8_t> _contentPool;
- std::vector<NativeDefinedAtomIvarsV1> _definedAtomIvars;
- std::vector<NativeAtomAttributesV1> _attributes;
- std::vector<NativeAtomAttributesV1> _absAttributes;
- std::vector<NativeUndefinedAtomIvarsV1> _undefinedAtomIvars;
- std::vector<NativeSharedLibraryAtomIvarsV1> _sharedLibraryAtomIvars;
- std::vector<NativeAbsoluteAtomIvarsV1> _absoluteAtomIvars;
- std::vector<NativeReferenceIvarsV1> _referencesV1;
- std::vector<NativeReferenceIvarsV2> _referencesV2;
- TargetToIndex _targetsTableIndex;
- TargetToIndex _definedAtomIndex;
- TargetToIndex _undefinedAtomIndex;
- TargetToIndex _sharedLibraryAtomIndex;
- TargetToIndex _absoluteAtomIndex;
- AddendToIndex _addendsTableIndex;
- NameToOffsetVector _sectionNames;
- NameToOffsetVector _sharedLibraryNames;
-};
-} // end namespace native
-
-std::unique_ptr<Writer> createWriterNative() {
- return std::unique_ptr<Writer>(new native::Writer());
-}
-} // end namespace lld
diff --git a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
index da822dc361f..f7c9c7e8ea5 100644
--- a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
+++ b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
@@ -312,11 +312,10 @@ std::error_code FileCOFF::doParse() {
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;
+ return make_dynamic_error_code(Twine("module machine type '") +
+ getMachineName(getMachineType()) +
+ "' conflicts with target machine type '" +
+ getMachineName(_ctx.getMachineType()) + "'");
}
if (std::error_code ec = getReferenceArch(_referenceArch))
diff --git a/lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp b/lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp
index e88ed057e80..7ae3096ac5e 100644
--- a/lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp
+++ b/lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp
@@ -257,7 +257,7 @@ public:
// Check if the total size is valid.
if (std::size_t(end - buf) != sizeof(COFF::ImportHeader) + dataSize)
- return make_error_code(NativeReaderError::unknown_file_format);
+ return make_dynamic_error_code(StringRef("Broken import library"));
uint16_t hint = read16le(buf + offsetof(COFF::ImportHeader, OrdinalHint));
StringRef symbolName(buf + sizeof(COFF::ImportHeader));
OpenPOWER on IntegriCloud