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:

    * Registering and unregistering clients.
    * Attaching and detaching processes for registered clients.
    * Running and quiescing attached processes.
    * Extracting the contents of the register sets supported by utrace
      under the existing architecture.
    * Reading process memory.
    * Extracting the environment strings in effect for attached tasks.
    * Extracting the process memory map

(Some of these services are provided courtesy of utrace, some via other
means available within the kernel.)

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 module
    <top>/utracer/          source tree for the module and its userspace i/f
    <top>/utracer/module    source for the kernel module itself
    <top>/utracer/utracer   source for the userspace i/f to the module
    <top>/utracer/include   headers for use by by the client

The 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.

-- 
Chris Moller

  Java: the blunt scissors of programming languages.
      -- Dave Thomas

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to