This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[RFA] Generic solution for store_struct_address
- From: Michael Snyder <msnyder at redhat dot com>
- To: gdb-patches at sources dot redhat dot com
- Cc: cagney at redhat dot com, kevinb at redhat dot com
- Date: Wed, 21 Aug 2002 19:22:02 -0700
- Subject: [RFA] Generic solution for store_struct_address
- Organization: Red Hat, Inc.
This patch lets store_struct_address save the struct_addr in a LIFO
queue,
from which extract_struct_value_address can then pull it out. The value
of SP is used as a confidence check, to make sure each struct_addr goes
to the right stack frame. If the struct_addr isn't found on the queue,
then the target can fall back to extracting it from a register.
I'm pretty sure this works -- I've tested it on mips, arm, d10v and
i386.
Kevin, would you by any chance be in a position to test it on ia64
and/or
rs6000?
I've included patches for all of the targets that use the infamous
"horrid kludge" from rs6000-tdep.c. Those will of course have to
be approved by individual maintainers, but the shared code could go
in before then.
Andrew, OK for mips? Tested, of course...
Michael
2002-08-21 Michael Snyder <msnyder@redhat.com>
* arch-utils.c (generic_push_struct_return,
generic_pop_struct_return): New functions, helpers for
store_struct_return and extract_struct_value_address.
* arch-utils.h: External interface to the above.
* cris-tdep.c (cris_store_struct_return): Use above.
(cris_extract_struct_value_address): Ditto.
* ia64-tdep.c (ia64_store_struct_return): Use above.
(ia64_extract_struct_value_address): Ditto.
* mips-tdep.c (mips_store_struct_return): Use above.
(mips_extract_struct_value_address): Ditto.
* ia64-tdep.c (ia64_store_struct_return): Use above.
(ia64_extract_struct_value_address): Ditto.
Index: arch-utils.h
===================================================================
RCS file: /cvs/src/src/gdb/arch-utils.h,v
retrieving revision 1.40
diff -c -3 -p -r1.40 arch-utils.h
*** arch-utils.h 20 Aug 2002 23:01:28 -0000 1.40
--- arch-utils.h 22 Aug 2002 02:26:47 -0000
*************** extern int generic_register_size (int re
*** 156,161 ****
--- 156,165 ----
/* Assume that the world is sane, the registers are all adjacent. */
extern int generic_register_byte (int regnum);
+ /* A stack of struct_returns. */
+ extern void generic_push_struct_return (CORE_ADDR addr, CORE_ADDR sp);
+ extern CORE_ADDR generic_pop_struct_return (CORE_ADDR sp);
+
/* Prop up old targets that use various IN_SIGTRAMP() macros. */
extern int legacy_pc_in_sigtramp (CORE_ADDR pc, char *name);
Index: arch-utils.c
===================================================================
RCS file: /cvs/src/src/gdb/arch-utils.c,v
retrieving revision 1.66
diff -c -3 -p -r1.66 arch-utils.c
*** arch-utils.c 20 Aug 2002 23:01:28 -0000 1.66
--- arch-utils.c 22 Aug 2002 02:26:47 -0000
*************** generic_register_byte (int regnum)
*** 453,458 ****
--- 453,504 ----
}
+ /* A simple stack of struct return addresses, stored by
+ store_struct_return and fetched by extract_struct_value_address.
+ Uses the stack pointer value as a key/identifier. */
+
+ struct struct_return_stack {
+ CORE_ADDR addr;
+ CORE_ADDR sp;
+ };
+
+ static struct struct_return_stack *struct_return_stack = NULL;
+ static int struct_return_stack_depth = 0;
+ static int struct_return_tos = 0;
+
+ enum { STRUCT_RETURN_STACK_CHUNK = 128 };
+
+ void
+ generic_push_struct_return (CORE_ADDR addr, CORE_ADDR sp)
+ {
+ if (struct_return_tos >= struct_return_stack_depth)
+ {
+ struct_return_stack_depth += STRUCT_RETURN_STACK_CHUNK;
+ struct_return_stack = xrealloc (struct_return_stack,
+ struct_return_stack_depth *
+ sizeof (struct struct_return_stack));
+ }
+ struct_return_stack[struct_return_tos].addr = addr;
+ struct_return_stack[struct_return_tos].sp = sp;
+ struct_return_tos++;
+ }
+
+ CORE_ADDR
+ generic_pop_struct_return (CORE_ADDR sp)
+ {
+ /* Stack empty? */
+ if (struct_return_tos == 0)
+ return 0;
+
+ /* Does this SP match the one on the top of our stack? */
+ if (sp != struct_return_stack[struct_return_tos - 1].sp)
+ return 0;
+
+ /* Top-of-stack is a valid struct_return value. Return it. */
+ return struct_return_stack[--struct_return_tos].addr;
+ }
+
+
int
legacy_pc_in_sigtramp (CORE_ADDR pc, char *name)
{
Index: rs6000-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/rs6000-tdep.c,v
retrieving revision 1.76
diff -c -3 -p -r1.76 rs6000-tdep.c
*** rs6000-tdep.c 21 Aug 2002 22:56:02 -0000 1.76
--- rs6000-tdep.c 22 Aug 2002 02:26:47 -0000
*************** rs6000_extract_return_value (struct type
*** 1193,1200 ****
living. This only allows a single nested call to a structure-returning
function. Come on, guys! -- gnu@cygnus.com, Aug 92 */
- static CORE_ADDR rs6000_struct_return_address;
-
/* Return whether handle_inferior_event() should proceed through code
starting at PC in function NAME when stepping.
--- 1193,1198 ----
*************** rs6000_stab_reg_to_regnum (int num)
*** 1789,1802 ****
In RS/6000, struct return addresses are passed as an extra parameter in r3.
In function return, callee is not responsible of returning this address
! back. Since gdb needs to find it, we will store in a designated variable
! `rs6000_struct_return_address'. */
static void
rs6000_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
{
write_register (3, addr);
- rs6000_struct_return_address = addr;
}
/* Write into appropriate registers a function return value
--- 1787,1800 ----
In RS/6000, struct return addresses are passed as an extra parameter in r3.
In function return, callee is not responsible of returning this address
! back. Since gdb needs to find it, we will store in a LIFO queue of
! struct-return addresses. */
static void
rs6000_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
{
+ generic_push_struct_return (addr, sp);
write_register (3, addr);
}
/* Write into appropriate registers a function return value
*************** rs6000_store_return_value (struct type *
*** 1833,1841 ****
as a CORE_ADDR (or an expression that can be used as one). */
static CORE_ADDR
! rs6000_extract_struct_value_address (char *regbuf)
{
! return rs6000_struct_return_address;
}
/* Return whether PC is in a dummy function call.
--- 1831,1848 ----
as a CORE_ADDR (or an expression that can be used as one). */
static CORE_ADDR
! rs6000_extract_struct_value_address (struct regcache *regcache)
{
! ULONGEST ret, sp;
!
! /* First try to fetch a struct_return from the cache. */
! regcache_cooked_read_unsigned (regcache, SP_REGNUM, &sp);
! ret = generic_pop_struct_return (sp);
! /* Failing that, get it from register 3. FIXME name? constant? */
! if (ret == 0)
! regcache_cooked_read_unsigned (regcache, 3, &ret);
!
! return ret;
}
/* Return whether PC is in a dummy function call.
*************** rs6000_gdbarch_init (struct gdbarch_info
*** 2684,2690 ****
set_gdbarch_store_struct_return (gdbarch, rs6000_store_struct_return);
set_gdbarch_store_return_value (gdbarch, rs6000_store_return_value);
! set_gdbarch_deprecated_extract_struct_value_address (gdbarch, rs6000_extract_struct_value_address);
set_gdbarch_pop_frame (gdbarch, rs6000_pop_frame);
set_gdbarch_skip_prologue (gdbarch, rs6000_skip_prologue);
--- 2691,2697 ----
set_gdbarch_store_struct_return (gdbarch, rs6000_store_struct_return);
set_gdbarch_store_return_value (gdbarch, rs6000_store_return_value);
! set_gdbarch_extract_struct_value_address (gdbarch, rs6000_extract_struct_value_address);
set_gdbarch_pop_frame (gdbarch, rs6000_pop_frame);
set_gdbarch_skip_prologue (gdbarch, rs6000_skip_prologue);
Index: mips-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-tdep.c,v
retrieving revision 1.118
diff -c -3 -p -r1.118 mips-tdep.c
*** mips-tdep.c 21 Aug 2002 22:39:26 -0000 1.118
--- mips-tdep.c 22 Aug 2002 02:26:47 -0000
*************** mips_eabi_push_arguments (int nargs,
*** 2622,2628 ****
fprintf_unfiltered (gdb_stdlog,
"mips_eabi_push_arguments: struct_return reg=%d 0x%s\n",
argreg, paddr_nz (struct_addr));
! write_register (argreg++, struct_addr);
}
/* Now load as many as possible of the first arguments into
--- 2622,2628 ----
fprintf_unfiltered (gdb_stdlog,
"mips_eabi_push_arguments: struct_return reg=%d 0x%s\n",
argreg, paddr_nz (struct_addr));
! argreg++; /* Reg reserved for passing struct_addr. */
}
/* Now load as many as possible of the first arguments into
*************** mips_n32n64_push_arguments (int nargs,
*** 2873,2879 ****
fprintf_unfiltered (gdb_stdlog,
"mips_n32n64_push_arguments: struct_return reg=%d 0x%s\n",
argreg, paddr_nz (struct_addr));
! write_register (argreg++, struct_addr);
}
/* Now load as many as possible of the first arguments into
--- 2873,2879 ----
fprintf_unfiltered (gdb_stdlog,
"mips_n32n64_push_arguments: struct_return reg=%d 0x%s\n",
argreg, paddr_nz (struct_addr));
! argreg++; /* Reg reserved for passing struct_addr. */
}
/* Now load as many as possible of the first arguments into
*************** mips_o32_push_arguments (int nargs,
*** 3099,3105 ****
fprintf_unfiltered (gdb_stdlog,
"mips_o32_push_arguments: struct_return reg=%d 0x%s\n",
argreg, paddr_nz (struct_addr));
! write_register (argreg++, struct_addr);
stack_offset += MIPS_STACK_ARGSIZE;
}
--- 3099,3105 ----
fprintf_unfiltered (gdb_stdlog,
"mips_o32_push_arguments: struct_return reg=%d 0x%s\n",
argreg, paddr_nz (struct_addr));
! argreg++; /* Reg reserved for passing struct_addr. */
stack_offset += MIPS_STACK_ARGSIZE;
}
*************** mips_o64_push_arguments (int nargs,
*** 3398,3404 ****
fprintf_unfiltered (gdb_stdlog,
"mips_o64_push_arguments: struct_return reg=%d 0x%s\n",
argreg, paddr_nz (struct_addr));
! write_register (argreg++, struct_addr);
stack_offset += MIPS_STACK_ARGSIZE;
}
--- 3398,3404 ----
fprintf_unfiltered (gdb_stdlog,
"mips_o64_push_arguments: struct_return reg=%d 0x%s\n",
argreg, paddr_nz (struct_addr));
! argreg++; /* Reg reserved for passing struct_addr. */
stack_offset += MIPS_STACK_ARGSIZE;
}
*************** mips_n32n64_store_return_value (struct t
*** 4902,4917 ****
static void
mips_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
{
! /* Nothing to do -- push_arguments does all the work. */
}
static CORE_ADDR
! mips_extract_struct_value_address (struct regcache *ignore)
{
! /* FIXME: This will only work at random. The caller passes the
! struct_return address in V0, but it is not preserved. It may
! still be there, or this may be a random value. */
! return read_register (V0_REGNUM);
}
/* Exported procedure: Is PC in the signal trampoline code */
--- 4902,4926 ----
static void
mips_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
{
! /* Save the struct_return address in a LIFO stack. */
! addr = ROUND_DOWN (addr, 16);
! generic_push_struct_return (addr, sp);
! write_register (A0_REGNUM, addr);
}
static CORE_ADDR
! mips_extract_struct_value_address (struct regcache *regcache)
{
! ULONGEST ret, sp;
!
! /* First try to fetch a struct_return from the cache. */
! regcache_cooked_read_unsigned (regcache, SP_REGNUM, &sp);
! ret = generic_pop_struct_return (sp);
! /* Failing that, get it from V0. */
! if (ret == 0)
! regcache_cooked_read_unsigned (regcache, V0_REGNUM, &ret);
!
! return ret;
}
/* Exported procedure: Is PC in the signal trampoline code */
Index: cris-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/cris-tdep.c,v
retrieving revision 1.20
diff -c -3 -p -r1.20 cris-tdep.c
*** cris-tdep.c 11 Jul 2002 19:25:13 -0000 1.20
--- cris-tdep.c 22 Aug 2002 02:26:47 -0000
*************** cris_abi (void)
*** 173,181 ****
return (gdbarch_tdep (current_gdbarch)->cris_abi);
}
- /* For saving call-clobbered contents in R9 when returning structs. */
- static CORE_ADDR struct_return_address;
-
struct frame_extra_info
{
CORE_ADDR return_pc;
--- 173,178 ----
*************** void
*** 1085,1091 ****
cris_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
{
write_register (STR_REGNUM, addr);
! struct_return_address = addr;
}
/* Extract from regbuf the address where a function should return a
--- 1082,1088 ----
cris_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
{
write_register (STR_REGNUM, addr);
! generic_push_return_address (addr, sp);
}
/* Extract from regbuf the address where a function should return a
*************** cris_store_struct_return (CORE_ADDR addr
*** 1093,1101 ****
way. */
CORE_ADDR
! cris_extract_struct_value_address (char *regbuf)
{
! return struct_return_address;
}
/* Returns 1 if a value of the given type being returned from a function
--- 1090,1107 ----
way. */
CORE_ADDR
! cris_extract_struct_value_address (struct regcache *regcache)
{
! ULONGEST ret, sp;
!
! /* First try to fetch a struct_return from the cache. */
! regcache_cooked_read_unsigned (regcache, SP_REGNUM, &sp);
! ret = generic_pop_struct_return (sp);
! /* Failing that, get it from STR_REGNUM. */
! if (ret == 0)
! regcache_cooked_read_unsigned (regcache, STR_REGNUM, &ret);
!
! return ret;
}
/* Returns 1 if a value of the given type being returned from a function
*************** cris_gdbarch_init (struct gdbarch_info i
*** 4297,4303 ****
set_gdbarch_pop_frame (gdbarch, cris_pop_frame);
set_gdbarch_store_struct_return (gdbarch, cris_store_struct_return);
! set_gdbarch_deprecated_extract_struct_value_address
(gdbarch, cris_extract_struct_value_address);
set_gdbarch_use_struct_convention (gdbarch, cris_use_struct_convention);
--- 4303,4309 ----
set_gdbarch_pop_frame (gdbarch, cris_pop_frame);
set_gdbarch_store_struct_return (gdbarch, cris_store_struct_return);
! set_gdbarch_extract_struct_value_address
(gdbarch, cris_extract_struct_value_address);
set_gdbarch_use_struct_convention (gdbarch, cris_use_struct_convention);
Index: ia64-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ia64-tdep.c,v
retrieving revision 1.32
diff -c -3 -p -r1.32 ia64-tdep.c
*** ia64-tdep.c 17 Jun 2002 23:32:31 -0000 1.32
--- ia64-tdep.c 22 Aug 2002 02:26:47 -0000
*************** ia64_extract_return_value (struct type *
*** 1428,1451 ****
TYPE_LENGTH (type));
}
- /* FIXME: Turn this into a stack of some sort. Unfortunately, something
- like this is necessary though since the IA-64 calling conventions specify
- that r8 is not preserved. */
- static CORE_ADDR struct_return_address;
-
CORE_ADDR
! ia64_extract_struct_value_address (char *regbuf)
{
! /* FIXME: See above. */
! return struct_return_address;
}
void
ia64_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
{
- /* FIXME: See above. */
/* Note that most of the work was done in ia64_push_arguments() */
! struct_return_address = addr;
}
int
--- 1428,1453 ----
TYPE_LENGTH (type));
}
CORE_ADDR
! ia64_extract_struct_value_address (struct regcache *regcache)
{
! ULONGEST ret, sp;
!
! /* First try to fetch a struct_return from the cache. */
! regcache_cooked_read_unsigned (regcache, SP_REGNUM, &sp);
! ret = generic_pop_struct_return (sp);
! /* Failing that, get it from GR8. */
! if (ret == 0)
! regcache_cooked_read_unsigned (regcache, IA64_GR8_REGNUM, &ret);
!
! return ret;
}
void
ia64_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
{
/* Note that most of the work was done in ia64_push_arguments() */
! generic_push_struct_return (addr, sp);
}
int
*************** ia64_gdbarch_init (struct gdbarch_info i
*** 2194,2200 ****
set_gdbarch_store_struct_return (gdbarch, ia64_store_struct_return);
set_gdbarch_store_return_value (gdbarch, ia64_store_return_value);
! set_gdbarch_deprecated_extract_struct_value_address (gdbarch, ia64_extract_struct_value_address);
set_gdbarch_memory_insert_breakpoint (gdbarch, ia64_memory_insert_breakpoint);
set_gdbarch_memory_remove_breakpoint (gdbarch, ia64_memory_remove_breakpoint);
--- 2196,2203 ----
set_gdbarch_store_struct_return (gdbarch, ia64_store_struct_return);
set_gdbarch_store_return_value (gdbarch, ia64_store_return_value);
! set_gdbarch_extract_struct_value_address (gdbarch,
! ia64_extract_struct_value_address);
set_gdbarch_memory_insert_breakpoint (gdbarch, ia64_memory_insert_breakpoint);
set_gdbarch_memory_remove_breakpoint (gdbarch, ia64_memory_remove_breakpoint);