This is the mail archive of the
gdb-patches@sourceware.cygnus.com
mailing list for the GDB project.
Re: Fix for call-ar-st.exp failure on x86
- To: Jim Kingdon <kingdon at redhat dot com>
- Subject: Re: Fix for call-ar-st.exp failure on x86
- From: Jim Blandy <jimb at cygnus dot com>
- Date: 11 Oct 1999 19:16:54 -0500
- Cc: gdb-patches at sourceware dot cygnus dot com
- References: <199910042140.RAA26414@devserv.devel.redhat.com>
> When GDB calls a function it incorrectly pads the arguments - that is,
> GDB's behavior differs from GCC and also from the x86 ABI at
> http://www.sco.com/developer/devspecs
Sure --- it makes sense to parameterize the generic argument passer
this way, rather than write a custom push_arguments function for IA32.
Some comments, though:
- You enlarge `len' to the nearest boundary, and then read garbage off
the end of GDB's value buffer. This probably won't make GDB crash,
but it seems sloppy.
- The PARM_BOUNDARY has an obvious extension to big-endian
architectures, but the code you supplied works only on little-endian
architectures.
- As Stan points out, new architecture parameters should be done in a
gdbarch-friendly way.
In principle, we should send patches back to the author for revision,
but these problems are pretty easy to fix, and I'm especially happy
to get rid of those call-ar-st.exp failures.
Here's what I did in valops.c. If you see anything dumb, let me know.
1999-10-11 Jim Blandy <jimb@zenia.red-bean.com>
Fix from Jim Kingdon <kingdon@redhat.com>, with tweaks to make it
gdbarch- and bigendian-friendly:
* valops.c (PARM_BOUNDARY): If not #defined, default to zero.
(value_push): If PARM_BOUNDARY is not zero, align arguments to
that boundary.
* config/i386/tm-i386.h: Define PARM_BOUNDARY.
Index: valops.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/valops.c,v
retrieving revision 1.180
diff -c -c -b -F'^(' -r1.180 valops.c
*** valops.c 1999/09/16 21:06:03 1.180
--- valops.c 1999/10/12 00:11:36
***************
*** 1061,1086 ****
return sp;
}
! /* Push onto the stack the specified value VALUE. */
static CORE_ADDR
value_push (sp, arg)
register CORE_ADDR sp;
value_ptr arg;
{
register int len = TYPE_LENGTH (VALUE_ENCLOSING_TYPE (arg));
if (INNER_THAN (1, 2))
{
/* stack grows downward */
! sp -= len;
! write_memory (sp, VALUE_CONTENTS_ALL (arg), len);
}
else
{
/* stack grows upward */
! write_memory (sp, VALUE_CONTENTS_ALL (arg), len);
! sp += len;
}
return sp;
--- 1061,1104 ----
return sp;
}
! #ifndef PARM_BOUNDARY
! #define PARM_BOUNDARY (0)
! #endif
+ /* Push onto the stack the specified value VALUE. Pad it correctly for
+ it to be an argument to a function. */
+
static CORE_ADDR
value_push (sp, arg)
register CORE_ADDR sp;
value_ptr arg;
{
register int len = TYPE_LENGTH (VALUE_ENCLOSING_TYPE (arg));
+ register int container_len;
+ register int offset;
+
+ /* How big is the container we're going to put this value in? */
+ if (PARM_BOUNDARY)
+ container_len = ((len + PARM_BOUNDARY / TARGET_CHAR_BIT - 1)
+ & ~(PARM_BOUNDARY / TARGET_CHAR_BIT - 1));
+
+ /* Are we going to put it at the high or low end of the container? */
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ offset = container_len - len;
+ else
+ offset = 0;
if (INNER_THAN (1, 2))
{
/* stack grows downward */
! sp -= container_len;
! write_memory (sp + offset, VALUE_CONTENTS_ALL (arg), len);
}
else
{
/* stack grows upward */
! write_memory (sp + offset, VALUE_CONTENTS_ALL (arg), len);
! sp += container_len;
}
return sp;