This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[RFA] Save the call dummy address
- From: Andrew Cagney <ac131313 at cygnus dot com>
- To: Michael Snyder <msnyder at redhat dot com>
- Cc: gdb-patches at sources dot redhat dot com
- Date: Sun, 14 Apr 2002 11:14:20 -0400
- Subject: [RFA] Save the call dummy address
Hello,
The attached patch modifies generic dummy frames so that they save the
address of the call dummy code. This in turn makes it possible to
modify the generic_pc_in_call_dummy() function so that it uses the PC
(instead of the FP) to determine if the PC is in a call dummy (yes you
read that right :-).
It also has the (er un-intended) side effect of removing the restriction
that generic dummy frames only work with the AT_ENTRY mechanism.
The only potential problem I can see is with someone typing ``(gdb) jump
*_start'' when there are dummy frames present. It could trigger a false
positive. I think that is a separate problem and I don't even know if
it really can occure.
Tested on NetBSD/PPC (which uses generic dummy frames) without regressions.
Michael, I suspect you're the ``maintainer'' of this code. Look ok?
enjoy,
Andrew
2002-04-14 Andrew Cagney <ac131313@redhat.com>
* valops.c (hand_function_call): Call
generic_save_call_dummy_addr.
* frame.h (generic_save_call_dummy_addr): Declare.
* blockframe.c (struct dummy_frame): Add fields call_lo and
call_hi.
(generic_find_dummy_frame): Check for PC in range call_lo to
call_hi instead of entry_point_address.
(generic_pc_in_call_dummy): Search the dummy frames for a PC in
the call_lo to call_hi range. Allow for DECR_PC_AFTER_BREAK.
(generic_save_call_dummy_addr): New function.
Index: blockframe.c
===================================================================
RCS file: /cvs/src/src/gdb/blockframe.c,v
retrieving revision 1.24
diff -u -r1.24 blockframe.c
--- blockframe.c 14 Apr 2002 13:38:06 -0000 1.24
+++ blockframe.c 14 Apr 2002 14:52:05 -0000
@@ -1070,42 +1070,59 @@
CORE_ADDR sp;
CORE_ADDR top;
char *registers;
+
+ /* Address range of the call dummy code. Look for PC in the range
+ [LO..HI) (after allowing for DECR_PC_AFTER_BREAK). */
+ CORE_ADDR call_lo;
+ CORE_ADDR call_hi;
};
static struct dummy_frame *dummy_frame_stack = NULL;
/* Function: find_dummy_frame(pc, fp, sp)
- Search the stack of dummy frames for one matching the given PC, FP and SP.
- This is the work-horse for pc_in_call_dummy and read_register_dummy */
+
+ Search the stack of dummy frames for one matching the given PC, FP
+ and SP. Unlike PC_IN_CALL_DUMMY, this function doesn't need to
+ adjust for DECR_PC_AFTER_BREAK. This is because it is only legal
+ to call this function after the PC has been adjusted. */
char *
generic_find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp)
{
struct dummy_frame *dummyframe;
- if (pc != entry_point_address ())
- return 0;
-
for (dummyframe = dummy_frame_stack; dummyframe != NULL;
dummyframe = dummyframe->next)
- if (fp == dummyframe->fp
- || fp == dummyframe->sp
- || fp == dummyframe->top)
+ if ((pc >= dummyframe->call_lo && pc < dummyframe->call_hi)
+ && (fp == dummyframe->fp
+ || fp == dummyframe->sp
+ || fp == dummyframe->top))
/* The frame in question lies between the saved fp and sp, inclusive */
return dummyframe->registers;
return 0;
}
-/* Function: pc_in_call_dummy (pc, fp)
- Return true if this is a dummy frame created by gdb for an inferior call */
+/* Function: pc_in_call_dummy (pc, sp, fp)
+
+ Return true if the PC falls in a dummy frame created by gdb for an
+ inferior call. The code below which allows DECR_PC_AFTER_BREAK is
+ for infrun.c, which may give the function a PC without that
+ subtracted out. */
int
generic_pc_in_call_dummy (CORE_ADDR pc, CORE_ADDR sp, CORE_ADDR fp)
{
- /* if find_dummy_frame succeeds, then PC is in a call dummy */
- /* Note: SP and not FP is passed on. */
- return (generic_find_dummy_frame (pc, sp) != 0);
+ struct dummy_frame *dummyframe;
+ for (dummyframe = dummy_frame_stack;
+ dummyframe != NULL;
+ dummyframe = dummyframe->next)
+ {
+ if ((pc >= dummyframe->call_lo)
+ && (pc < dummyframe->call_hi + DECR_PC_AFTER_BREAK))
+ return 1;
+ }
+ return 0;
}
/* Function: read_register_dummy
@@ -1168,6 +1185,15 @@
generic_save_dummy_frame_tos (CORE_ADDR sp)
{
dummy_frame_stack->top = sp;
+}
+
+/* Record the upper/lower bounds on the address of the call dummy. */
+
+void
+generic_save_call_dummy_addr (CORE_ADDR lo, CORE_ADDR hi)
+{
+ dummy_frame_stack->call_lo = lo;
+ dummy_frame_stack->call_hi = hi;
}
/* Restore the machine state from either the saved dummy stack or a
Index: frame.h
===================================================================
RCS file: /cvs/src/src/gdb/frame.h,v
retrieving revision 1.12
diff -u -r1.12 frame.h
--- frame.h 12 Apr 2002 18:18:57 -0000 1.12
+++ frame.h 14 Apr 2002 14:52:07 -0000
@@ -277,6 +277,8 @@
struct frame_info *, int,
enum lval_type *);
+extern void generic_save_call_dummy_addr (CORE_ADDR lo, CORE_ADDR hi);
+
extern void get_saved_register (char *raw_buffer, int *optimized,
CORE_ADDR * addrp,
struct frame_info *frame,
Index: valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.53
diff -u -r1.53 valops.c
--- valops.c 22 Mar 2002 18:57:08 -0000 1.53
+++ valops.c 14 Apr 2002 14:52:15 -0000
@@ -1385,6 +1385,8 @@
if (CALL_DUMMY_LOCATION == ON_STACK)
{
write_memory (start_sp, (char *) dummy1, sizeof_dummy1);
+ if (USE_GENERIC_DUMMY_FRAMES)
+ generic_save_call_dummy_addr (start_sp, start_sp + sizeof_dummy1);
}
if (CALL_DUMMY_LOCATION == BEFORE_TEXT_END)
@@ -1401,6 +1403,8 @@
sp = old_sp;
real_pc = text_end - sizeof_dummy1;
write_memory (real_pc, (char *) dummy1, sizeof_dummy1);
+ if (USE_GENERIC_DUMMY_FRAMES)
+ generic_save_call_dummy_addr (real_pc, real_pc + sizeof_dummy1);
}
if (CALL_DUMMY_LOCATION == AFTER_TEXT_END)
@@ -1412,11 +1416,18 @@
errcode = target_write_memory (real_pc, (char *) dummy1, sizeof_dummy1);
if (errcode != 0)
error ("Cannot write text segment -- call_function failed");
+ if (USE_GENERIC_DUMMY_FRAMES)
+ generic_save_call_dummy_addr (real_pc, real_pc + sizeof_dummy1);
}
if (CALL_DUMMY_LOCATION == AT_ENTRY_POINT)
{
real_pc = funaddr;
+ if (USE_GENERIC_DUMMY_FRAMES)
+ /* NOTE: cagney/2002-04-13: The entry point is going to be
+ modified with a single breakpoint. */
+ generic_save_call_dummy_addr (CALL_DUMMY_ADDRESS (),
+ CALL_DUMMY_ADDRESS () + 1);
}
#ifdef lint