diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:41:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:41:05 +0000 |
commit | 01095a5d43bbfde13731688ddcf6048ebb8b7721 (patch) | |
tree | 4def12e759965de927d963ac65840d663ef9d1ea /include/llvm/Object | |
parent | f0f4822ed4b66e3579e92a89f368f8fb860e218e (diff) |
Diffstat (limited to 'include/llvm/Object')
-rw-r--r-- | include/llvm/Object/Archive.h | 58 | ||||
-rw-r--r-- | include/llvm/Object/ArchiveWriter.h | 45 | ||||
-rw-r--r-- | include/llvm/Object/Binary.h | 12 | ||||
-rw-r--r-- | include/llvm/Object/COFF.h | 142 | ||||
-rw-r--r-- | include/llvm/Object/COFFYAML.h | 223 | ||||
-rw-r--r-- | include/llvm/Object/ELF.h | 78 | ||||
-rw-r--r-- | include/llvm/Object/ELFObjectFile.h | 146 | ||||
-rw-r--r-- | include/llvm/Object/ELFTypes.h | 89 | ||||
-rw-r--r-- | include/llvm/Object/ELFYAML.h | 319 | ||||
-rw-r--r-- | include/llvm/Object/Error.h | 47 | ||||
-rw-r--r-- | include/llvm/Object/FunctionIndexObjectFile.h | 110 | ||||
-rw-r--r-- | include/llvm/Object/IRObjectFile.h | 10 | ||||
-rw-r--r-- | include/llvm/Object/MachO.h | 30 | ||||
-rw-r--r-- | include/llvm/Object/MachOUniversal.h | 70 | ||||
-rw-r--r-- | include/llvm/Object/ModuleSummaryIndexObjectFile.h | 103 | ||||
-rw-r--r-- | include/llvm/Object/ObjectFile.h | 48 | ||||
-rw-r--r-- | include/llvm/Object/RelocVisitor.h | 16 | ||||
-rw-r--r-- | include/llvm/Object/StackMapParser.h | 3 | ||||
-rw-r--r-- | include/llvm/Object/SymbolicFile.h | 9 |
19 files changed, 677 insertions, 881 deletions
diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h index 8dd042a2533fe..cfba2567371ac 100644 --- a/include/llvm/Object/Archive.h +++ b/include/llvm/Object/Archive.h @@ -14,6 +14,7 @@ #ifndef LLVM_OBJECT_ARCHIVE_H #define LLVM_OBJECT_ARCHIVE_H +#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Object/Binary.h" @@ -42,7 +43,7 @@ struct ArchiveMemberHeader { sys::fs::perms getAccessMode() const; sys::TimeValue getLastModified() const; llvm::StringRef getRawLastModified() const { - return StringRef(LastModified, sizeof(LastModified)).rtrim(" "); + return StringRef(LastModified, sizeof(LastModified)).rtrim(' '); } unsigned getUID() const; unsigned getGID() const; @@ -78,6 +79,7 @@ public: ErrorOr<Child> getNext() const; ErrorOr<StringRef> getName() const; + ErrorOr<std::string> getFullName() const; StringRef getRawName() const { return getHeader()->getName(); } sys::TimeValue getLastModified() const { return getHeader()->getLastModified(); @@ -100,26 +102,25 @@ public: ErrorOr<MemoryBufferRef> getMemoryBufferRef() const; - ErrorOr<std::unique_ptr<Binary>> + Expected<std::unique_ptr<Binary>> getAsBinary(LLVMContext *Context = nullptr) const; }; class child_iterator { - ErrorOr<Child> child; + Child C; + Error *E; public: - child_iterator() : child(Child(nullptr, nullptr, nullptr)) {} - child_iterator(const Child &c) : child(c) {} - child_iterator(std::error_code EC) : child(EC) {} - const ErrorOr<Child> *operator->() const { return &child; } - const ErrorOr<Child> &operator*() const { return child; } + child_iterator() : C(Child(nullptr, nullptr, nullptr)), E(nullptr) {} + child_iterator(const Child &C, Error *E) : C(C), E(E) {} + const Child *operator->() const { return &C; } + const Child &operator*() const { return C; } bool operator==(const child_iterator &other) const { - // We ignore error states so that comparisions with end() work, which - // allows range loops. - if (child.getError() || other.child.getError()) - return false; - return *child == *other.child; + // Ignore errors here: If an error occurred during increment then getNext + // will have been set to child_end(), and the following comparison should + // do the right thing. + return C == other.C; } bool operator!=(const child_iterator &other) const { @@ -129,8 +130,15 @@ public: // Code in loops with child_iterators must check for errors on each loop // iteration. And if there is an error break out of the loop. child_iterator &operator++() { // Preincrement - assert(child && "Can't increment iterator with error"); - child = child->getNext(); + assert(E && "Can't increment iterator with no Error attached"); + if (auto ChildOrErr = C.getNext()) + C = *ChildOrErr; + else { + ErrorAsOutParameter ErrAsOutParam(*E); + C = C.getParent()->child_end().C; + *E = errorCodeToError(ChildOrErr.getError()); + E = nullptr; + } return *this; } }; @@ -175,23 +183,25 @@ public: } }; - Archive(MemoryBufferRef Source, std::error_code &EC); - static ErrorOr<std::unique_ptr<Archive>> create(MemoryBufferRef Source); + Archive(MemoryBufferRef Source, Error &Err); + static Expected<std::unique_ptr<Archive>> create(MemoryBufferRef Source); enum Kind { K_GNU, K_MIPS64, K_BSD, + K_DARWIN64, K_COFF }; Kind kind() const { return (Kind)Format; } bool isThin() const { return IsThin; } - child_iterator child_begin(bool SkipInternal = true) const; + child_iterator child_begin(Error &Err, bool SkipInternal = true) const; child_iterator child_end() const; - iterator_range<child_iterator> children(bool SkipInternal = true) const { - return make_range(child_begin(SkipInternal), child_end()); + iterator_range<child_iterator> children(Error &Err, + bool SkipInternal = true) const { + return make_range(child_begin(Err, SkipInternal), child_end()); } symbol_iterator symbol_begin() const; @@ -206,12 +216,16 @@ public: } // check if a symbol is in the archive - child_iterator findSym(StringRef name) const; + Expected<Optional<Child>> findSym(StringRef name) const; bool hasSymbolTable() const; StringRef getSymbolTable() const { return SymbolTable; } uint32_t getNumberOfSymbols() const; + std::vector<std::unique_ptr<MemoryBuffer>> takeThinBuffers() { + return std::move(ThinBuffers); + } + private: StringRef SymbolTable; StringRef StringTable; @@ -220,7 +234,7 @@ private: uint16_t FirstRegularStartOfFile = -1; void setFirstRegular(const Child &C); - unsigned Format : 2; + unsigned Format : 3; unsigned IsThin : 1; mutable std::vector<std::unique_ptr<MemoryBuffer>> ThinBuffers; }; diff --git a/include/llvm/Object/ArchiveWriter.h b/include/llvm/Object/ArchiveWriter.h index b5d2ba3580809..55b58fac4f66b 100644 --- a/include/llvm/Object/ArchiveWriter.h +++ b/include/llvm/Object/ArchiveWriter.h @@ -20,29 +20,36 @@ namespace llvm { -class NewArchiveIterator { - bool IsNewMember; - StringRef Name; - - object::Archive::Child OldMember; - -public: - NewArchiveIterator(const object::Archive::Child &OldMember, StringRef Name); - NewArchiveIterator(StringRef FileName); - bool isNewMember() const; - StringRef getName() const; - - const object::Archive::Child &getOld() const; - - StringRef getNew() const; - llvm::ErrorOr<int> getFD(sys::fs::file_status &NewStatus) const; - const sys::fs::file_status &getStatus() const; +struct NewArchiveMember { + std::unique_ptr<MemoryBuffer> Buf; + sys::TimeValue ModTime = sys::TimeValue::PosixZeroTime(); + unsigned UID = 0, GID = 0, Perms = 0644; + + NewArchiveMember() = default; + NewArchiveMember(NewArchiveMember &&Other) + : Buf(std::move(Other.Buf)), ModTime(Other.ModTime), UID(Other.UID), + GID(Other.GID), Perms(Other.Perms) {} + NewArchiveMember &operator=(NewArchiveMember &&Other) { + Buf = std::move(Other.Buf); + ModTime = Other.ModTime; + UID = Other.UID; + GID = Other.GID; + Perms = Other.Perms; + return *this; + } + NewArchiveMember(MemoryBufferRef BufRef); + + static Expected<NewArchiveMember> + getOldMember(const object::Archive::Child &OldMember, bool Deterministic); + + static Expected<NewArchiveMember> getFile(StringRef FileName, + bool Deterministic); }; std::pair<StringRef, std::error_code> -writeArchive(StringRef ArcName, std::vector<NewArchiveIterator> &NewMembers, +writeArchive(StringRef ArcName, std::vector<NewArchiveMember> &NewMembers, bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic, - bool Thin); + bool Thin, std::unique_ptr<MemoryBuffer> OldArchiveBuf = nullptr); } #endif diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index a0d1127781f64..5dff5406fcddc 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -42,8 +42,8 @@ protected: ID_Archive, ID_MachOUniversalBinary, ID_COFFImportFile, - ID_IR, // LLVM IR - ID_FunctionIndex, // Function summary index + ID_IR, // LLVM IR + ID_ModuleSummaryIndex, // Module summary index // Object and children. ID_StartObjects, @@ -123,7 +123,7 @@ public: return TypeID == ID_IR; } - bool isFunctionIndex() const { return TypeID == ID_FunctionIndex; } + bool isModuleSummaryIndex() const { return TypeID == ID_ModuleSummaryIndex; } bool isLittleEndian() const { return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B || @@ -134,8 +134,8 @@ public: /// @brief Create a Binary from Source, autodetecting the file type. /// /// @param Source The data to create the Binary from. -ErrorOr<std::unique_ptr<Binary>> createBinary(MemoryBufferRef Source, - LLVMContext *Context = nullptr); +Expected<std::unique_ptr<Binary>> createBinary(MemoryBufferRef Source, + LLVMContext *Context = nullptr); template <typename T> class OwningBinary { std::unique_ptr<T> Bin; @@ -185,7 +185,7 @@ template <typename T> const T* OwningBinary<T>::getBinary() const { return Bin.get(); } -ErrorOr<OwningBinary<Binary>> createBinary(StringRef Path); +Expected<OwningBinary<Binary>> createBinary(StringRef Path); } } diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index 3e69c3e6e5d4f..dcc58b06e228d 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -169,6 +169,26 @@ struct import_directory_table_entry { support::ulittle32_t ImportAddressTableRVA; }; +struct debug_directory { + support::ulittle32_t Characteristics; + support::ulittle32_t TimeDateStamp; + support::ulittle16_t MajorVersion; + support::ulittle16_t MinorVersion; + support::ulittle32_t Type; + support::ulittle32_t SizeOfData; + support::ulittle32_t AddressOfRawData; + support::ulittle32_t PointerToRawData; +}; + +/// Information that is resent in debug_directory::AddressOfRawData if Type is +/// IMAGE_DEBUG_TYPE_CODEVIEW. +struct debug_pdb_info { + support::ulittle32_t Signature; + uint8_t Guid[16]; + support::ulittle32_t Age; + // PDBFileName: The null-terminated PDB file name follows. +}; + template <typename IntTy> struct import_lookup_table_entry { IntTy Data; @@ -414,6 +434,18 @@ struct coff_section { return (Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) && NumberOfRelocations == UINT16_MAX; } + uint32_t getAlignment() const { + // The IMAGE_SCN_TYPE_NO_PAD bit is a legacy way of getting to + // IMAGE_SCN_ALIGN_1BYTES. + if (Characteristics & COFF::IMAGE_SCN_TYPE_NO_PAD) + return 1; + + // Bit [20:24] contains section alignment. Both 0 and 1 mean alignment 1. + uint32_t Shift = (Characteristics >> 20) & 0xF; + if (Shift > 0) + return 1U << (Shift - 1); + return 1; + } }; struct coff_relocation { @@ -427,20 +459,32 @@ struct coff_aux_function_definition { support::ulittle32_t TotalSize; support::ulittle32_t PointerToLinenumber; support::ulittle32_t PointerToNextFunction; + char Unused1[2]; }; +static_assert(sizeof(coff_aux_function_definition) == 18, + "auxiliary entry must be 18 bytes"); + struct coff_aux_bf_and_ef_symbol { char Unused1[4]; support::ulittle16_t Linenumber; char Unused2[6]; support::ulittle32_t PointerToNextFunction; + char Unused3[2]; }; +static_assert(sizeof(coff_aux_bf_and_ef_symbol) == 18, + "auxiliary entry must be 18 bytes"); + struct coff_aux_weak_external { support::ulittle32_t TagIndex; support::ulittle32_t Characteristics; + char Unused1[10]; }; +static_assert(sizeof(coff_aux_weak_external) == 18, + "auxiliary entry must be 18 bytes"); + struct coff_aux_section_definition { support::ulittle32_t Length; support::ulittle16_t NumberOfRelocations; @@ -458,12 +502,19 @@ struct coff_aux_section_definition { } }; +static_assert(sizeof(coff_aux_section_definition) == 18, + "auxiliary entry must be 18 bytes"); + struct coff_aux_clr_token { uint8_t AuxType; uint8_t Reserved; support::ulittle32_t SymbolTableIndex; + char MBZ[12]; }; +static_assert(sizeof(coff_aux_clr_token) == 18, + "auxiliary entry must be 18 bytes"); + struct coff_import_header { support::ulittle16_t Sig1; support::ulittle16_t Sig2; @@ -485,6 +536,26 @@ struct coff_import_directory_table_entry { support::ulittle32_t ImportAddressTableRVA; }; +template <typename IntTy> +struct coff_tls_directory { + IntTy StartAddressOfRawData; + IntTy EndAddressOfRawData; + IntTy AddressOfIndex; + IntTy AddressOfCallBacks; + support::ulittle32_t SizeOfZeroFill; + support::ulittle32_t Characteristics; + uint32_t getAlignment() const { + // Bit [20:24] contains section alignment. + uint32_t Shift = (Characteristics & 0x00F00000) >> 20; + if (Shift > 0) + return 1U << (Shift - 1); + return 0; + } +}; + +typedef coff_tls_directory<support::little32_t> coff_tls_directory32; +typedef coff_tls_directory<support::little64_t> coff_tls_directory64; + struct coff_load_configuration32 { support::ulittle32_t Characteristics; support::ulittle32_t TimeDateStamp; @@ -563,12 +634,13 @@ private: const char *StringTable; uint32_t StringTableSize; const import_directory_table_entry *ImportDirectory; - uint32_t NumberOfImportDirectory; const delay_import_directory_table_entry *DelayImportDirectory; uint32_t NumberOfDelayImportDirectory; const export_directory_table_entry *ExportDirectory; const coff_base_reloc_block_header *BaseRelocHeader; const coff_base_reloc_block_header *BaseRelocEnd; + const debug_directory *DebugDirectoryBegin; + const debug_directory *DebugDirectoryEnd; std::error_code getString(uint32_t offset, StringRef &Res) const; @@ -582,6 +654,7 @@ private: std::error_code initDelayImportTablePtr(); std::error_code initExportTablePtr(); std::error_code initBaseRelocPtr(); + std::error_code initDebugDirectoryPtr(); public: uintptr_t getSymbolTable() const { @@ -647,13 +720,13 @@ public: } protected: void moveSymbolNext(DataRefImpl &Symb) const override; - ErrorOr<StringRef> getSymbolName(DataRefImpl Symb) const override; - ErrorOr<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; + Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; + Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; - SymbolRef::Type getSymbolType(DataRefImpl Symb) const override; - ErrorOr<section_iterator> getSymbolSection(DataRefImpl Symb) const override; + Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; + Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; void moveSectionNext(DataRefImpl &Sec) const override; std::error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; @@ -662,6 +735,7 @@ protected: std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; uint64_t getSectionAlignment(DataRefImpl Sec) const override; + bool isSectionCompressed(DataRefImpl Sec) const override; bool isSectionText(DataRefImpl Sec) const override; bool isSectionData(DataRefImpl Sec) const override; bool isSectionBSS(DataRefImpl Sec) const override; @@ -693,6 +767,7 @@ public: uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; unsigned getArch() const override; + SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); } import_directory_iterator import_directory_begin() const; import_directory_iterator import_directory_end() const; @@ -702,12 +777,21 @@ public: export_directory_iterator export_directory_end() const; base_reloc_iterator base_reloc_begin() const; base_reloc_iterator base_reloc_end() const; + const debug_directory *debug_directory_begin() const { + return DebugDirectoryBegin; + } + const debug_directory *debug_directory_end() const { + return DebugDirectoryEnd; + } iterator_range<import_directory_iterator> import_directories() const; iterator_range<delay_import_directory_iterator> delay_import_directories() const; iterator_range<export_directory_iterator> export_directories() const; iterator_range<base_reloc_iterator> base_relocs() const; + iterator_range<const debug_directory *> debug_directories() const { + return make_range(debug_directory_begin(), debug_directory_end()); + } const dos_header *getDOSHeader() const { if (!PE32Header && !PE32PlusHeader) @@ -776,9 +860,28 @@ public: uint64_t getImageBase() const; std::error_code getVaPtr(uint64_t VA, uintptr_t &Res) const; std::error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const; + + /// Given an RVA base and size, returns a valid array of bytes or an error + /// code if the RVA and size is not contained completely within a valid + /// section. + std::error_code getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, + ArrayRef<uint8_t> &Contents) const; + std::error_code getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const; + /// Get PDB information out of a codeview debug directory entry. + std::error_code getDebugPDBInfo(const debug_directory *DebugDir, + const debug_pdb_info *&Info, + StringRef &PDBFileName) const; + + /// Get PDB information from an executable. If the information is not present, + /// Info will be set to nullptr and PDBFileName will be empty. An error is + /// returned only on corrupt object files. Convenience accessor that can be + /// used if the debug directory is not already handy. + std::error_code getDebugPDBInfo(const debug_pdb_info *&Info, + StringRef &PDBFileName) const; + bool isRelocatableObject() const override; bool is64() const { return PE32PlusHeader; } @@ -807,9 +910,6 @@ public: std::error_code getImportTableEntry(const import_directory_table_entry *&Result) const; - std::error_code - getImportLookupEntry(const import_lookup_table_entry32 *&Result) const; - private: const import_directory_table_entry *ImportTable; uint32_t Index; @@ -881,7 +981,9 @@ public: void moveNext(); std::error_code getSymbolName(StringRef &Result) const; + std::error_code isOrdinal(bool &Result) const; std::error_code getOrdinal(uint16_t &Result) const; + std::error_code getHintNameRVA(uint32_t &Result) const; private: const import_lookup_table_entry32 *Entry32; @@ -909,6 +1011,30 @@ private: const COFFObjectFile *OwningObject; }; +// Corresponds to `_FPO_DATA` structure in the PE/COFF spec. +struct FpoData { + support::ulittle32_t Offset; // ulOffStart: Offset 1st byte of function code + support::ulittle32_t Size; // cbProcSize: # bytes in function + support::ulittle32_t NumLocals; // cdwLocals: # bytes in locals/4 + support::ulittle16_t NumParams; // cdwParams: # bytes in params/4 + support::ulittle16_t Attributes; + + // cbProlog: # bytes in prolog + int getPrologSize() const { return Attributes & 0xF; } + + // cbRegs: # regs saved + int getNumSavedRegs() const { return (Attributes >> 8) & 0x7; } + + // fHasSEH: true if seh is func + bool hasSEH() const { return (Attributes >> 9) & 1; } + + // fUseBP: true if EBP has been allocated + bool useBP() const { return (Attributes >> 10) & 1; } + + // cbFrame: frame pointer + int getFP() const { return Attributes >> 14; } +}; + } // end namespace object } // end namespace llvm diff --git a/include/llvm/Object/COFFYAML.h b/include/llvm/Object/COFFYAML.h deleted file mode 100644 index 12a25223bd37e..0000000000000 --- a/include/llvm/Object/COFFYAML.h +++ /dev/null @@ -1,223 +0,0 @@ -//===- COFFYAML.h - COFF YAMLIO implementation ------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares classes for handling the YAML representation of COFF. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_COFFYAML_H -#define LLVM_OBJECT_COFFYAML_H - -#include "llvm/ADT/Optional.h" -#include "llvm/MC/YAML.h" -#include "llvm/Support/COFF.h" - -namespace llvm { - -namespace COFF { -inline Characteristics operator|(Characteristics a, Characteristics b) { - uint32_t Ret = static_cast<uint32_t>(a) | static_cast<uint32_t>(b); - return static_cast<Characteristics>(Ret); -} - -inline SectionCharacteristics operator|(SectionCharacteristics a, - SectionCharacteristics b) { - uint32_t Ret = static_cast<uint32_t>(a) | static_cast<uint32_t>(b); - return static_cast<SectionCharacteristics>(Ret); -} - -inline DLLCharacteristics operator|(DLLCharacteristics a, - DLLCharacteristics b) { - uint16_t Ret = static_cast<uint16_t>(a) | static_cast<uint16_t>(b); - return static_cast<DLLCharacteristics>(Ret); -} -} - -// The structure of the yaml files is not an exact 1:1 match to COFF. In order -// to use yaml::IO, we use these structures which are closer to the source. -namespace COFFYAML { - LLVM_YAML_STRONG_TYPEDEF(uint8_t, COMDATType) - LLVM_YAML_STRONG_TYPEDEF(uint32_t, WeakExternalCharacteristics) - LLVM_YAML_STRONG_TYPEDEF(uint8_t, AuxSymbolType) - - struct Relocation { - uint32_t VirtualAddress; - uint16_t Type; - StringRef SymbolName; - }; - - struct Section { - COFF::section Header; - unsigned Alignment; - yaml::BinaryRef SectionData; - std::vector<Relocation> Relocations; - StringRef Name; - Section(); - }; - - struct Symbol { - COFF::symbol Header; - COFF::SymbolBaseType SimpleType; - COFF::SymbolComplexType ComplexType; - Optional<COFF::AuxiliaryFunctionDefinition> FunctionDefinition; - Optional<COFF::AuxiliarybfAndefSymbol> bfAndefSymbol; - Optional<COFF::AuxiliaryWeakExternal> WeakExternal; - StringRef File; - Optional<COFF::AuxiliarySectionDefinition> SectionDefinition; - Optional<COFF::AuxiliaryCLRToken> CLRToken; - StringRef Name; - Symbol(); - }; - - struct PEHeader { - COFF::PE32Header Header; - Optional<COFF::DataDirectory> DataDirectories[COFF::NUM_DATA_DIRECTORIES]; - }; - - struct Object { - Optional<PEHeader> OptionalHeader; - COFF::header Header; - std::vector<Section> Sections; - std::vector<Symbol> Symbols; - Object(); - }; -} -} - -LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Section) -LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Symbol) -LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Relocation) - -namespace llvm { -namespace yaml { - -template <> -struct ScalarEnumerationTraits<COFFYAML::WeakExternalCharacteristics> { - static void enumeration(IO &IO, COFFYAML::WeakExternalCharacteristics &Value); -}; - -template <> -struct ScalarEnumerationTraits<COFFYAML::AuxSymbolType> { - static void enumeration(IO &IO, COFFYAML::AuxSymbolType &Value); -}; - -template <> -struct ScalarEnumerationTraits<COFFYAML::COMDATType> { - static void enumeration(IO &IO, COFFYAML::COMDATType &Value); -}; - -template <> -struct ScalarEnumerationTraits<COFF::MachineTypes> { - static void enumeration(IO &IO, COFF::MachineTypes &Value); -}; - -template <> -struct ScalarEnumerationTraits<COFF::SymbolBaseType> { - static void enumeration(IO &IO, COFF::SymbolBaseType &Value); -}; - -template <> -struct ScalarEnumerationTraits<COFF::SymbolStorageClass> { - static void enumeration(IO &IO, COFF::SymbolStorageClass &Value); -}; - -template <> -struct ScalarEnumerationTraits<COFF::SymbolComplexType> { - static void enumeration(IO &IO, COFF::SymbolComplexType &Value); -}; - -template <> -struct ScalarEnumerationTraits<COFF::RelocationTypeI386> { - static void enumeration(IO &IO, COFF::RelocationTypeI386 &Value); -}; - -template <> -struct ScalarEnumerationTraits<COFF::RelocationTypeAMD64> { - static void enumeration(IO &IO, COFF::RelocationTypeAMD64 &Value); -}; - -template <> -struct ScalarEnumerationTraits<COFF::WindowsSubsystem> { - static void enumeration(IO &IO, COFF::WindowsSubsystem &Value); -}; - -template <> -struct ScalarBitSetTraits<COFF::Characteristics> { - static void bitset(IO &IO, COFF::Characteristics &Value); -}; - -template <> -struct ScalarBitSetTraits<COFF::SectionCharacteristics> { - static void bitset(IO &IO, COFF::SectionCharacteristics &Value); -}; - -template <> -struct ScalarBitSetTraits<COFF::DLLCharacteristics> { - static void bitset(IO &IO, COFF::DLLCharacteristics &Value); -}; - -template <> -struct MappingTraits<COFFYAML::Relocation> { - static void mapping(IO &IO, COFFYAML::Relocation &Rel); -}; - -template <> -struct MappingTraits<COFFYAML::PEHeader> { - static void mapping(IO &IO, COFFYAML::PEHeader &PH); -}; - -template <> -struct MappingTraits<COFF::DataDirectory> { - static void mapping(IO &IO, COFF::DataDirectory &DD); -}; - -template <> -struct MappingTraits<COFF::header> { - static void mapping(IO &IO, COFF::header &H); -}; - -template <> struct MappingTraits<COFF::AuxiliaryFunctionDefinition> { - static void mapping(IO &IO, COFF::AuxiliaryFunctionDefinition &AFD); -}; - -template <> struct MappingTraits<COFF::AuxiliarybfAndefSymbol> { - static void mapping(IO &IO, COFF::AuxiliarybfAndefSymbol &AAS); -}; - -template <> struct MappingTraits<COFF::AuxiliaryWeakExternal> { - static void mapping(IO &IO, COFF::AuxiliaryWeakExternal &AWE); -}; - -template <> struct MappingTraits<COFF::AuxiliarySectionDefinition> { - static void mapping(IO &IO, COFF::AuxiliarySectionDefinition &ASD); -}; - -template <> struct MappingTraits<COFF::AuxiliaryCLRToken> { - static void mapping(IO &IO, COFF::AuxiliaryCLRToken &ACT); -}; - -template <> -struct MappingTraits<COFFYAML::Symbol> { - static void mapping(IO &IO, COFFYAML::Symbol &S); -}; - -template <> -struct MappingTraits<COFFYAML::Section> { - static void mapping(IO &IO, COFFYAML::Section &Sec); -}; - -template <> -struct MappingTraits<COFFYAML::Object> { - static void mapping(IO &IO, COFFYAML::Object &Obj); -}; - -} // end namespace yaml -} // end namespace llvm - -#endif diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index b0eaa3f5ed4d8..80b8be03810cc 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -54,14 +54,19 @@ public: typedef Elf_Versym_Impl<ELFT> Elf_Versym; typedef Elf_Hash_Impl<ELFT> Elf_Hash; typedef Elf_GnuHash_Impl<ELFT> Elf_GnuHash; - typedef iterator_range<const Elf_Dyn *> Elf_Dyn_Range; - typedef iterator_range<const Elf_Shdr *> Elf_Shdr_Range; - typedef iterator_range<const Elf_Sym *> Elf_Sym_Range; + typedef typename ELFT::DynRange Elf_Dyn_Range; + typedef typename ELFT::ShdrRange Elf_Shdr_Range; + typedef typename ELFT::SymRange Elf_Sym_Range; + typedef typename ELFT::RelRange Elf_Rel_Range; + typedef typename ELFT::RelaRange Elf_Rela_Range; + typedef typename ELFT::PhdrRange Elf_Phdr_Range; const uint8_t *base() const { return reinterpret_cast<const uint8_t *>(Buf.data()); } + size_t getBufSize() const { return Buf.size(); } + private: StringRef Buf; @@ -104,22 +109,10 @@ public: Header->getDataEncoding() == ELF::ELFDATA2LSB; } - ErrorOr<const Elf_Dyn *> dynamic_table_begin(const Elf_Phdr *Phdr) const; - ErrorOr<const Elf_Dyn *> dynamic_table_end(const Elf_Phdr *Phdr) const; - ErrorOr<Elf_Dyn_Range> dynamic_table(const Elf_Phdr *Phdr) const { - ErrorOr<const Elf_Dyn *> Begin = dynamic_table_begin(Phdr); - if (std::error_code EC = Begin.getError()) - return EC; - ErrorOr<const Elf_Dyn *> End = dynamic_table_end(Phdr); - if (std::error_code EC = End.getError()) - return EC; - return make_range(*Begin, *End); - } - const Elf_Shdr *section_begin() const; const Elf_Shdr *section_end() const; Elf_Shdr_Range sections() const { - return make_range(section_begin(), section_end()); + return makeArrayRef(section_begin(), section_end()); } const Elf_Sym *symbol_begin(const Elf_Shdr *Sec) const { @@ -138,11 +131,9 @@ public: return symbol_begin(Sec) + Size / sizeof(Elf_Sym); } Elf_Sym_Range symbols(const Elf_Shdr *Sec) const { - return make_range(symbol_begin(Sec), symbol_end(Sec)); + return makeArrayRef(symbol_begin(Sec), symbol_end(Sec)); } - typedef iterator_range<const Elf_Rela *> Elf_Rela_Range; - const Elf_Rela *rela_begin(const Elf_Shdr *sec) const { if (sec->sh_entsize != sizeof(Elf_Rela)) report_fatal_error("Invalid relocation entry size"); @@ -157,7 +148,7 @@ public: } Elf_Rela_Range relas(const Elf_Shdr *Sec) const { - return make_range(rela_begin(Sec), rela_end(Sec)); + return makeArrayRef(rela_begin(Sec), rela_end(Sec)); } const Elf_Rel *rel_begin(const Elf_Shdr *sec) const { @@ -173,9 +164,8 @@ public: return rel_begin(sec) + Size / sizeof(Elf_Rel); } - typedef iterator_range<const Elf_Rel *> Elf_Rel_Range; Elf_Rel_Range rels(const Elf_Shdr *Sec) const { - return make_range(rel_begin(Sec), rel_end(Sec)); + return makeArrayRef(rel_begin(Sec), rel_end(Sec)); } /// \brief Iterate over program header table. @@ -189,10 +179,8 @@ public: return program_header_begin() + Header->e_phnum; } - typedef iterator_range<const Elf_Phdr *> Elf_Phdr_Range; - const Elf_Phdr_Range program_headers() const { - return make_range(program_header_begin(), program_header_end()); + return makeArrayRef(program_header_begin(), program_header_end()); } uint64_t getNumSections() const; @@ -200,6 +188,9 @@ public: uint32_t getExtendedSymbolTableIndex(const Elf_Sym *Sym, const Elf_Shdr *SymTab, ArrayRef<Elf_Word> ShndxTable) const; + uint32_t getExtendedSymbolTableIndex(const Elf_Sym *Sym, + const Elf_Sym *FirstSym, + ArrayRef<Elf_Word> ShndxTable) const; const Elf_Ehdr *getHeader() const { return Header; } ErrorOr<const Elf_Shdr *> getSection(const Elf_Sym *Sym, const Elf_Shdr *SymTab, @@ -225,8 +216,15 @@ template <class ELFT> uint32_t ELFFile<ELFT>::getExtendedSymbolTableIndex( const Elf_Sym *Sym, const Elf_Shdr *SymTab, ArrayRef<Elf_Word> ShndxTable) const { + return getExtendedSymbolTableIndex(Sym, symbol_begin(SymTab), ShndxTable); +} + +template <class ELFT> +uint32_t ELFFile<ELFT>::getExtendedSymbolTableIndex( + const Elf_Sym *Sym, const Elf_Sym *FirstSym, + ArrayRef<Elf_Word> ShndxTable) const { assert(Sym->st_shndx == ELF::SHN_XINDEX); - unsigned Index = Sym - symbol_begin(SymTab); + unsigned Index = Sym - FirstSym; // The size of the table was checked in getSHNDXTable. return ShndxTable[Index]; @@ -404,34 +402,6 @@ const typename ELFFile<ELFT>::Elf_Shdr *ELFFile<ELFT>::section_end() const { } template <class ELFT> -ErrorOr<const typename ELFFile<ELFT>::Elf_Dyn *> -ELFFile<ELFT>::dynamic_table_begin(const Elf_Phdr *Phdr) const { - if (!Phdr) - return nullptr; - assert(Phdr->p_type == ELF::PT_DYNAMIC && "Got the wrong program header"); - uintX_t Offset = Phdr->p_offset; - if (Offset > Buf.size()) - return object_error::parse_failed; - return reinterpret_cast<const Elf_Dyn *>(base() + Offset); -} - -template <class ELFT> -ErrorOr<const typename ELFFile<ELFT>::Elf_Dyn *> -ELFFile<ELFT>::dynamic_table_end(const Elf_Phdr *Phdr) const { - if (!Phdr) - return nullptr; - assert(Phdr->p_type == ELF::PT_DYNAMIC && "Got the wrong program header"); - uintX_t Size = Phdr->p_filesz; - if (Size % sizeof(Elf_Dyn)) - return object_error::elf_invalid_dynamic_table_size; - // FIKME: Check for overflow? - uintX_t End = Phdr->p_offset + Size; - if (End > Buf.size()) - return object_error::parse_failed; - return reinterpret_cast<const Elf_Dyn *>(base() + End); -} - -template <class ELFT> template <typename T> const T *ELFFile<ELFT>::getEntry(uint32_t Section, uint32_t Entry) const { ErrorOr<const Elf_Shdr *> Sec = getSection(Section); diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index 5d826da4c2fc2..07c6364a68949 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -14,23 +14,28 @@ #ifndef LLVM_OBJECT_ELFOBJECTFILE_H #define LLVM_OBJECT_ELFOBJECTFILE_H -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/MC/SubtargetFeature.h" +#include "llvm/Object/Binary.h" #include "llvm/Object/ELF.h" +#include "llvm/Object/ELFTypes.h" +#include "llvm/Object/Error.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Object/SymbolicFile.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ELF.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ErrorOr.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cctype> -#include <limits> -#include <utility> +#include <cassert> +#include <cstdint> +#include <system_error> namespace llvm { namespace object { @@ -47,6 +52,7 @@ class ELFObjectFileBase : public ObjectFile { protected: ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source); + virtual uint16_t getEMachine() const = 0; virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0; virtual uint8_t getSymbolOther(DataRefImpl Symb) const = 0; virtual uint8_t getSymbolELFType(DataRefImpl Symb) const = 0; @@ -55,14 +61,16 @@ protected: virtual uint64_t getSectionFlags(DataRefImpl Sec) const = 0; virtual ErrorOr<int64_t> getRelocationAddend(DataRefImpl Rel) const = 0; -public: +public: typedef iterator_range<elf_symbol_iterator> elf_symbol_iterator_range; virtual elf_symbol_iterator_range getDynamicSymbolIterators() const = 0; elf_symbol_iterator_range symbols() const; static inline bool classof(const Binary *v) { return v->isELF(); } + + SubtargetFeatures getFeatures() const override; }; class ELFSectionRef : public SectionRef { @@ -175,6 +183,7 @@ ELFObjectFileBase::symbols() const { } template <class ELFT> class ELFObjectFile : public ELFObjectFileBase { + uint16_t getEMachine() const override; uint64_t getSymbolSize(DataRefImpl Sym) const override; public: @@ -197,18 +206,18 @@ protected: ArrayRef<Elf_Word> ShndxTable; void moveSymbolNext(DataRefImpl &Symb) const override; - ErrorOr<StringRef> getSymbolName(DataRefImpl Symb) const override; - ErrorOr<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; + Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; + Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; uint32_t getSymbolAlignment(DataRefImpl Symb) const override; uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; uint8_t getSymbolOther(DataRefImpl Symb) const override; uint8_t getSymbolELFType(DataRefImpl Symb) const override; - SymbolRef::Type getSymbolType(DataRefImpl Symb) const override; - ErrorOr<section_iterator> getSymbolSection(const Elf_Sym *Symb, - const Elf_Shdr *SymTab) const; - ErrorOr<section_iterator> getSymbolSection(DataRefImpl Symb) const override; + Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; + Expected<section_iterator> getSymbolSection(const Elf_Sym *Symb, + const Elf_Shdr *SymTab) const; + Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; void moveSectionNext(DataRefImpl &Sec) const override; std::error_code getSectionName(DataRefImpl Sec, @@ -218,6 +227,7 @@ protected: std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; uint64_t getSectionAlignment(DataRefImpl Sec) const override; + bool isSectionCompressed(DataRefImpl Sec) const override; bool isSectionText(DataRefImpl Sec) const override; bool isSectionData(DataRefImpl Sec) const override; bool isSectionBSS(DataRefImpl Sec) const override; @@ -284,11 +294,9 @@ protected: // A symbol is exported if its binding is either GLOBAL or WEAK, and its // visibility is either DEFAULT or PROTECTED. All other symbols are not // exported. - if ((Binding == ELF::STB_GLOBAL || Binding == ELF::STB_WEAK) && - (Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_PROTECTED)) - return true; - - return false; + return ((Binding == ELF::STB_GLOBAL || Binding == ELF::STB_WEAK) && + (Visibility == ELF::STV_DEFAULT || + Visibility == ELF::STV_PROTECTED)); } // This flag is used for classof, to distinguish ELFObjectFile from @@ -354,7 +362,7 @@ void ELFObjectFile<ELFT>::moveSymbolNext(DataRefImpl &Sym) const { } template <class ELFT> -ErrorOr<StringRef> ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Sym) const { +Expected<StringRef> ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Sym) const { const Elf_Sym *ESym = getSymbol(Sym); const Elf_Shdr *SymTableSec = *EF.getSection(Sym.d.a); const Elf_Shdr *StringTableSec = *EF.getSection(SymTableSec->sh_link); @@ -389,7 +397,7 @@ uint64_t ELFObjectFile<ELFT>::getSymbolValueImpl(DataRefImpl Symb) const { } template <class ELFT> -ErrorOr<uint64_t> +Expected<uint64_t> ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb) const { uint64_t Result = getSymbolValue(Symb); const Elf_Sym *ESym = getSymbol(Symb); @@ -407,7 +415,7 @@ ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb) const { ErrorOr<const Elf_Shdr *> SectionOrErr = EF.getSection(ESym, SymTab, ShndxTable); if (std::error_code EC = SectionOrErr.getError()) - return EC; + return errorCodeToError(EC); const Elf_Shdr *Section = *SectionOrErr; if (Section) Result += Section->sh_addr; @@ -425,6 +433,11 @@ uint32_t ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb) const { } template <class ELFT> +uint16_t ELFObjectFile<ELFT>::getEMachine() const { + return EF.getHeader()->e_machine; +} + +template <class ELFT> uint64_t ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Sym) const { return getSymbol(Sym)->st_size; } @@ -445,7 +458,8 @@ uint8_t ELFObjectFile<ELFT>::getSymbolELFType(DataRefImpl Symb) const { } template <class ELFT> -SymbolRef::Type ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb) const { +Expected<SymbolRef::Type> +ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb) const { const Elf_Sym *ESym = getSymbol(Symb); switch (ESym->getType()) { @@ -487,12 +501,17 @@ uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Sym) const { Result |= SymbolRef::SF_FormatSpecific; if (EF.getHeader()->e_machine == ELF::EM_ARM) { - if (ErrorOr<StringRef> NameOrErr = getSymbolName(Sym)) { + if (Expected<StringRef> NameOrErr = getSymbolName(Sym)) { StringRef Name = *NameOrErr; if (Name.startswith("$d") || Name.startswith("$t") || Name.startswith("$a")) Result |= SymbolRef::SF_FormatSpecific; + } else { + // TODO: Actually report errors helpfully. + consumeError(NameOrErr.takeError()); } + if (ESym->getType() == ELF::STT_FUNC && (ESym->st_value & 1) == 1) + Result |= SymbolRef::SF_Thumb; } if (ESym->st_shndx == ELF::SHN_UNDEF) @@ -511,12 +530,12 @@ uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Sym) const { } template <class ELFT> -ErrorOr<section_iterator> +Expected<section_iterator> ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym, const Elf_Shdr *SymTab) const { ErrorOr<const Elf_Shdr *> ESecOrErr = EF.getSection(ESym, SymTab, ShndxTable); if (std::error_code EC = ESecOrErr.getError()) - return EC; + return errorCodeToError(EC); const Elf_Shdr *ESec = *ESecOrErr; if (!ESec) @@ -528,7 +547,7 @@ ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym, } template <class ELFT> -ErrorOr<section_iterator> +Expected<section_iterator> ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb) const { const Elf_Sym *Sym = getSymbol(Symb); const Elf_Shdr *SymTab = *EF.getSection(Symb.d.a); @@ -576,6 +595,11 @@ uint64_t ELFObjectFile<ELFT>::getSectionAlignment(DataRefImpl Sec) const { } template <class ELFT> +bool ELFObjectFile<ELFT>::isSectionCompressed(DataRefImpl Sec) const { + return getSection(Sec)->sh_flags & ELF::SHF_COMPRESSED; +} + +template <class ELFT> bool ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec) const { return getSection(Sec)->sh_flags & ELF::SHF_EXECINSTR; } @@ -606,22 +630,6 @@ ELFObjectFile<ELFT>::section_rel_begin(DataRefImpl Sec) const { uintptr_t SHT = reinterpret_cast<uintptr_t>(EF.section_begin()); RelData.d.a = (Sec.p - SHT) / EF.getHeader()->e_shentsize; RelData.d.b = 0; - - const Elf_Shdr *S = reinterpret_cast<const Elf_Shdr *>(Sec.p); - if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL) - return relocation_iterator(RelocationRef(RelData, this)); - - const Elf_Shdr *RelSec = getRelSection(RelData); - ErrorOr<const Elf_Shdr *> SymSecOrErr = EF.getSection(RelSec->sh_link); - if (std::error_code EC = SymSecOrErr.getError()) - report_fatal_error(EC.message()); - const Elf_Shdr *SymSec = *SymSecOrErr; - uint32_t SymSecType = SymSec->sh_type; - if (SymSecType != ELF::SHT_SYMTAB && SymSecType != ELF::SHT_DYNSYM) - report_fatal_error("Invalid symbol table section type!"); - if (SymSecType == ELF::SHT_DYNSYM) - RelData.d.b = 1; - return relocation_iterator(RelocationRef(RelData, this)); } @@ -633,7 +641,14 @@ ELFObjectFile<ELFT>::section_rel_end(DataRefImpl Sec) const { if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL) return Begin; DataRefImpl RelData = Begin->getRawDataRefImpl(); - RelData.d.b += (S->sh_size / S->sh_entsize) << 1; + const Elf_Shdr *RelSec = getRelSection(RelData); + + // Error check sh_link here so that getRelocationSymbol can just use it. + ErrorOr<const Elf_Shdr *> SymSecOrErr = EF.getSection(RelSec->sh_link); + if (std::error_code EC = SymSecOrErr.getError()) + report_fatal_error(EC.message()); + + RelData.d.b += S->sh_size / S->sh_entsize; return relocation_iterator(RelocationRef(RelData, this)); } @@ -657,7 +672,7 @@ ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const { // Relocations template <class ELFT> void ELFObjectFile<ELFT>::moveRelocationNext(DataRefImpl &Rel) const { - Rel.d.b += 2; + ++Rel.d.b; } template <class ELFT> @@ -672,12 +687,10 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const { if (!symbolIdx) return symbol_end(); - bool IsDyn = Rel.d.b & 1; + // FIXME: error check symbolIdx DataRefImpl SymbolData; - if (IsDyn) - SymbolData = toDRI(DotDynSymSec, symbolIdx); - else - SymbolData = toDRI(DotSymtabSec, symbolIdx); + SymbolData.d.a = sec->sh_link; + SymbolData.d.b = symbolIdx; return symbol_iterator(SymbolRef(SymbolData, this)); } @@ -725,14 +738,14 @@ template <class ELFT> const typename ELFObjectFile<ELFT>::Elf_Rel * ELFObjectFile<ELFT>::getRel(DataRefImpl Rel) const { assert(getRelSection(Rel)->sh_type == ELF::SHT_REL); - return EF.template getEntry<Elf_Rel>(Rel.d.a, Rel.d.b >> 1); + return EF.template getEntry<Elf_Rel>(Rel.d.a, Rel.d.b); } template <class ELFT> const typename ELFObjectFile<ELFT>::Elf_Rela * ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const { assert(getRelSection(Rela)->sh_type == ELF::SHT_RELA); - return EF.template getEntry<Elf_Rela>(Rela.d.a, Rela.d.b >> 1); + return EF.template getEntry<Elf_Rela>(Rela.d.a, Rela.d.b); } template <class ELFT> @@ -835,6 +848,8 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { return "ELF32-avr"; case ELF::EM_HEXAGON: return "ELF32-hexagon"; + case ELF::EM_LANAI: + return "ELF32-lanai"; case ELF::EM_MIPS: return "ELF32-mips"; case ELF::EM_PPC: @@ -844,6 +859,8 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { return "ELF32-sparc"; case ELF::EM_WEBASSEMBLY: return "ELF32-wasm"; + case ELF::EM_AMDGPU: + return "ELF32-amdgpu"; default: return "ELF32-unknown"; } @@ -865,6 +882,12 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { return "ELF64-mips"; case ELF::EM_WEBASSEMBLY: return "ELF64-wasm"; + case ELF::EM_AMDGPU: + return (EF.getHeader()->e_ident[ELF::EI_OSABI] == ELF::ELFOSABI_AMDGPU_HSA + && IsLittleEndian) ? + "ELF64-amdgpu-hsacobj" : "ELF64-amdgpu"; + case ELF::EM_BPF: + return "ELF64-BPF"; default: return "ELF64-unknown"; } @@ -891,6 +914,8 @@ unsigned ELFObjectFile<ELFT>::getArch() const { return Triple::avr; case ELF::EM_HEXAGON: return Triple::hexagon; + case ELF::EM_LANAI: + return Triple::lanai; case ELF::EM_MIPS: switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) { case ELF::ELFCLASS32: @@ -919,6 +944,15 @@ unsigned ELFObjectFile<ELFT>::getArch() const { default: return Triple::UnknownArch; } + case ELF::EM_AMDGPU: + return (EF.getHeader()->e_ident[ELF::EI_CLASS] == ELF::ELFCLASS64 + && EF.getHeader()->e_ident[ELF::EI_OSABI] == ELF::ELFOSABI_AMDGPU_HSA + && IsLittleEndian) ? + Triple::amdgcn : Triple::UnknownArch; + + case ELF::EM_BPF: + return IsLittleEndian ? Triple::bpfel : Triple::bpfeb; + default: return Triple::UnknownArch; } @@ -934,7 +968,7 @@ template <class ELFT> bool ELFObjectFile<ELFT>::isRelocatableObject() const { return EF.getHeader()->e_type == ELF::ET_REL; } -} -} +} // end namespace object +} // end namespace llvm -#endif +#endif // LLVM_OBJECT_ELFOBJECTFILE_H diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h index 07b312a7d77c1..55028f360dbf3 100644 --- a/include/llvm/Object/ELFTypes.h +++ b/include/llvm/Object/ELFTypes.h @@ -21,9 +21,60 @@ namespace object { using support::endianness; -template <endianness target_endianness, bool is64Bits> struct ELFType { - static const endianness TargetEndianness = target_endianness; - static const bool Is64Bits = is64Bits; +template <class ELFT> struct Elf_Ehdr_Impl; +template <class ELFT> struct Elf_Shdr_Impl; +template <class ELFT> struct Elf_Sym_Impl; +template <class ELFT> struct Elf_Dyn_Impl; +template <class ELFT> struct Elf_Phdr_Impl; +template <class ELFT, bool isRela> struct Elf_Rel_Impl; +template <class ELFT> struct Elf_Verdef_Impl; +template <class ELFT> struct Elf_Verdaux_Impl; +template <class ELFT> struct Elf_Verneed_Impl; +template <class ELFT> struct Elf_Vernaux_Impl; +template <class ELFT> struct Elf_Versym_Impl; +template <class ELFT> struct Elf_Hash_Impl; +template <class ELFT> struct Elf_GnuHash_Impl; +template <class ELFT> struct Elf_Chdr_Impl; + +template <endianness E, bool Is64> struct ELFType { +private: + template <typename Ty> + using packed = support::detail::packed_endian_specific_integral<Ty, E, 2>; + +public: + static const endianness TargetEndianness = E; + static const bool Is64Bits = Is64; + + typedef typename std::conditional<Is64, uint64_t, uint32_t>::type uint; + typedef Elf_Ehdr_Impl<ELFType<E, Is64>> Ehdr; + typedef Elf_Shdr_Impl<ELFType<E, Is64>> Shdr; + typedef Elf_Sym_Impl<ELFType<E, Is64>> Sym; + typedef Elf_Dyn_Impl<ELFType<E, Is64>> Dyn; + typedef Elf_Phdr_Impl<ELFType<E, Is64>> Phdr; + typedef Elf_Rel_Impl<ELFType<E, Is64>, false> Rel; + typedef Elf_Rel_Impl<ELFType<E, Is64>, true> Rela; + typedef Elf_Verdef_Impl<ELFType<E, Is64>> Verdef; + typedef Elf_Verdaux_Impl<ELFType<E, Is64>> Verdaux; + typedef Elf_Verneed_Impl<ELFType<E, Is64>> Verneed; + typedef Elf_Vernaux_Impl<ELFType<E, Is64>> Vernaux; + typedef Elf_Versym_Impl<ELFType<E, Is64>> Versym; + typedef Elf_Hash_Impl<ELFType<E, Is64>> Hash; + typedef Elf_GnuHash_Impl<ELFType<E, Is64>> GnuHash; + typedef Elf_Chdr_Impl<ELFType<E, Is64>> Chdr; + typedef ArrayRef<Dyn> DynRange; + typedef ArrayRef<Shdr> ShdrRange; + typedef ArrayRef<Sym> SymRange; + typedef ArrayRef<Rel> RelRange; + typedef ArrayRef<Rela> RelaRange; + typedef ArrayRef<Phdr> PhdrRange; + + typedef packed<uint16_t> Half; + typedef packed<uint32_t> Word; + typedef packed<int32_t> Sword; + typedef packed<uint64_t> Xword; + typedef packed<int64_t> Sxword; + typedef packed<uint> Addr; + typedef packed<uint> Off; }; typedef ELFType<support::little, false> ELF32LE; @@ -208,14 +259,14 @@ struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> { return getBinding() != ELF::STB_LOCAL; } - ErrorOr<StringRef> getName(StringRef StrTab) const; + Expected<StringRef> getName(StringRef StrTab) const; }; template <class ELFT> -ErrorOr<StringRef> Elf_Sym_Impl<ELFT>::getName(StringRef StrTab) const { +Expected<StringRef> Elf_Sym_Impl<ELFT>::getName(StringRef StrTab) const { uint32_t Offset = this->st_name; if (Offset >= StrTab.size()) - return object_error::parse_failed; + return errorCodeToError(object_error::parse_failed); return StringRef(StrTab.data() + Offset); } @@ -320,12 +371,10 @@ struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> { uintX_t getPtr() const { return d_un.d_ptr; } }; -// Elf_Rel: Elf Relocation -template <class ELFT, bool isRela> struct Elf_Rel_Impl; - template <endianness TargetEndianness> struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, false> { LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) + static const bool IsRela = false; Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Word r_info; // Symbol table index and type of relocation to apply @@ -361,12 +410,14 @@ template <endianness TargetEndianness> struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, true> : public Elf_Rel_Impl<ELFType<TargetEndianness, false>, false> { LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) + static const bool IsRela = true; Elf_Sword r_addend; // Compute value for relocatable field by adding this }; template <endianness TargetEndianness> struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, false> { LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) + static const bool IsRela = false; Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Xword r_info; // Symbol table index and type of relocation to apply @@ -411,6 +462,7 @@ template <endianness TargetEndianness> struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, true> : public Elf_Rel_Impl<ELFType<TargetEndianness, true>, false> { LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) + static const bool IsRela = true; Elf_Sxword r_addend; // Compute value for relocatable field by adding this. }; @@ -508,6 +560,25 @@ struct Elf_GnuHash_Impl { } }; +// Compressed section headers. +// http://www.sco.com/developers/gabi/latest/ch4.sheader.html#compression_header +template <endianness TargetEndianness> +struct Elf_Chdr_Impl<ELFType<TargetEndianness, false>> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) + Elf_Word ch_type; + Elf_Word ch_size; + Elf_Word ch_addralign; +}; + +template <endianness TargetEndianness> +struct Elf_Chdr_Impl<ELFType<TargetEndianness, true>> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) + Elf_Word ch_type; + Elf_Word ch_reserved; + Elf_Xword ch_size; + Elf_Xword ch_addralign; +}; + // MIPS .reginfo section template <class ELFT> struct Elf_Mips_RegInfo; diff --git a/include/llvm/Object/ELFYAML.h b/include/llvm/Object/ELFYAML.h deleted file mode 100644 index df0aa500c8a29..0000000000000 --- a/include/llvm/Object/ELFYAML.h +++ /dev/null @@ -1,319 +0,0 @@ -//===- ELFYAML.h - ELF YAMLIO implementation --------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief This file declares classes for handling the YAML representation -/// of ELF. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_ELFYAML_H -#define LLVM_OBJECT_ELFYAML_H - -#include "llvm/MC/YAML.h" -#include "llvm/Support/ELF.h" - -namespace llvm { -namespace ELFYAML { - -// These types are invariant across 32/64-bit ELF, so for simplicity just -// directly give them their exact sizes. We don't need to worry about -// endianness because these are just the types in the YAMLIO structures, -// and are appropriately converted to the necessary endianness when -// reading/generating binary object files. -// The naming of these types is intended to be ELF_PREFIX, where PREFIX is -// the common prefix of the respective constants. E.g. ELF_EM corresponds -// to the `e_machine` constants, like `EM_X86_64`. -// In the future, these would probably be better suited by C++11 enum -// class's with appropriate fixed underlying type. -LLVM_YAML_STRONG_TYPEDEF(uint16_t, ELF_ET) -LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_EM) -LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFCLASS) -LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFDATA) -LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFOSABI) -// Just use 64, since it can hold 32-bit values too. -LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_EF) -LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT) -LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_REL) -LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_RSS) -// Just use 64, since it can hold 32-bit values too. -LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_SHF) -LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STT) -LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STV) -LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STO) - -LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_AFL_REG) -LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_ABI_FP) -LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_EXT) -LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_ASE) -LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_FLAGS1) -LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_ISA) - -// For now, hardcode 64 bits everywhere that 32 or 64 would be needed -// since 64-bit can hold 32-bit values too. -struct FileHeader { - ELF_ELFCLASS Class; - ELF_ELFDATA Data; - ELF_ELFOSABI OSABI; - ELF_ET Type; - ELF_EM Machine; - ELF_EF Flags; - llvm::yaml::Hex64 Entry; -}; -struct Symbol { - StringRef Name; - ELF_STT Type; - StringRef Section; - llvm::yaml::Hex64 Value; - llvm::yaml::Hex64 Size; - uint8_t Other; -}; -struct LocalGlobalWeakSymbols { - std::vector<Symbol> Local; - std::vector<Symbol> Global; - std::vector<Symbol> Weak; -}; - -struct SectionOrType { - StringRef sectionNameOrType; -}; - -struct Section { - enum class SectionKind { - Group, - RawContent, - Relocation, - NoBits, - MipsABIFlags - }; - SectionKind Kind; - StringRef Name; - ELF_SHT Type; - ELF_SHF Flags; - llvm::yaml::Hex64 Address; - StringRef Link; - StringRef Info; - llvm::yaml::Hex64 AddressAlign; - Section(SectionKind Kind) : Kind(Kind) {} - virtual ~Section(); -}; -struct RawContentSection : Section { - yaml::BinaryRef Content; - llvm::yaml::Hex64 Size; - RawContentSection() : Section(SectionKind::RawContent) {} - static bool classof(const Section *S) { - return S->Kind == SectionKind::RawContent; - } -}; - -struct NoBitsSection : Section { - llvm::yaml::Hex64 Size; - NoBitsSection() : Section(SectionKind::NoBits) {} - static bool classof(const Section *S) { - return S->Kind == SectionKind::NoBits; - } -}; - -struct Group : Section { - // Members of a group contain a flag and a list of section indices - // that are part of the group. - std::vector<SectionOrType> Members; - Group() : Section(SectionKind::Group) {} - static bool classof(const Section *S) { - return S->Kind == SectionKind::Group; - } -}; - -struct Relocation { - llvm::yaml::Hex64 Offset; - int64_t Addend; - ELF_REL Type; - StringRef Symbol; -}; -struct RelocationSection : Section { - std::vector<Relocation> Relocations; - RelocationSection() : Section(SectionKind::Relocation) {} - static bool classof(const Section *S) { - return S->Kind == SectionKind::Relocation; - } -}; - -// Represents .MIPS.abiflags section -struct MipsABIFlags : Section { - llvm::yaml::Hex16 Version; - MIPS_ISA ISALevel; - llvm::yaml::Hex8 ISARevision; - MIPS_AFL_REG GPRSize; - MIPS_AFL_REG CPR1Size; - MIPS_AFL_REG CPR2Size; - MIPS_ABI_FP FpABI; - MIPS_AFL_EXT ISAExtension; - MIPS_AFL_ASE ASEs; - MIPS_AFL_FLAGS1 Flags1; - llvm::yaml::Hex32 Flags2; - MipsABIFlags() : Section(SectionKind::MipsABIFlags) {} - static bool classof(const Section *S) { - return S->Kind == SectionKind::MipsABIFlags; - } -}; - -struct Object { - FileHeader Header; - std::vector<std::unique_ptr<Section>> Sections; - // Although in reality the symbols reside in a section, it is a lot - // cleaner and nicer if we read them from the YAML as a separate - // top-level key, which automatically ensures that invariants like there - // being a single SHT_SYMTAB section are upheld. - LocalGlobalWeakSymbols Symbols; -}; - -} // end namespace ELFYAML -} // end namespace llvm - -LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::ELFYAML::Section>) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Relocation) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::SectionOrType) - -namespace llvm { -namespace yaml { - -template <> -struct ScalarEnumerationTraits<ELFYAML::ELF_ET> { - static void enumeration(IO &IO, ELFYAML::ELF_ET &Value); -}; - -template <> -struct ScalarEnumerationTraits<ELFYAML::ELF_EM> { - static void enumeration(IO &IO, ELFYAML::ELF_EM &Value); -}; - -template <> -struct ScalarEnumerationTraits<ELFYAML::ELF_ELFCLASS> { - static void enumeration(IO &IO, ELFYAML::ELF_ELFCLASS &Value); -}; - -template <> -struct ScalarEnumerationTraits<ELFYAML::ELF_ELFDATA> { - static void enumeration(IO &IO, ELFYAML::ELF_ELFDATA &Value); -}; - -template <> -struct ScalarEnumerationTraits<ELFYAML::ELF_ELFOSABI> { - static void enumeration(IO &IO, ELFYAML::ELF_ELFOSABI &Value); -}; - -template <> -struct ScalarBitSetTraits<ELFYAML::ELF_EF> { - static void bitset(IO &IO, ELFYAML::ELF_EF &Value); -}; - -template <> -struct ScalarEnumerationTraits<ELFYAML::ELF_SHT> { - static void enumeration(IO &IO, ELFYAML::ELF_SHT &Value); -}; - -template <> -struct ScalarBitSetTraits<ELFYAML::ELF_SHF> { - static void bitset(IO &IO, ELFYAML::ELF_SHF &Value); -}; - -template <> -struct ScalarEnumerationTraits<ELFYAML::ELF_STT> { - static void enumeration(IO &IO, ELFYAML::ELF_STT &Value); -}; - -template <> -struct ScalarEnumerationTraits<ELFYAML::ELF_STV> { - static void enumeration(IO &IO, ELFYAML::ELF_STV &Value); -}; - -template <> -struct ScalarBitSetTraits<ELFYAML::ELF_STO> { - static void bitset(IO &IO, ELFYAML::ELF_STO &Value); -}; - -template <> -struct ScalarEnumerationTraits<ELFYAML::ELF_REL> { - static void enumeration(IO &IO, ELFYAML::ELF_REL &Value); -}; - -template <> -struct ScalarEnumerationTraits<ELFYAML::ELF_RSS> { - static void enumeration(IO &IO, ELFYAML::ELF_RSS &Value); -}; - -template <> -struct ScalarEnumerationTraits<ELFYAML::MIPS_AFL_REG> { - static void enumeration(IO &IO, ELFYAML::MIPS_AFL_REG &Value); -}; - -template <> -struct ScalarEnumerationTraits<ELFYAML::MIPS_ABI_FP> { - static void enumeration(IO &IO, ELFYAML::MIPS_ABI_FP &Value); -}; - -template <> -struct ScalarEnumerationTraits<ELFYAML::MIPS_AFL_EXT> { - static void enumeration(IO &IO, ELFYAML::MIPS_AFL_EXT &Value); -}; - -template <> -struct ScalarEnumerationTraits<ELFYAML::MIPS_ISA> { - static void enumeration(IO &IO, ELFYAML::MIPS_ISA &Value); -}; - -template <> -struct ScalarBitSetTraits<ELFYAML::MIPS_AFL_ASE> { - static void bitset(IO &IO, ELFYAML::MIPS_AFL_ASE &Value); -}; - -template <> -struct ScalarBitSetTraits<ELFYAML::MIPS_AFL_FLAGS1> { - static void bitset(IO &IO, ELFYAML::MIPS_AFL_FLAGS1 &Value); -}; - -template <> -struct MappingTraits<ELFYAML::FileHeader> { - static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr); -}; - -template <> -struct MappingTraits<ELFYAML::Symbol> { - static void mapping(IO &IO, ELFYAML::Symbol &Symbol); -}; - -template <> -struct MappingTraits<ELFYAML::LocalGlobalWeakSymbols> { - static void mapping(IO &IO, ELFYAML::LocalGlobalWeakSymbols &Symbols); -}; - -template <> struct MappingTraits<ELFYAML::Relocation> { - static void mapping(IO &IO, ELFYAML::Relocation &Rel); -}; - -template <> -struct MappingTraits<std::unique_ptr<ELFYAML::Section>> { - static void mapping(IO &IO, std::unique_ptr<ELFYAML::Section> &Section); - static StringRef validate(IO &io, std::unique_ptr<ELFYAML::Section> &Section); -}; - -template <> -struct MappingTraits<ELFYAML::Object> { - static void mapping(IO &IO, ELFYAML::Object &Object); -}; - -template <> struct MappingTraits<ELFYAML::SectionOrType> { - static void mapping(IO &IO, ELFYAML::SectionOrType §ionOrType); -}; - -} // end namespace yaml -} // end namespace llvm - -#endif diff --git a/include/llvm/Object/Error.h b/include/llvm/Object/Error.h index 0f79a6ed0dd81..cd55e5dc26d7b 100644 --- a/include/llvm/Object/Error.h +++ b/include/llvm/Object/Error.h @@ -14,11 +14,15 @@ #ifndef LLVM_OBJECT_ERROR_H #define LLVM_OBJECT_ERROR_H +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Error.h" #include <system_error> namespace llvm { namespace object { +class Binary; + const std::error_category &object_category(); enum class object_error { @@ -30,16 +34,51 @@ enum class object_error { string_table_non_null_end, invalid_section_index, bitcode_section_not_found, - elf_invalid_dynamic_table_size, - macho_small_load_command, - macho_load_segment_too_many_sections, - macho_load_segment_too_small, }; inline std::error_code make_error_code(object_error e) { return std::error_code(static_cast<int>(e), object_category()); } +/// Base class for all errors indicating malformed binary files. +/// +/// Having a subclass for all malformed binary files allows archive-walking +/// code to skip malformed files without having to understand every possible +/// way that a binary file might be malformed. +/// +/// Currently inherits from ECError for easy interoperability with +/// std::error_code, but this will be removed in the future. +class BinaryError : public ErrorInfo<BinaryError, ECError> { +public: + static char ID; + BinaryError() { + // Default to parse_failed, can be overridden with setErrorCode. + setErrorCode(make_error_code(object_error::parse_failed)); + } +}; + +/// Generic binary error. +/// +/// For errors that don't require their own specific sub-error (most errors) +/// this class can be used to describe the error via a string message. +class GenericBinaryError : public ErrorInfo<GenericBinaryError, BinaryError> { +public: + static char ID; + GenericBinaryError(Twine Msg); + GenericBinaryError(Twine Msg, object_error ECOverride); + const std::string &getMessage() const { return Msg; } + void log(raw_ostream &OS) const override; +private: + std::string Msg; +}; + +/// isNotObjectErrorInvalidFileType() is used when looping through the children +/// of an archive after calling getAsBinary() on the child and it returns an +/// llvm::Error. In the cases we want to loop through the children and ignore the +/// non-objects in the archive this is used to test the error to see if an +/// error() function needs to called on the llvm::Error. +Error isNotObjectErrorInvalidFileType(llvm::Error Err); + } // end namespace object. } // end namespace llvm. diff --git a/include/llvm/Object/FunctionIndexObjectFile.h b/include/llvm/Object/FunctionIndexObjectFile.h deleted file mode 100644 index 74b461dc7cc72..0000000000000 --- a/include/llvm/Object/FunctionIndexObjectFile.h +++ /dev/null @@ -1,110 +0,0 @@ -//===- FunctionIndexObjectFile.h - Function index file implementation -----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares the FunctionIndexObjectFile template class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_FUNCTIONINDEXOBJECTFILE_H -#define LLVM_OBJECT_FUNCTIONINDEXOBJECTFILE_H - -#include "llvm/IR/DiagnosticInfo.h" -#include "llvm/Object/SymbolicFile.h" - -namespace llvm { -class FunctionInfoIndex; -class Module; - -namespace object { -class ObjectFile; - -/// This class is used to read just the function summary index related -/// sections out of the given object (which may contain a single module's -/// bitcode or be a combined index bitcode file). It builds a FunctionInfoIndex -/// object. -class FunctionIndexObjectFile : public SymbolicFile { - std::unique_ptr<FunctionInfoIndex> Index; - -public: - FunctionIndexObjectFile(MemoryBufferRef Object, - std::unique_ptr<FunctionInfoIndex> I); - ~FunctionIndexObjectFile() override; - - // TODO: Walk through FunctionMap entries for function symbols. - // However, currently these interfaces are not used by any consumers. - void moveSymbolNext(DataRefImpl &Symb) const override { - llvm_unreachable("not implemented"); - } - std::error_code printSymbolName(raw_ostream &OS, - DataRefImpl Symb) const override { - llvm_unreachable("not implemented"); - return std::error_code(); - } - uint32_t getSymbolFlags(DataRefImpl Symb) const override { - llvm_unreachable("not implemented"); - return 0; - } - basic_symbol_iterator symbol_begin_impl() const override { - llvm_unreachable("not implemented"); - return basic_symbol_iterator(BasicSymbolRef()); - } - basic_symbol_iterator symbol_end_impl() const override { - llvm_unreachable("not implemented"); - return basic_symbol_iterator(BasicSymbolRef()); - } - - const FunctionInfoIndex &getIndex() const { - return const_cast<FunctionIndexObjectFile *>(this)->getIndex(); - } - FunctionInfoIndex &getIndex() { return *Index; } - std::unique_ptr<FunctionInfoIndex> takeIndex(); - - static inline bool classof(const Binary *v) { return v->isFunctionIndex(); } - - /// \brief Finds and returns bitcode embedded in the given object file, or an - /// error code if not found. - static ErrorOr<MemoryBufferRef> findBitcodeInObject(const ObjectFile &Obj); - - /// \brief Finds and returns bitcode in the given memory buffer (which may - /// be either a bitcode file or a native object file with embedded bitcode), - /// or an error code if not found. - static ErrorOr<MemoryBufferRef> - findBitcodeInMemBuffer(MemoryBufferRef Object); - - /// \brief Looks for function summary in the given memory buffer, - /// returns true if found, else false. - static bool - hasFunctionSummaryInMemBuffer(MemoryBufferRef Object, - DiagnosticHandlerFunction DiagnosticHandler); - - /// \brief Parse function index in the given memory buffer. - /// Return new FunctionIndexObjectFile instance containing parsed function - /// summary/index. - static ErrorOr<std::unique_ptr<FunctionIndexObjectFile>> - create(MemoryBufferRef Object, DiagnosticHandlerFunction DiagnosticHandler, - bool IsLazy = false); - - /// \brief Parse the function summary information for function with the - /// given name out of the given buffer. Parsed information is - /// stored on the index object saved in this object. - std::error_code - findFunctionSummaryInMemBuffer(MemoryBufferRef Object, - DiagnosticHandlerFunction DiagnosticHandler, - StringRef FunctionName); -}; -} - -/// Parse the function index out of an IR file and return the function -/// index object if found, or nullptr if not. -ErrorOr<std::unique_ptr<FunctionInfoIndex>> -getFunctionIndexForFile(StringRef Path, - DiagnosticHandlerFunction DiagnosticHandler); -} - -#endif diff --git a/include/llvm/Object/IRObjectFile.h b/include/llvm/Object/IRObjectFile.h index ef655287c34c6..9fe011e17d627 100644 --- a/include/llvm/Object/IRObjectFile.h +++ b/include/llvm/Object/IRObjectFile.h @@ -20,6 +20,7 @@ namespace llvm { class Mangler; class Module; class GlobalValue; +class Triple; namespace object { class ObjectFile; @@ -59,6 +60,15 @@ public: /// error code if not found. static ErrorOr<MemoryBufferRef> findBitcodeInObject(const ObjectFile &Obj); + /// Parse inline ASM and collect the symbols that are not defined in + /// the current module. + /// + /// For each found symbol, call \p AsmUndefinedRefs with the name of the + /// symbol found and the associated flags. + static void CollectAsmUndefinedRefs( + const Triple &TheTriple, StringRef InlineAsm, + function_ref<void(StringRef, BasicSymbolRef::Flags)> AsmUndefinedRefs); + /// \brief Finds and returns bitcode in the given memory buffer (which may /// be either a bitcode file or a native object file with embedded bitcode), /// or an error code if not found. diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index e02ce3b214168..7906db1e8a77d 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -193,24 +193,24 @@ public: typedef SmallVector<LoadCommandInfo, 4> LoadCommandList; typedef LoadCommandList::const_iterator load_command_iterator; - MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits, - std::error_code &EC); + static Expected<std::unique_ptr<MachOObjectFile>> + create(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits); void moveSymbolNext(DataRefImpl &Symb) const override; uint64_t getNValue(DataRefImpl Sym) const; - ErrorOr<StringRef> getSymbolName(DataRefImpl Symb) const override; + Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; // MachO specific. std::error_code getIndirectName(DataRefImpl Symb, StringRef &Res) const; unsigned getSectionType(SectionRef Sec) const; - ErrorOr<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; + Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; uint32_t getSymbolAlignment(DataRefImpl Symb) const override; uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; - SymbolRef::Type getSymbolType(DataRefImpl Symb) const override; + Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; - ErrorOr<section_iterator> getSymbolSection(DataRefImpl Symb) const override; + Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; unsigned getSymbolSectionID(SymbolRef Symb) const; unsigned getSectionID(SectionRef Sec) const; @@ -222,10 +222,12 @@ public: std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; uint64_t getSectionAlignment(DataRefImpl Sec) const override; + bool isSectionCompressed(DataRefImpl Sec) const override; bool isSectionText(DataRefImpl Sec) const override; bool isSectionData(DataRefImpl Sec) const override; bool isSectionBSS(DataRefImpl Sec) const override; bool isSectionVirtual(DataRefImpl Sec) const override; + bool isSectionBitcode(DataRefImpl Sec) const override; relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; @@ -251,6 +253,7 @@ public: // MachO specific. basic_symbol_iterator getSymbolByIndex(unsigned Index) const; + uint64_t getSymbolIndex(DataRefImpl Symb) const; section_iterator section_begin() const override; section_iterator section_end() const override; @@ -259,7 +262,8 @@ public: StringRef getFileFormatName() const override; unsigned getArch() const override; - Triple getArch(const char **McpuDefault, Triple *ThumbTriple) const; + SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); } + Triple getArchTriple(const char **McpuDefault = nullptr) const; relocation_iterator section_rel_begin(unsigned Index) const; relocation_iterator section_rel_end(unsigned Index) const; @@ -405,12 +409,8 @@ public: StringRef &Suffix); static Triple::ArchType getArch(uint32_t CPUType); - static Triple getArch(uint32_t CPUType, uint32_t CPUSubType, - const char **McpuDefault = nullptr); - static Triple getThumbArch(uint32_t CPUType, uint32_t CPUSubType, - const char **McpuDefault = nullptr); - static Triple getArch(uint32_t CPUType, uint32_t CPUSubType, - const char **McpuDefault, Triple *ThumbTriple); + static Triple getArchTriple(uint32_t CPUType, uint32_t CPUSubType, + const char **McpuDefault = nullptr); static bool isValidArch(StringRef ArchFlag); static Triple getHostArch(); @@ -441,6 +441,10 @@ public: } private: + + MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits, + Error &Err); + uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; union { diff --git a/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h index a11d381a700a2..7eb2af944f3dc 100644 --- a/include/llvm/Object/MachOUniversal.h +++ b/include/llvm/Object/MachOUniversal.h @@ -14,21 +14,22 @@ #ifndef LLVM_OBJECT_MACHOUNIVERSAL_H #define LLVM_OBJECT_MACHOUNIVERSAL_H -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Object/Archive.h" #include "llvm/Object/Binary.h" #include "llvm/Object/MachO.h" -#include "llvm/Support/ErrorOr.h" #include "llvm/Support/MachO.h" namespace llvm { +class StringRef; + namespace object { class MachOUniversalBinary : public Binary { virtual void anchor(); + uint32_t Magic; uint32_t NumberOfObjects; public: class ObjectForArch { @@ -37,6 +38,7 @@ public: uint32_t Index; /// \brief Descriptor of the object. MachO::fat_arch Header; + MachO::fat_arch_64 Header64; public: ObjectForArch(const MachOUniversalBinary *Parent, uint32_t Index); @@ -51,19 +53,58 @@ public: } ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); } - uint32_t getCPUType() const { return Header.cputype; } - uint32_t getCPUSubType() const { return Header.cpusubtype; } - uint32_t getOffset() const { return Header.offset; } - uint32_t getSize() const { return Header.size; } - uint32_t getAlign() const { return Header.align; } + uint32_t getCPUType() const { + if (Parent->getMagic() == MachO::FAT_MAGIC) + return Header.cputype; + else // Parent->getMagic() == MachO::FAT_MAGIC_64 + return Header64.cputype; + } + uint32_t getCPUSubType() const { + if (Parent->getMagic() == MachO::FAT_MAGIC) + return Header.cpusubtype; + else // Parent->getMagic() == MachO::FAT_MAGIC_64 + return Header64.cpusubtype; + } + uint32_t getOffset() const { + if (Parent->getMagic() == MachO::FAT_MAGIC) + return Header.offset; + else // Parent->getMagic() == MachO::FAT_MAGIC_64 + return Header64.offset; + } + uint32_t getSize() const { + if (Parent->getMagic() == MachO::FAT_MAGIC) + return Header.size; + else // Parent->getMagic() == MachO::FAT_MAGIC_64 + return Header64.size; + } + uint32_t getAlign() const { + if (Parent->getMagic() == MachO::FAT_MAGIC) + return Header.align; + else // Parent->getMagic() == MachO::FAT_MAGIC_64 + return Header64.align; + } + uint32_t getReserved() const { + if (Parent->getMagic() == MachO::FAT_MAGIC) + return 0; + else // Parent->getMagic() == MachO::FAT_MAGIC_64 + return Header64.reserved; + } std::string getArchTypeName() const { - Triple T = MachOObjectFile::getArch(Header.cputype, Header.cpusubtype); - return T.getArchName(); + if (Parent->getMagic() == MachO::FAT_MAGIC) { + Triple T = + MachOObjectFile::getArchTriple(Header.cputype, Header.cpusubtype); + return T.getArchName(); + } else { // Parent->getMagic() == MachO::FAT_MAGIC_64 + Triple T = + MachOObjectFile::getArchTriple(Header64.cputype, + Header64.cpusubtype); + return T.getArchName(); + } } - ErrorOr<std::unique_ptr<MachOObjectFile>> getAsObjectFile() const; + Expected<std::unique_ptr<MachOObjectFile>> getAsObjectFile() const; - ErrorOr<std::unique_ptr<Archive>> getAsArchive() const; + Expected<std::unique_ptr<Archive>> getAsArchive() const; }; class object_iterator { @@ -86,8 +127,8 @@ public: } }; - MachOUniversalBinary(MemoryBufferRef Souce, std::error_code &EC); - static ErrorOr<std::unique_ptr<MachOUniversalBinary>> + MachOUniversalBinary(MemoryBufferRef Souce, Error &Err); + static Expected<std::unique_ptr<MachOUniversalBinary>> create(MemoryBufferRef Source); object_iterator begin_objects() const { @@ -101,6 +142,7 @@ public: return make_range(begin_objects(), end_objects()); } + uint32_t getMagic() const { return Magic; } uint32_t getNumberOfObjects() const { return NumberOfObjects; } // Cast methods. @@ -108,7 +150,7 @@ public: return V->isMachOUniversalBinary(); } - ErrorOr<std::unique_ptr<MachOObjectFile>> + Expected<std::unique_ptr<MachOObjectFile>> getObjectForArch(StringRef ArchName) const; }; diff --git a/include/llvm/Object/ModuleSummaryIndexObjectFile.h b/include/llvm/Object/ModuleSummaryIndexObjectFile.h new file mode 100644 index 0000000000000..d021fb29427f0 --- /dev/null +++ b/include/llvm/Object/ModuleSummaryIndexObjectFile.h @@ -0,0 +1,103 @@ +//===- ModuleSummaryIndexObjectFile.h - Summary index file implementation -=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the ModuleSummaryIndexObjectFile template class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_MODULESUMMARYINDEXOBJECTFILE_H +#define LLVM_OBJECT_MODULESUMMARYINDEXOBJECTFILE_H + +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/Object/SymbolicFile.h" + +namespace llvm { +class ModuleSummaryIndex; +class Module; + +namespace object { +class ObjectFile; + +/// This class is used to read just the module summary index related +/// sections out of the given object (which may contain a single module's +/// bitcode or be a combined index bitcode file). It builds a ModuleSummaryIndex +/// object. +class ModuleSummaryIndexObjectFile : public SymbolicFile { + std::unique_ptr<ModuleSummaryIndex> Index; + +public: + ModuleSummaryIndexObjectFile(MemoryBufferRef Object, + std::unique_ptr<ModuleSummaryIndex> I); + ~ModuleSummaryIndexObjectFile() override; + + // TODO: Walk through GlobalValueMap entries for symbols. + // However, currently these interfaces are not used by any consumers. + void moveSymbolNext(DataRefImpl &Symb) const override { + llvm_unreachable("not implemented"); + } + std::error_code printSymbolName(raw_ostream &OS, + DataRefImpl Symb) const override { + llvm_unreachable("not implemented"); + return std::error_code(); + } + uint32_t getSymbolFlags(DataRefImpl Symb) const override { + llvm_unreachable("not implemented"); + return 0; + } + basic_symbol_iterator symbol_begin_impl() const override { + llvm_unreachable("not implemented"); + return basic_symbol_iterator(BasicSymbolRef()); + } + basic_symbol_iterator symbol_end_impl() const override { + llvm_unreachable("not implemented"); + return basic_symbol_iterator(BasicSymbolRef()); + } + + const ModuleSummaryIndex &getIndex() const { + return const_cast<ModuleSummaryIndexObjectFile *>(this)->getIndex(); + } + ModuleSummaryIndex &getIndex() { return *Index; } + std::unique_ptr<ModuleSummaryIndex> takeIndex(); + + static inline bool classof(const Binary *v) { + return v->isModuleSummaryIndex(); + } + + /// \brief Finds and returns bitcode embedded in the given object file, or an + /// error code if not found. + static ErrorOr<MemoryBufferRef> findBitcodeInObject(const ObjectFile &Obj); + + /// \brief Finds and returns bitcode in the given memory buffer (which may + /// be either a bitcode file or a native object file with embedded bitcode), + /// or an error code if not found. + static ErrorOr<MemoryBufferRef> + findBitcodeInMemBuffer(MemoryBufferRef Object); + + /// \brief Looks for summary sections in the given memory buffer, + /// returns true if found, else false. + static bool hasGlobalValueSummaryInMemBuffer( + MemoryBufferRef Object, + const DiagnosticHandlerFunction &DiagnosticHandler); + + /// \brief Parse module summary index in the given memory buffer. + /// Return new ModuleSummaryIndexObjectFile instance containing parsed module + /// summary/index. + static ErrorOr<std::unique_ptr<ModuleSummaryIndexObjectFile>> + create(MemoryBufferRef Object, + const DiagnosticHandlerFunction &DiagnosticHandler); +}; +} + +/// Parse the module summary index out of an IR file and return the module +/// summary index object if found, or nullptr if not. +ErrorOr<std::unique_ptr<ModuleSummaryIndex>> getModuleSummaryIndexForFile( + StringRef Path, const DiagnosticHandlerFunction &DiagnosticHandler); +} + +#endif diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index ce0c891ee0c22..6272a5f056eb8 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -15,13 +15,13 @@ #define LLVM_OBJECT_OBJECTFILE_H #include "llvm/ADT/StringRef.h" +#include "llvm/MC/SubtargetFeature.h" #include "llvm/Object/SymbolicFile.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include <cstring> -#include <vector> namespace llvm { namespace object { @@ -90,10 +90,12 @@ public: /// @brief Get the alignment of this section as the actual value (not log 2). uint64_t getAlignment() const; + bool isCompressed() const; bool isText() const; bool isData() const; bool isBSS() const; bool isVirtual() const; + bool isBitcode() const; bool containsSymbol(SymbolRef S) const; @@ -130,10 +132,10 @@ public: assert(isa<ObjectFile>(BasicSymbolRef::getObject())); } - ErrorOr<StringRef> getName() const; + Expected<StringRef> getName() const; /// Returns the symbol virtual address (i.e. address at which it will be /// mapped). - ErrorOr<uint64_t> getAddress() const; + Expected<uint64_t> getAddress() const; /// Return the value of the symbol depending on the object this can be an /// offset or a virtual address. @@ -142,11 +144,11 @@ public: /// @brief Get the alignment of this symbol as the actual value (not log 2). uint32_t getAlignment() const; uint64_t getCommonSize() const; - SymbolRef::Type getType() const; + Expected<SymbolRef::Type> getType() const; /// @brief Get section this symbol is defined in reference to. Result is /// end_sections() if it is undefined or is an absolute symbol. - ErrorOr<section_iterator> getSection() const; + Expected<section_iterator> getSection() const; const ObjectFile *getObject() const; }; @@ -193,15 +195,15 @@ protected: // Implementations assume that the DataRefImpl is valid and has not been // modified externally. It's UB otherwise. friend class SymbolRef; - virtual ErrorOr<StringRef> getSymbolName(DataRefImpl Symb) const = 0; + virtual Expected<StringRef> getSymbolName(DataRefImpl Symb) const = 0; std::error_code printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; - virtual ErrorOr<uint64_t> getSymbolAddress(DataRefImpl Symb) const = 0; + virtual Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const = 0; virtual uint64_t getSymbolValueImpl(DataRefImpl Symb) const = 0; virtual uint32_t getSymbolAlignment(DataRefImpl Symb) const; virtual uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const = 0; - virtual SymbolRef::Type getSymbolType(DataRefImpl Symb) const = 0; - virtual ErrorOr<section_iterator> + virtual Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const = 0; + virtual Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const = 0; // Same as above for SectionRef. @@ -214,11 +216,13 @@ protected: virtual std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const = 0; virtual uint64_t getSectionAlignment(DataRefImpl Sec) const = 0; + virtual bool isSectionCompressed(DataRefImpl Sec) const = 0; virtual bool isSectionText(DataRefImpl Sec) const = 0; virtual bool isSectionData(DataRefImpl Sec) const = 0; virtual bool isSectionBSS(DataRefImpl Sec) const = 0; // A section is 'virtual' if its contents aren't present in the object image. virtual bool isSectionVirtual(DataRefImpl Sec) const = 0; + virtual bool isSectionBitcode(DataRefImpl Sec) const; virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0; virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0; virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; @@ -259,6 +263,7 @@ public: virtual StringRef getFileFormatName() const = 0; virtual /* Triple::ArchType */ unsigned getArch() const = 0; + virtual SubtargetFeatures getFeatures() const = 0; /// Returns platform-specific object flags, if any. virtual std::error_code getPlatformFlags(unsigned &Result) const { @@ -273,12 +278,12 @@ public: /// @param ObjectPath The path to the object file. ObjectPath.isObject must /// return true. /// @brief Create ObjectFile from path. - static ErrorOr<OwningBinary<ObjectFile>> + static Expected<OwningBinary<ObjectFile>> createObjectFile(StringRef ObjectPath); - static ErrorOr<std::unique_ptr<ObjectFile>> + static Expected<std::unique_ptr<ObjectFile>> createObjectFile(MemoryBufferRef Object, sys::fs::file_magic Type); - static ErrorOr<std::unique_ptr<ObjectFile>> + static Expected<std::unique_ptr<ObjectFile>> createObjectFile(MemoryBufferRef Object) { return createObjectFile(Object, sys::fs::file_magic::unknown); } @@ -294,19 +299,20 @@ public: static ErrorOr<std::unique_ptr<ObjectFile>> createELFObjectFile(MemoryBufferRef Object); - static ErrorOr<std::unique_ptr<MachOObjectFile>> + static Expected<std::unique_ptr<MachOObjectFile>> createMachOObjectFile(MemoryBufferRef Object); + }; // Inline function definitions. inline SymbolRef::SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner) : BasicSymbolRef(SymbolP, Owner) {} -inline ErrorOr<StringRef> SymbolRef::getName() const { +inline Expected<StringRef> SymbolRef::getName() const { return getObject()->getSymbolName(getRawDataRefImpl()); } -inline ErrorOr<uint64_t> SymbolRef::getAddress() const { +inline Expected<uint64_t> SymbolRef::getAddress() const { return getObject()->getSymbolAddress(getRawDataRefImpl()); } @@ -322,11 +328,11 @@ inline uint64_t SymbolRef::getCommonSize() const { return getObject()->getCommonSymbolSize(getRawDataRefImpl()); } -inline ErrorOr<section_iterator> SymbolRef::getSection() const { +inline Expected<section_iterator> SymbolRef::getSection() const { return getObject()->getSymbolSection(getRawDataRefImpl()); } -inline SymbolRef::Type SymbolRef::getType() const { +inline Expected<SymbolRef::Type> SymbolRef::getType() const { return getObject()->getSymbolType(getRawDataRefImpl()); } @@ -378,6 +384,10 @@ inline uint64_t SectionRef::getAlignment() const { return OwningObject->getSectionAlignment(SectionPimpl); } +inline bool SectionRef::isCompressed() const { + return OwningObject->isSectionCompressed(SectionPimpl); +} + inline bool SectionRef::isText() const { return OwningObject->isSectionText(SectionPimpl); } @@ -394,6 +404,10 @@ inline bool SectionRef::isVirtual() const { return OwningObject->isSectionVirtual(SectionPimpl); } +inline bool SectionRef::isBitcode() const { + return OwningObject->isSectionBitcode(SectionPimpl); +} + inline relocation_iterator SectionRef::relocation_begin() const { return OwningObject->section_rel_begin(SectionPimpl); } diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h index d5e4258cb0a76..5e0df98d86279 100644 --- a/include/llvm/Object/RelocVisitor.h +++ b/include/llvm/Object/RelocVisitor.h @@ -16,7 +16,6 @@ #ifndef LLVM_OBJECT_RELOCVISITOR_H #define LLVM_OBJECT_RELOCVISITOR_H -#include "llvm/ADT/StringRef.h" #include "llvm/Object/COFF.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/MachO.h" @@ -175,6 +174,14 @@ private: case llvm::ELF::R_ARM_ABS32: return visitELF_ARM_ABS32(R, Value); } + case Triple::lanai: + switch (RelocType) { + case llvm::ELF::R_LANAI_32: + return visitELF_Lanai_32(R, Value); + default: + HasError = true; + return RelocToApply(); + } case Triple::mipsel: case Triple::mips: switch (RelocType) { @@ -311,6 +318,13 @@ private: return RelocToApply(Res, 4); } + /// Lanai ELF + RelocToApply visitELF_Lanai_32(RelocationRef R, uint64_t Value) { + int64_t Addend = getELFAddend(R); + uint32_t Res = (Value + Addend) & 0xFFFFFFFF; + return RelocToApply(Res, 4); + } + /// MIPS ELF RelocToApply visitELF_MIPS_32(RelocationRef R, uint64_t Value) { uint32_t Res = Value & 0xFFFFFFFF; diff --git a/include/llvm/Object/StackMapParser.h b/include/llvm/Object/StackMapParser.h index 276eab6c294e5..e58162de1501e 100644 --- a/include/llvm/Object/StackMapParser.h +++ b/include/llvm/Object/StackMapParser.h @@ -10,9 +10,8 @@ #ifndef LLVM_CODEGEN_STACKMAPPARSER_H #define LLVM_CODEGEN_STACKMAPPARSER_H -#include "llvm/Support/Debug.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Endian.h" -#include <map> #include <vector> namespace llvm { diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h index 0c5b38111a9c0..894c2670f265c 100644 --- a/include/llvm/Object/SymbolicFile.h +++ b/include/llvm/Object/SymbolicFile.h @@ -16,6 +16,7 @@ #include "llvm/Object/Binary.h" #include "llvm/Support/Format.h" +#include <utility> namespace llvm { namespace object { @@ -58,7 +59,7 @@ class content_iterator content_type Current; public: - content_iterator(content_type symb) : Current(symb) {} + content_iterator(content_type symb) : Current(std::move(symb)) {} const content_type *operator->() const { return &Current; } @@ -153,15 +154,15 @@ public: } // construction aux. - static ErrorOr<std::unique_ptr<SymbolicFile>> + static Expected<std::unique_ptr<SymbolicFile>> createSymbolicFile(MemoryBufferRef Object, sys::fs::file_magic Type, LLVMContext *Context); - static ErrorOr<std::unique_ptr<SymbolicFile>> + static Expected<std::unique_ptr<SymbolicFile>> createSymbolicFile(MemoryBufferRef Object) { return createSymbolicFile(Object, sys::fs::file_magic::unknown, nullptr); } - static ErrorOr<OwningBinary<SymbolicFile>> + static Expected<OwningBinary<SymbolicFile>> createSymbolicFile(StringRef ObjectPath); static inline bool classof(const Binary *v) { |