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 @@ -1368,18 +1368,6 @@ enum { VER_NEED_NONE = 0, VER_NEED_CURRENT = 1 }; // SHT_NOTE section types -enum { - NT_FREEBSD_THRMISC = 7, - NT_FREEBSD_PROCSTAT_PROC = 8, - NT_FREEBSD_PROCSTAT_FILES = 9, - NT_FREEBSD_PROCSTAT_VMMAP = 10, - NT_FREEBSD_PROCSTAT_GROUPS = 11, - NT_FREEBSD_PROCSTAT_UMASK = 12, - NT_FREEBSD_PROCSTAT_RLIMIT = 13, - NT_FREEBSD_PROCSTAT_OSREL = 14, - NT_FREEBSD_PROCSTAT_PSSTRINGS = 15, - NT_FREEBSD_PROCSTAT_AUXV = 16, -}; // Generic note types enum : unsigned { @@ -1523,6 +1511,27 @@ GNU_PROPERTY_X86_FEATURE_2_XSAVEC = 1 << 9, }; +// FreeBSD note types +enum { + NT_FREEBSD_ABI_TAG = 1, + NT_FREEBSD_NOINIT_TAG = 2, + NT_FREEBSD_ARCH_TAG = 3, + NT_FREEBSD_FEATURE_CTL = 4, +}; +// FreeBSD core note types +enum { + NT_FREEBSD_THRMISC = 7, + NT_FREEBSD_PROCSTAT_PROC = 8, + NT_FREEBSD_PROCSTAT_FILES = 9, + NT_FREEBSD_PROCSTAT_VMMAP = 10, + NT_FREEBSD_PROCSTAT_GROUPS = 11, + NT_FREEBSD_PROCSTAT_UMASK = 12, + NT_FREEBSD_PROCSTAT_RLIMIT = 13, + NT_FREEBSD_PROCSTAT_OSREL = 14, + NT_FREEBSD_PROCSTAT_PSSTRINGS = 15, + NT_FREEBSD_PROCSTAT_AUXV = 16, +}; + // AMDGPU-specific section indices. enum { SHN_AMDGPU_LDS = 0xff00, // Variable in LDS; symbol encoded like SHN_COMMON 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,145 @@ +## Test that note values are interpreted correctly for FreeBSD core files. +# RUN: yaml2obj %s -o %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 +Sections: + - Name: .note.foo + Type: SHT_NOTE + Notes: + - Name: FreeBSD + Type: NT_FREEBSD_THRMISC + - Name: FreeBSD + Type: NT_FREEBSD_PROCSTAT_PROC + - Name: FreeBSD + Type: NT_FREEBSD_PROCSTAT_FILES + - Name: FreeBSD + Type: NT_FREEBSD_PROCSTAT_VMMAP + - Name: FreeBSD + Type: NT_FREEBSD_PROCSTAT_GROUPS + - Name: FreeBSD + Type: NT_FREEBSD_PROCSTAT_UMASK + - Name: FreeBSD + Type: NT_FREEBSD_PROCSTAT_RLIMIT + - Name: FreeBSD + Type: NT_FREEBSD_PROCSTAT_OSREL + - Name: FreeBSD + Type: NT_FREEBSD_PROCSTAT_PSSTRINGS + - Name: FreeBSD + Type: NT_FREEBSD_PROCSTAT_AUXV + - Name: FreeBSD + Type: 0x12345 + - Name: .note.bar + Type: SHT_NOTE + Notes: + - Name: FreeBSD + Desc: 'aabbccddeeff' + Type: NT_PRPSINFO +ProgramHeaders: +ProgramHeaders: + - Type: PT_NOTE + FirstSec: .note.foo + LastSec: .note.foo + - Type: PT_NOTE + FirstSec: .note.bar + LastSec: .note.bar + +# GNU: Displaying notes found at file offset 0x000000b0 with length 0x000000dc: +# 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: FreeBSD 0x00000000 NT_PROCSTAT_FILES (files data) +# GNU-NEXT: FreeBSD 0x00000000 NT_PROCSTAT_VMMAP (vmmap data) +# GNU-NEXT: FreeBSD 0x00000000 NT_PROCSTAT_GROUPS (groups data) +# GNU-NEXT: FreeBSD 0x00000000 NT_PROCSTAT_UMASK (umask data) +# GNU-NEXT: FreeBSD 0x00000000 NT_PROCSTAT_RLIMIT (rlimit data) +# GNU-NEXT: FreeBSD 0x00000000 NT_PROCSTAT_OSREL (osreldate data) +# GNU-NEXT: FreeBSD 0x00000000 NT_PROCSTAT_PSSTRINGS (ps_strings data) +# GNU-NEXT: FreeBSD 0x00000000 NT_PROCSTAT_AUXV (auxv data) +# GNU-NEXT: FreeBSD 0x00000000 Unknown note type: (0x00012345) +# GNU-NEXT: Displaying notes found at file offset 0x0000018c with length 0x0000001c: +# GNU-NEXT: Owner Data size Description +# GNU-NEXT: FreeBSD 0x00000006 NT_PRPSINFO (prpsinfo structure) +# GNU-NEXT: description data: aa bb cc dd ee ff +# GNU-EMPTY: + +# LLVM: Notes [ +# LLVM-NEXT: NoteSection { +# LLVM-NEXT: Name: +# LLVM-NEXT: Offset: 0xB0 +# LLVM-NEXT: Size: 0xDC +# 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: Note { +# LLVM-NEXT: Owner: FreeBSD +# LLVM-NEXT: Data size: 0x0 +# LLVM-NEXT: Type: NT_PROCSTAT_FILES (files data) +# LLVM-NEXT: } +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: FreeBSD +# LLVM-NEXT: Data size: 0x0 +# LLVM-NEXT: Type: NT_PROCSTAT_VMMAP (vmmap data) +# LLVM-NEXT: } +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: FreeBSD +# LLVM-NEXT: Data size: 0x0 +# LLVM-NEXT: Type: NT_PROCSTAT_GROUPS (groups data) +# LLVM-NEXT: } +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: FreeBSD +# LLVM-NEXT: Data size: 0x0 +# LLVM-NEXT: Type: NT_PROCSTAT_UMASK (umask data) +# LLVM-NEXT: } +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: FreeBSD +# LLVM-NEXT: Data size: 0x0 +# LLVM-NEXT: Type: NT_PROCSTAT_RLIMIT (rlimit data) +# LLVM-NEXT: } +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: FreeBSD +# LLVM-NEXT: Data size: 0x0 +# LLVM-NEXT: Type: NT_PROCSTAT_OSREL (osreldate data) +# LLVM-NEXT: } +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: FreeBSD +# LLVM-NEXT: Data size: 0x0 +# LLVM-NEXT: Type: NT_PROCSTAT_PSSTRINGS (ps_strings data) +# LLVM-NEXT: } +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: FreeBSD +# LLVM-NEXT: Data size: 0x0 +# LLVM-NEXT: Type: NT_PROCSTAT_AUXV (auxv data) +# LLVM-NEXT: } +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: FreeBSD +# LLVM-NEXT: Data size: 0x0 +# LLVM-NEXT: Type: Unknown (0x00012345) +# LLVM-NEXT: } +# LLVM-NEXT: } +# LLVM-NEXT: NoteSection { +# LLVM-NEXT: Name: +# LLVM-NEXT: Offset: 0x18C +# LLVM-NEXT: Size: 0x1C +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: FreeBSD +# LLVM-NEXT: Data size: 0x6 +# LLVM-NEXT: Type: NT_PRPSINFO (prpsinfo structure) +# LLVM-NEXT: Description data ( +# LLVM-NEXT: 0000: AABBCCDD EEFF |......| +# 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,86 +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 in: .note.foo -// 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 in: .note.bar -// GNU-NEXT: Owner Data size Description -// GNU-NEXT: FreeBSD 0x00000000 NT_PROCSTAT_FILES (files data) -// GNU-NEXT: Displaying notes found in: .note.baz -// 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: Name: .note.foo -// 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: Name: .note.bar -// 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: Name: .note.baz -// LLVM-NEXT: Offset: 0x7C -// LLVM-NEXT: Size: 0x30 -// LLVM-NEXT: Note { -// LLVM-NEXT: Owner: FreeBSD -// LLVM-NEXT: Data size: 0x1C -// LLVM-NEXT: Type: Unknown (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,168 @@ +## Test that note values are interpreted correctly for FreeBSD executables. +# RUN: yaml2obj %s -o %t.o +# RUN: llvm-readelf --notes %t.o | FileCheck %s --check-prefixes=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 + AddressAlign: 0x0000000000000004 + Notes: + - Name: FreeBSD + Desc: '6CD61300' + Type: NT_FREEBSD_ABI_TAG + - Name: FreeBSD + Desc: '6C' # Invalid data (should be 4 bytes) + Type: NT_FREEBSD_ABI_TAG + - Name: FreeBSD + Desc: '61617263683634' + Type: NT_FREEBSD_ARCH_TAG + - Name: FreeBSD + Desc: 'FFFFFFFF' + Type: NT_FREEBSD_FEATURE_CTL + - Name: FreeBSD + Desc: '00' # Invalid data (should be 4 bytes) + Type: NT_FREEBSD_FEATURE_CTL + - Name: FreeBSD + Desc: '00000000' + Type: NT_FREEBSD_NOINIT_TAG + - Name: FreeBSD + Desc: '616263646566' + Type: 0xabcdef + - Name: FreeBSD + Desc: '616263646566' + Type: NT_FREEBSD_PROCSTAT_RLIMIT # Only valid for coredumps. + +# GNU: Displaying notes found in: .note.tag +# GNU-NEXT: Owner Data size Description +# GNU-NEXT: FreeBSD 0x00000004 NT_FREEBSD_ABI_TAG (ABI version tag) +# GNU-NEXT: ABI tag: 1300076 +# GNU-NEXT: FreeBSD 0x00000001 NT_FREEBSD_ABI_TAG (ABI version tag) +# GNU-NEXT: description data: 6c +# GNU-NEXT: FreeBSD 0x00000007 NT_FREEBSD_ARCH_TAG (architecture tag) +# GNU-NEXT: Arch tag: aarch64 +# GNU-NEXT: FreeBSD 0x00000004 NT_FREEBSD_FEATURE_CTL (FreeBSD feature control) +# GNU-NEXT: Feature flags: ASLR_DISABLE PROTMAX_DISABLE STKGAP_DISABLE WXNEEDED LA48 ASG_DISABLE (0xFFFFFFFF) +# GNU-NEXT: FreeBSD 0x00000001 NT_FREEBSD_FEATURE_CTL (FreeBSD feature control) +# GNU-NEXT: description data: 00 +# 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 +## NT_FREEBSD_PROCSTAT_RLIMIT is only a valid type for coredumps and should therefore not be decoded. +## Note: Binutils prints NT_PROCSTAT_RLIMIT, but this seems incorrect +# GNU-NEXT: FreeBSD 0x00000006 Unknown note type: (0x0000000d) +# GNU-NEXT: description data: 61 62 63 64 65 66 +# GNU-EMPTY: + +## For reference, here is the binutils 2.36 output (which does not appears to handle most FreeBSD notes): +## FIXME: remove this before committing +#Displaying notes found in: .note.tag +# Owner Data size Description +# FreeBSD 0x00000004 NT_VERSION (version) +# description data: 6c d6 13 00 +# FreeBSD 0x00000001 NT_VERSION (version) +# description data: 6c +# FreeBSD 0x00000007 Unknown note type: (0x00000003) +# description data: 61 61 72 63 68 36 34 +# FreeBSD 0x00000004 Unknown note type: (0x00000004) +# description data: ff ff ff ff +# FreeBSD 0x00000001 Unknown note type: (0x00000004) +# description data: 00 +# FreeBSD 0x00000004 NT_ARCH (architecture) +# description data: 00 00 00 00 +# FreeBSD 0x00000006 Unknown note type: (0x00abcdef) +# description data: 61 62 63 64 65 66 +# FreeBSD 0x00000006 NT_PROCSTAT_RLIMIT (rlimit data) +# description data: 61 62 63 64 65 66 +## And the FreeBSD elftoolchain readelf output: +#Notes at offset 0x00000040 with length 0x000000cc: +# Owner Data size Description +# FreeBSD 0x00000004 NT_FREEBSD_ABI_TAG +# ABI tag: 1300076 +# FreeBSD 0x00000001 NT_FREEBSD_ABI_TAG +# description data: 6c +# FreeBSD 0x00000007 NT_FREEBSD_ARCH_TAG +# Arch tag: aarch64 +# FreeBSD 0x00000004 NT_FREEBSD_FEATURE_CTL +# Features: ASLR_DISABLE PROTMAX_DISABLE STKGAP_DISABLE WXNEEDED unknown (0xfffffff0) +# FreeBSD 0x00000001 NT_FREEBSD_FEATURE_CTL +# description data: 00 +# FreeBSD 0x00000004 NT_FREEBSD_NOINIT_TAG +# description data: 00 00 00 00 +# FreeBSD 0x00000006 +# description data: 61 62 63 64 65 66 +# FreeBSD 0x00000006 +# description data: 61 62 63 64 65 66 + +# LLVM: Notes [ +# LLVM-NEXT: NoteSection { +# LLVM-NEXT: Name: .note.tag +# LLVM-NEXT: Offset: 0x40 +# LLVM-NEXT: Size: 0xCC +# 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 tag: 1300076 +# LLVM-NEXT: } +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: FreeBSD +# LLVM-NEXT: Data size: 0x1 +# LLVM-NEXT: Type: NT_FREEBSD_ABI_TAG (ABI version tag) +# LLVM-NEXT: Description data ( +# LLVM-NEXT: 0000: 6C |l| +# LLVM-NEXT: ) +# LLVM-NEXT: } +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: FreeBSD +# LLVM-NEXT: Data size: 0x7 +# LLVM-NEXT: Type: NT_FREEBSD_ARCH_TAG (architecture tag) +# LLVM-NEXT: Arch tag: aarch64 +# 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: Feature flags: ASLR_DISABLE PROTMAX_DISABLE STKGAP_DISABLE WXNEEDED LA48 ASG_DISABLE (0xFFFFFFFF) +# LLVM-NEXT: } +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: FreeBSD +# LLVM-NEXT: Data size: 0x1 +# LLVM-NEXT: Type: NT_FREEBSD_FEATURE_CTL (FreeBSD feature control) +# LLVM-NEXT: Description data ( +# LLVM-NEXT: 0000: 00 |.| +# 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 (0x00abcdef) +# LLVM-NEXT: Description data ( +# LLVM-NEXT: 0000: 61626364 6566 |abcdef| +# LLVM-NEXT: ) +# LLVM-NEXT: } +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: FreeBSD +# LLVM-NEXT: Data size: 0x6 +# LLVM-NEXT: Type: Unknown (0x0000000d) +# 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 @@ -4906,6 +4906,60 @@ OS << '\n'; } +// Defines copied from sys/sys/elf_common.h in the FreeBSD source tree: +#define NT_FREEBSD_FCTL_ASLR_DISABLE 0x00000001 +#define NT_FREEBSD_FCTL_PROTMAX_DISABLE 0x00000002 +#define NT_FREEBSD_FCTL_STKGAP_DISABLE 0x00000004 +#define NT_FREEBSD_FCTL_WXNEEDED 0x00000008 +#define NT_FREEBSD_FCTL_LA48 0x00000010 +#define NT_FREEBSD_FCTL_ASG_DISABLE 0x00000020 /* ASLR STACK GAP Disable */ +static const EnumEntry FreeBSDFeatureCtlFlags[] = { + {"ASLR_DISABLE", NT_FREEBSD_FCTL_ASLR_DISABLE}, + {"PROTMAX_DISABLE", NT_FREEBSD_FCTL_PROTMAX_DISABLE}, + {"STKGAP_DISABLE", NT_FREEBSD_FCTL_STKGAP_DISABLE}, + {"WXNEEDED", NT_FREEBSD_FCTL_WXNEEDED}, + {"LA48", NT_FREEBSD_FCTL_LA48}, + {"ASG_DISABLE", NT_FREEBSD_FCTL_ASG_DISABLE}, +}; + +struct FreeBSDNote { + std::string Type; + std::string Value; +}; + +template +static Optional +getFreeBSDNote(uint32_t NoteType, ArrayRef Desc, bool IsCore) { + if (IsCore) + return None; // No pretty-printing yet. + switch (NoteType) { + case ELF::NT_FREEBSD_ABI_TAG: + if (Desc.size() != 4) + return None; + return FreeBSDNote{ + "ABI tag", + utostr(support::endian::read32(Desc.data()))}; + case ELF::NT_FREEBSD_ARCH_TAG: + return FreeBSDNote{"Arch tag", toStringRef(Desc).str()}; + case ELF::NT_FREEBSD_FEATURE_CTL: { + if (Desc.size() != 4) + return None; + unsigned Value = + support::endian::read32(Desc.data()); + std::string FlagsStr; + raw_string_ostream OS(FlagsStr); + printFlags(Value, makeArrayRef(FreeBSDFeatureCtlFlags), OS); + if (OS.str().empty()) + OS << "0x" << utohexstr(Value); + else + OS << "(0x" << utohexstr(Value) << ")"; + return FreeBSDNote{"Feature flags", OS.str()}; + } + default: + return None; + } +} + struct AMDNote { std::string Type; std::string Value; @@ -5049,7 +5103,7 @@ {ELF::NT_GNU_PROPERTY_TYPE_0, "NT_GNU_PROPERTY_TYPE_0 (property note)"}, }; -static const NoteType FreeBSDNoteTypes[] = { +static const NoteType FreeBSDCoreNoteTypes[] = { {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)"}, @@ -5063,6 +5117,14 @@ {ELF::NT_FREEBSD_PROCSTAT_AUXV, "NT_PROCSTAT_AUXV (auxv data)"}, }; +static const NoteType FreeBSDNoteTypes[] = { + {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)"}, +}; + static const NoteType AMDNoteTypes[] = { {ELF::NT_AMD_AMDGPU_HSA_METADATA, "NT_AMD_AMDGPU_HSA_METADATA (HSA Metadata)"}, @@ -5153,8 +5215,17 @@ StringRef Name = Note.getName(); if (Name == "GNU") return FindNote(GNUNoteTypes); - if (Name == "FreeBSD") - return FindNote(FreeBSDNoteTypes); + if (Name == "FreeBSD") { + if (ELFType == ELF::ET_CORE) { + // FreeBSD also places the generic core notes in the FreeBSD namespace. + StringRef Result = FindNote(FreeBSDCoreNoteTypes); + if (!Result.empty()) + return Result; + return FindNote(CoreNoteTypes); + } else { + return FindNote(FreeBSDNoteTypes); + } + } if (Name == "AMD") return FindNote(AMDNoteTypes); if (Name == "AMDGPU") @@ -5171,12 +5242,13 @@ llvm::function_ref, typename ELFT::Off, typename ELFT::Addr)> StartNotesFn, - llvm::function_ref ProcessNoteFn, + llvm::function_ref ProcessNoteFn, llvm::function_ref FinishNotesFn) { const ELFFile &Obj = Dumper.getElfObject().getELFFile(); + bool IsCoreFile = Obj.getHeader().e_type == ELF::ET_CORE; ArrayRef Sections = cantFail(Obj.sections()); - if (Obj.getHeader().e_type != ELF::ET_CORE && !Sections.empty()) { + if (!IsCoreFile && !Sections.empty()) { for (const typename ELFT::Shdr &S : Sections) { if (S.sh_type != SHT_NOTE) continue; @@ -5185,7 +5257,7 @@ Error Err = Error::success(); size_t I = 0; for (const typename ELFT::Note Note : Obj.notes(S, Err)) { - if (Error E = ProcessNoteFn(Note)) + if (Error E = ProcessNoteFn(Note, IsCoreFile)) Dumper.reportUniqueWarning( "unable to read note with index " + Twine(I) + " from the " + describe(Obj, S) + ": " + toString(std::move(E))); @@ -5216,7 +5288,7 @@ Error Err = Error::success(); size_t Index = 0; for (const typename ELFT::Note Note : Obj.notes(P, Err)) { - if (Error E = ProcessNoteFn(Note)) + if (Error E = ProcessNoteFn(Note, IsCoreFile)) Dumper.reportUniqueWarning("unable to read note with index " + Twine(Index) + " from the PT_NOTE segment with index " + @@ -5246,7 +5318,7 @@ OS << " Owner Data size \tDescription\n"; }; - auto ProcessNote = [&](const Elf_Note &Note) -> Error { + auto ProcessNote = [&](const Elf_Note &Note, bool IsCore) -> Error { StringRef Name = Note.getName(); ArrayRef Descriptor = Note.getDesc(); Elf_Word Type = Note.getType(); @@ -5264,6 +5336,15 @@ // Print the description, or fallback to printing raw bytes for unknown // owners. + if (Name == "FreeBSD") { + if (Optional N = + getFreeBSDNote(Type, Descriptor, IsCore)) { + OS << " " << N->Type << ": " << N->Value << '\n'; + return Error::success(); + } + // No pretty-printing available, print the raw bytes. + // TODO: we should probably do this for the other notes too? + } if (Name == "GNU") { printGNUNote(OS, Type, Descriptor); } else if (Name == "AMD") { @@ -6504,7 +6585,7 @@ auto EndNotes = [&] { NoteScope.reset(); }; - auto ProcessNote = [&](const Elf_Note &Note) -> Error { + auto ProcessNote = [&](const Elf_Note &Note, bool IsCore) -> Error { DictScope D2(W, "Note"); StringRef Name = Note.getName(); ArrayRef Descriptor = Note.getDesc(); @@ -6524,6 +6605,15 @@ // Print the description, or fallback to printing raw bytes for unknown // owners. + if (Name == "FreeBSD") { + if (Optional N = + getFreeBSDNote(Type, Descriptor, IsCore)) { + W.printString(N->Type, N->Value); + return Error::success(); + } + // No pretty-printing available, fall back to printing the raw data. + // TODO: we should probably do this for the other notes too? + } if (Name == "GNU") { printGNUNoteLLVMStyle(Type, Descriptor, W); } else if (Name == "AMD") {