From: Daniel Jacobowitz Date: Mon, 7 May 2007 11:49:05 +0000 (+0000) Subject: * Makefile.in (c-lang.o, gnu-v3-abi.o): Update. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b18be20d0aadff1e7c5b4d161177481aa61b9fc4;p=binutils-gdb.git * Makefile.in (c-lang.o, gnu-v3-abi.o): Update. * NEWS: Mention improved C++ thunk support. * c-lang.c (cplus_language_defn): Mention cplus_skip_trampoline. * cp-abi.c (cplus_skip_trampoline): New. * cp-abi.h (cplus_skip_trampoline): New prototype. (struct cp_abi_ops): Add skip_trampoline member. * gnu-v3-abi.c (gnuv3_skip_trampoline): New. (init_gnuv3_ops): Set skip_trampoline. * gdb.cp/virtfunc.exp (proc do_tests): Test stepping through a thunk. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 815d1dab815..d059e46a887 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2007-05-07 Daniel Jacobowitz + + * Makefile.in (c-lang.o, gnu-v3-abi.o): Update. + * NEWS: Mention improved C++ thunk support. + * c-lang.c (cplus_language_defn): Mention cplus_skip_trampoline. + * cp-abi.c (cplus_skip_trampoline): New. + * cp-abi.h (cplus_skip_trampoline): New prototype. + (struct cp_abi_ops): Add skip_trampoline member. + * gnu-v3-abi.c (gnuv3_skip_trampoline): New. + (init_gnuv3_ops): Set skip_trampoline. + 2007-05-06 Daniel Jacobowitz * rs6000-tdep.c (struct frame_extra_info): Delete. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 1486a98a747..07da75dca54 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1862,7 +1862,7 @@ charset.o: charset.c $(defs_h) $(charset_h) $(gdbcmd_h) $(gdb_assert_h) \ c-lang.o: c-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \ $(parser_defs_h) $(language_h) $(c_lang_h) $(valprint_h) \ $(macroscope_h) $(gdb_assert_h) $(charset_h) $(gdb_string_h) \ - $(demangle_h) $(cp_support_h) + $(demangle_h) $(cp_abi_h) $(cp_support_h) cli-out.o: cli-out.c $(defs_h) $(ui_out_h) $(cli_out_h) $(gdb_string_h) \ $(gdb_assert_h) coff-pe-read.o: coff-pe-read.c $(coff_pe_read_h) $(bfd_h) $(defs_h) \ @@ -2043,7 +2043,8 @@ gnu-v2-abi.o: gnu-v2-abi.c $(defs_h) $(gdb_string_h) $(symtab_h) \ $(gdbtypes_h) $(value_h) $(demangle_h) $(cp_abi_h) $(cp_support_h) \ $(gnu_v2_abi_h) gnu-v3-abi.o: gnu-v3-abi.c $(defs_h) $(value_h) $(cp_abi_h) $(cp_support_h) \ - $(demangle_h) $(valprint_h) $(gdb_assert_h) $(gdb_string_h) + $(demangle_h) $(objfiles_h) $(valprint_h) \ + $(gdb_assert_h) $(gdb_string_h) go32-nat.o: go32-nat.c $(defs_h) $(inferior_h) $(gdb_wait_h) $(gdbcore_h) \ $(command_h) $(gdbcmd_h) $(floatformat_h) $(buildsym_h) \ $(i387_tdep_h) $(i386_tdep_h) $(value_h) $(regcache_h) \ diff --git a/gdb/NEWS b/gdb/NEWS index 14ffee12666..9ce7e668605 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -29,6 +29,8 @@ iWMMXt coprocessor. ARM Windows CE (mingw32ce) debugging, and GDB Windows CE support has been rewritten to use the standard GDB remote protocol. +* GDB can now step into C++ functions which are called through thunks. + * New commands set mem inaccessible-by-default diff --git a/gdb/c-lang.c b/gdb/c-lang.c index af421882269..52b2a36b221 100644 --- a/gdb/c-lang.c +++ b/gdb/c-lang.c @@ -33,6 +33,7 @@ #include "charset.h" #include "gdb_string.h" #include "demangle.h" +#include "cp-abi.h" #include "cp-support.h" extern void _initialize_c_language (void); @@ -642,7 +643,7 @@ const struct language_defn cplus_language_defn = c_print_type, /* Print a type using appropriate syntax */ c_val_print, /* Print a value using appropriate syntax */ c_value_print, /* Print a top-level value */ - NULL, /* Language specific skip_trampoline */ + cplus_skip_trampoline, /* Language specific skip_trampoline */ value_of_this, /* value_of_this */ cp_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */ cp_lookup_transparent_type, /* lookup_transparent_type */ diff --git a/gdb/cp-abi.c b/gdb/cp-abi.c index 23b5f9a20e1..7bc15525977 100644 --- a/gdb/cp-abi.c +++ b/gdb/cp-abi.c @@ -121,6 +121,14 @@ cplus_make_method_ptr (gdb_byte *contents, CORE_ADDR value, int is_virtual) (*current_cp_abi.make_method_ptr) (contents, value, is_virtual); } +CORE_ADDR +cplus_skip_trampoline (CORE_ADDR stop_pc) +{ + if (current_cp_abi.skip_trampoline == NULL) + return 0; + return (*current_cp_abi.skip_trampoline) (stop_pc); +} + struct value * cplus_method_ptr_to_value (struct value **this_p, struct value *method_ptr) { diff --git a/gdb/cp-abi.h b/gdb/cp-abi.h index 4ddc121bab1..91d89b340b0 100644 --- a/gdb/cp-abi.h +++ b/gdb/cp-abi.h @@ -170,6 +170,11 @@ struct value *cplus_method_ptr_to_value (struct value **this_p, void cplus_make_method_ptr (gdb_byte *CONTENTS, CORE_ADDR address, int is_virtual); +/* Determine if we are currently in a C++ thunk. If so, get the address + of the routine we are thunking to and continue to there instead. */ + +CORE_ADDR cplus_skip_trampoline (CORE_ADDR stop_pc); + struct cp_abi_ops { const char *shortname; @@ -192,6 +197,7 @@ struct cp_abi_ops int (*method_ptr_size) (void); void (*make_method_ptr) (gdb_byte *, CORE_ADDR, int); struct value * (*method_ptr_to_value) (struct value **, struct value *); + CORE_ADDR (*skip_trampoline) (CORE_ADDR); }; diff --git a/gdb/gnu-v3-abi.c b/gdb/gnu-v3-abi.c index 54feb779c70..d3c278c96a0 100644 --- a/gdb/gnu-v3-abi.c +++ b/gdb/gnu-v3-abi.c @@ -26,6 +26,7 @@ #include "cp-abi.h" #include "cp-support.h" #include "demangle.h" +#include "objfiles.h" #include "valprint.h" #include "gdb_assert.h" @@ -673,6 +674,47 @@ gnuv3_method_ptr_to_value (struct value **this_p, struct value *method_ptr) return value_from_pointer (lookup_pointer_type (method_type), ptr_value); } +/* Determine if we are currently in a C++ thunk. If so, get the address + of the routine we are thunking to and continue to there instead. */ + +static CORE_ADDR +gnuv3_skip_trampoline (CORE_ADDR stop_pc) +{ + CORE_ADDR real_stop_pc, method_stop_pc; + struct minimal_symbol *thunk_sym, *fn_sym; + struct obj_section *section; + char *thunk_name, *fn_name; + + real_stop_pc = SKIP_TRAMPOLINE_CODE (stop_pc); + if (real_stop_pc == 0) + real_stop_pc = stop_pc; + + /* Find the linker symbol for this potential thunk. */ + thunk_sym = lookup_minimal_symbol_by_pc (real_stop_pc); + section = find_pc_section (real_stop_pc); + if (thunk_sym == NULL || section == NULL) + return 0; + + /* The symbol's demangled name should be something like "virtual + thunk to FUNCTION", where FUNCTION is the name of the function + being thunked to. */ + thunk_name = SYMBOL_DEMANGLED_NAME (thunk_sym); + if (thunk_name == NULL || strstr (thunk_name, " thunk to ") == NULL) + return 0; + + fn_name = strstr (thunk_name, " thunk to ") + strlen (" thunk to "); + fn_sym = lookup_minimal_symbol (fn_name, NULL, section->objfile); + if (fn_sym == NULL) + return 0; + + method_stop_pc = SYMBOL_VALUE_ADDRESS (fn_sym); + real_stop_pc = SKIP_TRAMPOLINE_CODE (method_stop_pc); + if (real_stop_pc == 0) + real_stop_pc = method_stop_pc; + + return real_stop_pc; +} + static void init_gnuv3_ops (void) { @@ -694,6 +736,7 @@ init_gnuv3_ops (void) gnu_v3_abi_ops.method_ptr_size = gnuv3_method_ptr_size; gnu_v3_abi_ops.make_method_ptr = gnuv3_make_method_ptr; gnu_v3_abi_ops.method_ptr_to_value = gnuv3_method_ptr_to_value; + gnu_v3_abi_ops.skip_trampoline = gnuv3_skip_trampoline; } extern initialize_file_ftype _initialize_gnu_v3_abi; /* -Wmissing-prototypes */ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 9add7019861..ac1e20a38f9 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2007-05-07 Daniel Jacobowitz + + * gdb.cp/virtfunc.exp (proc do_tests): Test stepping through a thunk. + 2007-05-06 Daniel Jacobowitz * gdb.fortran/complex.exp, gdb.fortran/complex.f: New files. diff --git a/gdb/testsuite/gdb.cp/virtfunc.exp b/gdb/testsuite/gdb.cp/virtfunc.exp index 6f7a6e90e2a..4b1472eb58b 100644 --- a/gdb/testsuite/gdb.cp/virtfunc.exp +++ b/gdb/testsuite/gdb.cp/virtfunc.exp @@ -254,6 +254,10 @@ proc do_tests {} { gdb_breakpoint test_calls gdb_test "continue" ".*Breakpoint .* test_calls.*" "" test_virtual_calls + + gdb_test "next" ".*pAa->f.*" "next to pAa->f call" + gdb_test "next" ".*pDe->vg.*" "next to pDe->vg call" + gdb_test "step" ".*E::vg.*" "step through thunk into E::vg" } do_tests