diff options
author | Jeff Law <law@redhat.com> | 1995-06-11 00:03:02 +0000 |
---|---|---|
committer | Jeff Law <law@redhat.com> | 1995-06-11 00:03:02 +0000 |
commit | b7202faa33b382da19f2abf4b306ebdff3b69f8b (patch) | |
tree | 2603b87d3536afb717fb18e8a3ad7b2f4d47ddf0 /gdb/hppa-tdep.c | |
parent | 6167a840e59a21b814d8f14a2c2aebcb5fe52cda (diff) | |
download | gdb-b7202faa33b382da19f2abf4b306ebdff3b69f8b.zip gdb-b7202faa33b382da19f2abf4b306ebdff3b69f8b.tar.gz gdb-b7202faa33b382da19f2abf4b306ebdff3b69f8b.tar.bz2 |
* hppa-tdep.c (frame_chain): Try to compensate for incomplete
register information in core files when backtracing.
Diffstat (limited to 'gdb/hppa-tdep.c')
-rw-r--r-- | gdb/hppa-tdep.c | 63 |
1 files changed, 52 insertions, 11 deletions
diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c index d5595dc..a0f582c 100644 --- a/gdb/hppa-tdep.c +++ b/gdb/hppa-tdep.c @@ -955,6 +955,7 @@ frame_chain (frame) int my_framesize, caller_framesize; struct unwind_table_entry *u; CORE_ADDR frame_base; + struct frame_info *tmp_frame; /* Handle HPUX, BSD, and OSF1 style interrupt frames first. These are easy; at *sp we have a full save state strucutre which we can @@ -1003,9 +1004,10 @@ frame_chain (frame) We use information from unwind descriptors to determine if %r3 is saved into the stack (Entry_GR field has this information). */ - while (frame) + tmp_frame = frame; + while (tmp_frame) { - u = find_unwind_entry (frame->pc); + u = find_unwind_entry (tmp_frame->pc); if (!u) { @@ -1013,34 +1015,73 @@ frame_chain (frame) think anyone has actually written any tools (not even "strip") which leave them out of an executable, so maybe this is a moot point. */ - warning ("Unable to find unwind for PC 0x%x -- Help!", frame->pc); + warning ("Unable to find unwind for PC 0x%x -- Help!", tmp_frame->pc); return 0; } /* Entry_GR specifies the number of callee-saved general registers saved in the stack. It starts at %r3, so %r3 would be 1. */ if (u->Entry_GR >= 1 || u->Save_SP - || frame->signal_handler_caller - || pc_in_interrupt_handler (frame->pc)) + || tmp_frame->signal_handler_caller + || pc_in_interrupt_handler (tmp_frame->pc)) break; else - frame = frame->next; + tmp_frame = tmp_frame->next; } - if (frame) + if (tmp_frame) { /* We may have walked down the chain into a function with a frame pointer. */ if (u->Save_SP - && !frame->signal_handler_caller - && !pc_in_interrupt_handler (frame->pc)) - return read_memory_integer (frame->frame, 4); + && !tmp_frame->signal_handler_caller + && !pc_in_interrupt_handler (tmp_frame->pc)) + return read_memory_integer (tmp_frame->frame, 4); /* %r3 was saved somewhere in the stack. Dig it out. */ else { struct frame_saved_regs saved_regs; - get_frame_saved_regs (frame, &saved_regs); + /* Sick. + + For optimization purposes many kernels don't have the + callee saved registers into the save_state structure upon + entry into the kernel for a syscall; the optimization + is usually turned off if the process is being traced so + that the debugger can get full register state for the + process. + + This scheme works well except for two cases: + + * Attaching to a process when the process is in the + kernel performing a system call (debugger can't get + full register state for the inferior process since + the process wasn't being traced when it entered the + system call). + + * Register state is not complete if the system call + causes the process to core dump. + + + The following heinous code is an attempt to deal with + the lack of register state in a core dump. It will + fail miserably if the function which performs the + system call has a variable sized stack frame. */ + + get_frame_saved_regs (tmp_frame, &saved_regs); + + /* Abominable hack. */ + if (current_target.to_has_execution == 0 + && saved_regs.regs[FLAGS_REGNUM] + && (read_memory_integer (saved_regs.regs[FLAGS_REGNUM], 4) & 0x2)) + { + u = find_unwind_entry (FRAME_SAVED_PC (frame)); + if (!u) + return read_memory_integer (saved_regs.regs[FP_REGNUM], 4); + else + return frame_base - (u->Total_frame_size << 3); + } + return read_memory_integer (saved_regs.regs[FP_REGNUM], 4); } } |