Re: Multi-packet gdb server request/response - problem?

Ivo Raisr
2013-12-12T15:44:15Z

Hello guys!

After some hackery I think I understand a tiny bit of how remote
support works in gdb.
Request packet "s" ("c") is sent as a part of resume() as can be seen
from the following truss excerpt:

------------------
...
-> remote_serial_write(0xffff80ffbfffef60, 0x5, 0x0, 0x0,
0x18, 0x203a74656b636170)
-> serial_write(0xc195a0, 0xffff80ffbfffef60, 0x5, 0x0,
0x18, 0x203a74656b636170)
-> ser_base_write(0xc195a0, 0xffff80ffbfffef60, 0x5,
0x0, 0x18, 0x203a74656b636170)
-> ser_unix_write_prim(0xc195a0,
0xffff80ffbfffef60, 0x5, 0x0, 0x18, 0x203a74656b636170)
write(9, " $ s # 7 3", 5) = 5
<- ser_unix_write_prim() = 5
<- serial_write() = 0
<- remote_serial_write() = 0
<- putpkt() = 0
<- remote_resume() = 0
...
------------------

However code in resume() does not actively wait for the response.
It is assumed (I think) that target_wait() will do the response handling.
And it initially does, because it does the following:
------------------
for (t = current_target.beneath; t != NULL; t = t->beneath)
{
if (t->to_wait != NULL)
{
ptid_t retval = (*t->to_wait) (t, ptid, status, options);
...
------------------
Initially t->to_wait() is simply remote_wait() which indeed reads the response
packet and parses it.

At some point in the debugging session (not sure when but it does not matter),
I think gdb kicks in the OS-specific functions. For solaris, they are
found in sol-thread.c.
And t->to_wait() is no longer simple remote_wait() but is sol_thread_wait().

At this point, things go awry.
sol_thread_wait() contains the following stuff:
------------------
save_ptid = inferior_ptid;
old_chain = save_inferior_ptid ();

inferior_ptid = thread_to_lwp (inferior_ptid, PIDGET (main_ph.ptid));
if (PIDGET (inferior_ptid) == -1)
inferior_ptid = procfs_first_available ();

...

rtnval = beneath->to_wait (beneath, ptid, ourstatus, options);
------------------

The old remote_wait() function is hidden in the call of "beneath->to_wait()".
However the problem here is that thread_to_lwp() which precedes it is called
_before_ "beneath->to_wait()". And thread_to_lwp() invokes (among others)
target_read_memory() which in turn sends "m" request packet...

Looking at other *-thread.c sources (BSD, DEC, AIX etc.) they usually contain
call to "beneath->to_wait()" as their first thing. So I think the
logic in sol_thread_wait()
is flawed in that "beneath->to_wait()" is not called "early" enough.

I quickly hacked function sol_thread_wait() and removed all calls to
thread_to_lwp()
preceding "beneath->to_wait()". And the conversation with remote stub
is working now!
But now the ptid->lwp conversion is not done properly...

Anyone has any idea of how to overcome this flaw in sol_thread_wait()?

I.