amd64-windows: memory args passed by pointer during function calls.
authorJoel Brobecker <brobecker@gnat.com>
Fri, 29 Jan 2010 05:21:55 +0000 (05:21 +0000)
committerJoel Brobecker <brobecker@gnat.com>
Fri, 29 Jan 2010 05:21:55 +0000 (05:21 +0000)
        * i386-tdep.h (gdbarch_tdep): Add field memory_args_by_pointer.
        * amd64-tdep.c (amd64_push_arguments): Add handling of architectures
        where tdep->memory_args_by_pointer is non-zero.
        * amd64-windows-tdep.c (amd64_windows_init_abi): Set
        tdep->memory_args_by_pointer to 1.

gdb/ChangeLog
gdb/amd64-tdep.c
gdb/amd64-windows-tdep.c
gdb/i386-tdep.h

index 161a4dc0158e0cc19d3fadf9d25cf03b3028aa95..8755c3a4a703f259ff61f953597eaf0d502a1078 100644 (file)
@@ -1,3 +1,12 @@
+2010-01-29  Joel Brobecker  <brobecker@adacore.com>
+
+       amd64-windows: memory args passed by pointer during function calls.
+       * i386-tdep.h (gdbarch_tdep): Add field memory_args_by_pointer.
+       * amd64-tdep.c (amd64_push_arguments): Add handling of architectures
+       where tdep->memory_args_by_pointer is non-zero.
+       * amd64-windows-tdep.c (amd64_windows_init_abi): Set
+       tdep->memory_args_by_pointer to 1.
+
 2010-01-29  Joel Brobecker  <brobecker@adacore.com>
 
        * i386-tdep.h (enum amd64_reg_class): New, moved here from
index 466ec245ac94c698e75511edc5843f9c64d00df5..058b318277cedf650242d518b0b3f567e60f3988 100644 (file)
@@ -540,7 +540,8 @@ static CORE_ADDR
 amd64_push_arguments (struct regcache *regcache, int nargs,
                      struct value **args, CORE_ADDR sp, int struct_return)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   int *integer_regs = tdep->call_dummy_integer_regs;
   int num_integer_regs = tdep->call_dummy_num_integer_regs;
 
@@ -553,6 +554,11 @@ amd64_push_arguments (struct regcache *regcache, int nargs,
     AMD64_XMM0_REGNUM + 6, AMD64_XMM0_REGNUM + 7,
   };
   struct value **stack_args = alloca (nargs * sizeof (struct value *));
+  /* An array that mirrors the stack_args array.  For all arguments
+     that are passed by MEMORY, if that argument's address also needs
+     to be stored in a register, the ARG_ADDR_REGNO array will contain
+     that register number (or a negative value otherwise).  */
+  int *arg_addr_regno = alloca (nargs * sizeof (int));
   int num_stack_args = 0;
   int num_elements = 0;
   int element = 0;
@@ -596,7 +602,19 @@ amd64_push_arguments (struct regcache *regcache, int nargs,
        {
          /* The argument will be passed on the stack.  */
          num_elements += ((len + 7) / 8);
-         stack_args[num_stack_args++] = args[i];
+         stack_args[num_stack_args] = args[i];
+          /* If this is an AMD64_MEMORY argument whose address must also
+             be passed in one of the integer registers, reserve that
+             register and associate this value to that register so that
+             we can store the argument address as soon as we know it.  */
+          if (class[0] == AMD64_MEMORY
+              && tdep->memory_args_by_pointer
+              && integer_reg < tdep->call_dummy_num_integer_regs)
+            arg_addr_regno[num_stack_args] =
+              tdep->call_dummy_integer_regs[integer_reg++];
+          else
+            arg_addr_regno[num_stack_args] = -1;
+          num_stack_args++;
        }
       else
        {
@@ -652,8 +670,19 @@ amd64_push_arguments (struct regcache *regcache, int nargs,
       struct type *type = value_type (stack_args[i]);
       const gdb_byte *valbuf = value_contents (stack_args[i]);
       int len = TYPE_LENGTH (type);
-
-      write_memory (sp + element * 8, valbuf, len);
+      CORE_ADDR arg_addr = sp + element * 8;
+
+      write_memory (arg_addr, valbuf, len);
+      if (arg_addr_regno[i] >= 0)
+        {
+          /* We also need to store the address of that argument in
+             the given register.  */
+          gdb_byte buf[8];
+          enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+
+          store_unsigned_integer (buf, 8, byte_order, arg_addr);
+          regcache_cooked_write (regcache, arg_addr_regno[i], buf);
+        }
       element += ((len + 7) / 8);
     }
 
index b5a0035c7056f083b76a633af2453580b11eddd0..0ed93680340c169d5d65362fb122d64e57dc95cb 100644 (file)
@@ -83,6 +83,7 @@ amd64_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
     ARRAY_SIZE (amd64_windows_dummy_call_integer_regs);
   tdep->call_dummy_integer_regs = amd64_windows_dummy_call_integer_regs;
   tdep->classify = amd64_windows_classify;
+  tdep->memory_args_by_pointer = 1;
 
   set_solib_ops (gdbarch, &solib_target_so_ops);
 }
index d5b24faf729c24f834c4b36d851b9ca7685785d9..f79a15de7c58c9877322bd763f51ec33d9d5f154 100644 (file)
@@ -86,6 +86,15 @@ struct gdbarch_tdep
      the result in CLASS.  Used on amd64 only.  */
   void (*classify) (struct type *type, enum amd64_reg_class class[2]);
 
+  /* Non-zero if the first few MEMORY arguments should be passed by
+     pointer.
+
+     More precisely, MEMORY arguments are passed through the stack.
+     But certain architectures require that their address be passed
+     by register as well, if there are still some integer registers
+     available for argument passing.  */
+  int memory_args_by_pointer;
+
   /* Floating-point registers.  */
   struct regset *fpregset;
   size_t sizeof_fpregset;