diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -1360,6 +1360,10 @@ // SHT_NOTE section types enum { + NT_FREEBSD_ABI_TAG = 1, + NT_FREEBSD_NOINIT_TAG = 2, + NT_FREEBSD_ARCH_TAG = 3, + NT_FREEBSD_FEATURE_CTL = 4, NT_FREEBSD_THRMISC = 7, NT_FREEBSD_PROCSTAT_PROC = 8, NT_FREEBSD_PROCSTAT_FILES = 9, diff --git a/llvm/test/tools/llvm-readobj/ELF/note-freebsd-core.test b/llvm/test/tools/llvm-readobj/ELF/note-freebsd-core.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/note-freebsd-core.test @@ -0,0 +1,97 @@ +## Test that note values are interpreted correctly for FreeBSD binaries files. +# RUN: yaml2obj %s > %t.o +# RUN: llvm-readelf --notes %t.o +# RUN: llvm-readobj --notes %t.o +# RUN: llvm-readelf --notes %t.o | FileCheck %s --check-prefix=GNU --strict-whitespace +# RUN: llvm-readobj --notes %t.o | FileCheck %s --check-prefix=LLVM --strict-whitespace + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_CORE + Machine: EM_RISCV +Sections: + - Name: .note.foo + Type: SHT_NOTE + Notes: + - Name: FreeBSD + Desc: '' + Type: 0x00000007 # NT_FREEBSD_THRMISC + - Name: FreeBSD + Desc: '' + Type: 0x00000008 # NT_FREEBSD_PROC + - Name: .note.bar + Type: SHT_NOTE + Notes: + - Name: FreeBSD + Desc: '' + Type: 0x00000009 # NT_FREEBSD_FILES + - Name: .note.baz + Type: SHT_NOTE + Notes: + - Name: FreeBSD + Desc: '4c6f72656d20697073756d20646f6c6f722073697420616d65740a00' + Type: 0x00000003 +ProgramHeaders: + - Type: PT_NOTE + Sections: + - Section: .note.foo + - Type: PT_NOTE + Sections: + - Section: .note.bar + - Type: PT_NOTE + Sections: + - Section: .note.baz + +# GNU: Displaying notes found at file offset +# GNU-NEXT: Owner Data size Description +# GNU-NEXT: FreeBSD 0x00000000 NT_THRMISC (thrmisc structure) +# GNU-NEXT: FreeBSD 0x00000000 NT_PROCSTAT_PROC (proc data) +# GNU-NEXT: Displaying notes found at file offset +# GNU-NEXT: Owner Data size Description +# GNU-NEXT: FreeBSD 0x00000000 NT_PROCSTAT_FILES (files data) +# GNU-NEXT: Displaying notes found at file offset +# GNU-NEXT: Owner Data size Description +# GNU-NEXT: FreeBSD 0x0000001c Unknown note type: (0x00000003) +# GNU-NEXT: Description data: 4c 6f 72 65 6d 20 69 70 73 75 6d 20 64 6f 6c 6f 72 20 73 69 74 20 61 6d 65 74 0a 00 +# GNU-EMPTY: + +# LLVM: Notes [ +# LLVM-NEXT: NoteSection { +# LLVM-NEXT: Offset: +# LLVM-NEXT: Size: +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: FreeBSD +# LLVM-NEXT: Data size: 0x0 +# LLVM-NEXT: Type: NT_THRMISC (thrmisc structure) +# LLVM-NEXT: } +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: FreeBSD +# LLVM-NEXT: Data size: 0x0 +# LLVM-NEXT: Type: NT_PROCSTAT_PROC (proc data) +# LLVM-NEXT: } +# LLVM-NEXT: } +# LLVM-NEXT: NoteSection { +# LLVM-NEXT: Offset: 0x110 +# LLVM-NEXT: Size: 0x14 +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: FreeBSD +# LLVM-NEXT: Data size: 0x0 +# LLVM-NEXT: Type: NT_PROCSTAT_FILES (files data) +# LLVM-NEXT: } +# LLVM-NEXT: } +# LLVM-NEXT: NoteSection { +# LLVM-NEXT: Offset: 0x124 +# LLVM-NEXT: Size: 0x30 +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: FreeBSD +# LLVM-NEXT: Data size: 0x1C +# LLVM-NEXT: Type: Unknown note type: (0x00000003) +# LLVM-NEXT: Description data ( +# LLVM-NEXT: 0000: 4C6F7265 6D206970 73756D20 646F6C6F |Lorem ipsum dolo| +# LLVM-NEXT: 0010: 72207369 7420616D 65740A00 |r sit amet..| +# LLVM-NEXT: ) +# LLVM-NEXT: } +# LLVM-NEXT: } +# LLVM-NEXT: ] diff --git a/llvm/test/tools/llvm-readobj/ELF/note-freebsd.s b/llvm/test/tools/llvm-readobj/ELF/note-freebsd.s deleted file mode 100644 --- a/llvm/test/tools/llvm-readobj/ELF/note-freebsd.s +++ /dev/null @@ -1,83 +0,0 @@ -// REQUIRES: x86-registered-target -// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t.o - -// RUN: llvm-readobj --notes %t.o | FileCheck %s --check-prefix=LLVM -// RUN: llvm-readelf --notes %t.o | FileCheck %s --check-prefix=GNU - -// GNU: Displaying notes found -// GNU-NEXT: Owner Data size Description -// GNU-NEXT: FreeBSD 0x00000000 NT_THRMISC (thrmisc structure) -// GNU-NEXT: FreeBSD 0x00000000 NT_PROCSTAT_PROC (proc data) -// GNU-NEXT: Displaying notes found -// GNU-NEXT: Owner Data size Description -// GNU-NEXT: FreeBSD 0x00000000 NT_PROCSTAT_FILES (files data) -// GNU-NEXT: Displaying notes found -// GNU-NEXT: Owner Data size Description -// GNU-NEXT: FreeBSD 0x0000001c Unknown note type: (0x00000003) -// GNU-NEXT: Description data: 4c 6f 72 65 6d 20 69 70 73 75 6d 20 64 6f 6c 6f 72 20 73 69 74 20 61 6d 65 74 00 00 - -// LLVM: Notes [ -// LLVM-NEXT: NoteSection { -// LLVM-NEXT: Offset: -// LLVM-NEXT: Size: -// LLVM-NEXT: Note { -// LLVM-NEXT: Owner: FreeBSD -// LLVM-NEXT: Data size: 0x0 -// LLVM-NEXT: Type: NT_THRMISC (thrmisc structure) -// LLVM-NEXT: } -// LLVM-NEXT: Note { -// LLVM-NEXT: Owner: FreeBSD -// LLVM-NEXT: Data size: 0x0 -// LLVM-NEXT: Type: NT_PROCSTAT_PROC (proc data) -// LLVM-NEXT: } -// LLVM-NEXT: } -// LLVM-NEXT: NoteSection { -// LLVM-NEXT: Offset: 0x68 -// LLVM-NEXT: Size: 0x14 -// LLVM-NEXT: Note { -// LLVM-NEXT: Owner: FreeBSD -// LLVM-NEXT: Data size: 0x0 -// LLVM-NEXT: Type: NT_PROCSTAT_FILES (files data) -// LLVM-NEXT: } -// LLVM-NEXT: } -// LLVM-NEXT: NoteSection { -// LLVM-NEXT: Offset: 0x7C -// LLVM-NEXT: Size: 0x30 -// LLVM-NEXT: Note { -// LLVM-NEXT: Owner: FreeBSD -// LLVM-NEXT: Data size: 0x1C -// LLVM-NEXT: Type: Unknown note type: (0x00000003) -// LLVM-NEXT: Description data ( -// LLVM-NEXT: 0000: 4C6F7265 6D206970 73756D20 646F6C6F |Lorem ipsum dolo| -// LLVM-NEXT: 0010: 72207369 7420616D 65740000 |r sit amet..| -// LLVM-NEXT: ) -// LLVM-NEXT: } -// LLVM-NEXT: } -// LLVM-NEXT: ] - -.section ".note.foo", "a" - .align 4 - .long 8 /* namesz */ - .long 0 /* descsz */ - .long 7 /* type = NT_FREEBSD_THRMISC */ - .asciz "FreeBSD" - .long 8 /* namesz */ - .long 0 /* descsz */ - .long 8 /* type = NT_FREEBSD_PROC */ - .asciz "FreeBSD" -.section ".note.bar", "a" - .align 4 - .long 8 /* namesz */ - .long 0 /* descsz */ - .long 9 /* type = NT_FREEBSD_FILES */ - .asciz "FreeBSD" -.section ".note.baz", "a" - .align 4 - .long 8 /* namesz */ - .long end - begin /* descsz */ - .long 3 /* type */ - .asciz "FreeBSD" -begin: - .asciz "Lorem ipsum dolor sit amet" - .align 4 -end: diff --git a/llvm/test/tools/llvm-readobj/ELF/note-freebsd.test b/llvm/test/tools/llvm-readobj/ELF/note-freebsd.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/note-freebsd.test @@ -0,0 +1,82 @@ +## Test that note values are interpreted correctly for FreeBSD binaries files. +# RUN: yaml2obj %s > %t.o +# RUN: llvm-readobj --notes %t.o +# RUN: llvm-readelf --notes %t.o | FileCheck %s --check-prefix=GNU --strict-whitespace +# RUN: llvm-readobj --notes %t.o | FileCheck %s --check-prefix=LLVM --strict-whitespace + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_RISCV +Sections: + - Name: .note.tag + Type: SHT_NOTE + Flags: [ SHF_ALLOC ] + Address: 0x0000000000010270 + AddressAlign: 0x0000000000000004 + Notes: + - Name: FreeBSD + Desc: 6CD61300 + Type: 0x00000001 + - Name: FreeBSD + Desc: '00000000' + Type: 0x00000004 + - Name: FreeBSD + Desc: '00000000' + Type: 0x00000002 + - Name: FreeBSD + Desc: '616263646566' + Type: 0xabcdef + + +# GNU: Displaying notes found at file offset 0x00000040 with length 0x00000064: +# GNU-NEXT: Owner Data size Description +# GNU-NEXT: FreeBSD 0x00000004 NT_FREEBSD_ABI_TAG (ABI version tag) +# GNU-NEXT: ABI: 1300076 +# GNU-NEXT: FreeBSD 0x00000004 NT_FREEBSD_FEATURE_CTL (FreeBSD feature control) +# GNU-NEXT: Feature flags: 0x0 +# GNU-NEXT: FreeBSD 0x00000004 NT_FREEBSD_NOINIT_TAG (no .init tag) +# GNU-NEXT: Description data: 00 00 00 00 +# GNU-NEXT: FreeBSD 0x00000006 Unknown note type: (0x00abcdef) +# GNU-NEXT: Description data: 61 62 63 64 65 66 +# GNU-EMPTY: + +# LLVM: Notes [ +# LLVM-NEXT: NoteSection { +# LLVM-NEXT: Offset: 0x40 +# LLVM-NEXT: Size: 0x64 +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: FreeBSD +# LLVM-NEXT: Data size: 0x4 +# LLVM-NEXT: Type: NT_FREEBSD_ABI_TAG (ABI version tag) +# LLVM-NEXT: ABI: 1300076 +# LLVM-NEXT: } +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: FreeBSD +# LLVM-NEXT: Data size: 0x4 +# LLVM-NEXT: Type: NT_FREEBSD_FEATURE_CTL (FreeBSD feature control) +# LLVM-NEXT: Flags: 0x0 +# LLVM-NEXT: Description data ( +# LLVM-NEXT: 0000: 00000000 |....| +# LLVM-NEXT: ) +# LLVM-NEXT: } +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: FreeBSD +# LLVM-NEXT: Data size: 0x4 +# LLVM-NEXT: Type: NT_FREEBSD_NOINIT_TAG (no .init tag) +# LLVM-NEXT: Description data ( +# LLVM-NEXT: 0000: 00000000 |....| +# LLVM-NEXT: ) +# LLVM-NEXT: } +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: FreeBSD +# LLVM-NEXT: Data size: 0x6 +# LLVM-NEXT: Type: Unknown note type: (0x00abcdef) +# LLVM-NEXT: Description data ( +# LLVM-NEXT: 0000: 61626364 6566 |abcdef| +# LLVM-NEXT: ) +# LLVM-NEXT: } +# LLVM-NEXT: } +# LLVM-NEXT:] diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -4862,24 +4862,34 @@ return OS.str(); } -static std::string getFreeBSDNoteTypeName(const uint32_t NT) { +static std::string getFreeBSDNoteTypeName(const uint32_t NT, bool IsCore) { static const struct { uint32_t ID; const char *Name; - } Notes[] = { - {ELF::NT_FREEBSD_THRMISC, "NT_THRMISC (thrmisc structure)"}, - {ELF::NT_FREEBSD_PROCSTAT_PROC, "NT_PROCSTAT_PROC (proc data)"}, - {ELF::NT_FREEBSD_PROCSTAT_FILES, "NT_PROCSTAT_FILES (files data)"}, - {ELF::NT_FREEBSD_PROCSTAT_VMMAP, "NT_PROCSTAT_VMMAP (vmmap data)"}, - {ELF::NT_FREEBSD_PROCSTAT_GROUPS, "NT_PROCSTAT_GROUPS (groups data)"}, - {ELF::NT_FREEBSD_PROCSTAT_UMASK, "NT_PROCSTAT_UMASK (umask data)"}, - {ELF::NT_FREEBSD_PROCSTAT_RLIMIT, "NT_PROCSTAT_RLIMIT (rlimit data)"}, - {ELF::NT_FREEBSD_PROCSTAT_OSREL, "NT_PROCSTAT_OSREL (osreldate data)"}, - {ELF::NT_FREEBSD_PROCSTAT_PSSTRINGS, - "NT_PROCSTAT_PSSTRINGS (ps_strings data)"}, - {ELF::NT_FREEBSD_PROCSTAT_AUXV, "NT_PROCSTAT_AUXV (auxv data)"}, - }; - + } CoreDumpNotes[] = + { + {ELF::NT_FREEBSD_THRMISC, "NT_THRMISC (thrmisc structure)"}, + {ELF::NT_FREEBSD_PROCSTAT_PROC, "NT_PROCSTAT_PROC (proc data)"}, + {ELF::NT_FREEBSD_PROCSTAT_FILES, "NT_PROCSTAT_FILES (files data)"}, + {ELF::NT_FREEBSD_PROCSTAT_VMMAP, "NT_PROCSTAT_VMMAP (vmmap data)"}, + {ELF::NT_FREEBSD_PROCSTAT_GROUPS, "NT_PROCSTAT_GROUPS (groups data)"}, + {ELF::NT_FREEBSD_PROCSTAT_UMASK, "NT_PROCSTAT_UMASK (umask data)"}, + {ELF::NT_FREEBSD_PROCSTAT_RLIMIT, "NT_PROCSTAT_RLIMIT (rlimit data)"}, + {ELF::NT_FREEBSD_PROCSTAT_OSREL, + "NT_PROCSTAT_OSREL (osreldate data)"}, + {ELF::NT_FREEBSD_PROCSTAT_PSSTRINGS, + "NT_PROCSTAT_PSSTRINGS (ps_strings data)"}, + {ELF::NT_FREEBSD_PROCSTAT_AUXV, "NT_PROCSTAT_AUXV (auxv data)"}, + }, + OtherNotes[] = { + {ELF::NT_FREEBSD_ABI_TAG, "NT_FREEBSD_ABI_TAG (ABI version tag)"}, + {ELF::NT_FREEBSD_NOINIT_TAG, "NT_FREEBSD_NOINIT_TAG (no .init tag)"}, + {ELF::NT_FREEBSD_ARCH_TAG, "NT_FREEBSD_ARCH_TAG (architecture tag)"}, + {ELF::NT_FREEBSD_FEATURE_CTL, + "NT_FREEBSD_FEATURE_CTL (FreeBSD feature control)"}, + }; + const auto Notes = + IsCore ? makeArrayRef(CoreDumpNotes) : makeArrayRef(OtherNotes); for (const auto &Note : Notes) if (Note.ID == NT) return std::string(Note.Name); @@ -5148,6 +5158,40 @@ return true; } +template +static bool printFreeBSDNote(raw_ostream &OS, uint32_t NoteType, + ArrayRef Desc, bool IsCore) { + if (IsCore) + return false; // No pretty-printing yet + switch (NoteType) { + default: + return false; + case ELF::NT_FREEBSD_ABI_TAG: + if (Desc.size() != 4) { + OS << " \n"; + return false; + } + OS << " ABI: " + << support::endian::read32(Desc.data()); + break; + case ELF::NT_FREEBSD_FEATURE_CTL: + if (Desc.size() != 4) { + OS << " \n"; + return false; + } + // TODO: decode flags + // #define NT_FREEBSD_FCTL_ASLR_DISABLE 0x00000001 + // #define NT_FREEBSD_FCTL_PROTMAX_DISABLE 0x00000002 + // #define NT_FREEBSD_FCTL_STKGAP_DISABLE 0x00000004 + OS << " Feature flags: 0x" + << utohexstr( + support::endian::read32(Desc.data())); + break; + } + OS << '\n'; + return true; +} + struct AMDNote { std::string Type; std::string Value; @@ -5284,22 +5328,21 @@ StringRef Name = Note.getName(); ArrayRef Descriptor = Note.getDesc(); Elf_Word Type = Note.getType(); - + bool IsCore = Obj->getHeader()->e_type == ELF::ET_CORE; // Print the note owner/type. OS << " " << left_justify(Name, 20) << ' ' << format_hex(Descriptor.size(), 10) << '\t'; if (Name == "GNU") { OS << getGNUNoteTypeName(Type) << '\n'; } else if (Name == "FreeBSD") { - OS << getFreeBSDNoteTypeName(Type) << '\n'; + OS << getFreeBSDNoteTypeName(Type, IsCore) << '\n'; } else if (Name == "AMD") { OS << getAMDNoteTypeName(Type) << '\n'; } else if (Name == "AMDGPU") { OS << getAMDGPUNoteTypeName(Type) << '\n'; } else { - StringRef NoteType = Obj->getHeader()->e_type == ELF::ET_CORE - ? getCoreNoteTypeName(Type) - : getGenericNoteTypeName(Type); + StringRef NoteType = + IsCore ? getCoreNoteTypeName(Type) : getGenericNoteTypeName(Type); if (!NoteType.empty()) OS << NoteType << '\n'; else @@ -5311,6 +5354,9 @@ if (Name == "GNU") { if (printGNUNote(OS, Type, Descriptor)) return; + } else if (Name == "FreeBSD") { + if (printFreeBSDNote(OS, Type, Descriptor, IsCore)) + return; } else if (Name == "AMD") { const AMDNote N = getAMDNote(Type, Descriptor); if (!N.Type.empty()) { @@ -6489,6 +6535,38 @@ return true; } +template +static bool printFreeBSDNoteLLVMStyle(uint32_t NoteType, ArrayRef Desc, + ScopedPrinter &W, bool IsCore) { + if (IsCore) + return false; // No pretty-printing yet + switch (NoteType) { + default: + return false; + case ELF::NT_FREEBSD_ABI_TAG: + if (Desc.size() != 4) { + W.printString("ABI", ""); + return false; // Print the raw data + } + W.printNumber("ABI", + support::endian::read32(Desc.data())); + break; + case ELF::NT_FREEBSD_FEATURE_CTL: + if (Desc.size() != 4) { + W.printString("ABI", ""); + return false; // Print the raw data + } + W.printHex("Flags", + support::endian::read32(Desc.data())); + // TODO: pretty-print these values: + // #define NT_FREEBSD_FCTL_ASLR_DISABLE 0x00000001 + // #define NT_FREEBSD_FCTL_PROTMAX_DISABLE 0x00000002 + // #define NT_FREEBSD_FCTL_STKGAP_DISABLE 0x00000004 + break; + } + return true; +} + static void printCoreNoteLLVMStyle(const CoreNote &Note, ScopedPrinter &W) { W.printNumber("Page Size", Note.PageSize); for (const CoreFileMapping &Mapping : Note.Mappings) { @@ -6515,6 +6593,7 @@ StringRef Name = Note.getName(); ArrayRef Descriptor = Note.getDesc(); Elf_Word Type = Note.getType(); + bool IsCore = Obj->getHeader()->e_type == ELF::ET_CORE; // Print the note owner/type. W.printString("Owner", Name); @@ -6522,15 +6601,14 @@ if (Name == "GNU") { W.printString("Type", getGNUNoteTypeName(Type)); } else if (Name == "FreeBSD") { - W.printString("Type", getFreeBSDNoteTypeName(Type)); + W.printString("Type", getFreeBSDNoteTypeName(Type, IsCore)); } else if (Name == "AMD") { W.printString("Type", getAMDNoteTypeName(Type)); } else if (Name == "AMDGPU") { W.printString("Type", getAMDGPUNoteTypeName(Type)); } else { - StringRef NoteType = Obj->getHeader()->e_type == ELF::ET_CORE - ? getCoreNoteTypeName(Type) - : getGenericNoteTypeName(Type); + StringRef NoteType = + IsCore ? getCoreNoteTypeName(Type) : getGenericNoteTypeName(Type); if (!NoteType.empty()) W.printString("Type", NoteType); else @@ -6543,6 +6621,9 @@ if (Name == "GNU") { if (printGNUNoteLLVMStyle(Type, Descriptor, W)) return; + } else if (Name == "FreeBSD") { + if (printFreeBSDNoteLLVMStyle(Type, Descriptor, W, IsCore)) + return; } else if (Name == "AMD") { const AMDNote N = getAMDNote(Type, Descriptor); if (!N.Type.empty()) {