mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-13 19:32:41 +00:00
[RISCV] Support RISC-V ELF attributes sections in llvm-readobj.
Enable llvm-readobj to handle RISC-V ELF attribute sections. Differential Revision: https://reviews.llvm.org/D75833
This commit is contained in:
parent
be7a233e93
commit
501522b5b2
@ -217,7 +217,7 @@ Error ELFAttributeParser::parse(ArrayRef<uint8_t> section,
|
||||
|
||||
if (sectionLength < 4 || cursor.tell() - 4 + sectionLength > section.size())
|
||||
return createStringError(errc::invalid_argument,
|
||||
"invalid subsection length " +
|
||||
"invalid section length " +
|
||||
Twine(sectionLength) + " at offset 0x" +
|
||||
utohexstr(cursor.tell() - 4));
|
||||
|
||||
|
21
llvm/test/MC/RISCV/attribute-with-option.s
Normal file
21
llvm/test/MC/RISCV/attribute-with-option.s
Normal file
@ -0,0 +1,21 @@
|
||||
## When a user specifies an architecture extension which conflicts with an
|
||||
## architecture attribute, we use the architecture attribute instead of the
|
||||
## command line option.
|
||||
##
|
||||
## This test uses option '-mattr=+e' to specify the "e" extension. However,
|
||||
## there is an architecture attribute in the file to specify rv32i. We will
|
||||
## use rv32i to assemble the file instead of rv32e.
|
||||
|
||||
# RUN: llvm-mc %s -triple=riscv32 -mattr=+e -filetype=obj -o - \
|
||||
# RUN: | llvm-readobj -A - | FileCheck %s
|
||||
|
||||
.attribute arch, "rv32i2p0"
|
||||
## Invalid operand for RV32E, because x16 is an invalid register for RV32E.
|
||||
## Use RV32I to assemble, since it will not trigger an assembly error.
|
||||
lui x16, 1
|
||||
|
||||
## Check that the architecture attribute is not overridden by the command line
|
||||
## option.
|
||||
# CHECK: Tag: 5
|
||||
# CHECK-NEXT: TagName: arch
|
||||
# CHECK-NEXT: Value: rv32i2p0
|
44
llvm/test/tools/llvm-readobj/ELF/RISCV/attribute.s
Normal file
44
llvm/test/tools/llvm-readobj/ELF/RISCV/attribute.s
Normal file
@ -0,0 +1,44 @@
|
||||
## Test llvm-readobj & llvm-readelf can decode RISC-V attributes correctly.
|
||||
|
||||
# RUN: llvm-mc -triple riscv32 -filetype obj -o %t.rv32.o %s
|
||||
# RUN: llvm-mc -triple riscv64 -filetype obj -o %t.rv64.o %s
|
||||
# RUN: llvm-readobj --arch-specific %t.rv32.o \
|
||||
# RUN: | FileCheck %s --check-prefix=CHECK-OBJ
|
||||
# RUN: llvm-readelf -A %t.rv32.o \
|
||||
# RUN: | FileCheck %s --check-prefix=CHECK-OBJ
|
||||
# RUN: llvm-readobj --arch-specific %t.rv64.o \
|
||||
# RUN: | FileCheck %s --check-prefix=CHECK-OBJ
|
||||
# RUN: llvm-readelf -A %t.rv64.o \
|
||||
# RUN: | FileCheck %s --check-prefix=CHECK-OBJ
|
||||
|
||||
.attribute Tag_stack_align, 16
|
||||
# CHECK-OBJ: Tag: 4
|
||||
# CHECK-OBJ-NEXT: Value: 16
|
||||
# CHECK-OBJ-NEXT: TagName: stack_align
|
||||
# CHECK-OBJ-NEXT: Description: Stack alignment is 16-bytes
|
||||
|
||||
.attribute Tag_arch, "rv32i2p0_m2p0_a2p0_c2p0"
|
||||
# CHECK-OBJ: Tag: 5
|
||||
# CHECK-OBJ-NEXT: TagName: arch
|
||||
# CHECK-OBJ-NEXT: Value: rv32i2p0_m2p0_a2p0_c2p0
|
||||
|
||||
.attribute Tag_unaligned_access, 0
|
||||
# CHECK-OBJ: Tag: 6
|
||||
# CHECK-OBJ-NEXT: Value: 0
|
||||
# CHECK-OBJ-NEXT: TagName: unaligned_access
|
||||
# CHECK-OBJ-NEXT: Description: No unaligned access
|
||||
|
||||
.attribute Tag_priv_spec, 2
|
||||
# CHECK-OBJ: Tag: 8
|
||||
# CHECK-OBJ-NEXT: TagName: priv_spec
|
||||
# CHECK-OBJ-NEXT: Value: 2
|
||||
|
||||
.attribute Tag_priv_spec_minor, 0
|
||||
# CHECK-OBJ: Tag: 10
|
||||
# CHECK-OBJ-NEXT: TagName: priv_spec_minor
|
||||
# CHECK-OBJ-NEXT: Value: 0
|
||||
|
||||
.attribute Tag_priv_spec_revision, 0
|
||||
# CHECK-OBJ: Tag: 12
|
||||
# CHECK-OBJ-NEXT: TagName: priv_spec_revision
|
||||
# CHECK-OBJ-NEXT: Value: 0
|
@ -0,0 +1,20 @@
|
||||
## This test case is used to ensure the error code is caught by llvm-readobj.
|
||||
|
||||
# RUN: yaml2obj %s -D BITS=32 -o %t.32.o
|
||||
# RUN: llvm-readobj -A %t.32.o 2>&1 | FileCheck -DFILE=%t %s
|
||||
# RUN: yaml2obj %s -D BITS=64 -o %t.64.o
|
||||
# RUN: llvm-readobj -A %t.64.o 2>&1 | FileCheck -DFILE=%t %s
|
||||
|
||||
# CHECK: warning: '[[FILE]].{{32|64}}.o': invalid section length 0 at offset 0x1
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS[[BITS]]
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_RISCV
|
||||
Sections:
|
||||
- Name: .riscv.attributes
|
||||
Type: SHT_RISCV_ATTRIBUTES
|
||||
## Version: 'A'(0x41), section length: 0
|
||||
Content: 4100000000
|
@ -0,0 +1,21 @@
|
||||
## This test case is used to ensure llvm-readobj checks the version of
|
||||
## attribute sections correctly.
|
||||
|
||||
# RUN: yaml2obj %s -D BITS=32 -o %t.32.o
|
||||
# RUN: llvm-readobj -A %t.32.o 2>&1 | FileCheck -DFILE=%t %s
|
||||
# RUN: yaml2obj %s -D BITS=64 -o %t.64.o
|
||||
# RUN: llvm-readobj -A %t.64.o 2>&1 | FileCheck -DFILE=%t %s
|
||||
|
||||
# CHECK: warning: '[[FILE]].{{32|64}}.o': unrecognised FormatVersion: 0x42
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS[[BITS]]
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_RISCV
|
||||
Sections:
|
||||
- Name: .riscv.attributes
|
||||
Type: SHT_RISCV_ATTRIBUTES
|
||||
## Version: 'B'
|
||||
Content: 42
|
2
llvm/test/tools/llvm-readobj/ELF/RISCV/lit.local.cfg
Normal file
2
llvm/test/tools/llvm-readobj/ELF/RISCV/lit.local.cfg
Normal file
@ -0,0 +1,2 @@
|
||||
if not 'RISCV' in config.root.targets:
|
||||
config.unsupported = True
|
21
llvm/test/tools/llvm-readobj/ELF/RISCV/section-types.test
Normal file
21
llvm/test/tools/llvm-readobj/ELF/RISCV/section-types.test
Normal file
@ -0,0 +1,21 @@
|
||||
## Show that all RISCV specific section types are properly printed for both
|
||||
## LLVM and GNU styles.
|
||||
|
||||
# RUN: yaml2obj %s -o %t-riscv.o
|
||||
# RUN: llvm-readobj --section-headers %t-riscv.o | FileCheck %s --check-prefix=LLVM
|
||||
# RUN: llvm-readelf --section-headers %t-riscv.o | FileCheck %s --check-prefix=GNU
|
||||
|
||||
# LLVM: Name: .riscv.attributes (1)
|
||||
# LLVM-NEXT: Type: SHT_RISCV_ATTRIBUTES (0x70000003)
|
||||
|
||||
# GNU: [ 1] .riscv.attributes RISCV_ATTRIBUTES
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_RISCV
|
||||
Sections:
|
||||
- Name: .riscv.attributes
|
||||
Type: SHT_RISCV_ATTRIBUTES
|
@ -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 | FileCheck %s
|
||||
|
||||
# CHECK: Attributes not implemented.
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
## Test big-endian encoding.
|
||||
Data: ELFDATA2MSB
|
||||
Type: ET_REL
|
||||
Machine: EM_RISCV
|
||||
Sections:
|
||||
- Name: .riscv.attributes
|
||||
Type: SHT_RISCV_ATTRIBUTES
|
@ -52,6 +52,8 @@
|
||||
#include "llvm/Support/LEB128.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/MipsABIFlags.h"
|
||||
#include "llvm/Support/RISCVAttributeParser.h"
|
||||
#include "llvm/Support/RISCVAttributes.h"
|
||||
#include "llvm/Support/ScopedPrinter.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm>
|
||||
@ -2678,6 +2680,7 @@ template <class ELFT> void ELFDumper<ELFT>::printArchSpecificInfo() {
|
||||
const ELFFile<ELFT> *Obj = ObjF->getELFFile();
|
||||
switch (Obj->getHeader()->e_machine) {
|
||||
case EM_ARM:
|
||||
case EM_RISCV:
|
||||
printAttributes();
|
||||
break;
|
||||
case EM_MIPS: {
|
||||
@ -2698,40 +2701,45 @@ template <class ELFT> void ELFDumper<ELFT>::printArchSpecificInfo() {
|
||||
}
|
||||
}
|
||||
|
||||
template <class ELFT> void ELFDumper<ELFT>::printAttributes() {
|
||||
W.startLine() << "Attributes not implemented.\n";
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
template <> void ELFDumper<ELF32LE>::printAttributes() {
|
||||
const ELFFile<ELF32LE> *Obj = ObjF->getELFFile();
|
||||
if (Obj->getHeader()->e_machine != EM_ARM) {
|
||||
template <class ELFT> void ELFDumper<ELFT>::printAttributes() {
|
||||
const ELFFile<ELFT> *Obj = ObjF->getELFFile();
|
||||
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.");
|
||||
|
||||
DictScope BA(W, "BuildAttributes");
|
||||
for (const ELFO::Elf_Shdr &Sec :
|
||||
unwrapOrError(ObjF->getFileName(), Obj->sections())) {
|
||||
if (Sec.sh_type != ELF::SHT_ARM_ATTRIBUTES)
|
||||
for (const auto &Sec : unwrapOrError(ObjF->getFileName(), Obj->sections())) {
|
||||
if (Sec.sh_type != ELF::SHT_ARM_ATTRIBUTES &&
|
||||
Sec.sh_type != ELF::SHT_RISCV_ATTRIBUTES)
|
||||
continue;
|
||||
|
||||
ArrayRef<uint8_t> Contents =
|
||||
unwrapOrError(ObjF->getFileName(), Obj->getSectionContents(&Sec));
|
||||
if (Contents[0] != ELFAttrs::Format_Version) {
|
||||
errs() << "unrecognised FormatVersion: 0x"
|
||||
<< Twine::utohexstr(Contents[0]) << '\n';
|
||||
reportWarning(createError(Twine("unrecognised FormatVersion: 0x") +
|
||||
Twine::utohexstr(Contents[0])),
|
||||
ObjF->getFileName());
|
||||
continue;
|
||||
}
|
||||
|
||||
W.printHex("FormatVersion", Contents[0]);
|
||||
if (Contents.size() == 1)
|
||||
continue;
|
||||
|
||||
// TODO: Print error and delete the redundant FormatVersion check above.
|
||||
if (Error E = ARMAttributeParser(&W).parse(Contents, support::little))
|
||||
consumeError(std::move(E));
|
||||
// TODO: Delete the redundant FormatVersion check above.
|
||||
if (Machine == EM_ARM) {
|
||||
if (Error E = ARMAttributeParser(&W).parse(Contents, support::little))
|
||||
reportWarning(std::move(E), ObjF->getFileName());
|
||||
} else if (Machine == EM_RISCV) {
|
||||
if (Error E = RISCVAttributeParser(&W).parse(Contents, support::little))
|
||||
reportWarning(std::move(E), ObjF->getFileName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3569,6 +3577,11 @@ static std::string getSectionTypeString(unsigned Arch, unsigned Type) {
|
||||
return "MIPS_ABIFLAGS";
|
||||
}
|
||||
break;
|
||||
case EM_RISCV:
|
||||
switch (Type) {
|
||||
case SHT_RISCV_ATTRIBUTES:
|
||||
return "RISCV_ATTRIBUTES";
|
||||
}
|
||||
}
|
||||
switch (Type) {
|
||||
case SHT_NULL:
|
||||
|
@ -40,9 +40,9 @@ TEST(AttributeHeaderParser, UnrecognizedFormatVersion) {
|
||||
testParseError(bytes, "unrecognized format-version: 0x1");
|
||||
}
|
||||
|
||||
TEST(AttributeHeaderParser, InvalidSubsectionLength) {
|
||||
TEST(AttributeHeaderParser, InvalidSectionLength) {
|
||||
static const uint8_t bytes[] = {'A', 3, 0, 0, 0};
|
||||
testParseError(bytes, "invalid subsection length 3 at offset 0x1");
|
||||
testParseError(bytes, "invalid section length 3 at offset 0x1");
|
||||
}
|
||||
|
||||
TEST(AttributeHeaderParser, UnrecognizedVendorName) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user