Valgrind is an extremely useful debugging tool for memory errors. (And some other kinds of hard-to-find errors too.) Aside from being useful for program development in general, a Hurd port will help finding out why certain programs segfault on the Hurd, although they work on Linux. Even more importantly, it will help finding bugs in the Hurd servers themselfs.

To keep track of memory use, Valgrind however needs to know how each system call affects the validity of memory regions. This knowledge is highly kernel-specific, and thus Valgrind needs to be explicitely ported for every system.

Such a port involves two major steps: making Valgrind understand how kernel traps work in general on the system in question; and how all the individual kernel calls affect memory. The latter step is where most of the work is, as the behaviour of each single system call needs to be described.

Compared to Linux, Mach (the microkernel used by the Hurd) has very few kernel traps. Almost all system calls are implemented as RPCs instead -- either handled by Mach itself, or by the various Hurd servers. All RPCs use a pair of mach_msg() invocations: one to send a request message, and one to receive a reply. However, while all RPCs use the same mach_msg() trap, the actual effect of the call varies greatly depending on which RPC is invoked -- similar to the ioctl() call on Linux. Each request thus must be handled individually.

Unlike ioctl(), the RPC invocations have explicit type information for the parameters though, which can be retrieved from the message header. By analyzing the parameters of the RPC reply message, Valgrind can know exactly which memory regions are affected by that call, even without specific knowledge of the RPC in question. Thus implementing a general parser for the reply messages will already give Valgrind a fairly good approximation of memory validity -- without having to specify the exact semantic of each RPC by hand.

While this should make Valgrind quite usable on the Hurd already, it's not perfect: some RPCs might return a buffer that is only partially filled with valid data; or some reply parameters might be optional, and only contain valid data under certain conditions. Such specific semantics can't be deduced from the message headers alone. Thus for a complete port, it will still be necessary to go through the list of all known RPCs, and implement special handling in Valgrind for those RPCs that need it. Reading the source code of the rpctrace tool would probably be useful to understand how the RPC message can be parsed.

The goal of this task is at minimum to make Valgrind grok Mach traps, and to implement the generic RPC handler. Ideally, specific handling for RPCs needing it should also be implemented.

Completing this project will require digging into Valgrind's handling of system calls (in C), and into Hurd RPCs. It is not an easy task, but a fairly predictable one -- there shouldn't be any unexpected difficulties, and no major design work is necessary. It doesn't require any specific previous knowledge: only good programming skills in general. On the other hand, the student will obtain a good understanding of Hurd RPCs while working on this task, and thus perfect qualifications for Hurd development in general :-)

Possible mentors: Samuel Thibault (youpi)

Exercise: As a starter, students can try to teach valgrind a couple of Linux ioctls, as this will make them learn how to use the read/write primitives of valgrind.