aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Jacobowitz <drow@false.org>2008-05-02 20:38:16 +0000
committerDaniel Jacobowitz <drow@false.org>2008-05-02 20:38:16 +0000
commit60c5725ca96c0d9c347f04d37f0e1f6d0f263f41 (patch)
tree387933a649a79c50e3a372850696b04dbe644995
parent574dffa2b953e04f57a359f0e19b2ba42fbcf2a6 (diff)
downloadgdb-60c5725ca96c0d9c347f04d37f0e1f6d0f263f41.zip
gdb-60c5725ca96c0d9c347f04d37f0e1f6d0f263f41.tar.gz
gdb-60c5725ca96c0d9c347f04d37f0e1f6d0f263f41.tar.bz2
* 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.
-rw-r--r--gdb/ChangeLog20
-rw-r--r--gdb/Makefile.in2
-rw-r--r--gdb/arm-tdep.c130
-rw-r--r--gdb/elfread.c6
-rw-r--r--gdb/gdbarch.c33
-rw-r--r--gdb/gdbarch.h8
-rwxr-xr-xgdb/gdbarch.sh3
-rw-r--r--gdb/objfiles.c21
-rw-r--r--gdb/objfiles.h2
9 files changed, 222 insertions, 3 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e349f77..c7515cb 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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>
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 16dd2ee..6afdeba 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -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)
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index fa7a3e8..9fbd0fc 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -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,
diff --git a/gdb/elfread.c b/gdb/elfread.c
index 88ea77b..76af9dc 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -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
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 0449aaa..537da18 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -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. */
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index e89bd46..560b2ef 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -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);
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 08e3741..aedd9e5 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -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
}
diff --git a/gdb/objfiles.c b/gdb/objfiles.c
index 0234dce..38768cc 100644
--- a/gdb/objfiles.c
+++ b/gdb/objfiles.c
@@ -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 *));
}
diff --git a/gdb/objfiles.h b/gdb/objfiles.h
index 4f01f60..c3ae954 100644
--- a/gdb/objfiles.h
+++ b/gdb/objfiles.h
@@ -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);