This is the mail archive of the
mailing list for the GDB project.
Re: Multi-packet gdb server request/response - problem?
- From: Ivo Raisr <ivosh at ivosh dot net>
- To: gdb at sourceware dot org
- Date: Thu, 12 Dec 2013 16:44:04 +0100
- Subject: Re: Multi-packet gdb server request/response - problem?
- Authentication-results: sourceware.org; auth=none
- References: <CANXv6=u1BjBdJJDNtF=j=djNJVoNHo45gL4JZruzDYsaSqEU6Q at mail dot gmail dot com> <1386711973 dot 2226 dot 30 dot camel at soleil> <CANXv6=vFYfEDLPVHv_TRK4VTLmFX6c+2hvmodM9dg3gcJA4_jQ at mail dot gmail dot com> <CANXv6=uV5H9M17qLkSZ+VpX6AqzBBnXRSmK4g1yNyTyExw3SCA at mail dot gmail dot com>
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,
-> serial_write(0xc195a0, 0xffff80ffbfffef60, 0x5, 0x0,
-> ser_base_write(0xc195a0, 0xffff80ffbfffef60, 0x5,
0x0, 0x18, 0x203a74656b636170)
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
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()?