aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Object
diff options
context:
space:
mode:
authorFangrui Song <i@maskray.me>2024-07-08 09:14:34 -0700
committerGitHub <noreply@github.com>2024-07-08 09:14:34 -0700
commit2f37a22f10a1128c695bc469871a9101edce853e (patch)
tree7c135f7f5d61bd4f632dbaa1d3f4938543032725 /llvm/lib/Object
parent12e47aabd4e4c6cec15092183b91ec279a0a7ab4 (diff)
downloadllvm-2f37a22f10a1128c695bc469871a9101edce853e.zip
llvm-2f37a22f10a1128c695bc469871a9101edce853e.tar.gz
llvm-2f37a22f10a1128c695bc469871a9101edce853e.tar.bz2
[llvm-objdump] -r: support CREL
Extract the llvm-readelf decoder to `decodeCrel` (#91280) and reuse it for llvm-objdump. Because the section representation of LLVMObject (`SectionRef`) is 64-bit, insufficient to hold all decoder states, `section_rel_begin` is modified to decode CREL eagerly and hold the decoded relocations inside ELFObjectFile<ELFT>. The test is adapted from llvm/test/tools/llvm-readobj/ELF/crel.test. Pull Request: https://github.com/llvm/llvm-project/pull/97382
Diffstat (limited to 'llvm/lib/Object')
-rw-r--r--llvm/lib/Object/ELF.cpp61
-rw-r--r--llvm/lib/Object/ELFObjectFile.cpp11
2 files changed, 34 insertions, 38 deletions
diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp
index 18a1167..e47a40b8 100644
--- a/llvm/lib/Object/ELF.cpp
+++ b/llvm/lib/Object/ELF.cpp
@@ -408,46 +408,31 @@ ELFFile<ELFT>::getCrelHeader(ArrayRef<uint8_t> Content) const {
template <class ELFT>
Expected<typename ELFFile<ELFT>::RelsOrRelas>
ELFFile<ELFT>::decodeCrel(ArrayRef<uint8_t> Content) const {
- DataExtractor Data(Content, isLE(), sizeof(typename ELFT::Addr));
- DataExtractor::Cursor Cur(0);
- const uint64_t Hdr = Data.getULEB128(Cur);
- const size_t Count = Hdr / 8;
- const size_t FlagBits = Hdr & ELF::CREL_HDR_ADDEND ? 3 : 2;
- const size_t Shift = Hdr % ELF::CREL_HDR_ADDEND;
std::vector<Elf_Rel> Rels;
std::vector<Elf_Rela> Relas;
- if (Hdr & ELF::CREL_HDR_ADDEND)
- Relas.resize(Count);
- else
- Rels.resize(Count);
- typename ELFT::uint Offset = 0, Addend = 0;
- uint32_t SymIdx = 0, Type = 0;
- for (size_t I = 0; I != Count; ++I) {
- // The delta offset and flags member may be larger than uint64_t. Special
- // case the first byte (2 or 3 flag bits; the rest are offset bits). Other
- // ULEB128 bytes encode the remaining delta offset bits.
- const uint8_t B = Data.getU8(Cur);
- Offset += B >> FlagBits;
- if (B >= 0x80)
- Offset += (Data.getULEB128(Cur) << (7 - FlagBits)) - (0x80 >> FlagBits);
- // Delta symidx/type/addend members (SLEB128).
- if (B & 1)
- SymIdx += Data.getSLEB128(Cur);
- if (B & 2)
- Type += Data.getSLEB128(Cur);
- if (B & 4 & Hdr)
- Addend += Data.getSLEB128(Cur);
- if (Hdr & ELF::CREL_HDR_ADDEND) {
- Relas[I].r_offset = Offset << Shift;
- Relas[I].setSymbolAndType(SymIdx, Type, false);
- Relas[I].r_addend = Addend;
- } else {
- Rels[I].r_offset = Offset << Shift;
- Rels[I].setSymbolAndType(SymIdx, Type, false);
- }
- }
- if (!Cur)
- return std::move(Cur.takeError());
+ size_t I = 0;
+ bool HasAddend;
+ Error Err = object::decodeCrel<ELFT::Is64Bits>(
+ Content,
+ [&](uint64_t Count, bool HasA) {
+ HasAddend = HasA;
+ if (HasAddend)
+ Relas.resize(Count);
+ else
+ Rels.resize(Count);
+ },
+ [&](Elf_Crel Crel) {
+ if (HasAddend) {
+ Relas[I].r_offset = Crel.r_offset;
+ Relas[I].setSymbolAndType(Crel.r_symidx, Crel.r_type, false);
+ Relas[I++].r_addend = Crel.r_addend;
+ } else {
+ Rels[I].r_offset = Crel.r_offset;
+ Rels[I++].setSymbolAndType(Crel.r_symidx, Crel.r_type, false);
+ }
+ });
+ if (Err)
+ return std::move(Err);
return std::make_pair(std::move(Rels), std::move(Relas));
}
diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp
index cbc55a1..53c3de0 100644
--- a/llvm/lib/Object/ELFObjectFile.cpp
+++ b/llvm/lib/Object/ELFObjectFile.cpp
@@ -1013,3 +1013,14 @@ Expected<std::vector<BBAddrMap>> ELFObjectFileBase::readBBAddrMap(
return readBBAddrMapImpl(cast<ELF64BEObjectFile>(this)->getELFFile(),
TextSectionIndex, PGOAnalyses);
}
+
+StringRef ELFObjectFileBase::getCrelDecodeProblem(SectionRef Sec) const {
+ auto Data = Sec.getRawDataRefImpl();
+ if (const auto *Obj = dyn_cast<ELF32LEObjectFile>(this))
+ return Obj->getCrelDecodeProblem(Data);
+ if (const auto *Obj = dyn_cast<ELF32BEObjectFile>(this))
+ return Obj->getCrelDecodeProblem(Data);
+ if (const auto *Obj = dyn_cast<ELF64LEObjectFile>(this))
+ return Obj->getCrelDecodeProblem(Data);
+ return cast<ELF64BEObjectFile>(this)->getCrelDecodeProblem(Data);
+}