|
From: Chris J. <ch...@at...> - 2004-08-27 08:08:47
|
As some of you may know I developed a patch for Valgrind 2.0.0 that = allowed one to perform live debugging of programs running under Valgrind. = However the patch was never included in Valgrind CVS because the members of this list were unsure that using a shared memory region for to access the Valgrind's thread state was the best way to solve the problem. I agreed = with this analysis - exposing internal structures isn't future proof and also required changes to GDB. After careful thought I have come up with another design which I think = is more satisfactory. The basic idea is to write a function called = VG_(ptrace) which would have ptrace-like functionality, i.e. it would give access to = the simulated state of Valgrind's threads, etc. Then we link in GDB's remote debugging server with Valgrind, porting it to the new ptrace function. Valgrind processes will now be remote debugging targets for GDB. A small Valgrind target stub could be written for GDB which would launch and = connect to Valgrind processes transparently to hide the details of the mechanism from the users. Comments and criticism welcome. Regards, Chris January -- http://www.atomice.com |
|
From: Bryan O'S. <bo...@se...> - 2004-08-27 16:42:24
|
On Fri, 2004-08-27 at 09:10 +0100, Chris January wrote: > After careful thought I have come up with another design which I think is > more satisfactory. The basic idea is to write a function called VG_(ptrace) > which would have ptrace-like functionality, i.e. it would give access to the > simulated state of Valgrind's threads, etc. Then we link in GDB's remote > debugging server with Valgrind, porting it to the new ptrace function. Why not just get VG to implement GDB's remote debugging protocol directly? It's quite simple, and the protocol has been stable for a long time. That way, you don't have to modify GDB at all. This is doubly desirable since GDB evolves at a glacial pace. <b |
|
From: Chris J. <ch...@at...> - 2004-08-27 20:01:27
|
> > After careful thought I have come up with another design > which I think > > is more satisfactory. The basic idea is to write a function called > > VG_(ptrace) which would have ptrace-like functionality, > i.e. it would > > give access to the simulated state of Valgrind's threads, > etc. Then we > > link in GDB's remote debugging server with Valgrind, > porting it to the > > new ptrace function. > > Why not just get VG to implement GDB's remote debugging > protocol directly? It's quite simple, and the protocol has > been stable for a long time. That way, you don't have to > modify GDB at all. This is doubly desirable since GDB > evolves at a glacial pace. That was what I proposed however to keep the GDB debugging protocol server separate I suggested a VG_(ptrace) function which exposed all the functionality required to support it. Chris |
|
From: Bob F. <bfr...@si...> - 2004-08-27 21:04:35
|
On Fri, 27 Aug 2004, Chris January wrote: > >>> After careful thought I have come up with another design >> which I think >>> is more satisfactory. The basic idea is to write a function called >>> VG_(ptrace) which would have ptrace-like functionality, >> i.e. it would >>> give access to the simulated state of Valgrind's threads, >> etc. Then we >>> link in GDB's remote debugging server with Valgrind, >> porting it to the >>> new ptrace function. >> >> Why not just get VG to implement GDB's remote debugging >> protocol directly? It's quite simple, and the protocol has >> been stable for a long time. That way, you don't have to >> modify GDB at all. This is doubly desirable since GDB >> evolves at a glacial pace. > > That was what I proposed however to keep the GDB debugging protocol server > separate I suggested a VG_(ptrace) function which exposed all the > functionality required to support it. The two schemes are quite different. Ptrace is a way to control a subordinate process and get/set data to/from it. Ptrace is pretty gross, and requires the debugger to be aware of the memory layout (which is tweaked to non-standard configurations by valgrind). It is highly likely that GDB uses alternate means to access the process address space besides ptraces's primitive access, which would make it very difficult for valgrind to "virtualize" the process. I don't think that emulating "ptrace" makes much sense for valgrind. If valgrind implements the remote debugging protocol "directly" as would be done for an embedded environment, then the process would need to control itself. Valgrind's stub would need to virtualize the environment so that GDB thinks that it is debugging a normal OS application. The big question is if a Unix process is able to provide the control necessary to properly support a debugging stub. A third possibility is to implement a modified gdbserver which knows about valgrind so that it can use the existing Linux ptrace to control the process, but virtualize the process footprint so GDB itself doesn't need to be modified. GDB <---> <-- vgdbserver --> valgrind/process Bob ====================================== Bob Friesenhahn bfr...@si... http://www.simplesystems.org/users/bfriesen |
|
From: Jeremy F. <je...@go...> - 2004-08-27 21:58:37
|
On Fri, 2004-08-27 at 16:04 -0500, Bob Friesenhahn wrote: > The two schemes are quite different. Ptrace is a way to control a > subordinate process and get/set data to/from it. I think Chris understands that - he's just proposing an internal API, which is somewhat analogous to the ptrace syscall, to give the gdb server stub access to the per-thread virtual machine state. I don't think ptrace is a particularly good model though. Since the gdbserver will be in the same address space as the client, it can just directly access memory. For thread state, we can do something simple to allow read/modify access to the register state, and to control the thread's execution. There are some interesting questions to resolve though, since we also have Tool metadata associated with all the VM state. Should we (can we?) expose that to GDB, or just make things up when GDB modifies the state? J |
|
From: Bob F. <bfr...@si...> - 2004-08-27 23:12:25
|
On Fri, 27 Aug 2004, Jeremy Fitzhardinge wrote: > On Fri, 2004-08-27 at 16:04 -0500, Bob Friesenhahn wrote: >> The two schemes are quite different. Ptrace is a way to control a >> subordinate process and get/set data to/from it. > > I think Chris understands that - he's just proposing an internal API, > which is somewhat analogous to the ptrace syscall, to give the gdb > server stub access to the per-thread virtual machine state. Ok. The gdb server stub will need to be able to start/stop execution of the rest of the program while still being able to send responses to GDB and accept commands from GDB. I am not sure how to do this from within the context of a Unix process. Normally SIGSTOP would stop all threads in the process. It seems to me that another process is necessary in order to provide the external control. Bob ====================================== Bob Friesenhahn bfr...@si... http://www.simplesystems.org/users/bfriesen |
|
From: Jeremy F. <je...@go...> - 2004-08-27 23:39:18
|
On Fri, 2004-08-27 at 18:12 -0500, Bob Friesenhahn wrote: > Ok. The gdb server stub will need to be able to start/stop execution > of the rest of the program while still being able to send responses to > GDB and accept commands from GDB. I am not sure how to do this from > within the context of a Unix process. Normally SIGSTOP would stop all > threads in the process. It seems to me that another process is > necessary in order to provide the external control. Valgrind is essentially single-threaded internally, so if the gdb stub is running out of the scheduler thread, then nothing else is going on while it runs. I don't think any other processes would help at all. J |
|
From: Bob F. <bfr...@si...> - 2004-08-28 00:20:19
|
On Fri, 27 Aug 2004, Jeremy Fitzhardinge wrote: > On Fri, 2004-08-27 at 18:12 -0500, Bob Friesenhahn wrote: >> Ok. The gdb server stub will need to be able to start/stop execution >> of the rest of the program while still being able to send responses to >> GDB and accept commands from GDB. I am not sure how to do this from >> within the context of a Unix process. Normally SIGSTOP would stop all >> threads in the process. It seems to me that another process is >> necessary in order to provide the external control. > > Valgrind is essentially single-threaded internally, so if the gdb stub > is running out of the scheduler thread, then nothing else is going on > while it runs. I don't think any other processes would help at all. Great. However, it seems difficult to me to single-step through lines of code or instructions. Either two threads of control are necessary, or it must be possible to switch back and forth between execution contexts with great precision. I think that breakpoints would need to be implemented via signals. Bob ====================================== Bob Friesenhahn bfr...@si... http://www.simplesystems.org/users/bfriesen |
|
From: Paul M. <pa...@sa...> - 2004-08-28 01:09:43
|
Bob Friesenhahn writes: > Great. However, it seems difficult to me to single-step through lines > of code or instructions. Either two threads of control are necessary, > or it must be possible to switch back and forth between execution > contexts with great precision. I think that breakpoints would need to > be implemented via signals. Why? In valgrind, we *are* the cpu. :) Doing this would mean some changes to the scheduler, but not massive changes. I would think that V would have a socket open to gdb. We would drop the number of BBs that get executed in a bunch from 50000 to say 1000 or less. We would put a poll or select call in the scheduler to check for stuff from gdb, and if there is stuff, we call the gdbstub code. That can read/write memory and cpu registers by itself just fine, and if it wants to suspend execution for a while, it just does a blocking read on the socket. If it wants to write a breakpoint, it writes it, and calls a routine from vg_transtab.c to invalidate any translation of the code where the breakpoint is set. (Yes, this is slow, but we're debugging, so it doesn't matter - and if it does, I have a scheme that I use on PPC that makes invalidating translations much faster.) If it wants to send a signal it calls the routines we already have for delivering a signal on simulated cpu. The remaining thing is single-stepping. Here I think the thing is for the gdbstub routine to return a code to the scheduler indicating single-stepping, after having invalidated the translation (if any) for the current eip. That sets a 'single-stepping' flag, and on the next call to VG_(translate) we pass a parameter (a new parameter) indicating that we want it to translate at most one instruction. We execute that and then call the gdbstub again. We probably also need a new return code from run_thread_for_a_while to indicate that we have hit a breakpoint instruction. That should just about do it. For extra marks, we could subsequently implement "hardware" instruction and data address breakpoints. :) Paul. |
|
From: Jeremy F. <je...@go...> - 2004-08-28 05:53:53
|
On Sat, 2004-08-28 at 11:09 +1000, Paul Mackerras wrote: > I would think that V would have a socket open to gdb. We would drop > the number of BBs that get executed in a bunch from 50000 to say 1000 > or less. We would put a poll or select call in the scheduler to check > for stuff from gdb, and if there is stuff, we call the gdbstub code. Yes, the idle() function already does a poll() to see if there's anything interesting to do, so adding a gdb connection socket fd is trivial. > That can read/write memory and cpu registers by itself just fine, and > if it wants to suspend execution for a while, it just does a blocking > read on the socket. If it wants to write a breakpoint, it writes it, > and calls a routine from vg_transtab.c to invalidate any translation > of the code where the breakpoint is set. If the code you're breakpointing has already been translated, you could probably pretty easily modify the translated code in-place to do the breakpoint. > The remaining thing is single-stepping. Here I think the thing is for > the gdbstub routine to return a code to the scheduler indicating > single-stepping, after having invalidated the translation (if any) for > the current eip. That sets a 'single-stepping' flag, and on the next > call to VG_(translate) we pass a parameter (a new parameter) > indicating that we want it to translate at most one instruction. We > execute that and then call the gdbstub again. We probably also need > a new return code from run_thread_for_a_while to indicate that we have > hit a breakpoint instruction. There's already a --single-step=yes option, which translates every instruction as its own basic block. You could just implicitly set that when you enable the gdb server. > That should just about do it. For extra marks, we could subsequently > implement "hardware" instruction and data address breakpoints. :) Robert Walsh already has some watchpoint machinery. J |
|
From: Chris J. <ch...@at...> - 2004-08-28 09:17:41
|
> On Sat, 2004-08-28 at 11:09 +1000, Paul Mackerras wrote: > > I would think that V would have a socket open to gdb. We > would drop > > the number of BBs that get executed in a bunch from 50000 > to say 1000 > > or less. We would put a poll or select call in the > scheduler to check > > for stuff from gdb, and if there is stuff, we call the gdbstub code. > > Yes, the idle() function already does a poll() to see if > there's anything interesting to do, so adding a gdb > connection socket fd is trivial. > > > That can read/write memory and cpu registers by itself just > fine, and > > if it wants to suspend execution for a while, it just does > a blocking > > read on the socket. If it wants to write a breakpoint, it > writes it, > > and calls a routine from vg_transtab.c to invalidate any > translation > > of the code where the breakpoint is set. > > If the code you're breakpointing has already been translated, > you could probably pretty easily modify the translated code > in-place to do the breakpoint. > > > The remaining thing is single-stepping. Here I think the > thing is for > > the gdbstub routine to return a code to the scheduler indicating > > single-stepping, after having invalidated the translation > (if any) for > > the current eip. That sets a 'single-stepping' flag, and > on the next > > call to VG_(translate) we pass a parameter (a new parameter) > > indicating that we want it to translate at most one > instruction. We > > execute that and then call the gdbstub again. We probably > also need a > > new return code from run_thread_for_a_while to indicate > that we have > > hit a breakpoint instruction. > > There's already a --single-step=yes option, which translates > every instruction as its own basic block. You could just > implicitly set that when you enable the gdb server. I've already solved the problems associated with inserting breakpoints, single stepping etc. (see http://www.atomice.com/gdb-valgrind.html). Chris |