Last week I have implement fetch_register() relate functions. And I have finished memory-access functions. The problem I have met now is that the gdbserver can't resume from a breakpoint.
From my understanding now, the problem is not relate to the resume part but the inferior thread management.
Firstly, gdb will set breakpoint on dl_debug_state() to get dynamic load informations, from gdbserver with --remote-debug, I have found this
getpkt ("Z0,fad0,1"); [no ack sent]
putpkt ("$#00"); [noack mode]
getpkt ("mfad0,1"); [no ack sent]
putpkt ("$55#6a"); [noack mode]
getpkt ("Xfad0,0:"); [no ack sent]
before write, read data=55 89 e5 5d
after write, read data=55 89 e5 5d
putpkt ("$OK#9a"); [noack mode]
getpkt ("Xfad0,1:); [no ack sent]
before write, read data=55 89 e5 5d
after write, read data=cc 89 e5 5d
putpkt ("$OK#9a"); [noack mode]
($data#checksum) is the basic gdb remote protocol. And 0xfad0 is the address of _dl_debug_state on my hurd-box, and (Z0,addr,kind) command is request for inserting a memory breakpoint at addr. But on hurd porting of gdb doesn't support Z0 command, so gdbserver reply ($#00) which means command not support. So gdb send anther request, (m,addr,size) to read the momery and (X,addr,size,value) to change the momery. In the last two line, we can see the 0xfad0 is change to 0xCC which present the int 3 intruction.
After I input a continue command on the gdb side, I will get this:
getpkt ("vCont;c"); [no ack sent]
putpkt("$T0505:e44d0201;04:084d0201;08:d1fa0* ;thread:0;#f3"); [noack mode]
...
getpkt ("P8=d0fa0000"); [no ack sent]
...
getpkt ("Xfad0,1:U"); [no ack sent]
before write, read data=cc 89 e5 5d
after write, read data=55 89 e5 5d
putpkt ("$OK#9a"); [noack mode]
getpkt ("QPassSignals:"); [no ack sent]
putpkt ("$OK#9a"); [noack mode]
getpkt ("vCont;s:0;c:0"); [no ack sent]
I have omit some not relate output. This part have show three things. Firstly, when gdbserver get the "vCont;c" command, it will send a response to the gdb with the thread's information like ("$T0505:e44d0201;04:084d0201;08:d1fa0* ;thread:0;#f3"); d1fa0* means the eip is at 0x0000fad1 (because we have set a breakpoint at 0x0000fad0). Secondly, gdb will request gdbserver set the corrtect eip when recovery from the breakpoint, as we see ("P8=d0fa0000") to set eip to the origin value and remove the breakpoint ("Xfad0,1:U"). Last, gdbserver will get a ("vCont;s:0;c:0") packet, this means 's' step thread-id '0' and 'c' continue thread-id '0'. This is the problem, gdb get this thread-id from the packet putpkt("$T0505:e44d0201;04:084d0201;08:d1fa0* ;thread:0;");
when in the porting of linux gdbserver, the packet are
putpkt("$T0505:e0faffbf;04:bcf9ffbf;08:51e51100;thread:p53fa.53fa;core:0;#2a");
getpkt ("vCont;s:p53fa.53fa");
Now I am digging into the problem.
================edit ===============================
the problem is caused by the wrong use of structure ptid_t in gdbserver. Seems the gdbserver regard the field lwp as field tid. I found a comment from lynx-low.c
/* brobecker/2010-06-21: It looks like the LWP field in ptids should be distinct for each thread (see write_ptid where it writes the thread ID from the LWP). So instead of storing the LynxOS tid in the tid field of the ptid, we store it in
the lwp field. */
I just modify code to adapt to this, the continue problem is gone.