* 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.
This commit is contained in:
Daniel Jacobowitz 2007-05-07 11:49:05 +00:00
parent dda9b909e6
commit b18be20d0a
9 changed files with 83 additions and 3 deletions

View file

@ -1,3 +1,14 @@
2007-05-07 Daniel Jacobowitz <dan@codesourcery.com>
* 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 <dan@codesourcery.com> 2007-05-06 Daniel Jacobowitz <dan@codesourcery.com>
* rs6000-tdep.c (struct frame_extra_info): Delete. * rs6000-tdep.c (struct frame_extra_info): Delete.

View file

@ -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) \ c-lang.o: c-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \
$(parser_defs_h) $(language_h) $(c_lang_h) $(valprint_h) \ $(parser_defs_h) $(language_h) $(c_lang_h) $(valprint_h) \
$(macroscope_h) $(gdb_assert_h) $(charset_h) $(gdb_string_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) \ cli-out.o: cli-out.c $(defs_h) $(ui_out_h) $(cli_out_h) $(gdb_string_h) \
$(gdb_assert_h) $(gdb_assert_h)
coff-pe-read.o: coff-pe-read.c $(coff_pe_read_h) $(bfd_h) $(defs_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) \ $(gdbtypes_h) $(value_h) $(demangle_h) $(cp_abi_h) $(cp_support_h) \
$(gnu_v2_abi_h) $(gnu_v2_abi_h)
gnu-v3-abi.o: gnu-v3-abi.c $(defs_h) $(value_h) $(cp_abi_h) $(cp_support_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) \ go32-nat.o: go32-nat.c $(defs_h) $(inferior_h) $(gdb_wait_h) $(gdbcore_h) \
$(command_h) $(gdbcmd_h) $(floatformat_h) $(buildsym_h) \ $(command_h) $(gdbcmd_h) $(floatformat_h) $(buildsym_h) \
$(i387_tdep_h) $(i386_tdep_h) $(value_h) $(regcache_h) \ $(i387_tdep_h) $(i386_tdep_h) $(value_h) $(regcache_h) \

View file

@ -29,6 +29,8 @@ iWMMXt coprocessor.
ARM Windows CE (mingw32ce) debugging, and GDB Windows CE support ARM Windows CE (mingw32ce) debugging, and GDB Windows CE support
has been rewritten to use the standard GDB remote protocol. has been rewritten to use the standard GDB remote protocol.
* GDB can now step into C++ functions which are called through thunks.
* New commands * New commands
set mem inaccessible-by-default set mem inaccessible-by-default

View file

@ -33,6 +33,7 @@
#include "charset.h" #include "charset.h"
#include "gdb_string.h" #include "gdb_string.h"
#include "demangle.h" #include "demangle.h"
#include "cp-abi.h"
#include "cp-support.h" #include "cp-support.h"
extern void _initialize_c_language (void); 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_print_type, /* Print a type using appropriate syntax */
c_val_print, /* Print a value using appropriate syntax */ c_val_print, /* Print a value using appropriate syntax */
c_value_print, /* Print a top-level value */ 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 */ value_of_this, /* value_of_this */
cp_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */ cp_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
cp_lookup_transparent_type, /* lookup_transparent_type */ cp_lookup_transparent_type, /* lookup_transparent_type */

View file

@ -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); (*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 * struct value *
cplus_method_ptr_to_value (struct value **this_p, struct value *method_ptr) cplus_method_ptr_to_value (struct value **this_p, struct value *method_ptr)
{ {

View file

@ -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, void cplus_make_method_ptr (gdb_byte *CONTENTS, CORE_ADDR address,
int is_virtual); 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 struct cp_abi_ops
{ {
const char *shortname; const char *shortname;
@ -192,6 +197,7 @@ struct cp_abi_ops
int (*method_ptr_size) (void); int (*method_ptr_size) (void);
void (*make_method_ptr) (gdb_byte *, CORE_ADDR, int); void (*make_method_ptr) (gdb_byte *, CORE_ADDR, int);
struct value * (*method_ptr_to_value) (struct value **, struct value *); struct value * (*method_ptr_to_value) (struct value **, struct value *);
CORE_ADDR (*skip_trampoline) (CORE_ADDR);
}; };

View file

@ -26,6 +26,7 @@
#include "cp-abi.h" #include "cp-abi.h"
#include "cp-support.h" #include "cp-support.h"
#include "demangle.h" #include "demangle.h"
#include "objfiles.h"
#include "valprint.h" #include "valprint.h"
#include "gdb_assert.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); 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 static void
init_gnuv3_ops (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.method_ptr_size = gnuv3_method_ptr_size;
gnu_v3_abi_ops.make_method_ptr = gnuv3_make_method_ptr; 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.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 */ extern initialize_file_ftype _initialize_gnu_v3_abi; /* -Wmissing-prototypes */

View file

@ -1,3 +1,7 @@
2007-05-07 Daniel Jacobowitz <dan@codesourcery.com>
* gdb.cp/virtfunc.exp (proc do_tests): Test stepping through a thunk.
2007-05-06 Daniel Jacobowitz <dan@codesourcery.com> 2007-05-06 Daniel Jacobowitz <dan@codesourcery.com>
* gdb.fortran/complex.exp, gdb.fortran/complex.f: New files. * gdb.fortran/complex.exp, gdb.fortran/complex.f: New files.

View file

@ -254,6 +254,10 @@ proc do_tests {} {
gdb_breakpoint test_calls gdb_breakpoint test_calls
gdb_test "continue" ".*Breakpoint .* test_calls.*" "" gdb_test "continue" ".*Breakpoint .* test_calls.*" ""
test_virtual_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 do_tests