|
From: Chris J. <ch...@at...> - 2005-01-08 16:56:17
|
In which I propose adding a shared library that implements an API for accessing internal Valgrind data structures and tool-specific = information. Some time ago I submitted a patch to implement breakpoints and single stepping in Valgrind. Hopefully that patch can be revisited and = committed at some stage because I have a proposal that builds on that patch to make. As some of you may know I wrote some patches for Valgrind and GDB that allowed GDB to debug processes running under Valgrind. I moved the VG_(threads) structure to a shared memory region so that GDB could read = the register set of the threads from the structure. I also added a control variable to enable single stepping. Now although this method worked fine = it was fragile because GDB needed to have intimate knowledge of the VG_(threads) structure. I later proposed an alternative solution in = which Valgrind provided a GDB server that GDB could connect to. This seemed = like the 'right' solution at the time because GDB didn't need to have special knowledge about Valgrind (or so I thought) and I began implementing it = but didn't have enough time to finish. However now I am revisiting the = problem and have concluded that this idea is not the best solution because: a) it is limited to debuggers implenting the GDB remote debugging = protocol. b) it still needs a specialised Valgrind target for GDB to launch = Valgrind and connect to the server port in one operation. (I suppose it would be feasible to have the user manually launch Valgrind and then have = Valgrind wait for GDB to connect but this is less than ideal.) c) poor support for getting data from Valgrind's tools (e.g. memcheck). = The GDB protocol was never really designed for this. The only problem with the original shared memory implementation was the exposure of internal data structures. To solve this problem I propose = adding a debugging API shared library to Valgrind. This library would be = released as part of the Valgrind package and installed at the same time. The = library could therefore freely use access internal data structures without any problems. Valgrind's core would expose useful debugging information, = such as registers, and debugging control variables such as single stepping = through shared memory as before (either SysV or mmap). The debugging API would = know the structure of this shared memory and access it on behalf of user processes (such as a debugger). We could also add an API to Valgrind for skins to publish similar skin-specific information. The debugging API = would be lightweight and need not necessarily require many changes to = Valgrind. Comments and criticism welcome. Chris -- http://www.atomice.com |
|
From: Jeremy F. <je...@go...> - 2005-01-08 19:53:31
|
On Sat, 2005-01-08 at 16:56 +0000, Chris January wrote:
> This seemed like
> the 'right' solution at the time because GDB didn't need to have special
> knowledge about Valgrind (or so I thought) and I began implementing it but
> didn't have enough time to finish.
How far did you get?
> However now I am revisiting the problem
> and have concluded that this idea is not the best solution because:
> a) it is limited to debuggers implenting the GDB remote debugging protocol.
I'm not terribly worried about that, especially since the set of
debuggers implementing the gdb protocol is vastly larger than the set
using a special Valgrind library.
> b) it still needs a specialised Valgrind target for GDB to launch Valgrind
> and connect to the server port in one operation. (I suppose it would be
> feasible to have the user manually launch Valgrind and then have Valgrind
> wait for GDB to connect but this is less than ideal.)
Valgrind could do that itself, if that were a major concern. One of the
nice things about having gdb separate is that its independent of
Valgrind's terminal I/O, so I think you'd be commonly launching them in
separate windows anyway.
> c) poor support for getting data from Valgrind's tools (e.g. memcheck). The
> GDB protocol was never really designed for this.
Yep, that would be nice to have. Do you have any more concrete
thoughts? It seems like a difficult problem, because there's nothing
generic about a Tool; they can get very special purpose. How does one
represent that on the wire, and how can a generic debugger deal with it
once its there?
> The only problem with the original shared memory implementation was the
> exposure of internal data structures. To solve this problem I propose adding
> a debugging API shared library to Valgrind. This library would be released
> as part of the Valgrind package and installed at the same time. The library
> could therefore freely use access internal data structures without any
> problems. Valgrind's core would expose useful debugging information, such as
> registers, and debugging control variables such as single stepping through
> shared memory as before (either SysV or mmap).
(I don't think shared memory would be a good idea. It would preclude
remote machine access, and adds a complex protocol overhead for
synchronizing between the debugger and the Valgrind threads.)
> The debugging API would know
> the structure of this shared memory and access it on behalf of user
> processes (such as a debugger). We could also add an API to Valgrind for
> skins to publish similar skin-specific information. The debugging API would
> be lightweight and need not necessarily require many changes to Valgrind.
And the other end of the equation? Are you proposing that we modify gdb
to use this API, and maintain those modifications as gdb changes? Do
you have any other debuggers in mind which would use it?
While its certainly possible to do better, it seems that the gdb
protocol has a number of very strong features:
* it exists
* it's stable
* every gdb in the field can already use it
I definitely like the idea of having some way to use the Tool's metadata
in a debugging context, but I think the first step is to get some useful
debugging functionality. Once we have that, we can explore ways of
improving it/replacing it with improvements. Is the protocol really
completely inextensible?
One other thing we could look at is reviving Nick's interactive mode
stuff. I'm guessing it has aged rather a lot.
J
|
|
From: Chris J. <ch...@at...> - 2005-01-08 20:19:36
|
> On Sat, 2005-01-08 at 16:56 +0000, Chris January wrote: > > This seemed like > > the 'right' solution at the time because GDB didn't need to have=20 > > special knowledge about Valgrind (or so I thought) and I began=20 > > implementing it but didn't have enough time to finish. >=20 > How far did you get? I don't remember exactly - it was a number of months ago. >=20 > > However now I am revisiting the problem > > and have concluded that this idea is not the best solution because: > > a) it is limited to debuggers implenting the GDB remote debugging=20 > > protocol. >=20 > I'm not terribly worried about that, especially since the set=20 > of debuggers implementing the gdb protocol is vastly larger=20 > than the set using a special Valgrind library. True. >=20 > > b) it still needs a specialised Valgrind target for GDB to launch=20 > > Valgrind and connect to the server port in one operation.=20 > (I suppose=20 > > it would be feasible to have the user manually launch Valgrind and=20 > > then have Valgrind wait for GDB to connect but this is less than=20 > > ideal.) >=20 > Valgrind could do that itself, if that were a major concern. =20 > One of the nice things about having gdb separate is that its=20 > independent of Valgrind's terminal I/O, so I think you'd be=20 > commonly launching them in separate windows anyway. It hadn't actually occurred to me to do this the other way round = (Valgrind launches GDB) but that could work ok. >=20 > > c) poor support for getting data from Valgrind's tools (e.g.=20 > > memcheck). The GDB protocol was never really designed for this. >=20 > Yep, that would be nice to have. Do you have any more=20 > concrete thoughts? It seems like a difficult problem,=20 > because there's nothing generic about a Tool; they can get=20 > very special purpose. How does one represent that on the=20 > wire, and how can a generic debugger deal with it once its there? Tools would publish their own API helper libraries. These would = interpret the data stored in the tool specific area of the shared memory region. A client could ask the API what information the tool provided. A client = would either request this information as a binary structure, which it would = then need to interpret, or could ask for it in string form in which case it = would be displayed unprocessed to the user. >=20 > > The only problem with the original shared memory implementation was=20 > > the exposure of internal data structures. To solve this problem I=20 > > propose adding a debugging API shared library to Valgrind. This=20 > > library would be released as part of the Valgrind package and=20 > > installed at the same time. The library could therefore freely use=20 > > access internal data structures without any problems.=20 > Valgrind's core=20 > > would expose useful debugging information, such as registers, and=20 > > debugging control variables such as single stepping through shared=20 > > memory as before (either SysV or mmap). >=20 > (I don't think shared memory would be a good idea. It would=20 > preclude remote machine access, and adds a complex protocol=20 > overhead for synchronizing between the debugger and the=20 > Valgrind threads.) It's not difficult to synchronise between the debugger and Valgrind = threads. That is to say, I encountered no problems implementing this. As for remote machine access, see below. >=20 > > The debugging API would know > > the structure of this shared memory and access it on behalf of user=20 > > processes (such as a debugger). We could also add an API to=20 > Valgrind=20 > > for skins to publish similar skin-specific information. =20 > The debugging=20 > > API would be lightweight and need not necessarily require=20 > many changes=20 > > to Valgrind. >=20 > And the other end of the equation? Are you proposing that we=20 > modify gdb to use this API, and maintain those modifications=20 > as gdb changes? Do you have any other debuggers in mind=20 > which would use it? >=20 > While its certainly possible to do better, it seems that the=20 > gdb protocol has a number of very strong features: > * it exists > * it's stable > * every gdb in the field can already use it The advantage of the debugging API is you can implement the GDB protocol atop of it (e.g. for remote debugging or to support debuggers without a Valgrind target), but you are not limited to it. It also means the GDB server can be a separate component, whereas without the API it would be = more closely coupled to the Valgrind core. >=20 > I definitely like the idea of having some way to use the=20 > Tool's metadata in a debugging context, but I think the first=20 > step is to get some useful debugging functionality. Once we=20 > have that, we can explore ways of improving it/replacing it=20 > with improvements. Is the protocol really completely inextensible? I already have a set of patches that implement useful debugging functionality. The current question is what is the 'right' way to do it. = > One other thing we could look at is reviving Nick's=20 > interactive mode stuff. I'm guessing it has aged rather a lot. Chris |
|
From: Jeremy F. <je...@go...> - 2005-01-09 00:15:27
|
On Sat, 2005-01-08 at 20:20 +0000, Chris January wrote: > > Yep, that would be nice to have. Do you have any more > > concrete thoughts? It seems like a difficult problem, > > because there's nothing generic about a Tool; they can get > > very special purpose. How does one represent that on the > > wire, and how can a generic debugger deal with it once its there? > > Tools would publish their own API helper libraries. These would interpret > the data stored in the tool specific area of the shared memory region. A > client could ask the API what information the tool provided. A client would > either request this information as a binary structure, which it would then > need to interpret, or could ask for it in string form in which case it would > be displayed unprocessed to the user. > > > > > > The only problem with the original shared memory implementation was > > > the exposure of internal data structures. To solve this problem I > > > propose adding a debugging API shared library to Valgrind. This > > > library would be released as part of the Valgrind package and > > > installed at the same time. The library could therefore freely use > > > access internal data structures without any problems. > > Valgrind's core > > > would expose useful debugging information, such as registers, and > > > debugging control variables such as single stepping through shared > > > memory as before (either SysV or mmap). > > > > (I don't think shared memory would be a good idea. It would > > preclude remote machine access, and adds a complex protocol > > overhead for synchronizing between the debugger and the > > Valgrind threads.) > > It's not difficult to synchronise between the debugger and Valgrind threads. > That is to say, I encountered no problems implementing this. Well, I've just rearranged the internals again which affects the thread structure. Sure, the basic debugging pattern will be "stop the world; inspect modify state; resume the world", so there isn't much concurrency, but I don't understand what advantage using shared memory offers. Also, now that Valgrind can self-virtualize, you need to be able to deal with multiple Valgrind instances within one process, and be able to distinguish them. > The advantage of the debugging API is you can implement the GDB protocol > atop of it (e.g. for remote debugging or to support debuggers without a > Valgrind target), but you are not limited to it. It also means the GDB > server can be a separate component, whereas without the API it would be more > closely coupled to the Valgrind core. What about the other way around? Is the gdb protocol completely inextensible? I think the internal interface to any debugging protocol driver will be pretty simple anyway, so there's no particular advantage to deep layering. All it needs to be able to do is to be able to drive some async IO and inspect/modify memory and the ThreadState structures. Shared memory would make it more complex by adding more state to manage. J |
|
From: Chris J. <ch...@at...> - 2005-01-09 14:40:56
|
> On Sat, 2005-01-08 at 20:20 +0000, Chris January wrote: > > > Yep, that would be nice to have. Do you have any more > > > concrete thoughts? It seems like a difficult problem,=20 > > > because there's nothing generic about a Tool; they can get=20 > > > very special purpose. How does one represent that on the=20 > > > wire, and how can a generic debugger deal with it once its there? > >=20 > > Tools would publish their own API helper libraries. These would=20 > > interpret the data stored in the tool specific area of the shared=20 > > memory region. A client could ask the API what information the tool=20 > > provided. A client would either request this information as=20 > a binary=20 > > structure, which it would then need to interpret, or could=20 > ask for it=20 > > in string form in which case it would be displayed=20 > unprocessed to the=20 > > user. > >=20 > > >=20 > > > > The only problem with the original shared memory implementation=20 > > > > was > > > > the exposure of internal data structures. To solve this=20 > problem I=20 > > > > propose adding a debugging API shared library to Valgrind. This=20 > > > > library would be released as part of the Valgrind package and=20 > > > > installed at the same time. The library could therefore=20 > freely use=20 > > > > access internal data structures without any problems.=20 > > > Valgrind's core > > > > would expose useful debugging information, such as=20 > registers, and > > > > debugging control variables such as single stepping=20 > through shared=20 > > > > memory as before (either SysV or mmap). > > >=20 > > > (I don't think shared memory would be a good idea. It would > > > preclude remote machine access, and adds a complex protocol=20 > > > overhead for synchronizing between the debugger and the=20 > > > Valgrind threads.) > >=20 > > It's not difficult to synchronise between the debugger and Valgrind=20 > > threads. That is to say, I encountered no problems=20 > implementing this. >=20 > Well, I've just rearranged the internals again which affects=20 > the thread structure. Sure, the basic debugging pattern will=20 > be "stop the world; inspect modify state; resume the world",=20 > so there isn't much concurrency, but I don't understand what=20 > advantage using shared memory offers. You can't inspect or modify the state of the inferior process easily if = it's running under Valgrind because the register sets are not stored in = kernel space, they are stored at an unknown location in the inferior process. Shared memory effectively gives you a known location to look for the register sets and other information.=20 > Also, now that Valgrind can self-virtualize, you need to be=20 > able to deal with multiple Valgrind instances within one=20 > process, and be able to distinguish them. I don't think this is really necessary and GDB doesn't support this kind = of architecture anyway. >=20 > > The advantage of the debugging API is you can implement the GDB=20 > > protocol atop of it (e.g. for remote debugging or to=20 > support debuggers=20 > > without a Valgrind target), but you are not limited to it. It also=20 > > means the GDB server can be a separate component, whereas=20 > without the=20 > > API it would be more closely coupled to the Valgrind core. >=20 > What about the other way around? Is the gdb protocol=20 > completely inextensible? It's inextensible in the sense that any extension would require changes = to GDB which is what we were trying to avoid in the first place. >=20 > I think the internal interface to any debugging protocol=20 > driver will be pretty simple anyway, so there's no particular=20 > advantage to deep layering. All it needs to be able to do is=20 > to be able to drive some async IO and inspect/modify memory=20 > and the ThreadState structures. Shared memory would make it=20 > more complex by adding more state to manage. Shared memory actually reduces the amount of state to manage because you don't have to worry about the inferior process at all - all interaction = is with the shared memory region. Chris |
|
From: Jeremy F. <je...@go...> - 2005-01-10 00:15:34
|
I think we're talking at cross purposes a bit.
I see it as a pretty serious limitation that you can't use gdb on a
program while it runs under Valgrind. If we implement the gdbstub
protocol, we fix this in a very satisfactory way, since its immediately
usable by anyone who has pretty much any version of gdb installed. It's
nice for us too, since the protocol is stable and self-contained, and
won't pose any maintenance headaches. It's the 95% solution.
Sure, it would be nice to get the other 5%, some way of querying Tool
state from within the debugger. That could be solved either by
proposing a new debugger interface, or by trying to squeeze more out of
the gdbstub interface (by, for example, finding some way to set
breakpoints/watchpoints which are triggered by a Tool warning message).
I think the first is really important. We can worry about the second
once the first is in place. Holding back the first 95% of the answer
just so we can get the last 5% doesn't seem like a good tradeoff.
J
|
|
From: Chris J. <ch...@at...> - 2005-01-10 09:18:34
|
> I think we're talking at cross purposes a bit. > I see it as a pretty serious limitation that you can't use gdb on a program while it runs under Valgrind. If > we implement the gdbstub protocol, we fix this in a very satisfactory way, since its immediately usable by > anyone who has pretty much any version of gdb installed. It's nice for us too, since the protocol is stable > and self-contained, and won't pose any maintenance headaches. It's the 95% solution. I agree a gdb stub is very useful. I proposed building it on top of the debugging API rather than directly accessing internal data structures for several reasons: i) it makes the gdb stub even less maintenance. If we design the API well enough to enable forward compatibility then we need never touch the gdb stub code again, even if major internal changes occur. ii) the gdb stub needs access to internal data structures one way or another, be it through an API or directly. If the stub runs in the same address space as the inferior it is prone to corruption by the inferior. Also the Linux clone syscall is non-portable and on other platforms the stub may also share other process characteristics such as files. This could cause problems if, e.g. the inferior tried to close one of the stub's file descriptors. This one of the reasons I proposed using shared memory - it isolates the debugger/stub from the inferior. iii) the gdb stub needs to be able to reliably stop the inferior. This could prove problematic if the stub was actually running in a thread as part of the inferior process. E.g. pending signals would be delivered to the stub thread. I am not suggesting using shared memory because it means we can get that extra 5%, as you put it. I am suggesting it because I believe it to be the simplest and most reliable solution. An API to access that shared memory is then just common sense - it doesn't have to be complicated in any way. Chris |
|
From: Jeremy F. <je...@go...> - 2005-01-10 18:08:21
|
On Mon, 2005-01-10 at 09:18 +0000, Chris January wrote: > i) it makes the gdb stub even less maintenance. If we design the API well > enough to enable forward compatibility then we need never touch the gdb stub > code again, even if major internal changes occur. Well, maybe. gdbstub is so simple, I would be surprised if there were much difference in maintenance difficulty. > ii) the gdb stub needs access to internal data structures one way or > another, be it through an API or directly. If the stub runs in the same > address space as the inferior it is prone to corruption by the inferior. Um, but it won't be. The inferior will be the client running under Valgrind, but gdbstub will be part of Valgrind itself. It as if the CPU has gdbstub built into it. > Also the Linux clone syscall is non-portable and on other platforms the stub > may also share other process characteristics such as files. This could cause > problems if, e.g. the inferior tried to close one of the stub's file > descriptors. This one of the reasons I proposed using shared memory - it > isolates the debugger/stub from the inferior. ? I'm not sure what you're addressing here? Valgrind will only use clone() on Linux systems anyway. > iii) the gdb stub needs to be able to reliably stop the inferior. This could > prove problematic if the stub was actually running in a thread as part of > the inferior process. E.g. pending signals would be delivered to the stub > thread. I wouldn't implement the stub as a separate thread. I think it would be better implemented as an I/O+event-driven coroutine. I wouldn't want to add any extra threads (especially having just got rid of them all). J |
|
From: Chris J. <ch...@at...> - 2005-01-11 09:21:04
|
> > iii) the gdb stub needs to be able to reliably stop the > inferior. This > > could prove problematic if the stub was actually running in > a thread > > as part of the inferior process. E.g. pending signals would be > > delivered to the stub thread. > > I wouldn't implement the stub as a separate thread. I think > it would be better implemented as an I/O+event-driven > coroutine. I wouldn't want to add any extra threads > (especially having just got rid of them all). Then you lose the ability to debug Valgrind itself with GDB. Chris |
|
From: Jeremy F. <je...@go...> - 2005-01-11 10:03:52
|
On Tue, 2005-01-11 at 09:20 +0000, Chris January wrote: > Then you lose the ability to debug Valgrind itself with GDB. You can already debug Valgrind with gdb; that's not the problem I'm addressing. J |
|
From: Chris J. <ch...@at...> - 2005-01-11 10:12:25
|
> On Tue, 2005-01-11 at 09:20 +0000, Chris January wrote: > > Then you lose the ability to debug Valgrind itself with GDB. > > You can already debug Valgrind with gdb; that's not the > problem I'm addressing. I found it much easier to debug problems with Valgrind when all the information was in one place. It seems suplerfluous to me to require to instances of GDB, one to debug Valgrind itself and one to debug the client. Chris |
|
From: Nicholas N. <nj...@ca...> - 2005-01-09 11:27:07
|
On Sat, 8 Jan 2005, Jeremy Fitzhardinge wrote: > One other thing we could look at is reviving Nick's interactive mode > stuff. I'm guessing it has aged rather a lot. Yes. I don't think it was the right way to go, because it duplicated a lot of the GDB stuff anyway. All I really wanted was to be able to call a tool-specified C function from within GDB, but when I tried just doing that I had various problems; sometimes it would work and sometimes it would seg fault. I vaguely remember hearing that GDB's support for such C calls was flaky, but maybe Valgrind's interactions were causing other problems. N |