From 878ff1f9f85f6c539efb9b8c00978011d381f278 Mon Sep 17 00:00:00 2001
From: Frederic Cambus <fred@statdns.com>
Date: Mon, 29 Nov 2021 08:04:04 +0100
Subject: [PATCH] [llvm-readobj] Add support for machine-independent NetBSD ELF
 core notes.

Notes generated in NetBSD core files provide additional information about
processes. These notes are described in core.5, which can be viewed here:
https://man.netbsd.org/core.5

Differential Revision: https://reviews.llvm.org/D114635
---
 llvm/include/llvm/BinaryFormat/ELF.h          |  7 +++
 llvm/lib/ObjectYAML/ELFYAML.cpp               |  4 ++
 .../llvm-readobj/ELF/note-netbsd-core.test    | 54 +++++++++++++++++++
 llvm/tools/llvm-readobj/ELFDumper.cpp         | 13 +++++
 4 files changed, 78 insertions(+)
 create mode 100644 llvm/test/tools/llvm-readobj/ELF/note-netbsd-core.test

diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index a270fd399aeb3..c199e933116a7 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -1602,6 +1602,13 @@ enum {
   NT_FREEBSD_PROCSTAT_AUXV = 16,
 };
 
+// NetBSD core note types.
+enum {
+  NT_NETBSDCORE_PROCINFO = 1,
+  NT_NETBSDCORE_AUXV = 2,
+  NT_NETBSDCORE_LWPSTATUS = 24,
+};
+
 // OpenBSD core note types.
 enum {
   NT_OPENBSD_PROCINFO = 10,
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index fdf9aeae16228..e0dde4433d24c 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -155,6 +155,10 @@ void ScalarEnumerationTraits<ELFYAML::ELF_NT>::enumeration(
   ECase(NT_FREEBSD_PROCSTAT_OSREL);
   ECase(NT_FREEBSD_PROCSTAT_PSSTRINGS);
   ECase(NT_FREEBSD_PROCSTAT_AUXV);
+  // NetBSD core note types.
+  ECase(NT_NETBSDCORE_PROCINFO);
+  ECase(NT_NETBSDCORE_AUXV);
+  ECase(NT_NETBSDCORE_LWPSTATUS);
   // OpenBSD core note types.
   ECase(NT_OPENBSD_PROCINFO);
   ECase(NT_OPENBSD_AUXV);
diff --git a/llvm/test/tools/llvm-readobj/ELF/note-netbsd-core.test b/llvm/test/tools/llvm-readobj/ELF/note-netbsd-core.test
new file mode 100644
index 0000000000000..aec85aa513946
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/ELF/note-netbsd-core.test
@@ -0,0 +1,54 @@
+## Test that note values are interpreted correctly for NetBSD 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: NetBSD-CORE
+        Type: NT_NETBSDCORE_PROCINFO
+      - Name: NetBSD-CORE
+        Type: NT_NETBSDCORE_AUXV
+      - Name: NetBSD-CORE@3615
+        Type: NT_NETBSDCORE_LWPSTATUS
+
+ProgramHeaders:
+  - Type:     PT_NOTE
+    FirstSec: .note.foo
+    LastSec:  .note.foo
+
+# GNU:      Displaying notes found at file offset 0x00000078 with length 0x00000050:
+# GNU-NEXT:   Owner                Data size 	Description
+# GNU-NEXT:   NetBSD-CORE          0x00000000	NT_NETBSDCORE_PROCINFO (procinfo structure)
+# GNU-NEXT:   NetBSD-CORE          0x00000000	NT_NETBSDCORE_AUXV (ELF auxiliary vector data)
+# GNU-NEXT:   NetBSD-CORE@3615     0x00000000	PT_LWPSTATUS (ptrace_lwpstatus structure)
+
+# LLVM:      Notes [
+# LLVM-NEXT:   NoteSection {
+# LLVM-NEXT:     Name: <?>
+# LLVM-NEXT:     Offset: 0x78
+# LLVM-NEXT:     Size: 0x50
+# LLVM-NEXT:     Note {
+# LLVM-NEXT:       Owner: NetBSD-CORE
+# LLVM-NEXT:       Data size: 0x0
+# LLVM-NEXT:       Type: NT_NETBSDCORE_PROCINFO (procinfo structure)
+# LLVM-NEXT:     }
+# LLVM-NEXT:     Note {
+# LLVM-NEXT:       Owner: NetBSD-CORE
+# LLVM-NEXT:       Data size: 0x0
+# LLVM-NEXT:       Type: NT_NETBSDCORE_AUXV (ELF auxiliary vector data)
+# LLVM-NEXT:     }
+# LLVM-NEXT:     Note {
+# LLVM-NEXT:       Owner: NetBSD-CORE@3615
+# LLVM-NEXT:       Data size: 0x0
+# LLVM-NEXT:       Type: PT_LWPSTATUS (ptrace_lwpstatus structure)
+# LLVM-NEXT:     }
+# LLVM-NEXT:   }
+# LLVM-NEXT: ]
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 4abea0b1d23d9..9dd777dd98e7b 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -5333,6 +5333,13 @@ const NoteType FreeBSDNoteTypes[] = {
      "NT_FREEBSD_FEATURE_CTL (FreeBSD feature control)"},
 };
 
+const NoteType NetBSDCoreNoteTypes[] = {
+    {ELF::NT_NETBSDCORE_PROCINFO,
+     "NT_NETBSDCORE_PROCINFO (procinfo structure)"},
+    {ELF::NT_NETBSDCORE_AUXV, "NT_NETBSDCORE_AUXV (ELF auxiliary vector data)"},
+    {ELF::NT_NETBSDCORE_LWPSTATUS, "PT_LWPSTATUS (ptrace_lwpstatus structure)"},
+};
+
 const NoteType OpenBSDCoreNoteTypes[] = {
     {ELF::NT_OPENBSD_PROCINFO, "NT_OPENBSD_PROCINFO (procinfo structure)"},
     {ELF::NT_OPENBSD_AUXV, "NT_OPENBSD_AUXV (ELF auxiliary vector data)"},
@@ -5453,6 +5460,12 @@ StringRef getNoteTypeName(const typename ELFT::Note &Note, unsigned ELFType) {
       return FindNote(FreeBSDNoteTypes);
     }
   }
+  if (ELFType == ELF::ET_CORE && Name.startswith("NetBSD-CORE")) {
+    StringRef Result = FindNote(NetBSDCoreNoteTypes);
+    if (!Result.empty())
+      return Result;
+    return FindNote(CoreNoteTypes);
+  }
   if (Name.startswith("OpenBSD") && ELFType == ELF::ET_CORE) {
     // OpenBSD also places the generic core notes in the OpenBSD namespace.
     StringRef Result = FindNote(OpenBSDCoreNoteTypes);
