Add Solaris specific ELF note processing

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

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/
	* elf/common.h: Add note segment constants for core files on
	Solaris systems.
This commit is contained in:
Libor Bukata 2021-07-14 11:53:56 +02:00 committed by Alan Modra
parent 98ca73afe5
commit 6420dd27cb
2 changed files with 215 additions and 2 deletions

194
bfd/elf.c
View File

@ -11057,6 +11057,195 @@ 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))
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))
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);
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
elfcore_grok_solaris_note (bfd *abfd, Elf_Internal_Note *note)
{
if (!elfcore_grok_solaris_note_impl (abfd, note))
return false;
return elfcore_grok_note (abfd, note);
}
static bool
elfcore_grok_openbsd_note (bfd *abfd, Elf_Internal_Note *note)
{
@ -12214,10 +12403,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;

View File

@ -742,6 +742,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/". */