#ifndef LLVM_OBJECT_ELFTYPES_H
#define LLVM_OBJECT_ELFTYPES_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Object/Error.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
#include <cstdint>
#include <cstring>
#include <type_traits>
namespace llvm {
namespace object {
using support::endianness;
template <class ELFT> struct Elf_Ehdr_Impl;
template <class ELFT> struct Elf_Shdr_Impl;
template <class ELFT> struct Elf_Sym_Impl;
template <class ELFT> struct Elf_Dyn_Impl;
template <class ELFT> struct Elf_Phdr_Impl;
template <class ELFT, bool isRela> struct Elf_Rel_Impl;
template <class ELFT> struct Elf_Verdef_Impl;
template <class ELFT> struct Elf_Verdaux_Impl;
template <class ELFT> struct Elf_Verneed_Impl;
template <class ELFT> struct Elf_Vernaux_Impl;
template <class ELFT> struct Elf_Versym_Impl;
template <class ELFT> struct Elf_Hash_Impl;
template <class ELFT> struct Elf_GnuHash_Impl;
template <class ELFT> struct Elf_Chdr_Impl;
template <class ELFT> struct Elf_Nhdr_Impl;
template <class ELFT> class Elf_Note_Impl;
template <class ELFT> class Elf_Note_Iterator_Impl;
template <class ELFT> struct Elf_CGProfile_Impl;
template <endianness E, bool Is64> struct ELFType {
private:
template <typename Ty>
using packed = support::detail::packed_endian_specific_integral<Ty, E, 1>;
public:
static const endianness TargetEndianness = E;
static const bool Is64Bits = Is64;
using uint = std::conditional_t<Is64, uint64_t, uint32_t>;
using Ehdr = Elf_Ehdr_Impl<ELFType<E, Is64>>;
using Shdr = Elf_Shdr_Impl<ELFType<E, Is64>>;
using Sym = Elf_Sym_Impl<ELFType<E, Is64>>;
using Dyn = Elf_Dyn_Impl<ELFType<E, Is64>>;
using Phdr = Elf_Phdr_Impl<ELFType<E, Is64>>;
using Rel = Elf_Rel_Impl<ELFType<E, Is64>, false>;
using Rela = Elf_Rel_Impl<ELFType<E, Is64>, true>;
using Relr = packed<uint>;
using Verdef = Elf_Verdef_Impl<ELFType<E, Is64>>;
using Verdaux = Elf_Verdaux_Impl<ELFType<E, Is64>>;
using Verneed = Elf_Verneed_Impl<ELFType<E, Is64>>;
using Vernaux = Elf_Vernaux_Impl<ELFType<E, Is64>>;
using Versym = Elf_Versym_Impl<ELFType<E, Is64>>;
using Hash = Elf_Hash_Impl<ELFType<E, Is64>>;
using GnuHash = Elf_GnuHash_Impl<ELFType<E, Is64>>;
using Chdr = Elf_Chdr_Impl<ELFType<E, Is64>>;
using Nhdr = Elf_Nhdr_Impl<ELFType<E, Is64>>;
using Note = Elf_Note_Impl<ELFType<E, Is64>>;
using NoteIterator = Elf_Note_Iterator_Impl<ELFType<E, Is64>>;
using CGProfile = Elf_CGProfile_Impl<ELFType<E, Is64>>;
using DynRange = ArrayRef<Dyn>;
using ShdrRange = ArrayRef<Shdr>;
using SymRange = ArrayRef<Sym>;
using RelRange = ArrayRef<Rel>;
using RelaRange = ArrayRef<Rela>;
using RelrRange = ArrayRef<Relr>;
using PhdrRange = ArrayRef<Phdr>;
using Half = packed<uint16_t>;
using Word = packed<uint32_t>;
using Sword = packed<int32_t>;
using Xword = packed<uint64_t>;
using Sxword = packed<int64_t>;
using Addr = packed<uint>;
using Off = packed<uint>;
};
using ELF32LE = ELFType<support::little, false>;
using ELF32BE = ELFType<support::big, false>;
using ELF64LE = ELFType<support::little, true>;
using ELF64BE = ELFType<support::big, true>;
#define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \
using Elf_Addr = typename ELFT::Addr; \
using Elf_Off = typename ELFT::Off; \
using Elf_Half = typename ELFT::Half; \
using Elf_Word = typename ELFT::Word; \
using Elf_Sword = typename ELFT::Sword; \
using Elf_Xword = typename ELFT::Xword; \
using Elf_Sxword = typename ELFT::Sxword; \
using uintX_t = typename ELFT::uint; \
using Elf_Ehdr = typename ELFT::Ehdr; \
using Elf_Shdr = typename ELFT::Shdr; \
using Elf_Sym = typename ELFT::Sym; \
using Elf_Dyn = typename ELFT::Dyn; \
using Elf_Phdr = typename ELFT::Phdr; \
using Elf_Rel = typename ELFT::Rel; \
using Elf_Rela = typename ELFT::Rela; \
using Elf_Relr = typename ELFT::Relr; \
using Elf_Verdef = typename ELFT::Verdef; \
using Elf_Verdaux = typename ELFT::Verdaux; \
using Elf_Verneed = typename ELFT::Verneed; \
using Elf_Vernaux = typename ELFT::Vernaux; \
using Elf_Versym = typename ELFT::Versym; \
using Elf_Hash = typename ELFT::Hash; \
using Elf_GnuHash = typename ELFT::GnuHash; \
using Elf_Nhdr = typename ELFT::Nhdr; \
using Elf_Note = typename ELFT::Note; \
using Elf_Note_Iterator = typename ELFT::NoteIterator; \
using Elf_CGProfile = typename ELFT::CGProfile; \
using Elf_Dyn_Range = typename ELFT::DynRange; \
using Elf_Shdr_Range = typename ELFT::ShdrRange; \
using Elf_Sym_Range = typename ELFT::SymRange; \
using Elf_Rel_Range = typename ELFT::RelRange; \
using Elf_Rela_Range = typename ELFT::RelaRange; \
using Elf_Relr_Range = typename ELFT::RelrRange; \
using Elf_Phdr_Range = typename ELFT::PhdrRange;
#define LLVM_ELF_COMMA ,
#define LLVM_ELF_IMPORT_TYPES(E, W) \
LLVM_ELF_IMPORT_TYPES_ELFT(ELFType<E LLVM_ELF_COMMA W>)
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;
}
Expected<StringRef> getName(StringRef StrTab) const;
};
template <class ELFT>
Expected<StringRef> Elf_Sym_Impl<ELFT>::getName(StringRef StrTab) const {
uint32_t Offset = this->st_name;
if (Offset >= StrTab.size())
return createStringError(object_error::parse_failed,
"st_name (0x%" PRIx32
") is past the end of the string table"
" of size 0x%zx",
Offset, StrTab.size());
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_Verdef_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
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;
using intX_t = std::conditional_t<ELFT::Is64Bits, int64_t, int32_t>;
using uintX_t = std::conditional_t<ELFT::Is64Bits, uint64_t, uint32_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 <endianness TargetEndianness>
struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, false> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
static const bool IsRela = false;
Elf_Addr r_offset; 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), IsMips64EL);
}
void setType(unsigned char t, bool IsMips64EL) {
setSymbolAndType(getSymbol(IsMips64EL), 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)
static const bool IsRela = true;
Elf_Sword r_addend; };
template <endianness TargetEndianness>
struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, false> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
static const bool IsRela = false;
Elf_Addr r_offset; 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), IsMips64EL);
}
void setType(uint32_t t, bool IsMips64EL) {
setSymbolAndType(getSymbol(IsMips64EL), 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)
static const bool IsRela = 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 <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 {
assert(DynamicSymCount >= symndx);
return ArrayRef<Elf_Word>(buckets().end(), DynamicSymCount - symndx);
}
};
template <endianness TargetEndianness>
struct Elf_Chdr_Impl<ELFType<TargetEndianness, false>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
Elf_Word ch_type;
Elf_Word ch_size;
Elf_Word ch_addralign;
};
template <endianness TargetEndianness>
struct Elf_Chdr_Impl<ELFType<TargetEndianness, true>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
Elf_Word ch_type;
Elf_Word ch_reserved;
Elf_Xword ch_size;
Elf_Xword ch_addralign;
};
template <class ELFT>
struct Elf_Nhdr_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
Elf_Word n_namesz;
Elf_Word n_descsz;
Elf_Word n_type;
static const unsigned int Align = 4;
size_t getSize() const {
return sizeof(*this) + alignTo<Align>(n_namesz) + alignTo<Align>(n_descsz);
}
};
template <class ELFT>
class Elf_Note_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
const Elf_Nhdr_Impl<ELFT> &Nhdr;
template <class NoteIteratorELFT> friend class Elf_Note_Iterator_Impl;
public:
Elf_Note_Impl(const Elf_Nhdr_Impl<ELFT> &Nhdr) : Nhdr(Nhdr) {}
StringRef getName() const {
if (!Nhdr.n_namesz)
return StringRef();
return StringRef(reinterpret_cast<const char *>(&Nhdr) + sizeof(Nhdr),
Nhdr.n_namesz - 1);
}
ArrayRef<uint8_t> getDesc() const {
if (!Nhdr.n_descsz)
return ArrayRef<uint8_t>();
return ArrayRef<uint8_t>(
reinterpret_cast<const uint8_t *>(&Nhdr) + sizeof(Nhdr) +
alignTo<Elf_Nhdr_Impl<ELFT>::Align>(Nhdr.n_namesz),
Nhdr.n_descsz);
}
StringRef getDescAsStringRef() const {
ArrayRef<uint8_t> Desc = getDesc();
return StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size());
}
Elf_Word getType() const { return Nhdr.n_type; }
};
template <class ELFT> class Elf_Note_Iterator_Impl {
public:
using iterator_category = std::forward_iterator_tag;
using value_type = Elf_Note_Impl<ELFT>;
using difference_type = std::ptrdiff_t;
using pointer = value_type *;
using reference = value_type &;
private:
const Elf_Nhdr_Impl<ELFT> *Nhdr = nullptr;
size_t RemainingSize = 0u;
Error *Err = nullptr;
template <class ELFFileELFT> friend class ELFFile;
void stopWithOverflowError() {
Nhdr = nullptr;
*Err = make_error<StringError>("ELF note overflows container",
object_error::parse_failed);
}
void advanceNhdr(const uint8_t *NhdrPos, size_t NoteSize) {
RemainingSize -= NoteSize;
if (RemainingSize == 0u) {
*Err = Error::success();
Nhdr = nullptr;
} else if (sizeof(*Nhdr) > RemainingSize)
stopWithOverflowError();
else {
Nhdr = reinterpret_cast<const Elf_Nhdr_Impl<ELFT> *>(NhdrPos + NoteSize);
if (Nhdr->getSize() > RemainingSize)
stopWithOverflowError();
else
*Err = Error::success();
}
}
Elf_Note_Iterator_Impl() = default;
explicit Elf_Note_Iterator_Impl(Error &Err) : Err(&Err) {}
Elf_Note_Iterator_Impl(const uint8_t *Start, size_t Size, Error &Err)
: RemainingSize(Size), Err(&Err) {
consumeError(std::move(Err));
assert(Start && "ELF note iterator starting at NULL");
advanceNhdr(Start, 0u);
}
public:
Elf_Note_Iterator_Impl &operator++() {
assert(Nhdr && "incremented ELF note end iterator");
const uint8_t *NhdrPos = reinterpret_cast<const uint8_t *>(Nhdr);
size_t NoteSize = Nhdr->getSize();
advanceNhdr(NhdrPos, NoteSize);
return *this;
}
bool operator==(Elf_Note_Iterator_Impl Other) const {
if (!Nhdr && Other.Err)
(void)(bool)(*Other.Err);
if (!Other.Nhdr && Err)
(void)(bool)(*Err);
return Nhdr == Other.Nhdr;
}
bool operator!=(Elf_Note_Iterator_Impl Other) const {
return !(*this == Other);
}
Elf_Note_Impl<ELFT> operator*() const {
assert(Nhdr && "dereferenced ELF note end iterator");
return Elf_Note_Impl<ELFT>(*Nhdr);
}
};
template <class ELFT> struct Elf_CGProfile_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
Elf_Xword cgp_weight;
};
template <class ELFT>
struct Elf_Mips_RegInfo;
template <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 <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;
Elf_Mips_RegInfo<ELFT> &getRegInfo() {
assert(kind == ELF::ODK_REGINFO);
return *reinterpret_cast<Elf_Mips_RegInfo<ELFT> *>(
(uint8_t *)this + sizeof(Elf_Mips_Options));
}
const Elf_Mips_RegInfo<ELFT> &getRegInfo() const {
return const_cast<Elf_Mips_Options *>(this)->getRegInfo();
}
};
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; };
struct BBAddrMap {
uint64_t Addr; struct BBEntry {
uint32_t Offset; uint32_t Size;
bool HasReturn; bool HasTailCall; bool IsEHPad; bool CanFallThrough;
BBEntry(uint32_t Offset, uint32_t Size, uint32_t Metadata)
: Offset(Offset), Size(Size), HasReturn(Metadata & 1),
HasTailCall(Metadata & (1 << 1)), IsEHPad(Metadata & (1 << 2)),
CanFallThrough(Metadata & (1 << 3)){};
bool operator==(const BBEntry &Other) const {
return Offset == Other.Offset && Size == Other.Size &&
HasReturn == Other.HasReturn && HasTailCall == Other.HasTailCall &&
IsEHPad == Other.IsEHPad && CanFallThrough == Other.CanFallThrough;
}
};
std::vector<BBEntry> BBEntries;
bool operator==(const BBAddrMap &Other) const {
return Addr == Other.Addr && std::equal(BBEntries.begin(), BBEntries.end(),
Other.BBEntries.begin());
}
};
} }
#endif