* amd64-windows: Fix funcall with by-pointer arguments
@ 2012-10-24 17:23 Joel Brobecker
2012-10-24 17:23 ` [RFA 2/2] amd64-windows: Arguments passed by pointer Joel Brobecker
` (2 more replies)
0 siblings, 3 replies; 18+ messages in thread
From: Joel Brobecker @ 2012-10-24 17:23 UTC (permalink / raw)
To: gdb-patches; +Cc: kettenis
Hello,
I realized a while ago that I completely misunderstood the amd64-windows
API regarding arguments that are passed by pointer. The calling
convention is published there:
http://msdn.microsoft.com/en-us/library/zthk2dkh(v=vs.80).aspx
Aggregates whose size is not 8/16/32/64 should be passed by pointer,
and what that means is that the caller is expected to make a copy
of the object, and pass its address as the argument. This is different
from passing the argument through the stack and the stack address
at the same time.
In particular, when you have a function call which involves one of
those by-pointer argument that follows an on-stack argument, the
incorrect method would puth the by-pointer argument on the stack
after the first argument, thus screwing up the offset of the first
argument relative to the caller's frame address, etc.
This patch series fixes the problem by:
1. Reverting the first (incorrect) attempt at handling by-pointer
arguments;
2. Add handling of by-pointer arguments again.
Tested on x86_64-windows with AdaCore's testsuite, and on x86_64-linux
using the official testsuite.
^ permalink raw reply [flat|nested] 18+ messages in thread
* [RFA 2/2] amd64-windows: Arguments passed by pointer
2012-10-24 17:23 amd64-windows: Fix funcall with by-pointer arguments Joel Brobecker
@ 2012-10-24 17:23 ` Joel Brobecker
2012-10-24 17:24 ` [RFA 1/2] Revert "amd64-windows: memory args passed by pointer during function calls." Joel Brobecker
2012-10-25 13:18 ` amd64-windows: Fix funcall with by-pointer arguments Mark Kettenis
2 siblings, 0 replies; 18+ messages in thread
From: Joel Brobecker @ 2012-10-24 17:23 UTC (permalink / raw)
To: gdb-patches; +Cc: kettenis, Joel Brobecker
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
^ permalink raw reply [flat|nested] 18+ messages in thread
* [RFA 1/2] Revert "amd64-windows: memory args passed by pointer during function calls."
2012-10-24 17:23 amd64-windows: Fix funcall with by-pointer arguments Joel Brobecker
2012-10-24 17:23 ` [RFA 2/2] amd64-windows: Arguments passed by pointer Joel Brobecker
@ 2012-10-24 17:24 ` Joel Brobecker
2012-10-25 13:18 ` amd64-windows: Fix funcall with by-pointer arguments Mark Kettenis
2 siblings, 0 replies; 18+ messages in thread
From: Joel Brobecker @ 2012-10-24 17:24 UTC (permalink / raw)
To: gdb-patches; +Cc: kettenis, Joel Brobecker
A more correct implementation of parameters passed by pointer will
follow.
gdb/ChangeLog:
Revert the following change:
* 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.
Tested on both amd64-windows and amd64-linux.
OK to commit?
Thanks,
--
Joel
---
gdb/amd64-tdep.c | 40 ++++++----------------------------------
gdb/amd64-windows-tdep.c | 1 -
gdb/i386-tdep.h | 9 ---------
3 files changed, 6 insertions(+), 44 deletions(-)
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index a4172fc..c6ee493 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -749,8 +749,7 @@ static CORE_ADDR
amd64_push_arguments (struct regcache *regcache, int nargs,
struct value **args, CORE_ADDR sp, int struct_return)
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
int *integer_regs = tdep->call_dummy_integer_regs;
int num_integer_regs = tdep->call_dummy_num_integer_regs;
@@ -763,11 +762,6 @@ 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;
@@ -811,19 +805,7 @@ 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];
- /* 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++;
+ stack_args[num_stack_args++] = args[i];
}
else
{
@@ -878,20 +860,10 @@ 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]);
- CORE_ADDR arg_addr = sp + element * 8;
-
- write_memory (arg_addr, valbuf, TYPE_LENGTH (type));
- 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 += ((TYPE_LENGTH (type) + 7) / 8);
+ int len = TYPE_LENGTH (type);
+
+ write_memory (sp + element * 8, valbuf, len);
+ element += ((len + 7) / 8);
}
/* The psABI says that "For calls that may call functions that use
diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c
index 142e141..3e8a830 100644
--- a/gdb/amd64-windows-tdep.c
+++ b/gdb/amd64-windows-tdep.c
@@ -213,7 +213,6 @@ 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;
tdep->integer_param_regs_saved_in_caller_frame = 1;
set_gdbarch_return_value (gdbarch, amd64_windows_return_value);
set_gdbarch_skip_main_prologue (gdbarch, amd64_skip_main_prologue);
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index 5f233f5..01b0936 100644
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -85,15 +85,6 @@ struct gdbarch_tdep
and store the result in CLASS. */
void (*classify) (struct type *type, enum amd64_reg_class class[2]);
- /* Used on amd64 only. 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;
-
/* Used on amd64 only.
If non-zero, then the callers of a function are expected to reserve
--
1.7.9.5
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: amd64-windows: Fix funcall with by-pointer arguments
2012-10-24 17:23 amd64-windows: Fix funcall with by-pointer arguments Joel Brobecker
2012-10-24 17:23 ` [RFA 2/2] amd64-windows: Arguments passed by pointer Joel Brobecker
2012-10-24 17:24 ` [RFA 1/2] Revert "amd64-windows: memory args passed by pointer during function calls." Joel Brobecker
@ 2012-10-25 13:18 ` Mark Kettenis
2013-01-16 11:59 ` Joel Brobecker
2 siblings, 1 reply; 18+ messages in thread
From: Mark Kettenis @ 2012-10-25 13:18 UTC (permalink / raw)
To: brobecker; +Cc: gdb-patches
> From: "Joel Brobecker" <brobecker@adacore.com>
> Date: Wed, 24 Oct 2012 13:23:35 -0400
>
> Hello,
>
> I realized a while ago that I completely misunderstood the amd64-windows
> API regarding arguments that are passed by pointer. The calling
> convention is published there:
>
> http://msdn.microsoft.com/en-us/library/zthk2dkh(v=vs.80).aspx
Reading that document, I think you're much much better off just
implementing your own versons of _return_value(), _push_dummy_call()
for Windows. The complication of "classifying" the parameters makes
very little sense on Windows, and the hookds you're adding (and that
have been added in the past) only complicate the generic ABI code.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: amd64-windows: Fix funcall with by-pointer arguments
2012-10-25 13:18 ` amd64-windows: Fix funcall with by-pointer arguments Mark Kettenis
@ 2013-01-16 11:59 ` Joel Brobecker
2013-09-13 22:11 ` [RFC-v2] " Pierre Muller
0 siblings, 1 reply; 18+ messages in thread
From: Joel Brobecker @ 2013-01-16 11:59 UTC (permalink / raw)
To: Mark Kettenis; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1797 bytes --]
> > http://msdn.microsoft.com/en-us/library/zthk2dkh(v=vs.80).aspx
>
> Reading that document, I think you're much much better off just
> implementing your own versons of _return_value(), _push_dummy_call()
> for Windows. The complication of "classifying" the parameters makes
> very little sense on Windows, and the hookds you're adding (and that
> have been added in the past) only complicate the generic ABI code.
Makes sense indeed.
Attached is a patch that adds a standalone implementation of that ABI.
If it looks good to you, I'll finish the work by deleting all the hooks
that should now be unnecessary.
Overall, the Windows ABI seems to be simpler than the sysV one,
and I suspect the new implementation will fix some bugs (without,
hopefully, introducing too many! :-)). For instance, I noticed during
testing that calling functions with long double now works properly.
For the _return_value gdbarch routine, it's already independent of
the notion of classifying (and independent of the code in amd64-tdep,
so we should be OK there).
gdb/ChangeLog:
* amd64-tdep.c: #include "value.h"
(amd64_windows_classify): Delete.
(amd64_windows_passed_by_integer_register)
(amd64_windows_passed_by_xmm_register)
(amd64_windows_passed_by_pointer)
(amd64_windows_adjust_args_passed_by_pointer)
(amd64_windows_store_arg_in_reg, amd64_windows_push_arguments)
(amd64_windows_push_dummy_call): New functions.
(amd64_windows_init_abi): Remove setting of
tdep->call_dummy_num_integer_regs, tdep->call_dummy_integer_regs,
tdep->classify, tdep->memory_args_by_pointer and
tdep->integer_param_regs_saved_in_caller_frame.
Add call to set_gdbarch_push_dummy_call.
OK to commit?
Thanks,
--
Joel
[-- Attachment #2: 0001-Reimplement-function-calls-on-amd64-windows.patch --]
[-- Type: text/x-diff, Size: 10159 bytes --]
From d07d49d9e5c7a7ee50ef0e2890ca951583ca251b Mon Sep 17 00:00:00 2001
From: Joel Brobecker <brobecker@adacore.com>
Date: Wed, 16 Jan 2013 06:39:58 -0500
Subject: [PATCH] Reimplement function calls on amd64-windows.
gdb/ChangeLog:
* amd64-tdep.c: #include "value.h"
(amd64_windows_classify): Delete.
(amd64_windows_passed_by_integer_register)
(amd64_windows_passed_by_xmm_register)
(amd64_windows_passed_by_pointer)
(amd64_windows_adjust_args_passed_by_pointer)
(amd64_windows_store_arg_in_reg, amd64_windows_push_arguments)
(amd64_windows_push_dummy_call): New functions.
(amd64_windows_init_abi): Remove setting of
tdep->call_dummy_num_integer_regs, tdep->call_dummy_integer_regs,
tdep->classify, tdep->memory_args_by_pointer and
tdep->integer_param_regs_saved_in_caller_frame.
Add call to set_gdbarch_push_dummy_call.
---
gdb/amd64-windows-tdep.c | 264 ++++++++++++++++++++++++++++++++++++++++------
1 files changed, 232 insertions(+), 32 deletions(-)
diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c
index e7addfc..823c9d1 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,41 +36,245 @@ static int amd64_windows_dummy_call_integer_regs[] =
9 /* %r9 */
};
-/* Implement the "classify" method in the gdbarch_tdep structure
- for amd64-windows. */
+/* Return nonzero if an argument of type TYPE should be passed
+ via one of the integer registers. */
-static void
-amd64_windows_classify (struct type *type, enum amd64_reg_class class[2])
+static int
+amd64_windows_passed_by_integer_register (struct type *type)
{
switch (TYPE_CODE (type))
{
- case TYPE_CODE_ARRAY:
- /* Arrays are always passed by memory. */
- class[0] = class[1] = AMD64_MEMORY;
- break;
-
+ case TYPE_CODE_INT:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_REF:
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
- /* Struct/Union types whose size is 1, 2, 4, or 8 bytes
- are passed as if they were integers of the same size.
- Types of different sizes are passed by memory. */
- if (TYPE_LENGTH (type) == 1
- || TYPE_LENGTH (type) == 2
- || TYPE_LENGTH (type) == 4
- || TYPE_LENGTH (type) == 8)
- {
- class[0] = AMD64_INTEGER;
- class[1] = AMD64_NO_CLASS;
- }
- else
- class[0] = class[1] = AMD64_MEMORY;
- break;
+ return (TYPE_LENGTH (type) == 1
+ || TYPE_LENGTH (type) == 2
+ || TYPE_LENGTH (type) == 4
+ || TYPE_LENGTH (type) == 8);
default:
- /* For all the other types, the conventions are the same as
- with the System V ABI. */
- amd64_classify (type, class);
+ return 0;
+ }
+}
+
+/* Return nonzero if an argument of type TYPE should be passed
+ via one of the XMM registers. */
+
+static int
+amd64_windows_passed_by_xmm_register (struct type *type)
+{
+ return ((TYPE_CODE (type) == TYPE_CODE_FLT
+ || TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
+ && (TYPE_LENGTH (type) == 4 || TYPE_LENGTH (type) == 8));
+}
+
+/* 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)
+{
+ if (amd64_windows_passed_by_integer_register (type))
+ return 0;
+
+ if (amd64_windows_passed_by_xmm_register (type))
+ return 0;
+
+ return 1;
+}
+
+/* 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. */
+
+static CORE_ADDR
+amd64_windows_adjust_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;
+}
+
+/* Store the value of ARG in register REGNO (right-justified).
+ REGCACHE is the register cache. */
+
+static void
+amd64_windows_store_arg_in_reg (struct regcache *regcache,
+ struct value *arg, int regno)
+{
+ struct type *type = value_type (arg);
+ const gdb_byte *valbuf = value_contents (arg);
+ gdb_byte buf[8];
+
+ gdb_assert (TYPE_LENGTH (type) <= 8);
+ memset (buf, 0, sizeof buf);
+ memcpy (buf, valbuf, min (TYPE_LENGTH (type), 8));
+ regcache_cooked_write (regcache, regno, buf);
+}
+
+/* Push the arguments for an inferior function call, and return
+ the updated value of the SP (Stack Pointer).
+
+ All arguments are identical to the arguments used in
+ amd64_windows_push_dummy_call. */
+
+static CORE_ADDR
+amd64_windows_push_arguments (struct regcache *regcache, int nargs,
+ struct value **args, CORE_ADDR sp,
+ int struct_return)
+{
+ int reg_idx = 0;
+ int i;
+ struct value **stack_args = alloca (nargs * sizeof (struct value *));
+ int num_stack_args = 0;
+ int num_elements = 0;
+ int element = 0;
+
+ /* First, handle the arguments passed by pointer.
+
+ These arguments are replaced by pointers to a copy we are making
+ in inferior memory. So use a copy of the ARGS table, to avoid
+ modifying the original one. */
+ {
+ struct value **args1 = alloca (nargs * sizeof (struct value *));
+
+ memcpy (args1, args, nargs * sizeof (struct value *));
+ sp = amd64_windows_adjust_args_passed_by_pointer (args1, nargs, sp);
+ args = args1;
+ }
+
+ /* Reserve a register for the "hidden" argument. */
+ if (struct_return)
+ reg_idx++;
+
+ for (i = 0; i < nargs; i++)
+ {
+ struct type *type = value_type (args[i]);
+ int len = TYPE_LENGTH (type);
+ int on_stack_p = 1;
+
+ if (reg_idx < ARRAY_SIZE (amd64_windows_dummy_call_integer_regs))
+ {
+ if (amd64_windows_passed_by_integer_register (type))
+ {
+ amd64_windows_store_arg_in_reg
+ (regcache, args[i],
+ amd64_windows_dummy_call_integer_regs[reg_idx]);
+ on_stack_p = 0;
+ reg_idx++;
+ }
+ else if (amd64_windows_passed_by_xmm_register (type))
+ {
+ amd64_windows_store_arg_in_reg
+ (regcache, args[i], AMD64_XMM0_REGNUM + reg_idx);
+ /* In case of varargs, these parameters must also be
+ passed via the integer registers. */
+ amd64_windows_store_arg_in_reg
+ (regcache, args[i],
+ amd64_windows_dummy_call_integer_regs[reg_idx]);
+ on_stack_p = 0;
+ reg_idx++;
+ }
+ }
+
+ if (on_stack_p)
+ {
+ num_elements += ((len + 7) / 8);
+ stack_args[num_stack_args++] = args[i];
+ }
+ }
+
+ /* Allocate space for the arguments on the stack, keeping it
+ aligned on a 16 byte boundary. */
+ sp -= num_elements * 8;
+ sp &= ~0xf;
+
+ /* Write out the arguments to the stack. */
+ for (i = 0; i < num_stack_args; i++)
+ {
+ struct type *type = value_type (stack_args[i]);
+ const gdb_byte *valbuf = value_contents (stack_args[i]);
+
+ write_memory (sp + element * 8, valbuf, TYPE_LENGTH (type));
+ element += ((TYPE_LENGTH (type) + 7) / 8);
+ }
+
+ return sp;
+}
+
+/* Implement the "push_dummy_call" gdbarch method. */
+
+static CORE_ADDR
+amd64_windows_push_dummy_call
+ (struct gdbarch *gdbarch, struct value *function,
+ struct regcache *regcache, CORE_ADDR bp_addr,
+ int nargs, struct value **args,
+ CORE_ADDR sp, int struct_return, CORE_ADDR struct_addr)
+{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ gdb_byte buf[8];
+
+ /* Pass arguments. */
+ sp = amd64_windows_push_arguments (regcache, nargs, args, sp,
+ struct_return);
+
+ /* Pass "hidden" argument". */
+ if (struct_return)
+ {
+ /* The "hidden" argument is passed throught the first argument
+ register. */
+ const int arg_regnum = amd64_windows_dummy_call_integer_regs[0];
+
+ store_unsigned_integer (buf, 8, byte_order, struct_addr);
+ regcache_cooked_write (regcache, arg_regnum, buf);
}
+
+ /* Reserve some memory on the stack for the integer-parameter
+ registers, as required by the ABI. */
+ sp -= ARRAY_SIZE (amd64_windows_dummy_call_integer_regs) * 8;
+
+ /* Store return address. */
+ sp -= 8;
+ store_unsigned_integer (buf, 8, byte_order, bp_addr);
+ write_memory (sp, buf, 8);
+
+ /* Update the stack pointer... */
+ store_unsigned_integer (buf, 8, byte_order, sp);
+ regcache_cooked_write (regcache, AMD64_RSP_REGNUM, buf);
+
+ /* ...and fake a frame pointer. */
+ regcache_cooked_write (regcache, AMD64_RBP_REGNUM, buf);
+
+ return sp + 16;
}
/* Implement the "return_value" gdbarch method for amd64-windows. */
@@ -209,12 +414,7 @@ amd64_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_long_bit (gdbarch, 32);
/* Function calls. */
- 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->classify = amd64_windows_classify;
- tdep->memory_args_by_pointer = 1;
- tdep->integer_param_regs_saved_in_caller_frame = 1;
+ set_gdbarch_push_dummy_call (gdbarch, amd64_windows_push_dummy_call);
set_gdbarch_return_value (gdbarch, amd64_windows_return_value);
set_gdbarch_skip_main_prologue (gdbarch, amd64_skip_main_prologue);
set_gdbarch_skip_trampoline_code (gdbarch,
--
1.7.9
^ permalink raw reply [flat|nested] 18+ messages in thread
* [RFC-v2] amd64-windows: Fix funcall with by-pointer arguments
2013-01-16 11:59 ` Joel Brobecker
@ 2013-09-13 22:11 ` Pierre Muller
2013-09-16 20:57 ` Joel Brobecker
0 siblings, 1 reply; 18+ messages in thread
From: Pierre Muller @ 2013-09-13 22:11 UTC (permalink / raw)
To: 'Joel Brobecker', 'Mark Kettenis'; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 15441 bytes --]
As explained in the other thread,
I merged Joel's patch in this thread with my patch
in http://www.sourceware.org/ml/gdb-patches/2013-09/msg00145.html
I attached the difference between two runs of:
make check RUNTESTFKLAGS="gdb.base/*.exp"
with current CVS GDB and with the patch below applied
(plus a few other submitted patches concerning
testsuite runs for *-*-ming* builds).
The number of failure in gdb.base
drops from 326 to 243 FAILs.
Comments most welcome,
Pierre Muller
2013-09-12 Joel Brobecker <brobecker@adacore.com>
Pierre Muller <muller@sourceware.org>
* amd64-windows-tdep.c: #include "value.h" and "inferior.h".
(amd64_windows_classify): Delete.
(amd64_windows_passed_by_xmm_register)
(amd64_windows_return_in_xmm0_register)
(amd64_windows_passed_by_integer_register)
(amd64_windows_passed_by_pointer)
(amd64_windows_adjust_args_passed_by_pointer)
(amd64_windows_store_arg_in_reg, amd64_windows_push_arguments)
(amd64_windows_push_dummy_call): New functions.
(amd64_return_value): Use new functions above. Add "debug infrum"
information.
(amd64_windows_init_abi): Remove setting of
tdep->call_dummy_num_integer_regs, tdep->call_dummy_integer_regs,
tdep->classify, tdep->memory_args_by_pointer and
tdep->integer_param_regs_saved_in_caller_frame.
Add call to set_gdbarch_push_dummy_call.
Index: src/gdb/amd64-windows-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/amd64-windows-tdep.c,v
retrieving revision 1.17
diff -u -p -r1.17 amd64-windows-tdep.c
--- src/gdb/amd64-windows-tdep.c 2 Sep 2013 09:28:02 -0000 1.17
+++ src/gdb/amd64-windows-tdep.c 13 Sep 2013 21:46:09 -0000
@@ -31,53 +31,342 @@
#include "coff/i386.h"
#include "coff/pe.h"
#include "libcoff.h"
+#include "value.h"
+#include "inferior.h"
/* The registers used to pass integer arguments during a function call. */
static int amd64_windows_dummy_call_integer_regs[] =
{
AMD64_RCX_REGNUM, /* %rcx */
AMD64_RDX_REGNUM, /* %rdx */
- 8, /* %r8 */
- 9 /* %r9 */
+ AMD64_R8_REGNUM, /* %r8 */
+ AMD64_R9_REGNUM /* %r9 */
};
-/* Implement the "classify" method in the gdbarch_tdep structure
- for amd64-windows. */
+/* Return nonzero if an argument of type TYPE should be passed
+ via one of the XMM registers. */
-static void
-amd64_windows_classify (struct type *type, enum amd64_reg_class class[2])
+static int
+amd64_windows_passed_by_xmm_register (struct type *type)
{
switch (TYPE_CODE (type))
{
- case TYPE_CODE_ARRAY:
- /* Arrays are always passed by memory. */
- class[0] = class[1] = AMD64_MEMORY;
- break;
+ case TYPE_CODE_TYPEDEF:
+ if (TYPE_TARGET_TYPE (type))
+ return amd64_windows_passed_by_xmm_register (
+ TYPE_TARGET_TYPE (type));
+ else
+ return 0;
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ if (TYPE_NFIELDS (type) == 1)
+ return amd64_windows_passed_by_xmm_register (
+ TYPE_FIELD_TYPE (type, 0));
+ else
+ return 0;
+ case TYPE_CODE_FLT:
+ case TYPE_CODE_DECFLOAT:
+ return (TYPE_LENGTH (type) == 4 || TYPE_LENGTH (type) == 8);
+ default:
+ return 0;
+ }
+}
+
+/* Return nonzero if an return value of type TYPE should be passed
+ in XMM0 register. */
+
+static int
+amd64_windows_return_in_xmm0_register (struct type *type)
+{
+ if (amd64_windows_passed_by_xmm_register (type))
+ return 1;
+ else
+ {
+ /* __m128, __m128d and __m128i types are returned in $xmm0 also.
+ But they are not stored in XMM registers as arguments,
+ at least not in GCC 4.7.6 x86_64-w64-mingw32 target.
+ Note: The TYPE_VECTOR check should prevent other arrays from
+ being treated as special xmm types.
+ Note: This all works for the "unique" __fastcall calling
convention
+ as defined by Microsoft. The newer __vectorcall convention
+ does support passing __m128X type parameters in xmm registers
+ using /Gv option of Microsoft compilers. */
+ struct type *ltype = check_typedef (type);
+ if (ltype && TYPE_CODE (ltype) == TYPE_CODE_ARRAY
+ && (TYPE_CODE (TYPE_TARGET_TYPE (ltype)) == TYPE_CODE_FLT
+ || TYPE_CODE (TYPE_TARGET_TYPE (ltype)) == TYPE_CODE_INT)
+ && TYPE_VECTOR (ltype) && TYPE_LENGTH (ltype) == 16)
+ return 1;
+ else
+ return 0;
+ }
+}
+
+/* Return nonzero if an argument of type TYPE should be passed
+ via one of the integer registers. */
+static int
+amd64_windows_passed_by_integer_register (struct type *type)
+{
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_TYPEDEF:
+ if (TYPE_TARGET_TYPE (type))
+ return amd64_windows_passed_by_integer_register (
+ TYPE_TARGET_TYPE (type));
+ else
+ return 0;
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
- /* Struct/Union types whose size is 1, 2, 4, or 8 bytes
- are passed as if they were integers of the same size.
- Types of different sizes are passed by memory. */
- if (TYPE_LENGTH (type) == 1
- || TYPE_LENGTH (type) == 2
- || TYPE_LENGTH (type) == 4
- || TYPE_LENGTH (type) == 8)
+ if (TYPE_NFIELDS (type) == 1)
{
- class[0] = AMD64_INTEGER;
- class[1] = AMD64_NO_CLASS;
+ /* If only one field, exclude float type accepted as xmm reg.
*/
+ if (amd64_windows_passed_by_xmm_register (
+ TYPE_FIELD_TYPE (type, 0)))
+ return 0;
+ else
+ return amd64_windows_passed_by_integer_register (
+ TYPE_FIELD_TYPE (type, 0));
}
- else
- class[0] = class[1] = AMD64_MEMORY;
- break;
+ /* Struct/Union with several fields: Pass Through. */
+ case TYPE_CODE_INT:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_REF:
+ case TYPE_CODE_COMPLEX:
+ return (TYPE_LENGTH (type) == 1
+ || TYPE_LENGTH (type) == 2
+ || TYPE_LENGTH (type) == 4
+ || TYPE_LENGTH (type) == 8);
default:
- /* For all the other types, the conventions are the same as
- with the System V ABI. */
- amd64_classify (type, class);
+ return 0;
}
}
+/* 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)
+{
+ if (amd64_windows_passed_by_integer_register (type))
+ return 0;
+
+ if (amd64_windows_passed_by_xmm_register (type))
+ return 0;
+
+ return 1;
+}
+
+/* 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. */
+
+static CORE_ADDR
+amd64_windows_adjust_args_passed_by_pointer (struct gdbarch *gdbarch,
+ 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));
+ if (debug_infrun)
+ printf_filtered (_("Parameter #%d, length %d copied on stack "
+ "at address %s, and passed as pointer\n"),
+ i, len, paddress (gdbarch, sp));
+ }
+
+ return sp;
+}
+
+/* Store the value of ARG in register REGNO (right-justified).
+ REGCACHE is the register cache. */
+
+static void
+amd64_windows_store_arg_in_reg (struct gdbarch *gdbarch,
+ struct regcache *regcache,
+ struct value *arg, int regno, int i)
+{
+ struct type *type = value_type (arg);
+ const gdb_byte *valbuf = value_contents (arg);
+ gdb_byte buf[8];
+
+ gdb_assert (TYPE_LENGTH (type) <= 8);
+ memset (buf, 0, sizeof buf);
+ memcpy (buf, valbuf, min (TYPE_LENGTH (type), 8));
+ regcache_cooked_write (regcache, regno, buf);
+ if (debug_infrun)
+ printf_filtered (_("Parameter #%d, length %d copied to register %s\n"),
+ i, TYPE_LENGTH (type), i386_pseudo_register_name(
+ gdbarch, regno));
+}
+
+/* Push the arguments for an inferior function call, and return
+ the updated value of the SP (Stack Pointer).
+
+ All arguments are identical to the arguments used in
+ amd64_windows_push_dummy_call. */
+
+static CORE_ADDR
+amd64_windows_push_arguments (struct gdbarch *gdbarch,
+ struct regcache *regcache, int nargs,
+ struct value **args, CORE_ADDR sp,
+ int struct_return)
+{
+ int reg_idx = 0;
+ int i;
+ struct value **stack_args = alloca (nargs * sizeof (struct value *));
+ int num_stack_args = 0;
+ int num_elements = 0;
+ int element = 0;
+
+ /* First, handle the arguments passed by pointer.
+
+ These arguments are replaced by pointers to a copy we are making
+ in inferior memory. So use a copy of the ARGS table, to avoid
+ modifying the original one. */
+ {
+ struct value **args1 = alloca (nargs * sizeof (struct value *));
+
+ memcpy (args1, args, nargs * sizeof (struct value *));
+ sp = amd64_windows_adjust_args_passed_by_pointer (gdbarch, args1,
+ nargs, sp);
+ args = args1;
+ }
+
+ /* Reserve a register for the "hidden" argument. */
+ if (struct_return)
+ reg_idx++;
+
+ for (i = 0; i < nargs; i++)
+ {
+ struct type *type = value_type (args[i]);
+ int len = TYPE_LENGTH (type);
+ int on_stack_p = 1;
+
+ if (reg_idx < ARRAY_SIZE (amd64_windows_dummy_call_integer_regs))
+ {
+ if (amd64_windows_passed_by_integer_register (type))
+ {
+ amd64_windows_store_arg_in_reg
+ (gdbarch, regcache, args[i],
+ amd64_windows_dummy_call_integer_regs[reg_idx], i);
+ on_stack_p = 0;
+ reg_idx++;
+ }
+ else if (amd64_windows_passed_by_xmm_register (type))
+ {
+ amd64_windows_store_arg_in_reg
+ (gdbarch, regcache, args[i], AMD64_XMM0_REGNUM + reg_idx,
i);
+ /* In case of varargs, these parameters must also be
+ passed via the integer registers. */
+ amd64_windows_store_arg_in_reg
+ (gdbarch, regcache, args[i],
+ amd64_windows_dummy_call_integer_regs[reg_idx], i);
+ on_stack_p = 0;
+ reg_idx++;
+ }
+ }
+
+ if (on_stack_p)
+ {
+ num_elements += ((len + 7) / 8);
+ stack_args[num_stack_args++] = args[i];
+ }
+ }
+
+ /* Allocate space for the arguments on the stack, keeping it
+ aligned on a 16 byte boundary. */
+ sp -= num_elements * 8;
+ sp &= ~0xf;
+
+ /* Write out the arguments to the stack. */
+ for (i = 0; i < num_stack_args; i++)
+ {
+ struct type *type = value_type (stack_args[i]);
+ const gdb_byte *valbuf = value_contents (stack_args[i]);
+
+ write_memory (sp + element * 8, valbuf, TYPE_LENGTH (type));
+ if (debug_infrun)
+ printf_filtered (_("Parameter #%d, length %d copied on stack"
+ " at address %s\n"),
+ i, TYPE_LENGTH (type),
+ paddress (gdbarch, sp + element * 8));
+ element += ((TYPE_LENGTH (type) + 7) / 8);
+ }
+
+ return sp;
+}
+
+/* Implement the "push_dummy_call" gdbarch method. */
+
+static CORE_ADDR
+amd64_windows_push_dummy_call
+ (struct gdbarch *gdbarch, struct value *function,
+ struct regcache *regcache, CORE_ADDR bp_addr,
+ int nargs, struct value **args,
+ CORE_ADDR sp, int struct_return, CORE_ADDR struct_addr)
+{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ gdb_byte buf[8];
+
+ /* Pass arguments. */
+ sp = amd64_windows_push_arguments (gdbarch, regcache, nargs, args, sp,
+ struct_return);
+
+ /* Pass "hidden" argument". */
+ if (struct_return)
+ {
+ /* The "hidden" argument is passed throught the first argument
+ register. */
+ const int arg_regnum = amd64_windows_dummy_call_integer_regs[0];
+
+ store_unsigned_integer (buf, 8, byte_order, struct_addr);
+ regcache_cooked_write (regcache, arg_regnum, buf);
+ }
+
+ /* Reserve some memory on the stack for the integer-parameter
+ registers, as required by the ABI. */
+ sp -= ARRAY_SIZE (amd64_windows_dummy_call_integer_regs) * 8;
+
+ /* Store return address. */
+ sp -= 8;
+ store_unsigned_integer (buf, 8, byte_order, bp_addr);
+ write_memory (sp, buf, 8);
+
+ /* Update the stack pointer... */
+ store_unsigned_integer (buf, 8, byte_order, sp);
+ regcache_cooked_write (regcache, AMD64_RSP_REGNUM, buf);
+
+ /* ...and fake a frame pointer. */
+ regcache_cooked_write (regcache, AMD64_RBP_REGNUM, buf);
+
+ return sp + 16;
+}
+
/* Implement the "return_value" gdbarch method for amd64-windows. */
static enum return_value_convention
@@ -90,22 +379,10 @@ amd64_windows_return_value (struct gdbar
/* See if our value is returned through a register. If it is, then
store the associated register number in REGNUM. */
- switch (TYPE_CODE (type))
- {
- case TYPE_CODE_FLT:
- case TYPE_CODE_DECFLOAT:
- /* __m128, __m128i, __m128d, floats, and doubles are returned
- via XMM0. */
- if (len == 4 || len == 8 || len == 16)
- regnum = AMD64_XMM0_REGNUM;
- break;
- default:
- /* All other values that are 1, 2, 4 or 8 bytes long are returned
- via RAX. */
- if (len == 1 || len == 2 || len == 4 || len == 8)
- regnum = AMD64_RAX_REGNUM;
- break;
- }
+ if (amd64_windows_return_in_xmm0_register (type))
+ regnum = AMD64_XMM0_REGNUM;
+ else if (amd64_windows_passed_by_integer_register (type))
+ regnum = AMD64_RAX_REGNUM;
if (regnum < 0)
{
@@ -117,8 +394,10 @@ amd64_windows_return_value (struct gdbar
regcache_raw_read_unsigned (regcache, AMD64_RAX_REGNUM, &addr);
read_memory (addr, readbuf, TYPE_LENGTH (type));
}
+ if (debug_infrun)
+ printf_filtered (_("Return value as memory address in RAX\n"));
return RETURN_VALUE_ABI_RETURNS_ADDRESS;
- }
+ }
else
{
/* Extract the return value from the register where it was stored.
*/
@@ -126,6 +405,9 @@ amd64_windows_return_value (struct gdbar
regcache_raw_read_part (regcache, regnum, 0, len, readbuf);
if (writebuf)
regcache_raw_write_part (regcache, regnum, 0, len, writebuf);
+ if (debug_infrun)
+ printf_filtered (_("Return value in register %s\n"),
+ gdbarch_register_name (gdbarch, regnum));
return RETURN_VALUE_REGISTER_CONVENTION;
}
}
@@ -976,12 +1258,7 @@ amd64_windows_init_abi (struct gdbarch_i
set_gdbarch_long_bit (gdbarch, 32);
/* Function calls. */
- 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->classify = amd64_windows_classify;
- tdep->memory_args_by_pointer = 1;
- tdep->integer_param_regs_saved_in_caller_frame = 1;
+ set_gdbarch_push_dummy_call (gdbarch, amd64_windows_push_dummy_call);
set_gdbarch_return_value (gdbarch, amd64_windows_return_value);
set_gdbarch_skip_main_prologue (gdbarch, amd64_skip_main_prologue);
set_gdbarch_skip_trampoline_code (gdbarch,
[-- Attachment #2: diffs --]
[-- Type: application/octet-stream, Size: 50161 bytes --]
1c1
< Test Run By Pierre on Thu Sep 12 16:01:29 2013
---
> Test Run By Pierre on Fri Sep 13 11:39:27 2013
649,651c649,651
< FAIL: gdb.base/call-ar-st.exp: print sum_array_print(10, *list1, *list2, *list3, *list4)
< FAIL: gdb.base/call-ar-st.exp: next to 1237
< FAIL: gdb.base/call-ar-st.exp: print print_array_rep(*list1, *list2, *list3)
---
> PASS: gdb.base/call-ar-st.exp: print sum_array_print(10, *list1, *list2, *list3, *list4)
> PASS: gdb.base/call-ar-st.exp: next to 1237
> PASS: gdb.base/call-ar-st.exp: print print_array_rep(*list1, *list2, *list3)
653c653
< FAIL: gdb.base/call-ar-st.exp: continue to 1241 (the program exited)
---
> PASS: gdb.base/call-ar-st.exp: continue to 1241
656c656
< FAIL: gdb.base/call-ar-st.exp: check args of sum_array_print (the program is no longer running)
---
> PASS: gdb.base/call-ar-st.exp: check args of sum_array_print
658,661c658,661
< FAIL: gdb.base/call-ar-st.exp: continue to 1281 (the program is no longer running)
< FAIL: gdb.base/call-ar-st.exp: print print_small_structs (pattern 1)
< FAIL: gdb.base/call-ar-st.exp: print compute_with_small_structs(20)
< FAIL: gdb.base/call-ar-st.exp: print print_ten_doubles (pattern 1)
---
> PASS: gdb.base/call-ar-st.exp: continue to 1281
> PASS: gdb.base/call-ar-st.exp: print print_small_structs
> PASS: gdb.base/call-ar-st.exp: print compute_with_small_structs(20)
> PASS: gdb.base/call-ar-st.exp: print print_ten_doubles
663c663
< FAIL: gdb.base/call-ar-st.exp: continue to 1286 (the program is no longer running)
---
> PASS: gdb.base/call-ar-st.exp: continue to 1286
665,666c665,666
< FAIL: gdb.base/call-ar-st.exp: step into print_long_arg_list (the program is no longer running)
< FAIL: gdb.base/call-ar-st.exp: print print_small_structs from print_long_arg_list (pattern 1)
---
> PASS: gdb.base/call-ar-st.exp: step into print_long_arg_list
> PASS: gdb.base/call-ar-st.exp: print print_small_structs from print_long_arg_list
668,670c668,670
< FAIL: gdb.base/call-ar-st.exp: continue to 1300 (the program is no longer running)
< FAIL: gdb.base/call-ar-st.exp: step into init_bit_flags_combo (the program is no longer running)
< FAIL: gdb.base/call-ar-st.exp: print print_bit_flags_combo from init_bit_flags_combo
---
> PASS: gdb.base/call-ar-st.exp: continue to 1300
> PASS: gdb.base/call-ar-st.exp: step into init_bit_flags_combo
> PASS: gdb.base/call-ar-st.exp: print print_bit_flags_combo from init_bit_flags_combo
672,673c672,673
< FAIL: gdb.base/call-ar-st.exp: continue to 1305 (the program is no longer running)
< FAIL: gdb.base/call-ar-st.exp: print print_long_arg_list (pattern 1)
---
> PASS: gdb.base/call-ar-st.exp: continue to 1305
> PASS: gdb.base/call-ar-st.exp: print print_long_arg_list
675,678c675,678
< FAIL: gdb.base/call-ar-st.exp: continue to 1311 (the program is no longer running)
< FAIL: gdb.base/call-ar-st.exp: print sum_struct_print(10, *struct1, *struct2, *struct3, *struct4)
< FAIL: gdb.base/call-ar-st.exp: print print_struct_rep(*struct1, *struct2, *struct3) (pattern 1)
< FAIL: gdb.base/call-ar-st.exp: print print_one_large_struct(*list1)
---
> PASS: gdb.base/call-ar-st.exp: continue to 1311
> PASS: gdb.base/call-ar-st.exp: print sum_struct_print(10, *struct1, *struct2, *struct3, *struct4)
> PASS: gdb.base/call-ar-st.exp: print print_struct_rep(*struct1, *struct2, *struct3)
> PASS: gdb.base/call-ar-st.exp: print print_one_large_struct(*list1)
688c688
< FAIL: gdb.base/call-rt-st.exp: print print_one_double(*d1)
---
> PASS: gdb.base/call-rt-st.exp: print print_one_double(*d1)
773,800c773,786
< ERROR: Process no longer exists
< UNRESOLVED: gdb.base/call-sc.exp: ptype; call-sc-tll
< ERROR: Couldn't send p/c fun() to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: p/c fun(); call call-sc-tll
< ERROR: Couldn't send call Fun(foo) to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: call Fun(foo); call call-sc-tll
< ERROR: Couldn't send p/c L to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: p/c L; call call-sc-tll
< ERROR: Couldn't send advance fun to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: advance to fun for return; return call-sc-tll
< ERROR: Couldn't send p/c L to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: zed L for return; return call-sc-tll
< ERROR: Couldn't send return foo to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: return foo; return call-sc-tll
< ERROR: Couldn't send backtrace 1 to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: return foo; synchronize pc to main()
< ERROR: Couldn't send backtrace 1 to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: return foo; synchronize pc to main()
< ERROR: Couldn't send p/c L to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: value foo returned; return call-sc-tll
< ERROR: Couldn't send advance fun to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: advance to fun for finish; return call-sc-tll
< ERROR: Couldn't send p/c L to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: zed L for finish; return call-sc-tll
< ERROR: Couldn't send finish to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: finish foo; return call-sc-tll
< ERROR: Couldn't send p/c to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: value foo finished; return call-sc-tll
---
> PASS: gdb.base/call-sc.exp: ptype; call-sc-tll (long long int)
> PASS: gdb.base/call-sc.exp: ptype foo; call-sc-tll long long int
> PASS: gdb.base/call-sc.exp: p/c fun(); call call-sc-tll
> PASS: gdb.base/call-sc.exp: call Fun(foo); call call-sc-tll
> PASS: gdb.base/call-sc.exp: p/c L; call call-sc-tll
> PASS: gdb.base/call-sc.exp: advance to fun for return; return call-sc-tll
> PASS: gdb.base/call-sc.exp: zed L for return; return call-sc-tll
> PASS: gdb.base/call-sc.exp: return foo; return call-sc-tll
> PASS: gdb.base/call-sc.exp: return foo; synchronize pc to main()
> PASS: gdb.base/call-sc.exp: value foo returned; return call-sc-tll
> PASS: gdb.base/call-sc.exp: advance to fun for finish; return call-sc-tll
> PASS: gdb.base/call-sc.exp: zed L for finish; return call-sc-tll
> PASS: gdb.base/call-sc.exp: finish foo; return call-sc-tll
> PASS: gdb.base/call-sc.exp: value foo finished; return call-sc-tll
806,833c792,804
< ERROR: Process no longer exists
< UNRESOLVED: gdb.base/call-sc.exp: ptype foo; call-sc-tf float
< ERROR: Couldn't send p/c fun() to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: p/c fun(); call call-sc-tf
< ERROR: Couldn't send call Fun(foo) to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: call Fun(foo); call call-sc-tf
< ERROR: Couldn't send p/c L to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: p/c L; call call-sc-tf
< ERROR: Couldn't send advance fun to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: advance to fun for return; return call-sc-tf
< ERROR: Couldn't send p/c L to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: zed L for return; return call-sc-tf
< ERROR: Couldn't send return foo to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: return foo; return call-sc-tf
< ERROR: Couldn't send backtrace 1 to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: return foo; synchronize pc to main()
< ERROR: Couldn't send backtrace 1 to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: return foo; synchronize pc to main()
< ERROR: Couldn't send p/c L to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: value foo returned; return call-sc-tf
< ERROR: Couldn't send advance fun to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: advance to fun for finish; return call-sc-tf
< ERROR: Couldn't send p/c L to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: zed L for finish; return call-sc-tf
< ERROR: Couldn't send finish to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: finish foo; return call-sc-tf
< ERROR: Couldn't send p/c to GDB.
< UNRESOLVED: gdb.base/call-sc.exp: value foo finished; return call-sc-tf
---
> PASS: gdb.base/call-sc.exp: ptype foo; call-sc-tf float
> PASS: gdb.base/call-sc.exp: p/c fun(); call call-sc-tf
> PASS: gdb.base/call-sc.exp: call Fun(foo); call call-sc-tf
> PASS: gdb.base/call-sc.exp: p/c L; call call-sc-tf
> PASS: gdb.base/call-sc.exp: advance to fun for return; return call-sc-tf
> PASS: gdb.base/call-sc.exp: zed L for return; return call-sc-tf
> PASS: gdb.base/call-sc.exp: return foo; return call-sc-tf
> PASS: gdb.base/call-sc.exp: return foo; synchronize pc to main()
> PASS: gdb.base/call-sc.exp: value foo returned; return call-sc-tf
> PASS: gdb.base/call-sc.exp: advance to fun for finish; return call-sc-tf
> PASS: gdb.base/call-sc.exp: zed L for finish; return call-sc-tf
> PASS: gdb.base/call-sc.exp: finish foo; return call-sc-tf
> PASS: gdb.base/call-sc.exp: value foo finished; return call-sc-tf
845,846c816,823
< ERROR: Process no longer exists
< UNRESOLVED: gdb.base/call-sc.exp: return foo; return call-sc-td
---
> PASS: gdb.base/call-sc.exp: return foo; return call-sc-td
> PASS: gdb.base/call-sc.exp: return foo; synchronize pc to main()
> PASS: gdb.base/call-sc.exp: value foo returned; return call-sc-td
> PASS: gdb.base/call-sc.exp: advance to fun for finish; return call-sc-td
> PASS: gdb.base/call-sc.exp: zed L for finish; return call-sc-td
> PASS: gdb.base/call-sc.exp: finish foo; return call-sc-td
> PASS: gdb.base/call-sc.exp: value foo finished; return call-sc-td
> PASS: gdb.base/call-sc.exp: return and finish use same convention; return call-sc-td
852,859c829,835
< FAIL: gdb.base/call-sc.exp: p/c fun(); call call-sc-tld
< FAIL: gdb.base/call-sc.exp: call Fun(foo); call call-sc-tld
< FAIL: gdb.base/call-sc.exp: p/c L; call call-sc-tld
< FAIL: gdb.base/call-sc.exp: advance to fun for return; return call-sc-tld
< FAIL: gdb.base/call-sc.exp: zed L for return; return call-sc-tld
< FAIL: gdb.base/call-sc.exp: return foo; return call-sc-tld (got interactive prompt)
< FAIL: gdb.base/call-sc.exp: return foo; synchronize pc to main()
< FAIL: gdb.base/call-sc.exp: return foo; synchronize pc to main()
---
> PASS: gdb.base/call-sc.exp: p/c fun(); call call-sc-tld
> PASS: gdb.base/call-sc.exp: call Fun(foo); call call-sc-tld
> PASS: gdb.base/call-sc.exp: p/c L; call call-sc-tld
> PASS: gdb.base/call-sc.exp: advance to fun for return; return call-sc-tld
> PASS: gdb.base/call-sc.exp: zed L for return; return call-sc-tld
> PASS: gdb.base/call-sc.exp: return foo; return call-sc-tld
> PASS: gdb.base/call-sc.exp: return foo; synchronize pc to main()
861,865c837,841
< FAIL: gdb.base/call-sc.exp: advance to fun for finish; return call-sc-tld (the program exited)
< FAIL: gdb.base/call-sc.exp: zed L for finish; return call-sc-tld
< FAIL: gdb.base/call-sc.exp: finish foo; return call-sc-tld (the program is no longer running)
< FAIL: gdb.base/call-sc.exp: value foo finished; return call-sc-tld
< PASS: gdb.base/call-sc.exp: return and finish use same convention; return call-sc-tld
---
> PASS: gdb.base/call-sc.exp: advance to fun for finish; return call-sc-tld
> PASS: gdb.base/call-sc.exp: zed L for finish; return call-sc-tld
> PASS: gdb.base/call-sc.exp: finish foo; return call-sc-tld
> PASS: gdb.base/call-sc.exp: value foo finished; return call-sc-tld
> KFAIL: gdb.base/call-sc.exp: return and finish use same convention; return call-sc-tld (PRMS: gdb/1444)
885c861
< gdb compile failed, /tmp/ccIKF566.o: In function `gen_signal':
---
> gdb compile failed, /tmp/ccty9rh1.o: In function `gen_signal':
946c922
< FAIL: gdb.base/callfuncs.exp: Call function with many float arguments.
---
> PASS: gdb.base/callfuncs.exp: Call function with many float arguments.
953c929
< FAIL: gdb.base/callfuncs.exp: Call function with many double arguments.
---
> PASS: gdb.base/callfuncs.exp: Call function with many double arguments.
955c931
< FAIL: gdb.base/callfuncs.exp: p t_double_int(99.0, 99)
---
> PASS: gdb.base/callfuncs.exp: p t_double_int(99.0, 99)
957,958c933,934
< FAIL: gdb.base/callfuncs.exp: p t_int_double(99, 99.0)
< FAIL: gdb.base/callfuncs.exp: p t_float_complex_values(fc1, fc2)
---
> PASS: gdb.base/callfuncs.exp: p t_int_double(99, 99.0)
> PASS: gdb.base/callfuncs.exp: p t_float_complex_values(fc1, fc2)
960c936
< FAIL: gdb.base/callfuncs.exp: p t_float_complex_many_args(fc1, fc2, fc3, fc4, fc1, fc2, fc3, fc4, fc1, fc2, fc3, fc4, fc1, fc2, fc3, fc4)
---
> PASS: gdb.base/callfuncs.exp: p t_float_complex_many_args(fc1, fc2, fc3, fc4, fc1, fc2, fc3, fc4, fc1, fc2, fc3, fc4, fc1, fc2, fc3, fc4)
962c938
< FAIL: gdb.base/callfuncs.exp: p t_double_complex_values(dc1, dc2)
---
> PASS: gdb.base/callfuncs.exp: p t_double_complex_values(dc1, dc2)
964,966c940,942
< FAIL: gdb.base/callfuncs.exp: p t_double_complex_many_args(dc1, dc2, dc3, dc4, dc1, dc2, dc3, dc4, dc1, dc2, dc3, dc4, dc1, dc2, dc3, dc4)
< FAIL: gdb.base/callfuncs.exp: p t_double_complex_many_args(dc1, dc1, dc1, dc1, dc1, dc1, dc1, dc1, dc1, dc1, dc1, dc1, dc1, dc1, dc1, dc1)
< FAIL: gdb.base/callfuncs.exp: p t_long_double_complex_values(ldc1, ldc2)
---
> PASS: gdb.base/callfuncs.exp: p t_double_complex_many_args(dc1, dc2, dc3, dc4, dc1, dc2, dc3, dc4, dc1, dc2, dc3, dc4, dc1, dc2, dc3, dc4)
> PASS: gdb.base/callfuncs.exp: p t_double_complex_many_args(dc1, dc1, dc1, dc1, dc1, dc1, dc1, dc1, dc1, dc1, dc1, dc1, dc1, dc1, dc1, dc1)
> PASS: gdb.base/callfuncs.exp: p t_long_double_complex_values(ldc1, ldc2)
968,969c944,945
< FAIL: gdb.base/callfuncs.exp: p t_long_double_complex_many_args(ldc1, ldc2, ldc3, ldc4, ldc1, ldc2, ldc3, ldc4, ldc1, ldc2, ldc3, ldc4, ldc1, ldc2, ldc3, ldc4)
< FAIL: gdb.base/callfuncs.exp: p t_long_double_complex_many_args(ldc1, ldc1, ldc1, ldc1, ldc1, ldc1, ldc1,ldc1, ldc1, ldc1, ldc1, ldc1, ldc1, ldc1, ldc1, ldc1)
---
> PASS: gdb.base/callfuncs.exp: p t_long_double_complex_many_args(ldc1, ldc2, ldc3, ldc4, ldc1, ldc2, ldc3, ldc4, ldc1, ldc2, ldc3, ldc4, ldc1, ldc2, ldc3, ldc4)
> PASS: gdb.base/callfuncs.exp: p t_long_double_complex_many_args(ldc1, ldc1, ldc1, ldc1, ldc1, ldc1, ldc1,ldc1, ldc1, ldc1, ldc1, ldc1, ldc1, ldc1, ldc1, ldc1)
1072c1048
< gdb compile failed, /tmp/cc7RDncB.o: In function `main':
---
> gdb compile failed, /tmp/cc2GFfXn.o: In function `main':
2388c2364
< FAIL: gdb.base/dfp-test.exp: Backtrace function with correct _Decimal32 arguments.
---
> PASS: gdb.base/dfp-test.exp: Backtrace function with correct _Decimal32 arguments.
2391c2367
< FAIL: gdb.base/dfp-test.exp: Backtrace function with correct _Decimal64 arguments.
---
> PASS: gdb.base/dfp-test.exp: Backtrace function with correct _Decimal64 arguments.
2394c2370
< FAIL: gdb.base/dfp-test.exp: Backtrace function with correct _Decimal128 arguments.
---
> PASS: gdb.base/dfp-test.exp: Backtrace function with correct _Decimal128 arguments.
2396,2408c2372,2384
< FAIL: gdb.base/dfp-test.exp: Call function with mixed decimal float arguments TEST.
< FAIL: gdb.base/dfp-test.exp: Call function with mixed decimal float arguments.
< FAIL: gdb.base/dfp-test.exp: Call function with many _Decimal32 arguments.
< FAIL: gdb.base/dfp-test.exp: Call function with many _Decimal64 arguments.
< FAIL: gdb.base/dfp-test.exp: Call function with many _Decimal128 arguments.
< FAIL: gdb.base/dfp-test.exp: Call function with many mixed decimal float arguments.
< FAIL: gdb.base/dfp-test.exp: continue to breakpoint: Setting a decimal struct
< FAIL: gdb.base/dfp-test.exp: print ds.dec32
< FAIL: gdb.base/dfp-test.exp: print ds.dec64
< FAIL: gdb.base/dfp-test.exp: print ds.dec128
< FAIL: gdb.base/dfp-test.exp: print d32 + ds.dec32
< FAIL: gdb.base/dfp-test.exp: print d64 + ds.dec64
< FAIL: gdb.base/dfp-test.exp: print d128 + ds.dec128
---
> PASS: gdb.base/dfp-test.exp: Call function with mixed decimal float arguments TEST.
> PASS: gdb.base/dfp-test.exp: Call function with mixed decimal float arguments.
> PASS: gdb.base/dfp-test.exp: Call function with many _Decimal32 arguments.
> PASS: gdb.base/dfp-test.exp: Call function with many _Decimal64 arguments.
> PASS: gdb.base/dfp-test.exp: Call function with many _Decimal128 arguments.
> PASS: gdb.base/dfp-test.exp: Call function with many mixed decimal float arguments.
> PASS: gdb.base/dfp-test.exp: continue to breakpoint: Setting a decimal struct
> PASS: gdb.base/dfp-test.exp: print ds.dec32
> PASS: gdb.base/dfp-test.exp: print ds.dec64
> PASS: gdb.base/dfp-test.exp: print ds.dec128
> PASS: gdb.base/dfp-test.exp: print d32 + ds.dec32
> PASS: gdb.base/dfp-test.exp: print d64 + ds.dec64
> PASS: gdb.base/dfp-test.exp: print d128 + ds.dec128
2414c2390
< FAIL: gdb.base/dfp-test.exp: p ds.int4 + d128
---
> PASS: gdb.base/dfp-test.exp: p ds.int4 + d128
2422,2425c2398,2401
< FAIL: gdb.base/dfp-test.exp: p +d128
< FAIL: gdb.base/dfp-test.exp: p d64 == d128
< FAIL: gdb.base/dfp-test.exp: p d128 == ds.dec32
< FAIL: gdb.base/dfp-test.exp: p d128 == d32
---
> PASS: gdb.base/dfp-test.exp: p +d128
> PASS: gdb.base/dfp-test.exp: p d64 == d128
> PASS: gdb.base/dfp-test.exp: p d128 == ds.dec32
> PASS: gdb.base/dfp-test.exp: p d128 == d32
2427,2434c2403,2410
< FAIL: gdb.base/dfp-test.exp: p d32 < ds.dec32
< FAIL: gdb.base/dfp-test.exp: p d64 < ds.dec64
< FAIL: gdb.base/dfp-test.exp: p d128 < ds.dec128
< FAIL: gdb.base/dfp-test.exp: p ds.dec32 < d32
< FAIL: gdb.base/dfp-test.exp: p d64 > ds.dec64
< FAIL: gdb.base/dfp-test.exp: p ds.dec128 > d128
< FAIL: gdb.base/dfp-test.exp: p d32 < ds.int4
< FAIL: gdb.base/dfp-test.exp: p ds.int4 > d32
---
> PASS: gdb.base/dfp-test.exp: p d32 < ds.dec32
> PASS: gdb.base/dfp-test.exp: p d64 < ds.dec64
> PASS: gdb.base/dfp-test.exp: p d128 < ds.dec128
> PASS: gdb.base/dfp-test.exp: p ds.dec32 < d32
> PASS: gdb.base/dfp-test.exp: p d64 > ds.dec64
> PASS: gdb.base/dfp-test.exp: p ds.dec128 > d128
> PASS: gdb.base/dfp-test.exp: p d32 < ds.int4
> PASS: gdb.base/dfp-test.exp: p ds.int4 > d32
2437c2413
< FAIL: gdb.base/dfp-test.exp: p ds.dec128 > ds.int4
---
> PASS: gdb.base/dfp-test.exp: p ds.dec128 > ds.int4
2442c2418
< FAIL: gdb.base/dfp-test.exp: print ds.dec128=d128
---
> PASS: gdb.base/dfp-test.exp: print ds.dec128=d128
2445c2421
< FAIL: gdb.base/dfp-test.exp: print ds.dec128 = -d128
---
> PASS: gdb.base/dfp-test.exp: print ds.dec128 = -d128
2447c2423
< FAIL: gdb.base/dfp-test.exp: print ds.dec64 = ds.float4
---
> PASS: gdb.base/dfp-test.exp: print ds.dec64 = ds.float4
2450c2426
< FAIL: gdb.base/dfp-test.exp: print ds.dec32 = ds.int4
---
> PASS: gdb.base/dfp-test.exp: print ds.dec32 = ds.int4
2969c2945,3269
< ERROR: couldn't run to breakpoint
---
> PASS: gdb.base/exprs.exp: print char == (setup)
> PASS: gdb.base/exprs.exp: print char == (print v_char == 0)
> PASS: gdb.base/exprs.exp: print char == (print v_char == 127)
> PASS: gdb.base/exprs.exp: print char != (setup)
> PASS: gdb.base/exprs.exp: print char != (print v_char != 0)
> PASS: gdb.base/exprs.exp: print char != (print v_char != 127)
> PASS: gdb.base/exprs.exp: print char < (setup)
> PASS: gdb.base/exprs.exp: print char < (print v_char < 0)
> PASS: gdb.base/exprs.exp: print char < (print v_char < 127)
> PASS: gdb.base/exprs.exp: print char > (setup)
> PASS: gdb.base/exprs.exp: print char > (print v_char > 0)
> PASS: gdb.base/exprs.exp: print char > (print v_char > 127)
> PASS: gdb.base/exprs.exp: print signed char == (setup)
> PASS: gdb.base/exprs.exp: print signed char == (print v_signed_char == 0)
> PASS: gdb.base/exprs.exp: print signed char == (print v_signed_char == 127)
> PASS: gdb.base/exprs.exp: print signed char != (setup)
> PASS: gdb.base/exprs.exp: print signed char != (print v_signed_char != 0)
> PASS: gdb.base/exprs.exp: print signed char != (print v_signed_char != 127)
> PASS: gdb.base/exprs.exp: print signed char < (setup)
> PASS: gdb.base/exprs.exp: print signed char < (print v_signed_char < 0)
> PASS: gdb.base/exprs.exp: print signed char < (print v_signed_char < 127)
> PASS: gdb.base/exprs.exp: print signed char > (setup)
> PASS: gdb.base/exprs.exp: print signed char > (print v_signed_char > 0)
> PASS: gdb.base/exprs.exp: print signed char > (print v_signed_char > 127)
> PASS: gdb.base/exprs.exp: print signed char == (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed char == (minus) (print v_signed_char == 0)
> PASS: gdb.base/exprs.exp: print signed char == (minus) (print v_signed_char == -1)
> PASS: gdb.base/exprs.exp: print signed char != (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed char != (minus) (print v_signed_char != 0)
> PASS: gdb.base/exprs.exp: print signed char != (minus) (print v_signed_char != -1)
> PASS: gdb.base/exprs.exp: print signed char < (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed char < (minus) (print v_signed_char < 0)
> PASS: gdb.base/exprs.exp: print signed char < (minus) (print v_signed_char < 127)
> PASS: gdb.base/exprs.exp: print signed char > (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed char > (minus) (print v_signed_char > 0)
> PASS: gdb.base/exprs.exp: print signed char > (minus) (print v_signed_char > 127)
> PASS: gdb.base/exprs.exp: print unsigned char == (setup)
> PASS: gdb.base/exprs.exp: print unsigned char == (print v_unsigned_char == 0)
> PASS: gdb.base/exprs.exp: print unsigned char == (print v_unsigned_char == 127)
> PASS: gdb.base/exprs.exp: print unsigned char != (setup)
> PASS: gdb.base/exprs.exp: print unsigned char != (print v_unsigned_char != 0)
> PASS: gdb.base/exprs.exp: print unsigned char != (print v_unsigned_char != 127)
> PASS: gdb.base/exprs.exp: print unsigned char < (setup)
> PASS: gdb.base/exprs.exp: print unsigned char < (print v_unsigned_char < 0)
> PASS: gdb.base/exprs.exp: print unsigned char < (print v_unsigned_char < 127)
> PASS: gdb.base/exprs.exp: print unsigned char > (setup)
> PASS: gdb.base/exprs.exp: print unsigned char > (print v_unsigned_char > 0)
> PASS: gdb.base/exprs.exp: print unsigned char > (print v_unsigned_char > 127)
> PASS: gdb.base/exprs.exp: print unsigned char == (~0) (setup)
> PASS: gdb.base/exprs.exp: print unsigned char == (~0) (print v_unsigned_char == 0)
> PASS: gdb.base/exprs.exp: print unsigned char == (~0) (print v_unsigned_char == ~0)
> PASS: gdb.base/exprs.exp: print unsigned char == (~0) (print v_unsigned_char == (unsigned char)~0)
> PASS: gdb.base/exprs.exp: print unsigned char != (~0) (setup)
> PASS: gdb.base/exprs.exp: print unsigned char != (~0) (print v_unsigned_char != 0)
> PASS: gdb.base/exprs.exp: print unsigned char != (~0) (print v_unsigned_char != (unsigned char)~0)
> PASS: gdb.base/exprs.exp: print unsigned char != (~0) (print v_unsigned_char != ~0)
> PASS: gdb.base/exprs.exp: print unsigned char < (~0) (setup)
> PASS: gdb.base/exprs.exp: print unsigned char < (~0) (print v_unsigned_char < 0)
> PASS: gdb.base/exprs.exp: print unsigned char < (~0) (print v_unsigned_char < 127)
> PASS: gdb.base/exprs.exp: print unsigned char > (~0) (setup)
> PASS: gdb.base/exprs.exp: print unsigned char > (~0) (print v_unsigned_char > 0)
> PASS: gdb.base/exprs.exp: print unsigned char > (~0) (print v_unsigned_char > 127)
> PASS: gdb.base/exprs.exp: print signed short == (setup)
> PASS: gdb.base/exprs.exp: print signed short == (print v_short == 0)
> PASS: gdb.base/exprs.exp: print signed short == (print v_short == 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed short != (setup)
> PASS: gdb.base/exprs.exp: print signed short != (print v_short != 0)
> PASS: gdb.base/exprs.exp: print signed short != (print v_short != 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed short < (setup)
> PASS: gdb.base/exprs.exp: print signed short < (print v_short < 0)
> PASS: gdb.base/exprs.exp: print signed short < (print v_short < 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed short > (setup)
> PASS: gdb.base/exprs.exp: print signed short > (print v_short > 0)
> PASS: gdb.base/exprs.exp: print signed short > (print v_short > 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed short == (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed short == (minus) (print v_short == 0)
> PASS: gdb.base/exprs.exp: print signed short == (minus) (print v_short == -1)
> PASS: gdb.base/exprs.exp: print signed short != (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed short != (minus) (print v_short != 0)
> PASS: gdb.base/exprs.exp: print signed short != (minus) (print v_short != -1)
> PASS: gdb.base/exprs.exp: print signed short < (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed short < (minus) (print v_short < 0)
> PASS: gdb.base/exprs.exp: print signed short < (minus) (print v_short < 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed short > (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed short > (minus) (print v_short > 0)
> PASS: gdb.base/exprs.exp: print signed short > (minus) (print v_short > 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed signed short == (setup)
> PASS: gdb.base/exprs.exp: print signed signed short == (print v_signed_short == 0)
> PASS: gdb.base/exprs.exp: print signed signed short == (print v_signed_short == 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed signed short != (setup)
> PASS: gdb.base/exprs.exp: print signed signed short != (print v_signed_short != 0)
> PASS: gdb.base/exprs.exp: print signed signed short != (print v_signed_short != 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed signed short < (setup)
> PASS: gdb.base/exprs.exp: print signed signed short < (print v_signed_short < 0)
> PASS: gdb.base/exprs.exp: print signed signed short < (print v_signed_short < 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed signed short > (setup)
> PASS: gdb.base/exprs.exp: print signed signed short > (print v_signed_short > 0)
> PASS: gdb.base/exprs.exp: print signed signed short > (print v_signed_short > 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed signed short == (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed signed short == (minus) (print v_signed_short == 0)
> PASS: gdb.base/exprs.exp: print signed signed short == (minus) (print v_signed_short == -1)
> PASS: gdb.base/exprs.exp: print signed signed short != (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed signed short != (minus) (print v_signed_short != 0)
> PASS: gdb.base/exprs.exp: print signed signed short != (minus) (print v_signed_short != -1)
> PASS: gdb.base/exprs.exp: print signed signed short < (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed signed short < (minus) (print v_signed_short < 0)
> PASS: gdb.base/exprs.exp: print signed signed short < (minus) (print v_signed_short < 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed signed short > (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed signed short > (minus) (print v_signed_short > 0)
> PASS: gdb.base/exprs.exp: print signed signed short > (minus) (print v_signed_short > 0x7FFF)
> PASS: gdb.base/exprs.exp: print unsigned short == (setup)
> PASS: gdb.base/exprs.exp: print unsigned short == (print v_unsigned_short == 0)
> PASS: gdb.base/exprs.exp: print unsigned short == (print v_unsigned_short == 0x7FFF)
> PASS: gdb.base/exprs.exp: print unsigned short != (setup)
> PASS: gdb.base/exprs.exp: print unsigned short != (print v_unsigned_short != 0)
> PASS: gdb.base/exprs.exp: print unsigned short != (print v_unsigned_short != 0x7FFF)
> PASS: gdb.base/exprs.exp: print unsigned short < (setup)
> PASS: gdb.base/exprs.exp: print unsigned short < (print v_unsigned_short < 0)
> PASS: gdb.base/exprs.exp: print unsigned short < (print v_unsigned_short < 0x7FFF)
> PASS: gdb.base/exprs.exp: print unsigned short > (setup)
> PASS: gdb.base/exprs.exp: print unsigned short > (print v_unsigned_short > 0)
> PASS: gdb.base/exprs.exp: print unsigned short > (print v_unsigned_short > 0x7FFF)
> PASS: gdb.base/exprs.exp: print unsigned short == (~0) (setup)
> PASS: gdb.base/exprs.exp: print unsigned short == (~0) (print v_unsigned_short == 0)
> PASS: gdb.base/exprs.exp: print unsigned short == (~0) (print sizeof (v_unsigned_short) < sizeof (~0) && v_unsigned_short == ~0)
> PASS: gdb.base/exprs.exp: print unsigned short == (~0) (print v_unsigned_short == (unsigned short)~0)
> PASS: gdb.base/exprs.exp: print unsigned short != (~0) (setup)
> PASS: gdb.base/exprs.exp: print unsigned short != (~0) (print v_unsigned_short != 0)
> PASS: gdb.base/exprs.exp: print unsigned short != (~0) (print v_unsigned_short != (unsigned short)~0)
> PASS: gdb.base/exprs.exp: print unsigned short < (~0) (setup)
> PASS: gdb.base/exprs.exp: print unsigned short < (~0) (print v_unsigned_short < 0)
> PASS: gdb.base/exprs.exp: print unsigned short < (~0) (print v_unsigned_short < 0x7FFF)
> PASS: gdb.base/exprs.exp: print unsigned short > (~0) (setup)
> PASS: gdb.base/exprs.exp: print unsigned short > (~0) (print v_unsigned_short > 0)
> PASS: gdb.base/exprs.exp: print unsigned short > (~0) (print v_unsigned_short > 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed int == (setup)
> PASS: gdb.base/exprs.exp: print signed int == (print v_int == 0)
> PASS: gdb.base/exprs.exp: print signed int == (print v_int == 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed int != (setup)
> PASS: gdb.base/exprs.exp: print signed int != (print v_int != 0)
> PASS: gdb.base/exprs.exp: print signed int != (print v_int != 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed int < (setup)
> PASS: gdb.base/exprs.exp: print signed int < (print v_int < 0)
> PASS: gdb.base/exprs.exp: print signed int < (print v_int < 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed int > (setup)
> PASS: gdb.base/exprs.exp: print signed int > (print v_int > 0)
> PASS: gdb.base/exprs.exp: print signed int > (print v_int > 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed int == (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed int == (minus) (print v_int == 0)
> PASS: gdb.base/exprs.exp: print signed int == (minus) (print v_int == -1)
> PASS: gdb.base/exprs.exp: print signed int != (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed int != (minus) (print v_int != 0)
> PASS: gdb.base/exprs.exp: print signed int != (minus) (print v_int != -1)
> PASS: gdb.base/exprs.exp: print signed int < (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed int < (minus) (print v_int < 0)
> PASS: gdb.base/exprs.exp: print signed int < (minus) (print v_int < 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed int > (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed int > (minus) (print v_int > 0)
> PASS: gdb.base/exprs.exp: print signed int > (minus) (print v_int > 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed signed int == (setup)
> PASS: gdb.base/exprs.exp: print signed signed int == (print v_signed_int == 0)
> PASS: gdb.base/exprs.exp: print signed signed int == (print v_signed_int == 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed signed int != (setup)
> PASS: gdb.base/exprs.exp: print signed signed int != (print v_signed_int != 0)
> PASS: gdb.base/exprs.exp: print signed signed int != (print v_signed_int != 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed signed int < (setup)
> PASS: gdb.base/exprs.exp: print signed signed int < (print v_signed_int < 0)
> PASS: gdb.base/exprs.exp: print signed signed int < (print v_signed_int < 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed signed int > (setup)
> PASS: gdb.base/exprs.exp: print signed signed int > (print v_signed_int > 0)
> PASS: gdb.base/exprs.exp: print signed signed int > (print v_signed_int > 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed signed int == (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed signed int == (minus) (print v_signed_int == 0)
> PASS: gdb.base/exprs.exp: print signed signed int == (minus) (print v_signed_int == -1)
> PASS: gdb.base/exprs.exp: print signed signed int != (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed signed int != (minus) (print v_signed_int != 0)
> PASS: gdb.base/exprs.exp: print signed signed int != (minus) (print v_signed_int != -1)
> PASS: gdb.base/exprs.exp: print signed signed int < (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed signed int < (minus) (print v_signed_int < 0)
> PASS: gdb.base/exprs.exp: print signed signed int < (minus) (print v_signed_int < 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed signed int > (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed signed int > (minus) (print v_signed_int > 0)
> PASS: gdb.base/exprs.exp: print signed signed int > (minus) (print v_signed_int > 0x7FFF)
> PASS: gdb.base/exprs.exp: print unsigned int == (setup)
> PASS: gdb.base/exprs.exp: print unsigned int == (print v_unsigned_int == 0)
> PASS: gdb.base/exprs.exp: print unsigned int == (print v_unsigned_int == 0x7FFF)
> PASS: gdb.base/exprs.exp: print unsigned int != (setup)
> PASS: gdb.base/exprs.exp: print unsigned int != (print v_unsigned_int != 0)
> PASS: gdb.base/exprs.exp: print unsigned int != (print v_unsigned_int != 0x7FFF)
> PASS: gdb.base/exprs.exp: print unsigned int < (setup)
> PASS: gdb.base/exprs.exp: print unsigned int < (print v_unsigned_int < 0)
> PASS: gdb.base/exprs.exp: print unsigned int < (print v_unsigned_int < 0x7FFF)
> PASS: gdb.base/exprs.exp: print unsigned int > (setup)
> PASS: gdb.base/exprs.exp: print unsigned int > (print v_unsigned_int > 0)
> PASS: gdb.base/exprs.exp: print unsigned int > (print v_unsigned_int > 0x7FFF)
> PASS: gdb.base/exprs.exp: print unsigned int == (~0) (setup)
> PASS: gdb.base/exprs.exp: print unsigned int == (~0) (print v_unsigned_int == 0)
> PASS: gdb.base/exprs.exp: print unsigned int == (~0) (print v_unsigned_int == ~0)
> PASS: gdb.base/exprs.exp: print unsigned int == (~0) (print v_unsigned_int == (unsigned int)~0)
> PASS: gdb.base/exprs.exp: print unsigned int != (~0) (setup)
> PASS: gdb.base/exprs.exp: print unsigned int != (~0) (print v_unsigned_int != 0)
> PASS: gdb.base/exprs.exp: print unsigned int != (~0) (print v_unsigned_int != (unsigned int)~0)
> PASS: gdb.base/exprs.exp: print unsigned int < (~0) (setup)
> PASS: gdb.base/exprs.exp: print unsigned int < (~0) (print v_unsigned_int < 0)
> PASS: gdb.base/exprs.exp: print unsigned int < (~0) (print v_unsigned_int < 0x7FFF)
> PASS: gdb.base/exprs.exp: print unsigned int > (~0) (setup)
> PASS: gdb.base/exprs.exp: print unsigned int > (~0) (print v_unsigned_int > 0)
> PASS: gdb.base/exprs.exp: print unsigned int > (~0) (print v_unsigned_int > 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed long == (setup)
> PASS: gdb.base/exprs.exp: print signed long == (print v_long == 0)
> PASS: gdb.base/exprs.exp: print signed long == (print v_long == 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed long != (setup)
> PASS: gdb.base/exprs.exp: print signed long != (print v_long != 0)
> PASS: gdb.base/exprs.exp: print signed long != (print v_long != 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed long < (setup)
> PASS: gdb.base/exprs.exp: print signed long < (print v_long < 0)
> PASS: gdb.base/exprs.exp: print signed long < (print v_long < 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed long > (setup)
> PASS: gdb.base/exprs.exp: print signed long > (print v_long > 0)
> PASS: gdb.base/exprs.exp: print signed long > (print v_long > 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed long == (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed long == (minus) (print v_long == 0)
> PASS: gdb.base/exprs.exp: print signed long == (minus) (print v_long == -1)
> PASS: gdb.base/exprs.exp: print signed long != (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed long != (minus) (print v_long != 0)
> PASS: gdb.base/exprs.exp: print signed long != (minus) (print v_long != -1)
> PASS: gdb.base/exprs.exp: print signed long < (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed long < (minus) (print v_long < 0)
> PASS: gdb.base/exprs.exp: print signed long < (minus) (print v_long < 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed long > (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed long > (minus) (print v_long > 0)
> PASS: gdb.base/exprs.exp: print signed long > (minus) (print v_long > 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed signed long == (setup)
> PASS: gdb.base/exprs.exp: print signed signed long == (print v_signed_long == 0)
> PASS: gdb.base/exprs.exp: print signed signed long == (print v_signed_long == 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed signed long != (setup)
> PASS: gdb.base/exprs.exp: print signed signed long != (print v_signed_long != 0)
> PASS: gdb.base/exprs.exp: print signed signed long != (print v_signed_long != 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed signed long < (setup)
> PASS: gdb.base/exprs.exp: print signed signed long < (print v_signed_long < 0)
> PASS: gdb.base/exprs.exp: print signed signed long < (print v_signed_long < 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed signed long > (setup)
> PASS: gdb.base/exprs.exp: print signed signed long > (print v_signed_long > 0)
> PASS: gdb.base/exprs.exp: print signed signed long > (print v_signed_long > 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed signed long == (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed signed long == (minus) (print v_signed_long == 0)
> PASS: gdb.base/exprs.exp: print signed signed long == (minus) (print v_signed_long == -1)
> PASS: gdb.base/exprs.exp: print signed signed long != (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed signed long != (minus) (print v_signed_long != 0)
> PASS: gdb.base/exprs.exp: print signed signed long != (minus) (print v_signed_long != -1)
> PASS: gdb.base/exprs.exp: print signed signed long < (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed signed long < (minus) (print v_signed_long < 0)
> PASS: gdb.base/exprs.exp: print signed signed long < (minus) (print v_signed_long < 0x7FFF)
> PASS: gdb.base/exprs.exp: print signed signed long > (minus) (setup)
> PASS: gdb.base/exprs.exp: print signed signed long > (minus) (print v_signed_long > 0)
> PASS: gdb.base/exprs.exp: print signed signed long > (minus) (print v_signed_long > 0x7FFF)
> PASS: gdb.base/exprs.exp: print unsigned long == (setup)
> PASS: gdb.base/exprs.exp: print unsigned long == (print v_unsigned_long == 0)
> PASS: gdb.base/exprs.exp: print unsigned long == (print v_unsigned_long == 0x7FFF)
> PASS: gdb.base/exprs.exp: print unsigned long != (setup)
> PASS: gdb.base/exprs.exp: print unsigned long != (print v_unsigned_long != 0)
> PASS: gdb.base/exprs.exp: print unsigned long != (print v_unsigned_long != 0x7FFF)
> PASS: gdb.base/exprs.exp: print unsigned long < (setup)
> PASS: gdb.base/exprs.exp: print unsigned long < (print v_unsigned_long < 0)
> PASS: gdb.base/exprs.exp: print unsigned long < (print v_unsigned_long < 0x7FFF)
> PASS: gdb.base/exprs.exp: print unsigned long > (setup)
> PASS: gdb.base/exprs.exp: print unsigned long > (print v_unsigned_long > 0)
> PASS: gdb.base/exprs.exp: print unsigned long > (print v_unsigned_long > 0x7FFF)
> PASS: gdb.base/exprs.exp: print unsigned long == (~0) (setup)
> PASS: gdb.base/exprs.exp: print unsigned long == (~0) (print v_unsigned_long == 0)
> PASS: gdb.base/exprs.exp: print unsigned long == (~0) (print v_unsigned_long == ~0)
> PASS: gdb.base/exprs.exp: print unsigned long == (~0) (print v_unsigned_long == (unsigned long)~0)
> PASS: gdb.base/exprs.exp: print unsigned long != (~0) (setup)
> PASS: gdb.base/exprs.exp: print unsigned long != (~0) (print v_unsigned_long != 0)
> PASS: gdb.base/exprs.exp: print unsigned long != (~0) (print v_unsigned_long != (unsigned long)~0)
> PASS: gdb.base/exprs.exp: print unsigned long < (~0) (setup)
> PASS: gdb.base/exprs.exp: print unsigned long < (~0) (print v_unsigned_long < 0)
> PASS: gdb.base/exprs.exp: print unsigned long < (~0) (print v_unsigned_long < 0x7FFF)
> PASS: gdb.base/exprs.exp: print unsigned long > (~0) (setup)
> PASS: gdb.base/exprs.exp: print unsigned long > (~0) (print v_unsigned_long > 0)
> PASS: gdb.base/exprs.exp: print unsigned long > (~0) (print v_unsigned_long > 0x7FFF)
> PASS: gdb.base/exprs.exp: print (void*)v_signed_char (setup)
> PASS: gdb.base/exprs.exp: print (void*)v_signed_char (print (void*)v_signed_char)
> PASS: gdb.base/exprs.exp: print (void*)v_signed_short (setup)
> PASS: gdb.base/exprs.exp: print (void*)v_signed_short (print (void*)v_signed_short)
> PASS: gdb.base/exprs.exp: print (void*)v_signed_int (setup)
> PASS: gdb.base/exprs.exp: print (void*)v_signed_int (print (void*)v_signed_int)
> PASS: gdb.base/exprs.exp: print (void*)v_signed_long (setup)
> PASS: gdb.base/exprs.exp: print (void*)v_signed_long (print (void*)v_signed_long)
> PASS: gdb.base/exprs.exp: print (void*)v_unsigned_char (setup)
> PASS: gdb.base/exprs.exp: print (void*)v_unsigned_char (print (void*)v_unsigned_char)
> PASS: gdb.base/exprs.exp: print (void*)v_unsigned_short (setup)
> PASS: gdb.base/exprs.exp: print (void*)v_unsigned_short (print (void*)v_unsigned_short)
> PASS: gdb.base/exprs.exp: print (void*)v_unsigned_int (setup)
> PASS: gdb.base/exprs.exp: print (void*)v_unsigned_int (print (void*)v_unsigned_int)
> PASS: gdb.base/exprs.exp: print (void*)v_unsigned_long (setup)
> PASS: gdb.base/exprs.exp: print (void*)v_unsigned_long (print (void*)v_unsigned_long)
> PASS: gdb.base/exprs.exp: sizeof (long long) > sizeof (long) (true)
> FAIL: gdb.base/exprs.exp: truncate (void*) 0x00000000ffffffff + 1
> FAIL: gdb.base/exprs.exp: truncate (void*) 0xffffffff00000000 - 1
> PASS: gdb.base/exprs.exp: \$[0-9]* = "xy" (setup)
> PASS: gdb.base/exprs.exp: \$[0-9]* = "xyz" (setup)
> PASS: gdb.base/exprs.exp: \$[0-9]* = red (setup)
> PASS: gdb.base/exprs.exp: set output-radix 8
> PASS: gdb.base/exprs.exp: \$[0-9]* = red (setup)
> PASS: gdb.base/exprs.exp: \$[0-9]* = 0 (setup)
> PASS: gdb.base/exprs.exp: set output-radix 10
> PASS: gdb.base/exprs.exp: set variable v_int = 1
> PASS: gdb.base/exprs.exp: print v_int++
> PASS: gdb.base/exprs.exp: print ++v_int
> PASS: gdb.base/exprs.exp: print v_int--
> PASS: gdb.base/exprs.exp: print --v_int
> PASS: gdb.base/exprs.exp: print v_int++ = 5
> PASS: gdb.base/exprs.exp: print v_int-- = 5
> PASS: gdb.base/exprs.exp: print v_int_array_init
> PASS: gdb.base/exprs.exp: print *v_int_array_init@1
> PASS: gdb.base/exprs.exp: print *v_int_array_init@2
> PASS: gdb.base/exprs.exp: print v_int_array_init[0]@1
> PASS: gdb.base/exprs.exp: print v_int_array_init[0]@2
> PASS: gdb.base/exprs.exp: print v_int_array_init[1]@1
> PASS: gdb.base/exprs.exp: set variable v_short_array[0] = 42
> PASS: gdb.base/exprs.exp: print {short} v_short_array
> PASS: gdb.base/exprs.exp: print (void) v_int_pointer
> PASS: gdb.base/exprs.exp: print & (void) v_char
> PASS: gdb.base/exprs.exp: print null_t_struct && null_t_struct->v_int_member == 0
2973c3273
< UNRESOLVED: gdb.base/fileio.exp: fileio.exp
---
> UNTESTED: gdb.base/fileio.exp: fileio.exp
3275,3277c3575,3577
< gdb compile failed, /tmp/ccYKFlwS.s: Assembler messages:
< /tmp/ccYKFlwS.s:3: Warning: .type pseudo-op used outside of .def/.endef ignored.
< /tmp/ccYKFlwS.s:3: Error: junk at end of line, first unrecognized character is `g'
---
> gdb compile failed, /tmp/ccr8Alyx.s: Assembler messages:
> /tmp/ccr8Alyx.s:3: Warning: .type pseudo-op used outside of .def/.endef ignored.
> /tmp/ccr8Alyx.s:3: Error: junk at end of line, first unrecognized character is `g'
3280,3281c3580,3677
< gdb compile failed, exit status is 1
< UNTESTED: gdb.base/gnu_vector.exp: gnu_vector.exp
---
> PASS: gdb.base/gnu_vector.exp: print c4
> PASS: gdb.base/gnu_vector.exp: print c4[2]
> PASS: gdb.base/gnu_vector.exp: print i4a
> PASS: gdb.base/gnu_vector.exp: print i4b
> PASS: gdb.base/gnu_vector.exp: print i4a + i4b
> PASS: gdb.base/gnu_vector.exp: print i4a - i4b
> PASS: gdb.base/gnu_vector.exp: print i4a * i4b
> PASS: gdb.base/gnu_vector.exp: print i4a / i4b
> PASS: gdb.base/gnu_vector.exp: print i4a % i4b
> PASS: gdb.base/gnu_vector.exp: print i4a++
> PASS: gdb.base/gnu_vector.exp: print ++i4a
> PASS: gdb.base/gnu_vector.exp: print i4a--
> PASS: gdb.base/gnu_vector.exp: print --i4a
> PASS: gdb.base/gnu_vector.exp: print +i4a
> PASS: gdb.base/gnu_vector.exp: print -i4a
> PASS: gdb.base/gnu_vector.exp: print i4a & i4b
> PASS: gdb.base/gnu_vector.exp: print i4a | i4b
> PASS: gdb.base/gnu_vector.exp: print i4a ^ i4b
> PASS: gdb.base/gnu_vector.exp: print ~i4a
> PASS: gdb.base/gnu_vector.exp: print i4a << i4b
> PASS: gdb.base/gnu_vector.exp: print i4a >> i4b
> PASS: gdb.base/gnu_vector.exp: print f4a
> PASS: gdb.base/gnu_vector.exp: print f4b
> PASS: gdb.base/gnu_vector.exp: print f4a + f4b
> PASS: gdb.base/gnu_vector.exp: print f4a - f4b
> PASS: gdb.base/gnu_vector.exp: print f4a * f4b
> PASS: gdb.base/gnu_vector.exp: print f4a / f4b
> PASS: gdb.base/gnu_vector.exp: print +f4a
> PASS: gdb.base/gnu_vector.exp: print -f4a
> PASS: gdb.base/gnu_vector.exp: print (char4) 0x01010101
> PASS: gdb.base/gnu_vector.exp: print (char4) ia
> PASS: gdb.base/gnu_vector.exp: print (int2) lla
> PASS: gdb.base/gnu_vector.exp: print (int2) 1
> PASS: gdb.base/gnu_vector.exp: print (longlong2) 2
> PASS: gdb.base/gnu_vector.exp: print (float2) 3
> PASS: gdb.base/gnu_vector.exp: print (double2) 4
> PASS: gdb.base/gnu_vector.exp: print (uint4) ia
> PASS: gdb.base/gnu_vector.exp: print (int4) -3
> PASS: gdb.base/gnu_vector.exp: print (float4) 4
> PASS: gdb.base/gnu_vector.exp: print i4b = ia
> PASS: gdb.base/gnu_vector.exp: print i4a = 3
> PASS: gdb.base/gnu_vector.exp: print f4a = fb
> PASS: gdb.base/gnu_vector.exp: print f4b = 2
> PASS: gdb.base/gnu_vector.exp: print c4 + lla
> PASS: gdb.base/gnu_vector.exp: print i4a + lla
> PASS: gdb.base/gnu_vector.exp: print lla + c4
> PASS: gdb.base/gnu_vector.exp: print lla + i4a
> PASS: gdb.base/gnu_vector.exp: print c4 + ib
> PASS: gdb.base/gnu_vector.exp: print i4a + ib
> PASS: gdb.base/gnu_vector.exp: print i4a + 1
> PASS: gdb.base/gnu_vector.exp: print 1 + i4a
> PASS: gdb.base/gnu_vector.exp: print fa - f4b
> PASS: gdb.base/gnu_vector.exp: print 2 - f4b
> PASS: gdb.base/gnu_vector.exp: print f4a * fb
> PASS: gdb.base/gnu_vector.exp: print f4a * 1
> PASS: gdb.base/gnu_vector.exp: print ia / i4b
> PASS: gdb.base/gnu_vector.exp: print 2 / i4b
> PASS: gdb.base/gnu_vector.exp: print i4a % ib
> PASS: gdb.base/gnu_vector.exp: print i4a % 1
> PASS: gdb.base/gnu_vector.exp: print ia & i4b
> PASS: gdb.base/gnu_vector.exp: print 2 & i4b
> PASS: gdb.base/gnu_vector.exp: print i4a | ib
> PASS: gdb.base/gnu_vector.exp: print i4a | 1
> PASS: gdb.base/gnu_vector.exp: print ia ^ i4b
> PASS: gdb.base/gnu_vector.exp: print 2 ^ i4b
> PASS: gdb.base/gnu_vector.exp: print i4a << ib
> PASS: gdb.base/gnu_vector.exp: print i4a << 1
> PASS: gdb.base/gnu_vector.exp: print i4a >> ib
> PASS: gdb.base/gnu_vector.exp: print i4a >> 1
> PASS: gdb.base/gnu_vector.exp: print i4a = {2, 4, 8, 16}
> PASS: gdb.base/gnu_vector.exp: print i4a <<= ib
> PASS: gdb.base/gnu_vector.exp: print i4a + d2
> PASS: gdb.base/gnu_vector.exp: print d2 + i4a
> PASS: gdb.base/gnu_vector.exp: print f4a + ll2
> PASS: gdb.base/gnu_vector.exp: print ll2 + f4a
> PASS: gdb.base/gnu_vector.exp: print i2 + ll2
> PASS: gdb.base/gnu_vector.exp: print ll2 + i2
> PASS: gdb.base/gnu_vector.exp: print i4a + ll2
> PASS: gdb.base/gnu_vector.exp: print ll2 + i4a
> PASS: gdb.base/gnu_vector.exp: print f4a + d2
> PASS: gdb.base/gnu_vector.exp: print d2 + f4a
> PASS: gdb.base/gnu_vector.exp: print ui4 + i4a
> PASS: gdb.base/gnu_vector.exp: print i4a + ui4
> PASS: gdb.base/gnu_vector.exp: print i4a + i2
> PASS: gdb.base/gnu_vector.exp: print i2 + i4a
> PASS: gdb.base/gnu_vector.exp: print f4a + f2
> PASS: gdb.base/gnu_vector.exp: print f2 + f4a
> PASS: gdb.base/gnu_vector.exp: print (double2) f2
> PASS: gdb.base/gnu_vector.exp: print (int4) c4
> PASS: gdb.base/gnu_vector.exp: print (char4) i4a
> PASS: gdb.base/gnu_vector.exp: ptype c4
> PASS: gdb.base/gnu_vector.exp: ptype char4
> PASS: gdb.base/gnu_vector.exp: ptype i4a
> PASS: gdb.base/gnu_vector.exp: ptype int4
> PASS: gdb.base/gnu_vector.exp: ptype f4b
> PASS: gdb.base/gnu_vector.exp: ptype float4
> PASS: gdb.base/gnu_vector.exp: ptype union_with_vector_1
> PASS: gdb.base/gnu_vector.exp: ptype struct_with_vector_1
3612c4008
< gdb compile failed, /tmp/ccyKEEX1.o: In function `main':
---
> gdb compile failed, /tmp/ccwSgS7G.o: In function `main':
7391c7787
< FAIL: gdb.base/structs.exp: p/c L<n>; call 1 structs-tf
---
> PASS: gdb.base/structs.exp: p/c L<n>; call 1 structs-tf
7423c7819
< FAIL: gdb.base/structs.exp: p/c L<n>; call 1 structs-td
---
> PASS: gdb.base/structs.exp: p/c L<n>; call 1 structs-td
7846c8242
< gdb compile failed, /tmp/ccp17F3z.o: In function `main':
---
> gdb compile failed, /tmp/cc9Z0ZKo.o: In function `main':
7880,7882c8276,8278
< FAIL: gdb.base/varargs.exp: print find_max_float_real(4, fc1, fc2, fc3, fc4)
< FAIL: gdb.base/varargs.exp: print find_max_double_real(4, dc1, dc2, dc3, dc4)
< FAIL: gdb.base/varargs.exp: print find_max_long_double_real(4, ldc1, ldc2, ldc3, ldc4)
---
> PASS: gdb.base/varargs.exp: print find_max_float_real(4, fc1, fc2, fc3, fc4)
> PASS: gdb.base/varargs.exp: print find_max_double_real(4, dc1, dc2, dc3, dc4)
> PASS: gdb.base/varargs.exp: print find_max_long_double_real(4, ldc1, ldc2, ldc3, ldc4)
7982c8378
< gdb compile failed, /tmp/ccKclMwM.o: In function `open_shlib':
---
> gdb compile failed, /tmp/ccaeemVV.o: In function `open_shlib':
8407,8408c8803,8804
< # of expected passes 7336
< # of unexpected failures 326
---
> # of expected passes 7875
> # of unexpected failures 243
8410,8411c8806,8807
< # of known failures 23
< # of unresolved testcases 36
---
> # of known failures 24
> # of unresolved testcases 6
8414c8810
< /usr/local/src/gdbcvs/build-cross-src-mingw64/gdb/testsuite/../../gdb/gdb version 7.6.50.20130910-cvs -nw -nx -data-directory /usr/local/src/gdbcvs/build-cross-src-mingw64/gdb/testsuite/../data-directory -iex {maint set testsuite-mode on} -ex {set interactive-mode on} -iex {set target-charset UTF-8}
---
> /usr/local/src/gdbcvs/build-cross-src-mingw64/gdb/testsuite/../../gdb/gdb version 7.6.50.20130913-cvs -nw -nx -data-directory /usr/local/src/gdbcvs/build-cross-src-mingw64/gdb/testsuite/../data-directory -iex {maint set testsuite-mode on} -ex {set interactive-mode on} -iex {set target-charset UTF-8}
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC-v2] amd64-windows: Fix funcall with by-pointer arguments
2013-09-13 22:11 ` [RFC-v2] " Pierre Muller
@ 2013-09-16 20:57 ` Joel Brobecker
2013-09-17 13:50 ` Joel Brobecker
0 siblings, 1 reply; 18+ messages in thread
From: Joel Brobecker @ 2013-09-16 20:57 UTC (permalink / raw)
To: Pierre Muller; +Cc: 'Mark Kettenis', gdb-patches
Hi Pierre,
On Sat, Sep 14, 2013 at 12:10:59AM +0200, Pierre Muller wrote:
> As explained in the other thread,
> I merged Joel's patch in this thread with my patch
> in http://www.sourceware.org/ml/gdb-patches/2013-09/msg00145.html
>
> I attached the difference between two runs of:
> make check RUNTESTFKLAGS="gdb.base/*.exp"
> with current CVS GDB and with the patch below applied
> (plus a few other submitted patches concerning
> testsuite runs for *-*-ming* builds).
>
> The number of failure in gdb.base
> drops from 326 to 243 FAILs.
Thanks for doing that. I haven't completely finished reviewing
the patch yet, but I wanted to send a message so that you and
everyone else knows that I am on it. The patch looked good, minus
some trivial formatting issues which I will fix, but I noticed
a problem with function returning arrays. I am not sure where
it is coming from, whether from me incorrectly applying your
change, or missing something else, or whether it's a regression.
I ran out of time for today, but will try to pursue this further
tomorrow.
Just one comment below:
> 2013-09-12 Joel Brobecker <brobecker@adacore.com>
> Pierre Muller <muller@sourceware.org>
>
> * amd64-windows-tdep.c: #include "value.h" and "inferior.h".
> (amd64_windows_classify): Delete.
> (amd64_windows_passed_by_xmm_register)
> (amd64_windows_return_in_xmm0_register)
> (amd64_windows_passed_by_integer_register)
> (amd64_windows_passed_by_pointer)
> (amd64_windows_adjust_args_passed_by_pointer)
> (amd64_windows_store_arg_in_reg, amd64_windows_push_arguments)
> (amd64_windows_push_dummy_call): New functions.
> (amd64_return_value): Use new functions above. Add "debug infrum"
> information.
> (amd64_windows_init_abi): Remove setting of
> tdep->call_dummy_num_integer_regs, tdep->call_dummy_integer_regs,
> tdep->classify, tdep->memory_args_by_pointer and
> tdep->integer_param_regs_saved_in_caller_frame.
> Add call to set_gdbarch_push_dummy_call.
> /* The registers used to pass integer arguments during a function call. */
> static int amd64_windows_dummy_call_integer_regs[] =
> {
> AMD64_RCX_REGNUM, /* %rcx */
> AMD64_RDX_REGNUM, /* %rdx */
> - 8, /* %r8 */
> - 9 /* %r9 */
> + AMD64_R8_REGNUM, /* %r8 */
> + AMD64_R9_REGNUM /* %r9 */
This change can be checked in independently of this patch series,
I think.
> };
>
> -/* Implement the "classify" method in the gdbarch_tdep structure
> - for amd64-windows. */
> +/* Return nonzero if an argument of type TYPE should be passed
> + via one of the XMM registers. */
>
> -static void
> -amd64_windows_classify (struct type *type, enum amd64_reg_class class[2])
> +static int
> +amd64_windows_passed_by_xmm_register (struct type *type)
> {
> switch (TYPE_CODE (type))
> {
> - case TYPE_CODE_ARRAY:
> - /* Arrays are always passed by memory. */
> - class[0] = class[1] = AMD64_MEMORY;
> - break;
> + case TYPE_CODE_TYPEDEF:
> + if (TYPE_TARGET_TYPE (type))
> + return amd64_windows_passed_by_xmm_register (
> + TYPE_TARGET_TYPE (type));
> + else
> + return 0;
> + case TYPE_CODE_STRUCT:
> + case TYPE_CODE_UNION:
> + if (TYPE_NFIELDS (type) == 1)
> + return amd64_windows_passed_by_xmm_register (
> + TYPE_FIELD_TYPE (type, 0));
> + else
> + return 0;
> + case TYPE_CODE_FLT:
> + case TYPE_CODE_DECFLOAT:
> + return (TYPE_LENGTH (type) == 4 || TYPE_LENGTH (type) == 8);
> + default:
> + return 0;
> + }
> +}
> +
> +/* Return nonzero if an return value of type TYPE should be passed
> + in XMM0 register. */
> +
> +static int
> +amd64_windows_return_in_xmm0_register (struct type *type)
> +{
> + if (amd64_windows_passed_by_xmm_register (type))
> + return 1;
> + else
> + {
> + /* __m128, __m128d and __m128i types are returned in $xmm0 also.
> + But they are not stored in XMM registers as arguments,
> + at least not in GCC 4.7.6 x86_64-w64-mingw32 target.
> + Note: The TYPE_VECTOR check should prevent other arrays from
> + being treated as special xmm types.
> + Note: This all works for the "unique" __fastcall calling
> convention
> + as defined by Microsoft. The newer __vectorcall convention
> + does support passing __m128X type parameters in xmm registers
> + using /Gv option of Microsoft compilers. */
> + struct type *ltype = check_typedef (type);
> + if (ltype && TYPE_CODE (ltype) == TYPE_CODE_ARRAY
> + && (TYPE_CODE (TYPE_TARGET_TYPE (ltype)) == TYPE_CODE_FLT
> + || TYPE_CODE (TYPE_TARGET_TYPE (ltype)) == TYPE_CODE_INT)
> + && TYPE_VECTOR (ltype) && TYPE_LENGTH (ltype) == 16)
> + return 1;
> + else
> + return 0;
> + }
> +}
> +
> +/* Return nonzero if an argument of type TYPE should be passed
> + via one of the integer registers. */
>
> +static int
> +amd64_windows_passed_by_integer_register (struct type *type)
> +{
> + switch (TYPE_CODE (type))
> + {
> + case TYPE_CODE_TYPEDEF:
> + if (TYPE_TARGET_TYPE (type))
> + return amd64_windows_passed_by_integer_register (
> + TYPE_TARGET_TYPE (type));
> + else
> + return 0;
> case TYPE_CODE_STRUCT:
> case TYPE_CODE_UNION:
> - /* Struct/Union types whose size is 1, 2, 4, or 8 bytes
> - are passed as if they were integers of the same size.
> - Types of different sizes are passed by memory. */
> - if (TYPE_LENGTH (type) == 1
> - || TYPE_LENGTH (type) == 2
> - || TYPE_LENGTH (type) == 4
> - || TYPE_LENGTH (type) == 8)
> + if (TYPE_NFIELDS (type) == 1)
> {
> - class[0] = AMD64_INTEGER;
> - class[1] = AMD64_NO_CLASS;
> + /* If only one field, exclude float type accepted as xmm reg.
> */
> + if (amd64_windows_passed_by_xmm_register (
> + TYPE_FIELD_TYPE (type, 0)))
> + return 0;
> + else
> + return amd64_windows_passed_by_integer_register (
> + TYPE_FIELD_TYPE (type, 0));
> }
> - else
> - class[0] = class[1] = AMD64_MEMORY;
> - break;
> + /* Struct/Union with several fields: Pass Through. */
> + case TYPE_CODE_INT:
> + case TYPE_CODE_ENUM:
> + case TYPE_CODE_BOOL:
> + case TYPE_CODE_RANGE:
> + case TYPE_CODE_CHAR:
> + case TYPE_CODE_PTR:
> + case TYPE_CODE_REF:
> + case TYPE_CODE_COMPLEX:
> + return (TYPE_LENGTH (type) == 1
> + || TYPE_LENGTH (type) == 2
> + || TYPE_LENGTH (type) == 4
> + || TYPE_LENGTH (type) == 8);
>
> default:
> - /* For all the other types, the conventions are the same as
> - with the System V ABI. */
> - amd64_classify (type, class);
> + return 0;
> }
> }
>
> +/* 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)
> +{
> + if (amd64_windows_passed_by_integer_register (type))
> + return 0;
> +
> + if (amd64_windows_passed_by_xmm_register (type))
> + return 0;
> +
> + return 1;
> +}
> +
> +/* 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. */
> +
> +static CORE_ADDR
> +amd64_windows_adjust_args_passed_by_pointer (struct gdbarch *gdbarch,
> + 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));
> + if (debug_infrun)
> + printf_filtered (_("Parameter #%d, length %d copied on stack "
> + "at address %s, and passed as pointer\n"),
> + i, len, paddress (gdbarch, sp));
> + }
> +
> + return sp;
> +}
> +
> +/* Store the value of ARG in register REGNO (right-justified).
> + REGCACHE is the register cache. */
> +
> +static void
> +amd64_windows_store_arg_in_reg (struct gdbarch *gdbarch,
> + struct regcache *regcache,
> + struct value *arg, int regno, int i)
> +{
> + struct type *type = value_type (arg);
> + const gdb_byte *valbuf = value_contents (arg);
> + gdb_byte buf[8];
> +
> + gdb_assert (TYPE_LENGTH (type) <= 8);
> + memset (buf, 0, sizeof buf);
> + memcpy (buf, valbuf, min (TYPE_LENGTH (type), 8));
> + regcache_cooked_write (regcache, regno, buf);
> + if (debug_infrun)
> + printf_filtered (_("Parameter #%d, length %d copied to register %s\n"),
> + i, TYPE_LENGTH (type), i386_pseudo_register_name(
> + gdbarch, regno));
> +}
> +
> +/* Push the arguments for an inferior function call, and return
> + the updated value of the SP (Stack Pointer).
> +
> + All arguments are identical to the arguments used in
> + amd64_windows_push_dummy_call. */
> +
> +static CORE_ADDR
> +amd64_windows_push_arguments (struct gdbarch *gdbarch,
> + struct regcache *regcache, int nargs,
> + struct value **args, CORE_ADDR sp,
> + int struct_return)
> +{
> + int reg_idx = 0;
> + int i;
> + struct value **stack_args = alloca (nargs * sizeof (struct value *));
> + int num_stack_args = 0;
> + int num_elements = 0;
> + int element = 0;
> +
> + /* First, handle the arguments passed by pointer.
> +
> + These arguments are replaced by pointers to a copy we are making
> + in inferior memory. So use a copy of the ARGS table, to avoid
> + modifying the original one. */
> + {
> + struct value **args1 = alloca (nargs * sizeof (struct value *));
> +
> + memcpy (args1, args, nargs * sizeof (struct value *));
> + sp = amd64_windows_adjust_args_passed_by_pointer (gdbarch, args1,
> + nargs, sp);
> + args = args1;
> + }
> +
> + /* Reserve a register for the "hidden" argument. */
> + if (struct_return)
> + reg_idx++;
> +
> + for (i = 0; i < nargs; i++)
> + {
> + struct type *type = value_type (args[i]);
> + int len = TYPE_LENGTH (type);
> + int on_stack_p = 1;
> +
> + if (reg_idx < ARRAY_SIZE (amd64_windows_dummy_call_integer_regs))
> + {
> + if (amd64_windows_passed_by_integer_register (type))
> + {
> + amd64_windows_store_arg_in_reg
> + (gdbarch, regcache, args[i],
> + amd64_windows_dummy_call_integer_regs[reg_idx], i);
> + on_stack_p = 0;
> + reg_idx++;
> + }
> + else if (amd64_windows_passed_by_xmm_register (type))
> + {
> + amd64_windows_store_arg_in_reg
> + (gdbarch, regcache, args[i], AMD64_XMM0_REGNUM + reg_idx,
> i);
> + /* In case of varargs, these parameters must also be
> + passed via the integer registers. */
> + amd64_windows_store_arg_in_reg
> + (gdbarch, regcache, args[i],
> + amd64_windows_dummy_call_integer_regs[reg_idx], i);
> + on_stack_p = 0;
> + reg_idx++;
> + }
> + }
> +
> + if (on_stack_p)
> + {
> + num_elements += ((len + 7) / 8);
> + stack_args[num_stack_args++] = args[i];
> + }
> + }
> +
> + /* Allocate space for the arguments on the stack, keeping it
> + aligned on a 16 byte boundary. */
> + sp -= num_elements * 8;
> + sp &= ~0xf;
> +
> + /* Write out the arguments to the stack. */
> + for (i = 0; i < num_stack_args; i++)
> + {
> + struct type *type = value_type (stack_args[i]);
> + const gdb_byte *valbuf = value_contents (stack_args[i]);
> +
> + write_memory (sp + element * 8, valbuf, TYPE_LENGTH (type));
> + if (debug_infrun)
> + printf_filtered (_("Parameter #%d, length %d copied on stack"
> + " at address %s\n"),
> + i, TYPE_LENGTH (type),
> + paddress (gdbarch, sp + element * 8));
> + element += ((TYPE_LENGTH (type) + 7) / 8);
> + }
> +
> + return sp;
> +}
> +
> +/* Implement the "push_dummy_call" gdbarch method. */
> +
> +static CORE_ADDR
> +amd64_windows_push_dummy_call
> + (struct gdbarch *gdbarch, struct value *function,
> + struct regcache *regcache, CORE_ADDR bp_addr,
> + int nargs, struct value **args,
> + CORE_ADDR sp, int struct_return, CORE_ADDR struct_addr)
> +{
> + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
> + gdb_byte buf[8];
> +
> + /* Pass arguments. */
> + sp = amd64_windows_push_arguments (gdbarch, regcache, nargs, args, sp,
> + struct_return);
> +
> + /* Pass "hidden" argument". */
> + if (struct_return)
> + {
> + /* The "hidden" argument is passed throught the first argument
> + register. */
> + const int arg_regnum = amd64_windows_dummy_call_integer_regs[0];
> +
> + store_unsigned_integer (buf, 8, byte_order, struct_addr);
> + regcache_cooked_write (regcache, arg_regnum, buf);
> + }
> +
> + /* Reserve some memory on the stack for the integer-parameter
> + registers, as required by the ABI. */
> + sp -= ARRAY_SIZE (amd64_windows_dummy_call_integer_regs) * 8;
> +
> + /* Store return address. */
> + sp -= 8;
> + store_unsigned_integer (buf, 8, byte_order, bp_addr);
> + write_memory (sp, buf, 8);
> +
> + /* Update the stack pointer... */
> + store_unsigned_integer (buf, 8, byte_order, sp);
> + regcache_cooked_write (regcache, AMD64_RSP_REGNUM, buf);
> +
> + /* ...and fake a frame pointer. */
> + regcache_cooked_write (regcache, AMD64_RBP_REGNUM, buf);
> +
> + return sp + 16;
> +}
> +
> /* Implement the "return_value" gdbarch method for amd64-windows. */
>
> static enum return_value_convention
> @@ -90,22 +379,10 @@ amd64_windows_return_value (struct gdbar
>
> /* See if our value is returned through a register. If it is, then
> store the associated register number in REGNUM. */
> - switch (TYPE_CODE (type))
> - {
> - case TYPE_CODE_FLT:
> - case TYPE_CODE_DECFLOAT:
> - /* __m128, __m128i, __m128d, floats, and doubles are returned
> - via XMM0. */
> - if (len == 4 || len == 8 || len == 16)
> - regnum = AMD64_XMM0_REGNUM;
> - break;
> - default:
> - /* All other values that are 1, 2, 4 or 8 bytes long are returned
> - via RAX. */
> - if (len == 1 || len == 2 || len == 4 || len == 8)
> - regnum = AMD64_RAX_REGNUM;
> - break;
> - }
> + if (amd64_windows_return_in_xmm0_register (type))
> + regnum = AMD64_XMM0_REGNUM;
> + else if (amd64_windows_passed_by_integer_register (type))
> + regnum = AMD64_RAX_REGNUM;
>
> if (regnum < 0)
> {
> @@ -117,8 +394,10 @@ amd64_windows_return_value (struct gdbar
> regcache_raw_read_unsigned (regcache, AMD64_RAX_REGNUM, &addr);
> read_memory (addr, readbuf, TYPE_LENGTH (type));
> }
> + if (debug_infrun)
> + printf_filtered (_("Return value as memory address in RAX\n"));
> return RETURN_VALUE_ABI_RETURNS_ADDRESS;
> - }
> + }
> else
> {
> /* Extract the return value from the register where it was stored.
> */
> @@ -126,6 +405,9 @@ amd64_windows_return_value (struct gdbar
> regcache_raw_read_part (regcache, regnum, 0, len, readbuf);
> if (writebuf)
> regcache_raw_write_part (regcache, regnum, 0, len, writebuf);
> + if (debug_infrun)
> + printf_filtered (_("Return value in register %s\n"),
> + gdbarch_register_name (gdbarch, regnum));
> return RETURN_VALUE_REGISTER_CONVENTION;
> }
> }
> @@ -976,12 +1258,7 @@ amd64_windows_init_abi (struct gdbarch_i
> set_gdbarch_long_bit (gdbarch, 32);
>
> /* Function calls. */
> - 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->classify = amd64_windows_classify;
> - tdep->memory_args_by_pointer = 1;
> - tdep->integer_param_regs_saved_in_caller_frame = 1;
> + set_gdbarch_push_dummy_call (gdbarch, amd64_windows_push_dummy_call);
> set_gdbarch_return_value (gdbarch, amd64_windows_return_value);
> set_gdbarch_skip_main_prologue (gdbarch, amd64_skip_main_prologue);
> set_gdbarch_skip_trampoline_code (gdbarch,
--
Joel
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC-v2] amd64-windows: Fix funcall with by-pointer arguments
2013-09-16 20:57 ` Joel Brobecker
@ 2013-09-17 13:50 ` Joel Brobecker
2013-09-20 23:20 ` Joel Brobecker
0 siblings, 1 reply; 18+ messages in thread
From: Joel Brobecker @ 2013-09-17 13:50 UTC (permalink / raw)
To: Pierre Muller; +Cc: 'Mark Kettenis', gdb-patches
> Thanks for doing that. I haven't completely finished reviewing
> the patch yet, but I wanted to send a message so that you and
> everyone else knows that I am on it. The patch looked good, minus
> some trivial formatting issues which I will fix, but I noticed
> a problem with function returning arrays. I am not sure where
> it is coming from, whether from me incorrectly applying your
> change, or missing something else, or whether it's a regression.
>
> I ran out of time for today, but will try to pursue this further
> tomorrow.
Small update for today. This is the change I had to apply on top of
your patch in order to fix the problem:
- else if (amd64_windows_passed_by_integer_register (type))
- regnum = AMD64_RAX_REGNUM;
+ else if (len == 1 || len == 2 || len == 4 || len == 8)
+ {
+ /* All values of this size are returned via RAX. */
+ regnum = AMD64_RAX_REGNUM;
+ }
It fixes the case where we return a small array of integers.
The documentation I have said, at the time:
Return values that can fit into 64-bits are returned through RAX
(including __m64 types), except for __m128, __m128i, __m128d, floats,
and doubles, which are returned in XMM0. [...] User defined types to
be returned must be 1, 2, 4, 8, 16, 32, or 64 bits in length.
This all made me realize that merging our two patches creates
a bit of confusion about what is a pure rewrite, and what is an
attempt to fix what.
So, here is what I will do: I will clean my patch up, retest,
also remove all amd64-windows-specific hooks as initially said,
and then send you an updated patch containing your changes, with
my fixes. If you could please:
1. Re-test, making sure that I did not break anything back;
2. Re-submit each piece for each problem that you're solving,
with description provided with each patch.
This will make the review process easier for me.
Thank you!
--
Joel
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC-v2] amd64-windows: Fix funcall with by-pointer arguments
2013-09-17 13:50 ` Joel Brobecker
@ 2013-09-20 23:20 ` Joel Brobecker
2013-09-24 16:33 ` Joel Brobecker
0 siblings, 1 reply; 18+ messages in thread
From: Joel Brobecker @ 2013-09-20 23:20 UTC (permalink / raw)
To: Pierre Muller; +Cc: 'Mark Kettenis', gdb-patches
[-- Attachment #1: Type: text/plain, Size: 2024 bytes --]
Hello again Pierre,
> This all made me realize that merging our two patches creates
> a bit of confusion about what is a pure rewrite, and what is an
> attempt to fix what.
>
> So, here is what I will do: I will clean my patch up, retest,
> also remove all amd64-windows-specific hooks as initially said,
> and then send you an updated patch containing your changes, with
> my fixes. If you could please:
> 1. Re-test, making sure that I did not break anything back;
> 2. Re-submit each piece for each problem that you're solving,
> with description provided with each patch.
>
> This will make the review process easier for me.
Once again, I'm short of time to finish what I had hoped to be able
to complete. But I thought I'd send an update anyway. The first patch
is an update to the patch I wrote in January, rebased for today's HEAD.
This is what I have tested and intend to check in soon.
Left to do on my end, is clean things up in amd64-tdep, because many
hooks in the tdep structure can now be removed, and replaced by
direct calls. But this is independent of your changes, so we can
both work at the same time.
The second patch are your changes, adjusted to fix the one bug
I found, and also to better follow our coding style. From memory:
- When breaking lines in function calls, place the opening '(' on
the next line rather than breaking after it;
- if COND then return X; else return 0;
=> Replaced by return (COND && X)
It's not better, but shortens the code a little, which helps
when inside a large switch/case block
- No i18n required for debug traces
You can now start submitting your changes on top of mine anytime,
and I will try to review them promptly. Please try to break them up
and explain the rationale behind them (what problem do they fix, for
instance, and also, if there are already some tests in our testsuite
that go from FAIL to PASS thanks to your patch). The hunks adding
debug traces, for instance, could be sent separately.
Thank you,
--
Joel
[-- Attachment #2: 0001-Reimplement-function-calls-on-amd64-windows.patch --]
[-- Type: text/x-diff, Size: 10897 bytes --]
From 3d6ed716608d087422b92570cd84112470fa2f92 Mon Sep 17 00:00:00 2001
From: Joel Brobecker <brobecker@adacore.com>
Date: Sat, 21 Sep 2013 00:12:44 +0200
Subject: [PATCH 1/2] Reimplement function calls on amd64-windows
This patch provides a standalone implementation of function calls
on amd64-windows, instead of providing some bits and pieces hooking
into the function call implementation meant for sysV (in amd64-tdep).
It makes better sense to do it this way, because the two ABIs are
actually very different; for instance, the concept of argument
classification, which is so central in the sysV ABI and drove the
the implementation in amd64-tdep, makes no sense for Windows. It
is therefore better for the Windows implementation to be completely
separate, rather than rely on adaptations of the sysV implementation.
gdb/ChangeLog:
* amd64-tdep.c: #include "value.h"
(amd64_windows_classify): Delete.
(amd64_windows_passed_by_integer_register)
(amd64_windows_passed_by_xmm_register)
(amd64_windows_passed_by_pointer)
(amd64_windows_adjust_args_passed_by_pointer)
(amd64_windows_store_arg_in_reg, amd64_windows_push_arguments)
(amd64_windows_push_dummy_call): New functions.
(amd64_windows_init_abi): Remove setting of
tdep->call_dummy_num_integer_regs, tdep->call_dummy_integer_regs,
tdep->classify, tdep->memory_args_by_pointer and
tdep->integer_param_regs_saved_in_caller_frame.
Add call to set_gdbarch_push_dummy_call.
---
gdb/amd64-windows-tdep.c | 264 ++++++++++++++++++++++++++++++++++++++++------
1 files changed, 232 insertions(+), 32 deletions(-)
diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c
index 4e750a1..c09262a 100644
--- a/gdb/amd64-windows-tdep.c
+++ b/gdb/amd64-windows-tdep.c
@@ -31,6 +31,7 @@
#include "coff/i386.h"
#include "coff/pe.h"
#include "libcoff.h"
+#include "value.h"
/* The registers used to pass integer arguments during a function call. */
static int amd64_windows_dummy_call_integer_regs[] =
@@ -41,43 +42,247 @@ static int amd64_windows_dummy_call_integer_regs[] =
9 /* %r9 */
};
-/* Implement the "classify" method in the gdbarch_tdep structure
- for amd64-windows. */
+/* Return nonzero if an argument of type TYPE should be passed
+ via one of the integer registers. */
-static void
-amd64_windows_classify (struct type *type, enum amd64_reg_class class[2])
+static int
+amd64_windows_passed_by_integer_register (struct type *type)
{
switch (TYPE_CODE (type))
{
- case TYPE_CODE_ARRAY:
- /* Arrays are always passed by memory. */
- class[0] = class[1] = AMD64_MEMORY;
- break;
-
+ case TYPE_CODE_INT:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_REF:
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
- /* Struct/Union types whose size is 1, 2, 4, or 8 bytes
- are passed as if they were integers of the same size.
- Types of different sizes are passed by memory. */
- if (TYPE_LENGTH (type) == 1
- || TYPE_LENGTH (type) == 2
- || TYPE_LENGTH (type) == 4
- || TYPE_LENGTH (type) == 8)
- {
- class[0] = AMD64_INTEGER;
- class[1] = AMD64_NO_CLASS;
- }
- else
- class[0] = class[1] = AMD64_MEMORY;
- break;
+ return (TYPE_LENGTH (type) == 1
+ || TYPE_LENGTH (type) == 2
+ || TYPE_LENGTH (type) == 4
+ || TYPE_LENGTH (type) == 8);
default:
- /* For all the other types, the conventions are the same as
- with the System V ABI. */
- amd64_classify (type, class);
+ return 0;
}
}
+/* Return nonzero if an argument of type TYPE should be passed
+ via one of the XMM registers. */
+
+static int
+amd64_windows_passed_by_xmm_register (struct type *type)
+{
+ return ((TYPE_CODE (type) == TYPE_CODE_FLT
+ || TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
+ && (TYPE_LENGTH (type) == 4 || TYPE_LENGTH (type) == 8));
+}
+
+/* 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)
+{
+ if (amd64_windows_passed_by_integer_register (type))
+ return 0;
+
+ if (amd64_windows_passed_by_xmm_register (type))
+ return 0;
+
+ return 1;
+}
+
+/* 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. */
+
+static CORE_ADDR
+amd64_windows_adjust_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;
+}
+
+/* Store the value of ARG in register REGNO (right-justified).
+ REGCACHE is the register cache. */
+
+static void
+amd64_windows_store_arg_in_reg (struct regcache *regcache,
+ struct value *arg, int regno)
+{
+ struct type *type = value_type (arg);
+ const gdb_byte *valbuf = value_contents (arg);
+ gdb_byte buf[8];
+
+ gdb_assert (TYPE_LENGTH (type) <= 8);
+ memset (buf, 0, sizeof buf);
+ memcpy (buf, valbuf, min (TYPE_LENGTH (type), 8));
+ regcache_cooked_write (regcache, regno, buf);
+}
+
+/* Push the arguments for an inferior function call, and return
+ the updated value of the SP (Stack Pointer).
+
+ All arguments are identical to the arguments used in
+ amd64_windows_push_dummy_call. */
+
+static CORE_ADDR
+amd64_windows_push_arguments (struct regcache *regcache, int nargs,
+ struct value **args, CORE_ADDR sp,
+ int struct_return)
+{
+ int reg_idx = 0;
+ int i;
+ struct value **stack_args = alloca (nargs * sizeof (struct value *));
+ int num_stack_args = 0;
+ int num_elements = 0;
+ int element = 0;
+
+ /* First, handle the arguments passed by pointer.
+
+ These arguments are replaced by pointers to a copy we are making
+ in inferior memory. So use a copy of the ARGS table, to avoid
+ modifying the original one. */
+ {
+ struct value **args1 = alloca (nargs * sizeof (struct value *));
+
+ memcpy (args1, args, nargs * sizeof (struct value *));
+ sp = amd64_windows_adjust_args_passed_by_pointer (args1, nargs, sp);
+ args = args1;
+ }
+
+ /* Reserve a register for the "hidden" argument. */
+ if (struct_return)
+ reg_idx++;
+
+ for (i = 0; i < nargs; i++)
+ {
+ struct type *type = value_type (args[i]);
+ int len = TYPE_LENGTH (type);
+ int on_stack_p = 1;
+
+ if (reg_idx < ARRAY_SIZE (amd64_windows_dummy_call_integer_regs))
+ {
+ if (amd64_windows_passed_by_integer_register (type))
+ {
+ amd64_windows_store_arg_in_reg
+ (regcache, args[i],
+ amd64_windows_dummy_call_integer_regs[reg_idx]);
+ on_stack_p = 0;
+ reg_idx++;
+ }
+ else if (amd64_windows_passed_by_xmm_register (type))
+ {
+ amd64_windows_store_arg_in_reg
+ (regcache, args[i], AMD64_XMM0_REGNUM + reg_idx);
+ /* In case of varargs, these parameters must also be
+ passed via the integer registers. */
+ amd64_windows_store_arg_in_reg
+ (regcache, args[i],
+ amd64_windows_dummy_call_integer_regs[reg_idx]);
+ on_stack_p = 0;
+ reg_idx++;
+ }
+ }
+
+ if (on_stack_p)
+ {
+ num_elements += ((len + 7) / 8);
+ stack_args[num_stack_args++] = args[i];
+ }
+ }
+
+ /* Allocate space for the arguments on the stack, keeping it
+ aligned on a 16 byte boundary. */
+ sp -= num_elements * 8;
+ sp &= ~0xf;
+
+ /* Write out the arguments to the stack. */
+ for (i = 0; i < num_stack_args; i++)
+ {
+ struct type *type = value_type (stack_args[i]);
+ const gdb_byte *valbuf = value_contents (stack_args[i]);
+
+ write_memory (sp + element * 8, valbuf, TYPE_LENGTH (type));
+ element += ((TYPE_LENGTH (type) + 7) / 8);
+ }
+
+ return sp;
+}
+
+/* Implement the "push_dummy_call" gdbarch method. */
+
+static CORE_ADDR
+amd64_windows_push_dummy_call
+ (struct gdbarch *gdbarch, struct value *function,
+ struct regcache *regcache, CORE_ADDR bp_addr,
+ int nargs, struct value **args,
+ CORE_ADDR sp, int struct_return, CORE_ADDR struct_addr)
+{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ gdb_byte buf[8];
+
+ /* Pass arguments. */
+ sp = amd64_windows_push_arguments (regcache, nargs, args, sp,
+ struct_return);
+
+ /* Pass "hidden" argument". */
+ if (struct_return)
+ {
+ /* The "hidden" argument is passed throught the first argument
+ register. */
+ const int arg_regnum = amd64_windows_dummy_call_integer_regs[0];
+
+ store_unsigned_integer (buf, 8, byte_order, struct_addr);
+ regcache_cooked_write (regcache, arg_regnum, buf);
+ }
+
+ /* Reserve some memory on the stack for the integer-parameter
+ registers, as required by the ABI. */
+ sp -= ARRAY_SIZE (amd64_windows_dummy_call_integer_regs) * 8;
+
+ /* Store return address. */
+ sp -= 8;
+ store_unsigned_integer (buf, 8, byte_order, bp_addr);
+ write_memory (sp, buf, 8);
+
+ /* Update the stack pointer... */
+ store_unsigned_integer (buf, 8, byte_order, sp);
+ regcache_cooked_write (regcache, AMD64_RSP_REGNUM, buf);
+
+ /* ...and fake a frame pointer. */
+ regcache_cooked_write (regcache, AMD64_RBP_REGNUM, buf);
+
+ return sp + 16;
+}
+
/* Implement the "return_value" gdbarch method for amd64-windows. */
static enum return_value_convention
@@ -976,12 +1181,7 @@ amd64_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_long_bit (gdbarch, 32);
/* Function calls. */
- 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->classify = amd64_windows_classify;
- tdep->memory_args_by_pointer = 1;
- tdep->integer_param_regs_saved_in_caller_frame = 1;
+ set_gdbarch_push_dummy_call (gdbarch, amd64_windows_push_dummy_call);
set_gdbarch_return_value (gdbarch, amd64_windows_return_value);
set_gdbarch_skip_main_prologue (gdbarch, amd64_skip_main_prologue);
set_gdbarch_skip_trampoline_code (gdbarch,
--
1.6.6.1
[-- Attachment #3: 0002-Pierre-s-modifications-for-amd64-windows-funcalls.patch --]
[-- Type: text/x-diff, Size: 10849 bytes --]
From 5cc8a508d19e3474cba64583597c54d8f2f05e5e Mon Sep 17 00:00:00 2001
From: Joel Brobecker <brobecker@adacore.com>
Date: Sat, 21 Sep 2013 00:56:12 +0200
Subject: [PATCH 2/2] Pierre's modifications for amd64-windows funcalls
... with some minor edits from Joel, mostly style, but with one bug
correction (array return values).
ChangeLog to provided later, as this patch should be broken down
into individual pieces.
---
gdb/amd64-windows-tdep.c | 157 ++++++++++++++++++++++++++++++++++-----------
1 files changed, 118 insertions(+), 39 deletions(-)
diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c
index c09262a..b1a145f 100644
--- a/gdb/amd64-windows-tdep.c
+++ b/gdb/amd64-windows-tdep.c
@@ -32,6 +32,7 @@
#include "coff/pe.h"
#include "libcoff.h"
#include "value.h"
+#include "inferior.h"
/* The registers used to pass integer arguments during a function call. */
static int amd64_windows_dummy_call_integer_regs[] =
@@ -43,6 +44,64 @@ static int amd64_windows_dummy_call_integer_regs[] =
};
/* Return nonzero if an argument of type TYPE should be passed
+ via one of the XMM registers. */
+
+static int
+amd64_windows_passed_by_xmm_register (struct type *type)
+{
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_TYPEDEF:
+ return (TYPE_TARGET_TYPE (type) != NULL
+ && amd64_windows_passed_by_xmm_register
+ (TYPE_TARGET_TYPE (type)));
+
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ return (TYPE_NFIELDS (type) == 1
+ && amd64_windows_passed_by_xmm_register
+ (TYPE_FIELD_TYPE (type, 0)));
+
+ case TYPE_CODE_FLT:
+ case TYPE_CODE_DECFLOAT:
+ return (TYPE_LENGTH (type) == 4 || TYPE_LENGTH (type) == 8);
+
+ default:
+ return 0;
+ }
+}
+
+/* Return nonzero if an return value of type TYPE should be passed
+ in XMM0 register. */
+
+static int
+amd64_windows_return_in_xmm0_register (struct type *type)
+{
+ if (amd64_windows_passed_by_xmm_register (type))
+ return 1;
+ else
+ {
+ /* __m128, __m128d and __m128i types are returned in $xmm0 also.
+ But they are not stored in XMM registers as arguments,
+ at least not in GCC 4.7.6 x86_64-w64-mingw32 target.
+ Note: The TYPE_VECTOR check should prevent other arrays from
+ being treated as special xmm types.
+ Note: This all works for the "unique" __fastcall calling convention
+ as defined by Microsoft. The newer __vectorcall convention
+ does support passing __m128X type parameters in xmm registers
+ using /Gv option of Microsoft compilers. */
+ struct type *ltype = check_typedef (type);
+
+ return (ltype != NULL
+ && TYPE_CODE (ltype) == TYPE_CODE_ARRAY
+ && (TYPE_CODE (TYPE_TARGET_TYPE (ltype)) == TYPE_CODE_FLT
+ || TYPE_CODE (TYPE_TARGET_TYPE (ltype)) == TYPE_CODE_INT)
+ && TYPE_VECTOR (ltype)
+ && TYPE_LENGTH (ltype) == 16);
+ }
+}
+
+/* Return nonzero if an argument of type TYPE should be passed
via one of the integer registers. */
static int
@@ -50,6 +109,25 @@ amd64_windows_passed_by_integer_register (struct type *type)
{
switch (TYPE_CODE (type))
{
+ case TYPE_CODE_TYPEDEF:
+ return (TYPE_TARGET_TYPE (type) != NULL
+ && amd64_windows_passed_by_integer_register
+ (TYPE_TARGET_TYPE (type)));
+
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ /* If only one field, exclude float type accepted as xmm reg. */
+ if (TYPE_NFIELDS (type) == 1)
+ {
+ struct type *ftype = TYPE_FIELD_TYPE (type, 0);
+
+ if (amd64_windows_passed_by_xmm_register (ftype))
+ return 0;
+ else
+ return amd64_windows_passed_by_integer_register (ftype);
+ }
+ /* Struct/Union with several fields: Pass Through. */
+
case TYPE_CODE_INT:
case TYPE_CODE_ENUM:
case TYPE_CODE_BOOL:
@@ -57,8 +135,7 @@ amd64_windows_passed_by_integer_register (struct type *type)
case TYPE_CODE_CHAR:
case TYPE_CODE_PTR:
case TYPE_CODE_REF:
- case TYPE_CODE_STRUCT:
- case TYPE_CODE_UNION:
+ case TYPE_CODE_COMPLEX:
return (TYPE_LENGTH (type) == 1
|| TYPE_LENGTH (type) == 2
|| TYPE_LENGTH (type) == 4
@@ -69,17 +146,6 @@ amd64_windows_passed_by_integer_register (struct type *type)
}
}
-/* Return nonzero if an argument of type TYPE should be passed
- via one of the XMM registers. */
-
-static int
-amd64_windows_passed_by_xmm_register (struct type *type)
-{
- return ((TYPE_CODE (type) == TYPE_CODE_FLT
- || TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
- && (TYPE_LENGTH (type) == 4 || TYPE_LENGTH (type) == 8));
-}
-
/* Return non-zero iff an argument of the given TYPE should be passed
by pointer. */
@@ -103,7 +169,8 @@ amd64_windows_passed_by_pointer (struct type *type)
the value of each argument. SP is value of the Stack Pointer. */
static CORE_ADDR
-amd64_windows_adjust_args_passed_by_pointer (struct value **args,
+amd64_windows_adjust_args_passed_by_pointer (struct gdbarch *gdbarch,
+ struct value **args,
int nargs, CORE_ADDR sp)
{
int i;
@@ -125,6 +192,10 @@ amd64_windows_adjust_args_passed_by_pointer (struct value **args,
args[i]
= value_addr (value_from_contents_and_address (type, valbuf, sp));
+ if (debug_infrun)
+ printf_filtered ("Parameter #%d, length %d copied on stack"
+ " at address %s, and passed as pointer\n",
+ i, len, paddress (gdbarch, sp));
}
return sp;
@@ -134,8 +205,9 @@ amd64_windows_adjust_args_passed_by_pointer (struct value **args,
REGCACHE is the register cache. */
static void
-amd64_windows_store_arg_in_reg (struct regcache *regcache,
- struct value *arg, int regno)
+amd64_windows_store_arg_in_reg (struct gdbarch *gdbarch,
+ struct regcache *regcache,
+ struct value *arg, int regno, int i)
{
struct type *type = value_type (arg);
const gdb_byte *valbuf = value_contents (arg);
@@ -145,6 +217,10 @@ amd64_windows_store_arg_in_reg (struct regcache *regcache,
memset (buf, 0, sizeof buf);
memcpy (buf, valbuf, min (TYPE_LENGTH (type), 8));
regcache_cooked_write (regcache, regno, buf);
+ if (debug_infrun)
+ printf_filtered ("Parameter #%d, length %d copied to register %s\n",
+ i, TYPE_LENGTH (type),
+ i386_pseudo_register_name(gdbarch, regno));
}
/* Push the arguments for an inferior function call, and return
@@ -154,7 +230,8 @@ amd64_windows_store_arg_in_reg (struct regcache *regcache,
amd64_windows_push_dummy_call. */
static CORE_ADDR
-amd64_windows_push_arguments (struct regcache *regcache, int nargs,
+amd64_windows_push_arguments (struct gdbarch *gdbarch,
+ struct regcache *regcache, int nargs,
struct value **args, CORE_ADDR sp,
int struct_return)
{
@@ -174,7 +251,8 @@ amd64_windows_push_arguments (struct regcache *regcache, int nargs,
struct value **args1 = alloca (nargs * sizeof (struct value *));
memcpy (args1, args, nargs * sizeof (struct value *));
- sp = amd64_windows_adjust_args_passed_by_pointer (args1, nargs, sp);
+ sp = amd64_windows_adjust_args_passed_by_pointer (gdbarch, args1,
+ nargs, sp);
args = args1;
}
@@ -193,20 +271,20 @@ amd64_windows_push_arguments (struct regcache *regcache, int nargs,
if (amd64_windows_passed_by_integer_register (type))
{
amd64_windows_store_arg_in_reg
- (regcache, args[i],
- amd64_windows_dummy_call_integer_regs[reg_idx]);
+ (gdbarch, regcache, args[i],
+ amd64_windows_dummy_call_integer_regs[reg_idx], i);
on_stack_p = 0;
reg_idx++;
}
else if (amd64_windows_passed_by_xmm_register (type))
{
amd64_windows_store_arg_in_reg
- (regcache, args[i], AMD64_XMM0_REGNUM + reg_idx);
+ (gdbarch, regcache, args[i], AMD64_XMM0_REGNUM + reg_idx, i);
/* In case of varargs, these parameters must also be
passed via the integer registers. */
amd64_windows_store_arg_in_reg
- (regcache, args[i],
- amd64_windows_dummy_call_integer_regs[reg_idx]);
+ (gdbarch, regcache, args[i],
+ amd64_windows_dummy_call_integer_regs[reg_idx], i);
on_stack_p = 0;
reg_idx++;
}
@@ -231,6 +309,11 @@ amd64_windows_push_arguments (struct regcache *regcache, int nargs,
const gdb_byte *valbuf = value_contents (stack_args[i]);
write_memory (sp + element * 8, valbuf, TYPE_LENGTH (type));
+ if (debug_infrun)
+ printf_filtered ("Parameter #%d, length %d copied on stack"
+ " at address %s\n",
+ i, TYPE_LENGTH (type),
+ paddress (gdbarch, sp + element * 8));
element += ((TYPE_LENGTH (type) + 7) / 8);
}
@@ -250,7 +333,7 @@ amd64_windows_push_dummy_call
gdb_byte buf[8];
/* Pass arguments. */
- sp = amd64_windows_push_arguments (regcache, nargs, args, sp,
+ sp = amd64_windows_push_arguments (gdbarch, regcache, nargs, args, sp,
struct_return);
/* Pass "hidden" argument". */
@@ -295,21 +378,12 @@ amd64_windows_return_value (struct gdbarch *gdbarch, struct value *function,
/* See if our value is returned through a register. If it is, then
store the associated register number in REGNUM. */
- switch (TYPE_CODE (type))
+ if (amd64_windows_return_in_xmm0_register (type))
+ regnum = AMD64_XMM0_REGNUM;
+ else if (len == 1 || len == 2 || len == 4 || len == 8)
{
- case TYPE_CODE_FLT:
- case TYPE_CODE_DECFLOAT:
- /* __m128, __m128i, __m128d, floats, and doubles are returned
- via XMM0. */
- if (len == 4 || len == 8 || len == 16)
- regnum = AMD64_XMM0_REGNUM;
- break;
- default:
- /* All other values that are 1, 2, 4 or 8 bytes long are returned
- via RAX. */
- if (len == 1 || len == 2 || len == 4 || len == 8)
- regnum = AMD64_RAX_REGNUM;
- break;
+ /* All values of this size are returned via RAX. */
+ regnum = AMD64_RAX_REGNUM;
}
if (regnum < 0)
@@ -322,8 +396,10 @@ amd64_windows_return_value (struct gdbarch *gdbarch, struct value *function,
regcache_raw_read_unsigned (regcache, AMD64_RAX_REGNUM, &addr);
read_memory (addr, readbuf, TYPE_LENGTH (type));
}
+ if (debug_infrun)
+ printf_filtered ("Return value as memory address in RAX\n");
return RETURN_VALUE_ABI_RETURNS_ADDRESS;
- }
+ }
else
{
/* Extract the return value from the register where it was stored. */
@@ -331,6 +407,9 @@ amd64_windows_return_value (struct gdbarch *gdbarch, struct value *function,
regcache_raw_read_part (regcache, regnum, 0, len, readbuf);
if (writebuf)
regcache_raw_write_part (regcache, regnum, 0, len, writebuf);
+ if (debug_infrun)
+ printf_filtered ("Return value in register %s\n",
+ gdbarch_register_name (gdbarch, regnum));
return RETURN_VALUE_REGISTER_CONVENTION;
}
}
--
1.6.6.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* [commit 4/4] Revert use of classify callback in i386 gdbarch_tdep.
2013-09-24 16:33 ` Joel Brobecker
@ 2013-09-24 16:33 ` Joel Brobecker
2013-09-24 16:33 ` [commit 1/4] Reimplement function calls on amd64-windows Joel Brobecker
` (4 subsequent siblings)
5 siblings, 0 replies; 18+ messages in thread
From: Joel Brobecker @ 2013-09-24 16:33 UTC (permalink / raw)
To: gdb-patches; +Cc: Pierre Muller, Mark Kettenis
This is no longer useful, as it was introduced to reuse the funcall
handling code in amd64-tdep.c in the context of x64-windows. But
we have since then changed the implementations to be completely
independent of each other.
This reverts the non-windows-specific part of the change called:
amd64: Integer parameters in function calls on Windows
(the x64-windows portion has already been reverted)
gdb/ChangeLog:
Revert:
* i386-tdep.h (enum amd64_reg_class): New, moved here from
amd64-tdep.c.
(struct gdbarch_tdep): Add fields call_dummy_num_integer_regs,
call_dummy_integer_regs, and classify.
* amd64-tdep.h (amd64_classify): Add declaration.
* amd64-tdep.c (amd64_dummy_call_integer_regs): New static constant.
(amd64_reg_class): Delete, moved to i386-tdep.h.
(amd64_classify): Make non-static. Move declaration to amd64-tdep.h.
Replace call to amd64_classify by call to tdep->classify.
(amd64_push_arguments): Get the list of registers to use for
passing integer parameters from the gdbarch tdep structure,
rather than using a hardcoded one. Replace calls to amd64_classify
by calls to tdep->classify.
(amd64_push_dummy_call): Get the register number used for
the "hidden" argument from tdep->call_dummy_integer_regs.
(amd64_init_abi): Initialize tdep->call_dummy_num_integer_regs
and tdep->call_dummy_integer_regs. Set tdep->classify.
Tested on x86_64-linux, checked in.
---
gdb/ChangeLog | 21 ++++++++++++++++++
gdb/amd64-tdep.c | 65 +++++++++++++++++++++++++++-----------------------------
gdb/amd64-tdep.h | 4 ----
gdb/i386-tdep.h | 24 ---------------------
4 files changed, 52 insertions(+), 62 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index cd03e31..9d42eec 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,6 +1,27 @@
2013-09-24 Joel Brobecker <brobecker@adacore.com>
Revert:
+ * i386-tdep.h (enum amd64_reg_class): New, moved here from
+ amd64-tdep.c.
+ (struct gdbarch_tdep): Add fields call_dummy_num_integer_regs,
+ call_dummy_integer_regs, and classify.
+ * amd64-tdep.h (amd64_classify): Add declaration.
+ * amd64-tdep.c (amd64_dummy_call_integer_regs): New static constant.
+ (amd64_reg_class): Delete, moved to i386-tdep.h.
+ (amd64_classify): Make non-static. Move declaration to amd64-tdep.h.
+ Replace call to amd64_classify by call to tdep->classify.
+ (amd64_push_arguments): Get the list of registers to use for
+ passing integer parameters from the gdbarch tdep structure,
+ rather than using a hardcoded one. Replace calls to amd64_classify
+ by calls to tdep->classify.
+ (amd64_push_dummy_call): Get the register number used for
+ the "hidden" argument from tdep->call_dummy_integer_regs.
+ (amd64_init_abi): Initialize tdep->call_dummy_num_integer_regs
+ and tdep->call_dummy_integer_regs. Set tdep->classify.
+
+2013-09-24 Joel Brobecker <brobecker@adacore.com>
+
+ Revert:
* 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.
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index 35526cf..37218ce 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -92,17 +92,6 @@ static const char *amd64_ymmh_names[] =
"ymm12h", "ymm13h", "ymm14h", "ymm15h"
};
-/* The registers used to pass integer arguments during a function call. */
-static int amd64_dummy_call_integer_regs[] =
-{
- AMD64_RDI_REGNUM, /* %rdi */
- AMD64_RSI_REGNUM, /* %rsi */
- AMD64_RDX_REGNUM, /* %rdx */
- AMD64_RCX_REGNUM, /* %rcx */
- 8, /* %r8 */
- 9 /* %r9 */
-};
-
/* DWARF Register Number Mapping as defined in the System V psABI,
section 3.6. */
@@ -391,6 +380,20 @@ amd64_pseudo_register_write (struct gdbarch *gdbarch,
\f
+/* Register classes as defined in the psABI. */
+
+enum amd64_reg_class
+{
+ AMD64_INTEGER,
+ AMD64_SSE,
+ AMD64_SSEUP,
+ AMD64_X87,
+ AMD64_X87UP,
+ AMD64_COMPLEX_X87,
+ AMD64_NO_CLASS,
+ AMD64_MEMORY
+};
+
/* Return the union class of CLASS1 and CLASS2. See the psABI for
details. */
@@ -427,6 +430,8 @@ amd64_merge_classes (enum amd64_reg_class class1, enum amd64_reg_class class2)
return AMD64_SSE;
}
+static void amd64_classify (struct type *type, enum amd64_reg_class class[2]);
+
/* Return non-zero if TYPE is a non-POD structure or union type. */
static int
@@ -546,7 +551,7 @@ amd64_classify_aggregate (struct type *type, enum amd64_reg_class class[2])
/* Classify TYPE, and store the result in CLASS. */
-void
+static void
amd64_classify (struct type *type, enum amd64_reg_class class[2])
{
enum type_code code = TYPE_CODE (type);
@@ -614,7 +619,6 @@ amd64_return_value (struct gdbarch *gdbarch, struct value *function,
struct type *type, struct regcache *regcache,
gdb_byte *readbuf, const gdb_byte *writebuf)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
enum amd64_reg_class class[2];
int len = TYPE_LENGTH (type);
static int integer_regnum[] = { AMD64_RAX_REGNUM, AMD64_RDX_REGNUM };
@@ -624,10 +628,9 @@ amd64_return_value (struct gdbarch *gdbarch, struct value *function,
int i;
gdb_assert (!(readbuf && writebuf));
- gdb_assert (tdep->classify);
/* 1. Classify the return type with the classification algorithm. */
- tdep->classify (type, class);
+ amd64_classify (type, class);
/* 2. If the type has class MEMORY, then the caller provides space
for the return value and passes the address of this storage in
@@ -749,10 +752,15 @@ 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));
- int *integer_regs = tdep->call_dummy_integer_regs;
- int num_integer_regs = tdep->call_dummy_num_integer_regs;
-
+ static int integer_regnum[] =
+ {
+ AMD64_RDI_REGNUM, /* %rdi */
+ AMD64_RSI_REGNUM, /* %rsi */
+ AMD64_RDX_REGNUM, /* %rdx */
+ AMD64_RCX_REGNUM, /* %rcx */
+ 8, /* %r8 */
+ 9 /* %r9 */
+ };
static int sse_regnum[] =
{
/* %xmm0 ... %xmm7 */
@@ -769,8 +777,6 @@ amd64_push_arguments (struct regcache *regcache, int nargs,
int sse_reg = 0;
int i;
- gdb_assert (tdep->classify);
-
/* Reserve a register for the "hidden" argument. */
if (struct_return)
integer_reg++;
@@ -785,7 +791,7 @@ amd64_push_arguments (struct regcache *regcache, int nargs,
int j;
/* Classify argument. */
- tdep->classify (type, class);
+ amd64_classify (type, class);
/* Calculate the number of integer and SSE registers needed for
this argument. */
@@ -799,7 +805,7 @@ amd64_push_arguments (struct regcache *regcache, int nargs,
/* Check whether enough registers are available, and if the
argument should be passed in registers at all. */
- if (integer_reg + needed_integer_regs > num_integer_regs
+ if (integer_reg + needed_integer_regs > ARRAY_SIZE (integer_regnum)
|| sse_reg + needed_sse_regs > ARRAY_SIZE (sse_regnum)
|| (needed_integer_regs == 0 && needed_sse_regs == 0))
{
@@ -823,7 +829,7 @@ amd64_push_arguments (struct regcache *regcache, int nargs,
switch (class[j])
{
case AMD64_INTEGER:
- regnum = integer_regs[integer_reg++];
+ regnum = integer_regnum[integer_reg++];
break;
case AMD64_SSE:
@@ -881,7 +887,6 @@ amd64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
int struct_return, CORE_ADDR struct_addr)
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
gdb_byte buf[8];
/* Pass arguments. */
@@ -890,12 +895,8 @@ amd64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
/* Pass "hidden" argument". */
if (struct_return)
{
- /* The "hidden" argument is passed throught the first argument
- register. */
- const int arg_regnum = tdep->call_dummy_integer_regs[0];
-
store_unsigned_integer (buf, 8, byte_order, struct_addr);
- regcache_cooked_write (regcache, arg_regnum, buf);
+ regcache_cooked_write (regcache, AMD64_RDI_REGNUM, buf);
}
/* Store return address. */
@@ -2888,10 +2889,6 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_push_dummy_call (gdbarch, amd64_push_dummy_call);
set_gdbarch_frame_align (gdbarch, amd64_frame_align);
set_gdbarch_frame_red_zone_size (gdbarch, 128);
- tdep->call_dummy_num_integer_regs =
- ARRAY_SIZE (amd64_dummy_call_integer_regs);
- tdep->call_dummy_integer_regs = amd64_dummy_call_integer_regs;
- tdep->classify = amd64_classify;
set_gdbarch_convert_register_p (gdbarch, i387_convert_register_p);
set_gdbarch_register_to_value (gdbarch, i387_register_to_value);
diff --git a/gdb/amd64-tdep.h b/gdb/amd64-tdep.h
index a33e7d6..265e535 100644
--- a/gdb/amd64-tdep.h
+++ b/gdb/amd64-tdep.h
@@ -103,13 +103,9 @@ extern void amd64_supply_xsave (struct regcache *regcache, int regnum,
extern void amd64_collect_fxsave (const struct regcache *regcache, int regnum,
void *fxsave);
-
/* Similar to amd64_collect_fxsave, but use XSAVE extended state. */
extern void amd64_collect_xsave (const struct regcache *regcache,
int regnum, void *xsave, int gcore);
-
-void amd64_classify (struct type *type, enum amd64_reg_class class[2]);
-
\f
/* Variables exported from amd64-linux-tdep.c. */
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index 0c408fa..092744c 100644
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -52,20 +52,6 @@ enum struct_return
reg_struct_return /* Return "short" structures in registers. */
};
-/* Register classes as defined in the AMD x86-64 psABI. */
-
-enum amd64_reg_class
-{
- AMD64_INTEGER,
- AMD64_SSE,
- AMD64_SSEUP,
- AMD64_X87,
- AMD64_X87UP,
- AMD64_COMPLEX_X87,
- AMD64_NO_CLASS,
- AMD64_MEMORY
-};
-
/* i386 architecture specific information. */
struct gdbarch_tdep
{
@@ -75,16 +61,6 @@ struct gdbarch_tdep
int gregset_num_regs;
size_t sizeof_gregset;
- /* The general-purpose registers used to pass integers when making
- function calls. This only applies to amd64, as all parameters
- are passed through the stack on x86. */
- int call_dummy_num_integer_regs;
- int *call_dummy_integer_regs;
-
- /* Classify TYPE according to calling conventions, and store
- the result in CLASS. Used on amd64 only. */
- void (*classify) (struct type *type, enum amd64_reg_class class[2]);
-
/* Floating-point registers. */
struct regset *fpregset;
size_t sizeof_fpregset;
--
1.8.1.2
^ permalink raw reply [flat|nested] 18+ messages in thread
* [commit 2/4] Revert use of integer_param_regs_saved_in_caller_frame in i386 gdbarch_tdep.
2013-09-24 16:33 ` Joel Brobecker
` (2 preceding siblings ...)
2013-09-24 16:33 ` [commit 3/4] Revert use of memory_args_by_pointer in i386 gdbarch_tdep Joel Brobecker
@ 2013-09-24 16:33 ` Joel Brobecker
2013-09-24 16:53 ` [RFC-v2] amd64-windows: Fix funcall with by-pointer arguments Mark Kettenis
2013-09-24 22:02 ` Pierre Muller
5 siblings, 0 replies; 18+ messages in thread
From: Joel Brobecker @ 2013-09-24 16:33 UTC (permalink / raw)
To: gdb-patches; +Cc: Pierre Muller, Mark Kettenis
This is no longer useful, as it was introduced to reuse the funcall
handling code in amd64-tdep.c in the context of x64-windows. But
we have since then changed the implementations to be completely
independent of each other.
This reverts the non-windows-specific part of the change called:
amd64-windows: 32 bytes allocated on stack by caller for integer
parameter regs
(the x64-windows portion has already been reverted)
gdb/ChangeLog:
Revert:
* i386-tdep.h (struct gdbarch_tdep): Add new field
integer_param_regs_saved_in_caller_frame.
* amd64-tdep.c (amd64_push_dummy_call): Allocate some memory on
stack if tdep->integer_param_regs_saved_in_caller_frame is set.
Tested on x86_64-linux, checked in.
---
gdb/ChangeLog | 8 ++++++++
gdb/amd64-tdep.c | 5 -----
gdb/i386-tdep.h | 18 ++++--------------
3 files changed, 12 insertions(+), 19 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 71602a0..1977ff0 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,13 @@
2013-09-24 Joel Brobecker <brobecker@adacore.com>
+ Revert:
+ * i386-tdep.h (struct gdbarch_tdep): Add new field
+ integer_param_regs_saved_in_caller_frame.
+ * amd64-tdep.c (amd64_push_dummy_call): Allocate some memory on
+ stack if tdep->integer_param_regs_saved_in_caller_frame is set.
+
+2013-09-24 Joel Brobecker <brobecker@adacore.com>
+
* amd64-tdep.c: #include "value.h"
(amd64_windows_classify): Delete.
(amd64_windows_passed_by_integer_register)
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index 3ab74f0..ec6bfc6 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -926,11 +926,6 @@ amd64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
regcache_cooked_write (regcache, arg_regnum, buf);
}
- /* Reserve some memory on the stack for the integer-parameter registers,
- if required by the ABI. */
- if (tdep->integer_param_regs_saved_in_caller_frame)
- sp -= tdep->call_dummy_num_integer_regs * 8;
-
/* Store return address. */
sp -= 8;
store_unsigned_integer (buf, 8, byte_order, bp_addr);
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index 69bd281..8113dcc 100644
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -81,12 +81,12 @@ struct gdbarch_tdep
int call_dummy_num_integer_regs;
int *call_dummy_integer_regs;
- /* Used on amd64 only. Classify TYPE according to calling conventions,
- and store the result in CLASS. */
+ /* Classify TYPE according to calling conventions, and store
+ the result in CLASS. Used on amd64 only. */
void (*classify) (struct type *type, enum amd64_reg_class class[2]);
- /* Used on amd64 only. Non-zero if the first few MEMORY arguments
- should be passed by pointer.
+ /* 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
@@ -94,16 +94,6 @@ struct gdbarch_tdep
available for argument passing. */
int memory_args_by_pointer;
- /* Used on amd64 only.
-
- If non-zero, then the callers of a function are expected to reserve
- some space in the stack just before the area where the PC is saved
- so that the callee may save the integer-parameter registers there.
- The amount of space is dependent on the list of registers used for
- integer parameter passing (see component call_dummy_num_integer_regs
- above). */
- int integer_param_regs_saved_in_caller_frame;
-
/* Floating-point registers. */
struct regset *fpregset;
size_t sizeof_fpregset;
--
1.8.1.2
^ permalink raw reply [flat|nested] 18+ messages in thread
* [commit 3/4] Revert use of memory_args_by_pointer in i386 gdbarch_tdep.
2013-09-24 16:33 ` Joel Brobecker
2013-09-24 16:33 ` [commit 4/4] Revert use of classify callback in i386 gdbarch_tdep Joel Brobecker
2013-09-24 16:33 ` [commit 1/4] Reimplement function calls on amd64-windows Joel Brobecker
@ 2013-09-24 16:33 ` Joel Brobecker
2013-09-24 16:33 ` [commit 2/4] Revert use of integer_param_regs_saved_in_caller_frame " Joel Brobecker
` (2 subsequent siblings)
5 siblings, 0 replies; 18+ messages in thread
From: Joel Brobecker @ 2013-09-24 16:33 UTC (permalink / raw)
To: gdb-patches; +Cc: Pierre Muller, Mark Kettenis
This is no longer useful, as it was introduced to reuse the funcall
handling code in amd64-tdep.c in the context of x64-windows. But
we have since then changed the implementations to be completely
independent of each other.
This reverts the non-windows-specific part of the change called:
amd64-windows: memory args passed by pointer during function calls.
(the x64-windows portion has already been reverted)
gdb/ChangeLog:
Revert:
* 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.
Tested on x86_64-linux, checked in.
---
gdb/ChangeLog | 7 +++++++
gdb/amd64-tdep.c | 40 ++++++----------------------------------
gdb/i386-tdep.h | 9 ---------
3 files changed, 13 insertions(+), 43 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 1977ff0..cd03e31 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,6 +1,13 @@
2013-09-24 Joel Brobecker <brobecker@adacore.com>
Revert:
+ * 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.
+
+2013-09-24 Joel Brobecker <brobecker@adacore.com>
+
+ Revert:
* i386-tdep.h (struct gdbarch_tdep): Add new field
integer_param_regs_saved_in_caller_frame.
* amd64-tdep.c (amd64_push_dummy_call): Allocate some memory on
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index ec6bfc6..35526cf 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -749,8 +749,7 @@ static CORE_ADDR
amd64_push_arguments (struct regcache *regcache, int nargs,
struct value **args, CORE_ADDR sp, int struct_return)
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
int *integer_regs = tdep->call_dummy_integer_regs;
int num_integer_regs = tdep->call_dummy_num_integer_regs;
@@ -763,11 +762,6 @@ 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;
@@ -811,19 +805,7 @@ 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];
- /* 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++;
+ stack_args[num_stack_args++] = args[i];
}
else
{
@@ -878,20 +860,10 @@ 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]);
- CORE_ADDR arg_addr = sp + element * 8;
-
- write_memory (arg_addr, valbuf, TYPE_LENGTH (type));
- 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 += ((TYPE_LENGTH (type) + 7) / 8);
+ int len = TYPE_LENGTH (type);
+
+ write_memory (sp + element * 8, valbuf, len);
+ element += ((len + 7) / 8);
}
/* The psABI says that "For calls that may call functions that use
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index 8113dcc..0c408fa 100644
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -85,15 +85,6 @@ 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;
--
1.8.1.2
^ permalink raw reply [flat|nested] 18+ messages in thread
* [commit 1/4] Reimplement function calls on amd64-windows
2013-09-24 16:33 ` Joel Brobecker
2013-09-24 16:33 ` [commit 4/4] Revert use of classify callback in i386 gdbarch_tdep Joel Brobecker
@ 2013-09-24 16:33 ` Joel Brobecker
2013-09-24 17:26 ` fixed ChangeLog: " Joel Brobecker
2013-09-24 16:33 ` [commit 3/4] Revert use of memory_args_by_pointer in i386 gdbarch_tdep Joel Brobecker
` (3 subsequent siblings)
5 siblings, 1 reply; 18+ messages in thread
From: Joel Brobecker @ 2013-09-24 16:33 UTC (permalink / raw)
To: gdb-patches; +Cc: Pierre Muller, Mark Kettenis
This patch provides a standalone implementation of function calls
on amd64-windows, instead of providing some bits and pieces hooking
into the function call implementation meant for sysV (in amd64-tdep).
It makes better sense to do it this way, because the two ABIs are
actually very different; for instance, the concept of argument
classification, which is so central in the sysV ABI and drove the
the implementation in amd64-tdep, makes no sense for Windows. It
is therefore better for the Windows implementation to be completely
separate, rather than rely on adaptations of the sysV implementation.
gdb/ChangeLog:
* amd64-tdep.c: #include "value.h"
(amd64_windows_classify): Delete.
(amd64_windows_passed_by_integer_register)
(amd64_windows_passed_by_xmm_register)
(amd64_windows_passed_by_pointer)
(amd64_windows_adjust_args_passed_by_pointer)
(amd64_windows_store_arg_in_reg, amd64_windows_push_arguments)
(amd64_windows_push_dummy_call): New functions.
(amd64_windows_init_abi): Remove setting of
tdep->call_dummy_num_integer_regs, tdep->call_dummy_integer_regs,
tdep->classify, tdep->memory_args_by_pointer and
tdep->integer_param_regs_saved_in_caller_frame.
Add call to set_gdbarch_push_dummy_call.
Tested on amd64-windows. Checked in.
---
gdb/ChangeLog | 16 +++
gdb/amd64-windows-tdep.c | 264 +++++++++++++++++++++++++++++++++++++++++------
2 files changed, 248 insertions(+), 32 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 872baed..71602a0 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,19 @@
+2013-09-24 Joel Brobecker <brobecker@adacore.com>
+
+ * amd64-tdep.c: #include "value.h"
+ (amd64_windows_classify): Delete.
+ (amd64_windows_passed_by_integer_register)
+ (amd64_windows_passed_by_xmm_register)
+ (amd64_windows_passed_by_pointer)
+ (amd64_windows_adjust_args_passed_by_pointer)
+ (amd64_windows_store_arg_in_reg, amd64_windows_push_arguments)
+ (amd64_windows_push_dummy_call): New functions.
+ (amd64_windows_init_abi): Remove setting of
+ tdep->call_dummy_num_integer_regs, tdep->call_dummy_integer_regs,
+ tdep->classify, tdep->memory_args_by_pointer and
+ tdep->integer_param_regs_saved_in_caller_frame.
+ Add call to set_gdbarch_push_dummy_call.
+
2013-09-24 Jan Kratochvil <jan.kratochvil@redhat.com>
* dwarf2read.c (open_and_init_dwp_file): Try open_dwp_file also with
diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c
index 4e750a1..c09262a 100644
--- a/gdb/amd64-windows-tdep.c
+++ b/gdb/amd64-windows-tdep.c
@@ -31,6 +31,7 @@
#include "coff/i386.h"
#include "coff/pe.h"
#include "libcoff.h"
+#include "value.h"
/* The registers used to pass integer arguments during a function call. */
static int amd64_windows_dummy_call_integer_regs[] =
@@ -41,43 +42,247 @@ static int amd64_windows_dummy_call_integer_regs[] =
9 /* %r9 */
};
-/* Implement the "classify" method in the gdbarch_tdep structure
- for amd64-windows. */
+/* Return nonzero if an argument of type TYPE should be passed
+ via one of the integer registers. */
-static void
-amd64_windows_classify (struct type *type, enum amd64_reg_class class[2])
+static int
+amd64_windows_passed_by_integer_register (struct type *type)
{
switch (TYPE_CODE (type))
{
- case TYPE_CODE_ARRAY:
- /* Arrays are always passed by memory. */
- class[0] = class[1] = AMD64_MEMORY;
- break;
-
+ case TYPE_CODE_INT:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_REF:
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
- /* Struct/Union types whose size is 1, 2, 4, or 8 bytes
- are passed as if they were integers of the same size.
- Types of different sizes are passed by memory. */
- if (TYPE_LENGTH (type) == 1
- || TYPE_LENGTH (type) == 2
- || TYPE_LENGTH (type) == 4
- || TYPE_LENGTH (type) == 8)
- {
- class[0] = AMD64_INTEGER;
- class[1] = AMD64_NO_CLASS;
- }
- else
- class[0] = class[1] = AMD64_MEMORY;
- break;
+ return (TYPE_LENGTH (type) == 1
+ || TYPE_LENGTH (type) == 2
+ || TYPE_LENGTH (type) == 4
+ || TYPE_LENGTH (type) == 8);
default:
- /* For all the other types, the conventions are the same as
- with the System V ABI. */
- amd64_classify (type, class);
+ return 0;
}
}
+/* Return nonzero if an argument of type TYPE should be passed
+ via one of the XMM registers. */
+
+static int
+amd64_windows_passed_by_xmm_register (struct type *type)
+{
+ return ((TYPE_CODE (type) == TYPE_CODE_FLT
+ || TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
+ && (TYPE_LENGTH (type) == 4 || TYPE_LENGTH (type) == 8));
+}
+
+/* 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)
+{
+ if (amd64_windows_passed_by_integer_register (type))
+ return 0;
+
+ if (amd64_windows_passed_by_xmm_register (type))
+ return 0;
+
+ return 1;
+}
+
+/* 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. */
+
+static CORE_ADDR
+amd64_windows_adjust_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;
+}
+
+/* Store the value of ARG in register REGNO (right-justified).
+ REGCACHE is the register cache. */
+
+static void
+amd64_windows_store_arg_in_reg (struct regcache *regcache,
+ struct value *arg, int regno)
+{
+ struct type *type = value_type (arg);
+ const gdb_byte *valbuf = value_contents (arg);
+ gdb_byte buf[8];
+
+ gdb_assert (TYPE_LENGTH (type) <= 8);
+ memset (buf, 0, sizeof buf);
+ memcpy (buf, valbuf, min (TYPE_LENGTH (type), 8));
+ regcache_cooked_write (regcache, regno, buf);
+}
+
+/* Push the arguments for an inferior function call, and return
+ the updated value of the SP (Stack Pointer).
+
+ All arguments are identical to the arguments used in
+ amd64_windows_push_dummy_call. */
+
+static CORE_ADDR
+amd64_windows_push_arguments (struct regcache *regcache, int nargs,
+ struct value **args, CORE_ADDR sp,
+ int struct_return)
+{
+ int reg_idx = 0;
+ int i;
+ struct value **stack_args = alloca (nargs * sizeof (struct value *));
+ int num_stack_args = 0;
+ int num_elements = 0;
+ int element = 0;
+
+ /* First, handle the arguments passed by pointer.
+
+ These arguments are replaced by pointers to a copy we are making
+ in inferior memory. So use a copy of the ARGS table, to avoid
+ modifying the original one. */
+ {
+ struct value **args1 = alloca (nargs * sizeof (struct value *));
+
+ memcpy (args1, args, nargs * sizeof (struct value *));
+ sp = amd64_windows_adjust_args_passed_by_pointer (args1, nargs, sp);
+ args = args1;
+ }
+
+ /* Reserve a register for the "hidden" argument. */
+ if (struct_return)
+ reg_idx++;
+
+ for (i = 0; i < nargs; i++)
+ {
+ struct type *type = value_type (args[i]);
+ int len = TYPE_LENGTH (type);
+ int on_stack_p = 1;
+
+ if (reg_idx < ARRAY_SIZE (amd64_windows_dummy_call_integer_regs))
+ {
+ if (amd64_windows_passed_by_integer_register (type))
+ {
+ amd64_windows_store_arg_in_reg
+ (regcache, args[i],
+ amd64_windows_dummy_call_integer_regs[reg_idx]);
+ on_stack_p = 0;
+ reg_idx++;
+ }
+ else if (amd64_windows_passed_by_xmm_register (type))
+ {
+ amd64_windows_store_arg_in_reg
+ (regcache, args[i], AMD64_XMM0_REGNUM + reg_idx);
+ /* In case of varargs, these parameters must also be
+ passed via the integer registers. */
+ amd64_windows_store_arg_in_reg
+ (regcache, args[i],
+ amd64_windows_dummy_call_integer_regs[reg_idx]);
+ on_stack_p = 0;
+ reg_idx++;
+ }
+ }
+
+ if (on_stack_p)
+ {
+ num_elements += ((len + 7) / 8);
+ stack_args[num_stack_args++] = args[i];
+ }
+ }
+
+ /* Allocate space for the arguments on the stack, keeping it
+ aligned on a 16 byte boundary. */
+ sp -= num_elements * 8;
+ sp &= ~0xf;
+
+ /* Write out the arguments to the stack. */
+ for (i = 0; i < num_stack_args; i++)
+ {
+ struct type *type = value_type (stack_args[i]);
+ const gdb_byte *valbuf = value_contents (stack_args[i]);
+
+ write_memory (sp + element * 8, valbuf, TYPE_LENGTH (type));
+ element += ((TYPE_LENGTH (type) + 7) / 8);
+ }
+
+ return sp;
+}
+
+/* Implement the "push_dummy_call" gdbarch method. */
+
+static CORE_ADDR
+amd64_windows_push_dummy_call
+ (struct gdbarch *gdbarch, struct value *function,
+ struct regcache *regcache, CORE_ADDR bp_addr,
+ int nargs, struct value **args,
+ CORE_ADDR sp, int struct_return, CORE_ADDR struct_addr)
+{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ gdb_byte buf[8];
+
+ /* Pass arguments. */
+ sp = amd64_windows_push_arguments (regcache, nargs, args, sp,
+ struct_return);
+
+ /* Pass "hidden" argument". */
+ if (struct_return)
+ {
+ /* The "hidden" argument is passed throught the first argument
+ register. */
+ const int arg_regnum = amd64_windows_dummy_call_integer_regs[0];
+
+ store_unsigned_integer (buf, 8, byte_order, struct_addr);
+ regcache_cooked_write (regcache, arg_regnum, buf);
+ }
+
+ /* Reserve some memory on the stack for the integer-parameter
+ registers, as required by the ABI. */
+ sp -= ARRAY_SIZE (amd64_windows_dummy_call_integer_regs) * 8;
+
+ /* Store return address. */
+ sp -= 8;
+ store_unsigned_integer (buf, 8, byte_order, bp_addr);
+ write_memory (sp, buf, 8);
+
+ /* Update the stack pointer... */
+ store_unsigned_integer (buf, 8, byte_order, sp);
+ regcache_cooked_write (regcache, AMD64_RSP_REGNUM, buf);
+
+ /* ...and fake a frame pointer. */
+ regcache_cooked_write (regcache, AMD64_RBP_REGNUM, buf);
+
+ return sp + 16;
+}
+
/* Implement the "return_value" gdbarch method for amd64-windows. */
static enum return_value_convention
@@ -976,12 +1181,7 @@ amd64_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_long_bit (gdbarch, 32);
/* Function calls. */
- 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->classify = amd64_windows_classify;
- tdep->memory_args_by_pointer = 1;
- tdep->integer_param_regs_saved_in_caller_frame = 1;
+ set_gdbarch_push_dummy_call (gdbarch, amd64_windows_push_dummy_call);
set_gdbarch_return_value (gdbarch, amd64_windows_return_value);
set_gdbarch_skip_main_prologue (gdbarch, amd64_skip_main_prologue);
set_gdbarch_skip_trampoline_code (gdbarch,
--
1.8.1.2
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC-v2] amd64-windows: Fix funcall with by-pointer arguments
2013-09-20 23:20 ` Joel Brobecker
@ 2013-09-24 16:33 ` Joel Brobecker
2013-09-24 16:33 ` [commit 4/4] Revert use of classify callback in i386 gdbarch_tdep Joel Brobecker
` (5 more replies)
0 siblings, 6 replies; 18+ messages in thread
From: Joel Brobecker @ 2013-09-24 16:33 UTC (permalink / raw)
To: gdb-patches; +Cc: Pierre Muller, Mark Kettenis
Hello,
> Once again, I'm short of time to finish what I had hoped to be able
> to complete. But I thought I'd send an update anyway. The first patch
> is an update to the patch I wrote in January, rebased for today's HEAD.
> This is what I have tested and intend to check in soon.
>
> Left to do on my end, is clean things up in amd64-tdep, because many
> hooks in the tdep structure can now be removed, and replaced by
> direct calls. But this is independent of your changes, so we can
> both work at the same time.
I have now checked in the patch re-implementing function call on
amd64-windows. After this was done, I was able to revert all changes
that added hooks in the gdbarch_tdep and in the amd64 sysV code
to tweak it for amd64-windows, since the two implementations are
now completely distinct.
All patches were tested on x86_64-linux and x86_64-windows.
And just in case, I tested them on x86-windows as well.
Thanks,
--
Joel
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC-v2] amd64-windows: Fix funcall with by-pointer arguments
2013-09-24 16:33 ` Joel Brobecker
` (3 preceding siblings ...)
2013-09-24 16:33 ` [commit 2/4] Revert use of integer_param_regs_saved_in_caller_frame " Joel Brobecker
@ 2013-09-24 16:53 ` Mark Kettenis
2013-09-24 22:02 ` Pierre Muller
5 siblings, 0 replies; 18+ messages in thread
From: Mark Kettenis @ 2013-09-24 16:53 UTC (permalink / raw)
To: brobecker; +Cc: gdb-patches
> From: Joel Brobecker <brobecker@adacore.com>
> Date: Tue, 24 Sep 2013 09:33:20 -0700
>
> Hello,
>
> > Once again, I'm short of time to finish what I had hoped to be able
> > to complete. But I thought I'd send an update anyway. The first patch
> > is an update to the patch I wrote in January, rebased for today's HEAD.
> > This is what I have tested and intend to check in soon.
> >
> > Left to do on my end, is clean things up in amd64-tdep, because many
> > hooks in the tdep structure can now be removed, and replaced by
> > direct calls. But this is independent of your changes, so we can
> > both work at the same time.
>
> I have now checked in the patch re-implementing function call on
> amd64-windows. After this was done, I was able to revert all changes
> that added hooks in the gdbarch_tdep and in the amd64 sysV code
> to tweak it for amd64-windows, since the two implementations are
> now completely distinct.
>
> All patches were tested on x86_64-linux and x86_64-windows.
> And just in case, I tested them on x86-windows as well.
Thanks a bunch Joel!
^ permalink raw reply [flat|nested] 18+ messages in thread
* fixed ChangeLog: [commit 1/4] Reimplement function calls on amd64-windows
2013-09-24 16:33 ` [commit 1/4] Reimplement function calls on amd64-windows Joel Brobecker
@ 2013-09-24 17:26 ` Joel Brobecker
0 siblings, 0 replies; 18+ messages in thread
From: Joel Brobecker @ 2013-09-24 17:26 UTC (permalink / raw)
To: gdb-patches; +Cc: Pierre Muller
> gdb/ChangeLog:
>
> * amd64-tdep.c: #include "value.h"
> (amd64_windows_classify): Delete.
Ooops, Pierre correctly pointed out privately that the name of the file
in the ChangeLog was incorrect. I just checked in a change. It now
reads:
* amd64-windows-tdep.c: #include "value.h"
(amd64_windows_classify): Delete.
(amd64_windows_passed_by_integer_register)
(amd64_windows_passed_by_xmm_register)
(amd64_windows_passed_by_pointer)
(amd64_windows_adjust_args_passed_by_pointer)
(amd64_windows_store_arg_in_reg, amd64_windows_push_arguments)
(amd64_windows_push_dummy_call): New functions.
(amd64_windows_init_abi): Remove setting of
tdep->call_dummy_num_integer_regs, tdep->call_dummy_integer_regs,
tdep->classify, tdep->memory_args_by_pointer and
tdep->integer_param_regs_saved_in_caller_frame.
Add call to set_gdbarch_push_dummy_call.
Thank you, Pierre!
--
Joel
^ permalink raw reply [flat|nested] 18+ messages in thread
* RE: [RFC-v2] amd64-windows: Fix funcall with by-pointer arguments
2013-09-24 16:33 ` Joel Brobecker
` (4 preceding siblings ...)
2013-09-24 16:53 ` [RFC-v2] amd64-windows: Fix funcall with by-pointer arguments Mark Kettenis
@ 2013-09-24 22:02 ` Pierre Muller
2013-09-26 0:34 ` Joel Brobecker
5 siblings, 1 reply; 18+ messages in thread
From: Pierre Muller @ 2013-09-24 22:02 UTC (permalink / raw)
To: 'Joel Brobecker', gdb-patches; +Cc: 'Mark Kettenis'
Following your commit,
I was able to recheck my code,
as you rebased it in:
https://sourceware.org/ml/gdb-patches/2013-09/msg00784.html
It still applies cleanly.
I ran I small script (in order to avoid running the whole testsuite,
as it takes ages for mingw hosts due to losts of timeouts...)
Here is the script:
>>>>>>>>>>>>>>>>>>>>Start of script
#!/bin/bash
builddir=~/gdbcvs/build-cross-src-mingw64
srcdir=~/gdbcvs/src/gdb
# Obtained by grep -E '"(call|p|print) +[A-Za-z_][a-zA-Z0-9_]* *(' */*.exp
# in testsuite sub-directory
exp_list=`cd $srcdir/testsuite; grep -E '"(call|p|print)
+[a-zA-Z_][a-zA-Z0-9_]
* *\(' */*exp -l`
exp_list=`echo ${exp_list} | tr '\n' ' '`
echo "exp_list is $exp_list"
function runtests {
cd $builddir
echo compiling
make all-gdb 1> make-$1.log 2>&1
cd gdb/testsuite
echo Running testsuite
echo "make check RUNTESTFLAGS=\"$exp_list\""
make check RUNTESTFLAGS="$exp_list" > ../make-tests-$1.log
cp gdb.sum gdb-$1.sum
cp gdb.log gdb-$1.log
cd $srcdir
}
runtests 0
patch -p 2 -i
../../patches/0002-Pierre-s-modifications-for-amd64-windows-funcalls.patch
runtests 1
patch -p 2 -i
../../patches/0002-Pierre-s-modifications-for-amd64-windows-funcalls.patch
-R
runtests 0b
>>>>>>>>>>>>>>>>>>>>End of script
Diffgdb-0.sum and gdb-1.sum is given below,
most of the FAIL->PASS are related to the fact that your
patch mishandles "long double" types and passes them
in xmm register when the need to be handled as copy-on-stack and pass
stack-address.
I will try to separate the patch into smaller pieces
for easier review.
Pierre Muller
*** gdb-0.sum 2013-09-24 23:25:04.777087500 +0200
--- gdb-1.sum 2013-09-24 23:30:50.094838600 +0200
***************
*** 1,4 ****
! Test Run By Pierre on Tue Sep 24 23:19:29 2013
Target is x86_64-w64-mingw32
Host is x86_64-w64-mingw32
Build is i686-pc-cygwin
--- 1,4 ----
! Test Run By Pierre on Tue Sep 24 23:25:38 2013
Target is x86_64-w64-mingw32
Host is x86_64-w64-mingw32
Build is i686-pc-cygwin
***************
*** 1274,1280 ****
PASS: gdb.base/varargs.exp: print find_max1(10,1,2,3,4,5,6,7,8,29,0)
PASS: gdb.base/varargs.exp: print find_max2(3,1,2,3)
PASS: gdb.base/varargs.exp: print find_max_double(5,1.0,17.0,2.0,3.0,4.0)
! FAIL: gdb.base/varargs.exp: print find_max_float_real(4, fc1, fc2, fc3,
fc4)
PASS: gdb.base/varargs.exp: print find_max_double_real(4, dc1, dc2, dc3,
dc4)
PASS: gdb.base/varargs.exp: print find_max_long_double_real(4, ldc1, ldc2,
ldc3, ldc4)
Running ../../../src/gdb/testsuite/gdb.arch/e500-abi.exp ...
--- 1274,1280 ----
PASS: gdb.base/varargs.exp: print find_max1(10,1,2,3,4,5,6,7,8,29,0)
PASS: gdb.base/varargs.exp: print find_max2(3,1,2,3)
PASS: gdb.base/varargs.exp: print find_max_double(5,1.0,17.0,2.0,3.0,4.0)
! PASS: gdb.base/varargs.exp: print find_max_float_real(4, fc1, fc2, fc3,
fc4)
PASS: gdb.base/varargs.exp: print find_max_double_real(4, dc1, dc2, dc3,
dc4)
PASS: gdb.base/varargs.exp: print find_max_long_double_real(4, ldc1, ldc2,
ldc3, ldc4)
Running ../../../src/gdb/testsuite/gdb.arch/e500-abi.exp ...
***************
*** 1425,1433 ****
PASS: gdb.base/callfuncs.exp: p t_double_int(99.0, 99)
PASS: gdb.base/callfuncs.exp: p t_int_double(99, 1.0)
PASS: gdb.base/callfuncs.exp: p t_int_double(99, 99.0)
! FAIL: gdb.base/callfuncs.exp: p t_float_complex_values(fc1, fc2)
PASS: gdb.base/callfuncs.exp: p t_float_complex_values(fc3, fc4)
! FAIL: gdb.base/callfuncs.exp: p t_float_complex_many_args(fc1, fc2, fc3,
fc4, fc1, fc2, fc3, fc4, fc1, fc2, fc3, fc4, fc1, fc2, fc3, fc4)
PASS: gdb.base/callfuncs.exp: p t_float_complex_many_args(fc1, fc1, fc1,
fc1, fc1, fc1, fc1, fc1, fc1, fc1, fc1, fc1, fc1, fc1, fc1, fc1)
PASS: gdb.base/callfuncs.exp: p t_double_complex_values(dc1, dc2)
PASS: gdb.base/callfuncs.exp: p t_double_complex_values(dc3, dc4)
--- 1425,1433 ----
PASS: gdb.base/callfuncs.exp: p t_double_int(99.0, 99)
PASS: gdb.base/callfuncs.exp: p t_int_double(99, 1.0)
PASS: gdb.base/callfuncs.exp: p t_int_double(99, 99.0)
! PASS: gdb.base/callfuncs.exp: p t_float_complex_values(fc1, fc2)
PASS: gdb.base/callfuncs.exp: p t_float_complex_values(fc3, fc4)
! PASS: gdb.base/callfuncs.exp: p t_float_complex_many_args(fc1, fc2, fc3,
fc4, fc1, fc2, fc3, fc4, fc1, fc2, fc3, fc4, fc1, fc2, fc3, fc4)
PASS: gdb.base/callfuncs.exp: p t_float_complex_many_args(fc1, fc1, fc1,
fc1, fc1, fc1, fc1, fc1, fc1, fc1, fc1, fc1, fc1, fc1, fc1, fc1)
PASS: gdb.base/callfuncs.exp: p t_double_complex_values(dc1, dc2)
PASS: gdb.base/callfuncs.exp: p t_double_complex_values(dc3, dc4)
***************
*** 1601,1607 ****
PASS: gdb.cp/koenig.exp: p rfoo()
PASS: gdb.cp/koenig.exp: p this->rfoo()
Running ../../../src/gdb/testsuite/gdb.base/call-signal-resume.exp ...
! gdb compile failed, /tmp/ccGWbOM2.o: In function `gen_signal':
/home/Pierre/gdbcvs/build-cross-src-mingw64/gdb/testsuite/../../../src/gdb/t
estsuite/gdb.base/call-signals.c:35: undefined reference to `kill'
collect2: error: ld returned 1 exit status
UNTESTED: gdb.base/call-signal-resume.exp: call-signal-resume.exp
--- 1601,1607 ----
PASS: gdb.cp/koenig.exp: p rfoo()
PASS: gdb.cp/koenig.exp: p this->rfoo()
Running ../../../src/gdb/testsuite/gdb.base/call-signal-resume.exp ...
! gdb compile failed, /tmp/cc2cnwEe.o: In function `gen_signal':
/home/Pierre/gdbcvs/build-cross-src-mingw64/gdb/testsuite/../../../src/gdb/t
estsuite/gdb.base/call-signals.c:35: undefined reference to `kill'
collect2: error: ld returned 1 exit status
UNTESTED: gdb.base/call-signal-resume.exp: call-signal-resume.exp
***************
*** 1778,1797 ****
PASS: gdb.base/call-sc.exp: set width 0
PASS: gdb.base/call-sc.exp: ptype; call-sc-tld (long double)
PASS: gdb.base/call-sc.exp: ptype foo; call-sc-tld long double
! FAIL: gdb.base/call-sc.exp: p/c fun(); call call-sc-tld
PASS: gdb.base/call-sc.exp: call Fun(foo); call call-sc-tld
PASS: gdb.base/call-sc.exp: p/c L; call call-sc-tld
! FAIL: gdb.base/call-sc.exp: advance to fun for return; return call-sc-tld
! FAIL: gdb.base/call-sc.exp: zed L for return; return call-sc-tld
! FAIL: gdb.base/call-sc.exp: return foo; return call-sc-tld
! FAIL: gdb.base/call-sc.exp: return foo; synchronize pc to main()
! FAIL: gdb.base/call-sc.exp: return foo; synchronize pc to main()
! PASS: gdb.base/call-sc.exp: value foo returned; return call-sc-tld
! FAIL: gdb.base/call-sc.exp: advance to fun for finish; return call-sc-tld
(the program exited)
! FAIL: gdb.base/call-sc.exp: zed L for finish; return call-sc-tld
! FAIL: gdb.base/call-sc.exp: finish foo; return call-sc-tld (the program is
no longer running)
! FAIL: gdb.base/call-sc.exp: value foo finished; return call-sc-tld
! PASS: gdb.base/call-sc.exp: return and finish use same convention; return
call-sc-tld
PASS: gdb.base/call-sc.exp: set print sevenbit-strings
PASS: gdb.base/call-sc.exp: set print address off
PASS: gdb.base/call-sc.exp: set width 0
--- 1778,1796 ----
PASS: gdb.base/call-sc.exp: set width 0
PASS: gdb.base/call-sc.exp: ptype; call-sc-tld (long double)
PASS: gdb.base/call-sc.exp: ptype foo; call-sc-tld long double
! PASS: gdb.base/call-sc.exp: p/c fun(); call call-sc-tld
PASS: gdb.base/call-sc.exp: call Fun(foo); call call-sc-tld
PASS: gdb.base/call-sc.exp: p/c L; call call-sc-tld
! PASS: gdb.base/call-sc.exp: advance to fun for return; return call-sc-tld
! PASS: gdb.base/call-sc.exp: zed L for return; return call-sc-tld
! PASS: gdb.base/call-sc.exp: return foo; return call-sc-tld
! PASS: gdb.base/call-sc.exp: return foo; synchronize pc to main()
! FAIL: gdb.base/call-sc.exp: value foo returned; return call-sc-tld
! PASS: gdb.base/call-sc.exp: advance to fun for finish; return call-sc-tld
! PASS: gdb.base/call-sc.exp: zed L for finish; return call-sc-tld
! PASS: gdb.base/call-sc.exp: finish foo; return call-sc-tld
! PASS: gdb.base/call-sc.exp: value foo finished; return call-sc-tld
! KFAIL: gdb.base/call-sc.exp: return and finish use same convention; return
call-sc-tld (PRMS: gdb/1444)
PASS: gdb.base/call-sc.exp: set print sevenbit-strings
PASS: gdb.base/call-sc.exp: set print address off
PASS: gdb.base/call-sc.exp: set width 0
***************
*** 2365,2373 ****
PASS: gdb.cp/bool.exp: print return_true()
PASS: gdb.cp/bool.exp: print return_false()
Running ../../../src/gdb/testsuite/gdb.base/gnu-ifunc.exp ...
! gdb compile failed, /tmp/ccIypBHh.s: Assembler messages:
! /tmp/ccIypBHh.s:3: Warning: .type pseudo-op used outside of .def/.endef
ignored.
! /tmp/ccIypBHh.s:3: Error: junk at end of line, first unrecognized
character is `g'
UNTESTED: gdb.base/gnu-ifunc.exp: Could not compile dynamic executable
././gdb.base/gnu-ifunc.
Running ../../../src/gdb/testsuite/gdb.base/wchar.exp ...
PASS: gdb.base/wchar.exp: print narrow
--- 2364,2372 ----
PASS: gdb.cp/bool.exp: print return_true()
PASS: gdb.cp/bool.exp: print return_false()
Running ../../../src/gdb/testsuite/gdb.base/gnu-ifunc.exp ...
! gdb compile failed, /tmp/ccrPsyHD.s: Assembler messages:
! /tmp/ccrPsyHD.s:3: Warning: .type pseudo-op used outside of .def/.endef
ignored.
! /tmp/ccrPsyHD.s:3: Error: junk at end of line, first unrecognized
character is `g'
UNTESTED: gdb.base/gnu-ifunc.exp: Could not compile dynamic executable
././gdb.base/gnu-ifunc.
Running ../../../src/gdb/testsuite/gdb.base/wchar.exp ...
PASS: gdb.base/wchar.exp: print narrow
***************
*** 2737,2744 ****
PASS: gdb.base/dfp-test.exp: Backtrace function with correct _Decimal64
arguments.
PASS: gdb.base/dfp-test.exp: Correct _Decimal64 return value from called
function.
PASS: gdb.base/dfp-test.exp: Call function with correct _Decimal128
arguments.
! FAIL: gdb.base/dfp-test.exp: Backtrace function with correct _Decimal128
arguments.
! FAIL: gdb.base/dfp-test.exp: Correct _Decimal128 return value from called
function.
PASS: gdb.base/dfp-test.exp: Call function with mixed decimal float
arguments TEST.
PASS: gdb.base/dfp-test.exp: Call function with mixed decimal float
arguments.
PASS: gdb.base/dfp-test.exp: Call function with many _Decimal32 arguments.
--- 2736,2743 ----
PASS: gdb.base/dfp-test.exp: Backtrace function with correct _Decimal64
arguments.
PASS: gdb.base/dfp-test.exp: Correct _Decimal64 return value from called
function.
PASS: gdb.base/dfp-test.exp: Call function with correct _Decimal128
arguments.
! PASS: gdb.base/dfp-test.exp: Backtrace function with correct _Decimal128
arguments.
! PASS: gdb.base/dfp-test.exp: Correct _Decimal128 return value from called
function.
PASS: gdb.base/dfp-test.exp: Call function with mixed decimal float
arguments TEST.
PASS: gdb.base/dfp-test.exp: Call function with mixed decimal float
arguments.
PASS: gdb.base/dfp-test.exp: Call function with many _Decimal32 arguments.
***************
*** 3166,3172 ****
PASS: gdb.base/call-rt-st.exp: finish out from loop_count (line 777)
PASS: gdb.base/call-rt-st.exp: print print_struct_rep(*struct1)
PASS: gdb.base/call-rt-st.exp: print print_one_large_struct(*list1)
! FAIL: gdb.base/call-rt-st.exp: print print_one_double(*d1)
PASS: gdb.base/call-rt-st.exp: print print_two_floats(*f3)
PASS: gdb.base/call-rt-st.exp: print print_bit_flags_char(*cflags)
PASS: gdb.base/call-rt-st.exp: print print_bit_flags_short(*sflags)
--- 3165,3171 ----
PASS: gdb.base/call-rt-st.exp: finish out from loop_count (line 777)
PASS: gdb.base/call-rt-st.exp: print print_struct_rep(*struct1)
PASS: gdb.base/call-rt-st.exp: print print_one_large_struct(*list1)
! PASS: gdb.base/call-rt-st.exp: print print_one_double(*d1)
PASS: gdb.base/call-rt-st.exp: print print_two_floats(*f3)
PASS: gdb.base/call-rt-st.exp: print print_bit_flags_char(*cflags)
PASS: gdb.base/call-rt-st.exp: print print_bit_flags_short(*sflags)
***************
*** 3821,3830 ****
=== gdb Summary ===
! # of expected passes 3437
! # of unexpected failures 160
# of expected failures 11
! # of known failures 28
# of unresolved testcases 3
# of untested testcases 13
# of unsupported tests 6
--- 3820,3829 ----
=== gdb Summary ===
! # of expected passes 3450
! # of unexpected failures 145
# of expected failures 11
! # of known failures 29
# of unresolved testcases 3
# of untested testcases 13
# of unsupported tests 6
> -----Message d'origine-----
> De : gdb-patches-owner@sourceware.org [mailto:gdb-patches-
> owner@sourceware.org] De la part de Joel Brobecker
> Envoyé : mardi 24 septembre 2013 18:33
> À : gdb-patches@sourceware.org
> Cc : Pierre Muller; Mark Kettenis
> Objet : Re: [RFC-v2] amd64-windows: Fix funcall with by-pointer arguments
>
> Hello,
>
> > Once again, I'm short of time to finish what I had hoped to be able
> > to complete. But I thought I'd send an update anyway. The first patch
> > is an update to the patch I wrote in January, rebased for today's HEAD.
> > This is what I have tested and intend to check in soon.
> >
> > Left to do on my end, is clean things up in amd64-tdep, because many
> > hooks in the tdep structure can now be removed, and replaced by
> > direct calls. But this is independent of your changes, so we can
> > both work at the same time.
>
> I have now checked in the patch re-implementing function call on
> amd64-windows. After this was done, I was able to revert all changes
> that added hooks in the gdbarch_tdep and in the amd64 sysV code
> to tweak it for amd64-windows, since the two implementations are
> now completely distinct.
>
> All patches were tested on x86_64-linux and x86_64-windows.
> And just in case, I tested them on x86-windows as well.
>
> Thanks,
> --
> Joel
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC-v2] amd64-windows: Fix funcall with by-pointer arguments
2013-09-24 22:02 ` Pierre Muller
@ 2013-09-26 0:34 ` Joel Brobecker
0 siblings, 0 replies; 18+ messages in thread
From: Joel Brobecker @ 2013-09-26 0:34 UTC (permalink / raw)
To: Pierre Muller; +Cc: gdb-patches, 'Mark Kettenis'
> Diffgdb-0.sum and gdb-1.sum is given below,
> most of the FAIL->PASS are related to the fact that your
> patch mishandles "long double" types and passes them
> in xmm register when the need to be handled as copy-on-stack and pass
> stack-address.
>
> I will try to separate the patch into smaller pieces
> for easier review.
Thank you, Pierre.
--
Joel
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2013-09-26 0:34 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-10-24 17:23 amd64-windows: Fix funcall with by-pointer arguments Joel Brobecker
2012-10-24 17:23 ` [RFA 2/2] amd64-windows: Arguments passed by pointer Joel Brobecker
2012-10-24 17:24 ` [RFA 1/2] Revert "amd64-windows: memory args passed by pointer during function calls." Joel Brobecker
2012-10-25 13:18 ` amd64-windows: Fix funcall with by-pointer arguments Mark Kettenis
2013-01-16 11:59 ` Joel Brobecker
2013-09-13 22:11 ` [RFC-v2] " Pierre Muller
2013-09-16 20:57 ` Joel Brobecker
2013-09-17 13:50 ` Joel Brobecker
2013-09-20 23:20 ` Joel Brobecker
2013-09-24 16:33 ` Joel Brobecker
2013-09-24 16:33 ` [commit 4/4] Revert use of classify callback in i386 gdbarch_tdep Joel Brobecker
2013-09-24 16:33 ` [commit 1/4] Reimplement function calls on amd64-windows Joel Brobecker
2013-09-24 17:26 ` fixed ChangeLog: " Joel Brobecker
2013-09-24 16:33 ` [commit 3/4] Revert use of memory_args_by_pointer in i386 gdbarch_tdep Joel Brobecker
2013-09-24 16:33 ` [commit 2/4] Revert use of integer_param_regs_saved_in_caller_frame " Joel Brobecker
2013-09-24 16:53 ` [RFC-v2] amd64-windows: Fix funcall with by-pointer arguments Mark Kettenis
2013-09-24 22:02 ` Pierre Muller
2013-09-26 0:34 ` Joel Brobecker
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox