[llvm] 2f37a22 - [llvm-objdump] -r: support CREL
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 8 09:14:38 PDT 2024
Author: Fangrui Song
Date: 2024-07-08T09:14:34-07:00
New Revision: 2f37a22f10a1128c695bc469871a9101edce853e
URL: https://github.com/llvm/llvm-project/commit/2f37a22f10a1128c695bc469871a9101edce853e
DIFF: https://github.com/llvm/llvm-project/commit/2f37a22f10a1128c695bc469871a9101edce853e.diff
LOG: [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
Added:
llvm/test/tools/llvm-objdump/ELF/crel.test
Modified:
llvm/include/llvm/Object/ELF.h
llvm/include/llvm/Object/ELFObjectFile.h
llvm/lib/Object/ELF.cpp
llvm/lib/Object/ELFObjectFile.cpp
llvm/test/tools/llvm-objdump/X86/elf-disassemble-relocs.test
llvm/tools/llvm-objdump/ELFDump.cpp
llvm/tools/llvm-objdump/llvm-objdump.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h
index 0986379ce76f5e..6bf42de89e1c4f 100644
--- a/llvm/include/llvm/Object/ELF.h
+++ b/llvm/include/llvm/Object/ELF.h
@@ -21,11 +21,13 @@
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Object/ELFTypes.h"
#include "llvm/Object/Error.h"
+#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Error.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <limits>
+#include <type_traits>
#include <utility>
namespace llvm {
@@ -207,6 +209,47 @@ bool isSectionInSegment(const typename ELFT::Phdr &Phdr,
checkSectionVMA<ELFT>(Phdr, Sec);
}
+// HdrHandler is called once with the number of relocations and whether the
+// relocations have addends. EntryHandler is called once per decoded relocation.
+template <bool Is64>
+Error decodeCrel(
+ ArrayRef<uint8_t> Content,
+ function_ref<void(uint64_t /*relocation count*/, bool /*explicit addends*/)>
+ HdrHandler,
+ function_ref<void(Elf_Crel_Impl<Is64>)> EntryHandler) {
+ DataExtractor Data(Content, true, 8); // endian and address size are unused
+ DataExtractor::Cursor Cur(0);
+ const uint64_t Hdr = Data.getULEB128(Cur);
+ 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;
+ using uint = typename Elf_Crel_Impl<Is64>::uint;
+ uint Offset = 0, Addend = 0;
+ HdrHandler(Count, Hdr & ELF::CREL_HDR_ADDEND);
+ uint32_t SymIdx = 0, Type = 0;
+ for (; Count; --Count) {
+ // 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 (!Cur)
+ break;
+ EntryHandler(
+ {Offset << Shift, SymIdx, Type, std::make_signed_t<uint>(Addend)});
+ }
+ return Cur.takeError();
+}
+
template <class ELFT>
class ELFFile {
public:
diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h
index 8cc09e7fd7d551..811943dcd70887 100644
--- a/llvm/include/llvm/Object/ELFObjectFile.h
+++ b/llvm/include/llvm/Object/ELFObjectFile.h
@@ -29,6 +29,7 @@
#include "llvm/Support/ELFAttributes.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/LEB128.h"
#include "llvm/Support/MemoryBufferRef.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/TargetParser/SubtargetFeature.h"
@@ -122,6 +123,8 @@ class ELFObjectFileBase : public ObjectFile {
Expected<std::vector<BBAddrMap>>
readBBAddrMap(std::optional<unsigned> TextSectionIndex = std::nullopt,
std::vector<PGOAnalysisMap> *PGOAnalyses = nullptr) const;
+
+ StringRef getCrelDecodeProblem(SectionRef Sec) const;
};
class ELFSectionRef : public SectionRef {
@@ -292,6 +295,10 @@ template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
const Elf_Shdr *DotSymtabSec = nullptr; // Symbol table section.
const Elf_Shdr *DotSymtabShndxSec = nullptr; // SHT_SYMTAB_SHNDX section.
+ // Hold CREL relocations for SectionRef::relocations().
+ mutable SmallVector<SmallVector<Elf_Crel, 0>, 0> Crels;
+ mutable SmallVector<std::string, 0> CrelDecodeProblems;
+
Error initContent() override;
void moveSymbolNext(DataRefImpl &Symb) const override;
@@ -446,6 +453,7 @@ template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
const Elf_Rel *getRel(DataRefImpl Rel) const;
const Elf_Rela *getRela(DataRefImpl Rela) const;
+ Elf_Crel getCrel(DataRefImpl Crel) const;
Expected<const Elf_Sym *> getSymbol(DataRefImpl Sym) const {
return EF.template getEntry<Elf_Sym>(Sym.d.a, Sym.d.b);
@@ -499,6 +507,8 @@ template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
bool isRelocatableObject() const override;
void createFakeSections() { EF.createFakeSections(); }
+
+ StringRef getCrelDecodeProblem(DataRefImpl Sec) const;
};
using ELF32LEObjectFile = ELFObjectFile<ELF32LE>;
@@ -1022,6 +1032,24 @@ ELFObjectFile<ELFT>::section_rel_begin(DataRefImpl Sec) const {
uintptr_t SHT = reinterpret_cast<uintptr_t>((*SectionsOrErr).begin());
RelData.d.a = (Sec.p - SHT) / EF.getHeader().e_shentsize;
RelData.d.b = 0;
+ if (reinterpret_cast<const Elf_Shdr *>(Sec.p)->sh_type == ELF::SHT_CREL) {
+ if (RelData.d.a + 1 > Crels.size())
+ Crels.resize(RelData.d.a + 1);
+ auto &Crel = Crels[RelData.d.a];
+ if (Crel.empty()) {
+ ArrayRef<uint8_t> Content = cantFail(getSectionContents(Sec));
+ size_t I = 0;
+ Error Err = decodeCrel<ELFT::Is64Bits>(
+ Content, [&](uint64_t Count, bool) { Crel.resize(Count); },
+ [&](Elf_Crel Crel) { Crels[RelData.d.a][I++] = Crel; });
+ if (Err) {
+ Crel.assign(1, Elf_Crel{0, 0, 0, 0});
+ if (RelData.d.a + 1 > CrelDecodeProblems.size())
+ CrelDecodeProblems.resize(RelData.d.a + 1);
+ CrelDecodeProblems[RelData.d.a] = toString(std::move(Err));
+ }
+ }
+ }
return relocation_iterator(RelocationRef(RelData, this));
}
@@ -1030,9 +1058,13 @@ relocation_iterator
ELFObjectFile<ELFT>::section_rel_end(DataRefImpl Sec) const {
const Elf_Shdr *S = reinterpret_cast<const Elf_Shdr *>(Sec.p);
relocation_iterator Begin = section_rel_begin(Sec);
+ DataRefImpl RelData = Begin->getRawDataRefImpl();
+ if (S->sh_type == ELF::SHT_CREL) {
+ RelData.d.b = Crels[RelData.d.a].size();
+ return relocation_iterator(RelocationRef(RelData, this));
+ }
if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL)
return Begin;
- DataRefImpl RelData = Begin->getRawDataRefImpl();
const Elf_Shdr *RelSec = getRelSection(RelData);
// Error check sh_link here so that getRelocationSymbol can just use it.
@@ -1050,7 +1082,7 @@ Expected<section_iterator>
ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const {
const Elf_Shdr *EShdr = getSection(Sec);
uintX_t Type = EShdr->sh_type;
- if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA)
+ if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA && Type != ELF::SHT_CREL)
return section_end();
Expected<const Elf_Shdr *> SecOrErr = EF.getSection(EShdr->sh_info);
@@ -1070,7 +1102,9 @@ symbol_iterator
ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const {
uint32_t symbolIdx;
const Elf_Shdr *sec = getRelSection(Rel);
- if (sec->sh_type == ELF::SHT_REL)
+ if (sec->sh_type == ELF::SHT_CREL)
+ symbolIdx = getCrel(Rel).r_symidx;
+ else if (sec->sh_type == ELF::SHT_REL)
symbolIdx = getRel(Rel)->getSymbol(EF.isMips64EL());
else
symbolIdx = getRela(Rel)->getSymbol(EF.isMips64EL());
@@ -1087,6 +1121,8 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const {
template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel) const {
const Elf_Shdr *sec = getRelSection(Rel);
+ if (sec->sh_type == ELF::SHT_CREL)
+ return getCrel(Rel).r_offset;
if (sec->sh_type == ELF::SHT_REL)
return getRel(Rel)->r_offset;
@@ -1096,6 +1132,8 @@ uint64_t ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel) const {
template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel) const {
const Elf_Shdr *sec = getRelSection(Rel);
+ if (sec->sh_type == ELF::SHT_CREL)
+ return getCrel(Rel).r_type;
if (sec->sh_type == ELF::SHT_REL)
return getRel(Rel)->getType(EF.isMips64EL());
else
@@ -1117,9 +1155,11 @@ void ELFObjectFile<ELFT>::getRelocationTypeName(
template <class ELFT>
Expected<int64_t>
ELFObjectFile<ELFT>::getRelocationAddend(DataRefImpl Rel) const {
- if (getRelSection(Rel)->sh_type != ELF::SHT_RELA)
- return createError("Section is not SHT_RELA");
- return (int64_t)getRela(Rel)->r_addend;
+ if (getRelSection(Rel)->sh_type == ELF::SHT_RELA)
+ return (int64_t)getRela(Rel)->r_addend;
+ if (getRelSection(Rel)->sh_type == ELF::SHT_CREL)
+ return (int64_t)getCrel(Rel).r_addend;
+ return createError("Relocation section does not have addends");
}
template <class ELFT>
@@ -1142,6 +1182,14 @@ ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const {
return *Ret;
}
+template <class ELFT>
+typename ELFObjectFile<ELFT>::Elf_Crel
+ELFObjectFile<ELFT>::getCrel(DataRefImpl Crel) const {
+ assert(getRelSection(Crel)->sh_type == ELF::SHT_CREL);
+ assert(Crel.d.a < Crels.size());
+ return Crels[Crel.d.a][Crel.d.b];
+}
+
template <class ELFT>
Expected<ELFObjectFile<ELFT>>
ELFObjectFile<ELFT>::create(MemoryBufferRef Object, bool InitContent) {
@@ -1453,6 +1501,15 @@ template <class ELFT> bool ELFObjectFile<ELFT>::isRelocatableObject() const {
return EF.getHeader().e_type == ELF::ET_REL;
}
+template <class ELFT>
+StringRef ELFObjectFile<ELFT>::getCrelDecodeProblem(DataRefImpl Sec) const {
+ uintptr_t SHT = reinterpret_cast<uintptr_t>(cantFail(EF.sections()).begin());
+ auto I = (Sec.p - SHT) / EF.getHeader().e_shentsize;
+ if (I < CrelDecodeProblems.size())
+ return CrelDecodeProblems[I];
+ return "";
+}
+
} // end namespace object
} // end namespace llvm
diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp
index 18a116754f4566..e47a40b8715dd5 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 cbc55a145e0e6f..53c3de06d118cc 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);
+}
diff --git a/llvm/test/tools/llvm-objdump/ELF/crel.test b/llvm/test/tools/llvm-objdump/ELF/crel.test
new file mode 100644
index 00000000000000..ef3c4b011135c1
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/ELF/crel.test
@@ -0,0 +1,213 @@
+# RUN: yaml2obj --docnum=1 %s -o %t
+# RUN: llvm-objdump -r %t | FileCheck %s --strict-whitespace --match-full-lines
+
+# CHECK:RELOCATION RECORDS FOR [.text]:
+# CHECK-NEXT:OFFSET TYPE VALUE
+# CHECK-NEXT:0000000000000001 R_X86_64_32 g1+0x1
+# CHECK-NEXT:0000000000000002 R_X86_64_64 l1+0x2
+# CHECK-NEXT:0000000000000000 R_X86_64_32S g1-0x1
+# CHECK-NEXT:0000000000000004 R_X86_64_32S .text-0x8000000000000000
+#CHECK-EMPTY:
+# CHECK-NEXT:RELOCATION RECORDS FOR [nonalloc]:
+# CHECK-NEXT:OFFSET TYPE VALUE
+# CHECK-NEXT:0000000000000010 R_X86_64_64 g1+0x1
+# CHECK-NEXT:0000000000000020 R_X86_64_64 g2+0x2
+# CHECK-NEXT:0000000000000030 R_X86_64_64 *ABS*
+# CHECK-NOT:{{.}}
+
+--- !ELF
+FileHeader: !FileHeader
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+
+Sections:
+- Name: .text
+ Type: SHT_PROGBITS
+ Content: "0000000000000000"
+ Flags: [SHF_ALLOC]
+- Name: .crel.text
+ Type: SHT_CREL
+ Info: .text
+ Link: .symtab
+ Relocations:
+ - Offset: 0x1
+ Symbol: g1
+ Type: R_X86_64_32
+ Addend: 1
+ - Offset: 0x2
+ Symbol: l1
+ Type: R_X86_64_64
+ Addend: 2
+ - Offset: 0x0
+ Symbol: g1
+ Type: R_X86_64_32S
+ Addend: 0xffffffffffffffff
+ - Offset: 0x4
+ Symbol: .text
+ Type: R_X86_64_32S
+ Addend: 0x8000000000000000
+- Name: nonalloc
+ Type: SHT_PROGBITS
+ Size: 0x30
+- Name: .crelnonalloc
+ Type: SHT_CREL
+ Info: nonalloc
+ Link: .symtab
+ Relocations:
+ - Offset: 0x10
+ Symbol: g1
+ Type: R_X86_64_64
+ Addend: 1
+ - Offset: 0x20
+ Symbol: g2
+ Type: R_X86_64_64
+ Addend: 2
+ - Offset: 0x30
+ Symbol: 0
+ Type: R_X86_64_64
+
+Symbols:
+ - Name: .text
+ Type: STT_SECTION
+ Section: .text
+ - Name: l1
+ - Name: g1
+ Section: .text
+ Value: 0x0
+ Size: 4
+ Binding: STB_GLOBAL
+ - Name: g2
+ Binding: STB_GLOBAL
+
+## Check relocation formatting on ELFCLASS32 as well.
+# RUN: yaml2obj --docnum=2 %s > %t2
+# RUN: llvm-objdump -r %t2 | FileCheck %s --check-prefix=ELF32 --strict-whitespace --match-full-lines
+
+# ELF32:RELOCATION RECORDS FOR [.text]:
+# ELF32-NEXT:OFFSET TYPE VALUE
+# ELF32-NEXT:00000008 R_ARM_REL32 l1+0x1
+# ELF32-NEXT:00000004 R_ARM_ABS32 g1
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2MSB
+ Type: ET_REL
+ Machine: EM_ARM
+Sections:
+- Name: .text
+ Type: SHT_PROGBITS
+ Size: 0x10
+- Name: .crel.text
+ Type: SHT_CREL
+ Info: .text
+ Link: .symtab
+ Relocations:
+ - Offset: 0x8
+ Symbol: l1
+ Type: R_ARM_REL32
+ Addend: 1
+ - Offset: 0x4
+ Symbol: g1
+ Type: R_ARM_ABS32
+Symbols:
+ - Name: l1
+ - Name: g1
+ Binding: STB_GLOBAL
+
+## Check CREL with implicit addends.
+# RUN: yaml2obj --docnum=3 %s -o %t3
+# RUN: llvm-objdump -r %t3 | FileCheck %s --check-prefix=IMPLICIT --strict-whitespace --match-full-lines
+# IMPLICIT:RELOCATION RECORDS FOR [.data]:
+# IMPLICIT-NEXT:OFFSET TYPE VALUE
+# IMPLICIT-NEXT:000000000000001f R_X86_64_32 g1
+# IMPLICIT-NEXT:000000000000003f R_X86_64_64 g1
+# IMPLICIT-NEXT:0000000000000000 R_X86_64_32S l1
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ - Name: .data
+ Type: SHT_PROGBITS
+ - Name: .crel.data
+ Type: SHT_CREL
+ Flags: [ SHF_INFO_LINK ]
+ Link: .symtab
+ Info: .data
+ Content: 187f030a82017787feffffffffffffff077f0a
+Symbols:
+ - Name: .text
+ Type: STT_SECTION
+ Section: .text
+ - Name: l1
+ Section: .text
+ - Name: g1
+ Section: .text
+ Binding: STB_GLOBAL
+
+## Test errors.
+# RUN: yaml2obj --docnum=4 %s -o %t.err
+# RUN: llvm-objdump -r %t.err 2>&1 | FileCheck %s --check-prefix=ERR -DFILE=%t.err
+
+# ERR:RELOCATION RECORDS FOR [.data]:
+# ERR-NEXT:OFFSET TYPE VALUE
+# ERR-NEXT:warning: '[[FILE]]': unable to decode LEB128 at offset 0x00000000: malformed uleb128, extends past end
+# ERR-NOT:{{.}}
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ - Name: .data
+ Type: SHT_PROGBITS
+ - Name: .crel.data
+ Type: SHT_CREL
+ Flags: []
+ Link: .symtab
+ Info: .data
+Symbols:
+ - Name: .text
+ Type: STT_SECTION
+ Section: .text
+
+# RUN: yaml2obj --docnum=5 %s -o %t.err2
+# RUN: llvm-objdump -r %t.err2 2>&1 | FileCheck %s --check-prefix=ERR2 -DFILE=%t.err2
+
+# ERR2:RELOCATION RECORDS FOR [.data]:
+# ERR2-NEXT:OFFSET TYPE VALUE
+# ERR2-NEXT:warning: '[[FILE]]': unexpected end of data at offset 0x1 while reading [0x1, 0x2)
+# ERR2-NOT:{{.}}
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2MSB
+ Type: ET_REL
+ Machine: EM_ARM
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ - Name: .data
+ Type: SHT_PROGBITS
+ - Name: .crel.data
+ Type: SHT_CREL
+ Flags: []
+ Link: .symtab
+ Info: .data
+ Content: 08
+Symbols:
+ - Name: .text
+ Type: STT_SECTION
+ Section: .text
diff --git a/llvm/test/tools/llvm-objdump/X86/elf-disassemble-relocs.test b/llvm/test/tools/llvm-objdump/X86/elf-disassemble-relocs.test
index cce0712e8fa0d9..a6bd09ce3fa241 100644
--- a/llvm/test/tools/llvm-objdump/X86/elf-disassemble-relocs.test
+++ b/llvm/test/tools/llvm-objdump/X86/elf-disassemble-relocs.test
@@ -6,6 +6,10 @@
# RUN: llvm-objdump 1.o -d -r | FileCheck %s --implicit-check-not="RELOCATION RECORDS"
# RUN: llvm-objdump 1.o -r --disassemble-symbols=x2,x4 | FileCheck %s --check-prefix=CHECK2
+# RUN: llvm-mc -filetype=obj -triple=x86_64 -crel 1.s -o 1leb.o
+# RUN: llvm-objdump 1leb.o -d -r | FileCheck %s --implicit-check-not="RELOCATION RECORDS"
+# RUN: llvm-objdump 1leb.o -r --disassemble-symbols=x2,x4 | FileCheck %s --check-prefix=CHECK2
+
#--- 1.s
# CHECK: 0000000000000000 <x1>:
# CHECK-NEXT: 0: e8 00 00 00 00 callq 0x5 <x1+0x5>
diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp
index 8c184fc1fbb66a..5ac13495662faf 100644
--- a/llvm/tools/llvm-objdump/ELFDump.cpp
+++ b/llvm/tools/llvm-objdump/ELFDump.cpp
@@ -104,7 +104,11 @@ static Error getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
// In SHT_REL case we would need to read the addend from section data.
// GNU objdump does not do that and we just follow for simplicity atm.
bool Undef = false;
- if ((*SecOrErr)->sh_type == ELF::SHT_RELA) {
+ if ((*SecOrErr)->sh_type == ELF::SHT_CREL) {
+ auto ERela = Obj->getCrel(Rel);
+ Addend = ERela.r_addend;
+ Undef = ERela.getSymbol(false) == 0;
+ } else if ((*SecOrErr)->sh_type == ELF::SHT_RELA) {
const typename ELFT::Rela *ERela = Obj->getRela(Rel);
Addend = ERela->r_addend;
Undef = ERela->getSymbol(false) == 0;
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp
index 6249be4f332b78..d1240025625ca4 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -2687,6 +2687,16 @@ void Dumper::printRelocations() {
<< "VALUE\n";
for (SectionRef Section : P.second) {
+ // CREL sections require decoding, each section may have its own specific
+ // decode problems.
+ if (O.isELF() && ELFSectionRef(Section).getType() == ELF::SHT_CREL) {
+ StringRef Err =
+ cast<const ELFObjectFileBase>(O).getCrelDecodeProblem(Section);
+ if (!Err.empty()) {
+ reportUniqueWarning(Err);
+ continue;
+ }
+ }
for (const RelocationRef &Reloc : Section.relocations()) {
uint64_t Address = Reloc.getOffset();
SmallString<32> RelocName;
More information about the llvm-commits
mailing list