guy@uunet.uu.net (Guy Harris) (08/05/90)
The following may be useful, or it may just be an entertaining toy. It's a device driver for "/dev/vmunix", an idea I came up with a while ago, to deal with the problem of programs such as "ps" that need to get at the kernel file that was booted, to find the kernel's symbol table. Normally, this isn't a headache, but those of you who have installed new kernels, calling them something other than "/vmunix", and then tried to run "ps" or whatever and didn't provide whatever magic argument (if any) tells it to look elsewhere than "/vmunix", know that it can be a nuisance on occasion. With this driver, you open "/dev/vmunix", and you have a file descriptor that lets you read from the kernel file that was booted, even if it's not named "/vmunix", even if it was renamed since the system was booted (as long as you open it once before it gets renamed), or even if it was unlinked since the system was booted - the driver holds onto the vnode, so it doesn't go away (well, modulo the usual NFSisms; if it's unlinked on the client, the system should rename it rather than removing it, but if it's unlinked on the server, you lose). It's quite tiny, only 48 lines of code (counting blank lines and comments :-)). It has an "open()" routine which, the first time it's called, grabs the name handed to the boot PROM (and if it's a null string, defaults to "vmunix"), and opens the file in the current directory with that name. (This first open must be done in the root directory; the best way to do this would be with a toy program run from one of the "/etc/rc*" files. Ideally, this wouldn't be necessary; SunOS does permit a pseudo-device driver, such as this one, to have an "init" routine, but it appears to be called quite early in the boot process, before the system is ready to let you play around with the root file system.) It also has a "read" routine that, if the kernel file was successfully opened, calls the "read" method for the vnode for that file. You need to modify "sun/conf.c" to have an entry for this device. You should be able to just open it and read from it, and get the same data you'd have gotten had you opened the running kernel file. NOTE: this is, of course, maximally useful *only* if you can coerce all kmem-groveling programs to use it. This means whacking on various commands and "libkvm"; either you need source, or you need to patch the binaries to look elsewhere than "/vmunix". I make no claim that this driver can drop in and make this problem magically vanish.... Tested under 4.0.3, on a Sun-3E (well, on an NS5000, but "the difference that makes no difference is no difference"...). I was able to do "cp /dev/vmunix /tmp/vmunix" (from the root directory, so that the first "open" could find the file), and get the currently-running kernel file. The test was under UFS; I've not tried it under NFS, nor under 4.1. No more rigorous testing has been done. If you find bugs - or, even better, find bugs *and* the fixes for same - or have any other comments, send 'em to me. NOTE: this does not constitute a commitment by Auspex to provide this as part of SunOS on our systems. #include <sys/errno.h> #include <sys/param.h> #include <sys/file.h> #include <sys/user.h> #include <sys/uio.h> #include <sys/time.h> #include <sys/vnode.h> #include <mon/sunromvec.h> static struct vnode *vmunixvp; /*ARGSUSED*/ int vmunixopen(dev, flags) dev_t dev; int flags; { register struct bootparam *bp; register char *vmunix_name; if (vmunixvp == NULL) { bp = (*romp->v_bootparam); vmunix_name = bp->bp_name; if (vmunix_name[0] == '\0') { /* * No name given when booting; assume it was * "vmunix". */ vmunix_name = "vmunix"; } return (vn_open(vmunix_name, UIO_SYSSPACE, FREAD, 0, &vmunixvp)); } else return (0); } /*ARGSUSED*/ int vmunixread(dev, uio) dev_t dev; register struct uio *uio; { if (vmunixvp == NULL) return (ENOENT); return (VOP_RDWR(vmunixvp, uio, UIO_READ, 0, u.u_cred)); }