Skip to content

Commit a1984ec

Browse files
authored
[llvm-readobj][ELF][RISCV] Dump .note.gnu.property section contents (#125642)
RISCV Zicfilp/Zicfiss extensions uses the `.note.gnu.property` section to store flags indicating the adoption of features based on these extensions. This patch enables the llvm-readobj/llvm-readelf tools to dump these flags with the `--note` flag.
1 parent d21fc58 commit a1984ec

File tree

3 files changed

+95
-13
lines changed

3 files changed

+95
-13
lines changed

llvm/include/llvm/BinaryFormat/ELF.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1798,6 +1798,7 @@ enum : unsigned {
17981798
GNU_PROPERTY_AARCH64_FEATURE_1_AND = 0xc0000000,
17991799
GNU_PROPERTY_AARCH64_FEATURE_PAUTH = 0xc0000001,
18001800
GNU_PROPERTY_X86_FEATURE_1_AND = 0xc0000002,
1801+
GNU_PROPERTY_RISCV_FEATURE_1_AND = 0xc0000000,
18011802

18021803
GNU_PROPERTY_X86_UINT32_OR_LO = 0xc0008000,
18031804
GNU_PROPERTY_X86_FEATURE_2_NEEDED = GNU_PROPERTY_X86_UINT32_OR_LO + 1,
@@ -1862,6 +1863,13 @@ enum : unsigned {
18621863
GNU_PROPERTY_X86_ISA_1_V4 = 1 << 3,
18631864
};
18641865

1866+
// RISC-V processor feature bits.
1867+
enum : unsigned {
1868+
GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED = 1 << 0,
1869+
GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS = 1 << 1,
1870+
GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG = 1 << 2,
1871+
};
1872+
18651873
// FreeBSD note types.
18661874
enum {
18671875
NT_FREEBSD_ABI_TAG = 1,
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# RUN: yaml2obj %s -DBITS=32 -DPR_PADDING= -o %t1
2+
# RUN: llvm-readelf --notes %t1 | FileCheck %s --check-prefix=GNU
3+
# RUN: llvm-readobj --notes %t1 | FileCheck %s --check-prefix=LLVM
4+
5+
# RUN: yaml2obj %s -DBITS=64 -DPR_PADDING=00000000 -o %t2
6+
# RUN: llvm-readelf --notes %t2 | FileCheck %s --check-prefix=GNU
7+
# RUN: llvm-readobj --notes %t2 | FileCheck %s --check-prefix=LLVM
8+
9+
# GNU: Displaying notes found in: .note.gnu.property
10+
# GNU-NEXT: Owner Data size Description
11+
# GNU-NEXT: GNU 0x{{([0-9a-z]{8})}} NT_GNU_PROPERTY_TYPE_0 (property note)
12+
# GNU-NEXT: Properties: RISC-V feature: ZICFILP-unlabeled, ZICFISS, ZICFILP-func-sig
13+
14+
# LLVM: NoteSections [
15+
# LLVM-NEXT: NoteSection {
16+
# LLVM-NEXT: Name: .note.gnu.property
17+
# LLVM-NEXT: Offset:
18+
# LLVM-NEXT: Size:
19+
# LLVM-NEXT: Notes [
20+
# LLVM-NEXT: {
21+
# LLVM-NEXT: Owner: GNU
22+
# LLVM-NEXT: Data size:
23+
# LLVM-NEXT: Type: NT_GNU_PROPERTY_TYPE_0 (property note)
24+
# LLVM-NEXT: Property [
25+
# LLVM-NEXT: RISC-V feature: ZICFILP-unlabeled, ZICFISS, ZICFILP-func-sig
26+
# LLVM-NEXT: ]
27+
# LLVM-NEXT: }
28+
# LLVM-NEXT: ]
29+
# LLVM-NEXT: }
30+
# LLVM-NEXT: ]
31+
32+
--- !ELF
33+
FileHeader:
34+
Class: ELFCLASS[[BITS]]
35+
Data: ELFDATA2LSB
36+
Type: ET_REL
37+
Machine: EM_RISCV
38+
Sections:
39+
- Name: .note.gnu.property
40+
Type: SHT_NOTE
41+
Flags: [ SHF_ALLOC ]
42+
Notes:
43+
- Name: 'GNU'
44+
Desc: '000000c00400000007000000[[PR_PADDING]]'
45+
Type: 5 # NT_GNU_PROPERTY_TYPE_0

llvm/tools/llvm-readobj/ELFDumper.cpp

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5333,7 +5333,8 @@ static bool printAArch64PAuthABICoreInfo(raw_ostream &OS, uint32_t DataSize,
53335333

53345334
template <typename ELFT>
53355335
static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
5336-
ArrayRef<uint8_t> Data) {
5336+
ArrayRef<uint8_t> Data,
5337+
typename ELFT::Half EMachine) {
53375338
std::string str;
53385339
raw_string_ostream OS(str);
53395340
uint32_t PrData;
@@ -5366,8 +5367,25 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
53665367
return str;
53675368
case GNU_PROPERTY_AARCH64_FEATURE_1_AND:
53685369
case GNU_PROPERTY_X86_FEATURE_1_AND:
5369-
OS << ((Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) ? "aarch64 feature: "
5370-
: "x86 feature: ");
5370+
static_assert(GNU_PROPERTY_AARCH64_FEATURE_1_AND ==
5371+
GNU_PROPERTY_RISCV_FEATURE_1_AND,
5372+
"GNU_PROPERTY_RISCV_FEATURE_1_AND should equal "
5373+
"GNU_PROPERTY_AARCH64_FEATURE_1_AND, otherwise "
5374+
"GNU_PROPERTY_RISCV_FEATURE_1_AND would be skipped!");
5375+
5376+
if (EMachine == EM_AARCH64 && Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
5377+
OS << "aarch64 feature: ";
5378+
} else if (EMachine == EM_RISCV &&
5379+
Type == GNU_PROPERTY_RISCV_FEATURE_1_AND) {
5380+
OS << "RISC-V feature: ";
5381+
} else if ((EMachine == EM_386 || EMachine == EM_X86_64) &&
5382+
Type == GNU_PROPERTY_X86_FEATURE_1_AND) {
5383+
OS << "x86 feature: ";
5384+
} else {
5385+
OS << format("<application-specific type 0x%x>", Type);
5386+
return str;
5387+
}
5388+
53715389
if (DataSize != 4) {
53725390
OS << format("<corrupt length: 0x%x>", DataSize);
53735391
return str;
@@ -5377,10 +5395,16 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
53775395
OS << "<None>";
53785396
return str;
53795397
}
5380-
if (Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
5398+
5399+
if (EMachine == EM_AARCH64) {
53815400
DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_BTI, "BTI");
53825401
DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_PAC, "PAC");
53835402
DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_GCS, "GCS");
5403+
} else if (EMachine == EM_RISCV) {
5404+
DumpBit(GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED,
5405+
"ZICFILP-unlabeled");
5406+
DumpBit(GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS, "ZICFISS");
5407+
DumpBit(GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG, "ZICFILP-func-sig");
53845408
} else {
53855409
DumpBit(GNU_PROPERTY_X86_FEATURE_1_IBT, "IBT");
53865410
DumpBit(GNU_PROPERTY_X86_FEATURE_1_SHSTK, "SHSTK");
@@ -5441,7 +5465,8 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
54415465
}
54425466

54435467
template <typename ELFT>
5444-
static SmallVector<std::string, 4> getGNUPropertyList(ArrayRef<uint8_t> Arr) {
5468+
static SmallVector<std::string, 4>
5469+
getGNUPropertyList(ArrayRef<uint8_t> Arr, typename ELFT::Half EMachine) {
54455470
using Elf_Word = typename ELFT::Word;
54465471

54475472
SmallVector<std::string, 4> Properties;
@@ -5459,8 +5484,8 @@ static SmallVector<std::string, 4> getGNUPropertyList(ArrayRef<uint8_t> Arr) {
54595484
Properties.push_back(str);
54605485
break;
54615486
}
5462-
Properties.push_back(
5463-
getGNUProperty<ELFT>(Type, DataSize, Arr.take_front(PaddedSize)));
5487+
Properties.push_back(getGNUProperty<ELFT>(
5488+
Type, DataSize, Arr.take_front(PaddedSize), EMachine));
54645489
Arr = Arr.drop_front(PaddedSize);
54655490
}
54665491

@@ -5512,7 +5537,7 @@ static StringRef getDescAsStringRef(ArrayRef<uint8_t> Desc) {
55125537

55135538
template <typename ELFT>
55145539
static bool printGNUNote(raw_ostream &OS, uint32_t NoteType,
5515-
ArrayRef<uint8_t> Desc) {
5540+
ArrayRef<uint8_t> Desc, typename ELFT::Half EMachine) {
55165541
// Return true if we were able to pretty-print the note, false otherwise.
55175542
switch (NoteType) {
55185543
default:
@@ -5534,7 +5559,7 @@ static bool printGNUNote(raw_ostream &OS, uint32_t NoteType,
55345559
break;
55355560
case ELF::NT_GNU_PROPERTY_TYPE_0:
55365561
OS << " Properties:";
5537-
for (const std::string &Property : getGNUPropertyList<ELFT>(Desc))
5562+
for (const std::string &Property : getGNUPropertyList<ELFT>(Desc, EMachine))
55385563
OS << " " << Property << "\n";
55395564
break;
55405565
}
@@ -6223,10 +6248,12 @@ template <class ELFT> void GNUELFDumper<ELFT>::printNotes() {
62236248
else
62246249
OS << "Unknown note type: (" << format_hex(Type, 10) << ")\n";
62256250

6251+
const typename ELFT::Half EMachine = this->Obj.getHeader().e_machine;
6252+
62266253
// Print the description, or fallback to printing raw bytes for unknown
62276254
// owners/if we fail to pretty-print the contents.
62286255
if (Name == "GNU") {
6229-
if (printGNUNote<ELFT>(OS, Type, Descriptor))
6256+
if (printGNUNote<ELFT>(OS, Type, Descriptor, EMachine))
62306257
return Error::success();
62316258
} else if (Name == "FreeBSD") {
62326259
if (std::optional<FreeBSDNote> N =
@@ -7913,7 +7940,8 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printAddrsig() {
79137940

79147941
template <typename ELFT>
79157942
static bool printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
7916-
ScopedPrinter &W) {
7943+
ScopedPrinter &W,
7944+
typename ELFT::Half EMachine) {
79177945
// Return true if we were able to pretty-print the note, false otherwise.
79187946
switch (NoteType) {
79197947
default:
@@ -7938,7 +7966,7 @@ static bool printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
79387966
break;
79397967
case ELF::NT_GNU_PROPERTY_TYPE_0:
79407968
ListScope D(W, "Property");
7941-
for (const std::string &Property : getGNUPropertyList<ELFT>(Desc))
7969+
for (const std::string &Property : getGNUPropertyList<ELFT>(Desc, EMachine))
79427970
W.printString(Property);
79437971
break;
79447972
}
@@ -8057,10 +8085,11 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() {
80578085
W.printString("Type",
80588086
"Unknown (" + to_string(format_hex(Type, 10)) + ")");
80598087

8088+
const typename ELFT::Half EMachine = this->Obj.getHeader().e_machine;
80608089
// Print the description, or fallback to printing raw bytes for unknown
80618090
// owners/if we fail to pretty-print the contents.
80628091
if (Name == "GNU") {
8063-
if (printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W))
8092+
if (printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W, EMachine))
80648093
return Error::success();
80658094
} else if (Name == "FreeBSD") {
80668095
if (std::optional<FreeBSDNote> N =

0 commit comments

Comments
 (0)