[PATCH] Add OSE operating system support [2/5] relocation support

Hui Zhu hui_zhu@mentor.com
Fri Mar 8 13:29:00 GMT 2013


OSE is a target that requires relocating the main executable
(qOffsets, etc.).  We also need to relocate the main executable when
reading OSE core dumps.  This patch adds a gdbarch hook, and adds
an implementation to the OSE core backend in gdb.  The previous
patch exported the raw OSE signal that contains the necessary
info in a ".section-info" bfd pseudo section.  The GDB side
parses the OSE signal to extract the section info.  The BFD
bits that add the pseudo-section should be a part of this
patch, but I didn't feel that working on the patch split was
worth it.

Thanks,
Hui

2013-03-08  Pedro Alves  <pedro@codesourcery.com>
	    Luis Machado  <lgustavo@codesourcery.com>

	* corelow.c (core_open): Call gdbarch_core_relocate.
	* exec.c (relocate_with_load_map): New.
	* exec.h (load_map_info): New.
	(relocate_with_load_map): New extern.
	* gdbarch.sh (core_relocate): New.
	* gdbarch.h, gdbarch.c: Regenerate.
	* target.h (target_object): Add TARGET_OBJECT_LOAD_MAP.


On 03/05/13 17:59, Hui Zhu wrote:
> OSE need to do relocation before inspecting the core file or debug with the remote stub.  This patch is make GDB support relocation.
>
> This patch add new interface core_relocate to gdbarch, because the core file of OSE need relocation.  This interface can handle it.
> Add TARGET_OBJECT_LOAD_MAP make GDB can get load map from target.
> Add a new function relocate_with_load_map to do relocation from the map that load from target.
>
> Thanks,
> Hui
>
> 2013-03-05  Luis Machado  <lgustavo@codesourcery.com>
>
>      * corelow.c (core_open): Call gdbarch_core_relocate.
>      * exec.c (relocate_with_load_map): New.
>      * exec.h (load_map_info): New.
>      (relocate_with_load_map): New extern.
>      * gdbarch.sh (core_relocate): New.
>      * gdbarch.h, gdbarch.c: Regenerate.
>      * target.h (target_object): Add TARGET_OBJECT_LOAD_MAP.


-------------- next part --------------
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -383,6 +383,10 @@ core_open (char *filename, int from_tty)
      previous session, and the frame cache being stale.  */
   registers_changed ();
 
+  if (core_gdbarch
+      && gdbarch_core_relocate_p (core_gdbarch))
+    gdbarch_core_relocate (core_gdbarch, core_bfd);
+
   /* Build up thread list from BFD sections, and possibly set the
      current thread to the .reg/NN section matching the .reg
      section.  */
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -951,3 +951,84 @@ exec_make_note_section (bfd *obfd, int *
 {
   error (_("Can't create a corefile"));
 }
+
+void
+relocate_with_load_map (struct load_map_info *info)
+{
+  struct section_offsets *offs;
+  const char *load_map_document;
+  struct bfd *abfd;
+  const char *filename;
+  struct cleanup *old_chain;
+
+  offs = alloca (SIZEOF_N_SECTION_OFFSETS (symfile_objfile->num_sections));
+  memcpy (offs, symfile_objfile->section_offsets,
+	  SIZEOF_N_SECTION_OFFSETS (symfile_objfile->num_sections));
+
+  abfd = symfile_objfile->obfd;
+  filename = bfd_get_filename (abfd);
+
+  if (info->segment_bases != NULL)
+    {
+      struct symfile_segment_data *data;
+
+      data = get_symfile_segment_data (abfd);
+      if (data == NULL)
+	warning (_("\
+Could not relocate \"%s\": no segments"), filename);
+      else
+	{
+	  int num_bases;
+	  CORE_ADDR *segment_bases;
+
+	  num_bases = VEC_length (CORE_ADDR, info->segment_bases);
+	  segment_bases = VEC_address (CORE_ADDR, info->segment_bases);
+
+	  if (!symfile_map_offsets_to_segments (abfd, data,
+						offs,
+						num_bases, segment_bases))
+	    warning (_("\
+Could not relocate shared library \"%s\": bad offsets"), filename);
+
+	  free_symfile_segment_data (data);
+	}
+    }
+  else if (info->section_bases != NULL)
+    {
+      int i;
+      asection *sect;
+      int num_section_bases = VEC_length (CORE_ADDR, info->section_bases);
+      int num_alloc_sections = 0;
+
+      for (i = 0, sect = abfd->sections;
+	   sect != NULL;
+	   i++, sect = sect->next)
+	if ((bfd_get_section_flags (abfd, sect) & SEC_ALLOC))
+	  num_alloc_sections++;
+
+      if (num_alloc_sections != num_section_bases)
+	warning (_("\
+Could not relocate \"%s\": mismatch in number of ALLOC sections"),
+		 filename);
+      else
+	{
+	  int bases_index = 0;
+	  CORE_ADDR *section_bases;
+
+	  section_bases = VEC_address (CORE_ADDR, info->section_bases);
+
+	  for (i = 0, sect = abfd->sections;
+	       sect != NULL;
+	       i++, sect = sect->next)
+	    if (bfd_get_section_flags (abfd, sect) & SEC_ALLOC)
+	      {
+		const bfd_vma vma = bfd_section_vma (abfd, sect);
+
+		offs->offsets[i] = section_bases[bases_index] - vma;
+		bases_index++;
+	      }
+	}
+    }
+
+  objfile_relocate (symfile_objfile, offs);
+}
--- a/gdb/exec.h
+++ b/gdb/exec.h
@@ -33,6 +33,24 @@ extern struct target_ops exec_ops;
 #define exec_bfd current_program_space->ebfd
 #define exec_bfd_mtime current_program_space->ebfd_mtime
 
+/* Target load addresses, for relocation purposes.  */
+
+struct load_map_info
+{
+  /* The target can either specify segment bases or section bases, not
+     both.  */
+
+  /* The base addresses for each independently relocatable segment of
+     this executable object.  */
+  VEC(CORE_ADDR) *segment_bases;
+
+  /* The base addresses for each independently allocatable,
+     relocatable section of this executable object.  */
+  VEC(CORE_ADDR) *section_bases;
+};
+
+extern void relocate_with_load_map (struct load_map_info *info);
+
 /* Builds a section table, given args BFD, SECTABLE_PTR, SECEND_PTR.
    Returns 0 if OK, 1 on error.  */
 
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -236,6 +236,7 @@ struct gdbarch
   gdbarch_register_reggroup_p_ftype *register_reggroup_p;
   gdbarch_fetch_pointer_argument_ftype *fetch_pointer_argument;
   gdbarch_regset_from_core_section_ftype *regset_from_core_section;
+  gdbarch_core_relocate_ftype *core_relocate;
   struct core_regset_section * core_regset_sections;
   gdbarch_make_corefile_notes_ftype *make_corefile_notes;
   gdbarch_elfcore_write_linux_prpsinfo_ftype *elfcore_write_linux_prpsinfo;
@@ -407,6 +408,7 @@ struct gdbarch startup_gdbarch =
   default_register_reggroup_p,  /* register_reggroup_p */
   0,  /* fetch_pointer_argument */
   0,  /* regset_from_core_section */
+  0,  /* core_relocate */
   0,  /* core_regset_sections */
   0,  /* make_corefile_notes */
   0,  /* elfcore_write_linux_prpsinfo */
@@ -710,6 +712,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of register_reggroup_p, invalid_p == 0 */
   /* Skip verify of fetch_pointer_argument, has predicate.  */
   /* Skip verify of regset_from_core_section, has predicate.  */
+  /* Skip verify of core_relocate, has predicate.  */
   /* Skip verify of make_corefile_notes, has predicate.  */
   /* Skip verify of elfcore_write_linux_prpsinfo, has predicate.  */
   /* Skip verify of find_memory_regions, has predicate.  */
@@ -898,6 +901,12 @@ gdbarch_dump (struct gdbarch *gdbarch, s
                       "gdbarch_dump: core_regset_sections = %s\n",
                       host_address_to_string (gdbarch->core_regset_sections));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_core_relocate_p() = %d\n",
+                      gdbarch_core_relocate_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: core_relocate = <%s>\n",
+                      host_address_to_string (gdbarch->core_relocate));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: gdbarch_core_xfer_shared_libraries_p() = %d\n",
                       gdbarch_core_xfer_shared_libraries_p (gdbarch));
   fprintf_unfiltered (file,
@@ -3336,6 +3345,30 @@ set_gdbarch_regset_from_core_section (st
   gdbarch->regset_from_core_section = regset_from_core_section;
 }
 
+int
+gdbarch_core_relocate_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->core_relocate != NULL;
+}
+
+void
+gdbarch_core_relocate (struct gdbarch *gdbarch, bfd *core_bfd)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->core_relocate != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_core_relocate called\n");
+  gdbarch->core_relocate (gdbarch, core_bfd);
+}
+
+void
+set_gdbarch_core_relocate (struct gdbarch *gdbarch,
+                           gdbarch_core_relocate_ftype core_relocate)
+{
+  gdbarch->core_relocate = core_relocate;
+}
+
 struct core_regset_section *
 gdbarch_core_regset_sections (struct gdbarch *gdbarch)
 {
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -724,6 +724,14 @@ typedef const struct regset * (gdbarch_r
 extern const struct regset * gdbarch_regset_from_core_section (struct gdbarch *gdbarch, const char *sect_name, size_t sect_size);
 extern void set_gdbarch_regset_from_core_section (struct gdbarch *gdbarch, gdbarch_regset_from_core_section_ftype *regset_from_core_section);
 
+/* Relocate core file. */
+
+extern int gdbarch_core_relocate_p (struct gdbarch *gdbarch);
+
+typedef void (gdbarch_core_relocate_ftype) (struct gdbarch *gdbarch, bfd *core_bfd);
+extern void gdbarch_core_relocate (struct gdbarch *gdbarch, bfd *core_bfd);
+extern void set_gdbarch_core_relocate (struct gdbarch *gdbarch, gdbarch_core_relocate_ftype *core_relocate);
+
 /* Supported register notes in a core file. */
 
 extern struct core_regset_section * gdbarch_core_regset_sections (struct gdbarch *gdbarch);
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -635,6 +635,9 @@ F:CORE_ADDR:fetch_pointer_argument:struc
 # name SECT_NAME and size SECT_SIZE.
 M:const struct regset *:regset_from_core_section:const char *sect_name, size_t sect_size:sect_name, sect_size
 
+# Relocate core file.
+M:void:core_relocate:bfd *core_bfd:core_bfd
+
 # Supported register notes in a core file.
 v:struct core_regset_section *:core_regset_sections:const char *name, int len::::::host_address_to_string (gdbarch->core_regset_sections)
 
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -268,6 +268,8 @@ enum target_object
   TARGET_OBJECT_SIGNAL_INFO,
   /* The list of threads that are being debugged.  */
   TARGET_OBJECT_THREADS,
+  /* Relocation info for the main executable, in XML format.  */
+  TARGET_OBJECT_LOAD_MAP,
   /* Collected static trace data.  */
   TARGET_OBJECT_STATIC_TRACE_DATA,
   /* The HP-UX registers (those that can be obtained or modified by using



More information about the Binutils mailing list