From 6dd9a6a1d8e1d6013efed97c3330417ca30a8f40 Mon Sep 17 00:00:00 2001 From: Libor Bukata 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 * 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 * 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 + + * 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 * 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 + + * include/elf/common.h: Note segment constants + for core files on Solaris systems. + 2021-07-03 Nick Clifton * 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