diff options
Diffstat (limited to 'include/llvm/Object')
| -rw-r--r-- | include/llvm/Object/COFF.h | 102 | ||||
| -rw-r--r-- | include/llvm/Object/COFFYAML.h | 141 | ||||
| -rw-r--r-- | include/llvm/Object/ELF.h | 405 | ||||
| -rw-r--r-- | include/llvm/Object/ELFYAML.h | 92 | ||||
| -rw-r--r-- | include/llvm/Object/MachO.h | 92 | ||||
| -rw-r--r-- | include/llvm/Object/ObjectFile.h | 41 | ||||
| -rw-r--r-- | include/llvm/Object/RelocVisitor.h | 102 | ||||
| -rw-r--r-- | include/llvm/Object/YAML.h | 116 |
8 files changed, 878 insertions, 213 deletions
diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index 6f42d76..209aa76 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -24,6 +24,29 @@ namespace llvm { namespace object { +/// The DOS compatible header at the front of all PE/COFF executables. +struct dos_header { + support::ulittle16_t Magic; + support::ulittle16_t UsedBytesInTheLastPage; + support::ulittle16_t FileSizeInPages; + support::ulittle16_t NumberOfRelocationItems; + support::ulittle16_t HeaderSizeInParagraphs; + support::ulittle16_t MinimumExtraParagraphs; + support::ulittle16_t MaximumExtraParagraphs; + support::ulittle16_t InitialRelativeSS; + support::ulittle16_t InitialSP; + support::ulittle16_t Checksum; + support::ulittle16_t InitialIP; + support::ulittle16_t InitialRelativeCS; + support::ulittle16_t AddressOfRelocationTable; + support::ulittle16_t OverlayNumber; + support::ulittle16_t Reserved[4]; + support::ulittle16_t OEMid; + support::ulittle16_t OEMinfo; + support::ulittle16_t Reserved2[10]; + support::ulittle32_t AddressOfNewExeHeader; +}; + struct coff_file_header { support::ulittle16_t Machine; support::ulittle16_t NumberOfSections; @@ -34,6 +57,78 @@ struct coff_file_header { support::ulittle16_t Characteristics; }; +/// The 32-bit PE header that follows the COFF header. +struct pe32_header { + support::ulittle16_t Magic; + uint8_t MajorLinkerVersion; + uint8_t MinorLinkerVersion; + support::ulittle32_t SizeOfCode; + support::ulittle32_t SizeOfInitializedData; + support::ulittle32_t SizeOfUninitializedData; + support::ulittle32_t AddressOfEntryPoint; + support::ulittle32_t BaseOfCode; + support::ulittle32_t BaseOfData; + support::ulittle32_t ImageBase; + support::ulittle32_t SectionAlignment; + support::ulittle32_t FileAlignment; + support::ulittle16_t MajorOperatingSystemVersion; + support::ulittle16_t MinorOperatingSystemVersion; + support::ulittle16_t MajorImageVersion; + support::ulittle16_t MinorImageVersion; + support::ulittle16_t MajorSubsystemVersion; + support::ulittle16_t MinorSubsystemVersion; + support::ulittle32_t Win32VersionValue; + support::ulittle32_t SizeOfImage; + support::ulittle32_t SizeOfHeaders; + support::ulittle32_t CheckSum; + support::ulittle16_t Subsystem; + support::ulittle16_t DLLCharacteristics; + support::ulittle32_t SizeOfStackReserve; + support::ulittle32_t SizeOfStackCommit; + support::ulittle32_t SizeOfHeapReserve; + support::ulittle32_t SizeOfHeapCommit; + support::ulittle32_t LoaderFlags; + support::ulittle32_t NumberOfRvaAndSize; +}; + +/// The 64-bit PE header that follows the COFF header. +struct pe32plus_header { + support::ulittle16_t Magic; + uint8_t MajorLinkerVersion; + uint8_t MinorLinkerVersion; + support::ulittle32_t SizeOfCode; + support::ulittle32_t SizeOfInitializedData; + support::ulittle32_t SizeOfUninitializedData; + support::ulittle32_t AddressOfEntryPoint; + support::ulittle32_t BaseOfCode; + support::ulittle64_t ImageBase; + support::ulittle32_t SectionAlignment; + support::ulittle32_t FileAlignment; + support::ulittle16_t MajorOperatingSystemVersion; + support::ulittle16_t MinorOperatingSystemVersion; + support::ulittle16_t MajorImageVersion; + support::ulittle16_t MinorImageVersion; + support::ulittle16_t MajorSubsystemVersion; + support::ulittle16_t MinorSubsystemVersion; + support::ulittle32_t Win32VersionValue; + support::ulittle32_t SizeOfImage; + support::ulittle32_t SizeOfHeaders; + support::ulittle32_t CheckSum; + support::ulittle16_t Subsystem; + support::ulittle16_t DLLCharacteristics; + support::ulittle64_t SizeOfStackReserve; + support::ulittle64_t SizeOfStackCommit; + support::ulittle64_t SizeOfHeapReserve; + support::ulittle64_t SizeOfHeapCommit; + support::ulittle32_t LoaderFlags; + support::ulittle32_t NumberOfRvaAndSize; +}; + +struct data_directory { + support::ulittle32_t RelativeVirtualAddress; + support::ulittle32_t Size; +}; + struct coff_symbol { struct StringTableOffset { support::ulittle32_t Zeroes; @@ -143,14 +238,11 @@ protected: uint64_t &Res) const; virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; - virtual error_code getRelocationSymbol(DataRefImpl Rel, - SymbolRef &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 getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const; virtual error_code getRelocationValueString(DataRefImpl Rel, SmallVectorImpl<char> &Result) const; @@ -173,7 +265,7 @@ public: 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; diff --git a/include/llvm/Object/COFFYAML.h b/include/llvm/Object/COFFYAML.h new file mode 100644 index 0000000..3fa3ec6 --- /dev/null +++ b/include/llvm/Object/COFFYAML.h @@ -0,0 +1,141 @@ +//===- 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/Object/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); +} +} + +// 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 { + struct Relocation { + uint32_t VirtualAddress; + uint16_t Type; + StringRef SymbolName; + }; + + struct Section { + COFF::section Header; + unsigned Alignment; + object::yaml::BinaryRef SectionData; + std::vector<Relocation> Relocations; + StringRef Name; + Section(); + }; + + struct Symbol { + COFF::symbol Header; + COFF::SymbolBaseType SimpleType; + COFF::SymbolComplexType ComplexType; + object::yaml::BinaryRef AuxiliaryData; + StringRef Name; + Symbol(); + }; + + struct Object { + 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<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::RelocationTypeX86> { + static void enumeration(IO &IO, COFF::RelocationTypeX86 &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 MappingTraits<COFFYAML::Relocation> { + static void mapping(IO &IO, COFFYAML::Relocation &Rel); +}; + +template <> +struct MappingTraits<COFF::header> { + static void mapping(IO &IO, COFF::header &H); +}; + +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 491a17e..eb8e22e 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -55,8 +55,8 @@ inline std::pair<unsigned char, unsigned char> getElfArchType(MemoryBuffer *Object) { if (Object->getBufferSize() < ELF::EI_NIDENT) return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE); - return std::make_pair( (uint8_t)Object->getBufferStart()[ELF::EI_CLASS] - , (uint8_t)Object->getBufferStart()[ELF::EI_DATA]); + return std::make_pair((uint8_t) Object->getBufferStart()[ELF::EI_CLASS], + (uint8_t) Object->getBufferStart()[ELF::EI_DATA]); } // Templates to choose Elf_Addr and Elf_Off depending on is64Bits. @@ -318,8 +318,8 @@ struct Elf_Rel_Base; template<endianness TargetEndianness, std::size_t MaxAlign> struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, false> { LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, 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 + 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 uint32_t getRInfo(bool isMips64EL) const { assert(!isMips64EL); @@ -333,19 +333,18 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, false> { template<endianness TargetEndianness, std::size_t MaxAlign> struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, false> { LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - 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 + 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 uint64_t getRInfo(bool isMips64EL) const { uint64_t t = r_info; if (!isMips64EL) return t; - // Mip64 little endian has a "special" encoding of r_info. Instead of one - // 64 bit little endian number, it is a little ending 32 bit number followed + // Mips64 little endian has a "special" encoding of r_info. Instead of one + // 64 bit little endian number, it is a little endian 32 bit number followed // by a 32 bit big endian number. return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); - return r_info; } void setRInfo(uint64_t R) { // FIXME: Add mips64el support. @@ -356,9 +355,9 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, false> { template<endianness TargetEndianness, std::size_t MaxAlign> struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, true> { LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, 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 - Elf_Sword r_addend; // Compute value for relocatable field by adding this + 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 + Elf_Sword r_addend; // Compute value for relocatable field by adding this uint32_t getRInfo(bool isMips64EL) const { assert(!isMips64EL); @@ -372,13 +371,13 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, true> { template<endianness TargetEndianness, std::size_t MaxAlign> struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, true> { LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - 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 - Elf_Sxword r_addend; // Compute value for relocatable field by adding this. + 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 + Elf_Sxword r_addend; // Compute value for relocatable field by adding this. uint64_t getRInfo(bool isMips64EL) const { - // Mip64 little endian has a "special" encoding of r_info. Instead of one - // 64 bit little endian number, it is a little ending 32 bit number followed + // Mips64 little endian has a "special" encoding of r_info. Instead of one + // 64 bit little endian number, it is a little endian 32 bit number followed // by a 32 bit big endian number. uint64_t t = r_info; if (!isMips64EL) @@ -583,20 +582,14 @@ protected: bool isDyldELFObject; private: - typedef SmallVector<const Elf_Shdr *, 2> Sections_t; - typedef DenseMap<unsigned, unsigned> IndexMap_t; - typedef DenseMap<const Elf_Shdr*, SmallVector<uint32_t, 1> > RelocMap_t; - const Elf_Ehdr *Header; const Elf_Shdr *SectionHeaderTable; const Elf_Shdr *dot_shstrtab_sec; // Section header string table. const Elf_Shdr *dot_strtab_sec; // Symbol header string table. const Elf_Shdr *dot_dynstr_sec; // Dynamic symbol string table. - // SymbolTableSections[0] always points to the dynamic string table section - // header, or NULL if there is no dynamic string table. - Sections_t SymbolTableSections; - IndexMap_t SymbolTableSectionsIndexMap; + int SymbolTableIndex; + int DynamicSymbolTableIndex; DenseMap<const Elf_Sym*, ELF::Elf64_Word> ExtendedSymbolTable; const Elf_Shdr *dot_dynamic_sec; // .dynamic @@ -637,19 +630,15 @@ private: void LoadVersionNeeds(const Elf_Shdr *ec) const; void LoadVersionMap() const; - /// @brief Map sections to an array of relocation sections that reference - /// them sorted by section index. - RelocMap_t SectionRelocMap; - /// @brief Get the relocation section that contains \a Rel. const Elf_Shdr *getRelSection(DataRefImpl Rel) const { - return getSection(Rel.w.b); + return getSection(Rel.d.a); } public: bool isRelocationHasAddend(DataRefImpl Rel) const; template<typename T> - const T *getEntry(uint16_t Section, uint32_t Entry) const; + const T *getEntry(uint32_t Section, uint32_t Entry) const; template<typename T> const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const; const Elf_Shdr *getSection(DataRefImpl index) const; @@ -665,7 +654,7 @@ public: void VerifyStrTab(const Elf_Shdr *sh) const; protected: - const Elf_Sym *getSymbol(DataRefImpl Symb) const; // FIXME: Should be private? + const Elf_Sym *getSymbol(DataRefImpl Symb) const; // FIXME: Should be private? void validateSymbol(DataRefImpl Symb) const; StringRef getRelocationTypeName(uint32_t Type) const; @@ -679,6 +668,7 @@ public: error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, bool &IsDefault) const; uint64_t getSymbolIndex(const Elf_Sym *sym) const; + error_code getRelocationAddend(DataRefImpl Rel, int64_t &Res) const; protected: virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; @@ -688,7 +678,8 @@ protected: virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &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 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; @@ -714,6 +705,7 @@ protected: bool &Result) const; virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; + virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; virtual error_code getRelocationNext(DataRefImpl Rel, RelocationRef &Res) const; @@ -721,14 +713,11 @@ protected: uint64_t &Res) const; virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; - virtual error_code getRelocationSymbol(DataRefImpl Rel, - SymbolRef &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 getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const; virtual error_code getRelocationValueString(DataRefImpl Rel, SmallVectorImpl<char> &Result) const; @@ -754,7 +743,7 @@ public: virtual library_iterator end_libraries_needed() const; const Elf_Shdr *getDynamicSymbolTableSectionHeader() const { - return SymbolTableSections[0]; + return getSection(DynamicSymbolTableIndex); } const Elf_Shdr *getDynamicStringTableSectionHeader() const { @@ -767,7 +756,7 @@ public: Elf_Dyn_iterator end_dynamic_table(bool NULLEnd = false) const; Elf_Sym_iterator begin_elf_dynamic_symbols() const { - const Elf_Shdr *DynSymtab = SymbolTableSections[0]; + const Elf_Shdr *DynSymtab = getDynamicSymbolTableSectionHeader(); if (DynSymtab) return Elf_Sym_iterator(DynSymtab->sh_entsize, (const char *)base() + DynSymtab->sh_offset); @@ -775,7 +764,7 @@ public: } Elf_Sym_iterator end_elf_dynamic_symbols() const { - const Elf_Shdr *DynSymtab = SymbolTableSections[0]; + const Elf_Shdr *DynSymtab = getDynamicSymbolTableSectionHeader(); if (DynSymtab) return Elf_Sym_iterator(DynSymtab->sh_entsize, (const char *)base() + DynSymtab->sh_offset + DynSymtab->sh_size); @@ -842,6 +831,13 @@ public: } }; +// Use an alignment of 2 for the typedefs since that is the worst case for +// ELF files in archives. +typedef ELFObjectFile<ELFType<support::little, 2, false> > ELF32LEObjectFile; +typedef ELFObjectFile<ELFType<support::little, 2, true> > ELF64LEObjectFile; +typedef ELFObjectFile<ELFType<support::big, 2, false> > ELF32BEObjectFile; +typedef ELFObjectFile<ELFType<support::big, 2, true> > ELF64BEObjectFile; + // Iterate through the version definitions, and place each Elf_Verdef // in the VersionMap according to its index. template<class ELFT> @@ -904,7 +900,8 @@ void ELFObjectFile<ELFT>::LoadVersionNeeds(const Elf_Shdr *sec) const { template<class ELFT> void ELFObjectFile<ELFT>::LoadVersionMap() const { // If there is no dynamic symtab or version table, there is nothing to do. - if (SymbolTableSections[0] == NULL || dot_gnu_version_sec == NULL) + if (getDynamicStringTableSectionHeader() == NULL || + dot_gnu_version_sec == NULL) return; // Has the VersionMap already been loaded? @@ -927,7 +924,7 @@ template<class ELFT> void ELFObjectFile<ELFT>::validateSymbol(DataRefImpl Symb) const { #ifndef NDEBUG const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; + const Elf_Shdr *SymbolTableSection = getSection(Symb.d.b); // FIXME: We really need to do proper error handling in the case of an invalid // input file. Because we don't use exceptions, I think we'll just pass // an error object around. @@ -947,25 +944,7 @@ template<class ELFT> error_code ELFObjectFile<ELFT>::getSymbolNext(DataRefImpl Symb, SymbolRef &Result) const { validateSymbol(Symb); - const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; - ++Symb.d.a; - // Check to see if we are at the end of this symbol table. - if (Symb.d.a >= SymbolTableSection->getEntityCount()) { - // We are at the end. If there are other symbol tables, jump to them. - // If the symbol table is .dynsym, we are iterating dynamic symbols, - // and there is only one table of these. - if (Symb.d.b != 0) { - ++Symb.d.b; - Symb.d.a = 1; // The 0th symbol in ELF is fake. - } - // Otherwise return the terminator. - if (Symb.d.b == 0 || Symb.d.b >= SymbolTableSections.size()) { - Symb.d.a = std::numeric_limits<uint32_t>::max(); - Symb.d.b = std::numeric_limits<uint32_t>::max(); - } - } - Result = SymbolRef(Symb, this); return object_error::success; } @@ -975,7 +954,7 @@ error_code ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Symb, StringRef &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); - return getSymbolName(SymbolTableSections[Symb.d.b], symb, Result); + return getSymbolName(getSection(Symb.d.b), symb, Result); } template<class ELFT> @@ -985,8 +964,7 @@ error_code ELFObjectFile<ELFT>::getSymbolVersion(SymbolRef SymRef, DataRefImpl Symb = SymRef.getRawDataRefImpl(); validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); - return getSymbolVersion(SymbolTableSections[Symb.d.b], symb, - Version, IsDefault); + return getSymbolVersion(getSection(Symb.d.b), symb, Version, IsDefault); } template<class ELFT> @@ -1031,7 +1009,7 @@ const typename ELFObjectFile<ELFT>::Elf_Sym * ELFObjectFile<ELFT>::getElfSymbol(uint32_t index) const { DataRefImpl SymbolData; SymbolData.d.a = index; - SymbolData.d.b = 1; + SymbolData.d.b = SymbolTableIndex; return getSymbol(SymbolData); } @@ -1455,13 +1433,9 @@ template<class ELFT> relocation_iterator ELFObjectFile<ELFT>::getSectionRelBegin(DataRefImpl Sec) const { DataRefImpl RelData; - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec); - if (sec != 0 && ittr != SectionRelocMap.end()) { - RelData.w.a = getSection(ittr->second[0])->sh_info; - RelData.w.b = ittr->second[0]; - RelData.w.c = 0; - } + uintptr_t SHT = reinterpret_cast<uintptr_t>(SectionHeaderTable); + RelData.d.a = (Sec.p - SHT) / Header->e_shentsize; + RelData.d.b = 0; return relocation_iterator(RelocationRef(RelData, this)); } @@ -1469,53 +1443,49 @@ template<class ELFT> relocation_iterator ELFObjectFile<ELFT>::getSectionRelEnd(DataRefImpl Sec) const { DataRefImpl RelData; - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec); - if (sec != 0 && ittr != SectionRelocMap.end()) { - // Get the index of the last relocation section for this section. - std::size_t relocsecindex = ittr->second[ittr->second.size() - 1]; - const Elf_Shdr *relocsec = getSection(relocsecindex); - RelData.w.a = relocsec->sh_info; - RelData.w.b = relocsecindex; - RelData.w.c = relocsec->sh_size / relocsec->sh_entsize; - } + uintptr_t SHT = reinterpret_cast<uintptr_t>(SectionHeaderTable); + const Elf_Shdr *S = reinterpret_cast<const Elf_Shdr *>(Sec.p); + RelData.d.a = (Sec.p - SHT) / Header->e_shentsize; + if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL) + RelData.d.b = 0; + else + RelData.d.b = S->sh_size / S->sh_entsize; + return relocation_iterator(RelocationRef(RelData, this)); } +template <class ELFT> +section_iterator +ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const { + if (Header->e_type != ELF::ET_REL) + return end_sections(); + + const Elf_Shdr *S = reinterpret_cast<const Elf_Shdr *>(Sec.p); + unsigned sh_type = S->sh_type; + if (sh_type != ELF::SHT_RELA && sh_type != ELF::SHT_REL) + return end_sections(); + + assert(S->sh_info != 0); + const Elf_Shdr *R = getSection(S->sh_info); + DataRefImpl D; + D.p = reinterpret_cast<uintptr_t>(R); + return section_iterator(SectionRef(D, this)); +} + // Relocations template<class ELFT> error_code ELFObjectFile<ELFT>::getRelocationNext(DataRefImpl Rel, RelocationRef &Result) const { - ++Rel.w.c; - const Elf_Shdr *relocsec = getSection(Rel.w.b); - if (Rel.w.c >= (relocsec->sh_size / relocsec->sh_entsize)) { - // We have reached the end of the relocations for this section. See if there - // is another relocation section. - typename RelocMap_t::mapped_type relocseclist = - SectionRelocMap.lookup(getSection(Rel.w.a)); - - // Do a binary search for the current reloc section index (which must be - // present). Then get the next one. - typename RelocMap_t::mapped_type::const_iterator loc = - std::lower_bound(relocseclist.begin(), relocseclist.end(), Rel.w.b); - ++loc; - - // If there is no next one, don't do anything. The ++Rel.w.c above sets Rel - // to the end iterator. - if (loc != relocseclist.end()) { - Rel.w.b = *loc; - Rel.w.a = 0; - } - } + ++Rel.d.b; Result = RelocationRef(Rel, this); return object_error::success; } -template<class ELFT> -error_code ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Result) const { +template <class ELFT> +symbol_iterator +ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const { uint32_t symbolIdx; - const Elf_Shdr *sec = getSection(Rel.w.b); + const Elf_Shdr *sec = getRelSection(Rel); switch (sec->sh_type) { default : report_fatal_error("Invalid section type in Rel!"); @@ -1528,14 +1498,13 @@ error_code ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel, break; } } + if (!symbolIdx) + return end_symbols(); + DataRefImpl SymbolData; - IndexMap_t::const_iterator it = SymbolTableSectionsIndexMap.find(sec->sh_link); - if (it == SymbolTableSectionsIndexMap.end()) - report_fatal_error("Relocation symbol table not found!"); SymbolData.d.a = symbolIdx; - SymbolData.d.b = it->second; - Result = SymbolRef(SymbolData, this); - return object_error::success; + SymbolData.d.b = sec->sh_link; + return symbol_iterator(SymbolRef(SymbolData, this)); } template<class ELFT> @@ -1558,7 +1527,7 @@ error_code ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel, template<class ELFT> uint64_t ELFObjectFile<ELFT>::getROffset(DataRefImpl Rel) const { - const Elf_Shdr *sec = getSection(Rel.w.b); + const Elf_Shdr *sec = getRelSection(Rel); switch (sec->sh_type) { default: report_fatal_error("Invalid section type in Rel!"); @@ -1572,7 +1541,7 @@ uint64_t ELFObjectFile<ELFT>::getROffset(DataRefImpl Rel) const { template<class ELFT> error_code ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel, uint64_t &Result) const { - const Elf_Shdr *sec = getSection(Rel.w.b); + const Elf_Shdr *sec = getRelSection(Rel); switch (sec->sh_type) { default : report_fatal_error("Invalid section type in Rel!"); @@ -2071,10 +2040,18 @@ StringRef ELFObjectFile<ELFT>::getRelocationTypeName(uint32_t Type) const { switch (Type) { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_NONE); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_LO); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HA); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR14_BRTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR14_BRNTAKEN); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL14_BRTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL14_BRNTAKEN); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL32); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHER); @@ -2104,6 +2081,73 @@ StringRef ELFObjectFile<ELFT>::getRelocationTypeName(uint32_t Type) const { default: break; } break; + case ELF::EM_S390: + switch (Type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_COPY); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GLOB_DAT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_JMP_SLOT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_RELATIVE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC16DBL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT16DBL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC32DBL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT32DBL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPCDBL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTENT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLTENT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LOAD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GDCALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDCALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GD32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GD64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDM32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDM64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IE32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IE64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IEENT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LE32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LE64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDO32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDO64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_DTPMOD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_DTPOFF); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_TPOFF); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_20); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT20); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT20); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE20); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_IRELATIVE); + default: break; + } + break; default: break; } return Res; @@ -2114,7 +2158,7 @@ StringRef ELFObjectFile<ELFT>::getRelocationTypeName(uint32_t Type) const { template<class ELFT> error_code ELFObjectFile<ELFT>::getRelocationTypeName( DataRefImpl Rel, SmallVectorImpl<char> &Result) const { - const Elf_Shdr *sec = getSection(Rel.w.b); + const Elf_Shdr *sec = getRelSection(Rel); uint32_t type; switch (sec->sh_type) { default : @@ -2154,9 +2198,9 @@ error_code ELFObjectFile<ELFT>::getRelocationTypeName( } template<class ELFT> -error_code ELFObjectFile<ELFT>::getRelocationAdditionalInfo( +error_code ELFObjectFile<ELFT>::getRelocationAddend( DataRefImpl Rel, int64_t &Result) const { - const Elf_Shdr *sec = getSection(Rel.w.b); + const Elf_Shdr *sec = getRelSection(Rel); switch (sec->sh_type) { default : report_fatal_error("Invalid section type in Rel!"); @@ -2174,7 +2218,7 @@ error_code ELFObjectFile<ELFT>::getRelocationAdditionalInfo( template<class ELFT> error_code ELFObjectFile<ELFT>::getRelocationValueString( DataRefImpl Rel, SmallVectorImpl<char> &Result) const { - const Elf_Shdr *sec = getSection(Rel.w.b); + const Elf_Shdr *sec = getRelSection(Rel); uint8_t type; StringRef res; int64_t addend = 0; @@ -2298,8 +2342,8 @@ ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec) const Elf_Shdr* SymbolTableSectionHeaderIndex = 0; const Elf_Shdr* sh = SectionHeaderTable; - // Reserve SymbolTableSections[0] for .dynsym - SymbolTableSections.push_back(NULL); + SymbolTableIndex = -1; + DynamicSymbolTableIndex = -1; for (uint64_t i = 0, e = getNumSections(); i != e; ++i) { switch (sh->sh_type) { @@ -2311,23 +2355,21 @@ ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec) break; } case ELF::SHT_SYMTAB: { - SymbolTableSectionsIndexMap[i] = SymbolTableSections.size(); - SymbolTableSections.push_back(sh); + if (SymbolTableIndex != -1) + report_fatal_error("More than one SHT_SYMTAB!"); + SymbolTableIndex = i; break; } case ELF::SHT_DYNSYM: { - if (SymbolTableSections[0] != NULL) + if (DynamicSymbolTableIndex != -1) // FIXME: Proper error handling. - report_fatal_error("More than one .dynsym!"); - SymbolTableSectionsIndexMap[i] = 0; - SymbolTableSections[0] = sh; + report_fatal_error("More than one SHT_DYNSYM!"); + DynamicSymbolTableIndex = i; break; } case ELF::SHT_REL: - case ELF::SHT_RELA: { - SectionRelocMap[getSection(sh->sh_info)].push_back(i); + case ELF::SHT_RELA: break; - } case ELF::SHT_DYNAMIC: { if (dot_dynamic_sec != NULL) // FIXME: Proper error handling. @@ -2360,12 +2402,6 @@ ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec) ++sh; } - // Sort section relocation lists by index. - for (typename RelocMap_t::iterator i = SectionRelocMap.begin(), - e = SectionRelocMap.end(); i != e; ++i) { - std::sort(i->second.begin(), i->second.end()); - } - // Get string table sections. dot_shstrtab_sec = getSection(getStringTableIndex()); if (dot_shstrtab_sec) { @@ -2415,8 +2451,7 @@ ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec) // Get the symbol table index in the symtab section given a symbol template<class ELFT> uint64_t ELFObjectFile<ELFT>::getSymbolIndex(const Elf_Sym *Sym) const { - assert(SymbolTableSections.size() == 1 && "Only one symbol table supported!"); - const Elf_Shdr *SymTab = *SymbolTableSections.begin(); + const Elf_Shdr *SymTab = getSection(SymbolTableIndex); uintptr_t SymLoc = uintptr_t(Sym); uintptr_t SymTabLoc = uintptr_t(base() + SymTab->sh_offset); assert(SymLoc > SymTabLoc && "Symbol not in symbol table!"); @@ -2429,12 +2464,12 @@ uint64_t ELFObjectFile<ELFT>::getSymbolIndex(const Elf_Sym *Sym) const { template<class ELFT> symbol_iterator ELFObjectFile<ELFT>::begin_symbols() const { DataRefImpl SymbolData; - if (SymbolTableSections.size() <= 1) { - SymbolData.d.a = std::numeric_limits<uint32_t>::max(); - SymbolData.d.b = std::numeric_limits<uint32_t>::max(); + if (SymbolTableIndex == -1) { + SymbolData.d.a = 0; + SymbolData.d.b = 0; } else { - SymbolData.d.a = 1; // The 0th symbol in ELF is fake. - SymbolData.d.b = 1; // The 0th table is .dynsym + SymbolData.d.a = 0; + SymbolData.d.b = SymbolTableIndex; } return symbol_iterator(SymbolRef(SymbolData, this)); } @@ -2442,20 +2477,26 @@ symbol_iterator ELFObjectFile<ELFT>::begin_symbols() const { template<class ELFT> symbol_iterator ELFObjectFile<ELFT>::end_symbols() const { DataRefImpl SymbolData; - SymbolData.d.a = std::numeric_limits<uint32_t>::max(); - SymbolData.d.b = std::numeric_limits<uint32_t>::max(); + if (SymbolTableIndex == -1) { + SymbolData.d.a = 0; + SymbolData.d.b = 0; + } else { + const Elf_Shdr *SymbolTableSection = getSection(SymbolTableIndex); + SymbolData.d.a = SymbolTableSection->getEntityCount(); + SymbolData.d.b = SymbolTableIndex; + } return symbol_iterator(SymbolRef(SymbolData, this)); } template<class ELFT> symbol_iterator ELFObjectFile<ELFT>::begin_dynamic_symbols() const { DataRefImpl SymbolData; - if (SymbolTableSections[0] == NULL) { - SymbolData.d.a = std::numeric_limits<uint32_t>::max(); - SymbolData.d.b = std::numeric_limits<uint32_t>::max(); + if (DynamicSymbolTableIndex == -1) { + SymbolData.d.a = 0; + SymbolData.d.b = 0; } else { - SymbolData.d.a = 1; // The 0th symbol in ELF is fake. - SymbolData.d.b = 0; // The 0th table is .dynsym + SymbolData.d.a = 0; + SymbolData.d.b = DynamicSymbolTableIndex; } return symbol_iterator(SymbolRef(SymbolData, this)); } @@ -2463,8 +2504,14 @@ symbol_iterator ELFObjectFile<ELFT>::begin_dynamic_symbols() const { template<class ELFT> symbol_iterator ELFObjectFile<ELFT>::end_dynamic_symbols() const { DataRefImpl SymbolData; - SymbolData.d.a = std::numeric_limits<uint32_t>::max(); - SymbolData.d.b = std::numeric_limits<uint32_t>::max(); + if (DynamicSymbolTableIndex == -1) { + SymbolData.d.a = 0; + SymbolData.d.b = 0; + } else { + const Elf_Shdr *SymbolTableSection = getSection(DynamicSymbolTableIndex); + SymbolData.d.a = SymbolTableSection->getEntityCount(); + SymbolData.d.b = DynamicSymbolTableIndex; + } return symbol_iterator(SymbolRef(SymbolData, this)); } @@ -2618,6 +2665,8 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { return "ELF32-hexagon"; case ELF::EM_MIPS: return "ELF32-mips"; + case ELF::EM_PPC: + return "ELF32-ppc"; default: return "ELF32-unknown"; } @@ -2631,6 +2680,8 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { return "ELF64-aarch64"; case ELF::EM_PPC64: return "ELF64-ppc64"; + case ELF::EM_S390: + return "ELF64-s390"; default: return "ELF64-unknown"; } @@ -2658,6 +2709,8 @@ unsigned ELFObjectFile<ELFT>::getArch() const { Triple::mipsel : Triple::mips; case ELF::EM_PPC64: return Triple::ppc64; + case ELF::EM_S390: + return Triple::systemz; default: return Triple::UnknownArch; } @@ -2688,7 +2741,7 @@ ELFObjectFile<ELFT>::getStringTableIndex() const { template<class ELFT> template<typename T> inline const T * -ELFObjectFile<ELFT>::getEntry(uint16_t Section, uint32_t Entry) const { +ELFObjectFile<ELFT>::getEntry(uint32_t Section, uint32_t Entry) const { return getEntry<T>(getSection(Section), Entry); } @@ -2705,19 +2758,19 @@ ELFObjectFile<ELFT>::getEntry(const Elf_Shdr * Section, uint32_t Entry) const { template<class ELFT> const typename ELFObjectFile<ELFT>::Elf_Sym * ELFObjectFile<ELFT>::getSymbol(DataRefImpl Symb) const { - return getEntry<Elf_Sym>(SymbolTableSections[Symb.d.b], Symb.d.a); + return getEntry<Elf_Sym>(Symb.d.b, Symb.d.a); } template<class ELFT> const typename ELFObjectFile<ELFT>::Elf_Rel * ELFObjectFile<ELFT>::getRel(DataRefImpl Rel) const { - return getEntry<Elf_Rel>(Rel.w.b, Rel.w.c); + return getEntry<Elf_Rel>(Rel.d.a, Rel.d.b); } template<class ELFT> const typename ELFObjectFile<ELFT>::Elf_Rela * ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const { - return getEntry<Elf_Rela>(Rela.w.b, Rela.w.c); + return getEntry<Elf_Rela>(Rela.d.a, Rela.d.b); } template<class ELFT> @@ -2773,7 +2826,8 @@ error_code ELFObjectFile<ELFT>::getSymbolName(const Elf_Shdr *section, return object_error::success; } - if (section == SymbolTableSections[0]) { + if (DynamicSymbolTableIndex != -1 && + section == getSection(DynamicSymbolTableIndex)) { // Symbol is in .dynsym, use .dynstr string table Result = getString(dot_dynstr_sec, symb->st_name); } else { @@ -2796,7 +2850,7 @@ error_code ELFObjectFile<ELFT>::getSymbolVersion(const Elf_Shdr *section, StringRef &Version, bool &IsDefault) const { // Handle non-dynamic symbols. - if (section != SymbolTableSections[0]) { + if (section != getSection(DynamicSymbolTableIndex)) { // Non-dynamic symbols can have versions in their names // A name of the form 'foo@V1' indicates version 'V1', non-default. // A name of the form 'foo@@V2' indicates version 'V2', default version. @@ -2872,6 +2926,31 @@ error_code ELFObjectFile<ELFT>::getSymbolVersion(const Elf_Shdr *section, return object_error::success; } +/// 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) { + const ObjectFile *Obj = R.getObjectFile(); + DataRefImpl DRI = R.getRawDataRefImpl(); + // Little-endian 32-bit + if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + // Big-endian 32-bit + if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + // Little-endian 64-bit + if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + // Big-endian 64-bit + if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + llvm_unreachable("Object passed to getELFRelocationAddend() 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, @@ -2879,23 +2958,19 @@ static inline error_code GetELFSymbolVersion(const ObjectFile *Obj, StringRef &Version, bool &IsDefault) { // Little-endian 32-bit - if (const ELFObjectFile<ELFType<support::little, 4, false> > *ELFObj = - dyn_cast<ELFObjectFile<ELFType<support::little, 4, false> > >(Obj)) + if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); // Big-endian 32-bit - if (const ELFObjectFile<ELFType<support::big, 4, false> > *ELFObj = - dyn_cast<ELFObjectFile<ELFType<support::big, 4, false> > >(Obj)) + if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); // Little-endian 64-bit - if (const ELFObjectFile<ELFType<support::little, 8, true> > *ELFObj = - dyn_cast<ELFObjectFile<ELFType<support::little, 8, true> > >(Obj)) + if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); // Big-endian 64-bit - if (const ELFObjectFile<ELFType<support::big, 8, true> > *ELFObj = - dyn_cast<ELFObjectFile<ELFType<support::big, 8, true> > >(Obj)) + if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); llvm_unreachable("Object passed to GetELFSymbolVersion() is not ELF"); diff --git a/include/llvm/Object/ELFYAML.h b/include/llvm/Object/ELFYAML.h new file mode 100644 index 0000000..029a8ab --- /dev/null +++ b/include/llvm/Object/ELFYAML.h @@ -0,0 +1,92 @@ +//===- 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/Object/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) + +// 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_ET Type; + ELF_EM Machine; + llvm::yaml::Hex64 Entry; +}; +struct Object { + FileHeader Header; +}; + +} // end namespace ELFYAML +} // end namespace llvm + +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 MappingTraits<ELFYAML::FileHeader> { + static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr); +}; + +template <> +struct MappingTraits<ELFYAML::Object> { + static void mapping(IO &IO, ELFYAML::Object &Object); +}; + +} // end namespace yaml +} // end namespace llvm + +#endif diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 14cd4d7..1b9faaa 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -25,6 +25,31 @@ namespace llvm { namespace object { +/// DiceRef - This is a value type class that represents a single +/// data in code entry in the table in a Mach-O object file. +class DiceRef { + DataRefImpl DicePimpl; + const ObjectFile *OwningObject; + +public: + DiceRef() : OwningObject(NULL) { } + + DiceRef(DataRefImpl DiceP, const ObjectFile *Owner); + + bool operator==(const DiceRef &Other) const; + bool operator<(const DiceRef &Other) const; + + error_code getNext(DiceRef &Result) const; + + error_code getOffset(uint32_t &Result) const; + error_code getLength(uint16_t &Result) const; + error_code getKind(uint16_t &Result) const; + + DataRefImpl getRawDataRefImpl() const; + const ObjectFile *getObjectFile() const; +}; +typedef content_iterator<DiceRef> dice_iterator; + class MachOObjectFile : public ObjectFile { public: struct LoadCommandInfo { @@ -72,12 +97,10 @@ public: RelocationRef &Res) const; virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const; virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; - virtual error_code getRelocationSymbol(DataRefImpl Rel, SymbolRef &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 getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const; virtual error_code getRelocationValueString(DataRefImpl Rel, SmallVectorImpl<char> &Result) const; virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const; @@ -110,6 +133,9 @@ public: relocation_iterator getSectionRelBegin(unsigned Index) const; relocation_iterator getSectionRelEnd(unsigned Index) const; + dice_iterator begin_dices() const; + dice_iterator end_dices() const; + // In a MachO file, sections have a segment name. This is used in the .o // files. They have a single segment, but this field specifies which segment // a section should be put in in the final object. @@ -154,6 +180,7 @@ public: getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const; macho::RelocationEntry getRelocation(DataRefImpl Rel) const; + macho::DataInCodeTableEntry getDice(DataRefImpl Rel) const; macho::Header getHeader() const; macho::Header64Ext getHeader64Ext() const; macho::IndirectSymbolTableEntry @@ -163,6 +190,7 @@ public: unsigned Index) const; macho::SymtabLoadCommand getSymtabLoadCommand() const; macho::DysymtabLoadCommand getDysymtabLoadCommand() const; + macho::LinkeditDataLoadCommand getDataInCodeLoadCommand() const; StringRef getStringTableData() const; bool is64Bit() const; @@ -177,8 +205,66 @@ private: SectionList Sections; const char *SymtabLoadCmd; const char *DysymtabLoadCmd; + const char *DataInCodeLoadCmd; }; +/// DiceRef +inline DiceRef::DiceRef(DataRefImpl DiceP, const ObjectFile *Owner) + : DicePimpl(DiceP) , OwningObject(Owner) {} + +inline bool DiceRef::operator==(const DiceRef &Other) const { + return DicePimpl == Other.DicePimpl; +} + +inline bool DiceRef::operator<(const DiceRef &Other) const { + return DicePimpl < Other.DicePimpl; +} + +inline error_code DiceRef::getNext(DiceRef &Result) const { + DataRefImpl Rel = DicePimpl; + const macho::DataInCodeTableEntry *P = + reinterpret_cast<const macho::DataInCodeTableEntry *>(Rel.p); + Rel.p = reinterpret_cast<uintptr_t>(P + 1); + Result = DiceRef(Rel, OwningObject); + return object_error::success; +} + +// Since a Mach-O data in code reference, a DiceRef, can only be created when +// the OwningObject ObjectFile is a MachOObjectFile a static_cast<> is used for +// the methods that get the values of the fields of the reference. + +inline error_code DiceRef::getOffset(uint32_t &Result) const { + const MachOObjectFile *MachOOF = + static_cast<const MachOObjectFile *>(OwningObject); + macho::DataInCodeTableEntry Dice = MachOOF->getDice(DicePimpl); + Result = Dice.Offset; + return object_error::success; +} + +inline error_code DiceRef::getLength(uint16_t &Result) const { + const MachOObjectFile *MachOOF = + static_cast<const MachOObjectFile *>(OwningObject); + macho::DataInCodeTableEntry Dice = MachOOF->getDice(DicePimpl); + Result = Dice.Length; + return object_error::success; +} + +inline error_code DiceRef::getKind(uint16_t &Result) const { + const MachOObjectFile *MachOOF = + static_cast<const MachOObjectFile *>(OwningObject); + macho::DataInCodeTableEntry Dice = MachOOF->getDice(DicePimpl); + Result = Dice.Kind; + return object_error::success; +} + +inline DataRefImpl DiceRef::getRawDataRefImpl() const { + return DicePimpl; +} + +inline const ObjectFile *DiceRef::getObjectFile() const { + return OwningObject; +} + } } diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index eb53cc0..f434d63 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -28,12 +28,8 @@ namespace object { class ObjectFile; union DataRefImpl { - struct { - // ELF needs this for relocations. This entire union should probably be a - // char[max(8, sizeof(uintptr_t))] and require the impl to cast. - uint16_t a, b; - uint32_t c; - } w; + // 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; @@ -89,6 +85,7 @@ inline bool operator<(const DataRefImpl &a, const DataRefImpl &b) { } class SymbolRef; +typedef content_iterator<SymbolRef> symbol_iterator; /// RelocationRef - This is a value type class that represents a single /// relocation in the list of relocations in the object file. @@ -107,7 +104,7 @@ public: error_code getAddress(uint64_t &Result) const; error_code getOffset(uint64_t &Result) const; - error_code getSymbol(SymbolRef &Result) const; + symbol_iterator getSymbol() const; error_code getType(uint64_t &Result) const; /// @brief Indicates whether this relocation should hidden when listing @@ -119,7 +116,6 @@ public: /// /// This is for display purposes only. error_code getTypeName(SmallVectorImpl<char> &Result) const; - error_code getAdditionalInfo(int64_t &Result) const; /// @brief Get a string that represents the calculation of the value of this /// relocation. @@ -128,11 +124,14 @@ public: error_code getValueString(SmallVectorImpl<char> &Result) const; DataRefImpl getRawDataRefImpl() const; + const ObjectFile *getObjectFile() const; }; typedef content_iterator<RelocationRef> relocation_iterator; /// SectionRef - This is a value type class that represents a single section in /// the list of sections in the object file. +class SectionRef; +typedef content_iterator<SectionRef> section_iterator; class SectionRef { friend class SymbolRef; DataRefImpl SectionPimpl; @@ -169,10 +168,10 @@ public: relocation_iterator begin_relocations() const; relocation_iterator end_relocations() const; + section_iterator getRelocatedSection() const; DataRefImpl getRawDataRefImpl() const; }; -typedef content_iterator<SectionRef> section_iterator; /// SymbolRef - This is a value type class that represents a single symbol in /// the list of symbols in the object file. @@ -238,7 +237,6 @@ public: DataRefImpl getRawDataRefImpl() const; }; -typedef content_iterator<SymbolRef> symbol_iterator; /// LibraryRef - This is a value type class that represents a single library in /// the list of libraries needed by a shared or dynamic object. @@ -326,7 +324,7 @@ protected: bool &Result) const = 0; virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const = 0; virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const = 0; - + virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; // Same as above for RelocationRef. friend class RelocationRef; @@ -336,14 +334,11 @@ protected: uint64_t &Res) const =0; virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const =0; - virtual error_code getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Res) const = 0; + virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0; virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const = 0; virtual error_code getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl<char> &Result) const = 0; - virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const = 0; virtual error_code getRelocationValueString(DataRefImpl Rel, SmallVectorImpl<char> &Result) const = 0; virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const { @@ -540,6 +535,10 @@ inline relocation_iterator SectionRef::end_relocations() const { return OwningObject->getSectionRelEnd(SectionPimpl); } +inline section_iterator SectionRef::getRelocatedSection() const { + return OwningObject->getRelocatedSection(SectionPimpl); +} + inline DataRefImpl SectionRef::getRawDataRefImpl() const { return SectionPimpl; } @@ -566,8 +565,8 @@ inline error_code RelocationRef::getOffset(uint64_t &Result) const { return OwningObject->getRelocationOffset(RelocationPimpl, Result); } -inline error_code RelocationRef::getSymbol(SymbolRef &Result) const { - return OwningObject->getRelocationSymbol(RelocationPimpl, Result); +inline symbol_iterator RelocationRef::getSymbol() const { + return OwningObject->getRelocationSymbol(RelocationPimpl); } inline error_code RelocationRef::getType(uint64_t &Result) const { @@ -579,10 +578,6 @@ inline error_code RelocationRef::getTypeName(SmallVectorImpl<char> &Result) return OwningObject->getRelocationTypeName(RelocationPimpl, Result); } -inline error_code RelocationRef::getAdditionalInfo(int64_t &Result) const { - return OwningObject->getRelocationAdditionalInfo(RelocationPimpl, Result); -} - inline error_code RelocationRef::getValueString(SmallVectorImpl<char> &Result) const { return OwningObject->getRelocationValueString(RelocationPimpl, Result); @@ -596,6 +591,10 @@ inline DataRefImpl RelocationRef::getRawDataRefImpl() const { return RelocationPimpl; } +inline const ObjectFile *RelocationRef::getObjectFile() const { + return OwningObject; +} + // Inline function definitions. inline LibraryRef::LibraryRef(DataRefImpl LibraryP, const ObjectFile *Owner) : LibraryPimpl(LibraryP) diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h index 59d8107..52e4d6f 100644 --- a/include/llvm/Object/RelocVisitor.h +++ b/include/llvm/Object/RelocVisitor.h @@ -18,6 +18,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Object/ELF.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" #include "llvm/Support/raw_ostream.h" @@ -84,6 +85,14 @@ public: HasError = true; return RelocToApply(); } + } else if (FileFormat == "ELF32-ppc") { + switch (RelocType) { + case llvm::ELF::R_PPC_ADDR32: + return visitELF_PPC_ADDR32(R, Value); + default: + HasError = true; + return RelocToApply(); + } } else if (FileFormat == "ELF32-mips") { switch (RelocType) { case llvm::ELF::R_MIPS_32: @@ -102,6 +111,16 @@ public: HasError = true; return RelocToApply(); } + } else if (FileFormat == "ELF64-s390") { + switch (RelocType) { + case llvm::ELF::R_390_32: + return visitELF_390_32(R, Value); + case llvm::ELF::R_390_64: + return visitELF_390_64(R, Value); + default: + HasError = true; + return RelocToApply(); + } } HasError = true; return RelocToApply(); @@ -113,6 +132,37 @@ private: StringRef FileFormat; bool HasError; + int64_t getAddend32LE(RelocationRef R) { + const ELF32LEObjectFile *Obj = cast<ELF32LEObjectFile>(R.getObjectFile()); + DataRefImpl DRI = R.getRawDataRefImpl(); + int64_t Addend; + Obj->getRelocationAddend(DRI, Addend); + return Addend; + } + + int64_t getAddend64LE(RelocationRef R) { + const ELF64LEObjectFile *Obj = cast<ELF64LEObjectFile>(R.getObjectFile()); + DataRefImpl DRI = R.getRawDataRefImpl(); + int64_t Addend; + Obj->getRelocationAddend(DRI, Addend); + return Addend; + } + + int64_t getAddend32BE(RelocationRef R) { + const ELF32BEObjectFile *Obj = cast<ELF32BEObjectFile>(R.getObjectFile()); + DataRefImpl DRI = R.getRawDataRefImpl(); + int64_t Addend; + Obj->getRelocationAddend(DRI, Addend); + return Addend; + } + + int64_t getAddend64BE(RelocationRef R) { + const ELF64BEObjectFile *Obj = cast<ELF64BEObjectFile>(R.getObjectFile()); + DataRefImpl DRI = R.getRawDataRefImpl(); + int64_t Addend; + Obj->getRelocationAddend(DRI, Addend); + return Addend; + } /// Operations /// 386-ELF @@ -123,15 +173,13 @@ private: // Ideally the Addend here will be the addend in the data for // the relocation. It's not actually the case for Rel relocations. RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend32LE(R); return RelocToApply(Value + Addend, 4); } RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value, uint64_t SecAddr) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend32LE(R); uint64_t Address; R.getOffset(Address); return RelocToApply(Value + Addend - Address, 4); @@ -142,35 +190,37 @@ private: return RelocToApply(0, 0); } RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64LE(R); return RelocToApply(Value + Addend, 8); } RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value, uint64_t SecAddr) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64LE(R); uint64_t Address; R.getOffset(Address); return RelocToApply(Value + Addend - Address, 4); } RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64LE(R); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64LE(R); int32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } /// PPC64 ELF RelocToApply visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64BE(R); + uint32_t Res = (Value + Addend) & 0xFFFFFFFF; + return RelocToApply(Res, 4); + } + + /// PPC32 ELF + RelocToApply visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) { + int64_t Addend = getAddend32BE(R); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } @@ -178,15 +228,14 @@ private: /// MIPS ELF RelocToApply visitELF_MIPS_32(RelocationRef R, uint64_t Value) { int64_t Addend; - R.getAdditionalInfo(Addend); + getELFRelocationAddend(R, Addend); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } // AArch64 ELF RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64LE(R); int64_t Res = Value + Addend; // Overflow check allows for both signed and unsigned interpretation. @@ -197,11 +246,26 @@ private: } RelocToApply visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64LE(R); return RelocToApply(Value + Addend, 8); } + // SystemZ ELF + RelocToApply visitELF_390_32(RelocationRef R, uint64_t Value) { + int64_t Addend = getAddend64BE(R); + int64_t Res = Value + Addend; + + // Overflow check allows for both signed and unsigned interpretation. + if (Res < INT32_MIN || Res > UINT32_MAX) + HasError = true; + + return RelocToApply(static_cast<uint32_t>(Res), 4); + } + + RelocToApply visitELF_390_64(RelocationRef R, uint64_t Value) { + int64_t Addend = getAddend64BE(R); + return RelocToApply(Value + Addend, 8); + } }; } diff --git a/include/llvm/Object/YAML.h b/include/llvm/Object/YAML.h new file mode 100644 index 0000000..89fe504 --- /dev/null +++ b/include/llvm/Object/YAML.h @@ -0,0 +1,116 @@ +//===- YAML.h - YAMLIO utilities for object files ---------------*- 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 utility classes for handling the YAML representation of +// object files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_YAML_H +#define LLVM_OBJECT_YAML_H + +#include "llvm/Support/YAMLTraits.h" + +namespace llvm { +namespace object { +namespace yaml { + +/// \brief Specialized YAMLIO scalar type for representing a binary blob. +/// +/// A typical use case would be to represent the content of a section in a +/// binary file. +/// This class has custom YAMLIO traits for convenient reading and writing. +/// It renders as a string of hex digits in a YAML file. +/// For example, it might render as `DEADBEEFCAFEBABE` (YAML does not +/// require the quotation marks, so for simplicity when outputting they are +/// omitted). +/// When reading, any string whose content is an even number of hex digits +/// will be accepted. +/// For example, all of the following are acceptable: +/// `DEADBEEF`, `"DeADbEeF"`, `"\x44EADBEEF"` (Note: '\x44' == 'D') +/// +/// A significant advantage of using this class is that it never allocates +/// temporary strings or buffers for any of its functionality. +/// +/// Example: +/// +/// The YAML mapping: +/// \code +/// Foo: DEADBEEFCAFEBABE +/// \endcode +/// +/// Could be modeled in YAMLIO by the struct: +/// \code +/// struct FooHolder { +/// BinaryRef Foo; +/// }; +/// namespace llvm { +/// namespace yaml { +/// template <> +/// struct MappingTraits<FooHolder> { +/// static void mapping(IO &IO, FooHolder &FH) { +/// IO.mapRequired("Foo", FH.Foo); +/// } +/// }; +/// } // end namespace yaml +/// } // end namespace llvm +/// \endcode +class BinaryRef { + friend bool operator==(const BinaryRef &LHS, const BinaryRef &RHS); + /// \brief Either raw binary data, or a string of hex bytes (must always + /// be an even number of characters). + ArrayRef<uint8_t> Data; + /// \brief Discriminator between the two states of the `Data` member. + bool DataIsHexString; + +public: + BinaryRef(ArrayRef<uint8_t> Data) : Data(Data), DataIsHexString(false) {} + BinaryRef(StringRef Data) + : Data(reinterpret_cast<const uint8_t *>(Data.data()), Data.size()), + DataIsHexString(true) {} + BinaryRef() : DataIsHexString(true) {} + /// \brief The number of bytes that are represented by this BinaryRef. + /// This is the number of bytes that writeAsBinary() will write. + ArrayRef<uint8_t>::size_type binary_size() const { + if (DataIsHexString) + return Data.size() / 2; + return Data.size(); + } + /// \brief Write the contents (regardless of whether it is binary or a + /// hex string) as binary to the given raw_ostream. + void writeAsBinary(raw_ostream &OS) const; + /// \brief Write the contents (regardless of whether it is binary or a + /// hex string) as hex to the given raw_ostream. + /// + /// For example, a possible output could be `DEADBEEFCAFEBABE`. + void writeAsHex(raw_ostream &OS) const; +}; + +inline bool operator==(const BinaryRef &LHS, const BinaryRef &RHS) { + // Special case for default constructed BinaryRef. + if (LHS.Data.empty() && RHS.Data.empty()) + return true; + + return LHS.DataIsHexString == RHS.DataIsHexString && LHS.Data == RHS.Data; +} + +} +} + +namespace yaml { +template <> struct ScalarTraits<object::yaml::BinaryRef> { + static void output(const object::yaml::BinaryRef &, void *, + llvm::raw_ostream &); + static StringRef input(StringRef, void *, object::yaml::BinaryRef &); +}; +} + +} + +#endif |
