diff options
| -rw-r--r-- | llvm/include/llvm/BinaryFormat/ELF.h | 7 | ||||
| -rw-r--r-- | llvm/test/tools/llvm-readobj/note-gnu-property.s | 68 | ||||
| -rw-r--r-- | llvm/test/tools/llvm-readobj/note-gnu-property2.s | 22 | ||||
| -rw-r--r-- | llvm/tools/llvm-readobj/ELFDumper.cpp | 53 |
4 files changed, 149 insertions, 1 deletions
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index d04aac99e6e..1b811cc0612 100644 --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -1440,6 +1440,13 @@ enum { NT_GNU_HWCAP = 2, NT_GNU_BUILD_ID = 3, 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. diff --git a/llvm/test/tools/llvm-readobj/note-gnu-property.s b/llvm/test/tools/llvm-readobj/note-gnu-property.s new file mode 100644 index 00000000000..6fd69086612 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/note-gnu-property.s @@ -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: diff --git a/llvm/test/tools/llvm-readobj/note-gnu-property2.s b/llvm/test/tools/llvm-readobj/note-gnu-property2.s new file mode 100644 index 00000000000..fe6be0c9bcb --- /dev/null +++ b/llvm/test/tools/llvm-readobj/note-gnu-property2.s @@ -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: diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 8d62864f05c..b41d431fdc7 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -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_BUILD_ID, "NT_GNU_BUILD_ID (unique build ID bitstring)"}, {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) @@ -3476,8 +3477,35 @@ static std::string getAMDGPUNoteTypeName(const uint32_t NT) { } 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> static void printGNUNote(raw_ostream &OS, uint32_t NoteType, ArrayRef<typename ELFT::Word> Words, size_t Size) { + using Elf_Word = typename ELFT::Word; + switch (NoteType) { default: return; @@ -3509,8 +3537,31 @@ static void printGNUNote(raw_ostream &OS, uint32_t NoteType, OS << " Version: " << StringRef(reinterpret_cast<const char *>(Words.data()), Size); 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'; } |

