[comp.sources.misc] v06i019: xlist: Xenix V xlist/kmem utility

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (01/30/89)

Posting-number: Volume 6, Issue 19
Submitted-by: wht@tridom.UUCP (Warren Tucker)
Archive-name: xlist

[People, not everyone's going to read even a "short and sweet" program to
find out why they should save it.  Include README's or at minimum document
it somewhere other than the code.  ++bsa]

This program is short and sweet, so no README or Makefile is included.
It has been tested with SCO XENIX/286 2.2.1 and XENIX/386 2.3.1.

[Since the author didn't document it, I will:

This program displays symbol information from /xenix (it's for Xenix V, and
will most likely be useless for any other OS) and optionally displays the
value of kernel memory at the symbol address.  Usage is:

	xlist symbol[:count] ...

!WARNING! There may be a program called "xlist" in some Xenixes, especially
more recent ones.  Let the installer beware....
++bsa]

#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#
#	Run the following text with /bin/sh to create:
#	  xlist.c
#
sed 's/^X//' << 'SHAR_EOF' > xlist.c &&
X/* CHK=0x935A */
X/* vi: set tabstop=4 shiftwidth=4: */
X/*+-------------------------------------------------------------------------
X    xlist.c - Xenix System V xlist utility
X    by Warren H. Tucker, III. ...!gatech!{emory,kd4nc}!tridom!wht
X
X This program reads and displays /xenix symbol table information using
X xlist and optionally reads and displays /dev/kmem.  See usage() below.
X
X Compile instructions:
X 386: cc -Ox -K xlist.c -o xlist
X 286: cc -M2l -O xlist.c -o xlist
X--------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:01-18-1989-12:26-wht-get ready for net submisssion */
X/*:01-17-1989-19:43-wht-add dump feature and usage */
X/*:01-18-1989-12:25-wht-creation */
X
X#include <stdio.h>
X#include <fcntl.h>
X#include <sys/a.out.h>
X
X#define XENIX_KERNEL "/xenix"
X
X#define UINT8 unsigned char
X#define UINT16 unsigned short
X#define UINT32 unsigned long
X
Xint fd_kmem;
X
Xchar *usage_text[]=
X{
X"usage: xlist arg [ arg ...]\n",
X"where arg is of the form symbol[:count]\n",
X"and symbol is a public symbol in /xenix as shown in a map file (i.e.,\n",
X"with leading underscore as appropriate).  count is a number of bytes\n",
X"prefixed with a colon.  xlist looks up the symbol by xlist'ing /xenix\n",
X"and displays the xlist information on stdout.  If ':count' is present,\n",
X"xlist reads kmem starting at 'symbol' and displays 'count' bytes in hex.\n",
X#if defined(M_I286)
X"On the 286, count is limited to 32767.\n",
X#endif
X(char *)0
X};
X
X/*+-------------------------------------------------------------------------
X    usage()
X--------------------------------------------------------------------------*/
Xvoid
Xusage()
X{
Xregister char **text = usage_text;
X
X    while(*text)
X        fprintf(stderr,*text++);
X    exit(1);
X}   /* end of usage */
X
X#define dump_putc(ch)       fputc((ch),stdout)
X#define dump_puts(str)      fputs(str,stdout)
X
X/*+-----------------------------------------------------------------------
X    hex_dump#... subservient routines
X------------------------------------------------------------------------*/
Xvoid hex_dump4(int4)
XUINT8   int4;
X{
X    int4 &= 15;
X    dump_putc((int4 >= 10) ? (int4 + 'A' - 10) : (int4 + '0'));
X}
X
Xvoid hex_dump8(int8)
XUINT8   int8;
X{
X    hex_dump4(int8 >> 4);
X    hex_dump4(int8);
X}
X
Xvoid hex_dump16(int16)
XUINT16  int16;
X{
X    hex_dump8(int16 >> 8);
X    hex_dump8(int16);
X}
X
Xvoid hex_dump32(int32)
XUINT32  int32;
X{
X    hex_dump16((UINT16)(int32 >> 16));
X    hex_dump16((UINT16)int32);
X}
X
X/*+-----------------------------------------------------------------
X    hex_dump(str,len)
X------------------------------------------------------------------*/
Xvoid
Xhex_dump(str,len,offset)
XUINT8 *str;
Xunsigned int len;
Xlong offset;
X{
Xregister unsigned int itmp;
Xregister unsigned int istr = 0;
X
X    while (istr < len)
X    {
X        hex_dump32(offset + istr);
X        for (itmp = 0; itmp < 16; ++itmp)
X        {
X            dump_putc(' ');
X            if( istr + itmp >= len)
X            {
X                dump_putc(' ');
X                dump_putc(' ');
X                continue;
X            }
X            hex_dump8(str[istr + itmp]);
X        }
X        dump_puts(" | ");
X        for (itmp = 0; itmp < 16; ++itmp)
X        {
X        register char dchar;
X            if(istr + itmp >= len)
X                dump_putc(' ');
X            else
X            {
X                dchar = str[istr + itmp] & 0x7F;
X                dump_putc(((dchar >= ' ') && (dchar < 0x7f)) ? dchar : '.' );
X            }
X        }
X        dump_puts(" |\n");
X        istr += 16;
X    }   /* end of while(istr < len) */
X
X}   /* end of hex_dump */
X
X/*+-------------------------------------------------------------------------
X    dump_kmem(seekpos,length)
X--------------------------------------------------------------------------*/
Xvoid
Xdump_kmem(seekpos,length)
Xlong seekpos;
Xunsigned int length;
X{
Xchar *kmemdata;
Xchar *malloc();
Xlong lseek();
X
X    if((kmemdata = malloc(length)) == NULL)
X    {
X        printf("cannot allocate %u bytes\n",length);
X        return;
X    }
X
X    if(lseek(fd_kmem,seekpos,0) < 0)
X    {
X        fprintf(stderr,"cannot seek kmem (%d) to %08lx",fd_kmem,seekpos);
X        perror("");
X        free(kmemdata);
X        return;
X    }
X
X    if(read(fd_kmem,kmemdata,length) != length)
X    {
X        perror("kmem read");
X        free(kmemdata);
X        return;
X    }
X
X    hex_dump(kmemdata,length,seekpos);
X    free(kmemdata);
X
X}   /* end of dump_kmem */
X
X/*+-------------------------------------------------------------------------
X    open_kmem()
X--------------------------------------------------------------------------*/
Xvoid
Xopen_kmem()
X{
X    if((fd_kmem = open("/dev/kmem",O_RDONLY,0)) < 0)
X    {
X        perror("/dev/kmem");
X        exit(1);
X    }
X}   /* end of open_kmem */
X
X/*+-------------------------------------------------------------------------
X    main(argc,argv,envp)
X--------------------------------------------------------------------------*/
Xmain(argc,argv,envp)
Xint     argc;
Xchar    **argv;
Xchar    **envp;
X{
Xregister int iargv;
Xstruct xlist *xlst;
Xregister struct xlist *xx;
Xint need_kmem = 0;
Xunsigned long *count;
Xchar *cptr;
Xchar *strrchr();
Xchar *calloc();
Xlong atol();
X
X    if(argc < 2)
X        usage();
X
X    if((xlst = (struct xlist *)calloc(argc,sizeof(struct xlist))) ==
X            (struct xlist *)0)
X    {
X        fprintf(stderr,"memory not available\n");
X        exit(1);
X    }
X
X    if((count = (long *)calloc(argc,sizeof(long))) == (long *)0)
X    {
X        fprintf(stderr,"memory not available\n");
X        exit(1);
X    }
X
X    xx = xlst;
X    for(iargv = 1; iargv < argc; iargv++)
X    {
X        if(cptr = strrchr(argv[iargv],':'))
X        {
X            *cptr++ = 0;
X#if defined(M_I286)
X            if((count[iargv - 1] = atol(cptr)) > 32767L)
X            {
X                printf("max count is 32767 on 286: %s\n",argv[iargv]);
X                count[iargv - 1] = 32767;
X            }
X#else
X            count[iargv - 1] = atol(cptr);
X#endif
X            need_kmem = 1;
X        }
X        xx->xl_name = argv[iargv];
X        xx++;
X    }
X
X    xlist(XENIX_KERNEL, xlst);
X
X    if(need_kmem)
X        open_kmem();
X
X    xx = xlst;
X    for(iargv = 1; iargv < argc; iargv++)
X    {
X        if(xx->xl_type == 0)
X        {
X            printf("%s: can't xlist (try _%s ?)\n",
X                xx->xl_name,xx->xl_name);
X            continue;
X        }
X
X        printf("%s  type: %04x seg: %04x value: %08lx\n",
X            xx->xl_name,xx->xl_type,xx->xl_seg,xx->xl_value);
X
X        if(count[iargv - 1])
X            dump_kmem(xx->xl_value,(unsigned int)count[iargv - 1]);
X
X        xx++;
X    }
X
X    exit(0);
X}   /* end of main */
SHAR_EOF
chmod 0644 xlist.c || echo "restore of xlist.c fails"
exit 0