aboutsummaryrefslogtreecommitdiff
path: root/gdb/amd64-tdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/amd64-tdep.c')
-rw-r--r--gdb/amd64-tdep.c37
1 files changed, 33 insertions, 4 deletions
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index 466ec24..058b318 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -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);
}