[llvm-readobj] Refactor ELFDumper::printAttributes()

The current implementation of printAttributes makes it fiddly to extend
attribute support for new targets.

By refactoring the code so all target specific variables are
initialized in a switch/case statement, it becomes simpler to extend
attribute support for new targets.

Reviewed By: jhenderson, MaskRay

Differential Revision: https://reviews.llvm.org/D107968
This commit is contained in:
Jozef Lawrynowicz 2021-08-17 13:28:31 -07:00 committed by Fangrui Song
parent e21a21a977
commit 108ba4f4a4
3 changed files with 44 additions and 23 deletions

View File

@ -0,0 +1,17 @@
## We only implement attribute section printing for little-endian encoding.
# RUN: yaml2obj %s -o %t.o
# RUN: llvm-readobj -A %t.o 2>&1 | FileCheck %s -DFILE=%t.o
# CHECK: warning: '[[FILE]]': attribute printing not implemented for big-endian ARM objects
--- !ELF
FileHeader:
Class: ELFCLASS32
## Test big-endian encoding.
Data: ELFDATA2MSB
Type: ET_REL
Machine: EM_ARM
Sections:
- Name: .ARM.attributes
Type: SHT_ARM_ATTRIBUTES

View File

@ -1,9 +1,9 @@
## We only implement attribute section printing for little-endian encoding.
# RUN: yaml2obj %s -o %t.o
# RUN: llvm-readobj -A %t.o | FileCheck %s
# RUN: llvm-readobj -A %t.o 2>&1 | FileCheck %s -DFILE=%t.o
# CHECK: Attributes not implemented.
# CHECK: warning: '[[FILE]]': attribute printing not implemented for big-endian RISC-V objects
--- !ELF
FileHeader:

View File

@ -339,7 +339,8 @@ protected:
return DynRegionInfo(ObjF, *this, Obj.base() + Offset, Size, EntSize);
}
void printAttributes();
void printAttributes(unsigned, std::unique_ptr<ELFAttributeParser>,
support::endianness);
void printMipsReginfo();
void printMipsOptions();
@ -2557,8 +2558,22 @@ template <typename ELFT> void ELFDumper<ELFT>::printLoadName() {
template <class ELFT> void ELFDumper<ELFT>::printArchSpecificInfo() {
switch (Obj.getHeader().e_machine) {
case EM_ARM:
if (Obj.isLE())
printAttributes(ELF::SHT_ARM_ATTRIBUTES,
std::make_unique<ARMAttributeParser>(&W),
support::little);
else
reportUniqueWarning("attribute printing not implemented for big-endian "
"ARM objects");
break;
case EM_RISCV:
printAttributes();
if (Obj.isLE())
printAttributes(ELF::SHT_RISCV_ATTRIBUTES,
std::make_unique<RISCVAttributeParser>(&W),
support::little);
else
reportUniqueWarning("attribute printing not implemented for big-endian "
"RISC-V objects");
break;
case EM_MIPS: {
printMipsABIFlags();
@ -2581,20 +2596,15 @@ template <class ELFT> void ELFDumper<ELFT>::printArchSpecificInfo() {
}
}
template <class ELFT> void ELFDumper<ELFT>::printAttributes() {
if (!Obj.isLE()) {
W.startLine() << "Attributes not implemented.\n";
return;
}
const unsigned Machine = Obj.getHeader().e_machine;
assert((Machine == EM_ARM || Machine == EM_RISCV) &&
"Attributes not implemented.");
template <class ELFT>
void ELFDumper<ELFT>::printAttributes(
unsigned AttrShType, std::unique_ptr<ELFAttributeParser> AttrParser,
support::endianness Endianness) {
assert((AttrShType != ELF::SHT_NULL) && AttrParser &&
"Incomplete ELF attribute implementation");
DictScope BA(W, "BuildAttributes");
for (const Elf_Shdr &Sec : cantFail(Obj.sections())) {
if (Sec.sh_type != ELF::SHT_ARM_ATTRIBUTES &&
Sec.sh_type != ELF::SHT_RISCV_ATTRIBUTES)
if (Sec.sh_type != AttrShType)
continue;
ArrayRef<uint8_t> Contents;
@ -2613,13 +2623,7 @@ template <class ELFT> void ELFDumper<ELFT>::printAttributes() {
W.printHex("FormatVersion", Contents[0]);
auto ParseAttrubutes = [&]() {
if (Machine == EM_ARM)
return ARMAttributeParser(&W).parse(Contents, support::little);
return RISCVAttributeParser(&W).parse(Contents, support::little);
};
if (Error E = ParseAttrubutes())
if (Error E = AttrParser->parse(Contents, Endianness))
reportUniqueWarning("unable to dump attributes from the " +
describe(Sec) + ": " + toString(std::move(E)));
}