diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 20 | ||||
-rw-r--r-- | gdb/Makefile.in | 3 | ||||
-rw-r--r-- | gdb/minsyms.c | 17 | ||||
-rw-r--r-- | gdb/ppc-linux-tdep.c | 141 |
4 files changed, 165 insertions, 16 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index ad130d7..8d3aea6 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,25 @@ 2008-05-16 Ulrich Weigand <uweigand@de.ibm.com> + * minsyms.c: Include "target.h". + (find_solib_trampoline_target): Handle minimal symbols pointing + to function descriptors as well. + * Makefile.in (minsyms.o): Update dependencies. + + * ppc-linux-tdep.c (ppc64_standard_linkage): Rename to ... + (ppc64_standard_linkage1): ... this. Fix optional instructions. + (PPC64_STANDARD_LINKAGE_LEN): Rename to ... + (PPC64_STANDARD_LINKAGE1_LEN): ... this. + (ppc64_standard_linkage2, ppc64_standard_linkage3): New. + (PPC64_STANDARD_LINKAGE2_LEN, PPC64_STANDARD_LINKAGE3_LEN): New. + (ppc64_standard_linkage_target): Rename to ... + (ppc64_standard_linkage1_target): ... this. + (ppc64_standard_linkage2_target, ppc64_standard_linkage3_target): New. + (ppc64_skip_trampoline_code): Support three variants of standard + linkage stubs. Call find_solib_trampoline_target to handle + glink stubs. + +2008-05-16 Ulrich Weigand <uweigand@de.ibm.com> + * ppc-linux-tdep.c (ppc_linux_init_abi): Do not install ppc64_sysv_abi_adjust_breakpoint_address. * ppc-sysv-tdep.c (ppc64_sysv_abi_adjust_breakpoint_address): Remove. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 1a6a2de..b60f63c 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -2501,7 +2501,8 @@ mep-tdep.o: $(defs_h) $(frame_h) $(frame_unwind_h) $(frame_base_h) \ mingw-hdep.o: mingw-hdep.c $(defs_h) $(serial_h) $(event_loop_h) \ $(gdb_assert_h) $(gdb_select_h) $(gdb_string_h) $(readline_h) minsyms.o: minsyms.c $(defs_h) $(gdb_string_h) $(symtab_h) $(bfd_h) \ - $(symfile_h) $(objfiles_h) $(demangle_h) $(value_h) $(cp_abi_h) + $(symfile_h) $(objfiles_h) $(demangle_h) $(value_h) $(cp_abi_h) \ + $(target_h) mips64obsd-nat.o: mips64obsd-nat.c $(defs_h) $(inferior_h) $(regcache_h) \ $(target_h) $(mips_tdep_h) $(inf_ptrace_h) mips64obsd-tdep.o: mips64obsd-tdep.c $(defs_h) $(osabi_h) $(regcache_h) \ diff --git a/gdb/minsyms.c b/gdb/minsyms.c index f1a6c48..ca9ba9a 100644 --- a/gdb/minsyms.c +++ b/gdb/minsyms.c @@ -47,6 +47,7 @@ #include "demangle.h" #include "value.h" #include "cp-abi.h" +#include "target.h" /* Accumulate the minimal symbols for each objfile in bunches of BUNCH_SIZE. At the end, copy them all into one newly allocated location on an objfile's @@ -1110,6 +1111,22 @@ find_solib_trampoline_target (struct frame_info *frame, CORE_ADDR pc) && strcmp (SYMBOL_LINKAGE_NAME (msymbol), SYMBOL_LINKAGE_NAME (tsymbol)) == 0) return SYMBOL_VALUE_ADDRESS (msymbol); + + /* Also handle minimal symbols pointing to function descriptors. */ + if (MSYMBOL_TYPE (msymbol) == mst_data + && strcmp (SYMBOL_LINKAGE_NAME (msymbol), + SYMBOL_LINKAGE_NAME (tsymbol)) == 0) + { + CORE_ADDR func; + func = gdbarch_convert_from_func_ptr_addr + (get_objfile_arch (objfile), + SYMBOL_VALUE_ADDRESS (msymbol), + ¤t_target); + + /* Ignore data symbols that are not function descriptors. */ + if (func != SYMBOL_VALUE_ADDRESS (msymbol)) + return func; + } } } return 0; diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index 088e8b2..abc25ed 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -331,7 +331,7 @@ ppc64_desc_entry_point (CORE_ADDR desc) /* Pattern for the standard linkage function. These are built by build_plt_stub in elf64-ppc.c, whose GLINK argument is always zero. */ -static struct insn_pattern ppc64_standard_linkage[] = +static struct insn_pattern ppc64_standard_linkage1[] = { /* addis r12, r2, <any> */ { insn_d (-1, -1, -1, 0), insn_d (15, 12, 2, 0), 0 }, @@ -343,17 +343,16 @@ static struct insn_pattern ppc64_standard_linkage[] = { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 11, 12, 0, 0), 0 }, /* addis r12, r12, 1 <optional> */ - { insn_d (-1, -1, -1, -1), insn_d (15, 12, 2, 1), 1 }, + { insn_d (-1, -1, -1, -1), insn_d (15, 12, 12, 1), 1 }, /* ld r2, <any>(r12) */ { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 2, 12, 0, 0), 0 }, /* addis r12, r12, 1 <optional> */ - { insn_d (-1, -1, -1, -1), insn_d (15, 12, 2, 1), 1 }, + { insn_d (-1, -1, -1, -1), insn_d (15, 12, 12, 1), 1 }, /* mtctr r11 */ - { insn_xfx (-1, -1, -1, -1), insn_xfx (31, 11, 9, 467), - 0 }, + { insn_xfx (-1, -1, -1, -1), insn_xfx (31, 11, 9, 467), 0 }, /* ld r11, <any>(r12) */ { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 11, 12, 0, 0), 0 }, @@ -363,8 +362,68 @@ static struct insn_pattern ppc64_standard_linkage[] = { 0, 0, 0 } }; -#define PPC64_STANDARD_LINKAGE_LEN \ - (sizeof (ppc64_standard_linkage) / sizeof (ppc64_standard_linkage[0])) +#define PPC64_STANDARD_LINKAGE1_LEN \ + (sizeof (ppc64_standard_linkage1) / sizeof (ppc64_standard_linkage1[0])) + +static struct insn_pattern ppc64_standard_linkage2[] = + { + /* addis r12, r2, <any> */ + { insn_d (-1, -1, -1, 0), insn_d (15, 12, 2, 0), 0 }, + + /* std r2, 40(r1) */ + { -1, insn_ds (62, 2, 1, 40, 0), 0 }, + + /* ld r11, <any>(r12) */ + { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 11, 12, 0, 0), 0 }, + + /* addi r12, r12, <any> <optional> */ + { insn_d (-1, -1, -1, 0), insn_d (14, 12, 12, 0), 1 }, + + /* mtctr r11 */ + { insn_xfx (-1, -1, -1, -1), insn_xfx (31, 11, 9, 467), 0 }, + + /* ld r2, <any>(r12) */ + { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 2, 12, 0, 0), 0 }, + + /* ld r11, <any>(r12) */ + { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 11, 12, 0, 0), 0 }, + + /* bctr */ + { -1, 0x4e800420, 0 }, + + { 0, 0, 0 } + }; +#define PPC64_STANDARD_LINKAGE2_LEN \ + (sizeof (ppc64_standard_linkage2) / sizeof (ppc64_standard_linkage2[0])) + +static struct insn_pattern ppc64_standard_linkage3[] = + { + /* std r2, 40(r1) */ + { -1, insn_ds (62, 2, 1, 40, 0), 0 }, + + /* ld r11, <any>(r2) */ + { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 11, 2, 0, 0), 0 }, + + /* addi r2, r2, <any> <optional> */ + { insn_d (-1, -1, -1, 0), insn_d (14, 2, 2, 0), 1 }, + + /* mtctr r11 */ + { insn_xfx (-1, -1, -1, -1), insn_xfx (31, 11, 9, 467), 0 }, + + /* ld r11, <any>(r2) */ + { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 11, 2, 0, 0), 0 }, + + /* ld r2, <any>(r2) */ + { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 2, 2, 0, 0), 0 }, + + /* bctr */ + { -1, 0x4e800420, 0 }, + + { 0, 0, 0 } + }; +#define PPC64_STANDARD_LINKAGE3_LEN \ + (sizeof (ppc64_standard_linkage3) / sizeof (ppc64_standard_linkage3[0])) + /* When the dynamic linker is doing lazy symbol resolution, the first call to a function in another object will go like this: @@ -413,8 +472,8 @@ static struct insn_pattern ppc64_standard_linkage[] = standard linkage function will send them. (This doesn't deal with dynamic linker lazy symbol resolution stubs.) */ static CORE_ADDR -ppc64_standard_linkage_target (struct frame_info *frame, - CORE_ADDR pc, unsigned int *insn) +ppc64_standard_linkage1_target (struct frame_info *frame, + CORE_ADDR pc, unsigned int *insn) { struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (frame)); @@ -430,20 +489,72 @@ ppc64_standard_linkage_target (struct frame_info *frame, return ppc64_desc_entry_point (desc); } +static CORE_ADDR +ppc64_standard_linkage2_target (struct frame_info *frame, + CORE_ADDR pc, unsigned int *insn) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (frame)); + + /* The address of the function descriptor this linkage function + references. */ + CORE_ADDR desc + = ((CORE_ADDR) get_frame_register_unsigned (frame, + tdep->ppc_gp0_regnum + 2) + + (insn_d_field (insn[0]) << 16) + + insn_ds_field (insn[2])); + + /* The first word of the descriptor is the entry point. Return that. */ + return ppc64_desc_entry_point (desc); +} + +static CORE_ADDR +ppc64_standard_linkage3_target (struct frame_info *frame, + CORE_ADDR pc, unsigned int *insn) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (frame)); + + /* The address of the function descriptor this linkage function + references. */ + CORE_ADDR desc + = ((CORE_ADDR) get_frame_register_unsigned (frame, + tdep->ppc_gp0_regnum + 2) + + insn_ds_field (insn[1])); + + /* The first word of the descriptor is the entry point. Return that. */ + return ppc64_desc_entry_point (desc); +} + /* Given that we've begun executing a call trampoline at PC, return the entry point of the function the trampoline will go to. */ static CORE_ADDR ppc64_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc) { - unsigned int ppc64_standard_linkage_insn[PPC64_STANDARD_LINKAGE_LEN]; - - if (insns_match_pattern (pc, ppc64_standard_linkage, - ppc64_standard_linkage_insn)) - return ppc64_standard_linkage_target (frame, pc, - ppc64_standard_linkage_insn); + unsigned int ppc64_standard_linkage1_insn[PPC64_STANDARD_LINKAGE1_LEN]; + unsigned int ppc64_standard_linkage2_insn[PPC64_STANDARD_LINKAGE2_LEN]; + unsigned int ppc64_standard_linkage3_insn[PPC64_STANDARD_LINKAGE3_LEN]; + CORE_ADDR target; + + if (insns_match_pattern (pc, ppc64_standard_linkage1, + ppc64_standard_linkage1_insn)) + pc = ppc64_standard_linkage1_target (frame, pc, + ppc64_standard_linkage1_insn); + else if (insns_match_pattern (pc, ppc64_standard_linkage2, + ppc64_standard_linkage2_insn)) + pc = ppc64_standard_linkage2_target (frame, pc, + ppc64_standard_linkage2_insn); + else if (insns_match_pattern (pc, ppc64_standard_linkage3, + ppc64_standard_linkage3_insn)) + pc = ppc64_standard_linkage3_target (frame, pc, + ppc64_standard_linkage3_insn); else return 0; + + /* The PLT descriptor will either point to the already resolved target + address, or else to a glink stub. As the latter carry synthetic @plt + symbols, find_solib_trampoline_target should be able to resolve them. */ + target = find_solib_trampoline_target (frame, pc); + return target? target : pc; } |