#ifndef LLVM_OBJECT_ELFTYPES_H
#define LLVM_OBJECT_ELFTYPES_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Object/Error.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorOr.h"
namespace llvm {
namespace object {
using support::endianness;
template <endianness target_endianness, bool is64Bits> struct ELFType {
static const endianness TargetEndianness = target_endianness;
static const bool Is64Bits = is64Bits;
};
typedef ELFType<support::little, false> ELF32LE;
typedef ELFType<support::big, false> ELF32BE;
typedef ELFType<support::little, true> ELF64LE;
typedef ELFType<support::big, true> ELF64BE;
template <endianness target_endianness> struct ELFDataTypeTypedefHelperCommon {
typedef support::detail::packed_endian_specific_integral<
uint16_t, target_endianness, 2> Elf_Half;
typedef support::detail::packed_endian_specific_integral<
uint32_t, target_endianness, 2> Elf_Word;
typedef support::detail::packed_endian_specific_integral<
int32_t, target_endianness, 2> Elf_Sword;
typedef support::detail::packed_endian_specific_integral<
uint64_t, target_endianness, 2> Elf_Xword;
typedef support::detail::packed_endian_specific_integral<
int64_t, target_endianness, 2> Elf_Sxword;
};
template <class ELFT> struct ELFDataTypeTypedefHelper;
template <endianness TargetEndianness>
struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, false>>
: ELFDataTypeTypedefHelperCommon<TargetEndianness> {
typedef uint32_t value_type;
typedef support::detail::packed_endian_specific_integral<
value_type, TargetEndianness, 2> Elf_Addr;
typedef support::detail::packed_endian_specific_integral<
value_type, TargetEndianness, 2> Elf_Off;
};
template <endianness TargetEndianness>
struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, true>>
: ELFDataTypeTypedefHelperCommon<TargetEndianness> {
typedef uint64_t value_type;
typedef support::detail::packed_endian_specific_integral<
value_type, TargetEndianness, 2> Elf_Addr;
typedef support::detail::packed_endian_specific_integral<
value_type, TargetEndianness, 2> Elf_Off;
};
#define LLVM_ELF_IMPORT_TYPES(E, W) \
typedef typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Addr Elf_Addr; \
typedef typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Off Elf_Off; \
typedef typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Half Elf_Half; \
typedef typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Word Elf_Word; \
typedef \
typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Sword Elf_Sword; \
typedef \
typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Xword Elf_Xword; \
typedef \
typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Sxword Elf_Sxword;
#define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \
LLVM_ELF_IMPORT_TYPES(ELFT::TargetEndianness, ELFT::Is64Bits)
template <class ELFT> struct Elf_Shdr_Base;
template <endianness TargetEndianness>
struct Elf_Shdr_Base<ELFType<TargetEndianness, false>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
Elf_Word sh_name; Elf_Word sh_type; Elf_Word sh_flags; Elf_Addr sh_addr; Elf_Off sh_offset; Elf_Word sh_size; Elf_Word sh_link; Elf_Word sh_info; Elf_Word sh_addralign; Elf_Word sh_entsize; };
template <endianness TargetEndianness>
struct Elf_Shdr_Base<ELFType<TargetEndianness, true>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
Elf_Word sh_name; Elf_Word sh_type; Elf_Xword sh_flags; Elf_Addr sh_addr; Elf_Off sh_offset; Elf_Xword sh_size; Elf_Word sh_link; Elf_Word sh_info; Elf_Xword sh_addralign; Elf_Xword sh_entsize; };
template <class ELFT>
struct Elf_Shdr_Impl : Elf_Shdr_Base<ELFT> {
using Elf_Shdr_Base<ELFT>::sh_entsize;
using Elf_Shdr_Base<ELFT>::sh_size;
unsigned getEntityCount() const {
if (sh_entsize == 0)
return 0;
return sh_size / sh_entsize;
}
};
template <class ELFT> struct Elf_Sym_Base;
template <endianness TargetEndianness>
struct Elf_Sym_Base<ELFType<TargetEndianness, false>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
Elf_Word st_name; Elf_Addr st_value; Elf_Word st_size; unsigned char st_info; unsigned char st_other; Elf_Half st_shndx; };
template <endianness TargetEndianness>
struct Elf_Sym_Base<ELFType<TargetEndianness, true>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
Elf_Word st_name; unsigned char st_info; unsigned char st_other; Elf_Half st_shndx; Elf_Addr st_value; Elf_Xword st_size; };
template <class ELFT>
struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> {
using Elf_Sym_Base<ELFT>::st_info;
using Elf_Sym_Base<ELFT>::st_shndx;
using Elf_Sym_Base<ELFT>::st_other;
using Elf_Sym_Base<ELFT>::st_value;
unsigned char getBinding() const { return st_info >> 4; }
unsigned char getType() const { return st_info & 0x0f; }
uint64_t getValue() const { return st_value; }
void setBinding(unsigned char b) { setBindingAndType(b, getType()); }
void setType(unsigned char t) { setBindingAndType(getBinding(), t); }
void setBindingAndType(unsigned char b, unsigned char t) {
st_info = (b << 4) + (t & 0x0f);
}
unsigned char getVisibility() const { return st_other & 0x3; }
void setVisibility(unsigned char v) {
assert(v < 4 && "Invalid value for visibility");
st_other = (st_other & ~0x3) | v;
}
bool isAbsolute() const { return st_shndx == ELF::SHN_ABS; }
bool isCommon() const {
return getType() == ELF::STT_COMMON || st_shndx == ELF::SHN_COMMON;
}
bool isDefined() const { return !isUndefined(); }
bool isProcessorSpecific() const {
return st_shndx >= ELF::SHN_LOPROC && st_shndx <= ELF::SHN_HIPROC;
}
bool isOSSpecific() const {
return st_shndx >= ELF::SHN_LOOS && st_shndx <= ELF::SHN_HIOS;
}
bool isReserved() const {
return st_shndx >= ELF::SHN_LORESERVE;
}
bool isUndefined() const { return st_shndx == ELF::SHN_UNDEF; }
bool isExternal() const {
return getBinding() != ELF::STB_LOCAL;
}
ErrorOr<StringRef> getName(StringRef StrTab) const;
};
template <class ELFT>
ErrorOr<StringRef> Elf_Sym_Impl<ELFT>::getName(StringRef StrTab) const {
uint32_t Offset = this->st_name;
if (Offset >= StrTab.size())
return object_error::parse_failed;
return StringRef(StrTab.data() + Offset);
}
template <class ELFT>
struct Elf_Versym_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
Elf_Half vs_index; };
template <class ELFT> struct Elf_Verdaux_Impl;
template <class ELFT>
struct Elf_Verdef_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
typedef Elf_Verdaux_Impl<ELFT> Elf_Verdaux;
Elf_Half vd_version; Elf_Half vd_flags; Elf_Half vd_ndx; Elf_Half vd_cnt; Elf_Word vd_hash; Elf_Word vd_aux; Elf_Word vd_next;
const Elf_Verdaux *getAux() const {
return reinterpret_cast<const Elf_Verdaux *>((const char *)this + vd_aux);
}
};
template <class ELFT>
struct Elf_Verdaux_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
Elf_Word vda_name; Elf_Word vda_next; };
template <class ELFT>
struct Elf_Verneed_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
Elf_Half vn_version; Elf_Half vn_cnt; Elf_Word vn_file; Elf_Word vn_aux; Elf_Word vn_next; };
template <class ELFT>
struct Elf_Vernaux_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
Elf_Word vna_hash; Elf_Half vna_flags; Elf_Half vna_other; Elf_Word vna_name; Elf_Word vna_next; };
template <class ELFT> struct Elf_Dyn_Base;
template <endianness TargetEndianness>
struct Elf_Dyn_Base<ELFType<TargetEndianness, false>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
Elf_Sword d_tag;
union {
Elf_Word d_val;
Elf_Addr d_ptr;
} d_un;
};
template <endianness TargetEndianness>
struct Elf_Dyn_Base<ELFType<TargetEndianness, true>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
Elf_Sxword d_tag;
union {
Elf_Xword d_val;
Elf_Addr d_ptr;
} d_un;
};
template <class ELFT>
struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> {
using Elf_Dyn_Base<ELFT>::d_tag;
using Elf_Dyn_Base<ELFT>::d_un;
typedef typename std::conditional<ELFT::Is64Bits,
int64_t, int32_t>::type intX_t;
typedef typename std::conditional<ELFT::Is64Bits,
uint64_t, uint32_t>::type uintX_t;
intX_t getTag() const { return d_tag; }
uintX_t getVal() const { return d_un.d_val; }
uintX_t getPtr() const { return d_un.d_ptr; }
};
template <class ELFT, bool isRela> struct Elf_Rel_Impl;
template <endianness TargetEndianness>
struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, false> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
Elf_Addr r_offset; Elf_Word r_info;
uint32_t getRInfo(bool isMips64EL) const {
assert(!isMips64EL);
return r_info;
}
void setRInfo(uint32_t R, bool IsMips64EL) {
assert(!IsMips64EL);
r_info = R;
}
uint32_t getSymbol(bool isMips64EL) const {
return this->getRInfo(isMips64EL) >> 8;
}
unsigned char getType(bool isMips64EL) const {
return (unsigned char)(this->getRInfo(isMips64EL) & 0x0ff);
}
void setSymbol(uint32_t s, bool IsMips64EL) {
setSymbolAndType(s, getType(), IsMips64EL);
}
void setType(unsigned char t, bool IsMips64EL) {
setSymbolAndType(getSymbol(), t, IsMips64EL);
}
void setSymbolAndType(uint32_t s, unsigned char t, bool IsMips64EL) {
this->setRInfo((s << 8) + t, IsMips64EL);
}
};
template <endianness TargetEndianness>
struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, true>
: public Elf_Rel_Impl<ELFType<TargetEndianness, false>, false> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
Elf_Sword r_addend; };
template <endianness TargetEndianness>
struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, false> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
Elf_Addr r_offset; Elf_Xword r_info;
uint64_t getRInfo(bool isMips64EL) const {
uint64_t t = r_info;
if (!isMips64EL)
return t;
return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) |
((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff);
}
void setRInfo(uint64_t R, bool IsMips64EL) {
if (IsMips64EL)
r_info = (R >> 32) | ((R & 0xff000000) << 8) | ((R & 0x00ff0000) << 24) |
((R & 0x0000ff00) << 40) | ((R & 0x000000ff) << 56);
else
r_info = R;
}
uint32_t getSymbol(bool isMips64EL) const {
return (uint32_t)(this->getRInfo(isMips64EL) >> 32);
}
uint32_t getType(bool isMips64EL) const {
return (uint32_t)(this->getRInfo(isMips64EL) & 0xffffffffL);
}
void setSymbol(uint32_t s, bool IsMips64EL) {
setSymbolAndType(s, getType(), IsMips64EL);
}
void setType(uint32_t t, bool IsMips64EL) {
setSymbolAndType(getSymbol(), t, IsMips64EL);
}
void setSymbolAndType(uint32_t s, uint32_t t, bool IsMips64EL) {
this->setRInfo(((uint64_t)s << 32) + (t & 0xffffffffL), IsMips64EL);
}
};
template <endianness TargetEndianness>
struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, true>
: public Elf_Rel_Impl<ELFType<TargetEndianness, true>, false> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
Elf_Sxword r_addend; };
template <class ELFT>
struct Elf_Ehdr_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
unsigned char e_ident[ELF::EI_NIDENT]; Elf_Half e_type; Elf_Half e_machine; Elf_Word e_version; Elf_Addr e_entry; Elf_Off e_phoff; Elf_Off e_shoff; Elf_Word e_flags; Elf_Half e_ehsize; Elf_Half e_phentsize; Elf_Half e_phnum; Elf_Half e_shentsize; Elf_Half e_shnum; Elf_Half e_shstrndx; bool checkMagic() const {
return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0;
}
unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; }
unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; }
};
template <class ELFT> struct Elf_Phdr_Impl;
template <endianness TargetEndianness>
struct Elf_Phdr_Impl<ELFType<TargetEndianness, false>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
Elf_Word p_type; Elf_Off p_offset; Elf_Addr p_vaddr; Elf_Addr p_paddr; Elf_Word p_filesz; Elf_Word p_memsz; Elf_Word p_flags; Elf_Word p_align; };
template <endianness TargetEndianness>
struct Elf_Phdr_Impl<ELFType<TargetEndianness, true>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
Elf_Word p_type; Elf_Word p_flags; Elf_Off p_offset; Elf_Addr p_vaddr; Elf_Addr p_paddr; Elf_Xword p_filesz; Elf_Xword p_memsz; Elf_Xword p_align; };
template <class ELFT>
struct Elf_Hash_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
Elf_Word nbucket;
Elf_Word nchain;
ArrayRef<Elf_Word> buckets() const {
return ArrayRef<Elf_Word>(&nbucket + 2, &nbucket + 2 + nbucket);
}
ArrayRef<Elf_Word> chains() const {
return ArrayRef<Elf_Word>(&nbucket + 2 + nbucket,
&nbucket + 2 + nbucket + nchain);
}
};
template <class ELFT>
struct Elf_GnuHash_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
Elf_Word nbuckets;
Elf_Word symndx;
Elf_Word maskwords;
Elf_Word shift2;
ArrayRef<Elf_Off> filter() const {
return ArrayRef<Elf_Off>(reinterpret_cast<const Elf_Off *>(&shift2 + 1),
maskwords);
}
ArrayRef<Elf_Word> buckets() const {
return ArrayRef<Elf_Word>(
reinterpret_cast<const Elf_Word *>(filter().end()), nbuckets);
}
ArrayRef<Elf_Word> values(unsigned DynamicSymCount) const {
return ArrayRef<Elf_Word>(buckets().end(), DynamicSymCount - symndx);
}
};
template <class ELFT>
struct Elf_Mips_RegInfo;
template <llvm::support::endianness TargetEndianness>
struct Elf_Mips_RegInfo<ELFType<TargetEndianness, false>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
Elf_Word ri_gprmask; Elf_Word ri_cprmask[4]; Elf_Addr ri_gp_value; };
template <llvm::support::endianness TargetEndianness>
struct Elf_Mips_RegInfo<ELFType<TargetEndianness, true>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
Elf_Word ri_gprmask; Elf_Word ri_pad; Elf_Word ri_cprmask[4]; Elf_Addr ri_gp_value; };
template <class ELFT> struct Elf_Mips_Options {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
uint8_t kind; uint8_t size; Elf_Half section; Elf_Word info;
const Elf_Mips_RegInfo<ELFT> &getRegInfo() const {
assert(kind == llvm::ELF::ODK_REGINFO);
return *reinterpret_cast<const Elf_Mips_RegInfo<ELFT> *>(
(const uint8_t *)this + sizeof(Elf_Mips_Options));
}
};
template <class ELFT> struct Elf_Mips_ABIFlags {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
Elf_Half version; uint8_t isa_level; uint8_t isa_rev; uint8_t gpr_size; uint8_t cpr1_size; uint8_t cpr2_size; uint8_t fp_abi; Elf_Word isa_ext; Elf_Word ases; Elf_Word flags1; Elf_Word flags2; };
} }
#endif