[RFC,2/3,bfd] Add Solaris specific ELF note processing.

Message ID MWHPR1001MB222429E4FC4CF3E1CA83FF2AFF139@MWHPR1001MB2224.namprd10.prod.outlook.com
State New
Headers show
Series
  • [RFC,1/3] Fix parsing of auxiliary vector on Solaris.
Related show

Commit Message

Simon Marchi via Gdb-patches July 14, 2021, 1:18 p.m.
From 3dafe7a64cd42a017b58d916e3055d993173563a Mon Sep 17 00:00:00 2001
From: Libor Bukata <libor.bukata@oracle.com>
Date: Wed, 14 Jul 2021 11:53:56 +0200
Subject: [PATCH 2/3] [bfd] Add Solaris specific ELF note processing.

Added elfcore_grok_solaris_note function that enables to
obtain process status, register values, and program info.

Tested on Solaris x86_64/sparcv9 and Linux x86_64.

bfd/ChangeLog:

2021-07-12  Libor Bukata <libor.bukata@oracle.com>

  * elf-bfd.h (elf_backend_grok_lwpstatus): Added function.
  * elfxx-target.h (elf_backend_data): Updated ELF backend data.
  * bfd/elf.c (elfcore_grok_solaris_note): Solaris specific ELF
  note parser. Better GDB's coredump analysis on Solaris...
  (call_elfcore_grok_solaris_note): Helper function.
  (elf_parse_notes): Added "CORE" groker element.
---
 bfd/elf-bfd.h        |   5 +
 bfd/elf.c            | 294 ++++++++++++++++++++++++++++++++++++++++++-
 bfd/elfxx-target.h   |   4 +
 include/elf/common.h |  23 ++++
 4 files changed, 324 insertions(+), 2 deletions(-)

Comments

Simon Marchi via Gdb-patches July 15, 2021, 12:46 a.m. | #1
On 2021-07-14 9:18 a.m., Libor Bukata via Gdb-patches wrote:
> From 3dafe7a64cd42a017b58d916e3055d993173563a Mon Sep 17 00:00:00 2001

> From: Libor Bukata <libor.bukata@oracle.com>

> Date: Wed, 14 Jul 2021 11:53:56 +0200

> Subject: [PATCH 2/3] [bfd] Add Solaris specific ELF note processing.

> 

> Added elfcore_grok_solaris_note function that enables to

> obtain process status, register values, and program info.

> 

> Tested on Solaris x86_64/sparcv9 and Linux x86_64.

> 

> bfd/ChangeLog:

> 

> 2021-07-12  Libor Bukata <libor.bukata@oracle.com>

> 

>   * elf-bfd.h (elf_backend_grok_lwpstatus): Added function.

>   * elfxx-target.h (elf_backend_data): Updated ELF backend data.

>   * bfd/elf.c (elfcore_grok_solaris_note): Solaris specific ELF

>   note parser. Better GDB's coredump analysis on Solaris...

>   (call_elfcore_grok_solaris_note): Helper function.

>   (elf_parse_notes): Added "CORE" groker element.


Hi,

This should be sent to binutils@sourceware.org.

Simon

Patch

diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index b3f56b8c2ce..2427fcb1414 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -1377,6 +1377,11 @@  struct elf_backend_data
   bool (*elf_backend_grok_freebsd_prstatus)
     (bfd *, Elf_Internal_Note *);
 
+  /* This function, if defined, is called when a "Solaris" NT_LWPSTATUS
+     note is found in a core file.  */
+  bool (*elf_backend_grok_lwpstatus)
+    (bfd *, Elf_Internal_Note *);
+
   /* This function, if defined, is called to write a note to a corefile.  */
   char *(*elf_backend_write_core_note)
     (bfd *abfd, char *buf, int *bufsiz, int note_type, ...);
diff --git a/bfd/elf.c b/bfd/elf.c
index de5abafabf0..58297d1dd35 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -9717,7 +9717,10 @@  elfcore_make_note_pseudosection (bfd *abfd,
 static bool
 elfcore_grok_prfpreg (bfd *abfd, Elf_Internal_Note *note)
 {
-  return elfcore_make_note_pseudosection (abfd, ".reg2", note);
+  asection *sect = bfd_get_section_by_name (abfd, ".reg2");
+  if (sect == NULL)
+    return elfcore_make_note_pseudosection (abfd, ".reg2", note);
+  return true;
 }
 
 /* Linux dumps the Intel SSE regs in a note named "LINUX" with a note
@@ -10365,6 +10368,9 @@  elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
 
 #if defined (HAVE_LWPSTATUS_T)
     case NT_LWPSTATUS:
+      if (bed->elf_backend_grok_lwpstatus)
+	if ((*bed->elf_backend_grok_lwpstatus) (abfd, note))
+	  return true;
       return elfcore_grok_lwpstatus (abfd, note);
 #endif
 
@@ -11083,6 +11089,287 @@  elfcore_grok_openbsd_procinfo (bfd *abfd, Elf_Internal_Note *note)
   return true;
 }
 
+#if defined(__sun) || defined(__SVR4)
+#include <sys/types.h>
+#include <sys/elf.h>
+#include <sys/procfs.h>
+#include <sys/regset.h>
+#include <sys/auxv.h>
+
+static bool
+elfcore_grok_solaris_note (bfd *abfd, Elf_Internal_Note *note)
+{
+  asection *sect = NULL;
+  size_t fpregset_size;
+  size_t prgregset_size;
+  size_t prgregset_offset;
+  char reg2_section_name[16] = { 0 };
+
+#ifdef DEBUG
+  static const char* note_type[] = { "NONE (0)", "NT_PRSTATUS", "NT_PRFPREG",
+    "NT_PRPSINFO", "NT_PRXREG", "NT_PLATFORM", "NT_AUXV", "NT_GWINDOWS",
+    "NT_ASRS", "NT_LDT", "NT_PSTATUS", "INVALID (11)", "INVALID (12)",
+    "NT_PSINFO", "NT_PRCRED", "NT_UTSNAME", "NT_LWPSTATUS", "NT_LWPSINFO",
+    "NT_PRPRIV", "NT_PRPRIVINFO", "NT_CONTENT", "NT_ZONENAME",
+    "NT_PRCPUXREG", NULL };
+#endif
+
+  if (note == NULL)
+    return true;
+
+  /* core files are identified as 32- or 64-bit, SPARC or x86,
+     by the size of the descsz which matches the sizeof()
+     the type appropriate for that note type (e.g., prstatus_t for
+     SOLARIS_NT_PRSTATUS) for the corresponding architecture
+     on Solaris. The core file bitness may differ from the bitness of
+     gdb itself, so fixed values are used instead of sizeof().
+     Appropriate fixed offsets are also used to obtain data from
+     the note */
+
+  switch ((int) note->type)
+  {
+    case SOLARIS_NT_PRSTATUS:
+      if (note->descsz == 508) /* sizeof(prstatus_t) SPARC 32-bit */
+      {
+        prgregset_size = 152; /* sizeof(prgregset_t) SPARC 32-bit */
+        prgregset_offset = 356; /* offsetof(prstatus_t, pr_reg) */
+
+        elf_tdata (abfd)->core->signal =
+          bfd_get_16 (abfd, note->descdata + 136);
+        elf_tdata (abfd)->core->pid =
+          bfd_get_32 (abfd, note->descdata + 216);
+        elf_tdata (abfd)->core->lwpid =
+          bfd_get_32 (abfd, note->descdata + 308);
+      }
+      else if (note->descsz == 904) /* sizeof(prstatus_t) SPARC 64-bit */
+      {
+        prgregset_size = 304; /* sizeof(prgregset_t) SPARC 64-bit */
+        prgregset_offset = 600; /* offsetof(prstatus_t, pr_reg) */
+
+        elf_tdata (abfd)->core->signal =
+          bfd_get_16 (abfd, note->descdata + 264);
+        elf_tdata (abfd)->core->pid =
+          bfd_get_32 (abfd, note->descdata + 360);
+        elf_tdata (abfd)->core->lwpid =
+          bfd_get_32 (abfd, note->descdata + 520);
+      }
+      else if (note->descsz == 432) /* sizeof(prstatus_t) Intel 32-bit */
+      {
+        prgregset_size = 76; /* sizeof(prgregset_t) Intel 32-bit */
+        prgregset_offset = 356; /* offsetof(prstatus_t, pr_reg) */
+
+        elf_tdata (abfd)->core->signal =
+          bfd_get_16 (abfd, note->descdata + 136);
+        elf_tdata (abfd)->core->pid =
+          bfd_get_32 (abfd, note->descdata + 216);
+        elf_tdata (abfd)->core->lwpid =
+          bfd_get_32 (abfd, note->descdata + 308);
+      }
+      else if (note->descsz == 824) /* sizeof(prstatus_t) Intel 64-bit */
+      {
+        prgregset_size = 224; /* sizeof(prgregset_t) Intel 64-bit */
+        prgregset_offset = 600; /* offsetof(prstatus_t, pr_reg) */
+
+        elf_tdata (abfd)->core->signal =
+          bfd_get_16 (abfd, note->descdata + 264);
+        elf_tdata (abfd)->core->pid =
+          bfd_get_32 (abfd, note->descdata + 360);
+        elf_tdata (abfd)->core->lwpid =
+          bfd_get_32 (abfd, note->descdata + 520);
+      }
+
+      sect = bfd_get_section_by_name (abfd, ".reg");
+      if (sect != NULL)
+        sect->size = prgregset_size;
+
+      return _bfd_elfcore_make_pseudosection (abfd, ".reg",
+          prgregset_size, note->descpos + prgregset_offset);
+    case SOLARIS_NT_PRPSINFO:
+      if (note->descsz == 260) /* sizeof(prpsinfo_t) */
+      {
+          /* offsetof(prpsinfo, pr_fname) */
+        elf_tdata (abfd)->core->program
+          = _bfd_elfcore_strndup (abfd, note->descdata + 84, 16);
+          /* offsetof(prpsinfo, pr_psargs) */
+        elf_tdata (abfd)->core->command
+          = _bfd_elfcore_strndup (abfd, note->descdata + 100, 80);
+      }
+      break;
+    case SOLARIS_NT_PSINFO:
+      if (note->descsz == 336) /* sizeof(psinfo_t) SPARC */
+      {
+          /* offsetof(psinfo_t, pr_fname) */
+        elf_tdata (abfd)->core->program
+          = _bfd_elfcore_strndup (abfd, note->descdata + 88, 16);
+          /* offsetof(psinfo_t, pr_psargs) */
+        elf_tdata (abfd)->core->command
+          = _bfd_elfcore_strndup (abfd, note->descdata + 104, 80);
+      }
+      else if (note->descsz == 360) /* sizeof(psinfo_t) Intel */
+      {
+          /* offsetof(psinfo_t, pr_fname) */
+        elf_tdata (abfd)->core->program
+          = _bfd_elfcore_strndup (abfd, note->descdata + 88, 16);
+          /* offsetof(psinfo_t, pr_psargs) */
+        elf_tdata (abfd)->core->command
+          = _bfd_elfcore_strndup (abfd, note->descdata + 104, 80);
+      }
+      break;
+    case SOLARIS_NT_LWPSTATUS:
+          /* offsetof(lwpstatus_t, pr_lwpid */
+        elf_tdata (abfd)->core->lwpid =
+          bfd_get_32 (abfd, note->descdata + 4);
+          /* offsetof(lwpstatus_t, pr_cursig */
+        elf_tdata (abfd)->core->signal =
+          bfd_get_16 (abfd, note->descdata + 12);
+        (void) snprintf (reg2_section_name, 16, "%s/%i", ".reg2",
+            *(int*)(note->descdata + 4));
+
+        if (note->descsz == 896) /* sizeof(lwpstatus_t) SPARC 32-bit */
+        {
+          fpregset_size = 400;  /* sizeof(fpregset_t) SPARC 32-bit */
+          prgregset_size = 152; /* sizeof(prgregset_t) SPARC 32-bit */
+
+          sect = bfd_get_section_by_name (abfd, ".reg");
+          if (sect != NULL)
+            sect->size = sizeof(prgregset_t);
+          else
+          {
+            if ((_bfd_elfcore_make_pseudosection (abfd, ".reg",
+                    prgregset_size,
+                    note->descpos + 344)) != true)
+              return false;
+          }
+          sect = bfd_get_section_by_name (abfd, reg2_section_name);
+
+          if (sect != NULL)
+          {
+            sect->size = fpregset_size;
+            sect->filepos = note->descpos + 496;
+            sect->alignment_power = 2;
+            return true;
+          }
+          else
+            return _bfd_elfcore_make_pseudosection (abfd, ".reg2",
+                fpregset_size, note->descpos + 496);
+        }
+        else if (note->descsz == 1392) /* sizeof(lwpstatus_t) SPARC 64-bit */
+        {
+          fpregset_size = 544;  /* sizeof(fpregset_t) SPARC 64-bit */
+          prgregset_size = 304; /* sizeof(prgregset_t) SPARC 64-bit */
+
+          sect = bfd_get_section_by_name (abfd, ".reg");
+          if (sect != NULL)
+            sect->size = sizeof(prgregset_t);
+          else
+          {
+            if ((_bfd_elfcore_make_pseudosection (abfd, ".reg",
+                    prgregset_size,
+                    note->descpos + 544)) != true)
+              return false;
+          }
+          sect = bfd_get_section_by_name (abfd, reg2_section_name);
+
+          if (sect != NULL)
+          {
+            sect->size = fpregset_size;
+            sect->filepos = note->descpos + 848;
+            sect->alignment_power = 2;
+            return true;
+          }
+          else
+            return _bfd_elfcore_make_pseudosection (abfd, ".reg2",
+                fpregset_size, note->descpos + 848);
+        }
+        else if (note->descsz == 800) /* sizeof(lwpstatus_t) Intel 32-bit */
+        {
+          fpregset_size = 380;  /* sizeof(fpregset_t) Intel 32-bit */
+          prgregset_size = 76;  /* sizeof(prgregset_t) Intel 32-bit */
+
+          sect = bfd_get_section_by_name (abfd, ".reg");
+          if (sect != NULL)
+            sect->size = prgregset_size;
+          else
+          {
+            if ((_bfd_elfcore_make_pseudosection (abfd, ".reg",
+                    prgregset_size,
+                    note->descpos + 344)) != true)
+              return false;
+          }
+          sect = bfd_get_section_by_name (abfd, reg2_section_name);
+
+          if (sect != NULL)
+          {
+            sect->size = fpregset_size;
+            sect->filepos = note->descpos + 420;
+            sect->alignment_power = 2;
+            return true;
+          }
+          else
+            return _bfd_elfcore_make_pseudosection (abfd, ".reg2",
+                fpregset_size, note->descpos + 420);
+        }
+        else if (note->descsz == 1296) /* sizeof(lwpstatus_t) Intel 64-bit */
+        {
+          fpregset_size = 528; /* sizeof(fpregset_t) Intel 64-bit */
+          prgregset_size = 224; /* sizeof(prgregset_t) Intel 64-bit */
+
+          sect = bfd_get_section_by_name (abfd, ".reg");
+          if (sect != NULL)
+            sect->size = prgregset_size;
+          else
+          {
+            if ((_bfd_elfcore_make_pseudosection (abfd, ".reg",
+                    prgregset_size,
+                    note->descpos + 544)) != true)
+              return false;
+          }
+          sect = bfd_get_section_by_name (abfd, reg2_section_name);
+
+          if (sect != NULL)
+          {
+            sect->size = fpregset_size;
+            sect->filepos = note->descpos + 768;
+            sect->alignment_power = 2;
+            return true;
+          }
+          else
+            return _bfd_elfcore_make_pseudosection (abfd, ".reg2",
+                fpregset_size, note->descpos + 768);
+        }
+      break;
+    case SOLARIS_NT_LWPSINFO:
+        if (note->descsz == 128) /* sizeof(lwpsinfo_t) Intel and SPARC */
+        {
+          elf_tdata (abfd)->core->lwpid =
+            bfd_get_32 (abfd, note->descdata + 4);
+        }
+        break;
+    default:
+      break;
+  }
+
+  return true;
+}
+
+/*
+ * for name starting with "CORE" this may be either a Solaris
+ * core file or a gdb-generated core file.  Do Solaris-specific
+ * processing on selected note types first with
+ * elfcore_grok_solaris_note(), then process the note
+ * in elfcore_grok_note().
+ */
+static bool
+call_elfcore_grok_solaris_note (bfd *abfd, Elf_Internal_Note *note)
+{
+  if (! elfcore_grok_solaris_note (abfd, note)) {
+    return false;
+  } else {
+    return elfcore_grok_note (abfd, note);
+  }
+}
+#endif
+
 static bool
 elfcore_grok_openbsd_note (bfd *abfd, Elf_Internal_Note *note)
 {
@@ -12243,7 +12530,10 @@  elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset,
 	      GROKER_ELEMENT ( "OpenBSD", elfcore_grok_openbsd_note),
 	      GROKER_ELEMENT ("QNX", elfcore_grok_nto_note),
 	      GROKER_ELEMENT ("SPU/", elfcore_grok_spu_note),
-	      GROKER_ELEMENT ("GNU", elfobj_grok_gnu_note)
+	      GROKER_ELEMENT ("GNU", elfobj_grok_gnu_note),
+#if defined(__sun) || defined(__SVR4)
+	      GROKER_ELEMENT ("CORE", call_elfcore_grok_solaris_note)
+#endif
 	    };
 #undef GROKER_ELEMENT
 	    int i;
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index 4c6b1f20340..edd337dfd7b 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -624,6 +624,9 @@ 
 #ifndef elf_backend_grok_psinfo
 #define elf_backend_grok_psinfo			NULL
 #endif
+#ifndef elf_backend_grok_lwpstatus
+#define elf_backend_grok_lwpstatus			NULL
+#endif
 #ifndef elf_backend_grok_freebsd_prstatus
 #define elf_backend_grok_freebsd_prstatus	NULL
 #endif
@@ -875,6 +878,7 @@  static const struct elf_backend_data elfNN_bed =
   elf_backend_sort_relocs_p,
   elf_backend_grok_prstatus,
   elf_backend_grok_psinfo,
+  elf_backend_grok_lwpstatus,
   elf_backend_grok_freebsd_prstatus,
   elf_backend_write_core_note,
   elf_backend_lookup_section_flags_hook,
diff --git a/include/elf/common.h b/include/elf/common.h
index 6e6287206ca..a1ea7ff831f 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -739,6 +739,29 @@ 
 #define NT_OPENBSD_WCOOKIE	23
 
 
+/* Note segments for core files on Solaris systems.  Note name
+   must start with "CORE".  */
+#define SOLARIS_NT_PRSTATUS    1
+#define SOLARIS_NT_PRFPREG     2
+#define SOLARIS_NT_PRPSINFO    3
+#define SOLARIS_NT_PRXREG      4
+#define SOLARIS_NT_PLATFORM    5
+#define SOLARIS_NT_AUXV        6
+#define SOLARIS_NT_GWINDOWS    7
+#define SOLARIS_NT_ASRS        8
+#define SOLARIS_NT_LDT         9
+#define SOLARIS_NT_PSTATUS    10
+#define SOLARIS_NT_PSINFO     13
+#define SOLARIS_NT_PRCRED     14
+#define SOLARIS_NT_UTSNAME    15
+#define SOLARIS_NT_LWPSTATUS  16
+#define SOLARIS_NT_LWPSINFO   17
+#define SOLARIS_NT_PRPRIV     18
+#define SOLARIS_NT_PRPRIVINFO 19
+#define SOLARIS_NT_CONTENT    20
+#define SOLARIS_NT_ZONENAME   21
+#define SOLARIS_NT_PRCPUXREG  22
+
 /* Note segments for core files on SPU systems.  Note name
    must start with "SPU/".  */