This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[commit] C++ thunk support


(Five years ago, whoops) Andrew Walrond reported that he had trouble
stepping into C++ functions which were called by thunks, which
e.g. adjust "this".  This patch adds support to GDB to detect those
thunks and automatically step through them, just like we do for
Objective C.

Tested x86_64-linux and committed.

-- 
Daniel Jacobowitz
CodeSourcery

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-07  Daniel Jacobowitz  <dan@codesourcery.com>

	* gdb.cp/virtfunc.exp (proc do_tests): Test stepping through a thunk.

Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.907
diff -u -p -r1.907 Makefile.in
--- Makefile.in	7 May 2007 00:21:02 -0000	1.907
+++ Makefile.in	7 May 2007 03:15:28 -0000
@@ -1862,7 +1862,7 @@ charset.o: charset.c $(defs_h) $(charset
 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) $(g
 	$(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) \
Index: NEWS
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.223
diff -u -p -r1.223 NEWS
--- NEWS	6 May 2007 23:04:26 -0000	1.223
+++ NEWS	7 May 2007 03:15:29 -0000
@@ -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
Index: c-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/c-lang.c,v
retrieving revision 1.40
diff -u -p -r1.40 c-lang.c
--- c-lang.c	9 Jan 2007 17:58:50 -0000	1.40
+++ c-lang.c	7 May 2007 03:15:29 -0000
@@ -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_languag
   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 */
Index: cp-abi.c
===================================================================
RCS file: /cvs/src/src/gdb/cp-abi.c,v
retrieving revision 1.15
diff -u -p -r1.15 cp-abi.c
--- cp-abi.c	9 Jan 2007 17:58:50 -0000	1.15
+++ cp-abi.c	7 May 2007 03:15:29 -0000
@@ -121,6 +121,14 @@ cplus_make_method_ptr (gdb_byte *content
   (*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)
 {
Index: cp-abi.h
===================================================================
RCS file: /cvs/src/src/gdb/cp-abi.h,v
retrieving revision 1.11
diff -u -p -r1.11 cp-abi.h
--- cp-abi.h	9 Jan 2007 17:58:50 -0000	1.11
+++ cp-abi.h	7 May 2007 03:15:29 -0000
@@ -170,6 +170,11 @@ struct value *cplus_method_ptr_to_value 
 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);
 };
 
 
Index: gnu-v3-abi.c
===================================================================
RCS file: /cvs/src/src/gdb/gnu-v3-abi.c,v
retrieving revision 1.31
diff -u -p -r1.31 gnu-v3-abi.c
--- gnu-v3-abi.c	9 Jan 2007 17:58:51 -0000	1.31
+++ gnu-v3-abi.c	7 May 2007 03:15:29 -0000
@@ -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 
     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 */
Index: testsuite/gdb.cp/virtfunc.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/virtfunc.exp,v
retrieving revision 1.14
diff -u -p -r1.14 virtfunc.exp
--- testsuite/gdb.cp/virtfunc.exp	9 Jan 2007 17:59:12 -0000	1.14
+++ testsuite/gdb.cp/virtfunc.exp	7 May 2007 03:15:29 -0000
@@ -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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]