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.
This commit is contained in:
Joel Brobecker 2010-01-29 05:21:55 +00:00
parent ba581dc13b
commit 80d19a0621
4 changed files with 51 additions and 3 deletions

View 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

View 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);
CORE_ADDR arg_addr = sp + element * 8;
write_memory (sp + element * 8, valbuf, len);
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);
}

View 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);
}

View 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;