[llvm-readelf] Print raw ELF note contents if we can't parse it

Currently, if the note name is known, but the value isn't we don't print
the contents.

Reviewed By: jhenderson

Differential Revision: https://reviews.llvm.org/D74367
This commit is contained in:
Alex Richardson 2021-02-09 16:21:25 +00:00
parent d613d8eb0e
commit 135df21248
6 changed files with 170 additions and 30 deletions

View File

@ -1,11 +1,15 @@
## Check that a malformed NT_GNU_ABI_TAG note can be dumped without crashing.
# RUN: yaml2obj %s -o %t
# RUN: llvm-readelf --notes %t | FileCheck %s --check-prefix=GNU
# RUN: llvm-readobj --elf-output-style LLVM --notes %t | FileCheck %s --check-prefix=LLVM
## GNU binutils does not print the raw description data when encountering an
## invalid NT_GNU_ABI_TAG, but in LLVM style we print it.
# GNU: Displaying notes found in: .note.ABI-tag
# GNU-NEXT: Owner Data size Description
# GNU-NEXT: GNU 0x00000004 NT_GNU_ABI_TAG (ABI version tag)
# GNU-NEXT: <corrupt GNU_ABI_TAG>
# GNU-EMPTY:
# LLVM: Notes [
# LLVM-NEXT: NoteSection {
@ -17,6 +21,9 @@
# LLVM-NEXT: Data size: 0x4
# LLVM-NEXT: Type: NT_GNU_ABI_TAG (ABI version tag)
# LLVM-NEXT: ABI: <corrupt GNU_ABI_TAG>
# LLVM-NEXT: Description data (
# LLVM-NEXT: 0000: 00000000 |....|
# LLVM-NEXT: )
# LLVM-NEXT: }
# LLVM-NEXT: }
# LLVM-NEXT: ]

View File

@ -11,16 +11,22 @@
# GNU-NEXT: Owner Data size Description
# GNU-NEXT: GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)
# GNU-NEXT: OS: Linux, ABI: 2.6.32
# GNU:Displaying notes found in: .note.gnu.build-id
# GNU-EMPTY:
# GNU-NEXT:Displaying notes found in: .note.gnu.build-id
# GNU-NEXT: Owner Data size Description
# GNU-NEXT: GNU 0x00000010 NT_GNU_BUILD_ID (unique build ID bitstring)
# GNU-NEXT: Build ID: 4fcb712aa6387724a9f465a32cd8c14b
# GNU:Displaying notes found in: .note.gnu.gold-version
# GNU-EMPTY:
# GNU-NEXT:Displaying notes found in: .note.gnu.gold-version
# GNU-NEXT: Owner Data size Description
# GNU-NEXT: GNU 0x00000009 NT_GNU_GOLD_VERSION (gold version)
# GNU-NEXT: Version: gold 1.11
# GNU-EMPTY:
# GNU-NEXT:Displaying notes found in: .note.gnu.unknown
# GNU-NEXT: Owner Data size Description
# GNU-NEXT: GNU 0x00000004 Unknown note type: (0x0000abcd)
# GNU-NEXT: description data: 61 62 63 64
# GNU-EMPTY:
# LLVM: Notes [
# LLVM-NEXT: NoteSection {
@ -57,6 +63,19 @@
# LLVM-NEXT: Version: gold 1.11
# LLVM-NEXT: }
# LLVM-NEXT: }
# LLVM-NEXT: NoteSection {
# LLVM-NEXT: Name: .note.gnu.unknown
# LLVM-NEXT: Offset: 0xD4
# LLVM-NEXT: Size: 0x14
# LLVM-NEXT: Note {
# LLVM-NEXT: Owner: GNU
# LLVM-NEXT: Data size: 0x4
# LLVM-NEXT: Type: Unknown (0x0000abcd)
# LLVM-NEXT: Description data (
# LLVM-NEXT: 0000: 61626364 |abcd|
# LLVM-NEXT: )
# LLVM-NEXT: }
# LLVM-NEXT: }
# LLVM-NEXT: ]
## Note: the section name is <?> here because the section header table is not present.
@ -103,6 +122,10 @@ Sections:
Type: SHT_NOTE
AddressAlign: 0x0000000000000004
Content: 040000000900000004000000474E5500676F6C6420312E3131000000
- Name: .note.gnu.unknown
Type: SHT_NOTE
AddressAlign: 0x0000000000000004
Content: 0400000004000000cdab0000474E550061626364
ProgramHeaders:
- Type: PT_NOTE
FileSize: 0x20
@ -119,7 +142,7 @@ ProgramHeaders:
# ERR1-GNU: Displaying notes found in: .note
# ERR1-GNU-NEXT: Owner Data size Description
# ERR1-GNU-NEXT: warning: '[[FILE]]': unable to read notes from the SHT_NOTE section with index 1: invalid offset (0xffff0000) or size (0x0)
# ERR1-GNU-NOT: {{.}}
# ERR1-GNU-EMPTY:
# ERR1-LLVM: Notes [
# ERR1-LLVM-NEXT: NoteSection {
@ -152,7 +175,7 @@ Sections:
# ERR2-GNU: Displaying notes found in: .note
# ERR2-GNU-NEXT: Owner Data size Description
# ERR2-GNU-NEXT: warning: '[[FILE]]': unable to read notes from the SHT_NOTE section with index 1: invalid offset (0x40) or size (0xffff0000)
# ERR2-GNU-NOT: {{.}}
# ERR2-GNU-EMPTY:
# ERR2-LLVM: Notes [
# ERR2-LLVM-NEXT: NoteSection {
@ -204,7 +227,7 @@ ProgramHeaders:
# ERR4-GNU: Displaying notes found at file offset 0x00000000 with length 0xffff0000:
# ERR4-GNU-NEXT: Owner Data size Description
# ERR4-GNU-NEXT: warning: '[[FILE]]': unable to read notes from the PT_NOTE segment with index 0: invalid offset (0x0) or size (0xffff0000)
# ERR4-GNU-NOT: {{.}}
# ERR4-GNU-EMPTY:
# ERR4-LLVM: Notes [
# ERR4-LLVM-NEXT: NoteSection {

View File

@ -26,6 +26,11 @@
// GNU-NEXT: Owner Data size Description
// GNU-NEXT: AMD 0x00000000 NT_AMD_AMDGPU_PAL_METADATA (PAL Metadata)
// GNU-EMPTY:
// GNU-NEXT: Displaying notes found in: .note.unknown
// GNU-NEXT: Owner Data size Description
// GNU-NEXT: AMD 0x00000007 Unknown note type: (0x000004d2)
// GNU-NEXT: description data: 61 62 63 64 65 66 00
// GNU-EMPTY:
// LLVM: Notes [
// LLVM-NEXT: NoteSection {
@ -72,6 +77,19 @@
// LLVM-NEXT: Type: NT_AMD_AMDGPU_PAL_METADATA (PAL Metadata)
// LLVM-NEXT: }
// LLVM-NEXT: }
// LLVM-NEXT: NoteSection {
// LLVM-NEXT: Name: .note.unknown
// LLVM-NEXT: Offset:
// LLVM-NEXT: Size:
// LLVM-NEXT: Note {
// LLVM-NEXT: Owner: AMD
// LLVM-NEXT: Data size: 0x7
// LLVM-NEXT: Type: Unknown (0x000004d2)
// LLVM-NEXT: Description data (
// LLVM-NEXT: 0000: 61626364 656600 |abcdef.|
// LLVM-NEXT: )
// LLVM-NEXT: }
// LLVM-NEXT: }
// LLVM-NEXT: ]
.section ".note.no.desc", "a"
@ -108,3 +126,13 @@ end.isa:
.long 0 /* descsz */
.long 12 /* type = NT_AMD_AMDGPU_PAL_METADATA */
.asciz "AMD"
.section ".note.unknown", "a"
.align 4
.long 4 /* namesz */
.long end.unknown_data - begin.unknown_data /* descsz */
.long 1234 /* type = unknown */
.asciz "AMD"
begin.unknown_data:
.asciz "abcdef"
end.unknown_data:
.align 4

View File

@ -21,6 +21,12 @@
# GNU-NEXT: .wavefront_size: 5
# GNU-NEXT: ...
# GNU-EMPTY:
# GNU-EMPTY:
# GNU-NEXT: Displaying notes found in: .note.bar
# GNU-NEXT: Owner Data size Description
# GNU-NEXT: AMDGPU 0x00000003 NT_AMDGPU_METADATA (AMDGPU Metadata)
# GNU-NEXT: description data: 12 34 56
# GNU-EMPTY:
# LLVM: Notes [
# LLVM-NEXT: NoteSection {
@ -48,7 +54,20 @@
# LLVM-EMPTY:
# LLVM-NEXT: }
# LLVM-NEXT: }
# LLVM-NEXT: ]
# LLVM-NEXT: NoteSection {
# LLVM-NEXT: Name: .note.bar
# LLVM-NEXT: Offset: 0x128
# LLVM-NEXT: Size: 0x18
# LLVM-NEXT: Note {
# LLVM-NEXT: Owner: AMDGPU
# LLVM-NEXT: Data size: 0x3
# LLVM-NEXT: Type: NT_AMDGPU_METADATA (AMDGPU Metadata)
# LLVM-NEXT: Description data (
# LLVM-NEXT: 0000: 123456 |.4V|
# LLVM-NEXT: )
# LLVM-NEXT: }
# LLVM-NEXT: }
# LLVM-NEXT:]
## Use yaml2obj instead of llvm-mc for more test portability. This was
## generated by grabbing section data from note-amdgpu.s and removing the amdhsa.version field.
@ -62,3 +81,13 @@ Sections:
- Name: .note.foo
Type: SHT_NOTE
Content: 07000000D400000020000000414D44475055000081ae616d646873612e6b65726e656c73918ab92e67726f75705f7365676d656e745f66697865645f73697a6502b62e6b65726e6172675f7365676d656e745f616c69676e04b52e6b65726e6172675f7365676d656e745f73697a6501b82e6d61785f666c61745f776f726b67726f75705f73697a6508a52e6e616d65a3666f6fbb2e707269766174655f7365676d656e745f66697865645f73697a6503ab2e736770725f636f756e7406a72e73796d626f6ca3666f6fab2e766770725f636f756e7407af2e7761766566726f6e745f73697a6505
- Name: .note.bar
Type: SHT_NOTE
Notes:
- Name: AMDGPU
Type: NT_AMDGPU_METADATA
Desc: '123456'
# TODO: https://bugs.llvm.org/show_bug.cgi?id=49034
# - Name: AMDGPU
# Type: NT_AMDGPU_METADATA
# Desc: 'abcdef'

View File

@ -22,6 +22,13 @@
# GNU-NEXT: - 1
# GNU-NEXT: - 0
# GNU-NEXT: ...
# GNU-EMPTY:
# GNU-EMPTY:
# GNU-NEXT: Displaying notes found in: .note.unknown
# GNU-NEXT: Owner Data size Description
# GNU-NEXT: AMDGPU 0x00000002 Unknown note type: (0x00000101)
# GNU-NEXT: description data: ab cd
# GNU-EMPTY:
# LLVM: Notes [
# LLVM-NEXT: NoteSection {
@ -51,6 +58,19 @@
# LLVM-EMPTY:
# LLVM-NEXT: }
# LLVM-NEXT: }
# LLVM-NEXT: NoteSection {
# LLVM-NEXT: Name: .note.unknown
# LLVM-NEXT: Offset: 0x13C
# LLVM-NEXT: Size: 0x18
# LLVM-NEXT: Note {
# LLVM-NEXT: Owner: AMDGPU
# LLVM-NEXT: Data size: 0x2
# LLVM-NEXT: Type: Unknown (0x00000101)
# LLVM-NEXT: Description data (
# LLVM-NEXT: 0000: ABCD |..|
# LLVM-NEXT: )
# LLVM-NEXT: }
# LLVM-NEXT: }
# LLVM-NEXT: ]
## Use yaml2obj instead of llvm-mc for more test portability. This was
@ -83,3 +103,9 @@ Sections:
- Name: .note.foo
Type: SHT_NOTE
Content: 07000000E600000020000000414D44475055000082AE616D646873612E6B65726E656C73918AB92E67726F75705F7365676D656E745F66697865645F73697A6502B62E6B65726E6172675F7365676D656E745F616C69676E04B52E6B65726E6172675F7365676D656E745F73697A6501B82E6D61785F666C61745F776F726B67726F75705F73697A6508A52E6E616D65A3666F6FBB2E707269766174655F7365676D656E745F66697865645F73697A6503AB2E736770725F636F756E7406A72E73796D626F6CA3666F6FAB2E766770725F636F756E7407AF2E7761766566726F6E745F73697A6505AE616D646873612E76657273696F6E9201000000
- Name: .note.unknown
Type: SHT_NOTE
Notes:
- Name: AMDGPU
Type: NT_GNU_BUILD_ATTRIBUTE_FUNC
Desc: 'abcd'

View File

@ -4877,11 +4877,12 @@ static StringRef getGNUGoldVersion(ArrayRef<uint8_t> Desc) {
}
template <typename ELFT>
static void printGNUNote(raw_ostream &OS, uint32_t NoteType,
static bool printGNUNote(raw_ostream &OS, uint32_t NoteType,
ArrayRef<uint8_t> Desc) {
// Return true if we were able to pretty-print the note, false otherwise.
switch (NoteType) {
default:
return;
return false;
case ELF::NT_GNU_ABI_TAG: {
const GNUAbiTag &AbiTag = getGNUAbiTag<ELFT>(Desc);
if (!AbiTag.IsValid)
@ -4904,6 +4905,7 @@ static void printGNUNote(raw_ostream &OS, uint32_t NoteType,
break;
}
OS << '\n';
return true;
}
struct AMDNote {
@ -4942,7 +4944,7 @@ static AMDGPUNote getAMDGPUNote(uint32_t NoteType, ArrayRef<uint8_t> Desc) {
StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size());
msgpack::Document MsgPackDoc;
if (!MsgPackDoc.readFromBlob(MsgPackString, /*Multi=*/false))
return {"AMDGPU Metadata", "Invalid AMDGPU Metadata"};
return {"", ""};
AMDGPU::HSAMD::V3::MetadataVerifier Verifier(true);
std::string HSAMetadataString;
@ -4950,8 +4952,14 @@ static AMDGPUNote getAMDGPUNote(uint32_t NoteType, ArrayRef<uint8_t> Desc) {
HSAMetadataString = "Invalid AMDGPU Metadata\n";
raw_string_ostream StrOS(HSAMetadataString);
if (MsgPackDoc.getRoot().isScalar()) {
// TODO: passing a scalar root to toYAML() asserts:
// (PolymorphicTraits<T>::getKind(Val) != NodeKind::Scalar &&
// "plain scalar documents are not supported")
// To avoid this crash we print the raw data instead.
return {"", ""};
}
MsgPackDoc.toYAML(StrOS);
return {"AMDGPU Metadata", StrOS.str()};
}
}
@ -5271,28 +5279,36 @@ template <class ELFT> void GNUELFDumper<ELFT>::printNotes() {
OS << "Unknown note type: (" << format_hex(Type, 10) << ")\n";
// Print the description, or fallback to printing raw bytes for unknown
// owners.
// owners/if we fail to pretty-print the contents.
if (Name == "GNU") {
printGNUNote<ELFT>(OS, Type, Descriptor);
if (printGNUNote<ELFT>(OS, Type, Descriptor))
return Error::success();
} else if (Name == "AMD") {
const AMDNote N = getAMDNote<ELFT>(Type, Descriptor);
if (!N.Type.empty())
if (!N.Type.empty()) {
OS << " " << N.Type << ":\n " << N.Value << '\n';
return Error::success();
}
} else if (Name == "AMDGPU") {
const AMDGPUNote N = getAMDGPUNote<ELFT>(Type, Descriptor);
if (!N.Type.empty())
if (!N.Type.empty()) {
OS << " " << N.Type << ":\n " << N.Value << '\n';
return Error::success();
}
} else if (Name == "CORE") {
if (Type == ELF::NT_FILE) {
DataExtractor DescExtractor(Descriptor,
ELFT::TargetEndianness == support::little,
sizeof(Elf_Addr));
if (Expected<CoreNote> NoteOrErr = readCoreNote(DescExtractor))
if (Expected<CoreNote> NoteOrErr = readCoreNote(DescExtractor)) {
printCoreNote<ELFT>(OS, *NoteOrErr);
else
return Error::success();
} else {
return NoteOrErr.takeError();
}
}
} else if (!Descriptor.empty()) {
}
if (!Descriptor.empty()) {
OS << " description data:";
for (uint8_t B : Descriptor)
OS << " " << format("%02x", B);
@ -6456,15 +6472,17 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printAddrsig() {
}
template <typename ELFT>
static void printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
static bool printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
ScopedPrinter &W) {
// Return true if we were able to pretty-print the note, false otherwise.
switch (NoteType) {
default:
return;
return false;
case ELF::NT_GNU_ABI_TAG: {
const GNUAbiTag &AbiTag = getGNUAbiTag<ELFT>(Desc);
if (!AbiTag.IsValid) {
W.printString("ABI", "<corrupt GNU_ABI_TAG>");
return false;
} else {
W.printString("OS", AbiTag.OSName);
W.printString("ABI", AbiTag.ABI);
@ -6484,6 +6502,7 @@ static void printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
W.printString(Property);
break;
}
return true;
}
static void printCoreNoteLLVMStyle(const CoreNote &Note, ScopedPrinter &W) {
@ -6531,28 +6550,36 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() {
"Unknown (" + to_string(format_hex(Type, 10)) + ")");
// Print the description, or fallback to printing raw bytes for unknown
// owners.
// owners/if we fail to pretty-print the contents.
if (Name == "GNU") {
printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W);
if (printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W))
return Error::success();
} else if (Name == "AMD") {
const AMDNote N = getAMDNote<ELFT>(Type, Descriptor);
if (!N.Type.empty())
if (!N.Type.empty()) {
W.printString(N.Type, N.Value);
return Error::success();
}
} else if (Name == "AMDGPU") {
const AMDGPUNote N = getAMDGPUNote<ELFT>(Type, Descriptor);
if (!N.Type.empty())
if (!N.Type.empty()) {
W.printString(N.Type, N.Value);
return Error::success();
}
} else if (Name == "CORE") {
if (Type == ELF::NT_FILE) {
DataExtractor DescExtractor(Descriptor,
ELFT::TargetEndianness == support::little,
sizeof(Elf_Addr));
if (Expected<CoreNote> Note = readCoreNote(DescExtractor))
printCoreNoteLLVMStyle(*Note, W);
else
return Note.takeError();
if (Expected<CoreNote> N = readCoreNote(DescExtractor)) {
printCoreNoteLLVMStyle(*N, W);
return Error::success();
} else {
return N.takeError();
}
}
} else if (!Descriptor.empty()) {
}
if (!Descriptor.empty()) {
W.printBinaryBlock("Description data", Descriptor);
}
return Error::success();