Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: "Ulrich Weigand" <uweigand@de.ibm.com>
To: gdb-patches@sourceware.org
Subject: [rfc] Use proper extraction routine for C++ pointer-to-method types
Date: Thu, 04 Sep 2008 01:44:00 -0000	[thread overview]
Message-ID: <200809040143.m841h9mH013010@d12av02.megacenter.de.ibm.com> (raw)

Hello,

the first element of a C++ "pointer-to-method" is either a pointer to
a function, or else an integer representing an offset into the vtable.

The routines in gnu-v3-abi.c currently use extract_typed_address to
retrieve that value, which is certainly correct for the case of a
pointer to (non-virtual) function.

However, on platforms with nontrivial pointer_to_address conversions
this routine (which calls gdbarch_pointer_to_address) may do the
wrong thing for vtable offsets, which need to be treated as integers.

The following patch fixes this by using the appropriate extraction
routine for either variant.  To reduce code duplication, the code to
perform this conversion is extracted into a new routine.

Tested on powerpc-linux, powerpc64-linux, and spu-elf with no regression.

Any comments on this?

Bye,
Ulrich


ChangeLog:

	* gnu-v3-abi.c (gnuv3_decode_method_ptr): New function.
	(gnuv3_print_method_ptr): Use it.
	(gnuv3_method_ptr_to_value): Likewise.


Index: src/gdb/gnu-v3-abi.c
===================================================================
--- src.orig/gdb/gnu-v3-abi.c
+++ src/gdb/gnu-v3-abi.c
@@ -489,6 +489,46 @@ gnuv3_find_method_in (struct type *domai
   return NULL;
 }
 
+/* Decode GNU v3 method pointer.  */
+
+static int
+gnuv3_decode_method_ptr (const gdb_byte *contents,
+			 CORE_ADDR *value_p,
+			 LONGEST *adjustment_p)
+{
+  struct type *funcptr_type = builtin_type_void_func_ptr;
+  struct type *offset_type = builtin_type_long;
+  CORE_ADDR ptr_value;
+  LONGEST voffset, adjustment;
+  int vbit;
+
+  /* Extract the pointer to member.  The first element is either a pointer
+     or a vtable offset.  For pointers, we need to use extract_typed_address
+     to allow the back-end to convert the pointer to a GDB address -- but
+     vtable offsets we must handle as integers.  At this point, we do not
+     yet know which case we have, so we extract the value under both
+     interpretations and choose the right one later on.  */
+  ptr_value = extract_typed_address (contents, funcptr_type);
+  voffset = extract_signed_integer (contents, TYPE_LENGTH (funcptr_type));
+  contents += TYPE_LENGTH (funcptr_type);
+  adjustment = extract_signed_integer (contents, TYPE_LENGTH (offset_type));
+
+  if (!gdbarch_vbit_in_delta (current_gdbarch))
+    {
+      vbit = voffset & 1;
+      voffset = voffset ^ vbit;
+    }
+  else
+    {
+      vbit = adjustment & 1;
+      adjustment = adjustment >> 1;
+    }
+
+  *value_p = vbit? voffset : ptr_value;
+  *adjustment_p = adjustment;
+  return vbit;
+}
+
 /* GNU v3 implementation of cplus_print_method_ptr.  */
 
 static void
@@ -504,21 +544,7 @@ gnuv3_print_method_ptr (const gdb_byte *
   domain = TYPE_DOMAIN_TYPE (type);
 
   /* Extract the pointer to member.  */
-  ptr_value = extract_typed_address (contents, builtin_type_void_func_ptr);
-  contents += TYPE_LENGTH (builtin_type_void_func_ptr);
-  adjustment = extract_signed_integer (contents,
-				       TYPE_LENGTH (builtin_type_long));
-
-  if (!gdbarch_vbit_in_delta (current_gdbarch))
-    {
-      vbit = ptr_value & 1;
-      ptr_value = ptr_value ^ vbit;
-    }
-  else
-    {
-      vbit = adjustment & 1;
-      adjustment = adjustment >> 1;
-    }
+  vbit = gnuv3_decode_method_ptr (contents, &ptr_value, &adjustment);
 
   /* Check for NULL.  */
   if (ptr_value == 0 && vbit == 0)
@@ -625,21 +651,8 @@ gnuv3_method_ptr_to_value (struct value 
 
   method_type = TYPE_TARGET_TYPE (check_typedef (value_type (method_ptr)));
 
-  ptr_value = extract_typed_address (contents, builtin_type_void_func_ptr);
-  contents += TYPE_LENGTH (builtin_type_void_func_ptr);
-  adjustment = extract_signed_integer (contents,
-				       TYPE_LENGTH (builtin_type_long));
-
-  if (!gdbarch_vbit_in_delta (current_gdbarch))
-    {
-      vbit = ptr_value & 1;
-      ptr_value = ptr_value ^ vbit;
-    }
-  else
-    {
-      vbit = adjustment & 1;
-      adjustment = adjustment >> 1;
-    }
+  /* Extract the pointer to member.  */
+  vbit = gnuv3_decode_method_ptr (contents, &ptr_value, &adjustment);
 
   /* First convert THIS to match the containing type of the pointer to
      member.  This cast may adjust the value of THIS.  */
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


             reply	other threads:[~2008-09-04  1:44 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-09-04  1:44 Ulrich Weigand [this message]
2008-09-04 12:18 ` Daniel Jacobowitz
2008-09-05 11:54   ` Ulrich Weigand

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200809040143.m841h9mH013010@d12av02.megacenter.de.ibm.com \
    --to=uweigand@de.ibm.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox