From 650311737eee207171f2407da8ecea780863fa1f Mon Sep 17 00:00:00 2001
From: Frederic Cambus <fred@statdns.com>
Date: Mon, 1 Nov 2021 22:46:30 +0100
Subject: [PATCH] [llvm-readobj] Add support for reading OpenBSD ELF core
 notes.

Notes generated in OpenBSD core files provide additional information
about the kernel state and CPU registers. These notes are described
in core.5, which can be viewed here: https://man.openbsd.org/core.5

Differential Revision: https://reviews.llvm.org/D111966
---
 llvm/include/llvm/BinaryFormat/ELF.h          | 10 +++
 llvm/lib/ObjectYAML/ELFYAML.cpp               |  7 ++
 .../llvm-readobj/ELF/note-openbsd-core.test   | 69 +++++++++++++++++++
 llvm/tools/llvm-readobj/ELFDumper.cpp         | 15 ++++
 4 files changed, 101 insertions(+)
 create mode 100644 llvm/test/tools/llvm-readobj/ELF/note-openbsd-core.test

diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index df9fd49606378..a270fd399aeb3 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -1602,6 +1602,16 @@ enum {
   NT_FREEBSD_PROCSTAT_AUXV = 16,
 };
 
+// OpenBSD core note types.
+enum {
+  NT_OPENBSD_PROCINFO = 10,
+  NT_OPENBSD_AUXV = 11,
+  NT_OPENBSD_REGS = 20,
+  NT_OPENBSD_FPREGS = 21,
+  NT_OPENBSD_XFPREGS = 22,
+  NT_OPENBSD_WCOOKIE = 23,
+};
+
 // AMDGPU-specific section indices.
 enum {
   SHN_AMDGPU_LDS = 0xff00, // Variable in LDS; symbol encoded like SHN_COMMON
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index a9e63a68e45e0..fdf9aeae16228 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -155,6 +155,13 @@ void ScalarEnumerationTraits<ELFYAML::ELF_NT>::enumeration(
   ECase(NT_FREEBSD_PROCSTAT_OSREL);
   ECase(NT_FREEBSD_PROCSTAT_PSSTRINGS);
   ECase(NT_FREEBSD_PROCSTAT_AUXV);
+  // OpenBSD core note types.
+  ECase(NT_OPENBSD_PROCINFO);
+  ECase(NT_OPENBSD_AUXV);
+  ECase(NT_OPENBSD_REGS);
+  ECase(NT_OPENBSD_FPREGS);
+  ECase(NT_OPENBSD_XFPREGS);
+  ECase(NT_OPENBSD_WCOOKIE);
   // AMD specific notes. (Code Object V2)
   ECase(NT_AMD_HSA_CODE_OBJECT_VERSION);
   ECase(NT_AMD_HSA_HSAIL);
diff --git a/llvm/test/tools/llvm-readobj/ELF/note-openbsd-core.test b/llvm/test/tools/llvm-readobj/ELF/note-openbsd-core.test
new file mode 100644
index 0000000000000..0ccb55a8d6f33
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/ELF/note-openbsd-core.test
@@ -0,0 +1,69 @@
+## Test that note values are interpreted correctly for OpenBSD 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: OpenBSD
+        Type: NT_OPENBSD_PROCINFO
+      - Name: OpenBSD
+        Type: NT_OPENBSD_AUXV
+      - Name: OpenBSD
+        Type: NT_OPENBSD_WCOOKIE
+      - Name: OpenBSD@31337
+        Type: NT_OPENBSD_REGS
+      - Name: OpenBSD@31337
+        Type: NT_OPENBSD_FPREGS
+ProgramHeaders:
+  - Type:     PT_NOTE
+    FirstSec: .note.foo
+    LastSec:  .note.foo
+
+# GNU:      Displaying notes found at file offset 0x00000078 with length 0x00000074:
+# GNU-NEXT:   Owner                Data size 	Description
+# GNU-NEXT:   OpenBSD              0x00000000	NT_OPENBSD_PROCINFO (procinfo structure)
+# GNU-NEXT:   OpenBSD              0x00000000	NT_OPENBSD_AUXV (ELF auxiliary vector data)
+# GNU-NEXT:   OpenBSD              0x00000000	NT_OPENBSD_WCOOKIE (window cookie)
+# GNU-NEXT:   OpenBSD@31337        0x00000000	NT_OPENBSD_REGS (regular registers)
+# GNU-NEXT:   OpenBSD@31337        0x00000000	NT_OPENBSD_FPREGS (floating point registers)
+
+# LLVM:      Notes [
+# LLVM-NEXT:   NoteSection {
+# LLVM-NEXT:     Name: <?>
+# LLVM-NEXT:     Offset: 0x78
+# LLVM-NEXT:     Size: 0x74
+# LLVM-NEXT:     Note {
+# LLVM-NEXT:       Owner: OpenBSD
+# LLVM-NEXT:       Data size: 0x0
+# LLVM-NEXT:       Type: NT_OPENBSD_PROCINFO (procinfo structure)
+# LLVM-NEXT:     }
+# LLVM-NEXT:     Note {
+# LLVM-NEXT:       Owner: OpenBSD
+# LLVM-NEXT:       Data size: 0x0
+# LLVM-NEXT:       Type: NT_OPENBSD_AUXV (ELF auxiliary vector data)
+# LLVM-NEXT:     }
+# LLVM-NEXT:     Note {
+# LLVM-NEXT:       Owner: OpenBSD
+# LLVM-NEXT:       Data size: 0x0
+# LLVM-NEXT:       Type: NT_OPENBSD_WCOOKIE (window cookie)
+# LLVM-NEXT:     }
+# LLVM-NEXT:     Note {
+# LLVM-NEXT:       Owner: OpenBSD@31337
+# LLVM-NEXT:       Data size: 0x0
+# LLVM-NEXT:       Type: NT_OPENBSD_REGS (regular registers)
+# LLVM-NEXT:     }
+# LLVM-NEXT:     Note {
+# LLVM-NEXT:       Owner: OpenBSD@31337
+# LLVM-NEXT:       Data size: 0x0
+# LLVM-NEXT:       Type: NT_OPENBSD_FPREGS (floating point registers)
+# LLVM-NEXT:     }
+# LLVM-NEXT:   }
+# LLVM-NEXT: ]
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index f47cdc841a7b6..a62eae87197c5 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -5331,6 +5331,14 @@ const NoteType FreeBSDNoteTypes[] = {
      "NT_FREEBSD_FEATURE_CTL (FreeBSD feature control)"},
 };
 
+const NoteType OpenBSDCoreNoteTypes[] = {
+    {ELF::NT_OPENBSD_PROCINFO, "NT_OPENBSD_PROCINFO (procinfo structure)"},
+    {ELF::NT_OPENBSD_AUXV, "NT_OPENBSD_AUXV (ELF auxiliary vector data)"},
+    {ELF::NT_OPENBSD_REGS, "NT_OPENBSD_REGS (regular registers)"},
+    {ELF::NT_OPENBSD_FPREGS, "NT_OPENBSD_FPREGS (floating point registers)"},
+    {ELF::NT_OPENBSD_WCOOKIE, "NT_OPENBSD_WCOOKIE (window cookie)"},
+};
+
 const NoteType AMDNoteTypes[] = {
     {ELF::NT_AMD_HSA_CODE_OBJECT_VERSION,
      "NT_AMD_HSA_CODE_OBJECT_VERSION (AMD HSA Code Object Version)"},
@@ -5443,6 +5451,13 @@ StringRef getNoteTypeName(const typename ELFT::Note &Note, unsigned ELFType) {
       return FindNote(FreeBSDNoteTypes);
     }
   }
+  if (Name.startswith("OpenBSD") && ELFType == ELF::ET_CORE) {
+    // OpenBSD also places the generic core notes in the OpenBSD namespace.
+    StringRef Result = FindNote(OpenBSDCoreNoteTypes);
+    if (!Result.empty())
+      return Result;
+    return FindNote(CoreNoteTypes);
+  }
   if (Name == "AMD")
     return FindNote(AMDNoteTypes);
   if (Name == "AMDGPU")
