* 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.
This commit is contained in:
Daniel Jacobowitz 2008-05-02 20:38:16 +00:00
parent 574dffa2b9
commit 60c5725ca9
9 changed files with 222 additions and 3 deletions

View File

@ -1,3 +1,23 @@
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.

View 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)

View 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)
@ -2786,6 +2853,65 @@ arm_coff_make_msymbol_special(int val, struct minimal_symbol *msym)
MSYMBOL_SET_SPECIAL (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)
{
@ -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,

View 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

View 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)
@ -946,6 +949,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
fprintf_unfiltered (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);
@ -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. */

View 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);

View File

@ -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
}

View 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 *));
}

View 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);