This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[RFA] Fix ppc_sysv_abi_broken_return_value
- From: Mark Kettenis <mark dot kettenis at xs4all dot nl>
- To: gdb-patches at sources dot redhat dot com
- Date: Sun, 19 Jun 2005 22:59:44 +0200 (CEST)
- Subject: [RFA] Fix ppc_sysv_abi_broken_return_value
I noticed a few failures on NetBSD 2.0 that were similar to those I
see on OpenBSD 3.7. Both use GCC 3.3.x. I noticed a pattern, and
came up with the attached fix for OpenBSD. The same fix works for
NetBSD if I make it use ppc_sysv_abi_broken_return_value. Now it
seems that the brokenness changes with every GCC release, but I think
nevertheless that we should make the change below. There are a couple
of reasons:
1. I somehow doubt that the old code was completely correct. It
doesn't really make sense, and perhaps predates the additional
checks that Andrew added some time ago which made me find what was
really going on.
2. The new code is quite a bit simpler.
3. This makes things work on the most up-to-date release of OpenBSD
and NetBSD.
Of course the last reason is the most important one.
OK?
Mark
Index: ChangeLog
from Mark Kettenis <kettenis@gnu.org>
* ppc-sysv-tdep.c (do_ppc_sysv_return_value): Fix the code that
deals with the broken GCC convention.
2005-06-19 Mark Kettenis <kettenis@gnu.org>
Index: ppc-sysv-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ppc-sysv-tdep.c,v
retrieving revision 1.29
diff -u -p -r1.29 ppc-sysv-tdep.c
--- ppc-sysv-tdep.c 25 May 2005 03:12:13 -0000 1.29
+++ ppc-sysv-tdep.c 19 Jun 2005 20:50:44 -0000
@@ -433,52 +451,33 @@ do_ppc_sysv_return_value (struct gdbarch
}
if (broken_gcc && TYPE_LENGTH (type) <= 8)
{
+ /* GCC screwed up for structures or unions whose size is less
+ than or equal to 8 bytes.. Instead of left-aligning, it
+ right-aligns the data into the buffer formed by r3, r4. */
+ gdb_byte regvals[MAX_REGISTER_SIZE * 2];
+ int len = TYPE_LENGTH (type);
+ int offset = (2 * tdep->wordsize - len) % tdep->wordsize;
+
if (readbuf)
{
- /* GCC screwed up. The last register isn't "left" aligned.
- Need to extract the least significant part of each
- register and then store that. */
- /* Transfer any full words. */
- int word = 0;
- while (1)
- {
- ULONGEST reg;
- int len = TYPE_LENGTH (type) - word * tdep->wordsize;
- if (len <= 0)
- break;
- if (len > tdep->wordsize)
- len = tdep->wordsize;
- regcache_cooked_read_unsigned (regcache,
- tdep->ppc_gp0_regnum + 3 + word,
- ®);
- store_unsigned_integer (((bfd_byte *) readbuf
- + word * tdep->wordsize), len, reg);
- word++;
- }
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3,
+ regvals + 0 * tdep->wordsize);
+ if (len > tdep->wordsize)
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
+ regvals + 1 * tdep->wordsize);
+ memcpy (readbuf, regvals + offset, len);
}
if (writebuf)
{
- /* GCC screwed up. The last register isn't "left" aligned.
- Need to extract the least significant part of each
- register and then store that. */
- /* Transfer any full words. */
- int word = 0;
- while (1)
- {
- ULONGEST reg;
- int len = TYPE_LENGTH (type) - word * tdep->wordsize;
- if (len <= 0)
- break;
- if (len > tdep->wordsize)
- len = tdep->wordsize;
- reg = extract_unsigned_integer (((const bfd_byte *) writebuf
- + word * tdep->wordsize), len);
- regcache_cooked_write_unsigned (regcache,
- tdep->ppc_gp0_regnum + 3 + word,
- reg);
- word++;
- }
+ memset (regvals, 0, sizeof regvals);
+ memcpy (regvals + offset, writebuf, len);
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3,
+ regvals + 0 * tdep->wordsize);
+ if (len > tdep->wordsize)
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
+ regvals + 1 * tdep->wordsize);
}
+
return RETURN_VALUE_REGISTER_CONVENTION;
}
if (TYPE_LENGTH (type) <= 8)