Question about stepping on a target which supports multi-threading but can only step the last stopped thread

Antony KING antony.king@st.com
Thu Feb 18 20:25:00 GMT 2010


Hi again :-),

As a result of upgrading to GDB 7.0 from GDB 6.8 I am having to review a
workaround (i.e. bodge) I made to GDB 6.8 in order to handle stepping on
a target which supports multi-threading but which can only single
instruction step the last stopped thread.

The workaround I applied was to always switch to the last stopped thread
before resuming the target (which was the behaviour of GDB in versions
earlier than 6.8 - I cannot remember which). Unfortunately this
workaround as implemented for GDB 6.8 no longer works in GDB 7.0 (due to
the extensive changes) and I am in a quandary as to how to proceed.

As an experiment I checked to see what GDB 7.0 does normally without my
workaround in the following, problematic, scenario:

(gdb) continue
...stops at a break point in thread N...
(gdb) thread M
...we have now selected another thread that is not N...
(gdb) stepi
...my target cannot step thread M so what to do ???...

The trace I see (with target and infrun debugging enabled) is the following:

> infrun: clear_proceed_status_thread (Thread 7)
> infrun: clear_proceed_status_thread (Thread 6)
> infrun: clear_proceed_status_thread (Thread 5)
> infrun: clear_proceed_status_thread (Thread 4)
> infrun: clear_proceed_status_thread (Thread 2)
> infrun: clear_proceed_status_thread (Thread 1)
> infrun: clear_proceed_status_thread (Thread 3)
> infrun: proceed (addr=0xffffffff, signal=144, step=1)
> target_thread_architecture (Thread 3) = 0x9a83270 [sh4]
> target_fetch_registers (sr) = 00000040 0x40000000 1073741824
> target_fetch_registers (pc) = 9e170088 0x8800179e 2281707422
> target_thread_architecture (Thread 3) = 0x9a83270 [sh4]
> target_fetch_registers (sr) = 00000040 0x40000000 1073741824
> target_fetch_registers (pc) = 9e170088 0x8800179e 2281707422
> infrun: resume (step=1, signal=0), trap_expected=1
> target_terminal_inferior ()
> target_resume (42000000, step, 0)
> infrun: wait_for_inferior (treat_exec_as_sigtrap=0)
> target_wait (-1, status) = 42000000,   status->kind = stopped, signal = SIGTRAP
> infrun: target_wait (-1, status) =
> infrun:   42000000 [Thread 3],
> infrun:   status->kind = stopped, signal = SIGTRAP
> target_thread_architecture (Thread 3) = 0x9a83270 [sh4]
> infrun: infwait_normal_state
> infrun: TARGET_WAITKIND_STOPPED
> target_fetch_registers (sr) = 00000040 0x40000000 1073741824
> target_fetch_registers (pc) = a0170088 0x880017a0 2281707424
> infrun: stop_pc = 0x880017a0
> target_stopped_by_watchpoint () = 0
> infrun: handling deferred step
> target_thread_architecture (Thread 7) = 0x9a83270 [sh4]
> target_fetch_registers (sr) = 00000040 0x40000000 1073741824
> target_fetch_registers (pc) = 50440088 0x88004450 2281718864
> infrun: resume (step=1, signal=0), trap_expected=0
> target_terminal_inferior ()
> target_terminal_ours ()
> ... a source location is displayed here ...
> target_terminal_ours ()

and the following error is reported by my target's implementation of the
target_resume() method:

  Cannot step 'Thread 7', please select 'Thread 3'

which is a check I added to ensure that GDB doesn't request something
that the target cannot handle.

Due to the error being thrown the above debug output is missing a log
for the final target_resume(), which if I run under a debugger I can see
has the following invocation:

> target_resume (ops=<address>, ptid={pid = -1, lwp = 0, tid = 0}, step=1, signal=TARGET_SIGNAL_0)

At this point ptid is minus_one_ptid, the last stopped ptid is 'Thread
3' and the inferior_ptid is 'Thread 7'. It is my understanding that this
means that GDB wants the target to step 'Thread 7', which is not
supported and hence the error. Note that the invocation of the first
target_resume() looked like the following:

> target_resume (ops=<address>, ptid={pid = 42000000, lwp = 0, tid = 3}, step=1, signal=TARGET_SIGNAL_0)

Note that the initial step of 'Thread 3' above is due to there being a
S/W breakpoint being hit when the target stopped and GDB seems to want
to step over it before stepping 'Thread 7', which I assume is intended
logic.

Now some questions :-):

* Is my interpretation of the meaning of the target_resume() parameters
still valid for GDB 7.0 ?

* If it is correct, then is there a mechanism in GDB to honour the
restrictions of my target model without me needing to re-instate my
original workaround or forcing the user to switch to the only runnable
thread ?

Any advice gratefully received.

Cheers,

Antony.



More information about the Gdb mailing list