* Makefile.in (arm-tdep.o): Update.
authorDaniel Jacobowitz <drow@false.org>
Fri, 2 May 2008 20:38:16 +0000 (20:38 +0000)
committerDaniel Jacobowitz <drow@false.org>
Fri, 2 May 2008 20:38:16 +0000 (20:38 +0000)
* arm-tdep.c (arm_objfile_data_key, struct arm_mapping_symbol)
(struct arm_per_objfile, arm_compare_mapping_symbols): New.
(arm_pc_is_thumb): Use mapping symbols.
(arm_objfile_data_cleanup, arm_record_special_symbol): New.
(arm_gdbarch_init): Call set_gdbarch_record_special_symbol.
(_initialize_arm_tdep): Initialize arm_objfile_data_key.
* elfread.c (elf_symtab_read): Use gdbarch_record_special_symbol.
* gdbarch.sh: Add record_special_symbol.
* gdbarch.c, gdbarch.h: Regenerated.
* objfiles.c (struct objfile_data): Add cleanup member.
(register_objfile_data_with_cleanup): New function, from
register_objfile_data.
(register_objfile_data): Use it.
(objfile_free_data): Call clear_objfile_data.
(clear_objfile_data): Call cleanup functions.
* objfiles.h (register_objfile_data_with_cleanup): Declare.

gdb/ChangeLog
gdb/Makefile.in
gdb/arm-tdep.c
gdb/elfread.c
gdb/gdbarch.c
gdb/gdbarch.h
gdb/gdbarch.sh
gdb/objfiles.c
gdb/objfiles.h

index e349f77..c7515cb 100644 (file)
@@ -1,5 +1,25 @@
 2008-05-02  Daniel Jacobowitz  <dan@codesourcery.com>
 
+       * Makefile.in (arm-tdep.o): Update.
+       * arm-tdep.c (arm_objfile_data_key, struct arm_mapping_symbol)
+       (struct arm_per_objfile, arm_compare_mapping_symbols): New.
+       (arm_pc_is_thumb): Use mapping symbols.
+       (arm_objfile_data_cleanup, arm_record_special_symbol): New.
+       (arm_gdbarch_init): Call set_gdbarch_record_special_symbol.
+       (_initialize_arm_tdep): Initialize arm_objfile_data_key.
+       * elfread.c (elf_symtab_read): Use gdbarch_record_special_symbol.
+       * gdbarch.sh: Add record_special_symbol.
+       * gdbarch.c, gdbarch.h: Regenerated.
+       * objfiles.c (struct objfile_data): Add cleanup member.
+       (register_objfile_data_with_cleanup): New function, from
+       register_objfile_data.
+       (register_objfile_data): Use it.
+       (objfile_free_data): Call clear_objfile_data.
+       (clear_objfile_data): Call cleanup functions.
+       * objfiles.h (register_objfile_data_with_cleanup): Declare.
+
+2008-05-02  Daniel Jacobowitz  <dan@codesourcery.com>
+
        * objfiles.c (init_entry_point_info): Handle shared libraries.
 
 2008-05-02  Daniel Jacobowitz  <dan@codesourcery.com>
index 16dd2ee..6afdeba 100644 (file)
@@ -1943,7 +1943,7 @@ arm-tdep.o: arm-tdep.c $(defs_h) $(frame_h) $(inferior_h) $(gdbcmd_h) \
        $(gdb_sim_arm_h) $(elf_bfd_h) $(coff_internal_h) $(elf_arm_h) \
        $(gdb_assert_h) $(bfd_in2_h) $(libcoff_h) $(objfiles_h) \
        $(dwarf2_frame_h) $(gdbtypes_h) $(prologue_value_h) \
-       $(target_descriptions_h) $(user_regs_h)
+       $(target_descriptions_h) $(user_regs_h) $(vec_h)
 arm-wince-tdep.o: arm-wince-tdep.c $(defs_h) $(osabi_h) \
        $(gdbcore_h) $(target_h) $(solib_h) $(solib_target_h) \
        $(gdb_string_h) $(arm_tdep_h)
index fa7a3e8..9fbd0fc 100644 (file)
@@ -51,6 +51,7 @@
 #include "elf/arm.h"
 
 #include "gdb_assert.h"
+#include "vec.h"
 
 static int arm_debug;
 
@@ -68,6 +69,22 @@ static int arm_debug;
 #define MSYMBOL_IS_SPECIAL(msym)                               \
        (((long) MSYMBOL_INFO (msym) & 0x80000000) != 0)
 
+/* Per-objfile data used for mapping symbols.  */
+static const struct objfile_data *arm_objfile_data_key;
+
+struct arm_mapping_symbol
+{
+  bfd_vma value;
+  char type;
+};
+typedef struct arm_mapping_symbol arm_mapping_symbol_s;
+DEF_VEC_O(arm_mapping_symbol_s);
+
+struct arm_per_objfile
+{
+  VEC(arm_mapping_symbol_s) **section_maps;
+};
+
 /* The list of available "set arm ..." and "show arm ..." commands.  */
 static struct cmd_list_element *setarmcmdlist = NULL;
 static struct cmd_list_element *showarmcmdlist = NULL;
@@ -238,6 +255,15 @@ arm_frame_is_thumb (struct frame_info *frame)
   return (cpsr & CPSR_T) != 0;
 }
 
+/* Callback for VEC_lower_bound.  */
+
+static inline int
+arm_compare_mapping_symbols (const struct arm_mapping_symbol *lhs,
+                            const struct arm_mapping_symbol *rhs)
+{
+  return lhs->value < rhs->value;
+}
+
 /* Determine if the program counter specified in MEMADDR is in a Thumb
    function.  This function should be called for addresses unrelated to
    any executing frame; otherwise, prefer arm_frame_is_thumb.  */
@@ -245,6 +271,7 @@ arm_frame_is_thumb (struct frame_info *frame)
 static int
 arm_pc_is_thumb (CORE_ADDR memaddr)
 {
+  struct obj_section *sec;
   struct minimal_symbol *sym;
 
   /* If bit 0 of the address is set, assume this is a Thumb address.  */
@@ -257,6 +284,46 @@ arm_pc_is_thumb (CORE_ADDR memaddr)
   if (strcmp (arm_force_mode_string, "thumb") == 0)
     return 1;
 
+  /* If there are mapping symbols, consult them.  */
+  sec = find_pc_section (memaddr);
+  if (sec != NULL)
+    {
+      struct arm_per_objfile *data;
+      VEC(arm_mapping_symbol_s) *map;
+      struct arm_mapping_symbol map_key = { memaddr - sec->addr, 0 };
+      unsigned int idx;
+
+      data = objfile_data (sec->objfile, arm_objfile_data_key);
+      if (data != NULL)
+       {
+         map = data->section_maps[sec->the_bfd_section->index];
+         if (!VEC_empty (arm_mapping_symbol_s, map))
+           {
+             struct arm_mapping_symbol *map_sym;
+
+             idx = VEC_lower_bound (arm_mapping_symbol_s, map, &map_key,
+                                    arm_compare_mapping_symbols);
+
+             /* VEC_lower_bound finds the earliest ordered insertion
+                point.  If the following symbol starts at this exact
+                address, we use that; otherwise, the preceding
+                mapping symbol covers this address.  */
+             if (idx < VEC_length (arm_mapping_symbol_s, map))
+               {
+                 map_sym = VEC_index (arm_mapping_symbol_s, map, idx);
+                 if (map_sym->value == map_key.value)
+                   return map_sym->type == 't';
+               }
+
+             if (idx > 0)
+               {
+                 map_sym = VEC_index (arm_mapping_symbol_s, map, idx - 1);
+                 return map_sym->type == 't';
+               }
+           }
+       }
+    }
+
   /* Thumb functions have a "special" bit set in minimal symbols.  */
   sym = lookup_minimal_symbol_by_pc (memaddr);
   if (sym)
@@ -2787,6 +2854,65 @@ arm_coff_make_msymbol_special(int val, struct minimal_symbol *msym)
 }
 
 static void
+arm_objfile_data_cleanup (struct objfile *objfile, void *arg)
+{
+  struct arm_per_objfile *data = arg;
+  unsigned int i;
+
+  for (i = 0; i < objfile->obfd->section_count; i++)
+    VEC_free (arm_mapping_symbol_s, data->section_maps[i]);
+}
+
+static void
+arm_record_special_symbol (struct gdbarch *gdbarch, struct objfile *objfile,
+                          asymbol *sym)
+{
+  const char *name = bfd_asymbol_name (sym);
+  struct arm_per_objfile *data;
+  VEC(arm_mapping_symbol_s) **map_p;
+  struct arm_mapping_symbol new_map_sym;
+
+  gdb_assert (name[0] == '$');
+  if (name[1] != 'a' && name[1] != 't' && name[1] != 'd')
+    return;
+
+  data = objfile_data (objfile, arm_objfile_data_key);
+  if (data == NULL)
+    {
+      data = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+                            struct arm_per_objfile);
+      set_objfile_data (objfile, arm_objfile_data_key, data);
+      data->section_maps = OBSTACK_CALLOC (&objfile->objfile_obstack,
+                                          objfile->obfd->section_count,
+                                          VEC(arm_mapping_symbol_s) *);
+    }
+  map_p = &data->section_maps[bfd_get_section (sym)->index];
+
+  new_map_sym.value = sym->value;
+  new_map_sym.type = name[1];
+
+  /* Assume that most mapping symbols appear in order of increasing
+     value.  If they were randomly distributed, it would be faster to
+     always push here and then sort at first use.  */
+  if (!VEC_empty (arm_mapping_symbol_s, *map_p))
+    {
+      struct arm_mapping_symbol *prev_map_sym;
+
+      prev_map_sym = VEC_last (arm_mapping_symbol_s, *map_p);
+      if (prev_map_sym->value >= sym->value)
+       {
+         unsigned int idx;
+         idx = VEC_lower_bound (arm_mapping_symbol_s, *map_p, &new_map_sym,
+                                arm_compare_mapping_symbols);
+         VEC_safe_insert (arm_mapping_symbol_s, *map_p, idx, &new_map_sym);
+         return;
+       }
+    }
+
+  VEC_safe_push (arm_mapping_symbol_s, *map_p, &new_map_sym);
+}
+
+static void
 arm_write_pc (struct regcache *regcache, CORE_ADDR pc)
 {
   regcache_cooked_write_unsigned (regcache, ARM_PC_REGNUM, pc);
@@ -3157,6 +3283,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_elf_make_msymbol_special (gdbarch, arm_elf_make_msymbol_special);
   set_gdbarch_coff_make_msymbol_special (gdbarch,
                                         arm_coff_make_msymbol_special);
+  set_gdbarch_record_special_symbol (gdbarch, arm_record_special_symbol);
 
   /* Virtual tables.  */
   set_gdbarch_vbit_in_delta (gdbarch, 1);
@@ -3246,6 +3373,9 @@ _initialize_arm_tdep (void)
 
   gdbarch_register (bfd_arch_arm, arm_gdbarch_init, arm_dump_tdep);
 
+  arm_objfile_data_key
+    = register_objfile_data_with_cleanup (arm_objfile_data_cleanup);
+
   /* Register an ELF OS ABI sniffer for ARM binaries.  */
   gdbarch_register_osabi_sniffer (bfd_arch_arm,
                                  bfd_target_elf_flavour,
index 88ea77b..76af9dc 100644 (file)
@@ -240,7 +240,11 @@ elf_symtab_read (struct objfile *objfile, int type,
         symbols which do not correspond to objects in the symbol table,
         but have some other target-specific meaning.  */
       if (bfd_is_target_special_symbol (objfile->obfd, sym))
-       continue;
+       {
+         if (gdbarch_record_special_symbol_p (gdbarch))
+           gdbarch_record_special_symbol (gdbarch, objfile, sym);
+         continue;
+       }
 
       offset = ANOFFSET (objfile->section_offsets, sym->section->index);
       if (type == ST_DYNAMIC
index 0449aaa..537da18 100644 (file)
@@ -237,6 +237,7 @@ struct gdbarch
   int sofun_address_maybe_missing;
   gdbarch_target_signal_from_host_ftype *target_signal_from_host;
   gdbarch_target_signal_to_host_ftype *target_signal_to_host;
+  gdbarch_record_special_symbol_ftype *record_special_symbol;
 };
 
 
@@ -366,6 +367,7 @@ struct gdbarch startup_gdbarch =
   0,  /* sofun_address_maybe_missing */
   default_target_signal_from_host,  /* target_signal_from_host */
   default_target_signal_to_host,  /* target_signal_to_host */
+  0,  /* record_special_symbol */
   /* startup_gdbarch() */
 };
 
@@ -618,6 +620,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of sofun_address_maybe_missing, invalid_p == 0 */
   /* Skip verify of target_signal_from_host, invalid_p == 0 */
   /* Skip verify of target_signal_to_host, invalid_p == 0 */
+  /* Skip verify of record_special_symbol, has predicate */
   buf = ui_file_xstrdup (log, &dummy);
   make_cleanup (xfree, buf);
   if (strlen (buf) > 0)
@@ -947,6 +950,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       "gdbarch_dump: read_pc = <0x%lx>\n",
                       (long) gdbarch->read_pc);
   fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_record_special_symbol_p() = %d\n",
+                      gdbarch_record_special_symbol_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: record_special_symbol = <0x%lx>\n",
+                      (long) gdbarch->record_special_symbol);
+  fprintf_unfiltered (file,
                       "gdbarch_dump: register_name = <0x%lx>\n",
                       (long) gdbarch->register_name);
   fprintf_unfiltered (file,
@@ -3181,6 +3190,30 @@ set_gdbarch_target_signal_to_host (struct gdbarch *gdbarch,
   gdbarch->target_signal_to_host = target_signal_to_host;
 }
 
+int
+gdbarch_record_special_symbol_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->record_special_symbol != NULL;
+}
+
+void
+gdbarch_record_special_symbol (struct gdbarch *gdbarch, struct objfile *objfile, asymbol *sym)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->record_special_symbol != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_record_special_symbol called\n");
+  gdbarch->record_special_symbol (gdbarch, objfile, sym);
+}
+
+void
+set_gdbarch_record_special_symbol (struct gdbarch *gdbarch,
+                                   gdbarch_record_special_symbol_ftype record_special_symbol)
+{
+  gdbarch->record_special_symbol = record_special_symbol;
+}
+
 
 /* Keep a registry of per-architecture data-pointers required by GDB
    modules. */
index e89bd46..560b2ef 100644 (file)
@@ -794,6 +794,14 @@ typedef int (gdbarch_target_signal_to_host_ftype) (struct gdbarch *gdbarch, enum
 extern int gdbarch_target_signal_to_host (struct gdbarch *gdbarch, enum target_signal ts);
 extern void set_gdbarch_target_signal_to_host (struct gdbarch *gdbarch, gdbarch_target_signal_to_host_ftype *target_signal_to_host);
 
+/* Record architecture-specific information from the symbol table. */
+
+extern int gdbarch_record_special_symbol_p (struct gdbarch *gdbarch);
+
+typedef void (gdbarch_record_special_symbol_ftype) (struct gdbarch *gdbarch, struct objfile *objfile, asymbol *sym);
+extern void gdbarch_record_special_symbol (struct gdbarch *gdbarch, struct objfile *objfile, asymbol *sym);
+extern void set_gdbarch_record_special_symbol (struct gdbarch *gdbarch, gdbarch_record_special_symbol_ftype *record_special_symbol);
+
 extern struct gdbarch_tdep *gdbarch_tdep (struct gdbarch *gdbarch);
 
 
index 08e3741..aedd9e5 100755 (executable)
@@ -701,6 +701,9 @@ m:enum target_signal:target_signal_from_host:int signo:signo::default_target_sig
 # Signal translation: translate GDB's signal number into inferior's host
 # signal number.
 m:int:target_signal_to_host:enum target_signal ts:ts::default_target_signal_to_host::0
+
+# Record architecture-specific information from the symbol table.
+M:void:record_special_symbol:struct objfile *objfile, asymbol *sym:objfile, sym
 EOF
 }
 
index 0234dce..38768cc 100644 (file)
@@ -821,6 +821,7 @@ in_plt_section (CORE_ADDR pc, char *name)
 struct objfile_data
 {
   unsigned index;
+  void (*cleanup) (struct objfile *, void *);
 };
 
 struct objfile_data_registration
@@ -838,7 +839,7 @@ struct objfile_data_registry
 static struct objfile_data_registry objfile_data_registry = { NULL, 0 };
 
 const struct objfile_data *
-register_objfile_data (void)
+register_objfile_data_with_cleanup (void (*cleanup) (struct objfile *, void *))
 {
   struct objfile_data_registration **curr;
 
@@ -850,10 +851,17 @@ register_objfile_data (void)
   (*curr)->next = NULL;
   (*curr)->data = XMALLOC (struct objfile_data);
   (*curr)->data->index = objfile_data_registry.num_registrations++;
+  (*curr)->data->cleanup = cleanup;
 
   return (*curr)->data;
 }
 
+const struct objfile_data *
+register_objfile_data (void)
+{
+  return register_objfile_data_with_cleanup (NULL);
+}
+
 static void
 objfile_alloc_data (struct objfile *objfile)
 {
@@ -866,6 +874,7 @@ static void
 objfile_free_data (struct objfile *objfile)
 {
   gdb_assert (objfile->data != NULL);
+  clear_objfile_data (objfile);
   xfree (objfile->data);
   objfile->data = NULL;
 }
@@ -873,7 +882,17 @@ objfile_free_data (struct objfile *objfile)
 void
 clear_objfile_data (struct objfile *objfile)
 {
+  struct objfile_data_registration *registration;
+  int i;
+
   gdb_assert (objfile->data != NULL);
+
+  for (registration = objfile_data_registry.registrations, i = 0;
+       i < objfile->num_data;
+       registration = registration->next, i++)
+    if (objfile->data[i] != NULL && registration->data->cleanup)
+      registration->data->cleanup (objfile, objfile->data[i]);
+
   memset (objfile->data, 0, objfile->num_data * sizeof (void *));
 }
 
index 4f01f60..c3ae954 100644 (file)
@@ -527,6 +527,8 @@ extern int in_plt_section (CORE_ADDR, char *);
    modules.  */
 
 extern const struct objfile_data *register_objfile_data (void);
+extern const struct objfile_data *register_objfile_data_with_cleanup
+  (void (*cleanup) (struct objfile *, void *));
 extern void clear_objfile_data (struct objfile *objfile);
 extern void set_objfile_data (struct objfile *objfile,
                              const struct objfile_data *data, void *value);