diff options
Diffstat (limited to 'gdb/blockframe.c')
-rw-r--r-- | gdb/blockframe.c | 142 |
1 files changed, 109 insertions, 33 deletions
diff --git a/gdb/blockframe.c b/gdb/blockframe.c index 9366ca6..c3b377e 100644 --- a/gdb/blockframe.c +++ b/gdb/blockframe.c @@ -88,13 +88,14 @@ inside_entry_file (addr) return 1; if (symfile_objfile == 0) return 0; -#if CALL_DUMMY_LOCATION == AT_ENTRY_POINT - /* Do not stop backtracing if the pc is in the call dummy - at the entry point. */ -/* FIXME: Won't always work with zeros for the last two arguments */ - if (PC_IN_CALL_DUMMY (addr, 0, 0)) - return 0; -#endif + if (CALL_DUMMY_LOCATION == AT_ENTRY_POINT) + { + /* Do not stop backtracing if the pc is in the call dummy + at the entry point. */ + /* FIXME: Won't always work with zeros for the last two arguments */ + if (PC_IN_CALL_DUMMY (addr, 0, 0)) + return 0; + } return (addr >= symfile_objfile -> ei.entry_file_lowpc && addr < symfile_objfile -> ei.entry_file_highpc); } @@ -148,19 +149,20 @@ CORE_ADDR pc; int inside_entry_func (pc) -CORE_ADDR pc; + CORE_ADDR pc; { if (pc == 0) return 1; if (symfile_objfile == 0) return 0; -#if CALL_DUMMY_LOCATION == AT_ENTRY_POINT - /* Do not stop backtracing if the pc is in the call dummy - at the entry point. */ -/* FIXME: Won't always work with zeros for the last two arguments */ - if (PC_IN_CALL_DUMMY (pc, 0, 0)) - return 0; -#endif + if (CALL_DUMMY_LOCATION == AT_ENTRY_POINT) + { + /* Do not stop backtracing if the pc is in the call dummy + at the entry point. */ + /* FIXME: Won't always work with zeros for the last two arguments */ + if (PC_IN_CALL_DUMMY (pc, 0, 0)) + return 0; + } return (symfile_objfile -> ei.entry_func_lowpc <= pc && symfile_objfile -> ei.entry_func_highpc > pc); } @@ -245,16 +247,6 @@ create_new_frame (addr, pc) return fi; } -/* Return the frame that called FI. - If FI is the original frame (it has no caller), return 0. */ - -struct frame_info * -get_prev_frame (frame) - struct frame_info *frame; -{ - return get_prev_frame_info (frame); -} - /* Return the frame that FRAME calls (NULL if FRAME is the innermost frame). */ @@ -352,7 +344,7 @@ frameless_look_for_prologue (frame) if there is no such frame. */ struct frame_info * -get_prev_frame_info (next_frame) +get_prev_frame (next_frame) struct frame_info *next_frame; { CORE_ADDR address = 0; @@ -1034,7 +1026,72 @@ sigtramp_saved_pc (frame) } #endif /* SIGCONTEXT_PC_OFFSET */ -#ifdef USE_GENERIC_DUMMY_FRAMES + +/* Are we in a call dummy? The code below which allows DECR_PC_AFTER_BREAK + below is for infrun.c, which may give the macro a pc without that + subtracted out. */ + +extern CORE_ADDR text_end; + +int +pc_in_call_dummy_before_text_end (pc, sp, frame_address) + CORE_ADDR pc; + CORE_ADDR sp; + CORE_ADDR frame_address; +{ + return ((pc) >= text_end - CALL_DUMMY_LENGTH + && (pc) <= text_end + DECR_PC_AFTER_BREAK); +} + +int +pc_in_call_dummy_after_text_end (pc, sp, frame_address) + CORE_ADDR pc; + CORE_ADDR sp; + CORE_ADDR frame_address; +{ + return ((pc) >= text_end + && (pc) <= text_end + CALL_DUMMY_LENGTH + DECR_PC_AFTER_BREAK); +} + +/* Is the PC in a call dummy? SP and FRAME_ADDRESS are the bottom and + top of the stack frame which we are checking, where "bottom" and + "top" refer to some section of memory which contains the code for + the call dummy. Calls to this macro assume that the contents of + SP_REGNUM and FP_REGNUM (or the saved values thereof), respectively, + are the things to pass. + + This won't work on the 29k, where SP_REGNUM and FP_REGNUM don't + have that meaning, but the 29k doesn't use ON_STACK. This could be + fixed by generalizing this scheme, perhaps by passing in a frame + and adding a few fields, at least on machines which need them for + PC_IN_CALL_DUMMY. + + Something simpler, like checking for the stack segment, doesn't work, + since various programs (threads implementations, gcc nested function + stubs, etc) may either allocate stack frames in another segment, or + allocate other kinds of code on the stack. */ + +int +pc_in_call_dummy_on_stack (pc, sp, frame_address) + CORE_ADDR pc; + CORE_ADDR sp; + CORE_ADDR frame_address; +{ + return (INNER_THAN ((sp), (pc)) + && (frame_address != 0) + && INNER_THAN ((pc), (frame_address))); +} + +int +pc_in_call_dummy_at_entry_point (pc, sp, frame_address) + CORE_ADDR pc; + CORE_ADDR sp; + CORE_ADDR frame_address; +{ + return ((pc) >= CALL_DUMMY_ADDRESS () + && (pc) <= (CALL_DUMMY_ADDRESS () + DECR_PC_AFTER_BREAK)); +} + /* * GENERIC DUMMY FRAMES @@ -1053,6 +1110,20 @@ sigtramp_saved_pc (frame) * being executed by the target. Also FRAME_CHAIN_VALID as * generic_frame_chain_valid. */ +/* Dummy frame. This saves the processor state just prior to setting + up the inferior function call. Older targets save the registers + target stack (but that really slows down function calls). */ + +struct dummy_frame +{ + struct dummy_frame *next; + + CORE_ADDR pc; + CORE_ADDR fp; + CORE_ADDR sp; + char *registers; +}; + static struct dummy_frame *dummy_frame_stack = NULL; /* Function: find_dummy_frame(pc, fp, sp) @@ -1073,7 +1144,7 @@ generic_find_dummy_frame (pc, fp) dummyframe = dummyframe->next) if (fp == dummyframe->fp || fp == dummyframe->sp) /* The frame in question lies between the saved fp and sp, inclusive */ - return dummyframe->regs; + return dummyframe->registers; return 0; } @@ -1082,12 +1153,14 @@ generic_find_dummy_frame (pc, fp) Return true if this is a dummy frame created by gdb for an inferior call */ int -generic_pc_in_call_dummy (pc, fp) +generic_pc_in_call_dummy (pc, sp, fp) CORE_ADDR pc; + CORE_ADDR sp; CORE_ADDR fp; { /* if find_dummy_frame succeeds, then PC is in a call dummy */ - return (generic_find_dummy_frame (pc, fp) != 0); + /* Note: SP and not FP is passed on. */ + return (generic_find_dummy_frame (pc, sp) != 0); } /* Function: read_register_dummy @@ -1137,10 +1210,12 @@ generic_push_dummy_frame () dummy_frame = dummy_frame->next; dummy_frame = xmalloc (sizeof (struct dummy_frame)); + dummy_frame->registers = xmalloc (REGISTER_BYTES); + dummy_frame->pc = read_register (PC_REGNUM); dummy_frame->sp = read_register (SP_REGNUM); dummy_frame->fp = fp; - read_register_bytes (0, dummy_frame->regs, REGISTER_BYTES); + read_register_bytes (0, dummy_frame->registers, REGISTER_BYTES); dummy_frame->next = dummy_frame_stack; dummy_frame_stack = dummy_frame; } @@ -1174,8 +1249,10 @@ generic_pop_dummy_frame () if (!dummy_frame) error ("Can't pop dummy frame!"); dummy_frame_stack = dummy_frame->next; - write_register_bytes (0, dummy_frame->regs, REGISTER_BYTES); + write_register_bytes (0, dummy_frame->registers, REGISTER_BYTES); flush_cached_frames (); + + free (dummy_frame->registers); free (dummy_frame); } @@ -1292,7 +1369,6 @@ generic_get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval) if (raw_buffer) read_register_gen (regnum, raw_buffer); } -#endif /* USE_GENERIC_DUMMY_FRAMES */ void _initialize_blockframe () |