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]

[RFA 2/2] amd64-windows: Arguments passed by pointer


This patch provides support for arguments passed by pointer in
inferior function calls.

gdb/ChangeLog:

        * i386-tdep.h (struct gdbarch_tdep): Add new field
        "handle_args_passed_by_pointer".
        * amd64-tdep.c (amd64_push_arguments): Add handling of
        arguments to be passed by pointer.
        * amd64-windows-tdep.c: #include "value.h".
        (amd64_windows_passed_by_pointer): New function.
        (amd64_windows_handle_args_passed_by_pointer): New function.
        (amd64_windows_init_abi): Set tdep->handle_args_passed_by_pointer.

Tested on amd64-windows and amd64-linux.
OK to commit?

Thanks,
-- 
Joel

---
 gdb/amd64-tdep.c         |   12 +++++++++++
 gdb/amd64-windows-tdep.c |   53 ++++++++++++++++++++++++++++++++++++++++++++++
 gdb/i386-tdep.h          |   14 ++++++++++++
 3 files changed, 79 insertions(+)

diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index c6ee493..d464a35 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -771,6 +771,18 @@ amd64_push_arguments (struct regcache *regcache, int nargs,
 
   gdb_assert (tdep->classify);
 
+  if (tdep->handle_args_passed_by_pointer)
+    {
+      /* Make a copy of the array of arguments, and let
+	 handle_args_passed_by_pointer transform those that need
+	 to be passed by pointer.  */
+      struct value **args1 = alloca (nargs * sizeof (struct value *));
+
+      memcpy (args1, args, nargs * sizeof (struct value *));
+      sp = tdep->handle_args_passed_by_pointer (args1, nargs, sp);
+      args = args1;
+    }
+
   /* Reserve a register for the "hidden" argument.  */
   if (struct_return)
     integer_reg++;
diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c
index 3e8a830..0b616f3 100644
--- a/gdb/amd64-windows-tdep.c
+++ b/gdb/amd64-windows-tdep.c
@@ -25,6 +25,7 @@
 #include "regcache.h"
 #include "windows-tdep.h"
 #include "frame.h"
+#include "value.h"
 
 /* The registers used to pass integer arguments during a function call.  */
 static int amd64_windows_dummy_call_integer_regs[] =
@@ -35,6 +36,56 @@ static int amd64_windows_dummy_call_integer_regs[] =
   9                          /* %r9 */
 };
 
+/* Return non-zero iff an argument of the given TYPE should be passed
+   by pointer.  */
+
+static int
+amd64_windows_passed_by_pointer (struct type *type)
+{
+  /* Only structs and unions are passed by pointer.  */
+  if (TYPE_CODE (type) != TYPE_CODE_STRUCT
+      && TYPE_CODE (type) != TYPE_CODE_UNION)
+    return 0;
+
+  /* Among these, only struct/unions whose size is different from
+     1, 2, 4 or 8 bytes are passed by pointer.  */
+  return (TYPE_LENGTH (type) != 1
+	  && TYPE_LENGTH (type) != 2
+	  && TYPE_LENGTH (type) != 4
+	  && TYPE_LENGTH (type) != 8);
+}
+
+/* Implement the "handle_args_passed_by_pointer" in the gdbarch_tdep
+   structure for amd64-windows.  */
+
+static CORE_ADDR
+amd64_windows_handle_args_passed_by_pointer (struct value **args,
+                                             int nargs, CORE_ADDR sp)
+{
+  int i;
+
+  for (i = 0; i < nargs; i++)
+    if (amd64_windows_passed_by_pointer (value_type (args[i])))
+      {
+	struct type *type = value_type (args[i]);
+	const gdb_byte *valbuf = value_contents (args[i]);
+	const int len = TYPE_LENGTH (type);
+
+	/* Store a copy of that argument on the stack, aligned to
+	   a 16 bytes boundary, and then use the copy's address as
+	   the argument.  */
+
+	sp -= len;
+	sp &= ~0xf;
+	write_memory (sp, valbuf, len);
+
+	args[i] =
+	  value_addr (value_from_contents_and_address (type, valbuf, sp));
+      }
+
+  return sp;
+}
+
 /* Implement the "classify" method in the gdbarch_tdep structure
    for amd64-windows.  */
 
@@ -212,6 +263,8 @@ amd64_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   tdep->call_dummy_num_integer_regs =
     ARRAY_SIZE (amd64_windows_dummy_call_integer_regs);
   tdep->call_dummy_integer_regs = amd64_windows_dummy_call_integer_regs;
+  tdep->handle_args_passed_by_pointer =
+    amd64_windows_handle_args_passed_by_pointer;
   tdep->classify = amd64_windows_classify;
   tdep->integer_param_regs_saved_in_caller_frame = 1;
   set_gdbarch_return_value (gdbarch, amd64_windows_return_value);
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index 01b0936..ce38600 100644
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -81,6 +81,20 @@ struct gdbarch_tdep
   int call_dummy_num_integer_regs;
   int *call_dummy_integer_regs;
 
+  /* Only used on platforms where some arguments are to be passed
+     by pointer (the caller is expected to make a copy of the argument
+     and then pass its address as the argument).
+
+     For each argument that should be passed by pointer, reserve some
+     stack space, store a copy of the argument on the stack, and replace
+     the argument by its address.  Return the new Stack Pointer value.
+
+     NARGS is the number of arguments. ARGS is the array containing
+     the value of each argument.  SP is value of the Stack Pointer.  */
+
+  CORE_ADDR (*handle_args_passed_by_pointer) (struct value **args,
+					      int nargs, CORE_ADDR sp);
+
   /* Used on amd64 only.  Classify TYPE according to calling conventions,
      and store the result in CLASS.  */
   void (*classify) (struct type *type, enum amd64_reg_class class[2]);
-- 
1.7.9.5


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