diff options
Diffstat (limited to 'include/llvm/Object')
-rw-r--r-- | include/llvm/Object/Binary.h | 20 | ||||
-rw-r--r-- | include/llvm/Object/ELF.h | 476 | ||||
-rw-r--r-- | include/llvm/Object/MachO.h | 171 | ||||
-rw-r--r-- | include/llvm/Object/MachOObject.h | 210 | ||||
-rw-r--r-- | include/llvm/Object/ObjectFile.h | 12 | ||||
-rw-r--r-- | include/llvm/Object/RelocVisitor.h | 32 |
6 files changed, 469 insertions, 452 deletions
diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index 8bbcd8b..78fcf6f 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -41,11 +41,17 @@ protected: // Object and children. ID_StartObjects, ID_COFF, + ID_ELF32L, // ELF 32-bit, little endian ID_ELF32B, // ELF 32-bit, big endian ID_ELF64L, // ELF 64-bit, little endian ID_ELF64B, // ELF 64-bit, big endian - ID_MachO, + + ID_MachO32L, // MachO 32-bit, little endian + ID_MachO32B, // MachO 32-bit, big endian + ID_MachO64L, // MachO 64-bit, little endian + ID_MachO64B, // MachO 64-bit, big endian + ID_EndObjects }; @@ -56,6 +62,13 @@ protected: return is64Bits ? ID_ELF64B : ID_ELF32B; } + static unsigned int getMachOType(bool isLE, bool is64Bits) { + if (isLE) + return is64Bits ? ID_MachO64L : ID_MachO32L; + else + return is64Bits ? ID_MachO64B : ID_MachO32B; + } + public: virtual ~Binary(); @@ -79,7 +92,7 @@ public: } bool isMachO() const { - return TypeID == ID_MachO; + return TypeID >= ID_MachO32L && TypeID <= ID_MachO64B; } bool isCOFF() const { @@ -87,7 +100,8 @@ public: } bool isLittleEndian() const { - return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B); + return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B || + TypeID == ID_MachO32B || TypeID == ID_MachO64B); } }; diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index 8ea5e46..eb2390a 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -81,9 +81,8 @@ template<class ELFT> struct ELFDataTypeTypedefHelper; /// ELF 32bit types. -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct ELFDataTypeTypedefHelper<ELFT<TargetEndianness, MaxAlign, false> > +template<endianness TargetEndianness, std::size_t MaxAlign> +struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, MaxAlign, false> > : ELFDataTypeTypedefHelperCommon<TargetEndianness, MaxAlign> { typedef uint32_t value_type; typedef support::detail::packed_endian_specific_integral @@ -95,9 +94,8 @@ struct ELFDataTypeTypedefHelper<ELFT<TargetEndianness, MaxAlign, false> > }; /// ELF 64bit types. -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct ELFDataTypeTypedefHelper<ELFT<TargetEndianness, MaxAlign, true> > +template<endianness TargetEndianness, std::size_t MaxAlign> +struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, MaxAlign, true> > : ELFDataTypeTypedefHelperCommon<TargetEndianness, MaxAlign> { typedef uint64_t value_type; typedef support::detail::packed_endian_specific_integral @@ -109,27 +107,29 @@ struct ELFDataTypeTypedefHelper<ELFT<TargetEndianness, MaxAlign, true> > }; // I really don't like doing this, but the alternative is copypasta. -#define LLVM_ELF_IMPORT_TYPES(ELFT) \ -typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Addr Elf_Addr; \ -typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Off Elf_Off; \ -typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Half Elf_Half; \ -typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Word Elf_Word; \ -typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Sword Elf_Sword; \ -typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Xword Elf_Xword; \ -typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Sxword Elf_Sxword; - -// This is required to get template types into a macro :( -#define LLVM_ELF_COMMA , - - // Section header. +#define LLVM_ELF_IMPORT_TYPES(E, M, W) \ +typedef typename ELFDataTypeTypedefHelper<ELFType<E,M,W> >::Elf_Addr Elf_Addr; \ +typedef typename ELFDataTypeTypedefHelper<ELFType<E,M,W> >::Elf_Off Elf_Off; \ +typedef typename ELFDataTypeTypedefHelper<ELFType<E,M,W> >::Elf_Half Elf_Half; \ +typedef typename ELFDataTypeTypedefHelper<ELFType<E,M,W> >::Elf_Word Elf_Word; \ +typedef typename \ + ELFDataTypeTypedefHelper<ELFType<E,M,W> >::Elf_Sword Elf_Sword; \ +typedef typename \ + ELFDataTypeTypedefHelper<ELFType<E,M,W> >::Elf_Xword Elf_Xword; \ +typedef typename \ + ELFDataTypeTypedefHelper<ELFType<E,M,W> >::Elf_Sxword Elf_Sxword; + +#define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \ + LLVM_ELF_IMPORT_TYPES(ELFT::TargetEndianness, ELFT::MaxAlignment, \ + ELFT::Is64Bits) + +// Section header. template<class ELFT> struct Elf_Shdr_Base; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Shdr_Base<ELFT<TargetEndianness, MaxAlign, false> > { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA false>) +template<endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Shdr_Base<ELFType<TargetEndianness, MaxAlign, false> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) Elf_Word sh_name; // Section name (index into string table) Elf_Word sh_type; // Section type (SHT_*) Elf_Word sh_flags; // Section flags (SHF_*) @@ -142,11 +142,9 @@ struct Elf_Shdr_Base<ELFT<TargetEndianness, MaxAlign, false> > { Elf_Word sh_entsize; // Size of records contained within the section }; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Shdr_Base<ELFT<TargetEndianness, MaxAlign, true> > { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA true>) +template<endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Shdr_Base<ELFType<TargetEndianness, MaxAlign, true> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) Elf_Word sh_name; // Section name (index into string table) Elf_Word sh_type; // Section type (SHT_*) Elf_Xword sh_flags; // Section flags (SHF_*) @@ -175,11 +173,9 @@ struct Elf_Shdr_Impl : Elf_Shdr_Base<ELFT> { template<class ELFT> struct Elf_Sym_Base; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Sym_Base<ELFT<TargetEndianness, MaxAlign, false> > { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA false>) +template<endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Sym_Base<ELFType<TargetEndianness, MaxAlign, false> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) Elf_Word st_name; // Symbol name (index into string table) Elf_Addr st_value; // Value or address associated with the symbol Elf_Word st_size; // Size of the symbol @@ -188,11 +184,9 @@ struct Elf_Sym_Base<ELFT<TargetEndianness, MaxAlign, false> > { Elf_Half st_shndx; // Which section (header table index) it's defined in }; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Sym_Base<ELFT<TargetEndianness, MaxAlign, true> > { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA true>) +template<endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Sym_Base<ELFType<TargetEndianness, MaxAlign, true> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) Elf_Word st_name; // Symbol name (index into string table) unsigned char st_info; // Symbol's type and binding attributes unsigned char st_other; // Must be zero; reserved @@ -220,7 +214,7 @@ struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> { /// (.gnu.version). This structure is identical for ELF32 and ELF64. template<class ELFT> struct Elf_Versym_Impl { - LLVM_ELF_IMPORT_TYPES(ELFT) + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) Elf_Half vs_index; // Version index with flags (e.g. VERSYM_HIDDEN) }; @@ -231,7 +225,7 @@ struct Elf_Verdaux_Impl; /// (.gnu.version_d). This structure is identical for ELF32 and ELF64. template<class ELFT> struct Elf_Verdef_Impl { - LLVM_ELF_IMPORT_TYPES(ELFT) + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) typedef Elf_Verdaux_Impl<ELFT> Elf_Verdaux; Elf_Half vd_version; // Version of this structure (e.g. VER_DEF_CURRENT) Elf_Half vd_flags; // Bitwise flags (VER_DEF_*) @@ -251,7 +245,7 @@ struct Elf_Verdef_Impl { /// section (.gnu.version_d). This structure is identical for ELF32 and ELF64. template<class ELFT> struct Elf_Verdaux_Impl { - LLVM_ELF_IMPORT_TYPES(ELFT) + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) Elf_Word vda_name; // Version name (offset in string table) Elf_Word vda_next; // Offset to next Verdaux entry (in bytes) }; @@ -260,7 +254,7 @@ struct Elf_Verdaux_Impl { /// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. template<class ELFT> struct Elf_Verneed_Impl { - LLVM_ELF_IMPORT_TYPES(ELFT) + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) Elf_Half vn_version; // Version of this structure (e.g. VER_NEED_CURRENT) Elf_Half vn_cnt; // Number of associated Vernaux entries Elf_Word vn_file; // Library name (string table offset) @@ -272,7 +266,7 @@ struct Elf_Verneed_Impl { /// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. template<class ELFT> struct Elf_Vernaux_Impl { - LLVM_ELF_IMPORT_TYPES(ELFT) + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) Elf_Word vna_hash; // Hash of dependency name Elf_Half vna_flags; // Bitwise Flags (VER_FLAG_*) Elf_Half vna_other; // Version index, used in .gnu.version entries @@ -285,11 +279,9 @@ struct Elf_Vernaux_Impl { template<class ELFT> struct Elf_Dyn_Base; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Dyn_Base<ELFT<TargetEndianness, MaxAlign, false> > { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA false>) +template<endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Dyn_Base<ELFType<TargetEndianness, MaxAlign, false> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) Elf_Sword d_tag; union { Elf_Word d_val; @@ -297,11 +289,9 @@ struct Elf_Dyn_Base<ELFT<TargetEndianness, MaxAlign, false> > { } d_un; }; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Dyn_Base<ELFT<TargetEndianness, MaxAlign, true> > { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA true>) +template<endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Dyn_Base<ELFType<TargetEndianness, MaxAlign, true> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) Elf_Sxword d_tag; union { Elf_Xword d_val; @@ -323,11 +313,9 @@ struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> { template<class ELFT, bool isRela> struct Elf_Rel_Base; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, false> { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA false>) +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 @@ -340,11 +328,9 @@ struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, false> { } }; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, false> { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA true>) +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 @@ -365,11 +351,9 @@ struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, false> { } }; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, true> { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA 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 @@ -383,11 +367,9 @@ struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, true> { } }; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, true> { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA 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. @@ -411,12 +393,10 @@ struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, true> { template<class ELFT, bool isRela> struct Elf_Rel_Impl; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign, bool isRela> -struct Elf_Rel_Impl<ELFT<TargetEndianness, MaxAlign, true>, isRela> - : Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, isRela> { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA true>) +template<endianness TargetEndianness, std::size_t MaxAlign, bool isRela> +struct Elf_Rel_Impl<ELFType<TargetEndianness, MaxAlign, true>, isRela> + : Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, isRela> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, // and ELF64_R_INFO macros defined in the ELF specification: @@ -433,12 +413,10 @@ struct Elf_Rel_Impl<ELFT<TargetEndianness, MaxAlign, true>, isRela> } }; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign, bool isRela> -struct Elf_Rel_Impl<ELFT<TargetEndianness, MaxAlign, false>, isRela> - : Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, isRela> { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA false>) +template<endianness TargetEndianness, std::size_t MaxAlign, bool isRela> +struct Elf_Rel_Impl<ELFType<TargetEndianness, MaxAlign, false>, isRela> + : Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, isRela> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, // and ELF32_R_INFO macros defined in the ELF specification: @@ -457,7 +435,7 @@ struct Elf_Rel_Impl<ELFT<TargetEndianness, MaxAlign, false>, isRela> template<class ELFT> struct Elf_Ehdr_Impl { - LLVM_ELF_IMPORT_TYPES(ELFT) + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes Elf_Half e_type; // Type of file (see ET_*) Elf_Half e_machine; // Required architecture for this file (see EM_*) @@ -483,11 +461,9 @@ struct Elf_Ehdr_Impl { template<class ELFT> struct Elf_Phdr_Impl; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Phdr_Impl<ELFT<TargetEndianness, MaxAlign, false> > { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA false>) +template<endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Phdr_Impl<ELFType<TargetEndianness, MaxAlign, false> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) Elf_Word p_type; // Type of segment Elf_Off p_offset; // FileOffset where segment is located, in bytes Elf_Addr p_vaddr; // Virtual Address of beginning of segment @@ -498,11 +474,9 @@ struct Elf_Phdr_Impl<ELFT<TargetEndianness, MaxAlign, false> > { Elf_Word p_align; // Segment alignment constraint }; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Phdr_Impl<ELFT<TargetEndianness, MaxAlign, true> > { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA true>) +template<endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Phdr_Impl<ELFType<TargetEndianness, MaxAlign, true> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) Elf_Word p_type; // Type of segment Elf_Word p_flags; // Segment flags Elf_Off p_offset; // FileOffset where segment is located, in bytes @@ -515,7 +489,7 @@ struct Elf_Phdr_Impl<ELFT<TargetEndianness, MaxAlign, true> > { template<class ELFT> class ELFObjectFile : public ObjectFile { - LLVM_ELF_IMPORT_TYPES(ELFT) + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) public: /// \brief Iterate over constant sized entities. @@ -633,6 +607,8 @@ private: mutable const char *dt_soname; private: + uint64_t getROffset(DataRefImpl Rel) const; + // Records for each version index the corresponding Verdef or Vernaux entry. // This is filled the first time LoadVersionMap() is called. class VersionMapEntry : public PointerIntPair<const void*, 1> { @@ -689,6 +665,7 @@ public: protected: const Elf_Sym *getSymbol(DataRefImpl Symb) const; // FIXME: Should be private? void validateSymbol(DataRefImpl Symb) const; + StringRef getRelocationTypeName(uint32_t Type) const; public: error_code getSymbolName(const Elf_Shdr *section, @@ -705,6 +682,7 @@ protected: 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 getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; @@ -1138,6 +1116,21 @@ error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb, } template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb, + uint32_t &Res) const { + uint32_t flags; + getSymbolFlags(Symb, flags); + if (flags & SymbolRef::SF_Common) { + uint64_t Value; + getSymbolValue(Symb, Value); + Res = Value; + } else { + Res = 0; + } + return object_error::success; +} + +template<class ELFT> error_code ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Symb, uint64_t &Result) const { validateSymbol(Symb); @@ -1546,45 +1539,32 @@ error_code ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel, template<class ELFT> error_code ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel, uint64_t &Result) const { - uint64_t offset; - const Elf_Shdr *sec = getSection(Rel.w.b); - switch (sec->sh_type) { - default : - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL : { - offset = getRel(Rel)->r_offset; - break; - } - case ELF::SHT_RELA : { - offset = getRela(Rel)->r_offset; - break; - } - } - - Result = offset; + assert((Header->e_type == ELF::ET_EXEC || Header->e_type == ELF::ET_DYN) && + "Only executable and shared objects files have addresses"); + Result = getROffset(Rel); return object_error::success; } template<class ELFT> error_code ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel, uint64_t &Result) const { - uint64_t offset; + assert(Header->e_type == ELF::ET_REL && + "Only relocatable object files have relocation offsets"); + Result = getROffset(Rel); + return object_error::success; +} + +template<class ELFT> +uint64_t ELFObjectFile<ELFT>::getROffset(DataRefImpl Rel) const { const Elf_Shdr *sec = getSection(Rel.w.b); switch (sec->sh_type) { - default : - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL : { - offset = getRel(Rel)->r_offset; - break; - } - case ELF::SHT_RELA : { - offset = getRela(Rel)->r_offset; - break; - } + default: + report_fatal_error("Invalid section type in Rel!"); + case ELF::SHT_REL: + return getRel(Rel)->r_offset; + case ELF::SHT_RELA: + return getRela(Rel)->r_offset; } - - Result = offset - sec->sh_addr; - return object_error::success; } template<class ELFT> @@ -1607,29 +1587,14 @@ error_code ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel, } #define LLVM_ELF_SWITCH_RELOC_TYPE_NAME(enum) \ - case ELF::enum: res = #enum; break; + case ELF::enum: Res = #enum; break; template<class ELFT> -error_code ELFObjectFile<ELFT>::getRelocationTypeName( - DataRefImpl Rel, SmallVectorImpl<char> &Result) const { - const Elf_Shdr *sec = getSection(Rel.w.b); - uint32_t type; - StringRef res; - switch (sec->sh_type) { - default : - return object_error::parse_failed; - case ELF::SHT_REL : { - type = getRel(Rel)->getType(isMips64EL()); - break; - } - case ELF::SHT_RELA : { - type = getRela(Rel)->getType(isMips64EL()); - break; - } - } +StringRef ELFObjectFile<ELFT>::getRelocationTypeName(uint32_t Type) const { + StringRef Res = "Unknown"; switch (Header->e_machine) { case ELF::EM_X86_64: - switch (type) { + switch (Type) { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_NONE); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC32); @@ -1657,17 +1622,22 @@ error_code ELFObjectFile<ELFT>::getRelocationTypeName( LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTOFF64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOT64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPCREL64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPLT64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PLTOFF64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_SIZE32); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_SIZE64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC32_TLSDESC); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSDESC_CALL); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSDESC); - default: - res = "Unknown"; + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_IRELATIVE); + default: break; } break; case ELF::EM_386: - switch (type) { + switch (Type) { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_NONE); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_32); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC32); @@ -1708,12 +1678,11 @@ error_code ELFObjectFile<ELFT>::getRelocationTypeName( LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DESC_CALL); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DESC); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_IRELATIVE); - default: - res = "Unknown"; + default: break; } break; case ELF::EM_MIPS: - switch (type) { + switch (Type) { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_NONE); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_16); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_32); @@ -1765,12 +1734,12 @@ error_code ELFObjectFile<ELFT>::getRelocationTypeName( LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GLOB_DAT); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_COPY); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_JUMP_SLOT); - default: - res = "Unknown"; + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_NUM); + default: break; } break; case ELF::EM_AARCH64: - switch (type) { + switch (Type) { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_NONE); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS32); @@ -1844,13 +1813,11 @@ error_code ELFObjectFile<ELFT>::getRelocationTypeName( LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_LD64_LO12_NC); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_ADD_LO12_NC); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_CALL); - - default: - res = "Unknown"; + default: break; } break; case ELF::EM_ARM: - switch (type) { + switch (Type) { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_NONE); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PC24); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS32); @@ -1982,12 +1949,11 @@ error_code ELFObjectFile<ELFT>::getRelocationTypeName( LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ME_TOO); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_DESCSEQ16); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_DESCSEQ32); - default: - res = "Unknown"; + default: break; } break; case ELF::EM_HEXAGON: - switch (type) { + switch (Type) { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_NONE); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B22_PCREL); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B15_PCREL); @@ -2074,20 +2040,185 @@ error_code ELFObjectFile<ELFT>::getRelocationTypeName( LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_32_6_X); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_16_X); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_11_X); - default: - res = "Unknown"; + default: break; } break; - default: - res = "Unknown"; + case ELF::EM_PPC: + switch (Type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14_BRTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14_BRNTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14_BRTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14_BRNTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_HA); + default: break; + } + break; + case ELF::EM_PPC64: + 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_ADDR16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL24); + 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); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHEST); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLSGD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLSLD); + 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; } - Result.append(res.begin(), res.end()); - return object_error::success; + return Res; } #undef LLVM_ELF_SWITCH_RELOC_TYPE_NAME template<class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationTypeName( + DataRefImpl Rel, SmallVectorImpl<char> &Result) const { + const Elf_Shdr *sec = getSection(Rel.w.b); + uint32_t type; + switch (sec->sh_type) { + default : + return object_error::parse_failed; + case ELF::SHT_REL : { + type = getRel(Rel)->getType(isMips64EL()); + break; + } + case ELF::SHT_RELA : { + type = getRela(Rel)->getType(isMips64EL()); + break; + } + } + + if (!isMips64EL()) { + StringRef Name = getRelocationTypeName(type); + Result.append(Name.begin(), Name.end()); + } else { + uint8_t Type1 = (type >> 0) & 0xFF; + uint8_t Type2 = (type >> 8) & 0xFF; + uint8_t Type3 = (type >> 16) & 0xFF; + + // Concat all three relocation type names. + StringRef Name = getRelocationTypeName(Type1); + Result.append(Name.begin(), Name.end()); + + Name = getRelocationTypeName(Type2); + Result.append(1, '/'); + Result.append(Name.begin(), Name.end()); + + Name = getRelocationTypeName(Type3); + Result.append(1, '/'); + Result.append(Name.begin(), Name.end()); + } + + return object_error::success; +} + +template<class ELFT> error_code ELFObjectFile<ELFT>::getRelocationAdditionalInfo( DataRefImpl Rel, int64_t &Result) const { const Elf_Shdr *sec = getSection(Rel.w.b); @@ -2189,8 +2320,7 @@ ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec) : ObjectFile(getELFType( static_cast<endianness>(ELFT::TargetEndianness) == support::little, ELFT::Is64Bits), - Object, - ec) + Object) , isDyldELFObject(false) , SectionHeaderTable(0) , dot_shstrtab_sec(0) @@ -2566,6 +2696,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"; } @@ -2593,6 +2725,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; } diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index ed7aabd..14cd4d7 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -7,16 +7,17 @@ // //===----------------------------------------------------------------------===// // -// This file declares the MachOObjectFile class, which binds the MachOObject -// class to the generic ObjectFile wrapper. +// This file declares the MachOObjectFile class, which implement the ObjectFile +// interface for MachO files. // //===----------------------------------------------------------------------===// #ifndef LLVM_OBJECT_MACHO_H #define LLVM_OBJECT_MACHO_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Object/MachOObject.h" +#include "llvm/Object/MachOFormat.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/MachO.h" #include "llvm/Support/raw_ostream.h" @@ -24,46 +25,26 @@ namespace llvm { namespace object { -typedef MachOObject::LoadCommandInfo LoadCommandInfo; - class MachOObjectFile : public ObjectFile { public: - MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, 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; + struct LoadCommandInfo { + const char *Ptr; // Where in memory the load command is. + macho::LoadCommand C; // The command itself. + }; - virtual uint8_t getBytesInAddress() const; - virtual StringRef getFileFormatName() const; - virtual unsigned getArch() const; - virtual StringRef getLoadName() const; + MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits, + error_code &ec); - // 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. - error_code getSectionFinalSegmentName(DataRefImpl Sec, StringRef &Res) const; - - MachOObject *getObject() { return MachOObj.get(); } - - static inline bool classof(const Binary *v) { - return v->isMachO(); - } - -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 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 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 getSymbolSection(DataRefImpl Symb, section_iterator &Res) const; virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; @@ -82,21 +63,17 @@ protected: 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 DRI, DataRefImpl S, + virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const; virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; virtual relocation_iterator getSectionRelEnd(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 error_code getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Res) const; - virtual error_code getRelocationType(DataRefImpl Rel, - uint64_t &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 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, @@ -108,28 +85,98 @@ protected: virtual error_code getLibraryNext(DataRefImpl LibData, LibraryRef &Res) const; virtual error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const; -private: - OwningPtr<MachOObject> MachOObj; - mutable uint32_t RegisteredStringTable; - typedef SmallVector<DataRefImpl, 1> SectionList; - SectionList Sections; + // 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; + + virtual symbol_iterator begin_dynamic_symbols() const; + virtual symbol_iterator end_dynamic_symbols() const; + + virtual section_iterator begin_sections() const; + virtual section_iterator end_sections() const; + + virtual library_iterator begin_libraries_needed() const; + virtual library_iterator end_libraries_needed() const; + + virtual uint8_t getBytesInAddress() const; + + virtual StringRef getFileFormatName() const; + virtual unsigned getArch() const; + + virtual StringRef getLoadName() const; - void moveToNextSection(DataRefImpl &DRI) const; - void getSymbolTableEntry(DataRefImpl DRI, - InMemoryStruct<macho::SymbolTableEntry> &Res) const; - void getSymbol64TableEntry(DataRefImpl DRI, - InMemoryStruct<macho::Symbol64TableEntry> &Res) const; - void moveToNextSymbol(DataRefImpl &DRI) const; - void getSection(DataRefImpl DRI, InMemoryStruct<macho::Section> &Res) const; - void getSection64(DataRefImpl DRI, - InMemoryStruct<macho::Section64> &Res) const; - void getRelocation(DataRefImpl Rel, - InMemoryStruct<macho::RelocationEntry> &Res) const; - std::size_t getSectionIndex(DataRefImpl Sec) const; - - void printRelocationTargetName(InMemoryStruct<macho::RelocationEntry>& RE, - raw_string_ostream &fmt) const; + relocation_iterator getSectionRelBegin(unsigned Index) const; + relocation_iterator getSectionRelEnd(unsigned Index) 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. + StringRef getSectionFinalSegmentName(DataRefImpl Sec) const; + + // Names are stored as 16 bytes. These returns the raw 16 bytes without + // interpreting them as a C string. + ArrayRef<char> getSectionRawName(DataRefImpl Sec) const; + ArrayRef<char> getSectionRawFinalSegmentName(DataRefImpl Sec) const; + + // MachO specific Info about relocations. + bool isRelocationScattered(const macho::RelocationEntry &RE) const; + unsigned getPlainRelocationSymbolNum(const macho::RelocationEntry &RE) const; + bool getPlainRelocationExternal(const macho::RelocationEntry &RE) const; + bool getScatteredRelocationScattered(const macho::RelocationEntry &RE) const; + uint32_t getScatteredRelocationValue(const macho::RelocationEntry &RE) const; + unsigned getAnyRelocationAddress(const macho::RelocationEntry &RE) const; + unsigned getAnyRelocationPCRel(const macho::RelocationEntry &RE) const; + unsigned getAnyRelocationLength(const macho::RelocationEntry &RE) const; + unsigned getAnyRelocationType(const macho::RelocationEntry &RE) const; + SectionRef getRelocationSection(const macho::RelocationEntry &RE) const; + + // Walk load commands. + LoadCommandInfo getFirstLoadCommandInfo() const; + LoadCommandInfo getNextLoadCommandInfo(const LoadCommandInfo &L) const; + + // MachO specific structures. + macho::Section getSection(DataRefImpl DRI) const; + macho::Section64 getSection64(DataRefImpl DRI) const; + macho::Section getSection(const LoadCommandInfo &L, unsigned Index) const; + macho::Section64 getSection64(const LoadCommandInfo &L, unsigned Index) const; + macho::SymbolTableEntry getSymbolTableEntry(DataRefImpl DRI) const; + macho::Symbol64TableEntry getSymbol64TableEntry(DataRefImpl DRI) const; + + macho::LinkeditDataLoadCommand + getLinkeditDataLoadCommand(const LoadCommandInfo &L) const; + macho::SegmentLoadCommand + getSegmentLoadCommand(const LoadCommandInfo &L) const; + macho::Segment64LoadCommand + getSegment64LoadCommand(const LoadCommandInfo &L) const; + macho::LinkerOptionsLoadCommand + getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const; + + macho::RelocationEntry getRelocation(DataRefImpl Rel) const; + macho::Header getHeader() const; + macho::Header64Ext getHeader64Ext() const; + macho::IndirectSymbolTableEntry + getIndirectSymbolTableEntry(const macho::DysymtabLoadCommand &DLC, + unsigned Index) const; + macho::DataInCodeTableEntry getDataInCodeTableEntry(uint32_t DataOffset, + unsigned Index) const; + macho::SymtabLoadCommand getSymtabLoadCommand() const; + macho::DysymtabLoadCommand getDysymtabLoadCommand() const; + + StringRef getStringTableData() const; + bool is64Bit() const; + void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const; + + static bool classof(const Binary *v) { + return v->isMachO(); + } + +private: + typedef SmallVector<const char*, 1> SectionList; + SectionList Sections; + const char *SymtabLoadCmd; + const char *DysymtabLoadCmd; }; } diff --git a/include/llvm/Object/MachOObject.h b/include/llvm/Object/MachOObject.h deleted file mode 100644 index 9e4ab19..0000000 --- a/include/llvm/Object/MachOObject.h +++ /dev/null @@ -1,210 +0,0 @@ -//===- MachOObject.h - Mach-O Object File Wrapper ---------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_MACHOOBJECT_H -#define LLVM_OBJECT_MACHOOBJECT_H - -#include "llvm/ADT/InMemoryStruct.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Object/MachOFormat.h" -#include <string> - -namespace llvm { - -class MemoryBuffer; -class raw_ostream; - -namespace object { - -/// \brief Wrapper object for manipulating Mach-O object files. -/// -/// This class is designed to implement a full-featured, efficient, portable, -/// and robust Mach-O interface to Mach-O object files. It does not attempt to -/// smooth over rough edges in the Mach-O format or generalize access to object -/// independent features. -/// -/// The class is designed around accessing the Mach-O object which is expected -/// to be fully loaded into memory. -/// -/// This class is *not* suitable for concurrent use. For efficient operation, -/// the class uses APIs which rely on the ability to cache the results of -/// certain calls in internal objects which are not safe for concurrent -/// access. This allows the API to be zero-copy on the common paths. -// -// FIXME: It would be cool if we supported a "paged" MemoryBuffer -// implementation. This would allow us to implement a more sensible version of -// MemoryObject which can work like a MemoryBuffer, but be more efficient for -// objects which are in the current address space. -class MachOObject { -public: - struct LoadCommandInfo { - /// The load command information. - macho::LoadCommand Command; - - /// The offset to the start of the load command in memory. - uint64_t Offset; - }; - -private: - OwningPtr<MemoryBuffer> Buffer; - - /// Whether the object is little endian. - bool IsLittleEndian; - /// Whether the object is 64-bit. - bool Is64Bit; - /// Whether the object is swapped endianness from the host. - bool IsSwappedEndian; - /// Whether the string table has been registered. - bool HasStringTable; - - /// The cached information on the load commands. - LoadCommandInfo *LoadCommands; - mutable unsigned NumLoadedCommands; - - /// The cached copy of the header. - macho::Header Header; - macho::Header64Ext Header64Ext; - - /// Cache string table information. - StringRef StringTable; - -private: - MachOObject(MemoryBuffer *Buffer, bool IsLittleEndian, bool Is64Bit); - -public: - ~MachOObject(); - - /// \brief Load a Mach-O object from a MemoryBuffer object. - /// - /// \param Buffer - The buffer to load the object from. This routine takes - /// exclusive ownership of the buffer (which is passed to the returned object - /// on success). - /// \param ErrorStr [out] - If given, will be set to a user readable error - /// message on failure. - /// \returns The loaded object, or null on error. - static MachOObject *LoadFromBuffer(MemoryBuffer *Buffer, - std::string *ErrorStr = 0); - - /// @name File Information - /// @{ - - bool isLittleEndian() const { return IsLittleEndian; } - bool isSwappedEndian() const { return IsSwappedEndian; } - bool is64Bit() const { return Is64Bit; } - - unsigned getHeaderSize() const { - return Is64Bit ? macho::Header64Size : macho::Header32Size; - } - - StringRef getData(size_t Offset, size_t Size) const; - - /// @} - /// @name String Table Data - /// @{ - - StringRef getStringTableData() const { - assert(HasStringTable && "String table has not been registered!"); - return StringTable; - } - - StringRef getStringAtIndex(unsigned Index) const { - size_t End = getStringTableData().find('\0', Index); - return getStringTableData().slice(Index, End); - } - - void RegisterStringTable(macho::SymtabLoadCommand &SLC); - - /// @} - /// @name Object Header Access - /// @{ - - const macho::Header &getHeader() const { return Header; } - const macho::Header64Ext &getHeader64Ext() const { - assert(is64Bit() && "Invalid access!"); - return Header64Ext; - } - - /// @} - /// @name Object Structure Access - /// @{ - - /// \brief Retrieve the information for the given load command. - const LoadCommandInfo &getLoadCommandInfo(unsigned Index) const; - - void ReadSegmentLoadCommand( - const LoadCommandInfo &LCI, - InMemoryStruct<macho::SegmentLoadCommand> &Res) const; - void ReadSegment64LoadCommand( - const LoadCommandInfo &LCI, - InMemoryStruct<macho::Segment64LoadCommand> &Res) const; - void ReadSymtabLoadCommand( - const LoadCommandInfo &LCI, - InMemoryStruct<macho::SymtabLoadCommand> &Res) const; - void ReadDysymtabLoadCommand( - const LoadCommandInfo &LCI, - InMemoryStruct<macho::DysymtabLoadCommand> &Res) const; - void ReadLinkeditDataLoadCommand( - const LoadCommandInfo &LCI, - InMemoryStruct<macho::LinkeditDataLoadCommand> &Res) const; - void ReadLinkerOptionsLoadCommand( - const LoadCommandInfo &LCI, - InMemoryStruct<macho::LinkerOptionsLoadCommand> &Res) const; - void ReadIndirectSymbolTableEntry( - const macho::DysymtabLoadCommand &DLC, - unsigned Index, - InMemoryStruct<macho::IndirectSymbolTableEntry> &Res) const; - void ReadSection( - const LoadCommandInfo &LCI, - unsigned Index, - InMemoryStruct<macho::Section> &Res) const; - void ReadSection64( - const LoadCommandInfo &LCI, - unsigned Index, - InMemoryStruct<macho::Section64> &Res) const; - void ReadRelocationEntry( - uint64_t RelocationTableOffset, unsigned Index, - InMemoryStruct<macho::RelocationEntry> &Res) const; - void ReadSymbolTableEntry( - uint64_t SymbolTableOffset, unsigned Index, - InMemoryStruct<macho::SymbolTableEntry> &Res) const; - void ReadSymbol64TableEntry( - uint64_t SymbolTableOffset, unsigned Index, - InMemoryStruct<macho::Symbol64TableEntry> &Res) const; - void ReadDataInCodeTableEntry( - uint64_t TableOffset, unsigned Index, - InMemoryStruct<macho::DataInCodeTableEntry> &Res) const; - void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const; - - /// @} - - /// @name Object Dump Facilities - /// @{ - /// dump - Support for debugging, callable in GDB: V->dump() - // - void dump() const; - void dumpHeader() const; - - /// print - Implement operator<< on Value. - /// - void print(raw_ostream &O) const; - void printHeader(raw_ostream &O) const; - - /// @} -}; - -inline raw_ostream &operator<<(raw_ostream &OS, const MachOObject &V) { - V.print(OS); - return OS; -} - -} // end namespace object -} // end namespace llvm - -#endif diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index 6a66653..eb53cc0 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -217,6 +217,8 @@ public: /// mapped). error_code getAddress(uint64_t &Result) const; error_code getFileOffset(uint64_t &Result) const; + /// @brief Get the alignment of this symbol as the actual value (not log 2). + error_code getAlignment(uint32_t &Result) const; error_code getSize(uint64_t &Result) const; error_code getType(SymbolRef::Type &Result) const; @@ -227,9 +229,6 @@ public: /// Get symbol flags (bitwise OR of SymbolRef::Flags) error_code getFlags(uint32_t &Result) const; - /// @brief Return true for common symbols such as uninitialized globals - error_code isCommon(bool &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; @@ -276,7 +275,7 @@ class ObjectFile : public Binary { ObjectFile(const ObjectFile &other) LLVM_DELETED_FUNCTION; protected: - ObjectFile(unsigned int Type, MemoryBuffer *source, error_code &ec); + ObjectFile(unsigned int Type, MemoryBuffer *source); const uint8_t *base() const { return reinterpret_cast<const uint8_t *>(Data->getBufferStart()); @@ -295,6 +294,7 @@ protected: virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const = 0; 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; @@ -428,6 +428,10 @@ inline error_code SymbolRef::getFileOffset(uint64_t &Result) const { return OwningObject->getSymbolFileOffset(SymbolPimpl, Result); } +inline error_code SymbolRef::getAlignment(uint32_t &Result) const { + return OwningObject->getSymbolAlignment(SymbolPimpl, Result); +} + inline error_code SymbolRef::getSize(uint64_t &Result) const { return OwningObject->getSymbolSize(SymbolPimpl, Result); } diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h index 2dcbdf9..6239ec1 100644 --- a/include/llvm/Object/RelocVisitor.h +++ b/include/llvm/Object/RelocVisitor.h @@ -102,6 +102,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(); @@ -133,7 +143,7 @@ private: int64_t Addend; R.getAdditionalInfo(Addend); uint64_t Address; - R.getAddress(Address); + R.getOffset(Address); return RelocToApply(Value + Addend - Address, 4); } @@ -151,7 +161,7 @@ private: int64_t Addend; R.getAdditionalInfo(Addend); uint64_t Address; - R.getAddress(Address); + R.getOffset(Address); return RelocToApply(Value + Addend - Address, 4); } RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) { @@ -202,6 +212,24 @@ private: return RelocToApply(Value + Addend, 8); } + // SystemZ ELF + RelocToApply visitELF_390_32(RelocationRef R, uint64_t Value) { + int64_t Addend; + R.getAdditionalInfo(Addend); + 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; + R.getAdditionalInfo(Addend); + return RelocToApply(Value + Addend, 8); + } }; } |