14using namespace object;
16#define STRINGIFY_ENUM_CASE(ns, name) \
20#define ELF_RELOC(name, value) STRINGIFY_ENUM_CASE(ELF, name)
27#include "llvm/BinaryFormat/ELFRelocs/M68k.def"
34#include "llvm/BinaryFormat/ELFRelocs/x86_64.def"
42#include "llvm/BinaryFormat/ELFRelocs/i386.def"
49#include "llvm/BinaryFormat/ELFRelocs/Mips.def"
56#include "llvm/BinaryFormat/ELFRelocs/AArch64.def"
63#include "llvm/BinaryFormat/ELFRelocs/ARM.def"
71#include "llvm/BinaryFormat/ELFRelocs/ARC.def"
78#include "llvm/BinaryFormat/ELFRelocs/AVR.def"
85#include "llvm/BinaryFormat/ELFRelocs/Hexagon.def"
92#include "llvm/BinaryFormat/ELFRelocs/Lanai.def"
99#include "llvm/BinaryFormat/ELFRelocs/PowerPC.def"
106#include "llvm/BinaryFormat/ELFRelocs/PowerPC64.def"
113#include "llvm/BinaryFormat/ELFRelocs/RISCV.def"
120#include "llvm/BinaryFormat/ELFRelocs/SystemZ.def"
129#include "llvm/BinaryFormat/ELFRelocs/Sparc.def"
136#include "llvm/BinaryFormat/ELFRelocs/AMDGPU.def"
143#include "llvm/BinaryFormat/ELFRelocs/BPF.def"
150#include "llvm/BinaryFormat/ELFRelocs/MSP430.def"
157#include "llvm/BinaryFormat/ELFRelocs/VE.def"
164#include "llvm/BinaryFormat/ELFRelocs/CSKY.def"
171#include "llvm/BinaryFormat/ELFRelocs/LoongArch.def"
178#include "llvm/BinaryFormat/ELFRelocs/Xtensa.def"
194 return ELF::R_X86_64_RELATIVE;
197 return ELF::R_386_RELATIVE;
201 return ELF::R_AARCH64_RELATIVE;
203 return ELF::R_ARM_RELATIVE;
206 return ELF::R_ARC_RELATIVE;
210 return ELF::R_HEX_RELATIVE;
216 return ELF::R_PPC64_RELATIVE;
218 return ELF::R_RISCV_RELATIVE;
220 return ELF::R_390_RELATIVE;
224 return ELF::R_SPARC_RELATIVE;
226 return ELF::R_CKCORE_RELATIVE;
228 return ELF::R_VE_RELATIVE;
234 return ELF::R_LARCH_RELATIVE;
321std::vector<typename ELFT::Rel>
355 Rel.setType(getRelativeRelocationType(),
false);
356 std::vector<Elf_Rel> Relocs;
359 using Addr =
typename ELFT::uint;
362 for (Elf_Relr R : relrs) {
363 typename ELFT::uint Entry = R;
364 if ((Entry & 1) == 0) {
366 Rel.r_offset = Entry;
367 Relocs.push_back(Rel);
373 if ((Entry & 1) != 0) {
375 Relocs.push_back(Rel);
377 Base += (CHAR_BIT *
sizeof(Entry) - 1) *
sizeof(
Addr);
395 return createError(
"invalid packed relocation header");
406 std::vector<Elf_Rela> Relocs;
407 Relocs.reserve(NumRelocs);
412 if (NumRelocsInGroup > NumRelocs)
413 return createError(
"relocation group unexpectedly large");
414 NumRelocs -= NumRelocsInGroup;
423 if (GroupedByOffsetDelta)
424 GroupOffsetDelta =
Data.getSLEB128(Cur);
428 GroupRInfo =
Data.getSLEB128(Cur);
430 if (GroupedByAddend && GroupHasAddend)
431 Addend +=
Data.getSLEB128(Cur);
436 for (
uint64_t I = 0; Cur &&
I != NumRelocsInGroup; ++
I) {
438 Offset += GroupedByOffsetDelta ? GroupOffsetDelta :
Data.getSLEB128(Cur);
440 R.r_info = GroupedByInfo ? GroupRInfo :
Data.getSLEB128(Cur);
441 if (GroupHasAddend && !GroupedByAddend)
442 Addend +=
Data.getSLEB128(Cur);
456#define DYNAMIC_STRINGIFY_ENUM(tag, value) \
460#define DYNAMIC_TAG(n, v)
464#define AARCH64_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
465#include "llvm/BinaryFormat/DynamicTags.def"
466#undef AARCH64_DYNAMIC_TAG
472#define HEXAGON_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
473#include "llvm/BinaryFormat/DynamicTags.def"
474#undef HEXAGON_DYNAMIC_TAG
480#define MIPS_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
481#include "llvm/BinaryFormat/DynamicTags.def"
482#undef MIPS_DYNAMIC_TAG
488#define PPC_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
489#include "llvm/BinaryFormat/DynamicTags.def"
490#undef PPC_DYNAMIC_TAG
496#define PPC64_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
497#include "llvm/BinaryFormat/DynamicTags.def"
498#undef PPC64_DYNAMIC_TAG
504#define RISCV_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
505#include "llvm/BinaryFormat/DynamicTags.def"
506#undef RISCV_DYNAMIC_TAG
513#define AARCH64_DYNAMIC_TAG(name, value)
514#define MIPS_DYNAMIC_TAG(name, value)
515#define HEXAGON_DYNAMIC_TAG(name, value)
516#define PPC_DYNAMIC_TAG(name, value)
517#define PPC64_DYNAMIC_TAG(name, value)
518#define RISCV_DYNAMIC_TAG(name, value)
520#define DYNAMIC_TAG_MARKER(name, value)
521#define DYNAMIC_TAG(name, value) case value: return #name;
522#include "llvm/BinaryFormat/DynamicTags.def"
524#undef AARCH64_DYNAMIC_TAG
525#undef MIPS_DYNAMIC_TAG
526#undef HEXAGON_DYNAMIC_TAG
527#undef PPC_DYNAMIC_TAG
528#undef PPC64_DYNAMIC_TAG
529#undef RISCV_DYNAMIC_TAG
530#undef DYNAMIC_TAG_MARKER
531#undef DYNAMIC_STRINGIFY_ENUM
533 return "<unknown:>0x" + utohexstr(
Type,
true);
539 return getDynamicTagAsString(getHeader().e_machine,
Type);
546 auto ProgramHeadersOrError = program_headers();
547 if (!ProgramHeadersOrError)
548 return ProgramHeadersOrError.takeError();
550 for (
const Elf_Phdr &Phdr : *ProgramHeadersOrError) {
552 Dyn =
ArrayRef(
reinterpret_cast<const Elf_Dyn *
>(base() + Phdr.p_offset),
553 Phdr.p_filesz /
sizeof(Elf_Dyn));
561 auto SectionsOrError = sections();
562 if (!SectionsOrError)
563 return SectionsOrError.takeError();
565 for (
const Elf_Shdr &Sec : *SectionsOrError) {
568 getSectionContentsAsArray<Elf_Dyn>(Sec);
581 return createError(
"invalid empty dynamic section");
583 if (Dyn.
back().d_tag != ELF::DT_NULL)
584 return createError(
"dynamic sections must be DT_NULL terminated");
592 auto ProgramHeadersOrError = program_headers();
593 if (!ProgramHeadersOrError)
594 return ProgramHeadersOrError.takeError();
598 for (
const Elf_Phdr &Phdr : *ProgramHeadersOrError)
600 LoadSegments.
push_back(
const_cast<Elf_Phdr *
>(&Phdr));
604 return A->p_vaddr <
B->p_vaddr;
608 WarnHandler(
"loadable segments are unsorted by virtual address"))
615 return VAddr < Phdr->p_vaddr;
618 if (
I == LoadSegments.
begin())
619 return createError(
"virtual address is not in any segment: 0x" +
622 const Elf_Phdr &Phdr = **
I;
623 uint64_t Delta = VAddr - Phdr.p_vaddr;
624 if (Delta >= Phdr.p_filesz)
625 return createError(
"virtual address is not in any segment: 0x" +
629 if (
Offset >= getBufSize())
630 return createError(
"can't map virtual address 0x" +
632 Twine(&Phdr - (*ProgramHeadersOrError).data() + 1) +
633 ": the segment ends at 0x" +
635 ", which is greater than the file size (0x" +
649 std::vector<BBAddrMap> FunctionEntries;
657 auto ReadULEB128AsUInt32 = [&
Data, &Cur, &ULEBSizeErr]() ->
uint32_t {
663 if (
Value > UINT32_MAX) {
673 while (!ULEBSizeErr && Cur && Cur.
tell() <
Content.size()) {
675 Version =
Data.getU8(Cur);
679 return createError(
"unsupported SHT_LLVM_BB_ADDR_MAP version: " +
680 Twine(
static_cast<int>(Version)));
683 uintX_t Address =
static_cast<uintX_t
>(
Data.getAddress(Cur));
684 uint32_t NumBlocks = ReadULEB128AsUInt32();
685 std::vector<BBAddrMap::BBEntry> BBEntries;
688 !ULEBSizeErr && Cur && (BlockIndex < NumBlocks); ++BlockIndex) {
689 uint32_t ID = Version >= 2 ? ReadULEB128AsUInt32() : BlockIndex;
695 Offset += PrevBBEndOffset;
700 FunctionEntries.push_back({Address, std::move(BBEntries)});
704 if (!Cur || ULEBSizeErr)
706 return FunctionEntries;
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define STRINGIFY_ENUM_CASE(ns, name)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & back() const
back - Get the last element.
bool empty() const
empty - Check if the array is empty.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static Twine utohexstr(const uint64_t &Val)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
An efficient, type-erasing, non-owning reference to a callable.
Expected< std::vector< Elf_Rela > > android_relas(const Elf_Shdr &Sec) const
std::string getDynamicTagAsString(unsigned Arch, uint64_t Type) const
Expected< Elf_Dyn_Range > dynamicEntries() const
Expected< const uint8_t * > toMappedAddr(uint64_t VAddr, WarningHandler WarnHandler=&defaultWarningHandler) const
Expected< std::vector< BBAddrMap > > decodeBBAddrMap(const Elf_Shdr &Sec) const
std::vector< Elf_Rel > decode_relrs(Elf_Relr_Range relrs) const
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG
@ RELOCATION_GROUPED_BY_INFO_FLAG
@ RELOCATION_GROUPED_BY_ADDEND_FLAG
@ RELOCATION_GROUP_HAS_ADDEND_FLAG
Error createError(const Twine &Err)
StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type)
uint32_t getELFRelativeRelocationType(uint32_t Machine)
StringRef getELFSectionTypeName(uint32_t Machine, uint32_t Type)
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
auto upper_bound(R &&Range, T &&Value)
Provide wrappers to std::upper_bound which take ranges instead of having to pass begin/end explicitly...
Error joinErrors(Error E1, Error E2)
Concatenate errors.
bool is_sorted(R &&Range, Compare C)
Wrapper function around std::is_sorted to check if elements in a range R are sorted with respect to a...