Help with nlist(3c)

Colburn mhc at aicchi.UUCP
Tue Feb 23 01:29:28 AEST 1988


Since there are probably more than one other person who is interested in
this, I thought that I would post it to the net.  

> I found /usr/include/sys/sysinfo.h to be interesting. There is a structure
> sysinfo that I want to get some stuff out of. In this file is:
> extern struct sysinfo sysinfo;
> This is all fine and good, but sysinfo is in /unix. This is not the sort of
> thing you find laying around in a library. How does one ld this sort of
> thing?
> nm -x /unix | grep sysinfo
> gives me:
> sysinfo             |0x00026ea0|extern|                 |      |     |.bss
> 
> I am trying to accomplish this on an AT&T UNIXpc. My guess is that there is
> a trick with the /lib/shlib.ifile that can be made to work, since that must
> be how shared libraries are being done anyway. Please correct me if I'm wrong.
> 
> I want to goof around in the kernal for fun, and this is where I'm stuck
> right now. BTW how does one know the format of /dev/kmem?


One does not know the format of /dev/kmem.  Only the kernel knows.
/dev/kmem is the actual kernel memory image of the currently executing 
kernel.  You can find the address of things in /dev/kmem by using the 
nlist(3c) function.  

The nlist(3c) function will return the address of a named symbol in
/dev/kmem.  In the case of functions and predefined data objects,
the address returned by nlist(3c) will be same as that printed out
by nm(1) (usually anyways :-).

By the way, I would not advise writing to /dev/kmem unless you REALLY know 
what you are doing :-)

As an aside, when using the nlist(3) function as described in the 
3B1 Manual, you must be careful to '#undef  n_name' if you include
a.out.h.  It appears that AT&T and/or Convergent screwed up when writing 
the header files for the UNIX PC.  In the attached program, the #undef in 
the program is required.

Below is a program which will pull the information located in the 
sysinfo, syswait and syserr structures (all defined in the
/usr/include/sys/sysinfo.h header file) and display it on the screen.

One last comment.  The attached program must be run as root, or as some
other id which has read permission to /dev/kmem.  The program itself is
pretty simple.  

I hope that this will help!  Please let me know how you make out.

------------------------------- cut here --------------------------------


/*
 * mnl.c - print out the sysinfo, syswait and syserr structures in /dev/kmem
 *
 * Comments:
 *         This program must be run as root or as some other user which has
 *         read access to /dev/kmem.  This program was written as an example.
 *         It will probably not pass lint, and I don't really care.
 *
 *         BTW: the undef of n_name is required to bypass a bug which 
 *              Convergent dropped into the a.out.h header file.
 *
 * Author: Mark H. Colburn (mark at jhereg.mn.org)
 */


#include <stdio.h>
#include <a.out.h>
#undef n_name
#include <fcntl.h>
#include <sys/sysinfo.h>


struct nlist mynl[] = {
	"sysinfo", 0, 0, 0, 0, 0,
	"syswait", 0, 0, 0, 0, 0,
	"syserr", 0, 0, 0, 0, 0,
	"", 0, 0, 0, 0, 0
};

struct syserr myerr;
struct syswait mywait;
struct sysinfo	mysys;


int
main()
{

	int		fd;

	if (nlist("/unix", mynl) == -1) {
		fprintf(stderr, "Unable perform nlist() call\n");
		perror("");
		exit(1);
	}	
	if ((fd  = open("/dev/kmem", O_RDONLY)) == -1) {
		fprintf(stderr, "Unable open /dev/kmem\n");
		perror("");
		exit(1);
	}
	printf("n_value = %d\n", mynl[0].n_value);
	if (mynl[0].n_value != 0) {
		if (lseek(fd, mynl[0].n_value, 0) != -1 && 
			read(fd, (char *)&mysys, sizeof(mysys)) != -1) {
				printsys();	
		}
		if (lseek(fd, mynl[1].n_value, 0) != -1 && 
			read(fd, (char *)&mywait, sizeof(mywait)) != -1) {
				printwait();	
		}
		if (lseek(fd, mynl[2].n_value, 0) != -1 && 
			read(fd, (char *)&myerr, sizeof(myerr)) != -1) {
				printerr();	
		}
	} else {
		printf("n_value = 0, lookup failed!\n");
	}
	exit(0);
}


printsys()
{
	printf("\nsysinfo:\n");
	printf("cpu[IDLE]   = %d\t", mysys.cpu[CPU_IDLE]);
	printf("cpu[USER]   = %d\n", mysys.cpu[CPU_USER]);
	printf("cpu[KERNAL] = %d\t", mysys.cpu[CPU_KERNAL]);
	printf("cpu[WAIT]   = %d\n", mysys.cpu[CPU_WAIT]);
	printf("wait[IO]    = %d\t", mysys.wait[W_IO]);
	printf("wait[SWAP]  = %d\t", mysys.wait[W_SWAP]);
	printf("wait[PIO]   = %d\n", mysys.wait[W_PIO]);
	printf("bread       = %d\t", mysys.bread);
	printf("bwrite      = %d\n", mysys.bwrite);
	printf("lread       = %d\t", mysys.lread);
	printf("lwrite      = %d\n", mysys.lwrite);
	printf("phread      = %d\t", mysys.phread);
	printf("phwrite     = %d\n", mysys.phwrite);
	printf("swapin      = %d\t", mysys.swapin);
	printf("swapout     = %d\n", mysys.swapout);
	printf("bswapin     = %d\t", mysys.bswapin);
	printf("bswapout    = %d\n", mysys.bswapout);
	printf("pswitch     = %d\t", mysys.pswitch);
	printf("syscall     = %d\n", mysys.syscall);
	printf("sysread     = %d\t", mysys.sysread);
	printf("syswrite    = %d\n", mysys.syswrite);
	printf("sysfork     = %d\t", mysys.sysfork);
	printf("sysexec     = %d\n", mysys.sysexec);
	printf("runque      = %d\t", mysys.runque);
	printf("runocc      = %d\n", mysys.runocc);
	printf("swpque      = %d\t", mysys.swpque);
	printf("swpocc      = %d\n", mysys.swpocc);
	printf("iget        = %d\t", mysys.iget);
	printf("namei       = %d\t", mysys.namei);
	printf("dirblk      = %d\n", mysys.dirblk);
	printf("readch      = %d\t", mysys.readch);
	printf("writech     = %d\n", mysys.writech);
	printf("rcvint      = %d\t", mysys.rcvint);
	printf("xmtint      = %d\t", mysys.xmtint);
	printf("mdmint      = %d\n", mysys.mdmint);
	printf("rawch       = %d\t", mysys.rawch);
	printf("canch       = %d\t", mysys.canch);
	printf("outch       = %d\n", mysys.outch);
	printf("msg         = %d\t", mysys.msg);
	printf("sema        = %d\n", mysys.sema);
	printf("pgin        = %d\t", mysys.pgin);
	printf("pgout       = %d\n", mysys.pgout);
}



printwait() 
{
	printf("\nsyswait:\n");
	printf("iowait = %d\t", mywait.iowait);
	printf("swap   = %d\t", mywait.swap);
	printf("physio = %d\n", mywait.physio);
}


printerr() 
{
	printf("\nsyserr:\n");
	printf("inodeovf = %d\t", myerr.inodeovf);
	printf("fileovf  = %d\t", myerr.fileovf);
	printf("textovf  = %d\t", myerr.textovf);
	printf("procovf  = %d\n", myerr.procovf);
}

--
Mark H. Colburn		mark at jhereg.MN.ORG
                        ihnp4!chinet!jhereg!mark



More information about the Unix-pc.sources mailing list