This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
Re: [RFA] Save the call dummy address
- From: Michael Snyder <msnyder at redhat dot com>
- To: Andrew Cagney <ac131313 at cygnus dot com>
- Cc: gdb-patches at sources dot redhat dot com
- Date: Wed, 24 Apr 2002 14:50:50 -0700
- Subject: Re: [RFA] Save the call dummy address
- Organization: Red Hat, Inc.
- References: <3CB99CCC.6010001@cygnus.com>
Andrew Cagney wrote:
>
> 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?
Yes. I wish that the calls to generic_push_dummy_frame,
generic_save_dummy_frame_tos, and generic_save_dummy_frame_addr
could be combined into one (for data locality), but that does
not have to hold up this patch. The spread is getting worse, though...
>
> 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