File indexing completed on 2026-05-10 08:44:18
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_OBJECT_ELFTYPES_H
0010 #define LLVM_OBJECT_ELFTYPES_H
0011
0012 #include "llvm/ADT/ArrayRef.h"
0013 #include "llvm/ADT/StringRef.h"
0014 #include "llvm/BinaryFormat/ELF.h"
0015 #include "llvm/Object/Error.h"
0016 #include "llvm/Support/BlockFrequency.h"
0017 #include "llvm/Support/BranchProbability.h"
0018 #include "llvm/Support/Endian.h"
0019 #include "llvm/Support/Error.h"
0020 #include "llvm/Support/MathExtras.h"
0021 #include <cassert>
0022 #include <cstdint>
0023 #include <cstring>
0024 #include <type_traits>
0025
0026 namespace llvm {
0027 namespace object {
0028
0029 template <class ELFT> struct Elf_Ehdr_Impl;
0030 template <class ELFT> struct Elf_Shdr_Impl;
0031 template <class ELFT> struct Elf_Sym_Impl;
0032 template <class ELFT> struct Elf_Dyn_Impl;
0033 template <class ELFT> struct Elf_Phdr_Impl;
0034 template <class ELFT, bool isRela> struct Elf_Rel_Impl;
0035 template <bool Is64> struct Elf_Crel_Impl;
0036 template <class ELFT> struct Elf_Verdef_Impl;
0037 template <class ELFT> struct Elf_Verdaux_Impl;
0038 template <class ELFT> struct Elf_Verneed_Impl;
0039 template <class ELFT> struct Elf_Vernaux_Impl;
0040 template <class ELFT> struct Elf_Versym_Impl;
0041 template <class ELFT> struct Elf_Hash_Impl;
0042 template <class ELFT> struct Elf_GnuHash_Impl;
0043 template <class ELFT> struct Elf_Chdr_Impl;
0044 template <class ELFT> struct Elf_Nhdr_Impl;
0045 template <class ELFT> class Elf_Note_Impl;
0046 template <class ELFT> class Elf_Note_Iterator_Impl;
0047 template <class ELFT> struct Elf_CGProfile_Impl;
0048
0049 template <endianness E, bool Is64> struct ELFType {
0050 private:
0051 template <typename Ty>
0052 using packed = support::detail::packed_endian_specific_integral<Ty, E, 1>;
0053
0054 public:
0055 static const endianness Endianness = E;
0056 static const bool Is64Bits = Is64;
0057
0058 using uint = std::conditional_t<Is64, uint64_t, uint32_t>;
0059 using Ehdr = Elf_Ehdr_Impl<ELFType<E, Is64>>;
0060 using Shdr = Elf_Shdr_Impl<ELFType<E, Is64>>;
0061 using Sym = Elf_Sym_Impl<ELFType<E, Is64>>;
0062 using Dyn = Elf_Dyn_Impl<ELFType<E, Is64>>;
0063 using Phdr = Elf_Phdr_Impl<ELFType<E, Is64>>;
0064 using Rel = Elf_Rel_Impl<ELFType<E, Is64>, false>;
0065 using Rela = Elf_Rel_Impl<ELFType<E, Is64>, true>;
0066 using Crel = Elf_Crel_Impl<Is64>;
0067 using Relr = packed<uint>;
0068 using Verdef = Elf_Verdef_Impl<ELFType<E, Is64>>;
0069 using Verdaux = Elf_Verdaux_Impl<ELFType<E, Is64>>;
0070 using Verneed = Elf_Verneed_Impl<ELFType<E, Is64>>;
0071 using Vernaux = Elf_Vernaux_Impl<ELFType<E, Is64>>;
0072 using Versym = Elf_Versym_Impl<ELFType<E, Is64>>;
0073 using Hash = Elf_Hash_Impl<ELFType<E, Is64>>;
0074 using GnuHash = Elf_GnuHash_Impl<ELFType<E, Is64>>;
0075 using Chdr = Elf_Chdr_Impl<ELFType<E, Is64>>;
0076 using Nhdr = Elf_Nhdr_Impl<ELFType<E, Is64>>;
0077 using Note = Elf_Note_Impl<ELFType<E, Is64>>;
0078 using NoteIterator = Elf_Note_Iterator_Impl<ELFType<E, Is64>>;
0079 using CGProfile = Elf_CGProfile_Impl<ELFType<E, Is64>>;
0080 using DynRange = ArrayRef<Dyn>;
0081 using ShdrRange = ArrayRef<Shdr>;
0082 using SymRange = ArrayRef<Sym>;
0083 using RelRange = ArrayRef<Rel>;
0084 using RelaRange = ArrayRef<Rela>;
0085 using RelrRange = ArrayRef<Relr>;
0086 using PhdrRange = ArrayRef<Phdr>;
0087
0088 using Half = packed<uint16_t>;
0089 using Word = packed<uint32_t>;
0090 using Sword = packed<int32_t>;
0091 using Xword = packed<uint64_t>;
0092 using Sxword = packed<int64_t>;
0093 using Addr = packed<uint>;
0094 using Off = packed<uint>;
0095 };
0096
0097 using ELF32LE = ELFType<llvm::endianness::little, false>;
0098 using ELF32BE = ELFType<llvm::endianness::big, false>;
0099 using ELF64LE = ELFType<llvm::endianness::little, true>;
0100 using ELF64BE = ELFType<llvm::endianness::big, true>;
0101
0102
0103
0104
0105
0106 #define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \
0107 using Elf_Addr = typename ELFT::Addr; \
0108 using Elf_Off = typename ELFT::Off; \
0109 using Elf_Half = typename ELFT::Half; \
0110 using Elf_Word = typename ELFT::Word; \
0111 using Elf_Sword = typename ELFT::Sword; \
0112 using Elf_Xword = typename ELFT::Xword; \
0113 using Elf_Sxword = typename ELFT::Sxword; \
0114 using uintX_t = typename ELFT::uint; \
0115 using Elf_Ehdr = typename ELFT::Ehdr; \
0116 using Elf_Shdr = typename ELFT::Shdr; \
0117 using Elf_Sym = typename ELFT::Sym; \
0118 using Elf_Dyn = typename ELFT::Dyn; \
0119 using Elf_Phdr = typename ELFT::Phdr; \
0120 using Elf_Rel = typename ELFT::Rel; \
0121 using Elf_Rela = typename ELFT::Rela; \
0122 using Elf_Crel = typename ELFT::Crel; \
0123 using Elf_Relr = typename ELFT::Relr; \
0124 using Elf_Verdef = typename ELFT::Verdef; \
0125 using Elf_Verdaux = typename ELFT::Verdaux; \
0126 using Elf_Verneed = typename ELFT::Verneed; \
0127 using Elf_Vernaux = typename ELFT::Vernaux; \
0128 using Elf_Versym = typename ELFT::Versym; \
0129 using Elf_Hash = typename ELFT::Hash; \
0130 using Elf_GnuHash = typename ELFT::GnuHash; \
0131 using Elf_Chdr = typename ELFT::Chdr; \
0132 using Elf_Nhdr = typename ELFT::Nhdr; \
0133 using Elf_Note = typename ELFT::Note; \
0134 using Elf_Note_Iterator = typename ELFT::NoteIterator; \
0135 using Elf_CGProfile = typename ELFT::CGProfile; \
0136 using Elf_Dyn_Range = typename ELFT::DynRange; \
0137 using Elf_Shdr_Range = typename ELFT::ShdrRange; \
0138 using Elf_Sym_Range = typename ELFT::SymRange; \
0139 using Elf_Rel_Range = typename ELFT::RelRange; \
0140 using Elf_Rela_Range = typename ELFT::RelaRange; \
0141 using Elf_Relr_Range = typename ELFT::RelrRange; \
0142 using Elf_Phdr_Range = typename ELFT::PhdrRange;
0143
0144 #define LLVM_ELF_COMMA ,
0145 #define LLVM_ELF_IMPORT_TYPES(E, W) \
0146 LLVM_ELF_IMPORT_TYPES_ELFT(ELFType<E LLVM_ELF_COMMA W>)
0147
0148
0149 template <class ELFT> struct Elf_Shdr_Base;
0150
0151 template <endianness Endianness>
0152 struct Elf_Shdr_Base<ELFType<Endianness, false>> {
0153 LLVM_ELF_IMPORT_TYPES(Endianness, false)
0154 Elf_Word sh_name;
0155 Elf_Word sh_type;
0156 Elf_Word sh_flags;
0157 Elf_Addr sh_addr;
0158 Elf_Off sh_offset;
0159 Elf_Word sh_size;
0160 Elf_Word sh_link;
0161 Elf_Word sh_info;
0162 Elf_Word sh_addralign;
0163 Elf_Word sh_entsize;
0164 };
0165
0166 template <endianness Endianness>
0167 struct Elf_Shdr_Base<ELFType<Endianness, true>> {
0168 LLVM_ELF_IMPORT_TYPES(Endianness, true)
0169 Elf_Word sh_name;
0170 Elf_Word sh_type;
0171 Elf_Xword sh_flags;
0172 Elf_Addr sh_addr;
0173 Elf_Off sh_offset;
0174 Elf_Xword sh_size;
0175 Elf_Word sh_link;
0176 Elf_Word sh_info;
0177 Elf_Xword sh_addralign;
0178 Elf_Xword sh_entsize;
0179 };
0180
0181 template <class ELFT>
0182 struct Elf_Shdr_Impl : Elf_Shdr_Base<ELFT> {
0183 using Elf_Shdr_Base<ELFT>::sh_entsize;
0184 using Elf_Shdr_Base<ELFT>::sh_size;
0185
0186
0187 unsigned getEntityCount() const {
0188 if (sh_entsize == 0)
0189 return 0;
0190 return sh_size / sh_entsize;
0191 }
0192 };
0193
0194 template <class ELFT> struct Elf_Sym_Base;
0195
0196 template <endianness Endianness>
0197 struct Elf_Sym_Base<ELFType<Endianness, false>> {
0198 LLVM_ELF_IMPORT_TYPES(Endianness, false)
0199 Elf_Word st_name;
0200 Elf_Addr st_value;
0201 Elf_Word st_size;
0202 unsigned char st_info;
0203 unsigned char st_other;
0204 Elf_Half st_shndx;
0205 };
0206
0207 template <endianness Endianness>
0208 struct Elf_Sym_Base<ELFType<Endianness, true>> {
0209 LLVM_ELF_IMPORT_TYPES(Endianness, true)
0210 Elf_Word st_name;
0211 unsigned char st_info;
0212 unsigned char st_other;
0213 Elf_Half st_shndx;
0214 Elf_Addr st_value;
0215 Elf_Xword st_size;
0216 };
0217
0218 template <class ELFT>
0219 struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> {
0220 using Elf_Sym_Base<ELFT>::st_info;
0221 using Elf_Sym_Base<ELFT>::st_shndx;
0222 using Elf_Sym_Base<ELFT>::st_other;
0223 using Elf_Sym_Base<ELFT>::st_value;
0224
0225
0226
0227 unsigned char getBinding() const { return st_info >> 4; }
0228 unsigned char getType() const { return st_info & 0x0f; }
0229 uint64_t getValue() const { return st_value; }
0230 void setBinding(unsigned char b) { setBindingAndType(b, getType()); }
0231 void setType(unsigned char t) { setBindingAndType(getBinding(), t); }
0232
0233 void setBindingAndType(unsigned char b, unsigned char t) {
0234 st_info = (b << 4) + (t & 0x0f);
0235 }
0236
0237
0238
0239
0240
0241
0242 unsigned char getVisibility() const { return st_other & 0x3; }
0243 void setVisibility(unsigned char v) {
0244 assert(v < 4 && "Invalid value for visibility");
0245 st_other = (st_other & ~0x3) | v;
0246 }
0247
0248 bool isAbsolute() const { return st_shndx == ELF::SHN_ABS; }
0249
0250 bool isCommon() const {
0251 return getType() == ELF::STT_COMMON || st_shndx == ELF::SHN_COMMON;
0252 }
0253
0254 bool isDefined() const { return !isUndefined(); }
0255
0256 bool isProcessorSpecific() const {
0257 return st_shndx >= ELF::SHN_LOPROC && st_shndx <= ELF::SHN_HIPROC;
0258 }
0259
0260 bool isOSSpecific() const {
0261 return st_shndx >= ELF::SHN_LOOS && st_shndx <= ELF::SHN_HIOS;
0262 }
0263
0264 bool isReserved() const {
0265
0266
0267 return st_shndx >= ELF::SHN_LORESERVE;
0268 }
0269
0270 bool isUndefined() const { return st_shndx == ELF::SHN_UNDEF; }
0271
0272 bool isExternal() const {
0273 return getBinding() != ELF::STB_LOCAL;
0274 }
0275
0276 Expected<StringRef> getName(StringRef StrTab) const;
0277 };
0278
0279 template <class ELFT>
0280 Expected<StringRef> Elf_Sym_Impl<ELFT>::getName(StringRef StrTab) const {
0281 uint32_t Offset = this->st_name;
0282 if (Offset >= StrTab.size())
0283 return createStringError(object_error::parse_failed,
0284 "st_name (0x%" PRIx32
0285 ") is past the end of the string table"
0286 " of size 0x%zx",
0287 Offset, StrTab.size());
0288 return StringRef(StrTab.data() + Offset);
0289 }
0290
0291
0292
0293 template <class ELFT>
0294 struct Elf_Versym_Impl {
0295 LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
0296 Elf_Half vs_index;
0297 };
0298
0299
0300
0301 template <class ELFT>
0302 struct Elf_Verdef_Impl {
0303 LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
0304 Elf_Half vd_version;
0305 Elf_Half vd_flags;
0306 Elf_Half vd_ndx;
0307 Elf_Half vd_cnt;
0308 Elf_Word vd_hash;
0309 Elf_Word vd_aux;
0310 Elf_Word vd_next;
0311
0312
0313 const Elf_Verdaux *getAux() const {
0314 return reinterpret_cast<const Elf_Verdaux *>((const char *)this + vd_aux);
0315 }
0316 };
0317
0318
0319
0320 template <class ELFT>
0321 struct Elf_Verdaux_Impl {
0322 LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
0323 Elf_Word vda_name;
0324 Elf_Word vda_next;
0325 };
0326
0327
0328
0329 template <class ELFT>
0330 struct Elf_Verneed_Impl {
0331 LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
0332 Elf_Half vn_version;
0333 Elf_Half vn_cnt;
0334 Elf_Word vn_file;
0335 Elf_Word vn_aux;
0336 Elf_Word vn_next;
0337 };
0338
0339
0340
0341 template <class ELFT>
0342 struct Elf_Vernaux_Impl {
0343 LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
0344 Elf_Word vna_hash;
0345 Elf_Half vna_flags;
0346 Elf_Half vna_other;
0347 Elf_Word vna_name;
0348 Elf_Word vna_next;
0349 };
0350
0351
0352
0353 template <class ELFT> struct Elf_Dyn_Base;
0354
0355 template <endianness Endianness>
0356 struct Elf_Dyn_Base<ELFType<Endianness, false>> {
0357 LLVM_ELF_IMPORT_TYPES(Endianness, false)
0358 Elf_Sword d_tag;
0359 union {
0360 Elf_Word d_val;
0361 Elf_Addr d_ptr;
0362 } d_un;
0363 };
0364
0365 template <endianness Endianness>
0366 struct Elf_Dyn_Base<ELFType<Endianness, true>> {
0367 LLVM_ELF_IMPORT_TYPES(Endianness, true)
0368 Elf_Sxword d_tag;
0369 union {
0370 Elf_Xword d_val;
0371 Elf_Addr d_ptr;
0372 } d_un;
0373 };
0374
0375
0376 template <class ELFT>
0377 struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> {
0378 using Elf_Dyn_Base<ELFT>::d_tag;
0379 using Elf_Dyn_Base<ELFT>::d_un;
0380 using intX_t = std::conditional_t<ELFT::Is64Bits, int64_t, int32_t>;
0381 using uintX_t = std::conditional_t<ELFT::Is64Bits, uint64_t, uint32_t>;
0382 intX_t getTag() const { return d_tag; }
0383 uintX_t getVal() const { return d_un.d_val; }
0384 uintX_t getPtr() const { return d_un.d_ptr; }
0385 };
0386
0387 template <endianness Endianness>
0388 struct Elf_Rel_Impl<ELFType<Endianness, false>, false> {
0389 LLVM_ELF_IMPORT_TYPES(Endianness, false)
0390 static const bool HasAddend = false;
0391 static const bool IsCrel = false;
0392 Elf_Addr r_offset;
0393 Elf_Word r_info;
0394
0395 uint32_t getRInfo(bool isMips64EL) const {
0396 assert(!isMips64EL);
0397 return r_info;
0398 }
0399 void setRInfo(uint32_t R, bool IsMips64EL) {
0400 assert(!IsMips64EL);
0401 r_info = R;
0402 }
0403
0404
0405
0406 uint32_t getSymbol(bool isMips64EL) const {
0407 return this->getRInfo(isMips64EL) >> 8;
0408 }
0409 unsigned char getType(bool isMips64EL) const {
0410 return (unsigned char)(this->getRInfo(isMips64EL) & 0x0ff);
0411 }
0412 void setSymbol(uint32_t s, bool IsMips64EL) {
0413 setSymbolAndType(s, getType(IsMips64EL), IsMips64EL);
0414 }
0415 void setType(unsigned char t, bool IsMips64EL) {
0416 setSymbolAndType(getSymbol(IsMips64EL), t, IsMips64EL);
0417 }
0418 void setSymbolAndType(uint32_t s, unsigned char t, bool IsMips64EL) {
0419 this->setRInfo((s << 8) + t, IsMips64EL);
0420 }
0421 };
0422
0423 template <endianness Endianness>
0424 struct Elf_Rel_Impl<ELFType<Endianness, false>, true>
0425 : public Elf_Rel_Impl<ELFType<Endianness, false>, false> {
0426 LLVM_ELF_IMPORT_TYPES(Endianness, false)
0427 static const bool HasAddend = true;
0428 static const bool IsCrel = false;
0429 Elf_Sword r_addend;
0430 };
0431
0432 template <endianness Endianness>
0433 struct Elf_Rel_Impl<ELFType<Endianness, true>, false> {
0434 LLVM_ELF_IMPORT_TYPES(Endianness, true)
0435 static const bool HasAddend = false;
0436 static const bool IsCrel = false;
0437 Elf_Addr r_offset;
0438 Elf_Xword r_info;
0439
0440 uint64_t getRInfo(bool isMips64EL) const {
0441 uint64_t t = r_info;
0442 if (!isMips64EL)
0443 return t;
0444
0445
0446
0447 return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) |
0448 ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff);
0449 }
0450
0451 void setRInfo(uint64_t R, bool IsMips64EL) {
0452 if (IsMips64EL)
0453 r_info = (R >> 32) | ((R & 0xff000000) << 8) | ((R & 0x00ff0000) << 24) |
0454 ((R & 0x0000ff00) << 40) | ((R & 0x000000ff) << 56);
0455 else
0456 r_info = R;
0457 }
0458
0459
0460
0461 uint32_t getSymbol(bool isMips64EL) const {
0462 return (uint32_t)(this->getRInfo(isMips64EL) >> 32);
0463 }
0464 uint32_t getType(bool isMips64EL) const {
0465 return (uint32_t)(this->getRInfo(isMips64EL) & 0xffffffffL);
0466 }
0467 void setSymbol(uint32_t s, bool IsMips64EL) {
0468 setSymbolAndType(s, getType(IsMips64EL), IsMips64EL);
0469 }
0470 void setType(uint32_t t, bool IsMips64EL) {
0471 setSymbolAndType(getSymbol(IsMips64EL), t, IsMips64EL);
0472 }
0473 void setSymbolAndType(uint32_t s, uint32_t t, bool IsMips64EL) {
0474 this->setRInfo(((uint64_t)s << 32) + (t & 0xffffffffL), IsMips64EL);
0475 }
0476 };
0477
0478 template <endianness Endianness>
0479 struct Elf_Rel_Impl<ELFType<Endianness, true>, true>
0480 : public Elf_Rel_Impl<ELFType<Endianness, true>, false> {
0481 LLVM_ELF_IMPORT_TYPES(Endianness, true)
0482 static const bool HasAddend = true;
0483 static const bool IsCrel = false;
0484 Elf_Sxword r_addend;
0485 };
0486
0487
0488 template <bool Is64> struct Elf_Crel_Impl {
0489 using uint = std::conditional_t<Is64, uint64_t, uint32_t>;
0490 static const bool HasAddend = true;
0491 static const bool IsCrel = true;
0492 uint r_offset;
0493 uint32_t r_symidx;
0494 uint32_t r_type;
0495 std::conditional_t<Is64, int64_t, int32_t> r_addend;
0496
0497
0498 uint32_t getType(bool) const { return r_type; }
0499 uint32_t getSymbol(bool) const { return r_symidx; }
0500 void setSymbolAndType(uint32_t s, unsigned char t, bool) {
0501 r_symidx = s;
0502 r_type = t;
0503 }
0504 };
0505
0506 template <class ELFT>
0507 struct Elf_Ehdr_Impl {
0508 LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
0509 unsigned char e_ident[ELF::EI_NIDENT];
0510 Elf_Half e_type;
0511 Elf_Half e_machine;
0512 Elf_Word e_version;
0513 Elf_Addr e_entry;
0514 Elf_Off e_phoff;
0515 Elf_Off e_shoff;
0516 Elf_Word e_flags;
0517 Elf_Half e_ehsize;
0518 Elf_Half e_phentsize;
0519 Elf_Half e_phnum;
0520 Elf_Half e_shentsize;
0521 Elf_Half e_shnum;
0522 Elf_Half e_shstrndx;
0523
0524
0525 bool checkMagic() const {
0526 return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0;
0527 }
0528
0529 unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; }
0530 unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; }
0531 };
0532
0533 template <endianness Endianness>
0534 struct Elf_Phdr_Impl<ELFType<Endianness, false>> {
0535 LLVM_ELF_IMPORT_TYPES(Endianness, false)
0536 Elf_Word p_type;
0537 Elf_Off p_offset;
0538 Elf_Addr p_vaddr;
0539 Elf_Addr p_paddr;
0540 Elf_Word p_filesz;
0541 Elf_Word p_memsz;
0542 Elf_Word p_flags;
0543 Elf_Word p_align;
0544 };
0545
0546 template <endianness Endianness>
0547 struct Elf_Phdr_Impl<ELFType<Endianness, true>> {
0548 LLVM_ELF_IMPORT_TYPES(Endianness, true)
0549 Elf_Word p_type;
0550 Elf_Word p_flags;
0551 Elf_Off p_offset;
0552 Elf_Addr p_vaddr;
0553 Elf_Addr p_paddr;
0554 Elf_Xword p_filesz;
0555 Elf_Xword p_memsz;
0556 Elf_Xword p_align;
0557 };
0558
0559
0560 template <class ELFT>
0561 struct Elf_Hash_Impl {
0562 LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
0563 Elf_Word nbucket;
0564 Elf_Word nchain;
0565
0566 ArrayRef<Elf_Word> buckets() const {
0567 return ArrayRef<Elf_Word>(&nbucket + 2, &nbucket + 2 + nbucket);
0568 }
0569
0570 ArrayRef<Elf_Word> chains() const {
0571 return ArrayRef<Elf_Word>(&nbucket + 2 + nbucket,
0572 &nbucket + 2 + nbucket + nchain);
0573 }
0574 };
0575
0576
0577 template <class ELFT>
0578 struct Elf_GnuHash_Impl {
0579 LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
0580 Elf_Word nbuckets;
0581 Elf_Word symndx;
0582 Elf_Word maskwords;
0583 Elf_Word shift2;
0584
0585 ArrayRef<Elf_Off> filter() const {
0586 return ArrayRef<Elf_Off>(reinterpret_cast<const Elf_Off *>(&shift2 + 1),
0587 maskwords);
0588 }
0589
0590 ArrayRef<Elf_Word> buckets() const {
0591 return ArrayRef<Elf_Word>(
0592 reinterpret_cast<const Elf_Word *>(filter().end()), nbuckets);
0593 }
0594
0595 ArrayRef<Elf_Word> values(unsigned DynamicSymCount) const {
0596 assert(DynamicSymCount >= symndx);
0597 return ArrayRef<Elf_Word>(buckets().end(), DynamicSymCount - symndx);
0598 }
0599 };
0600
0601
0602
0603 template <endianness Endianness>
0604 struct Elf_Chdr_Impl<ELFType<Endianness, false>> {
0605 LLVM_ELF_IMPORT_TYPES(Endianness, false)
0606 Elf_Word ch_type;
0607 Elf_Word ch_size;
0608 Elf_Word ch_addralign;
0609 };
0610
0611 template <endianness Endianness>
0612 struct Elf_Chdr_Impl<ELFType<Endianness, true>> {
0613 LLVM_ELF_IMPORT_TYPES(Endianness, true)
0614 Elf_Word ch_type;
0615 Elf_Word ch_reserved;
0616 Elf_Xword ch_size;
0617 Elf_Xword ch_addralign;
0618 };
0619
0620
0621 template <class ELFT>
0622 struct Elf_Nhdr_Impl {
0623 LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
0624 Elf_Word n_namesz;
0625 Elf_Word n_descsz;
0626 Elf_Word n_type;
0627
0628
0629
0630
0631
0632 size_t getSize(size_t Align) const {
0633 return alignToPowerOf2(sizeof(*this) + n_namesz, Align) +
0634 alignToPowerOf2(n_descsz, Align);
0635 }
0636 };
0637
0638
0639
0640
0641
0642 template <class ELFT>
0643 class Elf_Note_Impl {
0644 LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
0645
0646 const Elf_Nhdr_Impl<ELFT> &Nhdr;
0647
0648 template <class NoteIteratorELFT> friend class Elf_Note_Iterator_Impl;
0649
0650 public:
0651 Elf_Note_Impl(const Elf_Nhdr_Impl<ELFT> &Nhdr) : Nhdr(Nhdr) {}
0652
0653
0654 StringRef getName() const {
0655 if (!Nhdr.n_namesz)
0656 return StringRef();
0657 return StringRef(reinterpret_cast<const char *>(&Nhdr) + sizeof(Nhdr),
0658 Nhdr.n_namesz - 1);
0659 }
0660
0661
0662 ArrayRef<uint8_t> getDesc(size_t Align) const {
0663 if (!Nhdr.n_descsz)
0664 return ArrayRef<uint8_t>();
0665 return ArrayRef<uint8_t>(
0666 reinterpret_cast<const uint8_t *>(&Nhdr) +
0667 alignToPowerOf2(sizeof(Nhdr) + Nhdr.n_namesz, Align),
0668 Nhdr.n_descsz);
0669 }
0670
0671
0672 StringRef getDescAsStringRef(size_t Align) const {
0673 ArrayRef<uint8_t> Desc = getDesc(Align);
0674 return StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size());
0675 }
0676
0677
0678 Elf_Word getType() const { return Nhdr.n_type; }
0679 };
0680
0681 template <class ELFT> class Elf_Note_Iterator_Impl {
0682 public:
0683 using iterator_category = std::forward_iterator_tag;
0684 using value_type = Elf_Note_Impl<ELFT>;
0685 using difference_type = std::ptrdiff_t;
0686 using pointer = value_type *;
0687 using reference = value_type &;
0688
0689 private:
0690
0691 const Elf_Nhdr_Impl<ELFT> *Nhdr = nullptr;
0692 size_t RemainingSize = 0u;
0693 size_t Align = 0;
0694 Error *Err = nullptr;
0695
0696 template <class ELFFileELFT> friend class ELFFile;
0697
0698
0699 void stopWithOverflowError() {
0700 Nhdr = nullptr;
0701 *Err = make_error<StringError>("ELF note overflows container",
0702 object_error::parse_failed);
0703 }
0704
0705
0706
0707
0708
0709
0710 void advanceNhdr(const uint8_t *NhdrPos, size_t NoteSize) {
0711 RemainingSize -= NoteSize;
0712 if (RemainingSize == 0u) {
0713
0714
0715 *Err = Error::success();
0716 Nhdr = nullptr;
0717 } else if (sizeof(*Nhdr) > RemainingSize)
0718 stopWithOverflowError();
0719 else {
0720 Nhdr = reinterpret_cast<const Elf_Nhdr_Impl<ELFT> *>(NhdrPos + NoteSize);
0721 if (Nhdr->getSize(Align) > RemainingSize)
0722 stopWithOverflowError();
0723 else
0724 *Err = Error::success();
0725 }
0726 }
0727
0728 Elf_Note_Iterator_Impl() = default;
0729 explicit Elf_Note_Iterator_Impl(Error &Err) : Err(&Err) {}
0730 Elf_Note_Iterator_Impl(const uint8_t *Start, size_t Size, size_t Align,
0731 Error &Err)
0732 : RemainingSize(Size), Align(Align), Err(&Err) {
0733 consumeError(std::move(Err));
0734 assert(Start && "ELF note iterator starting at NULL");
0735 advanceNhdr(Start, 0u);
0736 }
0737
0738 public:
0739 Elf_Note_Iterator_Impl &operator++() {
0740 assert(Nhdr && "incremented ELF note end iterator");
0741 const uint8_t *NhdrPos = reinterpret_cast<const uint8_t *>(Nhdr);
0742 size_t NoteSize = Nhdr->getSize(Align);
0743 advanceNhdr(NhdrPos, NoteSize);
0744 return *this;
0745 }
0746 bool operator==(Elf_Note_Iterator_Impl Other) const {
0747 if (!Nhdr && Other.Err)
0748 (void)(bool)(*Other.Err);
0749 if (!Other.Nhdr && Err)
0750 (void)(bool)(*Err);
0751 return Nhdr == Other.Nhdr;
0752 }
0753 bool operator!=(Elf_Note_Iterator_Impl Other) const {
0754 return !(*this == Other);
0755 }
0756 Elf_Note_Impl<ELFT> operator*() const {
0757 assert(Nhdr && "dereferenced ELF note end iterator");
0758 return Elf_Note_Impl<ELFT>(*Nhdr);
0759 }
0760 };
0761
0762 template <class ELFT> struct Elf_CGProfile_Impl {
0763 LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
0764 Elf_Xword cgp_weight;
0765 };
0766
0767
0768 template <class ELFT>
0769 struct Elf_Mips_RegInfo;
0770
0771 template <llvm::endianness Endianness>
0772 struct Elf_Mips_RegInfo<ELFType<Endianness, false>> {
0773 LLVM_ELF_IMPORT_TYPES(Endianness, false)
0774 Elf_Word ri_gprmask;
0775 Elf_Word ri_cprmask[4];
0776 Elf_Addr ri_gp_value;
0777 };
0778
0779 template <llvm::endianness Endianness>
0780 struct Elf_Mips_RegInfo<ELFType<Endianness, true>> {
0781 LLVM_ELF_IMPORT_TYPES(Endianness, true)
0782 Elf_Word ri_gprmask;
0783 Elf_Word ri_pad;
0784 Elf_Word ri_cprmask[4];
0785 Elf_Addr ri_gp_value;
0786 };
0787
0788
0789 template <class ELFT> struct Elf_Mips_Options {
0790 LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
0791 uint8_t kind;
0792 uint8_t size;
0793 Elf_Half section;
0794
0795 Elf_Word info;
0796
0797 Elf_Mips_RegInfo<ELFT> &getRegInfo() {
0798 assert(kind == ELF::ODK_REGINFO);
0799 return *reinterpret_cast<Elf_Mips_RegInfo<ELFT> *>(
0800 (uint8_t *)this + sizeof(Elf_Mips_Options));
0801 }
0802 const Elf_Mips_RegInfo<ELFT> &getRegInfo() const {
0803 return const_cast<Elf_Mips_Options *>(this)->getRegInfo();
0804 }
0805 };
0806
0807
0808 template <class ELFT> struct Elf_Mips_ABIFlags {
0809 LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
0810 Elf_Half version;
0811 uint8_t isa_level;
0812 uint8_t isa_rev;
0813 uint8_t gpr_size;
0814 uint8_t cpr1_size;
0815 uint8_t cpr2_size;
0816 uint8_t fp_abi;
0817 Elf_Word isa_ext;
0818 Elf_Word ases;
0819 Elf_Word flags1;
0820 Elf_Word flags2;
0821 };
0822
0823
0824 struct BBAddrMap {
0825
0826
0827
0828 struct Features {
0829 bool FuncEntryCount : 1;
0830 bool BBFreq : 1;
0831 bool BrProb : 1;
0832 bool MultiBBRange : 1;
0833 bool OmitBBEntries : 1;
0834
0835 bool hasPGOAnalysis() const { return FuncEntryCount || BBFreq || BrProb; }
0836
0837 bool hasPGOAnalysisBBData() const { return BBFreq || BrProb; }
0838
0839
0840 uint8_t encode() const {
0841 return (static_cast<uint8_t>(FuncEntryCount) << 0) |
0842 (static_cast<uint8_t>(BBFreq) << 1) |
0843 (static_cast<uint8_t>(BrProb) << 2) |
0844 (static_cast<uint8_t>(MultiBBRange) << 3) |
0845 (static_cast<uint8_t>(OmitBBEntries) << 4);
0846 }
0847
0848
0849
0850 static Expected<Features> decode(uint8_t Val) {
0851 Features Feat{
0852 static_cast<bool>(Val & (1 << 0)), static_cast<bool>(Val & (1 << 1)),
0853 static_cast<bool>(Val & (1 << 2)), static_cast<bool>(Val & (1 << 3)),
0854 static_cast<bool>(Val & (1 << 4))};
0855 if (Feat.encode() != Val)
0856 return createStringError(
0857 std::error_code(), "invalid encoding for BBAddrMap::Features: 0x%x",
0858 Val);
0859 return Feat;
0860 }
0861
0862 bool operator==(const Features &Other) const {
0863 return std::tie(FuncEntryCount, BBFreq, BrProb, MultiBBRange,
0864 OmitBBEntries) ==
0865 std::tie(Other.FuncEntryCount, Other.BBFreq, Other.BrProb,
0866 Other.MultiBBRange, Other.OmitBBEntries);
0867 }
0868 };
0869
0870
0871 struct BBEntry {
0872 struct Metadata {
0873 bool HasReturn : 1;
0874
0875 bool HasTailCall : 1;
0876 bool IsEHPad : 1;
0877 bool CanFallThrough : 1;
0878 bool HasIndirectBranch : 1;
0879
0880
0881 bool operator==(const Metadata &Other) const {
0882 return HasReturn == Other.HasReturn &&
0883 HasTailCall == Other.HasTailCall && IsEHPad == Other.IsEHPad &&
0884 CanFallThrough == Other.CanFallThrough &&
0885 HasIndirectBranch == Other.HasIndirectBranch;
0886 }
0887
0888
0889 uint32_t encode() const {
0890 return static_cast<uint32_t>(HasReturn) |
0891 (static_cast<uint32_t>(HasTailCall) << 1) |
0892 (static_cast<uint32_t>(IsEHPad) << 2) |
0893 (static_cast<uint32_t>(CanFallThrough) << 3) |
0894 (static_cast<uint32_t>(HasIndirectBranch) << 4);
0895 }
0896
0897
0898 static Expected<Metadata> decode(uint32_t V) {
0899 Metadata MD{static_cast<bool>(V & 1),
0900 static_cast<bool>(V & (1 << 1)),
0901 static_cast<bool>(V & (1 << 2)),
0902 static_cast<bool>(V & (1 << 3)),
0903 static_cast<bool>(V & (1 << 4))};
0904 if (MD.encode() != V)
0905 return createStringError(
0906 std::error_code(), "invalid encoding for BBEntry::Metadata: 0x%x",
0907 V);
0908 return MD;
0909 }
0910 };
0911
0912 uint32_t ID = 0;
0913 uint32_t Offset = 0;
0914 uint32_t Size = 0;
0915 Metadata MD = {false, false, false, false,
0916 false};
0917
0918 BBEntry(uint32_t ID, uint32_t Offset, uint32_t Size, Metadata MD)
0919 : ID(ID), Offset(Offset), Size(Size), MD(MD){};
0920
0921 bool operator==(const BBEntry &Other) const {
0922 return ID == Other.ID && Offset == Other.Offset && Size == Other.Size &&
0923 MD == Other.MD;
0924 }
0925
0926 bool hasReturn() const { return MD.HasReturn; }
0927 bool hasTailCall() const { return MD.HasTailCall; }
0928 bool isEHPad() const { return MD.IsEHPad; }
0929 bool canFallThrough() const { return MD.CanFallThrough; }
0930 bool hasIndirectBranch() const { return MD.HasIndirectBranch; }
0931 };
0932
0933
0934
0935 struct BBRangeEntry {
0936 uint64_t BaseAddress = 0;
0937 std::vector<BBEntry> BBEntries;
0938
0939
0940 bool operator==(const BBRangeEntry &Other) const {
0941 return BaseAddress == Other.BaseAddress &&
0942 std::equal(BBEntries.begin(), BBEntries.end(),
0943 Other.BBEntries.begin());
0944 }
0945 };
0946
0947
0948
0949 std::vector<BBRangeEntry> BBRanges;
0950
0951
0952
0953 uint64_t getFunctionAddress() const {
0954 assert(!BBRanges.empty());
0955 return BBRanges.front().BaseAddress;
0956 }
0957
0958
0959 size_t getNumBBEntries() const {
0960 size_t NumBBEntries = 0;
0961 for (const auto &BBR : BBRanges)
0962 NumBBEntries += BBR.BBEntries.size();
0963 return NumBBEntries;
0964 }
0965
0966
0967
0968 std::optional<size_t>
0969 getBBRangeIndexForBaseAddress(uint64_t BaseAddress) const {
0970 for (size_t I = 0; I < BBRanges.size(); ++I)
0971 if (BBRanges[I].BaseAddress == BaseAddress)
0972 return I;
0973 return {};
0974 }
0975
0976
0977 const std::vector<BBEntry> &getBBEntries() const {
0978 return BBRanges.front().BBEntries;
0979 }
0980
0981 const std::vector<BBRangeEntry> &getBBRanges() const { return BBRanges; }
0982
0983
0984 bool operator==(const BBAddrMap &Other) const {
0985 return std::equal(BBRanges.begin(), BBRanges.end(), Other.BBRanges.begin());
0986 }
0987 };
0988
0989
0990 struct PGOAnalysisMap {
0991
0992
0993 struct PGOBBEntry {
0994
0995
0996 struct SuccessorEntry {
0997
0998 uint32_t ID;
0999
1000 BranchProbability Prob;
1001
1002 bool operator==(const SuccessorEntry &Other) const {
1003 return std::tie(ID, Prob) == std::tie(Other.ID, Other.Prob);
1004 }
1005 };
1006
1007
1008 BlockFrequency BlockFreq;
1009
1010 llvm::SmallVector<SuccessorEntry, 2> Successors;
1011
1012 bool operator==(const PGOBBEntry &Other) const {
1013 return std::tie(BlockFreq, Successors) ==
1014 std::tie(Other.BlockFreq, Other.Successors);
1015 }
1016 };
1017
1018 uint64_t FuncEntryCount;
1019 std::vector<PGOBBEntry> BBEntries;
1020
1021
1022 BBAddrMap::Features FeatEnable;
1023
1024 bool operator==(const PGOAnalysisMap &Other) const {
1025 return std::tie(FuncEntryCount, BBEntries, FeatEnable) ==
1026 std::tie(Other.FuncEntryCount, Other.BBEntries, Other.FeatEnable);
1027 }
1028 };
1029
1030 }
1031 }
1032
1033 #endif