[llvm] 7dc3136 - [llvm-readobj] Add support for decoding FreeBSD ELF notes
Alex Richardson via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 9 08:59:53 PST 2021
Author: Alex Richardson
Date: 2021-02-09T16:59:22Z
New Revision: 7dc31360339268b25d49680d23268731b33f51aa
URL: https://github.com/llvm/llvm-project/commit/7dc31360339268b25d49680d23268731b33f51aa
DIFF: https://github.com/llvm/llvm-project/commit/7dc31360339268b25d49680d23268731b33f51aa.diff
LOG: [llvm-readobj] Add support for decoding FreeBSD ELF notes
The current support only printed coredump notes, but most binaries also
contain notes. This change adds names for four FreeBSD-specific notes and
pretty-prints three of them:
NT_FREEBSD_ABI_TAG:
This note holds a 32-bit (decimal) integer containing the value of the
__FreeBSD_version macro, which is defined in crt1.o and will hold a value
such as 1300076 for a binary build on a FreeBSD 13 system.
NT_FREEBSD_ARCH_TAG:
A string containing the value of the build-time MACHINE_ARCH
NT_FREEBSD_FEATURE_CTL: A 32-bit flag that indicates to the kernel that
the binary wants certain bevahiour. Examples include setting
NT_FREEBSD_FCTL_ASLR_DISABLE which tells the kernel to disable ASLR.
After this change llvm-readobj also no longer decodes coredump-only
FreeBSD notes in non-coredump files. I've also converted the
note-freebsd.s test to use yaml2obj instead of llvm-mc.
Reviewed By: jhenderson
Differential Revision: https://reviews.llvm.org/D74393
Added:
llvm/test/tools/llvm-readobj/ELF/note-freebsd-core.test
llvm/test/tools/llvm-readobj/ELF/note-freebsd.test
Modified:
llvm/include/llvm/BinaryFormat/ELF.h
llvm/lib/ObjectYAML/ELFYAML.cpp
llvm/tools/llvm-readobj/ELFDumper.cpp
Removed:
llvm/test/tools/llvm-readobj/ELF/note-freebsd.s
################################################################################
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<ELFYAML::ELF_NT>::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<unsigned> 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 <typename ELFT>
+static Optional<FreeBSDNote>
+getFreeBSDNote(uint32_t NoteType, ArrayRef<uint8_t> 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<ELFT::TargetEndianness>(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<ELFT::TargetEndianness>(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<void(Optional<StringRef>, typename ELFT::Off,
typename ELFT::Addr)>
StartNotesFn,
- llvm::function_ref<Error(const typename ELFT::Note &)> ProcessNoteFn,
+ llvm::function_ref<Error(const typename ELFT::Note &, bool)> ProcessNoteFn,
llvm::function_ref<void()> FinishNotesFn) {
const ELFFile<ELFT> &Obj = Dumper.getElfObject().getELFFile();
+ bool IsCoreFile = Obj.getHeader().e_type == ELF::ET_CORE;
ArrayRef<typename ELFT::Shdr> 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 <class ELFT> void GNUELFDumper<ELFT>::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<uint8_t> Descriptor = Note.getDesc();
Elf_Word Type = Note.getType();
@@ -5283,6 +5348,12 @@ template <class ELFT> void GNUELFDumper<ELFT>::printNotes() {
if (Name == "GNU") {
if (printGNUNote<ELFT>(OS, Type, Descriptor))
return Error::success();
+ } else if (Name == "FreeBSD") {
+ if (Optional<FreeBSDNote> N =
+ getFreeBSDNote<ELFT>(Type, Descriptor, IsCore)) {
+ OS << " " << N->Type << ": " << N->Value << '\n';
+ return Error::success();
+ }
} else if (Name == "AMD") {
const AMDNote N = getAMDNote<ELFT>(Type, Descriptor);
if (!N.Type.empty()) {
@@ -6531,7 +6602,7 @@ template <class ELFT> void LLVMELFDumper<ELFT>::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<uint8_t> Descriptor = Note.getDesc();
@@ -6554,6 +6625,12 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() {
if (Name == "GNU") {
if (printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W))
return Error::success();
+ } else if (Name == "FreeBSD") {
+ if (Optional<FreeBSDNote> N =
+ getFreeBSDNote<ELFT>(Type, Descriptor, IsCore)) {
+ W.printString(N->Type, N->Value);
+ return Error::success();
+ }
} else if (Name == "AMD") {
const AMDNote N = getAMDNote<ELFT>(Type, Descriptor);
if (!N.Type.empty()) {
More information about the llvm-commits
mailing list