[binutils-gdb] bfd/riscv: prepare to handle bare metal core dump creation

Andrew Burgess aburgess@sourceware.org
Fri Mar 5 17:23:11 GMT 2021


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=0897bb7d6dc4e803cd99d4656186c965f099d01c

commit 0897bb7d6dc4e803cd99d4656186c965f099d01c
Author: Andrew Burgess <andrew.burgess@embecosm.com>
Date:   Mon Nov 30 12:14:38 2020 +0000

    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.

Diff:
---
 bfd/ChangeLog     |  9 ++++++
 bfd/elfnn-riscv.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 91 insertions(+), 2 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 31d0714da27..9e7f90e1625 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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>
 
diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index ec8a3e73c8f..76d29b73332 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -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


More information about the Binutils-cvs mailing list