[GSoC weekly report#10]implement basic gdbserver(3)

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.

[GSoC weekly report#9]implement basic gdbserver(2)

After I set breakpoint, the gdbserver will go wrong. In gdb side will complain that "PC register is not avaliable". 

This is main problem this week I meet. Now the gdb can attach to the gdbserver, and run the continue command. Sadly to say, it just can resume the   inferior one time because can't set breakpoint yet.

I think the problem is in fetch_register(), I will solve this soon.

(not finished...)

[GSoC weekly report#8]implement basic gdbserver

According to Youpi's adivice, I planing build gdbserver from scratch. As say, implement the basic gdbserver first, then add more feature one by one. But I also borrow code from the gdb part.

Reference for the implementation of the lynxOS port of gdbserver(because this port is much simpler than linux's), I have summarized the basic framework of how to implement a gdbserver.

1. Implement gnu_create_inferior(); which fork and exec the inferior and initialize the process list. The Hurd port of gdb have two specific core structures, such as structure inf which describe the state of the inferior and structure proc which describe the thread info of the inferior. And now I have put this two structures into gdbserver's process list and thread list reference by the pointer private_data and target_data respective.

2. Implement gnu_wait_1(). which does the actual work of set the wait_status. This is the most import function in gdbserver. Gdbserver only care of this three wait_kinds,TARGET_WAITKIND_EXITED,TARGET_WAITKIND_SIGNALED,TARGET_WAITKIND_STOPPED and should take care of the SIGNAL_TRAP when meet TARGET_WAITKING_STOPPED.

3. Implement the gnu_remuse() which recover  the inferior's execution.

Now I have meet a tiny problem, when I use gdb to attach gdbserver, it replied "Remote connection closed".  I will debug it and fix this. Before this weekend,  my gdbserver should work I think.

 

[GSoC weekly report#7]build gdbserver on GNU/Hurd

This week I have try to build gdbserver on hurd. And it works, but can't do any debugger stuffs, just a program named gdbserver which stays in gdb's build hierarchy.

When I begin to add function pointer to structure target_ops one by one, I have met a design problem, as says, how to implement gdbserver on GNU/Hurd? Should I implement gdbserver from scratch and then add features one by one or borrow code from gdb's implemention and then omit useless parts?

The latter, I must say, there are big gap between gdb's interface and gdbserver's. The gdbserver is much simpler than gdb that just care of the target side doesn't consider of the symbol side. Gdbserver implement many interfaces and structures simply than gdb (such like thread-part, target-ops etc). So I don't know how to decide which interface should be omit or simplify.

For instance, There are 6110 lines in the linux-low.c which is the main part of linux gdbserver's implemention.(BTW, there are only 5320 lines in linux-nat.c which is the main part of linux gdb's impemention). And there are only 723 lines in lynx-low.c which is the main part of LynxOS porting.

Which principle should I follow when I make the decision?