2007-06-13 Claudio Fontana <claudio.fontana@gmail.com>
[deliverable/binutils-gdb.git] / gdb / gnu-v3-abi.c
index 54feb779c70370114e12c595a3fc0333fd94654b..0f9f420844ae56371cef89dda6bae636180f5c40 100644 (file)
@@ -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"
@@ -116,7 +117,8 @@ build_gdb_vtable_type (struct gdbarch *arch)
 
   /* ARCH can't give us the true ptrdiff_t type, so we guess.  */
   struct type *ptrdiff_type
-    = init_type (TYPE_CODE_INT, TARGET_PTR_BIT / TARGET_CHAR_BIT, 0,
+    = init_type (TYPE_CODE_INT,
+                gdbarch_ptr_bit (current_gdbarch) / TARGET_CHAR_BIT, 0,
                  "ptrdiff_t", 0);
 
   /* We assume no padding is necessary, since GDB doesn't know
@@ -673,6 +675,48 @@ 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 = gdbarch_skip_trampoline_code (current_gdbarch, 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 = gdbarch_skip_trampoline_code
+                  (current_gdbarch, 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 +738,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 */
This page took 0.024812 seconds and 4 git commands to generate.