diff options
author | Stephen Hines <srhines@google.com> | 2014-04-23 16:57:46 -0700 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-04-24 15:53:16 -0700 |
commit | 36b56886974eae4f9c5ebc96befd3e7bfe5de338 (patch) | |
tree | e6cfb69fbbd937f450eeb83bfb83b9da3b01275a /include/llvm/Object | |
parent | 69a8640022b04415ae9fac62f8ab090601d8f889 (diff) | |
download | external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.zip external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.gz external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.bz2 |
Update to LLVM 3.5a.
Change-Id: Ifadecab779f128e62e430c2b4f6ddd84953ed617
Diffstat (limited to 'include/llvm/Object')
-rw-r--r-- | include/llvm/Object/Archive.h | 17 | ||||
-rw-r--r-- | include/llvm/Object/Binary.h | 27 | ||||
-rw-r--r-- | include/llvm/Object/COFF.h | 339 | ||||
-rw-r--r-- | include/llvm/Object/COFFYAML.h | 47 | ||||
-rw-r--r-- | include/llvm/Object/ELF.h | 6 | ||||
-rw-r--r-- | include/llvm/Object/ELFObjectFile.h | 332 | ||||
-rw-r--r-- | include/llvm/Object/ELFYAML.h | 8 | ||||
-rw-r--r-- | include/llvm/Object/Error.h | 6 | ||||
-rw-r--r-- | include/llvm/Object/IRObjectFile.h | 46 | ||||
-rw-r--r-- | include/llvm/Object/MachO.h | 132 | ||||
-rw-r--r-- | include/llvm/Object/MachOUniversal.h | 7 | ||||
-rw-r--r-- | include/llvm/Object/ObjectFile.h | 279 | ||||
-rw-r--r-- | include/llvm/Object/RelocVisitor.h | 70 | ||||
-rw-r--r-- | include/llvm/Object/SymbolicFile.h | 194 |
14 files changed, 983 insertions, 527 deletions
diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h index 1cba519..4fae76f 100644 --- a/include/llvm/Object/Archive.h +++ b/include/llvm/Object/Archive.h @@ -17,6 +17,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Object/Binary.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ErrorOr.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" @@ -90,8 +91,13 @@ public: error_code getMemoryBuffer(OwningPtr<MemoryBuffer> &Result, bool FullPath = false) const; + error_code getMemoryBuffer(std::unique_ptr<MemoryBuffer> &Result, + bool FullPath = false) const; - error_code getAsBinary(OwningPtr<Binary> &Result) const; + error_code getAsBinary(OwningPtr<Binary> &Result, + LLVMContext *Context = 0) const; + error_code getAsBinary(std::unique_ptr<Binary> &Result, + LLVMContext *Context = 0) const; }; class child_iterator { @@ -163,6 +169,7 @@ public: }; Archive(MemoryBuffer *source, error_code &ec); + static ErrorOr<Archive *> create(MemoryBuffer *Source); enum Kind { K_GNU, @@ -174,11 +181,11 @@ public: return Format; } - child_iterator begin_children(bool SkipInternal = true) const; - child_iterator end_children() const; + child_iterator child_begin(bool SkipInternal = true) const; + child_iterator child_end() const; - symbol_iterator begin_symbols() const; - symbol_iterator end_symbols() const; + symbol_iterator symbol_begin() const; + symbol_iterator symbol_end() const; // Cast methods. static inline bool classof(Binary const *v) { diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index a3f5625..b10e40a 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -14,11 +14,13 @@ #ifndef LLVM_OBJECT_BINARY_H #define LLVM_OBJECT_BINARY_H -#include "llvm/ADT/OwningPtr.h" #include "llvm/Object/Error.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/FileSystem.h" namespace llvm { +class LLVMContext; class MemoryBuffer; class StringRef; @@ -30,15 +32,18 @@ private: Binary(const Binary &other) LLVM_DELETED_FUNCTION; unsigned int TypeID; + bool BufferOwned; protected: MemoryBuffer *Data; - Binary(unsigned int Type, MemoryBuffer *Source); + Binary(unsigned int Type, MemoryBuffer *Source, bool BufferOwned = true); enum { ID_Archive, ID_MachOUniversalBinary, + ID_IR, // LLVM IR + // Object and children. ID_StartObjects, ID_COFF, @@ -84,6 +89,10 @@ public: return TypeID > ID_StartObjects && TypeID < ID_EndObjects; } + bool isSymbolic() const { + return isIR() || isObject(); + } + bool isArchive() const { return TypeID == ID_Archive; } @@ -104,6 +113,10 @@ public: return TypeID == ID_COFF; } + bool isIR() const { + return TypeID == ID_IR; + } + bool isLittleEndian() const { return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B || TypeID == ID_MachO32B || TypeID == ID_MachO64B); @@ -113,13 +126,11 @@ public: /// @brief Create a Binary from Source, autodetecting the file type. /// /// @param Source The data to create the Binary from. Ownership is transferred -/// to Result if successful. If an error is returned, Source is destroyed -/// by createBinary before returning. -/// @param Result A pointer to the resulting Binary if no error occured. -error_code createBinary(MemoryBuffer *Source, OwningPtr<Binary> &Result); - -error_code createBinary(StringRef Path, OwningPtr<Binary> &Result); +/// to the Binary if successful. If an error is returned, +/// Source is destroyed by createBinary before returning. +ErrorOr<Binary *> createBinary(MemoryBuffer *Source, LLVMContext *Context = 0); +ErrorOr<Binary *> createBinary(StringRef Path); } } diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index e05ae6c..6e05c2d 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -19,12 +19,13 @@ #include "llvm/Support/Endian.h" namespace llvm { - template <typename T> - class ArrayRef; +template <typename T> class ArrayRef; namespace object { class ImportDirectoryEntryRef; +class ExportDirectoryEntryRef; typedef content_iterator<ImportDirectoryEntryRef> import_directory_iterator; +typedef content_iterator<ExportDirectoryEntryRef> export_directory_iterator; /// The DOS compatible header at the front of all PE/COFF executables. struct dos_header { @@ -64,8 +65,8 @@ struct coff_file_header { /// The 32-bit PE header that follows the COFF header. struct pe32_header { support::ulittle16_t Magic; - uint8_t MajorLinkerVersion; - uint8_t MinorLinkerVersion; + uint8_t MajorLinkerVersion; + uint8_t MinorLinkerVersion; support::ulittle32_t SizeOfCode; support::ulittle32_t SizeOfInitializedData; support::ulittle32_t SizeOfUninitializedData; @@ -98,8 +99,8 @@ struct pe32_header { /// The 64-bit PE header that follows the COFF header. struct pe32plus_header { support::ulittle16_t Magic; - uint8_t MajorLinkerVersion; - uint8_t MinorLinkerVersion; + uint8_t MajorLinkerVersion; + uint8_t MinorLinkerVersion; support::ulittle32_t SizeOfCode; support::ulittle32_t SizeOfInitializedData; support::ulittle32_t SizeOfUninitializedData; @@ -157,6 +158,28 @@ struct import_lookup_table_entry32 { } }; +struct export_directory_table_entry { + support::ulittle32_t ExportFlags; + support::ulittle32_t TimeDateStamp; + support::ulittle16_t MajorVersion; + support::ulittle16_t MinorVersion; + support::ulittle32_t NameRVA; + support::ulittle32_t OrdinalBase; + support::ulittle32_t AddressTableEntries; + support::ulittle32_t NumberOfNamePointers; + support::ulittle32_t ExportAddressTableRVA; + support::ulittle32_t NamePointerRVA; + support::ulittle32_t OrdinalTableRVA; +}; + +union export_address_table_entry { + support::ulittle32_t ExportRVA; + support::ulittle32_t ForwarderRVA; +}; + +typedef support::ulittle32_t export_name_pointer_table_entry; +typedef support::ulittle16_t export_ordinal_table_entry; + struct coff_symbol { struct StringTableOffset { support::ulittle32_t Zeroes; @@ -169,19 +192,50 @@ struct coff_symbol { } Name; support::ulittle32_t Value; - support::little16_t SectionNumber; + support::ulittle16_t SectionNumber; support::ulittle16_t Type; - support::ulittle8_t StorageClass; - support::ulittle8_t NumberOfAuxSymbols; + support::ulittle8_t StorageClass; + support::ulittle8_t NumberOfAuxSymbols; + + uint8_t getBaseType() const { return Type & 0x0F; } + + uint8_t getComplexType() const { return (Type & 0xF0) >> 4; } + + bool isFunctionDefinition() const { + return StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && + getBaseType() == COFF::IMAGE_SYM_TYPE_NULL && + getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION && + !COFF::isReservedSectionNumber(SectionNumber); + } + + bool isFunctionLineInfo() const { + return StorageClass == COFF::IMAGE_SYM_CLASS_FUNCTION; + } + + bool isWeakExternal() const { + return StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL || + (StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && + SectionNumber == COFF::IMAGE_SYM_UNDEFINED && Value == 0); + } + + bool isFileRecord() const { + return StorageClass == COFF::IMAGE_SYM_CLASS_FILE; + } - uint8_t getBaseType() const { - return Type & 0x0F; + bool isSectionDefinition() const { + // C++/CLI creates external ABS symbols for non-const appdomain globals. + // These are also followed by an auxiliary section definition. + bool isAppdomainGlobal = StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && + SectionNumber == COFF::IMAGE_SYM_ABSOLUTE; + bool isOrdinarySection = + StorageClass == COFF::IMAGE_SYM_CLASS_STATIC && Value == 0; + return isAppdomainGlobal || isOrdinarySection; } - uint8_t getComplexType() const { - return (Type & 0xF0) >> 4; + bool isCLRToken() const { + return StorageClass == COFF::IMAGE_SYM_CLASS_CLR_TOKEN; } }; @@ -196,6 +250,13 @@ struct coff_section { support::ulittle16_t NumberOfRelocations; support::ulittle16_t NumberOfLinenumbers; support::ulittle32_t Characteristics; + + // Returns true if the actual number of relocations is stored in + // VirtualAddress field of the first relocation table entry. + bool hasExtendedRelocations() const { + return Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL && + NumberOfRelocations == UINT16_MAX; + }; }; struct coff_relocation { @@ -204,6 +265,22 @@ struct coff_relocation { support::ulittle16_t Type; }; +struct coff_aux_function_definition { + support::ulittle32_t TagIndex; + support::ulittle32_t TotalSize; + support::ulittle32_t PointerToLinenumber; + support::ulittle32_t PointerToNextFunction; + char Unused[2]; +}; + +struct coff_aux_bf_and_ef_symbol { + char Unused1[4]; + support::ulittle16_t Linenumber; + char Unused2[6]; + support::ulittle32_t PointerToNextFunction; + char Unused3[2]; +}; + struct coff_aux_weak_external { support::ulittle32_t TagIndex; support::ulittle32_t Characteristics; @@ -220,104 +297,143 @@ struct coff_aux_section_definition { char Unused[3]; }; +struct coff_aux_clr_token { + support::ulittle8_t AuxType; + support::ulittle8_t Reserved; + support::ulittle32_t SymbolTableIndex; + char Unused[12]; +}; + +struct coff_load_configuration32 { + support::ulittle32_t Characteristics; + support::ulittle32_t TimeDateStamp; + support::ulittle16_t MajorVersion; + support::ulittle16_t MinorVersion; + support::ulittle32_t GlobalFlagsClear; + support::ulittle32_t GlobalFlagsSet; + support::ulittle32_t CriticalSectionDefaultTimeout; + support::ulittle32_t DeCommitFreeBlockThreshold; + support::ulittle32_t DeCommitTotalFreeThreshold; + support::ulittle32_t LockPrefixTable; + support::ulittle32_t MaximumAllocationSize; + support::ulittle32_t VirtualMemoryThreshold; + support::ulittle32_t ProcessAffinityMask; + support::ulittle32_t ProcessHeapFlags; + support::ulittle16_t CSDVersion; + uint16_t Reserved; + support::ulittle32_t EditList; + support::ulittle32_t SecurityCookie; + support::ulittle32_t SEHandlerTable; + support::ulittle32_t SEHandlerCount; +}; + +struct coff_runtime_function_x64 { + support::ulittle32_t BeginAddress; + support::ulittle32_t EndAddress; + support::ulittle32_t UnwindInformation; +}; + class COFFObjectFile : public ObjectFile { private: friend class ImportDirectoryEntryRef; + friend class ExportDirectoryEntryRef; const coff_file_header *COFFHeader; - const pe32_header *PE32Header; - const data_directory *DataDirectory; - const coff_section *SectionTable; - const coff_symbol *SymbolTable; - const char *StringTable; - uint32_t StringTableSize; + const pe32_header *PE32Header; + const pe32plus_header *PE32PlusHeader; + const data_directory *DataDirectory; + const coff_section *SectionTable; + const coff_symbol *SymbolTable; + const char *StringTable; + uint32_t StringTableSize; const import_directory_table_entry *ImportDirectory; - uint32_t NumberOfImportDirectory; + uint32_t NumberOfImportDirectory; + const export_directory_table_entry *ExportDirectory; - error_code getString(uint32_t offset, StringRef &Res) const; + error_code getString(uint32_t offset, StringRef &Res) const; - const coff_symbol *toSymb(DataRefImpl Symb) const; - const coff_section *toSec(DataRefImpl Sec) const; - const coff_relocation *toRel(DataRefImpl Rel) const; + const coff_symbol *toSymb(DataRefImpl Symb) const; + const coff_section *toSec(DataRefImpl Sec) const; + const coff_relocation *toRel(DataRefImpl Rel) const; - error_code initSymbolTablePtr(); - error_code initImportTablePtr(); + error_code initSymbolTablePtr(); + error_code initImportTablePtr(); + error_code initExportTablePtr(); protected: - virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; - virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; - virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; - virtual error_code getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const; - virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; - - virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; - virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const; - virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const; - virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const; - virtual relocation_iterator section_rel_end(DataRefImpl Sec) const; - - virtual error_code getRelocationNext(DataRefImpl Rel, - RelocationRef &Res) const; - virtual error_code getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const; - virtual error_code getRelocationOffset(DataRefImpl Rel, - uint64_t &Res) const; - virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const; - virtual error_code getRelocationType(DataRefImpl Rel, - uint64_t &Res) const; - virtual error_code getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const; - virtual error_code getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const; - - virtual error_code getLibraryNext(DataRefImpl LibData, - LibraryRef &Result) const; - virtual error_code getLibraryPath(DataRefImpl LibData, - StringRef &Result) const; + void moveSymbolNext(DataRefImpl &Symb) const override; + error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const override; + error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const override; + error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; + uint32_t getSymbolFlags(DataRefImpl Symb) const override; + error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const override; + error_code getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const override; + void moveSectionNext(DataRefImpl &Sec) const override; + error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; + error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const override; + error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; + error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; + error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const override; + error_code isSectionText(DataRefImpl Sec, bool &Res) const override; + error_code isSectionData(DataRefImpl Sec, bool &Res) const override; + error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; + error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; + error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; + error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const override; + error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const override; + error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, + bool &Result) const override; + relocation_iterator section_rel_begin(DataRefImpl Sec) const override; + relocation_iterator section_rel_end(DataRefImpl Sec) const override; + bool section_rel_empty(DataRefImpl Sec) const override; + + void moveRelocationNext(DataRefImpl &Rel) const override; + error_code getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const override; + error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const override; + symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const override; + error_code + getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + error_code + getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + + error_code getLibraryNext(DataRefImpl LibData, + LibraryRef &Result) const override; + error_code getLibraryPath(DataRefImpl LibData, + StringRef &Result) const override; public: - COFFObjectFile(MemoryBuffer *Object, error_code &ec); - virtual symbol_iterator begin_symbols() const; - virtual symbol_iterator end_symbols() const; - virtual symbol_iterator begin_dynamic_symbols() const; - virtual symbol_iterator end_dynamic_symbols() const; - virtual library_iterator begin_libraries_needed() const; - virtual library_iterator end_libraries_needed() const; - virtual section_iterator begin_sections() const; - virtual section_iterator end_sections() const; - - const coff_section *getCOFFSection(section_iterator &It) const; - const coff_symbol *getCOFFSymbol(symbol_iterator &It) const; - const coff_relocation *getCOFFRelocation(relocation_iterator &It) const; - - virtual uint8_t getBytesInAddress() const; - virtual StringRef getFileFormatName() const; - virtual unsigned getArch() const; - virtual StringRef getLoadName() const; + COFFObjectFile(MemoryBuffer *Object, error_code &EC, bool BufferOwned = true); + basic_symbol_iterator symbol_begin_impl() const override; + basic_symbol_iterator symbol_end_impl() const override; + library_iterator needed_library_begin() const override; + library_iterator needed_library_end() const override; + section_iterator section_begin() const override; + section_iterator section_end() const override; + + const coff_section *getCOFFSection(const SectionRef &Section) const; + const coff_symbol *getCOFFSymbol(const SymbolRef &Symbol) const; + const coff_relocation *getCOFFRelocation(const RelocationRef &Reloc) const; + + uint8_t getBytesInAddress() const override; + StringRef getFileFormatName() const override; + unsigned getArch() const override; + StringRef getLoadName() const override; import_directory_iterator import_directory_begin() const; import_directory_iterator import_directory_end() const; + export_directory_iterator export_directory_begin() const; + export_directory_iterator export_directory_end() const; error_code getHeader(const coff_file_header *&Res) const; error_code getCOFFHeader(const coff_file_header *&Res) const; error_code getPE32Header(const pe32_header *&Res) const; + error_code getPE32PlusHeader(const pe32plus_header *&Res) const; error_code getDataDirectory(uint32_t index, const data_directory *&Res) const; error_code getSection(int32_t index, const coff_section *&Res) const; error_code getSymbol(uint32_t index, const coff_symbol *&Res) const; @@ -325,7 +441,7 @@ public: error_code getAuxSymbol(uint32_t index, const T *&Res) const { const coff_symbol *s; error_code ec = getSymbol(index, s); - Res = reinterpret_cast<const T*>(s); + Res = reinterpret_cast<const T *>(s); return ec; } error_code getSymbolName(const coff_symbol *symbol, StringRef &Res) const; @@ -335,24 +451,23 @@ public: error_code getSectionContents(const coff_section *Sec, ArrayRef<uint8_t> &Res) const; + error_code getVaPtr(uint64_t VA, uintptr_t &Res) const; error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const; error_code getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const; - static inline bool classof(const Binary *v) { - return v->isCOFF(); - } + static inline bool classof(const Binary *v) { return v->isCOFF(); } }; // The iterator for the import directory table. class ImportDirectoryEntryRef { public: ImportDirectoryEntryRef() : OwningObject(0) {} - ImportDirectoryEntryRef(DataRefImpl ImportDirectory, + ImportDirectoryEntryRef(const import_directory_table_entry *Table, uint32_t I, const COFFObjectFile *Owner) - : ImportDirectoryPimpl(ImportDirectory), OwningObject(Owner) {} + : ImportTable(Table), Index(I), OwningObject(Owner) {} bool operator==(const ImportDirectoryEntryRef &Other) const; - error_code getNext(ImportDirectoryEntryRef &Result) const; + void moveNext(); error_code getName(StringRef &Result) const; error_code @@ -362,7 +477,31 @@ public: getImportLookupEntry(const import_lookup_table_entry32 *&Result) const; private: - DataRefImpl ImportDirectoryPimpl; + const import_directory_table_entry *ImportTable; + uint32_t Index; + const COFFObjectFile *OwningObject; +}; + +// The iterator for the export directory table entry. +class ExportDirectoryEntryRef { +public: + ExportDirectoryEntryRef() : OwningObject(0) {} + ExportDirectoryEntryRef(const export_directory_table_entry *Table, uint32_t I, + const COFFObjectFile *Owner) + : ExportTable(Table), Index(I), OwningObject(Owner) {} + + bool operator==(const ExportDirectoryEntryRef &Other) const; + void moveNext(); + + error_code getDllName(StringRef &Result) const; + error_code getOrdinalBase(uint32_t &Result) const; + error_code getOrdinal(uint32_t &Result) const; + error_code getExportRVA(uint32_t &Result) const; + error_code getSymbolName(StringRef &Result) const; + +private: + const export_directory_table_entry *ExportTable; + uint32_t Index; const COFFObjectFile *OwningObject; }; } // end namespace object diff --git a/include/llvm/Object/COFFYAML.h b/include/llvm/Object/COFFYAML.h index 3fa3ec6..b5f9ccc 100644 --- a/include/llvm/Object/COFFYAML.h +++ b/include/llvm/Object/COFFYAML.h @@ -14,6 +14,7 @@ #ifndef LLVM_OBJECT_COFFYAML_H #define LLVM_OBJECT_COFFYAML_H +#include "llvm/ADT/Optional.h" #include "llvm/Object/YAML.h" #include "llvm/Support/COFF.h" @@ -35,6 +36,10 @@ inline SectionCharacteristics operator|(SectionCharacteristics a, // 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; @@ -54,7 +59,12 @@ namespace COFFYAML { COFF::symbol Header; COFF::SymbolBaseType SimpleType; COFF::SymbolComplexType ComplexType; - object::yaml::BinaryRef AuxiliaryData; + 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(); }; @@ -76,6 +86,21 @@ 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); }; @@ -120,6 +145,26 @@ 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); diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index 6c000bb..824e06e 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -33,8 +33,6 @@ #include <limits> #include <utility> -#include <ctype.h> - namespace llvm { namespace object { @@ -53,8 +51,8 @@ template <class ELFT> class ELFFile { public: LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - typedef typename conditional<ELFT::Is64Bits, - uint64_t, uint32_t>::type uintX_t; + typedef typename std::conditional<ELFT::Is64Bits, + uint64_t, uint32_t>::type uintX_t; /// \brief Iterate over constant sized entities. template <class EntT> diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index 962a3e2..2958067 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -44,6 +44,7 @@ public: typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym; typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr; + typedef typename ELFFile<ELFT>::Elf_Ehdr Elf_Ehdr; typedef typename ELFFile<ELFT>::Elf_Rel Elf_Rel; typedef typename ELFFile<ELFT>::Elf_Rela Elf_Rela; typedef typename ELFFile<ELFT>::Elf_Dyn Elf_Dyn; @@ -55,53 +56,52 @@ public: protected: ELFFile<ELFT> EF; - virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; - virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; - virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Res) const; - virtual error_code getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const; - virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; - - virtual error_code getLibraryNext(DataRefImpl Data, LibraryRef &Result) const; - virtual error_code getLibraryPath(DataRefImpl Data, StringRef &Res) const; - - virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; - virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const; - virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; - virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const; - virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const; - virtual relocation_iterator section_rel_end(DataRefImpl Sec) const; - virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; - - virtual error_code getRelocationNext(DataRefImpl Rel, - RelocationRef &Res) const; - virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const; - virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; - virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const; - virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const; - virtual error_code getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const; - virtual error_code - getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const; + void moveSymbolNext(DataRefImpl &Symb) const override; + error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const override; + error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const override; + error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const override; + error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; + uint32_t getSymbolFlags(DataRefImpl Symb) const override; + error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const override; + error_code getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const override; + + error_code getLibraryNext(DataRefImpl Data, + LibraryRef &Result) const override; + error_code getLibraryPath(DataRefImpl Data, StringRef &Res) const override; + + void moveSectionNext(DataRefImpl &Sec) const override; + error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; + error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const override; + error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; + error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; + error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const override; + error_code isSectionText(DataRefImpl Sec, bool &Res) const override; + error_code isSectionData(DataRefImpl Sec, bool &Res) const override; + error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; + error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const override; + error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; + error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; + error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const override; + error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, + bool &Result) const override; + relocation_iterator section_rel_begin(DataRefImpl Sec) const override; + relocation_iterator section_rel_end(DataRefImpl Sec) const override; + bool section_rel_empty(DataRefImpl Sec) const override; + section_iterator getRelocatedSection(DataRefImpl Sec) const override; + + void moveRelocationNext(DataRefImpl &Rel) const override; + error_code getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const override; + error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const override; + symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const override; + error_code getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + error_code getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; uint64_t getROffset(DataRefImpl Rel) const; StringRef getRelocationTypeName(uint32_t Type) const; @@ -165,31 +165,31 @@ protected: bool isDyldELFObject; public: - ELFObjectFile(MemoryBuffer *Object, error_code &ec); + ELFObjectFile(MemoryBuffer *Object, error_code &EC, bool BufferOwned = true); const Elf_Sym *getSymbol(DataRefImpl Symb) const; - virtual symbol_iterator begin_symbols() const; - virtual symbol_iterator end_symbols() const; + basic_symbol_iterator symbol_begin_impl() const override; + basic_symbol_iterator symbol_end_impl() const override; - virtual symbol_iterator begin_dynamic_symbols() const; - virtual symbol_iterator end_dynamic_symbols() const; + symbol_iterator dynamic_symbol_begin() const; + symbol_iterator dynamic_symbol_end() const; - virtual section_iterator begin_sections() const; - virtual section_iterator end_sections() const; + section_iterator section_begin() const override; + section_iterator section_end() const override; - virtual library_iterator begin_libraries_needed() const; - virtual library_iterator end_libraries_needed() const; + library_iterator needed_library_begin() const override; + library_iterator needed_library_end() const override; error_code getRelocationAddend(DataRefImpl Rel, int64_t &Res) const; error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, bool &IsDefault) const; - virtual uint8_t getBytesInAddress() const; - virtual StringRef getFileFormatName() const; - virtual StringRef getObjectType() const { return "ELF"; } - virtual unsigned getArch() const; - virtual StringRef getLoadName() const; + + uint8_t getBytesInAddress() const override; + StringRef getFileFormatName() const override; + unsigned getArch() const override; + StringRef getLoadName() const override; const ELFFile<ELFT> *getELFFile() const { return &EF; } @@ -208,10 +208,8 @@ typedef ELFObjectFile<ELFType<support::big, 2, false> > ELF32BEObjectFile; typedef ELFObjectFile<ELFType<support::big, 2, true> > ELF64BEObjectFile; template <class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolNext(DataRefImpl Symb, - SymbolRef &Result) const { - Result = SymbolRef(toDRI(++toELFSymIter(Symb)), this); - return object_error::success; +void ELFObjectFile<ELFT>::moveSymbolNext(DataRefImpl &Symb) const { + Symb = toDRI(++toELFSymIter(Symb)); } template <class ELFT> @@ -219,7 +217,7 @@ error_code ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Symb, StringRef &Result) const { ErrorOr<StringRef> Name = EF.getSymbolName(toELFSymIter(Symb)); if (!Name) - return Name; + return Name.getError(); Result = *Name; return object_error::success; } @@ -233,49 +231,15 @@ error_code ELFObjectFile<ELFT>::getSymbolVersion(SymbolRef SymRef, ErrorOr<StringRef> Ver = EF.getSymbolVersion(EF.getSection(Symb.d.b), symb, IsDefault); if (!Ver) - return Ver; + return Ver.getError(); Version = *Ver; return object_error::success; } template <class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolFileOffset(DataRefImpl Symb, - uint64_t &Result) const { - const Elf_Sym *ESym = getSymbol(Symb); - const Elf_Shdr *ESec; - switch (EF.getSymbolTableIndex(ESym)) { - case ELF::SHN_COMMON: - // Unintialized symbols have no offset in the object file - case ELF::SHN_UNDEF: - Result = UnknownAddressOrSize; - return object_error::success; - case ELF::SHN_ABS: - Result = ESym->st_value; - return object_error::success; - default: - ESec = EF.getSection(ESym); - } - - switch (ESym->getType()) { - case ELF::STT_SECTION: - Result = ESec ? ESec->sh_offset : UnknownAddressOrSize; - return object_error::success; - case ELF::STT_FUNC: - case ELF::STT_OBJECT: - case ELF::STT_NOTYPE: - Result = ESym->st_value + (ESec ? ESec->sh_offset : 0); - return object_error::success; - default: - Result = UnknownAddressOrSize; - return object_error::success; - } -} - -template <class ELFT> error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb, uint64_t &Result) const { const Elf_Sym *ESym = getSymbol(Symb); - const Elf_Shdr *ESec; switch (EF.getSymbolTableIndex(ESym)) { case ELF::SHN_COMMON: case ELF::SHN_UNDEF: @@ -285,38 +249,21 @@ error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb, Result = ESym->st_value; return object_error::success; default: - ESec = EF.getSection(ESym); + break; } - switch (ESym->getType()) { - case ELF::STT_SECTION: - Result = ESec ? ESec->sh_addr : UnknownAddressOrSize; - return object_error::success; - case ELF::STT_FUNC: - case ELF::STT_OBJECT: - case ELF::STT_NOTYPE: - bool IsRelocatable; - switch (EF.getHeader()->e_type) { - case ELF::ET_EXEC: - case ELF::ET_DYN: - IsRelocatable = false; - break; - default: - IsRelocatable = true; - } - Result = ESym->st_value; + const Elf_Ehdr *Header = EF.getHeader(); + Result = ESym->st_value; - // Clear the ARM/Thumb indicator flag. - if (EF.getHeader()->e_machine == ELF::EM_ARM) - Result &= ~1; + // Clear the ARM/Thumb indicator flag. + if (EF.getHeader()->e_machine == ELF::EM_ARM && + ESym->getType() == ELF::STT_FUNC) + Result &= ~1; - if (IsRelocatable && ESec != 0) - Result += ESec->sh_addr; - return object_error::success; - default: - Result = UnknownAddressOrSize; - return object_error::success; - } + if (Header->e_type == ELF::ET_REL) + Result += EF.getSection(ESym)->sh_addr; + + return object_error::success; } template <class ELFT> @@ -368,11 +315,11 @@ error_code ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb, } template <class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Symb, - uint32_t &Result) const { - const Elf_Sym *ESym = getSymbol(Symb); +uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Symb) const { + Elf_Sym_Iter EIter = toELFSymIter(Symb); + const Elf_Sym *ESym = &*EIter; - Result = SymbolRef::SF_None; + uint32_t Result = SymbolRef::SF_None; if (ESym->getBinding() != ELF::STB_LOCAL) Result |= SymbolRef::SF_Global; @@ -384,7 +331,7 @@ error_code ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Symb, Result |= SymbolRef::SF_Absolute; if (ESym->getType() == ELF::STT_FILE || ESym->getType() == ELF::STT_SECTION || - ESym == &*EF.begin_symbols()) + EIter == EF.begin_symbols() || EIter == EF.begin_dynamic_symbols()) Result |= SymbolRef::SF_FormatSpecific; if (EF.getSymbolTableIndex(ESym) == ELF::SHN_UNDEF) @@ -394,10 +341,7 @@ error_code ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Symb, EF.getSymbolTableIndex(ESym) == ELF::SHN_COMMON) Result |= SymbolRef::SF_Common; - if (ESym->getType() == ELF::STT_TLS) - Result |= SymbolRef::SF_ThreadLocal; - - return object_error::success; + return Result; } template <class ELFT> @@ -406,7 +350,7 @@ error_code ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb, const Elf_Sym *ESym = getSymbol(Symb); const Elf_Shdr *ESec = EF.getSection(ESym); if (!ESec) - Res = end_sections(); + Res = section_end(); else { DataRefImpl Sec; Sec.p = reinterpret_cast<intptr_t>(ESec); @@ -416,18 +360,8 @@ error_code ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb, } template <class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolValue(DataRefImpl Symb, - uint64_t &Val) const { - const Elf_Sym *ESym = getSymbol(Symb); - Val = ESym->st_value; - return object_error::success; -} - -template <class ELFT> -error_code ELFObjectFile<ELFT>::getSectionNext(DataRefImpl Sec, - SectionRef &Result) const { - Result = SectionRef(toDRI(++toELFShdrIter(Sec)), this); - return object_error::success; +void ELFObjectFile<ELFT>::moveSectionNext(DataRefImpl &Sec) const { + Sec = toDRI(++toELFShdrIter(Sec)); } template <class ELFT> @@ -435,7 +369,7 @@ error_code ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec, StringRef &Result) const { ErrorOr<StringRef> Name = EF.getSectionName(&*toELFShdrIter(Sec)); if (!Name) - return Name; + return Name.getError(); Result = *Name; return object_error::success; } @@ -563,15 +497,21 @@ ELFObjectFile<ELFT>::section_rel_end(DataRefImpl Sec) const { } template <class ELFT> +bool ELFObjectFile<ELFT>::section_rel_empty(DataRefImpl Sec) const { + const Elf_Shdr *S = reinterpret_cast<const Elf_Shdr *>(Sec.p); + return S->sh_size == 0; +} + +template <class ELFT> section_iterator ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const { if (EF.getHeader()->e_type != ELF::ET_REL) - return end_sections(); + return section_end(); Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); uintX_t Type = EShdr->sh_type; if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA) - return end_sections(); + return section_end(); const Elf_Shdr *R = EF.getSection(EShdr->sh_info); return section_iterator(SectionRef(toDRI(R), this)); @@ -579,11 +519,8 @@ ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const { // Relocations template <class ELFT> -error_code ELFObjectFile<ELFT>::getRelocationNext(DataRefImpl Rel, - RelocationRef &Result) const { +void ELFObjectFile<ELFT>::moveRelocationNext(DataRefImpl &Rel) const { ++Rel.d.b; - Result = RelocationRef(Rel, this); - return object_error::success; } template <class ELFT> @@ -604,7 +541,7 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const { } } if (!symbolIdx) - return end_symbols(); + return symbol_end(); const Elf_Shdr *SymSec = EF.getSection(sec->sh_link); @@ -626,6 +563,9 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const { template <class ELFT> error_code ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel, uint64_t &Result) const { + assert((EF.getHeader()->e_type == ELF::ET_EXEC || + EF.getHeader()->e_type == ELF::ET_DYN) && + "Only executable and shared objects files have relocation addresses"); Result = getROffset(Rel); return object_error::success; } @@ -633,6 +573,8 @@ error_code ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel, template <class ELFT> error_code ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel, uint64_t &Result) const { + assert(EF.getHeader()->e_type == ELF::ET_REL && + "Only relocatable object files have relocation offsets"); Result = getROffset(Rel); return object_error::success; } @@ -743,7 +685,7 @@ error_code ELFObjectFile<ELFT>::getRelocationValueString( ErrorOr<StringRef> SymName = EF.getSymbolName(EF.getSection(sec->sh_link), symb); if (!SymName) - return SymName; + return SymName.getError(); switch (EF.getHeader()->e_machine) { case ELF::EM_X86_64: switch (type) { @@ -783,6 +725,7 @@ error_code ELFObjectFile<ELFT>::getRelocationValueString( } case ELF::EM_ARM: case ELF::EM_HEXAGON: + case ELF::EM_MIPS: res = *SymName; break; default: @@ -812,40 +755,41 @@ ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const { } template <class ELFT> -ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec) +ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec, + bool BufferOwned) : ObjectFile(getELFType(static_cast<endianness>(ELFT::TargetEndianness) == support::little, ELFT::Is64Bits), - Object), + Object, BufferOwned), EF(Object, ec) {} template <class ELFT> -symbol_iterator ELFObjectFile<ELFT>::begin_symbols() const { - return symbol_iterator(SymbolRef(toDRI(EF.begin_symbols()), this)); +basic_symbol_iterator ELFObjectFile<ELFT>::symbol_begin_impl() const { + return basic_symbol_iterator(SymbolRef(toDRI(EF.begin_symbols()), this)); } template <class ELFT> -symbol_iterator ELFObjectFile<ELFT>::end_symbols() const { - return symbol_iterator(SymbolRef(toDRI(EF.end_symbols()), this)); +basic_symbol_iterator ELFObjectFile<ELFT>::symbol_end_impl() const { + return basic_symbol_iterator(SymbolRef(toDRI(EF.end_symbols()), this)); } template <class ELFT> -symbol_iterator ELFObjectFile<ELFT>::begin_dynamic_symbols() const { +symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_begin() const { return symbol_iterator(SymbolRef(toDRI(EF.begin_dynamic_symbols()), this)); } template <class ELFT> -symbol_iterator ELFObjectFile<ELFT>::end_dynamic_symbols() const { +symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_end() const { return symbol_iterator(SymbolRef(toDRI(EF.end_dynamic_symbols()), this)); } template <class ELFT> -section_iterator ELFObjectFile<ELFT>::begin_sections() const { +section_iterator ELFObjectFile<ELFT>::section_begin() const { return section_iterator(SectionRef(toDRI(EF.begin_sections()), this)); } template <class ELFT> -section_iterator ELFObjectFile<ELFT>::end_sections() const { +section_iterator ELFObjectFile<ELFT>::section_end() const { return section_iterator(SectionRef(toDRI(EF.end_sections()), this)); } @@ -863,7 +807,7 @@ StringRef ELFObjectFile<ELFT>::getLoadName() const { } template <class ELFT> -library_iterator ELFObjectFile<ELFT>::begin_libraries_needed() const { +library_iterator ELFObjectFile<ELFT>::needed_library_begin() const { Elf_Dyn_Iter DI = EF.begin_dynamic_table(); Elf_Dyn_Iter DE = EF.end_dynamic_table(); @@ -896,7 +840,7 @@ error_code ELFObjectFile<ELFT>::getLibraryPath(DataRefImpl Data, } template <class ELFT> -library_iterator ELFObjectFile<ELFT>::end_libraries_needed() const { +library_iterator ELFObjectFile<ELFT>::needed_library_end() const { return library_iterator(LibraryRef(toDRI(EF.end_dynamic_table()), this)); } @@ -922,6 +866,9 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { return "ELF32-mips"; case ELF::EM_PPC: return "ELF32-ppc"; + case ELF::EM_SPARC: + case ELF::EM_SPARC32PLUS: + return "ELF32-sparc"; default: return "ELF32-unknown"; } @@ -937,6 +884,10 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { return "ELF64-ppc64"; case ELF::EM_S390: return "ELF64-s390"; + case ELF::EM_SPARCV9: + return "ELF64-sparc"; + case ELF::EM_MIPS: + return "ELF64-mips"; default: return "ELF64-unknown"; } @@ -967,6 +918,13 @@ unsigned ELFObjectFile<ELFT>::getArch() const { : Triple::ppc64; case ELF::EM_S390: return Triple::systemz; + + case ELF::EM_SPARC: + case ELF::EM_SPARC32PLUS: + return Triple::sparc; + case ELF::EM_SPARCV9: + return Triple::sparcv9; + default: return Triple::UnknownArch; } @@ -974,8 +932,8 @@ unsigned ELFObjectFile<ELFT>::getArch() const { /// FIXME: Maybe we should have a base ElfObjectFile that is not a template /// and make these member functions? -static inline error_code getELFRelocationAddend(const RelocationRef R, - int64_t &Addend) { +inline error_code getELFRelocationAddend(const RelocationRef R, + int64_t &Addend) { const ObjectFile *Obj = R.getObjectFile(); DataRefImpl DRI = R.getRawDataRefImpl(); // Little-endian 32-bit @@ -997,12 +955,30 @@ static inline error_code getELFRelocationAddend(const RelocationRef R, llvm_unreachable("Object passed to getELFRelocationAddend() is not ELF"); } +inline std::pair<symbol_iterator, symbol_iterator> +getELFDynamicSymbolIterators(SymbolicFile *Obj) { + if (const ELF32LEObjectFile *ELF = dyn_cast<ELF32LEObjectFile>(Obj)) + return std::make_pair(ELF->dynamic_symbol_begin(), + ELF->dynamic_symbol_end()); + if (const ELF64LEObjectFile *ELF = dyn_cast<ELF64LEObjectFile>(Obj)) + return std::make_pair(ELF->dynamic_symbol_begin(), + ELF->dynamic_symbol_end()); + if (const ELF32BEObjectFile *ELF = dyn_cast<ELF32BEObjectFile>(Obj)) + return std::make_pair(ELF->dynamic_symbol_begin(), + ELF->dynamic_symbol_end()); + if (const ELF64BEObjectFile *ELF = cast<ELF64BEObjectFile>(Obj)) + return std::make_pair(ELF->dynamic_symbol_begin(), + ELF->dynamic_symbol_end()); + + llvm_unreachable( + "Object passed to getELFDynamicSymbolIterators() is not ELF"); +} + /// This is a generic interface for retrieving GNU symbol version /// information from an ELFObjectFile. -static inline error_code GetELFSymbolVersion(const ObjectFile *Obj, - const SymbolRef &Sym, - StringRef &Version, - bool &IsDefault) { +inline error_code GetELFSymbolVersion(const ObjectFile *Obj, + const SymbolRef &Sym, StringRef &Version, + bool &IsDefault) { // Little-endian 32-bit if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); diff --git a/include/llvm/Object/ELFYAML.h b/include/llvm/Object/ELFYAML.h index fca965f..1eba660 100644 --- a/include/llvm/Object/ELFYAML.h +++ b/include/llvm/Object/ELFYAML.h @@ -37,6 +37,8 @@ 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) // Just use 64, since it can hold 32-bit values too. LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_SHF) @@ -50,6 +52,7 @@ struct FileHeader { ELF_ELFOSABI OSABI; ELF_ET Type; ELF_EM Machine; + ELF_EF Flags; llvm::yaml::Hex64 Entry; }; struct Symbol { @@ -118,6 +121,11 @@ struct ScalarEnumerationTraits<ELFYAML::ELF_ELFOSABI> { }; 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); }; diff --git a/include/llvm/Object/Error.h b/include/llvm/Object/Error.h index 8b0570b..779c747 100644 --- a/include/llvm/Object/Error.h +++ b/include/llvm/Object/Error.h @@ -41,10 +41,10 @@ inline error_code make_error_code(object_error e) { } // end namespace object. -template <> struct is_error_code_enum<object::object_error> : true_type { }; +template <> struct is_error_code_enum<object::object_error> : std::true_type {}; -template <> struct is_error_code_enum<object::object_error::Impl> : true_type { -}; +template <> +struct is_error_code_enum<object::object_error::Impl> : std::true_type {}; } // end namespace llvm. diff --git a/include/llvm/Object/IRObjectFile.h b/include/llvm/Object/IRObjectFile.h new file mode 100644 index 0000000..78f5b2b --- /dev/null +++ b/include/llvm/Object/IRObjectFile.h @@ -0,0 +1,46 @@ +//===- IRObjectFile.h - LLVM IR object file 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 the IRObjectFile template class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_IR_OBJECT_FILE_H +#define LLVM_OBJECT_IR_OBJECT_FILE_H + +#include "llvm/Object/SymbolicFile.h" + +namespace llvm { +class Mangler; +class Module; +class GlobalValue; + +namespace object { +class IRObjectFile : public SymbolicFile { + std::unique_ptr<Module> M; + std::unique_ptr<Mangler> Mang; + +public: + IRObjectFile(MemoryBuffer *Object, error_code &EC, LLVMContext &Context, + bool BufferOwned); + void moveSymbolNext(DataRefImpl &Symb) const override; + error_code printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; + uint32_t getSymbolFlags(DataRefImpl Symb) const override; + const GlobalValue &getSymbolGV(DataRefImpl Symb) const; + basic_symbol_iterator symbol_begin_impl() const override; + basic_symbol_iterator symbol_end_impl() const override; + + static inline bool classof(const Binary *v) { + return v->isIR(); + } +}; +} +} + +#endif diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 100613a..f242611 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -38,7 +38,7 @@ public: bool operator==(const DiceRef &Other) const; bool operator<(const DiceRef &Other) const; - error_code getNext(DiceRef &Result) const; + void moveNext(); error_code getOffset(uint32_t &Result) const; error_code getLength(uint16_t &Result) const; @@ -57,76 +57,73 @@ public: }; MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits, - error_code &ec); - - virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; - virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; - virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Res) const; - virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const; - virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; - - virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; - virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const; - virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; - virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const; - virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const; - virtual relocation_iterator section_rel_end(DataRefImpl Sec) const; - - virtual error_code getRelocationNext(DataRefImpl Rel, - RelocationRef &Res) const; - virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const; - virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; - virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const; - virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const; - virtual error_code getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const; - virtual error_code getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const; - virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const; - - virtual error_code getLibraryNext(DataRefImpl LibData, LibraryRef &Res) const; - virtual error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const; + error_code &EC, bool BufferOwned = true); + + void moveSymbolNext(DataRefImpl &Symb) const override; + error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const override; + error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const override; + error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const override; + error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; + error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const override; + uint32_t getSymbolFlags(DataRefImpl Symb) const override; + error_code getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const override; + + void moveSectionNext(DataRefImpl &Sec) const override; + error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; + error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const override; + error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; + error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; + error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const override; + error_code isSectionText(DataRefImpl Sec, bool &Res) const override; + error_code isSectionData(DataRefImpl Sec, bool &Res) const override; + error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; + error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const override; + error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; + error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; + error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const override; + error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, + bool &Result) const override; + relocation_iterator section_rel_begin(DataRefImpl Sec) const override; + relocation_iterator section_rel_end(DataRefImpl Sec) const override; + bool section_rel_empty(DataRefImpl Sec) const override; + + void moveRelocationNext(DataRefImpl &Rel) const override; + error_code getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const override; + error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const override; + symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const override; + error_code getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + error_code getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const override; + + error_code getLibraryNext(DataRefImpl LibData, + LibraryRef &Res) const override; + error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const override; // TODO: Would be useful to have an iterator based version // of the load command interface too. - virtual symbol_iterator begin_symbols() const; - virtual symbol_iterator end_symbols() const; + basic_symbol_iterator symbol_begin_impl() const override; + basic_symbol_iterator symbol_end_impl() const override; - virtual symbol_iterator begin_dynamic_symbols() const; - virtual symbol_iterator end_dynamic_symbols() const; + section_iterator section_begin() const override; + section_iterator section_end() const override; - virtual section_iterator begin_sections() const; - virtual section_iterator end_sections() const; + library_iterator needed_library_begin() const override; + library_iterator needed_library_end() const override; - virtual library_iterator begin_libraries_needed() const; - virtual library_iterator end_libraries_needed() const; + uint8_t getBytesInAddress() const override; - virtual uint8_t getBytesInAddress() const; + StringRef getFileFormatName() const override; + unsigned getArch() const override; - virtual StringRef getFileFormatName() const; - virtual unsigned getArch() const; - - virtual StringRef getLoadName() const; + StringRef getLoadName() const override; relocation_iterator section_rel_begin(unsigned Index) const; relocation_iterator section_rel_end(unsigned Index) const; @@ -179,6 +176,8 @@ public: getSegment64LoadCommand(const LoadCommandInfo &L) const; MachO::linker_options_command getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const; + MachO::version_min_command + getVersionMinLoadCommand(const LoadCommandInfo &L) const; MachO::any_relocation_info getRelocation(DataRefImpl Rel) const; MachO::data_in_code_entry getDice(DataRefImpl Rel) const; @@ -223,13 +222,10 @@ inline bool DiceRef::operator<(const DiceRef &Other) const { return DicePimpl < Other.DicePimpl; } -inline error_code DiceRef::getNext(DiceRef &Result) const { - DataRefImpl Rel = DicePimpl; +inline void DiceRef::moveNext() { const MachO::data_in_code_entry *P = - reinterpret_cast<const MachO::data_in_code_entry *>(Rel.p); - Rel.p = reinterpret_cast<uintptr_t>(P + 1); - Result = DiceRef(Rel, OwningObject); - return object_error::success; + reinterpret_cast<const MachO::data_in_code_entry *>(DicePimpl.p); + DicePimpl.p = reinterpret_cast<uintptr_t>(P + 1); } // Since a Mach-O data in code reference, a DiceRef, can only be created when diff --git a/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h index c5d1359..9b1afd2 100644 --- a/include/llvm/Object/MachOUniversal.h +++ b/include/llvm/Object/MachOUniversal.h @@ -14,10 +14,10 @@ #ifndef LLVM_OBJECT_MACHOUNIVERSAL_H #define LLVM_OBJECT_MACHOUNIVERSAL_H -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/Object/Binary.h" +#include "llvm/Support/ErrorOr.h" #include "llvm/Support/MachO.h" namespace llvm { @@ -52,7 +52,7 @@ public: ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); } uint32_t getCPUType() const { return Header.cputype; } - error_code getAsObjectFile(OwningPtr<ObjectFile> &Result) const; + error_code getAsObjectFile(std::unique_ptr<ObjectFile> &Result) const; }; class object_iterator { @@ -77,6 +77,7 @@ public: }; MachOUniversalBinary(MemoryBuffer *Source, error_code &ec); + static ErrorOr<MachOUniversalBinary*> create(MemoryBuffer *Source); object_iterator begin_objects() const { return ObjectForArch(this, 0); @@ -93,7 +94,7 @@ public: } error_code getObjectForArch(Triple::ArchType Arch, - OwningPtr<ObjectFile> &Result) const; + std::unique_ptr<ObjectFile> &Result) const; }; } diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index 9aea639..8298b63 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -15,9 +15,10 @@ #define LLVM_OBJECT_OBJECTFILE_H #include "llvm/ADT/StringRef.h" -#include "llvm/Object/Binary.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> @@ -27,65 +28,8 @@ namespace object { class ObjectFile; -union DataRefImpl { - // This entire union should probably be a - // char[max(8, sizeof(uintptr_t))] and require the impl to cast. - struct { - uint32_t a, b; - } d; - uintptr_t p; - DataRefImpl() { - std::memset(this, 0, sizeof(DataRefImpl)); - } -}; - -template<class content_type> -class content_iterator { - content_type Current; -public: - content_iterator(content_type symb) - : Current(symb) {} - - const content_type* operator->() const { - return &Current; - } - - const content_type &operator*() const { - return Current; - } - - bool operator==(const content_iterator &other) const { - return Current == other.Current; - } - - bool operator!=(const content_iterator &other) const { - return !(*this == other); - } - - content_iterator& increment(error_code &err) { - content_type next; - if (error_code ec = Current.getNext(next)) - err = ec; - else - Current = next; - return *this; - } -}; - -inline bool operator==(const DataRefImpl &a, const DataRefImpl &b) { - // Check bitwise identical. This is the only legal way to compare a union w/o - // knowing which member is in use. - return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0; -} - -inline bool operator<(const DataRefImpl &a, const DataRefImpl &b) { - // Check bitwise identical. This is the only legal way to compare a union w/o - // knowing which member is in use. - return std::memcmp(&a, &b, sizeof(DataRefImpl)) < 0; -} - class SymbolRef; -typedef content_iterator<SymbolRef> symbol_iterator; +class symbol_iterator; /// RelocationRef - This is a value type class that represents a single /// relocation in the list of relocations in the object file. @@ -100,7 +44,7 @@ public: bool operator==(const RelocationRef &Other) const; - error_code getNext(RelocationRef &Result) const; + void moveNext(); error_code getAddress(uint64_t &Result) const; error_code getOffset(uint64_t &Result) const; @@ -143,9 +87,10 @@ public: SectionRef(DataRefImpl SectionP, const ObjectFile *Owner); bool operator==(const SectionRef &Other) const; + bool operator!=(const SectionRef &Other) const; bool operator<(const SectionRef &Other) const; - error_code getNext(SectionRef &Result) const; + void moveNext(); error_code getName(StringRef &Result) const; error_code getAddress(uint64_t &Result) const; @@ -166,8 +111,13 @@ public: error_code containsSymbol(SymbolRef S, bool &Result) const; - relocation_iterator begin_relocations() const; - relocation_iterator end_relocations() const; + relocation_iterator relocation_begin() const; + relocation_iterator relocation_end() const; + typedef iterator_range<relocation_iterator> relocation_iterator_range; + relocation_iterator_range relocations() const { + return relocation_iterator_range(relocation_begin(), relocation_end()); + } + bool relocation_empty() const; section_iterator getRelocatedSection() const; DataRefImpl getRawDataRefImpl() const; @@ -175,13 +125,11 @@ public: /// SymbolRef - This is a value type class that represents a single symbol in /// the list of symbols in the object file. -class SymbolRef { +class SymbolRef : public BasicSymbolRef { friend class SectionRef; - DataRefImpl SymbolPimpl; - const ObjectFile *OwningObject; public: - SymbolRef() : OwningObject(NULL) { } + SymbolRef() : BasicSymbolRef() {} enum Type { ST_Unknown, // Type not specified @@ -192,25 +140,8 @@ public: ST_Other }; - enum Flags LLVM_ENUM_INT_TYPE(unsigned) { - SF_None = 0, - SF_Undefined = 1U << 0, // Symbol is defined in another object file - SF_Global = 1U << 1, // Global symbol - SF_Weak = 1U << 2, // Weak symbol - SF_Absolute = 1U << 3, // Absolute symbol - SF_ThreadLocal = 1U << 4, // Thread local symbol - SF_Common = 1U << 5, // Symbol has common linkage - SF_FormatSpecific = 1U << 31 // Specific to the object file format - // (e.g. section symbols) - }; - SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner); - bool operator==(const SymbolRef &Other) const; - bool operator<(const SymbolRef &Other) const; - - error_code getNext(SymbolRef &Result) const; - error_code getName(StringRef &Result) const; /// Returns the symbol virtual address (i.e. address at which it will be /// mapped). @@ -221,17 +152,29 @@ public: error_code getSize(uint64_t &Result) const; error_code getType(SymbolRef::Type &Result) const; - /// Get symbol flags (bitwise OR of SymbolRef::Flags) - error_code getFlags(uint32_t &Result) const; - /// @brief Get section this symbol is defined in reference to. Result is /// end_sections() if it is undefined or is an absolute symbol. error_code getSection(section_iterator &Result) const; - /// @brief Get value of the symbol in the symbol table. - error_code getValue(uint64_t &Val) const; + const ObjectFile *getObject() const; +}; - DataRefImpl getRawDataRefImpl() const; +class symbol_iterator : public basic_symbol_iterator { +public: + symbol_iterator(SymbolRef Sym) : basic_symbol_iterator(Sym) {} + symbol_iterator(const basic_symbol_iterator &B) + : basic_symbol_iterator(SymbolRef(B->getRawDataRefImpl(), + cast<ObjectFile>(B->getObject()))) {} + + const SymbolRef *operator->() const { + const BasicSymbolRef &P = basic_symbol_iterator::operator *(); + return static_cast<const SymbolRef*>(&P); + } + + const SymbolRef &operator*() const { + const BasicSymbolRef &P = basic_symbol_iterator::operator *(); + return static_cast<const SymbolRef&>(P); + } }; /// LibraryRef - This is a value type class that represents a single library in @@ -258,18 +201,16 @@ public: }; typedef content_iterator<LibraryRef> library_iterator; -const uint64_t UnknownAddressOrSize = ~0ULL; - /// ObjectFile - This class is the base class for all object file types. /// Concrete instances of this object are created by createObjectFile, which /// figures out which type to create. -class ObjectFile : public Binary { +class ObjectFile : public SymbolicFile { virtual void anchor(); ObjectFile() LLVM_DELETED_FUNCTION; ObjectFile(const ObjectFile &other) LLVM_DELETED_FUNCTION; protected: - ObjectFile(unsigned int Type, MemoryBuffer *source); + ObjectFile(unsigned int Type, MemoryBuffer *Source, bool BufferOwned = true); const uint8_t *base() const { return reinterpret_cast<const uint8_t *>(Data->getBufferStart()); @@ -284,23 +225,19 @@ protected: // Implementations assume that the DataRefImpl is valid and has not been // modified externally. It's UB otherwise. friend class SymbolRef; - virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const = 0; virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const = 0; + error_code printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const = 0; - virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res)const=0; virtual error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const; virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const = 0; virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const = 0; - virtual error_code getSymbolFlags(DataRefImpl Symb, - uint32_t &Res) const = 0; virtual error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const = 0; - virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const = 0; // Same as above for SectionRef. friend class SectionRef; - virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const = 0; + virtual void moveSectionNext(DataRefImpl &Sec) const = 0; virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const = 0; virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const =0; virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const = 0; @@ -319,12 +256,12 @@ protected: bool &Result) const = 0; virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0; virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0; + virtual bool section_rel_empty(DataRefImpl Sec) const = 0; virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; // Same as above for RelocationRef. friend class RelocationRef; - virtual error_code getRelocationNext(DataRefImpl Rel, - RelocationRef &Res) const = 0; + virtual void moveRelocationNext(DataRefImpl &Rel) const = 0; virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const =0; virtual error_code getRelocationOffset(DataRefImpl Rel, @@ -347,18 +284,21 @@ protected: virtual error_code getLibraryPath(DataRefImpl Lib, StringRef &Res) const = 0; public: + typedef iterator_range<symbol_iterator> symbol_iterator_range; + symbol_iterator_range symbols() const { + return symbol_iterator_range(symbol_begin(), symbol_end()); + } - virtual symbol_iterator begin_symbols() const = 0; - virtual symbol_iterator end_symbols() const = 0; - - virtual symbol_iterator begin_dynamic_symbols() const = 0; - virtual symbol_iterator end_dynamic_symbols() const = 0; + virtual section_iterator section_begin() const = 0; + virtual section_iterator section_end() const = 0; - virtual section_iterator begin_sections() const = 0; - virtual section_iterator end_sections() const = 0; + typedef iterator_range<section_iterator> section_iterator_range; + section_iterator_range sections() const { + return section_iterator_range(section_begin(), section_end()); + } - virtual library_iterator begin_libraries_needed() const = 0; - virtual library_iterator end_libraries_needed() const = 0; + virtual library_iterator needed_library_begin() const = 0; + virtual library_iterator needed_library_end() const = 0; /// @brief The number of bytes used to represent an address in this object /// file format. @@ -376,74 +316,95 @@ public: /// @param ObjectPath The path to the object file. ObjectPath.isObject must /// return true. /// @brief Create ObjectFile from path. - static ObjectFile *createObjectFile(StringRef ObjectPath); - static ObjectFile *createObjectFile(MemoryBuffer *Object); + static ErrorOr<ObjectFile *> createObjectFile(StringRef ObjectPath); + static ErrorOr<ObjectFile *> createObjectFile(MemoryBuffer *Object, + bool BufferOwned, + sys::fs::file_magic Type); + static ErrorOr<ObjectFile *> createObjectFile(MemoryBuffer *Object) { + return createObjectFile(Object, true, sys::fs::file_magic::unknown); + } + static inline bool classof(const Binary *v) { return v->isObject(); } public: - static ObjectFile *createCOFFObjectFile(MemoryBuffer *Object); - static ObjectFile *createELFObjectFile(MemoryBuffer *Object); - static ObjectFile *createMachOObjectFile(MemoryBuffer *Object); + static ErrorOr<ObjectFile *> createCOFFObjectFile(MemoryBuffer *Object, + bool BufferOwned = true); + static ErrorOr<ObjectFile *> createELFObjectFile(MemoryBuffer *Object, + bool BufferOwned = true); + static ErrorOr<ObjectFile *> createMachOObjectFile(MemoryBuffer *Object, + bool BufferOwned = true); }; // Inline function definitions. inline SymbolRef::SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner) - : SymbolPimpl(SymbolP) - , OwningObject(Owner) {} - -inline bool SymbolRef::operator==(const SymbolRef &Other) const { - return SymbolPimpl == Other.SymbolPimpl; -} - -inline bool SymbolRef::operator<(const SymbolRef &Other) const { - return SymbolPimpl < Other.SymbolPimpl; -} - -inline error_code SymbolRef::getNext(SymbolRef &Result) const { - return OwningObject->getSymbolNext(SymbolPimpl, Result); -} + : BasicSymbolRef(SymbolP, Owner) {} inline error_code SymbolRef::getName(StringRef &Result) const { - return OwningObject->getSymbolName(SymbolPimpl, Result); + return getObject()->getSymbolName(getRawDataRefImpl(), Result); } inline error_code SymbolRef::getAddress(uint64_t &Result) const { - return OwningObject->getSymbolAddress(SymbolPimpl, Result); + return getObject()->getSymbolAddress(getRawDataRefImpl(), Result); } inline error_code SymbolRef::getFileOffset(uint64_t &Result) const { - return OwningObject->getSymbolFileOffset(SymbolPimpl, Result); + uint64_t Address; + if (error_code EC = getAddress(Address)) + return EC; + if (Address == UnknownAddressOrSize) { + Result = UnknownAddressOrSize; + return object_error::success; + } + + const ObjectFile *Obj = getObject(); + section_iterator SecI(Obj->section_begin()); + if (error_code EC = getSection(SecI)) + return EC; + + if (SecI == Obj->section_end()) { + Result = UnknownAddressOrSize; + return object_error::success; + } + + uint64_t SectionAddress; + if (error_code EC = SecI->getAddress(SectionAddress)) + return EC; + + uint64_t OffsetInSection = Address - SectionAddress; + + StringRef SecContents; + if (error_code EC = SecI->getContents(SecContents)) + return EC; + + // FIXME: this is a hack. + uint64_t SectionOffset = (uint64_t)SecContents.data() - (uint64_t)Obj->base(); + + Result = SectionOffset + OffsetInSection; + return object_error::success; } inline error_code SymbolRef::getAlignment(uint32_t &Result) const { - return OwningObject->getSymbolAlignment(SymbolPimpl, Result); + return getObject()->getSymbolAlignment(getRawDataRefImpl(), Result); } inline error_code SymbolRef::getSize(uint64_t &Result) const { - return OwningObject->getSymbolSize(SymbolPimpl, Result); -} - -inline error_code SymbolRef::getFlags(uint32_t &Result) const { - return OwningObject->getSymbolFlags(SymbolPimpl, Result); + return getObject()->getSymbolSize(getRawDataRefImpl(), Result); } inline error_code SymbolRef::getSection(section_iterator &Result) const { - return OwningObject->getSymbolSection(SymbolPimpl, Result); + return getObject()->getSymbolSection(getRawDataRefImpl(), Result); } inline error_code SymbolRef::getType(SymbolRef::Type &Result) const { - return OwningObject->getSymbolType(SymbolPimpl, Result); -} - -inline error_code SymbolRef::getValue(uint64_t &Val) const { - return OwningObject->getSymbolValue(SymbolPimpl, Val); + return getObject()->getSymbolType(getRawDataRefImpl(), Result); } -inline DataRefImpl SymbolRef::getRawDataRefImpl() const { - return SymbolPimpl; +inline const ObjectFile *SymbolRef::getObject() const { + const SymbolicFile *O = BasicSymbolRef::getObject(); + return cast<ObjectFile>(O); } @@ -457,12 +418,16 @@ inline bool SectionRef::operator==(const SectionRef &Other) const { return SectionPimpl == Other.SectionPimpl; } +inline bool SectionRef::operator!=(const SectionRef &Other) const { + return SectionPimpl != Other.SectionPimpl; +} + inline bool SectionRef::operator<(const SectionRef &Other) const { return SectionPimpl < Other.SectionPimpl; } -inline error_code SectionRef::getNext(SectionRef &Result) const { - return OwningObject->getSectionNext(SectionPimpl, Result); +inline void SectionRef::moveNext() { + return OwningObject->moveSectionNext(SectionPimpl); } inline error_code SectionRef::getName(StringRef &Result) const { @@ -514,18 +479,22 @@ inline error_code SectionRef::isReadOnlyData(bool &Result) const { } inline error_code SectionRef::containsSymbol(SymbolRef S, bool &Result) const { - return OwningObject->sectionContainsSymbol(SectionPimpl, S.SymbolPimpl, - Result); + return OwningObject->sectionContainsSymbol(SectionPimpl, + S.getRawDataRefImpl(), Result); } -inline relocation_iterator SectionRef::begin_relocations() const { +inline relocation_iterator SectionRef::relocation_begin() const { return OwningObject->section_rel_begin(SectionPimpl); } -inline relocation_iterator SectionRef::end_relocations() const { +inline relocation_iterator SectionRef::relocation_end() const { return OwningObject->section_rel_end(SectionPimpl); } +inline bool SectionRef::relocation_empty() const { + return OwningObject->section_rel_empty(SectionPimpl); +} + inline section_iterator SectionRef::getRelocatedSection() const { return OwningObject->getRelocatedSection(SectionPimpl); } @@ -544,8 +513,8 @@ inline bool RelocationRef::operator==(const RelocationRef &Other) const { return RelocationPimpl == Other.RelocationPimpl; } -inline error_code RelocationRef::getNext(RelocationRef &Result) const { - return OwningObject->getRelocationNext(RelocationPimpl, Result); +inline void RelocationRef::moveNext() { + return OwningObject->moveRelocationNext(RelocationPimpl); } inline error_code RelocationRef::getAddress(uint64_t &Result) const { diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h index 97912fe..a3aaf17 100644 --- a/include/llvm/Object/RelocVisitor.h +++ b/include/llvm/Object/RelocVisitor.h @@ -17,8 +17,8 @@ #define LLVM_OBJECT_RELOCVISITOR_H #include "llvm/ADT/StringRef.h" -#include "llvm/Object/ObjectFile.h" #include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" #include "llvm/Support/raw_ostream.h" @@ -33,7 +33,6 @@ struct RelocToApply { // The width of the value; how many bytes to touch when applying the // relocation. char Width; - RelocToApply(const RelocToApply &In) : Value(In.Value), Width(In.Width) {} RelocToApply(int64_t Value, char Width) : Value(Value), Width(Width) {} RelocToApply() : Value(0), Width(0) {} }; @@ -103,6 +102,16 @@ public: HasError = true; return RelocToApply(); } + } else if (FileFormat == "ELF64-mips") { + switch (RelocType) { + case llvm::ELF::R_MIPS_32: + return visitELF_MIPS_32(R, Value); + case llvm::ELF::R_MIPS_64: + return visitELF_MIPS_64(R, Value); + default: + HasError = true; + return RelocToApply(); + } } else if (FileFormat == "ELF64-aarch64") { switch (RelocType) { case llvm::ELF::R_AARCH64_ABS32: @@ -123,6 +132,35 @@ public: HasError = true; return RelocToApply(); } + } else if (FileFormat == "ELF32-sparc") { + switch (RelocType) { + case llvm::ELF::R_SPARC_32: + case llvm::ELF::R_SPARC_UA32: + return visitELF_SPARC_32(R, Value); + default: + HasError = true; + return RelocToApply(); + } + } else if (FileFormat == "ELF64-sparc") { + switch (RelocType) { + case llvm::ELF::R_SPARC_32: + case llvm::ELF::R_SPARC_UA32: + return visitELF_SPARCV9_32(R, Value); + case llvm::ELF::R_SPARC_64: + case llvm::ELF::R_SPARC_UA64: + return visitELF_SPARCV9_64(R, Value); + default: + HasError = true; + return RelocToApply(); + } + } else if (FileFormat == "ELF32-arm") { + switch (RelocType) { + default: + HasError = true; + return RelocToApply(); + case llvm::ELF::R_ARM_ABS32: + return visitELF_ARM_ABS32(R, Value); + } } HasError = true; return RelocToApply(); @@ -239,6 +277,13 @@ private: return RelocToApply(Res, 4); } + RelocToApply visitELF_MIPS_64(RelocationRef R, uint64_t Value) { + int64_t Addend; + getELFRelocationAddend(R, Addend); + uint64_t Res = (Value + Addend); + return RelocToApply(Res, 8); + } + // AArch64 ELF RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) { int64_t Addend = getAddend64LE(R); @@ -272,6 +317,27 @@ private: int64_t Addend = getAddend64BE(R); return RelocToApply(Value + Addend, 8); } + + RelocToApply visitELF_SPARC_32(RelocationRef R, uint32_t Value) { + int32_t Addend = getAddend32BE(R); + return RelocToApply(Value + Addend, 4); + } + + RelocToApply visitELF_SPARCV9_32(RelocationRef R, uint64_t Value) { + int32_t Addend = getAddend64BE(R); + return RelocToApply(Value + Addend, 4); + } + + RelocToApply visitELF_SPARCV9_64(RelocationRef R, uint64_t Value) { + int64_t Addend = getAddend64BE(R); + return RelocToApply(Value + Addend, 8); + } + + RelocToApply visitELF_ARM_ABS32(RelocationRef R, uint64_t Value) { + int64_t Addend = getAddend32LE(R); + return RelocToApply(Value + Addend, 4); + } + }; } diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h new file mode 100644 index 0000000..bead2c3 --- /dev/null +++ b/include/llvm/Object/SymbolicFile.h @@ -0,0 +1,194 @@ +//===- SymbolicFile.h - Interface that only provides symbols ----*- 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 the SymbolicFile interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_SYMBOLIC_FILE_H +#define LLVM_OBJECT_SYMBOLIC_FILE_H + +#include "llvm/Object/Binary.h" + +namespace llvm { +namespace object { + +union DataRefImpl { + // This entire union should probably be a + // char[max(8, sizeof(uintptr_t))] and require the impl to cast. + struct { + uint32_t a, b; + } d; + uintptr_t p; + DataRefImpl() { std::memset(this, 0, sizeof(DataRefImpl)); } +}; + +inline bool operator==(const DataRefImpl &a, const DataRefImpl &b) { + // Check bitwise identical. This is the only legal way to compare a union w/o + // knowing which member is in use. + return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0; +} + +inline bool operator!=(const DataRefImpl &a, const DataRefImpl &b) { + return !operator==(a, b); +} + +inline bool operator<(const DataRefImpl &a, const DataRefImpl &b) { + // Check bitwise identical. This is the only legal way to compare a union w/o + // knowing which member is in use. + return std::memcmp(&a, &b, sizeof(DataRefImpl)) < 0; +} + +template <class content_type> class content_iterator { + content_type Current; + +public: + content_iterator(content_type symb) : Current(symb) {} + + const content_type *operator->() const { return &Current; } + + const content_type &operator*() const { return Current; } + + bool operator==(const content_iterator &other) const { + return Current == other.Current; + } + + bool operator!=(const content_iterator &other) const { + return !(*this == other); + } + + content_iterator &operator++() { // preincrement + Current.moveNext(); + return *this; + } +}; + +class SymbolicFile; + +/// This is a value type class that represents a single symbol in the list of +/// symbols in the object file. +class BasicSymbolRef { + DataRefImpl SymbolPimpl; + const SymbolicFile *OwningObject; + +public: + // FIXME: should we add a SF_Text? + enum Flags : unsigned { + SF_None = 0, + SF_Undefined = 1U << 0, // Symbol is defined in another object file + SF_Global = 1U << 1, // Global symbol + SF_Weak = 1U << 2, // Weak symbol + SF_Absolute = 1U << 3, // Absolute symbol + SF_Common = 1U << 4, // Symbol has common linkage + SF_FormatSpecific = 1U << 5 // Specific to the object file format + // (e.g. section symbols) + }; + + BasicSymbolRef() : OwningObject(NULL) { } + BasicSymbolRef(DataRefImpl SymbolP, const SymbolicFile *Owner); + + bool operator==(const BasicSymbolRef &Other) const; + bool operator<(const BasicSymbolRef &Other) const; + + void moveNext(); + + error_code printName(raw_ostream &OS) const; + + /// Get symbol flags (bitwise OR of SymbolRef::Flags) + uint32_t getFlags() const; + + DataRefImpl getRawDataRefImpl() const; + const SymbolicFile *getObject() const; +}; + +typedef content_iterator<BasicSymbolRef> basic_symbol_iterator; + +const uint64_t UnknownAddressOrSize = ~0ULL; + +class SymbolicFile : public Binary { +public: + virtual ~SymbolicFile(); + SymbolicFile(unsigned int Type, MemoryBuffer *Source, bool BufferOwned); + + // virtual interface. + virtual void moveSymbolNext(DataRefImpl &Symb) const = 0; + + virtual error_code printSymbolName(raw_ostream &OS, + DataRefImpl Symb) const = 0; + + virtual uint32_t getSymbolFlags(DataRefImpl Symb) const = 0; + + virtual basic_symbol_iterator symbol_begin_impl() const = 0; + + virtual basic_symbol_iterator symbol_end_impl() const = 0; + + // convenience wrappers. + basic_symbol_iterator symbol_begin() const { + return symbol_begin_impl(); + } + basic_symbol_iterator symbol_end() const { + return symbol_end_impl(); + } + + // construction aux. + static ErrorOr<SymbolicFile *> createIRObjectFile(MemoryBuffer *Object, + LLVMContext &Context, + bool BufferOwned = true); + + static ErrorOr<SymbolicFile *> createSymbolicFile(MemoryBuffer *Object, + bool BufferOwned, + sys::fs::file_magic Type, + LLVMContext *Context); + + static ErrorOr<SymbolicFile *> createSymbolicFile(MemoryBuffer *Object) { + return createSymbolicFile(Object, true, sys::fs::file_magic::unknown, 0); + } + static ErrorOr<SymbolicFile *> createSymbolicFile(StringRef ObjectPath); + + static inline bool classof(const Binary *v) { + return v->isSymbolic(); + } +}; + +inline BasicSymbolRef::BasicSymbolRef(DataRefImpl SymbolP, + const SymbolicFile *Owner) + : SymbolPimpl(SymbolP), OwningObject(Owner) {} + +inline bool BasicSymbolRef::operator==(const BasicSymbolRef &Other) const { + return SymbolPimpl == Other.SymbolPimpl; +} + +inline bool BasicSymbolRef::operator<(const BasicSymbolRef &Other) const { + return SymbolPimpl < Other.SymbolPimpl; +} + +inline void BasicSymbolRef::moveNext() { + return OwningObject->moveSymbolNext(SymbolPimpl); +} + +inline error_code BasicSymbolRef::printName(raw_ostream &OS) const { + return OwningObject->printSymbolName(OS, SymbolPimpl); +} + +inline uint32_t BasicSymbolRef::getFlags() const { + return OwningObject->getSymbolFlags(SymbolPimpl); +} + +inline DataRefImpl BasicSymbolRef::getRawDataRefImpl() const { + return SymbolPimpl; +} + +inline const SymbolicFile *BasicSymbolRef::getObject() const { + return OwningObject; +} + +} +} + +#endif |