Re: internal-error: insert_step_resume_breakpoint_at_sal

Andrew Cagney
2005-02-06T07:16:00Z

[chug chug chug]

This is what I've noticed ...

(gdb) n
infrun: proceed (addr=0xffffffff, signal=144, step=1)
GDB tries to single step off the breakpoint @0x80a05f6, (when doing this
all breakpoints are removed). GDB is expecting to get a SIGTRAP back ...

infrun: resume (step=1, signal=0)
target_terminal_inferior ()
child:target_xfer_partial (2, (null), 0xbffff18a, 0x0, 0x80a05f6, 2) =
2, bytes = 8b 45
target_resume (2896, step, 0)
infrun: wait_for_inferior

... but instead the inferior executes _no_ instructions and instead
returns a [pending] SIGIO (still @0x80a05f6) ...

target_wait (-1, status) = 2896, status->kind = stopped, signal = SIGIO
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
target_fetch_registers (eip) = f6050a08 0x80a05f6 134874614
infrun: stop_pc = 0x80a05f6
infrun: random signal 23
... so GDB again tries to step the inferior, this time passing in the
SIGNAL, and expecting back a SIGTRAP when the inferior reaches the
signal handlers first instruction ...

[wonder if, for this case GDB can insert all breakpoints and do a continue]

infrun: resume (step=1, signal=23)
target_terminal_inferior ()
child:target_xfer_partial (2, (null), 0xbfffeffa, 0x0, 0x80a05f6, 2) =
2, bytes = 8b 45
target_resume (2896, step, SIGIO)
infrun: prepare_to_wait

... but instead GDB gets back another pending SIGIO with the PC still
back at the original BP instruction!

=> that's a known kernel bug. Instead of single-stepping into the
signal handler, the kernel runs the signal handler to completion. Fixed
in very recent 2.6 kernels.

... so gdb tries again to step into the signal handler again (remember,
GDB's expecting the inferior to return a sigtrap from the process
reaching the signal handler's first instruction) ...

target_wait (-1, status) = 2896, status->kind = stopped, signal = SIGIO
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
target_fetch_registers (eip) = f6050a08 0x80a05f6 134874614
infrun: stop_pc = 0x80a05f6
infrun: random signal 23
infrun: resume (step=1, signal=23)
target_terminal_inferior ()
child:target_xfer_partial (2, (null), 0xbfffeffa, 0x0, 0x80a05f6, 2) =
2, bytes = 8b 45
target_resume (2896, step, SIGIO)
infrun: prepare_to_wait

... but instead the signal handler runs, returns, and then executes
_one_ instruction before trapping!

=> that's part of the same kernel bug

target_wait (-1, status) = 2896, status->kind = stopped, signal = SIGTRAP
target_fetch_registers (eip) = f9050a08 0x80a05f9 134874617
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x80a05f9
infrun: trap expected
infrun: step-resume breakpoint
... so I think we've now got gdb thinking that the inferior got a
sigtrap [tick] indicating that the process reached the handler [cross]
and hence the the inferior should continue until the signal handler
returns ...

child:target_xfer_partial (2, (null), 0x84ff020, 0x0, 0x810bdc0, 1) =
1, bytes =
83
child:target_xfer_partial (2, (null), 0x0, 0x8271b10, 0x810bdc0, 1) =
1, bytes =
cc
target_insert_breakpoint (0x810bdc0, xxx) = 0
child:target_xfer_partial (2, (null), 0x85004c8, 0x0, 0x80e74c1, 1) =
1, bytes = 68
child:target_xfer_partial (2, (null), 0x0, 0x8271b10, 0x80e74c1, 1) =
1, bytes =
cc
target_insert_breakpoint (0x80e74c1, xxx) = 0
child:target_xfer_partial (2, (null), 0x874d058, 0x0, 0x80a05f6, 1) =
1, bytes = 8b
child:target_xfer_partial (2, (null), 0x0, 0x8271b10, 0x80a05f6, 1) =
1, bytes =
cc
target_insert_breakpoint (0x80a05f6, xxx) = 0
child:target_xfer_partial (2, (null), 0x874d348, 0x0, 0x40009bd0, 1) =
1, bytes = c3
child:target_xfer_partial (2, (null), 0x0, 0x8271b10, 0x40009bd0, 1) =
1, bytes =
cc
target_insert_breakpoint (0x40009bd0, xxx) = 0
child:target_xfer_partial (2, (null), 0x8aacb20, 0x0, 0x4000c2e0, 1) =
1, bytes =
55
child:target_xfer_partial (2, (null), 0x0, 0x8271b10, 0x4000c2e0, 1) =
1, bytes =
cc
target_insert_breakpoint (0x4000c2e0, xxx) = 0
child:target_xfer_partial (2, (null), 0x87f2118, 0x0, 0x4032e860, 1) =
1, bytes = 55
child:target_xfer_partial (2, (null), 0x0, 0x8271b10, 0x4032e860, 1) =
1, bytes =
cc
target_insert_breakpoint (0x4032e860, xxx) = 0
infrun: resume (step=0, signal=0)

... consequently GDB inserts breakpoints, including the step-resume
breakpoint at expected signal return address, and continues the target.
The inferior is ment to next run the handler, return, and hit the
step-resume breakpoint. Funny enough this doesn't work (it's well past
that step resume breakpoint).

First thing I'd do is run the sig*.exp tests to see which are failing -
if the kernel's working correctly they all pass.

The next thing we can consider is, for the case of GDB wanting to "next"
over a signal optimizing things so that instead it does a
"continue/signal". That might help a little, but then it might not.

Andrew