[RFC] Add Solaris specific ELF note processing.

Message ID MWHPR1001MB2224D8D17A7D6B3DEF2E0E66FFE19@MWHPR1001MB2224.namprd10.prod.outlook.com
State New
Headers show
Series
  • [RFC] Add Solaris specific ELF note processing.
Related show

Commit Message

Alan Modra via Binutils July 19, 2021, 7:09 a.m.
From f22881a7543ae96a00d0b6d7c5183d4451af7a8d 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] [bfd] Add Solaris specific ELF note processing.

Added elfcore_grok_solaris_note function that enables to
obtain process status, register values, and program info
from Solaris's core files.

Tested on Solaris x86_64/sparcv9 and Linux x86_64.

bfd/ChangeLog:

2021-07-16  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...
  (elfcore_grok_solaris_note_impl): New function.
  (elfcore_grok_solaris_prstatus): New function.
  (elfcore_grok_solaris_info): New function.
  (elfcore_grok_solaris_lwpstatus): New function.
  (elf_parse_notes): Added "CORE" groker element.

include/ChangeLog:

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

  * include/elf/common.h: Note segment constants
  for core files on Solaris systems.
---
 bfd/ChangeLog        |  12 +++
 bfd/elf-bfd.h        |   5 ++
 bfd/elf.c            | 203 ++++++++++++++++++++++++++++++++++++++++++-
 bfd/elfxx-target.h   |   4 +
 include/ChangeLog    |   5 ++
 include/elf/common.h |  23 +++++
 6 files changed, 249 insertions(+), 3 deletions(-)

Comments

Alan Modra via Binutils July 28, 2021, 9:14 a.m. | #1
On Mon, Jul 19, 2021 at 07:09:47AM +0000, Libor Bukata via Binutils wrote:
> 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 *);

> +


Why did you add this?  There is no place where it is defined as
anything other than NULL.

>    /* 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..d39b4bd3b88 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


The above was not described or mentioned in a ChangeLog.  Why do you
need this?

There are also rather a lot of formatting errors in the rest of the
patch.

-- 
Alan Modra
Australia Development Lab, IBM
Alan Modra via Binutils July 30, 2021, 3:18 p.m. | #2
Hi Alan,

thank you for looking into it.

On 7/28/21 11:14 AM, Alan Modra wrote:
> On Mon, Jul 19, 2021 at 07:09:47AM +0000, Libor Bukata via Binutils wrote:

>> 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 *);

>> +

> Why did you add this?  There is no place where it is defined as

> anything other than NULL.

Frankly speaking, I am not the original author of the patch but I 
maintain, update, and refactor it on behalf of Oracle. I got the 
approvals from Oracle to contribute it to binutils project. I removed 
elf_backend_grok_lwpstatus since it is obviously not needed.
>

>>     /* 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..d39b4bd3b88 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

> The above was not described or mentioned in a ChangeLog.  Why do you

> need this?

Maybe it was required with older GDB versions. I removed it and 
retested.  Note that elfcore_make_note_pseudosection returns false only 
in case of errors and the existence of a section is not considered an 
error...
>

> There are also rather a lot of formatting errors in the rest of the

> patch.

>

I hopefully improved the code formatting (lines with at max 79 
characters, aligned function arguments). Let me know if more work is 
needed. Thanks.

Testing:

Solaris: Verified that general and float registers are loaded from core 
files on both x86 and sparc.
Linux: No regressions in binutils unit tests. Loaded a core file 
generated by GDB.

I have some issues with my email client, therefore, I attached the patch 
instead of inlining the text.

I have a favor to ask you, could you please check the following auxv fix 
from binutils side?
https://sourceware.org/pipermail/gdb-patches/2021-July/180967.html

I need an approval of AT_SUN_CAP_HW3 constant addition. Simon Marchi 
approved GDB changes. Many thanks.

Regards,
Libor
From 6dd9a6a1d8e1d6013efed97c3330417ca30a8f40 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] [bfd] Add Solaris specific ELF note processing.

Added elfcore_grok_solaris_note function that enables to
obtain process status, register values, and program info
from Solaris's core files.

Tested on Solaris x86_64/sparcv9 and Linux x86_64.

bfd/ChangeLog:

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

  * bfd/elf.c (elfcore_grok_solaris_note): Solaris specific ELF
  note parser. Better GDB's coredump analysis on Solaris...
  (elfcore_grok_solaris_note_impl): New function.
  (elfcore_grok_solaris_prstatus): New function.
  (elfcore_grok_solaris_info): New function.
  (elfcore_grok_solaris_lwpstatus): New function.
  (elf_parse_notes): Added "CORE" groker element.

include/ChangeLog:

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

  * include/elf/common.h: Note segment constants
  for core files on Solaris systems.
---
 bfd/ChangeLog        |  10 +++
 bfd/elf.c            | 204 ++++++++++++++++++++++++++++++++++++++++++-
 include/ChangeLog    |   5 ++
 include/elf/common.h |  23 +++++
 4 files changed, 240 insertions(+), 2 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 4dc3d685255..84af0079eba 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,13 @@
+2021-07-16  Libor Bukata <libor.bukata@oracle.com>
+
+	* bfd/elf.c (elfcore_grok_solaris_note): Solaris specific ELF
+	note parser. Better GDB's coredump analysis on Solaris...
+	(elfcore_grok_solaris_note_impl): New function.
+	(elfcore_grok_solaris_prstatus): New function.
+	(elfcore_grok_solaris_info): New function.
+	(elfcore_grok_solaris_lwpstatus): New function.
+	(elf_parse_notes): Added "CORE" groker element.
+
 2021-07-10  Alan Modra  <amodra@gmail.com>
 
 	* dwarf2.c (read_address): Remove accidental commit.
diff --git a/bfd/elf.c b/bfd/elf.c
index de5abafabf0..5d0be59a2ed 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -11083,6 +11083,205 @@ elfcore_grok_openbsd_procinfo (bfd *abfd, Elf_Internal_Note *note)
   return true;
 }
 
+/* Processes Solaris's process status note.
+   sig_off ~ offsetof(prstatus_t, pr_cursig)
+   pid_off ~ offsetof(prstatus_t, pr_pid)
+   lwpid_off ~ offsetof(prstatus_t, pr_who)
+   gregset_size ~ sizeof(gregset_t)
+   gregset_offset ~ offsetof(prstatus_t, pr_reg) */
+static bool
+elfcore_grok_solaris_prstatus (bfd *abfd, Elf_Internal_Note* note, int sig_off,
+                               int pid_off, int lwpid_off, size_t gregset_size,
+                               size_t gregset_offset)
+{
+  asection *sect = NULL;
+  elf_tdata (abfd)->core->signal =
+    bfd_get_16 (abfd, note->descdata + sig_off);
+  elf_tdata (abfd)->core->pid =
+    bfd_get_32 (abfd, note->descdata + pid_off);
+  elf_tdata (abfd)->core->lwpid =
+    bfd_get_32 (abfd, note->descdata + lwpid_off);
+
+  sect = bfd_get_section_by_name (abfd, ".reg");
+  if (sect != NULL)
+    sect->size = gregset_size;
+
+  return _bfd_elfcore_make_pseudosection (abfd, ".reg",
+      gregset_size, note->descpos + gregset_offset);
+}
+
+/* Gets program and arguments from a core.
+   prog_off ~ offsetof(prpsinfo | psinfo_t, pr_fname)
+   comm_off ~ offsetof(prpsinfo | psinfo_t, pr_psargs) */
+static bool
+elfcore_grok_solaris_info(bfd *abfd, Elf_Internal_Note* note,
+                          int prog_off, int comm_off)
+{
+  elf_tdata (abfd)->core->program
+    = _bfd_elfcore_strndup (abfd, note->descdata + prog_off, 16);
+  elf_tdata (abfd)->core->command
+    = _bfd_elfcore_strndup (abfd, note->descdata + comm_off, 80);
+
+  return true;
+}
+
+/* Processes Solaris's LWP status note.
+   gregset_size ~ sizeof(gregset_t)
+   gregset_off ~ offsetof(lwpstatus_t, pr_reg)
+   fpregset_size ~ sizeof(fpregset_t)
+   fpregset_off ~ offsetof(lwpstatus_t, pr_fpreg)
+*/
+static bool
+elfcore_grok_solaris_lwpstatus (bfd *abfd, Elf_Internal_Note* note,
+                                size_t gregset_size, int gregset_off,
+                                size_t fpregset_size, int fpregset_off)
+{
+  asection *sect = NULL;
+  char reg2_section_name[16] = { 0 };
+  (void) snprintf (reg2_section_name, 16, "%s/%i", ".reg2",
+      elf_tdata (abfd)->core->lwpid);
+
+  /* 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);
+
+  sect = bfd_get_section_by_name (abfd, ".reg");
+  if (sect != NULL)
+  {
+    sect->size = gregset_size;
+  }
+  else
+  {
+    if ((_bfd_elfcore_make_pseudosection (abfd, ".reg",
+            gregset_size, note->descpos + gregset_off)) != true)
+      return false;
+  }
+
+  sect = bfd_get_section_by_name (abfd, reg2_section_name);
+  if (sect != NULL)
+  {
+    sect->size = fpregset_size;
+    sect->filepos = note->descpos + fpregset_off;
+    sect->alignment_power = 2;
+  }
+  else
+  {
+    if ((_bfd_elfcore_make_pseudosection (abfd, ".reg2",
+            fpregset_size, note->descpos + fpregset_off)) != true)
+      return false;
+  }
+
+  return true;
+}
+
+static bool
+elfcore_grok_solaris_note_impl (bfd *abfd, Elf_Internal_Note *note)
+{
+  if (note == NULL)
+    return false;
+
+  /* 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:
+      switch (note->descsz)
+      {
+        case 508: /* sizeof(prstatus_t) SPARC 32-bit */
+          return elfcore_grok_solaris_prstatus(abfd, note,
+                                               136, 216, 308, 152, 356);
+        case 904: /* sizeof(prstatus_t) SPARC 64-bit */
+          return elfcore_grok_solaris_prstatus(abfd, note,
+                                               264, 360, 520, 304, 600);
+        case 432: /* sizeof(prstatus_t) Intel 32-bit */
+          return elfcore_grok_solaris_prstatus(abfd, note,
+                                               136, 216, 308, 76, 356);
+        case 824: /* sizeof(prstatus_t) Intel 64-bit */
+          return elfcore_grok_solaris_prstatus(abfd, note,
+                                               264, 360, 520, 224, 600);
+        default:
+          return true;
+      }
+
+    case SOLARIS_NT_PSINFO:
+    case SOLARIS_NT_PRPSINFO:
+      switch (note->descsz)
+      {
+        case 260: /* sizeof(prpsinfo_t) SPARC and Intel 32-bit */
+          return elfcore_grok_solaris_info(abfd, note, 84, 100);
+        case 328: /* sizeof(prpsinfo_t) SPARC and Intel 64-bit */
+          return elfcore_grok_solaris_info(abfd, note, 120, 136);
+        case 360: /* sizeof(psinfo_t) SPARC and Intel 32-bit */
+          return elfcore_grok_solaris_info(abfd, note, 88, 104);
+        case 440: /* sizeof(psinfo_t) SPARC and Intel 64-bit */
+          return elfcore_grok_solaris_info(abfd, note, 136, 152);
+        default:
+          return true;
+      }
+
+    case SOLARIS_NT_LWPSTATUS:
+      switch (note->descsz)
+      {
+        case 896: /* sizeof(lwpstatus_t) SPARC 32-bit */
+          return elfcore_grok_solaris_lwpstatus(abfd, note,
+                                                152, 344, 400, 496);
+        case 1392: /* sizeof(lwpstatus_t) SPARC 64-bit */
+          return elfcore_grok_solaris_lwpstatus(abfd, note,
+                                                304, 544, 544, 848);
+        case 800: /* sizeof(lwpstatus_t) Intel 32-bit */
+          return elfcore_grok_solaris_lwpstatus(abfd, note,
+                                                76, 344, 380, 420);
+        case 1296: /* sizeof(lwpstatus_t) Intel 64-bit */
+          return elfcore_grok_solaris_lwpstatus(abfd, note,
+                                                224, 544, 528, 768);
+        default:
+          return true;
+      }
+
+    case SOLARIS_NT_LWPSINFO:
+      /* sizeof(lwpsinfo_t) on 32- and 64-bit, respectively */
+      if (note->descsz == 128 || note->descsz == 152)
+      {
+        elf_tdata (abfd)->core->lwpid =
+          bfd_get_32 (abfd, note->descdata + 4);
+      }
+      else
+      {
+        return true;
+      }
+
+    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
+elfcore_grok_solaris_note (bfd *abfd, Elf_Internal_Note *note)
+{
+  if (! elfcore_grok_solaris_note_impl (abfd, note)) {
+    return false;
+  } else {
+    return elfcore_grok_note (abfd, note);
+  }
+}
+
 static bool
 elfcore_grok_openbsd_note (bfd *abfd, Elf_Internal_Note *note)
 {
@@ -12240,10 +12439,11 @@ elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset,
 	      GROKER_ELEMENT ("", elfcore_grok_note),
 	      GROKER_ELEMENT ("FreeBSD", elfcore_grok_freebsd_note),
 	      GROKER_ELEMENT ("NetBSD-CORE", elfcore_grok_netbsd_note),
-	      GROKER_ELEMENT ( "OpenBSD", elfcore_grok_openbsd_note),
+	      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),
+	      GROKER_ELEMENT ("CORE", elfcore_grok_solaris_note)
 	    };
 #undef GROKER_ELEMENT
 	    int i;
diff --git a/include/ChangeLog b/include/ChangeLog
index 11001a3d1e3..b242eeb7df2 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,8 @@
+2021-07-16  Libor Bukata <libor.bukata@oracle.com>
+
+	* include/elf/common.h: Note segment constants
+	for core files on Solaris systems.
+
 2021-07-03  Nick Clifton  <nickc@redhat.com>
 
 	* 2.37 release branch created.
diff --git a/include/elf/common.h b/include/elf/common.h
index 0d381f0d27b..7a00542cbdc 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/".  */
 
-- 
2.31.1
Alan Modra via Binutils Sept. 30, 2021, 7:08 a.m. | #3
On Fri, Jul 30, 2021 at 05:18:40PM +0200, Libor Bukata wrote:
> I hopefully improved the code formatting (lines with at max 79 characters,

> aligned function arguments). Let me know if more work is needed. Thanks.


I've made a few more style/formatting fixes and now committed the
patch.  Sorry for the long delay, your email got lost in my inbox.

> I have a favor to ask you, could you please check the following auxv fix

> from binutils side?

> https://sourceware.org/pipermail/gdb-patches/2021-July/180967.html

> 

> I need an approval of AT_SUN_CAP_HW3 constant addition. Simon Marchi

> approved GDB changes. Many thanks.


OK, and it's completely fine by me for Simon or any of the gdb global
maintainers to OK patches like this in shared directories.

-- 
Alan Modra
Australia Development Lab, IBM

Patch

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 4dc3d685255..18098dc0f0d 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,15 @@ 
+2021-07-16  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...
+	(elfcore_grok_solaris_note_impl): New function.
+	(elfcore_grok_solaris_prstatus): New function.
+	(elfcore_grok_solaris_info): New function.
+	(elfcore_grok_solaris_lwpstatus): New function.
+	(elf_parse_notes): Added "CORE" groker element.
+
 2021-07-10  Alan Modra  <amodra@gmail.com>
 
 	* dwarf2.c (read_address): Remove accidental commit.
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..d39b4bd3b88 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,196 @@  elfcore_grok_openbsd_procinfo (bfd *abfd, Elf_Internal_Note *note)
   return true;
 }
 
+/* Processes Solaris's process status note.
+   sig_off ~ offsetof(prstatus_t, pr_cursig)
+   pid_off ~ offsetof(prstatus_t, pr_pid)
+   lwpid_off ~ offsetof(prstatus_t, pr_who)
+   gregset_size ~ sizeof(gregset_t)
+   gregset_offset ~ offsetof(prstatus_t, pr_reg) */
+static bool
+elfcore_grok_solaris_prstatus (bfd *abfd, Elf_Internal_Note* note,
+    int sig_off, int pid_off, int lwpid_off, size_t gregset_size,
+    size_t gregset_offset)
+{
+  asection *sect = NULL;
+  elf_tdata (abfd)->core->signal =
+    bfd_get_16 (abfd, note->descdata + sig_off);
+  elf_tdata (abfd)->core->pid =
+    bfd_get_32 (abfd, note->descdata + pid_off);
+  elf_tdata (abfd)->core->lwpid =
+    bfd_get_32 (abfd, note->descdata + lwpid_off);
+
+  sect = bfd_get_section_by_name (abfd, ".reg");
+  if (sect != NULL)
+    sect->size = gregset_size;
+
+  return _bfd_elfcore_make_pseudosection (abfd, ".reg",
+      gregset_size, note->descpos + gregset_offset);
+}
+
+/* Gets program and arguments from a core.
+   prog_off ~ offsetof(prpsinfo | psinfo_t, pr_fname)
+   comm_off ~ offsetof(prpsinfo | psinfo_t, pr_psargs) */
+static bool
+elfcore_grok_solaris_info(bfd *abfd, Elf_Internal_Note* note,
+    int prog_off, int comm_off)
+{
+  elf_tdata (abfd)->core->program
+    = _bfd_elfcore_strndup (abfd, note->descdata + prog_off, 16);
+  elf_tdata (abfd)->core->command
+    = _bfd_elfcore_strndup (abfd, note->descdata + comm_off, 80);
+
+  return true;
+}
+
+/* Processes Solaris's LWP status note.
+   gregset_size ~ sizeof(gregset_t)
+   gregset_off ~ offsetof(lwpstatus_t, pr_reg)
+   fpregset_size ~ sizeof(fpregset_t)
+   fpregset_off ~ offsetof(lwpstatus_t, pr_fpreg)
+*/
+static bool
+elfcore_grok_solaris_lwpstatus (bfd *abfd, Elf_Internal_Note* note,
+    size_t gregset_size, int gregset_off, size_t fpregset_size, int fpregset_off)
+{
+  asection *sect = NULL;
+  char reg2_section_name[16] = { 0 };
+  (void) snprintf (reg2_section_name, 16, "%s/%i", ".reg2",
+      elf_tdata (abfd)->core->lwpid);
+
+  /* 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);
+
+  sect = bfd_get_section_by_name (abfd, ".reg");
+  if (sect != NULL)
+  {
+    sect->size = gregset_size;
+  }
+  else
+  {
+    if ((_bfd_elfcore_make_pseudosection (abfd, ".reg",
+            gregset_size, note->descpos + gregset_off)) != true)
+      return false;
+  }
+
+  sect = bfd_get_section_by_name (abfd, reg2_section_name);
+  if (sect != NULL)
+  {
+    sect->size = fpregset_size;
+    sect->filepos = note->descpos + fpregset_off;
+    sect->alignment_power = 2;
+  }
+  else
+  {
+    if ((_bfd_elfcore_make_pseudosection (abfd, ".reg2",
+            fpregset_size, note->descpos + fpregset_off)) != true)
+      return false;
+  }
+
+  return true;
+}
+
+static bool
+elfcore_grok_solaris_note_impl (bfd *abfd, Elf_Internal_Note *note)
+{
+  if (note == NULL)
+    return false;
+
+  /* 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:
+      switch (note->descsz)
+      {
+        case 508: /* sizeof(prstatus_t) SPARC 32-bit */
+          return elfcore_grok_solaris_prstatus(abfd, note, 136, 216, 308, 152, 356);
+        case 904: /* sizeof(prstatus_t) SPARC 64-bit */
+          return elfcore_grok_solaris_prstatus(abfd, note, 264, 360, 520, 304, 600);
+        case 432: /* sizeof(prstatus_t) Intel 32-bit */
+          return elfcore_grok_solaris_prstatus(abfd, note, 136, 216, 308, 76, 356);
+        case 824: /* sizeof(prstatus_t) Intel 64-bit */
+          return elfcore_grok_solaris_prstatus(abfd, note, 264, 360, 520, 224, 600);
+        default:
+          return true;
+      }
+
+    case SOLARIS_NT_PSINFO:
+    case SOLARIS_NT_PRPSINFO:
+      switch (note->descsz)
+      {
+        case 260: /* sizeof(prpsinfo_t) SPARC and Intel 32-bit */
+          return elfcore_grok_solaris_info(abfd, note, 84, 100);
+        case 328: /* sizeof(prpsinfo_t) SPARC and Intel 64-bit */
+          return elfcore_grok_solaris_info(abfd, note, 120, 136);
+        case 360: /* sizeof(psinfo_t) SPARC and Intel 32-bit */
+          return elfcore_grok_solaris_info(abfd, note, 88, 104);
+        case 440: /* sizeof(psinfo_t) SPARC and Intel 64-bit */
+          return elfcore_grok_solaris_info(abfd, note, 136, 152);
+        default:
+          return true;
+      }
+
+    case SOLARIS_NT_LWPSTATUS:
+      switch (note->descsz)
+      {
+        case 896: /* sizeof(lwpstatus_t) SPARC 32-bit */
+          return elfcore_grok_solaris_lwpstatus(abfd, note, 152, 344, 400, 496);
+        case 1392: /* sizeof(lwpstatus_t) SPARC 64-bit */
+          return elfcore_grok_solaris_lwpstatus(abfd, note, 304, 544, 544, 848);
+        case 800: /* sizeof(lwpstatus_t) Intel 32-bit */
+          return elfcore_grok_solaris_lwpstatus(abfd, note, 76, 344, 380, 420);
+        case 1296: /* sizeof(lwpstatus_t) Intel 64-bit */
+          return elfcore_grok_solaris_lwpstatus(abfd, note, 224, 544, 528, 768);
+        default:
+          return true;
+      }
+
+    case SOLARIS_NT_LWPSINFO:
+      /* sizeof(lwpsinfo_t) on 32- and 64-bit, respectively */
+      if (note->descsz == 128 || note->descsz == 152)
+      {
+        elf_tdata (abfd)->core->lwpid =
+          bfd_get_32 (abfd, note->descdata + 4);
+      }
+      else
+      {
+        return true;
+      }
+
+    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
+elfcore_grok_solaris_note (bfd *abfd, Elf_Internal_Note *note)
+{
+  if (! elfcore_grok_solaris_note_impl (abfd, note)) {
+    return false;
+  } else {
+    return elfcore_grok_note (abfd, note);
+  }
+}
+
 static bool
 elfcore_grok_openbsd_note (bfd *abfd, Elf_Internal_Note *note)
 {
@@ -12240,10 +12436,11 @@  elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset,
 	      GROKER_ELEMENT ("", elfcore_grok_note),
 	      GROKER_ELEMENT ("FreeBSD", elfcore_grok_freebsd_note),
 	      GROKER_ELEMENT ("NetBSD-CORE", elfcore_grok_netbsd_note),
-	      GROKER_ELEMENT ( "OpenBSD", elfcore_grok_openbsd_note),
+	      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),
+	      GROKER_ELEMENT ("CORE", elfcore_grok_solaris_note)
 	    };
 #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/ChangeLog b/include/ChangeLog
index 11001a3d1e3..b242eeb7df2 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,8 @@ 
+2021-07-16  Libor Bukata <libor.bukata@oracle.com>
+
+	* include/elf/common.h: Note segment constants
+	for core files on Solaris systems.
+
 2021-07-03  Nick Clifton  <nickc@redhat.com>
 
 	* 2.37 release branch created.
diff --git a/include/elf/common.h b/include/elf/common.h
index 0d381f0d27b..7a00542cbdc 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/".  */