diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index 6650eec934f0..a33b6f37e62a 100644 --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -1516,6 +1516,24 @@ enum : unsigned { 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, +}; + +// NT_FREEBSD_FEATURE_CTL values (see FreeBSD's sys/sys/elf_common.h). +enum { + NT_FREEBSD_FCTL_ASLR_DISABLE = 0x00000001, + NT_FREEBSD_FCTL_PROTMAX_DISABLE = 0x00000002, + NT_FREEBSD_FCTL_STKGAP_DISABLE = 0x00000004, + NT_FREEBSD_FCTL_WXNEEDED = 0x00000008, + NT_FREEBSD_FCTL_LA48 = 0x00000010, + NT_FREEBSD_FCTL_ASG_DISABLE = 0x00000020, +}; + // FreeBSD core note types. enum { NT_FREEBSD_THRMISC = 7, diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp index 43d27beeb1e1..bde91c542f47 100644 --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -138,6 +138,11 @@ void ScalarEnumerationTraits::enumeration( ECase(NT_GNU_BUILD_ID); ECase(NT_GNU_GOLD_VERSION); ECase(NT_GNU_PROPERTY_TYPE_0); + // FreeBSD note types. + ECase(NT_FREEBSD_ABI_TAG); + ECase(NT_FREEBSD_NOINIT_TAG); + ECase(NT_FREEBSD_ARCH_TAG); + ECase(NT_FREEBSD_FEATURE_CTL); // FreeBSD core note types. ECase(NT_FREEBSD_THRMISC); ECase(NT_FREEBSD_PROCSTAT_PROC); 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 index 000000000000..438c278de68a --- /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: + - 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-EMPTY: +# 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 index c3175db69da1..000000000000 --- a/llvm/test/tools/llvm-readobj/ELF/note-freebsd.s +++ /dev/null @@ -1,89 +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-EMPTY: -// GNU-NEXT: Displaying notes found in: .note.bar -// GNU-NEXT: Owner Data size Description -// GNU-NEXT: FreeBSD 0x00000000 NT_PROCSTAT_FILES (files data) -// GNU-EMPTY: -// 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 -// GNU-EMPTY: - -// 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 index 000000000000..937cb6f426b1 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/note-freebsd.test @@ -0,0 +1,128 @@ +## 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: + +# 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 index f800b650330e..dc775f9fcc76 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -4908,6 +4908,53 @@ static bool printGNUNote(raw_ostream &OS, uint32_t NoteType, return true; } +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; @@ -5057,7 +5104,7 @@ static const NoteType GNUNoteTypes[] = { {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)"}, @@ -5071,6 +5118,14 @@ static const NoteType FreeBSDNoteTypes[] = { {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)"}, @@ -5161,8 +5216,17 @@ StringRef getNoteTypeName(const typename ELFT::Note &Note, unsigned ELFType) { 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") @@ -5179,12 +5243,13 @@ static void printNotesHelper( 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; @@ -5193,7 +5258,7 @@ static void printNotesHelper( 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))); @@ -5224,7 +5289,7 @@ static void printNotesHelper( 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 " + @@ -5262,7 +5327,7 @@ template void GNUELFDumper::printNotes() { 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(); @@ -5283,6 +5348,12 @@ template void GNUELFDumper::printNotes() { if (Name == "GNU") { if (printGNUNote(OS, Type, Descriptor)) return Error::success(); + } else if (Name == "FreeBSD") { + if (Optional N = + getFreeBSDNote(Type, Descriptor, IsCore)) { + OS << " " << N->Type << ": " << N->Value << '\n'; + return Error::success(); + } } else if (Name == "AMD") { const AMDNote N = getAMDNote(Type, Descriptor); if (!N.Type.empty()) { @@ -6531,7 +6602,7 @@ template void LLVMELFDumper::printNotes() { 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(); @@ -6554,6 +6625,12 @@ template void LLVMELFDumper::printNotes() { if (Name == "GNU") { if (printGNUNoteLLVMStyle(Type, Descriptor, W)) return Error::success(); + } else if (Name == "FreeBSD") { + if (Optional N = + getFreeBSDNote(Type, Descriptor, IsCore)) { + W.printString(N->Type, N->Value); + return Error::success(); + } } else if (Name == "AMD") { const AMDNote N = getAMDNote(Type, Descriptor); if (!N.Type.empty()) {