From 544c67cda1686c1b204cb96c0d7885b08d37b8d6 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Fri, 6 Oct 2017 11:41:45 -0700 Subject: Account for padding in FreeBSD/mipsn32 NT_PRSTATUS notes. Add a new ELF backend method to grok FreeBSD NT_PRSTATUS core dump notes. Define a method for MIPS N32 to override the default elfcore_grok_freebsd_prstatus that accounts for additional padding between pr_pid and pr_reg that is not present in other 32-bit FreeBSD platforms. * elf-bfd.h (struct elf_backend_data): Add `elf_backend_grok_freebsd_prstatus'. * elf.c (elfcore_grok_freebsd_note): Call `elf_backend_grok_freebsd_prstatus' to handle NT_PRSTATUS if present. * elfn32-mips.c (elf_n32_mips_grok_freebsd_prstatus): New function. (elf_backend_grok_freebsd_prstatus): Define. * elfxx-target.h (elf_backend_grok_freebsd_prstatus): Define. (elfNN_bed): Initialize `elf_backend_grok_freebsd_prstatus'. --- bfd/ChangeLog | 13 +++++++++++++ bfd/elf-bfd.h | 5 +++++ bfd/elf.c | 5 +++++ bfd/elfn32-mips.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ bfd/elfxx-target.h | 4 ++++ 5 files changed, 81 insertions(+) (limited to 'bfd') diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 8633071..dd25779 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,16 @@ +2017-10-06 John Baldwin + + * elf-bfd.h (struct elf_backend_data): Add + `elf_backend_grok_freebsd_prstatus'. + * elf.c (elfcore_grok_freebsd_note): Call + `elf_backend_grok_freebsd_prstatus' to handle NT_PRSTATUS if + present. + * elfn32-mips.c (elf_n32_mips_grok_freebsd_prstatus): New + function. + (elf_backend_grok_freebsd_prstatus): Define. + * elfxx-target.h (elf_backend_grok_freebsd_prstatus): Define. + (elfNN_bed): Initialize `elf_backend_grok_freebsd_prstatus'. + 2017-10-06 H.J. Lu * elfxx-x86.h (COPY_INPUT_RELOC_P): Add "do/while(0);". diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index fd08748..399e298 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -1270,6 +1270,11 @@ struct elf_backend_data bfd_boolean (*elf_backend_grok_psinfo) (bfd *, Elf_Internal_Note *); + /* This function, if defined, is called when a "FreeBSD" NT_PRSTATUS + note is found in a core file. */ + bfd_boolean (*elf_backend_grok_freebsd_prstatus) + (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 02decea..c6de70d 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -9981,9 +9981,14 @@ elfcore_grok_freebsd_prstatus (bfd *abfd, Elf_Internal_Note *note) static bfd_boolean elfcore_grok_freebsd_note (bfd *abfd, Elf_Internal_Note *note) { + const struct elf_backend_data *bed = get_elf_backend_data (abfd); + switch (note->type) { case NT_PRSTATUS: + if (bed->elf_backend_grok_freebsd_prstatus) + if ((*bed->elf_backend_grok_freebsd_prstatus) (abfd, note)) + return TRUE; return elfcore_grok_freebsd_prstatus (abfd, note); case NT_FPREGSET: diff --git a/bfd/elfn32-mips.c b/bfd/elfn32-mips.c index dce7ba1..fdae183 100644 --- a/bfd/elfn32-mips.c +++ b/bfd/elfn32-mips.c @@ -80,6 +80,8 @@ static bfd_boolean elf32_mips_grok_prstatus (bfd *, Elf_Internal_Note *); static bfd_boolean elf32_mips_grok_psinfo (bfd *, Elf_Internal_Note *); +static bfd_boolean elf_n32_mips_grok_freebsd_prstatus + (bfd *, Elf_Internal_Note *); static irix_compat_t elf_n32_mips_irix_compat (bfd *); @@ -3578,6 +3580,56 @@ elf32_mips_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) return TRUE; } + +static bfd_boolean +elf_n32_mips_grok_freebsd_prstatus (bfd *abfd, Elf_Internal_Note *note) +{ + size_t offset; + size_t size; + size_t min_size; + + /* Compute offset of pr_getregsz, skipping over pr_statussz. + Also compute minimum size of this note. */ + offset = 4 + 4; + min_size = offset + 4 * 2 + 4 + 4 + 4; + + if (note->descsz < min_size) + return FALSE; + + /* Check for version 1 in pr_version. */ + if (bfd_h_get_32 (abfd, (bfd_byte *) note->descdata) != 1) + return FALSE; + + /* Extract size of pr_reg from pr_gregsetsz. */ + /* Skip over pr_gregsetsz and pr_fpregsetsz. */ + size = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset); + offset += 4 * 2; + + /* Skip over pr_osreldate. */ + offset += 4; + + /* Read signal from pr_cursig. */ + if (elf_tdata (abfd)->core->signal == 0) + elf_tdata (abfd)->core->signal + = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset); + offset += 4; + + /* Read TID from pr_pid. */ + elf_tdata (abfd)->core->lwpid + = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset); + offset += 4; + + /* Padding before pr_reg. */ + offset += 4; + + /* Make sure that there is enough data remaining in the note. */ + if (note->descsz - offset < size) + return FALSE; + + /* Make a ".reg/999" section and a ".reg" section. */ + return _bfd_elfcore_make_pseudosection (abfd, ".reg", + size, note->descpos + offset); +} /* Depending on the target vector we generate some version of Irix executables or "normal" MIPS ELF ABI executables. */ @@ -3684,6 +3736,8 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = { _bfd_mips_elf_copy_indirect_symbol #define elf_backend_grok_prstatus elf32_mips_grok_prstatus #define elf_backend_grok_psinfo elf32_mips_grok_psinfo +#define elf_backend_grok_freebsd_prstatus \ + elf_n32_mips_grok_freebsd_prstatus #define elf_backend_ecoff_debug_swap &mips_elf32_ecoff_debug_swap #define elf_backend_got_header_size (4 * MIPS_RESERVED_GOTNO) diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h index 551883f..6efca84 100644 --- a/bfd/elfxx-target.h +++ b/bfd/elfxx-target.h @@ -597,6 +597,9 @@ #ifndef elf_backend_grok_psinfo #define elf_backend_grok_psinfo NULL #endif +#ifndef elf_backend_grok_freebsd_prstatus +#define elf_backend_grok_freebsd_prstatus NULL +#endif #ifndef elf_backend_write_core_note #define elf_backend_write_core_note NULL #endif @@ -820,6 +823,7 @@ static struct elf_backend_data elfNN_bed = elf_backend_sort_relocs_p, elf_backend_grok_prstatus, elf_backend_grok_psinfo, + elf_backend_grok_freebsd_prstatus, elf_backend_write_core_note, elf_backend_lookup_section_flags_hook, elf_backend_reloc_type_class, -- cgit v1.1