bfd/riscv: prepare to handle bare metal core dump creation

When creating a core file GDB will call the function
elfcore_write_prstatus to write out the general purpose registers
along with the pid/tid for the thread (into a prstatus structure) and
the executable name and arguments (into a prpsinfo_t structure).

However, for a bare metal RISC-V tool chain the prstatus_t and
prpsinfo_t types are not defined so the elfcore_write_prstatus
function will return NULL, preventing core file creation.

This commit provides the `elf_backend_write_core_note' hook and uses
the provided function to write out the required information.

In order to keep changes in the non bare metal tools to a minimum, the
provided backend function will itself return NULL when the prstatus_t
or pspsinfo_t types are available, the consequence of this is that the
generic code in elfcore_write_prstatus will be used just as before.
But, when prstatus_t or prpsinfo_t is not available, the new backend
function will write out the information using predefined offsets.

This new functionality will be used by a later GDB commit that will
add bare metal core dumps for RISC-V.

bfd/ChangeLog:

	* elfnn-riscv.c (PRPSINFO_PR_FNAME_LENGTH): Define.
	(PRPSINFO_PR_PSARGS_LENGTH): Define.
	(riscv_write_core_note): New function.
	(riscv_elf_grok_psinfo): Make use of two new length defines.
	(elf_backend_write_core_note): Define.
This commit is contained in:
Andrew Burgess 2020-11-30 12:14:38 +00:00
parent 95ce627aeb
commit 0897bb7d6d
2 changed files with 91 additions and 2 deletions

View file

@ -1,3 +1,12 @@
2021-03-05 Craig Blackmore <craig.blackmore@embecosm.com>
Andrew Burgess <andrew.burgess@embecosm.com>
* elfnn-riscv.c (PRPSINFO_PR_FNAME_LENGTH): Define.
(PRPSINFO_PR_PSARGS_LENGTH): Define.
(riscv_write_core_note): New function.
(riscv_elf_grok_psinfo): Make use of two new length defines.
(elf_backend_write_core_note): Define.
2021-03-05 Craig Blackmore <craig.blackmore@embecosm.com>
Andrew Burgess <andrew.burgess@embecosm.com>

View file

@ -4877,6 +4877,8 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
# define PRPSINFO_OFFSET_PR_PID 16
# define PRPSINFO_OFFSET_PR_FNAME 32
# define PRPSINFO_OFFSET_PR_PSARGS 48
# define PRPSINFO_PR_FNAME_LENGTH 16
# define PRPSINFO_PR_PSARGS_LENGTH 80
#else
# define PRSTATUS_SIZE 376
# define PRSTATUS_OFFSET_PR_CURSIG 12
@ -4887,8 +4889,83 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
# define PRPSINFO_OFFSET_PR_PID 24
# define PRPSINFO_OFFSET_PR_FNAME 40
# define PRPSINFO_OFFSET_PR_PSARGS 56
# define PRPSINFO_PR_FNAME_LENGTH 16
# define PRPSINFO_PR_PSARGS_LENGTH 80
#endif
/* Write PRSTATUS and PRPSINFO note into core file. This will be called
before the generic code in elf.c. By checking the compiler defines we
only perform any action here if the generic code would otherwise not be
able to help us. The intention is that bare metal core dumps (where the
prstatus_t and/or prpsinfo_t might not be available) will use this code,
while non bare metal tools will use the generic elf code. */
static char *
riscv_write_core_note (bfd *abfd ATTRIBUTE_UNUSED,
char *buf ATTRIBUTE_UNUSED,
int *bufsiz ATTRIBUTE_UNUSED,
int note_type ATTRIBUTE_UNUSED, ...)
{
switch (note_type)
{
default:
return NULL;
#if !defined (HAVE_PRPSINFO_T)
case NT_PRPSINFO:
{
char data[PRPSINFO_SIZE] ATTRIBUTE_NONSTRING;
va_list ap;
va_start (ap, note_type);
memset (data, 0, sizeof (data));
strncpy (data + PRPSINFO_OFFSET_PR_FNAME, va_arg (ap, const char *),
PRPSINFO_PR_FNAME_LENGTH);
#if GCC_VERSION == 8000 || GCC_VERSION == 8001
DIAGNOSTIC_PUSH;
/* GCC 8.0 and 8.1 warn about 80 equals destination size with
-Wstringop-truncation:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85643
*/
DIAGNOSTIC_IGNORE_STRINGOP_TRUNCATION;
#endif
strncpy (data + PRPSINFO_OFFSET_PR_PSARGS, va_arg (ap, const char *),
PRPSINFO_PR_PSARGS_LENGTH);
#if GCC_VERSION == 8000 || GCC_VERSION == 8001
DIAGNOSTIC_POP;
#endif
va_end (ap);
return elfcore_write_note (abfd, buf, bufsiz,
"CORE", note_type, data, sizeof (data));
}
#endif /* !HAVE_PRPSINFO_T */
#if !defined (HAVE_PRSTATUS_T)
case NT_PRSTATUS:
{
char data[PRSTATUS_SIZE];
va_list ap;
long pid;
int cursig;
const void *greg;
va_start (ap, note_type);
memset (data, 0, sizeof(data));
pid = va_arg (ap, long);
bfd_put_32 (abfd, pid, data + PRSTATUS_OFFSET_PR_PID);
cursig = va_arg (ap, int);
bfd_put_16 (abfd, cursig, data + PRSTATUS_OFFSET_PR_CURSIG);
greg = va_arg (ap, const void *);
memcpy (data + PRSTATUS_OFFSET_PR_REG, greg,
PRSTATUS_SIZE - PRSTATUS_OFFSET_PR_REG - ARCH_SIZE / 8);
va_end (ap);
return elfcore_write_note (abfd, buf, bufsiz,
"CORE", note_type, data, sizeof (data));
}
#endif /* !HAVE_PRSTATUS_T */
}
}
/* Support for core dump NOTE sections. */
static bfd_boolean
@ -4930,11 +5007,13 @@ riscv_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
/* pr_fname */
elf_tdata (abfd)->core->program = _bfd_elfcore_strndup
(abfd, note->descdata + PRPSINFO_OFFSET_PR_FNAME, 16);
(abfd, note->descdata + PRPSINFO_OFFSET_PR_FNAME,
PRPSINFO_PR_FNAME_LENGTH);
/* pr_psargs */
elf_tdata (abfd)->core->command = _bfd_elfcore_strndup
(abfd, note->descdata + PRPSINFO_OFFSET_PR_PSARGS, 80);
(abfd, note->descdata + PRPSINFO_OFFSET_PR_PSARGS,
PRPSINFO_PR_PSARGS_LENGTH);
break;
}
@ -5003,6 +5082,7 @@ riscv_elf_obj_attrs_arg_type (int tag)
#define elf_backend_grok_prstatus riscv_elf_grok_prstatus
#define elf_backend_grok_psinfo riscv_elf_grok_psinfo
#define elf_backend_object_p riscv_elf_object_p
#define elf_backend_write_core_note riscv_write_core_note
#define elf_info_to_howto_rel NULL
#define elf_info_to_howto riscv_info_to_howto_rela
#define bfd_elfNN_bfd_relax_section _bfd_riscv_relax_section