Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions llvm/include/llvm/BinaryFormat/ELF.h
Original file line number Diff line number Diff line change
Expand Up @@ -1798,6 +1798,7 @@ enum : unsigned {
GNU_PROPERTY_AARCH64_FEATURE_1_AND = 0xc0000000,
GNU_PROPERTY_AARCH64_FEATURE_PAUTH = 0xc0000001,
GNU_PROPERTY_X86_FEATURE_1_AND = 0xc0000002,
GNU_PROPERTY_RISCV_FEATURE_1_AND = 0xc0000000,

GNU_PROPERTY_X86_UINT32_OR_LO = 0xc0008000,
GNU_PROPERTY_X86_FEATURE_2_NEEDED = GNU_PROPERTY_X86_UINT32_OR_LO + 1,
Expand Down Expand Up @@ -1862,6 +1863,13 @@ enum : unsigned {
GNU_PROPERTY_X86_ISA_1_V4 = 1 << 3,
};

// RISC-V processor feature bits.
enum : unsigned {
GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED = 1 << 0,
GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS = 1 << 1,
GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG = 1 << 2,
};

// FreeBSD note types.
enum {
NT_FREEBSD_ABI_TAG = 1,
Expand Down
45 changes: 45 additions & 0 deletions llvm/test/tools/llvm-readobj/ELF/RISCV/note-gnu-property.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# RUN: yaml2obj %s -DBITS=32 -DPR_PADDING= -o %t1
# RUN: llvm-readelf --notes %t1 | FileCheck %s --check-prefix=GNU
# RUN: llvm-readobj --notes %t1 | FileCheck %s --check-prefix=LLVM

# RUN: yaml2obj %s -DBITS=64 -DPR_PADDING=00000000 -o %t2
# RUN: llvm-readelf --notes %t2 | FileCheck %s --check-prefix=GNU
# RUN: llvm-readobj --notes %t2 | FileCheck %s --check-prefix=LLVM

# GNU: Displaying notes found in: .note.gnu.property
# GNU-NEXT: Owner Data size Description
# GNU-NEXT: GNU 0x{{([0-9a-z]{8})}} NT_GNU_PROPERTY_TYPE_0 (property note)
# GNU-NEXT: Properties: RISC-V feature: ZICFILP-unlabeled, ZICFISS, ZICFILP-func-sig

# LLVM: NoteSections [
# LLVM-NEXT: NoteSection {
# LLVM-NEXT: Name: .note.gnu.property
# LLVM-NEXT: Offset:
# LLVM-NEXT: Size:
# LLVM-NEXT: Notes [
# LLVM-NEXT: {
# LLVM-NEXT: Owner: GNU
# LLVM-NEXT: Data size:
# LLVM-NEXT: Type: NT_GNU_PROPERTY_TYPE_0 (property note)
# LLVM-NEXT: Property [
# LLVM-NEXT: RISC-V feature: ZICFILP-unlabeled, ZICFISS, ZICFILP-func-sig
# LLVM-NEXT: ]
# LLVM-NEXT: }
# LLVM-NEXT: ]
# LLVM-NEXT: }
# LLVM-NEXT: ]

--- !ELF
FileHeader:
Class: ELFCLASS[[BITS]]
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_RISCV
Sections:
- Name: .note.gnu.property
Type: SHT_NOTE
Flags: [ SHF_ALLOC ]
Notes:
- Name: 'GNU'
Desc: '000000c00400000007000000[[PR_PADDING]]'
Type: 5 # NT_GNU_PROPERTY_TYPE_0
55 changes: 42 additions & 13 deletions llvm/tools/llvm-readobj/ELFDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5333,7 +5333,8 @@ static bool printAArch64PAuthABICoreInfo(raw_ostream &OS, uint32_t DataSize,

template <typename ELFT>
static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
ArrayRef<uint8_t> Data) {
ArrayRef<uint8_t> Data,
typename ELFT::Half EMachine) {
std::string str;
raw_string_ostream OS(str);
uint32_t PrData;
Expand Down Expand Up @@ -5366,8 +5367,25 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
return str;
case GNU_PROPERTY_AARCH64_FEATURE_1_AND:
case GNU_PROPERTY_X86_FEATURE_1_AND:
OS << ((Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) ? "aarch64 feature: "
: "x86 feature: ");
static_assert(GNU_PROPERTY_AARCH64_FEATURE_1_AND ==
GNU_PROPERTY_RISCV_FEATURE_1_AND,
"GNU_PROPERTY_RISCV_FEATURE_1_AND should equal "
"GNU_PROPERTY_AARCH64_FEATURE_1_AND, otherwise "
"GNU_PROPERTY_RISCV_FEATURE_1_AND would be skipped!");

if (EMachine == EM_AARCH64 && Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
OS << "aarch64 feature: ";
} else if (EMachine == EM_RISCV &&
Type == GNU_PROPERTY_RISCV_FEATURE_1_AND) {
OS << "RISC-V feature: ";
} else if ((EMachine == EM_386 || EMachine == EM_X86_64) &&
Type == GNU_PROPERTY_X86_FEATURE_1_AND) {
OS << "x86 feature: ";
} else {
OS << format("<application-specific type 0x%x>", Type);
return str;
}

if (DataSize != 4) {
OS << format("<corrupt length: 0x%x>", DataSize);
return str;
Expand All @@ -5377,10 +5395,16 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
OS << "<None>";
return str;
}
if (Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {

if (EMachine == EM_AARCH64) {
DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_BTI, "BTI");
DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_PAC, "PAC");
DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_GCS, "GCS");
} else if (EMachine == EM_RISCV) {
DumpBit(GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED,
"ZICFILP-unlabeled");
DumpBit(GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS, "ZICFISS");
DumpBit(GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG, "ZICFILP-func-sig");
} else {
DumpBit(GNU_PROPERTY_X86_FEATURE_1_IBT, "IBT");
DumpBit(GNU_PROPERTY_X86_FEATURE_1_SHSTK, "SHSTK");
Expand Down Expand Up @@ -5441,7 +5465,8 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
}

template <typename ELFT>
static SmallVector<std::string, 4> getGNUPropertyList(ArrayRef<uint8_t> Arr) {
static SmallVector<std::string, 4>
getGNUPropertyList(ArrayRef<uint8_t> Arr, typename ELFT::Half EMachine) {
using Elf_Word = typename ELFT::Word;

SmallVector<std::string, 4> Properties;
Expand All @@ -5459,8 +5484,8 @@ static SmallVector<std::string, 4> getGNUPropertyList(ArrayRef<uint8_t> Arr) {
Properties.push_back(str);
break;
}
Properties.push_back(
getGNUProperty<ELFT>(Type, DataSize, Arr.take_front(PaddedSize)));
Properties.push_back(getGNUProperty<ELFT>(
Type, DataSize, Arr.take_front(PaddedSize), EMachine));
Arr = Arr.drop_front(PaddedSize);
}

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

template <typename ELFT>
static bool printGNUNote(raw_ostream &OS, uint32_t NoteType,
ArrayRef<uint8_t> Desc) {
ArrayRef<uint8_t> Desc, typename ELFT::Half EMachine) {
// Return true if we were able to pretty-print the note, false otherwise.
switch (NoteType) {
default:
Expand All @@ -5534,7 +5559,7 @@ static bool printGNUNote(raw_ostream &OS, uint32_t NoteType,
break;
case ELF::NT_GNU_PROPERTY_TYPE_0:
OS << " Properties:";
for (const std::string &Property : getGNUPropertyList<ELFT>(Desc))
for (const std::string &Property : getGNUPropertyList<ELFT>(Desc, EMachine))
OS << " " << Property << "\n";
break;
}
Expand Down Expand Up @@ -6223,10 +6248,12 @@ template <class ELFT> void GNUELFDumper<ELFT>::printNotes() {
else
OS << "Unknown note type: (" << format_hex(Type, 10) << ")\n";

const typename ELFT::Half EMachine = this->Obj.getHeader().e_machine;

// Print the description, or fallback to printing raw bytes for unknown
// owners/if we fail to pretty-print the contents.
if (Name == "GNU") {
if (printGNUNote<ELFT>(OS, Type, Descriptor))
if (printGNUNote<ELFT>(OS, Type, Descriptor, EMachine))
return Error::success();
} else if (Name == "FreeBSD") {
if (std::optional<FreeBSDNote> N =
Expand Down Expand Up @@ -7913,7 +7940,8 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printAddrsig() {

template <typename ELFT>
static bool printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
ScopedPrinter &W) {
ScopedPrinter &W,
typename ELFT::Half EMachine) {
// Return true if we were able to pretty-print the note, false otherwise.
switch (NoteType) {
default:
Expand All @@ -7938,7 +7966,7 @@ static bool printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
break;
case ELF::NT_GNU_PROPERTY_TYPE_0:
ListScope D(W, "Property");
for (const std::string &Property : getGNUPropertyList<ELFT>(Desc))
for (const std::string &Property : getGNUPropertyList<ELFT>(Desc, EMachine))
W.printString(Property);
break;
}
Expand Down Expand Up @@ -8057,10 +8085,11 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() {
W.printString("Type",
"Unknown (" + to_string(format_hex(Type, 10)) + ")");

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