ARM/FDPIC: Add core file support

2021-04-14  Mickael Guene <mickael.guene@st.com>
	Christophe Lyon  <christophe.lyon@st.com>

	* bfd/elf32-arm.c (elf32_arm_nabi_grok_prstatus): Add support for
	ARM FDPIC ABI.
	* gdb/solib-fdpic.c (fdpic_get_initial_loadmaps_return_error): New.
	(fdpic_get_initial_loadmaps): Add support for core files.
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index bc1f195..f05ae97 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -1952,6 +1952,30 @@
 	size = 72;
 
 	break;
+
+      case 156:		/* Linux/ARM 32-bit, FDPIC ABI.  */
+	/* pr_cursig */
+	elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
+
+	/* pr_pid */
+	elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 24);
+
+	/* pr_reg */
+	offset = 72;
+	size = 72;
+
+	/* Create pseudo sections that embed loadmap addresses.  */
+	if (!_bfd_elfcore_make_pseudosection (abfd,
+					      ".pr_exec_fdpic_loadmap_addr", 4,
+					      note->descpos + offset + size))
+	  return FALSE;
+
+	if (!_bfd_elfcore_make_pseudosection (abfd,
+					      ".pr_interp_fdpic_loadmap_addr", 4,
+					      note->descpos + offset + size + 4))
+	  return FALSE;
+
+	break;
     }
 
   /* Make a ".reg/999" section.  */
diff --git a/gdb/solib-fdpic.c b/gdb/solib-fdpic.c
index 497742d..4142407 100644
--- a/gdb/solib-fdpic.c
+++ b/gdb/solib-fdpic.c
@@ -209,6 +209,13 @@
     }
 }
 
+static void *fdpic_get_initial_loadmaps_return_error (int is_interpreter)
+{
+  if (!is_interpreter)
+    error (_("Error reading FDPIC exec loadmap"));
+  return NULL;
+}
+
 static struct elf32_fdpic_loadmap *
 fdpic_get_initial_loadmaps (int is_interpreter)
 {
@@ -218,18 +225,51 @@
   if (solib_fdpic_debug)
     fprintf_unfiltered (gdb_stdlog, "  %s : %d\n", __FUNCTION__, is_interpreter);
 
-  /* Read raw loadmap.  */
-  if (0 >= target_read_alloc (&current_target, TARGET_OBJECT_FDPIC,
-			      is_interpreter ? "interp" : "exec",
-			      (gdb_byte**) &buf))
+  if (core_bfd)
     {
-      if (!is_interpreter)
-	error (_("Error reading FDPIC exec loadmap"));
-      return NULL;
+      /* Things would be easier if we add a kernel patch to output
+       * loadmap info in elf notes.  Then we would just transform
+       * those notes into pseudo sections and add TARGET_OBJECT_FDPIC
+       * support in core_xfer_partial() in corelow.c.
+       */
+      enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
+      struct bfd_section *section;
+      gdb_byte addrbuf[4];
+      CORE_ADDR loadmap_addr;
+
+      /* Extract loadmap address from corresponding pseudo section.  */
+      section = bfd_get_section_by_name (core_bfd,
+					 is_interpreter
+					 ? ".pr_interp_fdpic_loadmap_addr"
+					 : ".pr_exec_fdpic_loadmap_addr");
+      if (section == NULL
+	  || !bfd_get_section_contents (core_bfd, section, &addrbuf, 0, 4))
+	return fdpic_get_initial_loadmaps_return_error (is_interpreter);
+
+      loadmap_addr = extract_unsigned_integer (addrbuf, 4/*INT_REGISTER_SIZE*/,
+					       byte_order);
+      if (!loadmap_addr)
+	return fdpic_get_initial_loadmaps_return_error (is_interpreter);
+
+      /* Now read loadmap from memory.  */
+      buf = xmalloc (sizeof (struct elf32_fdpic_loadmap)
+		     + 2 * sizeof (struct elf32_fdpic_loadseg));
+      if (target_read_memory (loadmap_addr, buf,
+			      sizeof (struct elf32_fdpic_loadmap)
+			      + 2 * sizeof (struct elf32_fdpic_loadseg)) != 0)
+	return fdpic_get_initial_loadmaps_return_error (0);
     }
-  else if (solib_fdpic_debug)
+  else
+    {
+      /* Read raw loadmap.  */
+      if (0 >= target_read_alloc (&current_target, TARGET_OBJECT_FDPIC,
+				  is_interpreter ? "interp" : "exec",
+				  (gdb_byte**) &buf))
+	return fdpic_get_initial_loadmaps_return_error (is_interpreter);
+    }
+  if (solib_fdpic_debug)
     fprintf_unfiltered (gdb_stdlog,
-			"   - Successfully loaded %s loadmap\n",
+			"   - Successfully load %s loadmap\n",
 			is_interpreter ? "interpreter" : "executable");
 
   res = decode_loadmap (buf);