From: Andrew Cagney Date: Fri, 26 Apr 2002 03:37:42 +0000 (+0000) Subject: * valops.c (hand_function_call): Call X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6096c27ac0ed55998d2c8d887254c75a19afca0d;p=binutils-gdb.git * 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. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 8dd3fdd10dc..e91880f33f1 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,16 @@ +2002-04-25 Andrew Cagney + + * 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. + 2002-04-24 David S. Miller * sparc-tdep.c (sparc_gdbarch_skip_prologue): Kill, duplicates diff --git a/gdb/blockframe.c b/gdb/blockframe.c index 3150f8884e8..6f2a796049f 100644 --- a/gdb/blockframe.c +++ b/gdb/blockframe.c @@ -1070,42 +1070,59 @@ struct dummy_frame 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 @@ -1170,6 +1187,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 real stack frame. */ diff --git a/gdb/frame.h b/gdb/frame.h index 2b7bf41a239..aca2e259a95 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -285,6 +285,8 @@ extern void generic_get_saved_register (char *, int *, CORE_ADDR *, 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, diff --git a/gdb/valops.c b/gdb/valops.c index 16d3c8cf3a2..86c31122b3b 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -1385,6 +1385,8 @@ hand_function_call (struct value *function, int nargs, struct value **args) 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 @@ hand_function_call (struct value *function, int nargs, struct value **args) 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 @@ hand_function_call (struct value *function, int nargs, struct value **args) 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