* 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:
parent
574dffa2b9
commit
60c5725ca9
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
130
gdb/arm-tdep.c
130
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)
|
||||
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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 *));
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue