[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