[llvm-readobj] - Teach llvm-readobj to dump .note.gnu.property sections.

NT_GNU_PROPERTY_TYPE_0 is a recently added type of .note.gnu.property
section specified in Linux Extensions to gABI.
(https://github.com/hjl-tools/linux-abi/wiki/Linux-Extensions-to-gABI)

Patch teach tool to print such notes properly.

Differential revision: https://reviews.llvm.org/D44469

llvm-svn: 328078
This commit is contained in:
George Rimar 2018-03-21 08:34:55 +00:00
parent f1fc25eb74
commit 6a14c02431
4 changed files with 149 additions and 1 deletions

View File

@ -1440,6 +1440,13 @@ enum {
NT_GNU_HWCAP = 2, NT_GNU_HWCAP = 2,
NT_GNU_BUILD_ID = 3, NT_GNU_BUILD_ID = 3,
NT_GNU_GOLD_VERSION = 4, NT_GNU_GOLD_VERSION = 4,
NT_GNU_PROPERTY_TYPE_0 = 5,
};
// Property types used in GNU_PROPERTY_TYPE_0 notes.
enum {
GNU_PROPERTY_STACK_SIZE = 1,
GNU_PROPERTY_NO_COPY_ON_PROTECTED = 2,
}; };
// AMDGPU specific notes. // AMDGPU specific notes.

View File

@ -0,0 +1,68 @@
// REQUIRES: x86-registered-target
// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t
// RUN: llvm-readobj -elf-output-style GNU --notes %t | FileCheck %s
// CHECK: Displaying notes found at file offset 0x00000040 with length 0x00000070:
// CHECK-NEXT: Owner Data size Description
// CHECK-NEXT: GNU 0x00000060 NT_GNU_PROPERTY_TYPE_0 (property note)
// CHECK-NEXT: Properties: stack size: 0x100
// CHECK-NEXT: stack size: 0x100
// CHECK-NEXT: no copy on protected
// CHECK-NEXT: <application-specific type 0xfefefefe>
// CHECK-NEXT: stack size: <corrupt length: 0x0>
// CHECK-NEXT: stack size: <corrupt length: 0x4>
// CHECK-NEXT: no copy on protected <corrupt length: 0x1>
// CHECK-NEXT: <corrupt type (0x2) datasz: 0x1>
.section ".note.gnu.property", "a"
.align 4
.long 4 /* Name length is always 4 ("GNU") */
.long end - begin /* Data length */
.long 5 /* Type: NT_GNU_PROPERTY_TYPE_0 */
.asciz "GNU" /* Name */
.p2align 3
begin:
.long 1 /* Type: GNU_PROPERTY_STACK_SIZE */
.long 8 /* Data size */
.quad 0x100 /* Data (stack size) */
.p2align 3 /* Align to 8 byte for 64 bit */
/* Test we handle alignment properly */
.long 1 /* Type: GNU_PROPERTY_STACK_SIZE */
.long 8 /* Data size */
.long 0x100 /* Data (stack size) */
.p2align 3 /* Align to 8 byte for 64 bit */
.long 2 /* Type: GNU_PROPERTY_NO_COPY_ON_PROTECTED */
.long 0 /* Data size */
.p2align 3 /* Align to 8 byte for 64 bit */
/* All notes below are broken. Test we are able to report them. */
/* Broken note type */
.long 0xfefefefe /* Invalid type for testing */
.long 0 /* Data size */
.p2align 3 /* Align to 8 byte for 64 bit */
/* GNU_PROPERTY_STACK_SIZE with zero stack size */
.long 1 /* Type: GNU_PROPERTY_STACK_SIZE */
.long 0 /* Data size */
.p2align 3 /* Align to 8 byte for 64 bit */
/* GNU_PROPERTY_STACK_SIZE with data size 4 (should be 8) */
.long 1 /* Type: GNU_PROPERTY_STACK_SIZE */
.long 4 /* Data size */
.long 0x100 /* Data (stack size) */
.p2align 3 /* Align to 8 byte for 64 bit */
/* GNU_PROPERTY_NO_COPY_ON_PROTECTED with pr_datasz and some data */
.long 2 /* Type: GNU_PROPERTY_NO_COPY_ON_PROTECTED */
.long 1 /* Data size (corrupted) */
.byte 1 /* Data */
.p2align 3 /* Align to 8 byte for 64 bit */
/* GNU_PROPERTY_NO_COPY_ON_PROTECTED with pr_datasz and without data */
.long 2 /* Type: GNU_PROPERTY_NO_COPY_ON_PROTECTED */
.long 1 /* Data size (corrupted) */
.p2align 3 /* Align to 8 byte for 64 bit */
end:

View File

@ -0,0 +1,22 @@
// REQUIRES: x86-registered-target
// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t
// RUN: llvm-readobj -elf-output-style GNU --notes %t | FileCheck %s
// CHECK: Displaying notes found at file offset 0x00000040 with length 0x00000014:
// CHECK-NEXT: Owner Data size Description
// CHECK-NEXT: GNU 0x00000004 NT_GNU_PROPERTY_TYPE_0 (property note)
// CHECK-NEXT: Properties:
// CHECK-NEXT: <corrupted GNU_PROPERTY_TYPE_0>
// Section below is broken, check we report that.
.section ".note.gnu.property", "a"
.align 4
.long 4 /* Name length is always 4 ("GNU") */
.long end - begin /* Data length */
.long 5 /* Type: NT_GNU_PROPERTY_TYPE_0 */
.asciz "GNU" /* Name */
.p2align 3
begin:
.long 1 /* Type: GNU_PROPERTY_STACK_SIZE */
end:

View File

@ -3412,6 +3412,7 @@ static std::string getGNUNoteTypeName(const uint32_t NT) {
{ELF::NT_GNU_HWCAP, "NT_GNU_HWCAP (DSO-supplied software HWCAP info)"}, {ELF::NT_GNU_HWCAP, "NT_GNU_HWCAP (DSO-supplied software HWCAP info)"},
{ELF::NT_GNU_BUILD_ID, "NT_GNU_BUILD_ID (unique build ID bitstring)"}, {ELF::NT_GNU_BUILD_ID, "NT_GNU_BUILD_ID (unique build ID bitstring)"},
{ELF::NT_GNU_GOLD_VERSION, "NT_GNU_GOLD_VERSION (gold version)"}, {ELF::NT_GNU_GOLD_VERSION, "NT_GNU_GOLD_VERSION (gold version)"},
{ELF::NT_GNU_PROPERTY_TYPE_0, "NT_GNU_PROPERTY_TYPE_0 (property note)"},
}; };
for (const auto &Note : Notes) for (const auto &Note : Notes)
@ -3475,9 +3476,36 @@ static std::string getAMDGPUNoteTypeName(const uint32_t NT) {
return OS.str(); return OS.str();
} }
template <typename ELFT>
static void printGNUProperty(raw_ostream &OS, uint32_t Type, uint32_t DataSize,
ArrayRef<uint8_t> Data) {
switch (Type) {
default:
OS << format(" <application-specific type 0x%x>\n", Type);
return;
case GNU_PROPERTY_STACK_SIZE: {
OS << " stack size: ";
if (DataSize == sizeof(typename ELFT::uint))
OS << format("0x%x\n",
(uint64_t)(*(const typename ELFT::Addr *)Data.data()));
else
OS << format("<corrupt length: 0x%x>\n", DataSize);
break;
}
case GNU_PROPERTY_NO_COPY_ON_PROTECTED:
OS << " no copy on protected";
if (DataSize)
OS << format(" <corrupt length: 0x%x>", DataSize);
OS << "\n";
break;
}
}
template <typename ELFT> template <typename ELFT>
static void printGNUNote(raw_ostream &OS, uint32_t NoteType, static void printGNUNote(raw_ostream &OS, uint32_t NoteType,
ArrayRef<typename ELFT::Word> Words, size_t Size) { ArrayRef<typename ELFT::Word> Words, size_t Size) {
using Elf_Word = typename ELFT::Word;
switch (NoteType) { switch (NoteType) {
default: default:
return; return;
@ -3509,8 +3537,31 @@ static void printGNUNote(raw_ostream &OS, uint32_t NoteType,
OS << " Version: " OS << " Version: "
<< StringRef(reinterpret_cast<const char *>(Words.data()), Size); << StringRef(reinterpret_cast<const char *>(Words.data()), Size);
break; break;
} case ELF::NT_GNU_PROPERTY_TYPE_0:
OS << " Properties:";
ArrayRef<uint8_t> Arr(reinterpret_cast<const uint8_t *>(Words.data()),
Size);
while (Arr.size() >= 8) {
uint32_t Type = *reinterpret_cast<const Elf_Word *>(Arr.data());
uint32_t DataSize = *reinterpret_cast<const Elf_Word *>(Arr.data() + 4);
Arr = Arr.drop_front(8);
// Take padding size into account if present.
uint64_t PaddedSize = alignTo(DataSize, sizeof(typename ELFT::uint));
if (Arr.size() < PaddedSize) {
OS << format(" <corrupt type (0x%x) datasz: 0x%x>\n", Type,
DataSize);
break;
}
printGNUProperty<ELFT>(OS, Type, DataSize, Arr.take_front(PaddedSize));
Arr = Arr.drop_front(PaddedSize);
}
if (!Arr.empty())
OS << " <corrupted GNU_PROPERTY_TYPE_0>";
break;
}
OS << '\n'; OS << '\n';
} }