In case anyone's interested, I've
written a fairly substantial beginning of a module that provides a
user-space interface to utrace. The interface to the module consists
of a collection of /proc/utrace entries that can be accessed via
read(), write(), and ioctl(). The module supports, via a registration
procedure, any number of concurrent clients such as frysk or any other
debugger that needs the capabilities utrace offers, and for each
registered client supports any number of attached processes.|
A present, the module provides a number of basic services, including:
For every client process, two /proc entries are created, /proc/utrace/$PID/cmd, and /proc/utrace/$PID/resp (where $PID is that of the client process). The first of these, via write() (or pwrite()) and ioctl() are used by clients to control the behavior of the module and to synchronously extract information. The "resp" entry is intended to be the file associated with a blocking read() and provides a means by which asynchronous utrace report_* callbacks can notify the client that various events (such as syscalls, execs, clones, exits, signals, etc.) have occurred. (Use of this capability requires two client threads, one for control operations, the other to wait for report_* events.)
There are a lot of obvious capabilities that need implementing: writing regs, writing memory, possibly other capabilities usually provided by various /proc/$PID entries but more efficiently provided by the module, plus whatever else people want. A fairly brief look at uprobes suggests that those capabilities could be given a user-space interface through the module.
Source code for the module is available via cvs at sourceware.org:/cvs/frysk, checkout frysk-utrace. The structure of the code is still in flux, but at the moment it's:
<top>/udb-*.[ch] source for a fake client to test the moduleThe whole lot, including the fake client, the module, and the module i/f, can be built by pounding in "./do_make"--I haven't gotten around to doing anything with automake and the like. You'll need to have the kernel headers installed.
There are two ways to access the kernel: directly via read()s, write()s, and ioctl()s to the module (in the utracer/module directory), or through the interface library in utracer/utracer. The i/f lib source can be mined for examples on how to use the direct fileio i/f; the top-level udb-*.[ch] (mostly--there's still some direct fileio there, but I'm slowly migrating away from it) offers examples of the use of the lib i/f.
Keep in mind that this is pre-alpha level code that, being kernel stuff, may slag your computer completely. (Though the worst it's ever done to my machines is lock the kernel up, and even that hasn't happened in a couple of weeks.)
Another pending i/f I'm planning, and the major reason I implemented the userspace i/f hiding the fileio, is a Java wrapper around the userspace i/f--the fileio passes data in C structs which I'm fairly sure Java doesn't grok. (Caveat: I'm not a Java guy; see the .sig below.)
At the moment, the fake client is i386-only, but all the arch-specific stuff is (or should be...) contained in the files udb-i386.[ch]. With a bit of porting and a brighter configure/build process, it shouldn't be hard to support other archs. So far as I know, the module and the interface lib are arch-independent (at least, any arch-dependent bits are taken care of by the kernel config of the kernel headers).
Have fun; comments welcome,
-- Chris Moller Java: the blunt scissors of programming languages. -- Dave Thomas
Description: OpenPGP digital signature