diff options
-rw-r--r-- | gdb/ChangeLog | 20 | ||||
-rw-r--r-- | gdb/Makefile.in | 5 | ||||
-rw-r--r-- | gdb/linespec.c | 20 | ||||
-rw-r--r-- | gdb/minsyms.c | 20 | ||||
-rw-r--r-- | gdb/parse.c | 43 | ||||
-rw-r--r-- | gdb/symtab.c | 57 | ||||
-rw-r--r-- | gdb/symtab.h | 5 | ||||
-rw-r--r-- | gdb/value.c | 10 |
8 files changed, 136 insertions, 44 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 6912451..7291695 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,23 @@ +2008-05-02 Ulrich Weigand <uweigand@de.ibm.com> + + * linespec.c: Include "target.h". + (minsym_found): Handle minimal symbols pointing to function + descriptors. Use find_function_start_pc. + * minsyms.c (msymbol_objfile): New function. + * parse.c (write_exp_msymbol): Handle minimal symbols pointing + to function descriptors. + * symtab.c (fixup_section): Only use minimal symbol at the same + address to determine section of a symbol. + (find_function_start_pc): New function. + (find_function_start_sal): Use it. + * symtab.h (msymbol_objfile): Add prototype. + (find_function_start_pc): Likewise. + * value.c: Include "objfiles.h". + (value_fn_field): Handle minimal symbols pointing to function + descriptors. + * Makefile.in (linespec.o): Update dependencies. + (value.o): Likewise. + 2008-05-02 Joel Brobecker <brobecker@adacore.com> * ada-lang.c (unwrap_value): Handle the case where the "F" field diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 6afdeba..269ccf7 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -2373,7 +2373,8 @@ libunwind-frame.o: libunwind-frame.c $(defs_h) $(inferior_h) $(frame_h) \ linespec.o: linespec.c $(defs_h) $(symtab_h) $(frame_h) $(command_h) \ $(symfile_h) $(objfiles_h) $(source_h) $(demangle_h) $(value_h) \ $(completer_h) $(cp_abi_h) $(parser_defs_h) $(block_h) $(interps_h) \ - $(objc_lang_h) $(linespec_h) $(exceptions_h) $(language_h) $(mi_cmds_h) + $(objc_lang_h) $(linespec_h) $(exceptions_h) $(language_h) \ + $(mi_cmds_h) $(target_h) linux-fork.o: linux-fork.c $(defs_h) $(inferior_h) $(regcache_h) $(gdbcmd_h) \ $(infcall_h) $(gdb_assert_h) $(gdb_string_h) $(linux_fork_h) \ $(linux_nat_h) $(gdb_wait_h) $(gdb_dirent_h) @@ -2967,7 +2968,7 @@ valprint.o: valprint.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \ value.o: value.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \ $(value_h) $(gdbcore_h) $(command_h) $(gdbcmd_h) $(target_h) \ $(language_h) $(demangle_h) $(doublest_h) \ - $(gdb_assert_h) $(regcache_h) $(block_h) $(dfp_h) + $(gdb_assert_h) $(regcache_h) $(block_h) $(dfp_h) $(objfiles_h) varobj.o: varobj.c $(defs_h) $(exceptions_h) $(value_h) $(expression_h) \ $(frame_h) $(language_h) $(wrapper_h) $(gdbcmd_h) $(block_h) \ $(gdb_assert_h) $(gdb_string_h) $(varobj_h) $(vec_h) $(gdbthread_h) \ diff --git a/gdb/linespec.c b/gdb/linespec.c index 9ffbfd7..c63f162 100644 --- a/gdb/linespec.c +++ b/gdb/linespec.c @@ -38,6 +38,7 @@ #include "language.h" #include "interps.h" #include "mi/mi-cmds.h" +#include "target.h" /* We share this one with symtab.c, but it is not exported widely. */ @@ -1846,21 +1847,32 @@ symbol_found (int funfirstline, char ***canonical, char *copy, static struct symtabs_and_lines minsym_found (int funfirstline, struct minimal_symbol *msymbol) { + struct objfile *objfile = msymbol_objfile (msymbol); + struct gdbarch *gdbarch = get_objfile_arch (objfile); struct symtabs_and_lines values; + CORE_ADDR pc; values.sals = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line)); values.sals[0] = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (msymbol), (struct bfd_section *) 0, 0); values.sals[0].section = SYMBOL_BFD_SECTION (msymbol); + + /* The minimal symbol might point to a function descriptor; + resolve it to the actual code address instead. */ + pc = gdbarch_convert_from_func_ptr_addr (gdbarch, + values.sals[0].pc, + ¤t_target); + if (pc != values.sals[0].pc) + values.sals[0] = find_pc_sect_line (pc, NULL, 0); + if (funfirstline) { struct symtab_and_line sal; - values.sals[0].pc - += gdbarch_deprecated_function_start_offset (current_gdbarch); - values.sals[0].pc = gdbarch_skip_prologue - (current_gdbarch, values.sals[0].pc); + values.sals[0].pc = find_function_start_pc (gdbarch, + values.sals[0].pc, + values.sals[0].section); sal = find_pc_sect_line (values.sals[0].pc, values.sals[0].section, 0); diff --git a/gdb/minsyms.c b/gdb/minsyms.c index 1d0ae6c..8dceb0d 100644 --- a/gdb/minsyms.c +++ b/gdb/minsyms.c @@ -132,6 +132,26 @@ add_minsym_to_demangled_hash_table (struct minimal_symbol *sym, } +/* Return OBJFILE where minimal symbol SYM is defined. */ +struct objfile * +msymbol_objfile (struct minimal_symbol *sym) +{ + struct objfile *objf; + struct minimal_symbol *tsym; + + unsigned int hash + = msymbol_hash (SYMBOL_LINKAGE_NAME (sym)) % MINIMAL_SYMBOL_HASH_SIZE; + + for (objf = object_files; objf; objf = objf->next) + for (tsym = objf->msymbol_hash[hash]; tsym; tsym = tsym->hash_next) + if (tsym == sym) + return objf; + + /* We should always be able to find the objfile ... */ + internal_error (__FILE__, __LINE__, _("failed internal consistency check")); +} + + /* Look through all the current minimal symbol tables and find the first minimal symbol that matches NAME. If OBJF is non-NULL, limit the search to that objfile. If SFILE is non-NULL, the only file-scope diff --git a/gdb/parse.c b/gdb/parse.c index 09ef1df..734739a 100644 --- a/gdb/parse.c +++ b/gdb/parse.c @@ -400,39 +400,46 @@ write_exp_msymbol (struct minimal_symbol *msymbol, struct type *text_symbol_type, struct type *data_symbol_type) { - struct gdbarch *gdbarch = current_gdbarch; - CORE_ADDR addr; + struct objfile *objfile = msymbol_objfile (msymbol); + struct gdbarch *gdbarch = get_objfile_arch (objfile); + + CORE_ADDR addr = SYMBOL_VALUE_ADDRESS (msymbol); + asection *bfd_section = SYMBOL_BFD_SECTION (msymbol); + enum minimal_symbol_type type = msymbol->type; + CORE_ADDR pc; + + /* The minimal symbol might point to a function descriptor; + resolve it to the actual code address instead. */ + pc = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, ¤t_target); + if (pc != addr) + { + /* In this case, assume we have a code symbol instead of + a data symbol. */ + type = mst_text; + bfd_section = NULL; + addr = pc; + } + + if (overlay_debugging) + addr = symbol_overlayed_address (addr, bfd_section); write_exp_elt_opcode (OP_LONG); /* Let's make the type big enough to hold a 64-bit address. */ write_exp_elt_type (builtin_type_CORE_ADDR); - - addr = SYMBOL_VALUE_ADDRESS (msymbol); - if (overlay_debugging) - addr = symbol_overlayed_address (addr, SYMBOL_BFD_SECTION (msymbol)); write_exp_elt_longcst ((LONGEST) addr); - write_exp_elt_opcode (OP_LONG); - if (SYMBOL_BFD_SECTION (msymbol) - && SYMBOL_BFD_SECTION (msymbol)->flags & SEC_THREAD_LOCAL) + if (bfd_section && bfd_section->flags & SEC_THREAD_LOCAL) { - bfd *bfd = SYMBOL_BFD_SECTION (msymbol)->owner; - struct objfile *ofp; - - ALL_OBJFILES (ofp) - if (ofp->obfd == bfd) - break; - write_exp_elt_opcode (UNOP_MEMVAL_TLS); - write_exp_elt_objfile (ofp); + write_exp_elt_objfile (objfile); write_exp_elt_type (builtin_type (gdbarch)->nodebug_tls_symbol); write_exp_elt_opcode (UNOP_MEMVAL_TLS); return; } write_exp_elt_opcode (UNOP_MEMVAL); - switch (msymbol->type) + switch (type) { case mst_text: case mst_file_text: diff --git a/gdb/symtab.c b/gdb/symtab.c index 5eb1d9d..608ce6b 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -998,7 +998,13 @@ fixup_section (struct general_symbol_info *ginfo, struct objfile *objfile) struct minimal_symbol *msym; msym = lookup_minimal_symbol (ginfo->name, NULL, objfile); - if (msym) + /* First, check whether a minimal symbol with the same name exists + and points to the same address. The address check is required + e.g. on PowerPC64, where the minimal symbol for a function will + point to the function descriptor, while the debug symbol will + point to the actual function code. */ + if (msym + && SYMBOL_VALUE_ADDRESS (msym) == ginfo->value.address) { ginfo->bfd_section = SYMBOL_BFD_SECTION (msym); ginfo->section = SYMBOL_SECTION (msym); @@ -2530,6 +2536,26 @@ find_pc_line_pc_range (CORE_ADDR pc, CORE_ADDR *startptr, CORE_ADDR *endptr) return sal.symtab != 0; } +/* Given a function start address PC and SECTION, find the first + address after the function prologue. */ +CORE_ADDR +find_function_start_pc (struct gdbarch *gdbarch, + CORE_ADDR pc, asection *section) +{ + /* If the function is in an unmapped overlay, use its unmapped LMA address, + so that gdbarch_skip_prologue has something unique to work on. */ + if (section_is_overlay (section) && !section_is_mapped (section)) + pc = overlay_unmapped_address (pc, section); + + pc += gdbarch_deprecated_function_start_offset (gdbarch); + pc = gdbarch_skip_prologue (gdbarch, pc); + + /* For overlays, map pc back into its mapped VMA range. */ + pc = overlay_mapped_address (pc, section); + + return pc; +} + /* Given a function symbol SYM, find the symtab and line for the start of the function. If the argument FUNFIRSTLINE is nonzero, we want the first line @@ -2538,34 +2564,27 @@ find_pc_line_pc_range (CORE_ADDR pc, CORE_ADDR *startptr, CORE_ADDR *endptr) struct symtab_and_line find_function_start_sal (struct symbol *sym, int funfirstline) { + struct block *block = SYMBOL_BLOCK_VALUE (sym); + struct objfile *objfile = lookup_objfile_from_block (block); + struct gdbarch *gdbarch = get_objfile_arch (objfile); + CORE_ADDR pc; struct symtab_and_line sal; - pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)); - fixup_symbol_section (sym, NULL); + pc = BLOCK_START (block); + fixup_symbol_section (sym, objfile); if (funfirstline) - { /* skip "first line" of function (which is actually its prologue) */ - asection *section = SYMBOL_BFD_SECTION (sym); - /* If function is in an unmapped overlay, use its unmapped LMA - address, so that gdbarch_skip_prologue has something unique to work - on */ - if (section_is_overlay (section) && - !section_is_mapped (section)) - pc = overlay_unmapped_address (pc, section); - - pc += gdbarch_deprecated_function_start_offset (current_gdbarch); - pc = gdbarch_skip_prologue (current_gdbarch, pc); - - /* For overlays, map pc back into its mapped VMA range */ - pc = overlay_mapped_address (pc, section); + { + /* Skip "first line" of function (which is actually its prologue). */ + pc = find_function_start_pc (gdbarch, pc, SYMBOL_BFD_SECTION (sym)); } sal = find_pc_sect_line (pc, SYMBOL_BFD_SECTION (sym), 0); /* Check if gdbarch_skip_prologue left us in mid-line, and the next line is still part of the same function. */ if (sal.pc != pc - && BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) <= sal.end - && sal.end < BLOCK_END (SYMBOL_BLOCK_VALUE (sym))) + && BLOCK_START (block) <= sal.end + && sal.end < BLOCK_END (block)) { /* First pc of next line */ pc = sal.end; diff --git a/gdb/symtab.h b/gdb/symtab.h index ffcc446..8aa3fc5 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -1168,6 +1168,8 @@ extern unsigned int msymbol_hash_iw (const char *); extern unsigned int msymbol_hash (const char *); +extern struct objfile * msymbol_objfile (struct minimal_symbol *sym); + extern void add_minsym_to_hash_table (struct minimal_symbol *sym, struct minimal_symbol **table); @@ -1342,6 +1344,9 @@ extern struct partial_symtab *find_main_psymtab (void); extern struct symtab *find_line_symtab (struct symtab *, int, int *, int *); +extern CORE_ADDR find_function_start_pc (struct gdbarch *, + CORE_ADDR, asection *); + extern struct symtab_and_line find_function_start_sal (struct symbol *sym, int); diff --git a/gdb/value.c b/gdb/value.c index 52d0030..21a7e6c 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -35,6 +35,7 @@ #include "regcache.h" #include "block.h" #include "dfp.h" +#include "objfiles.h" /* Prototypes for exported functions. */ @@ -1433,7 +1434,14 @@ value_fn_field (struct value **arg1p, struct fn_field *f, int j, struct type *ty } else { - VALUE_ADDRESS (v) = SYMBOL_VALUE_ADDRESS (msym); + /* The minimal symbol might point to a function descriptor; + resolve it to the actual code address instead. */ + struct objfile *objfile = msymbol_objfile (msym); + struct gdbarch *gdbarch = get_objfile_arch (objfile); + + VALUE_ADDRESS (v) + = gdbarch_convert_from_func_ptr_addr + (gdbarch, SYMBOL_VALUE_ADDRESS (msym), ¤t_target); } if (arg1p) |