home *** CD-ROM | disk | FTP | other *** search
- /*
- * update_db.c - create/update psdatabase
- *
- * Copyright (c) 1992 Branko Lankester
- *
- * munged into psupdate.c by Michael K. Johnson for the procps suite.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <a.out.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <string.h>
- #include <sys/utsname.h>
- #include "psdata.h"
- #include "ps.h"
-
- #define SYS_PATH "/usr/src/linux/tools/zSystem"
-
-
- int update_psdb(char *syspath);
- int read_nlist(char *systemfile);
- int write_tbl(int fd, struct dbtbl_s *dbtbl, struct tbl_s *tbl);
- void make_fnctbl(void);
- void make_vartbl(void);
- __compar_fn_t addrcmp(struct sym_s *p1, struct sym_s *p2);
- __compar_fn_t varcmp(struct sym_s *p1, struct sym_s *p2);
- unsigned long k_addr(char *sym);
-
- static struct nlist *namelist;
- static int nsym;
- static char *strings;
- static int stringsize;
-
- int main(int argc, char **argv) {
-
- char nsyspath[128];
-
- if(argc == 1)
- update_psdb(SYS_PATH);
- if(argc == 2) {
- sscanf(argv[1], "%s", nsyspath);
- update_psdb(nsyspath);
- }
- return 0;
- }
-
-
- /*
- * Open systemfile, if update is non zero the psdatabase will be
- * updated from sysfile. If sysfile is NULL the system file that
- * was used to create the existing database will be used for
- * updating.
- */
-
- int open_sys(char *sysfile, int update)
- {
-
- if (sysfile == NULL || *sysfile == '\0') {
- if (open_psdb() == -1) {
- #if 0
- if (!update)
- return -1;
- #else
- read_nlist(SYS_PATH);
- #endif
- sysfile = SYS_PATH;
- } else
- sysfile = db_hdr.sys_path;
- } else
- read_nlist(sysfile);
-
- if (update)
- update_psdb(sysfile);
-
- return(0);
- }
-
-
- int update_psdb(char *syspath)
- {
- int fd, sysfd;
- struct utsname uts;
-
- if (namelist == NULL)
- read_nlist(syspath);
-
- close_psdb();
-
- if ((fd = open(PSDATABASE, O_RDWR|O_TRUNC|O_CREAT, 0666)) == -1) {
- perror(PSDATABASE);
- exit(1);
- }
- if (*syspath != '/') {
- memset(db_hdr.sys_path, 0, sizeof db_hdr.sys_path);
- if (getcwd(db_hdr.sys_path, sizeof db_hdr.sys_path - 2) != NULL)
- strcat(db_hdr.sys_path, "/");
- strncat(db_hdr.sys_path, syspath, sizeof db_hdr.sys_path -
- strlen(db_hdr.sys_path) - 1);
- } else
- strncpy(db_hdr.sys_path, syspath, sizeof db_hdr.sys_path);
- strncpy(db_hdr.magic, PS_MAGIC, sizeof db_hdr.magic);
-
- /* strncpy(db_hdr.swap_path, swappath[0], sizeof db_hdr.swap_path);*/
- strncpy(db_hdr.swap_path, "/dev/swap", sizeof db_hdr.swap_path);
-
-
- make_vartbl();
- make_fnctbl();
-
- write(fd, (char *) &db_hdr, sizeof db_hdr);
- write_tbl(fd, &db_hdr.vars, &vars);
- write_tbl(fd, &db_hdr.fncs, &fncs);
-
- if ((sysfd = open(syspath, O_RDONLY)) == -1) {
- perror(syspath);
- exit(1);
- }
- lseek(sysfd, k_addr("_system_utsname") + 1024, SEEK_SET);
- read(sysfd, (char *) &uts, sizeof(struct utsname));
- close(sysfd);
- strncpy(db_hdr.uts_release, uts.release, sizeof db_hdr.uts_release);
- strncpy(db_hdr.uts_version, uts.version, sizeof db_hdr.uts_version);
-
- lseek(fd, 0L, SEEK_SET);
- write(fd, (char *) &db_hdr, sizeof db_hdr);
- close(fd);
-
- free(namelist);
- namelist = NULL;
- return(0);
- }
-
- int read_nlist(char *systemfile)
- {
- int fd;
- struct exec hdr;
- unsigned symsize, size;
-
- if ((fd = open(systemfile, O_RDONLY)) < 0) {
- perror(systemfile);
- exit(1);
- }
- if (read(fd, (char *) &hdr, sizeof(hdr)) != sizeof(hdr)) {
- perror(systemfile);
- exit(1);
- }
- if (N_BADMAG(hdr)) {
- fprintf(stderr, "%s: bad magic number\n", systemfile);
- exit(1);
- }
- if (N_STROFF(hdr) == 0) {
- fprintf(stderr, "%s has no symbols\n", systemfile);
- exit(1);
- }
- lseek(fd, N_STROFF(hdr), SEEK_SET);
- read(fd, (char *) &stringsize, sizeof(stringsize));
- symsize = N_STROFF(hdr) - N_SYMOFF(hdr);
- size = symsize + stringsize;
- namelist = (struct nlist *) xmalloc(size);
- lseek(fd, N_SYMOFF(hdr), SEEK_SET);
- if (read(fd, (char *) namelist, size) != size) {
- perror(systemfile);
- exit(1);
- }
- close(fd);
-
- strings = ((char *) namelist) + symsize;
- nsym = symsize / sizeof(struct nlist);
- if (Debug > 1)
- fprintf(stderr, "read %d symbols from %s\n", nsym, systemfile);
- return(0);
- }
-
-
- /*
- * make list of all text symbols, sorted on address for easy
- * lookup of wait channel.
- */
- void make_fnctbl(void)
- {
- int i;
- struct sym_s *fp;
-
- fp= fncs.tbl= (struct sym_s *) xmalloc(nsym * sizeof(struct sym_s));
- fncs.strings = strings;
- for (i = 0; i < nsym; ++i) {
- if ((namelist[i].n_type & ~N_EXT) == N_TEXT &&
- !strchr(strings + namelist[i].n_un.n_strx, '.')) {
- fp->addr = namelist[i].n_value;
- fp->name = namelist[i].n_un.n_strx;
- ++fp;
- }
- }
- fncs.nsym = fp - fncs.tbl;
-
- if (Debug > 1)
- fprintf(stderr, "%d text symbols\n", fncs.nsym);
- qsort(fncs.tbl, fncs.nsym, sizeof(struct sym_s), (__compar_fn_t) addrcmp);
- if (Debug > 1)
- for (i = 1; i<fncs.nsym; ++i)
- if (fncs.tbl[i].addr == fncs.tbl[i-1].addr)
- printf("text symbols %s and %s both have address %lx\n",
- strings + fncs.tbl[i-1].name,
- strings + fncs.tbl[i].name, fncs.tbl[i].addr);
- }
-
-
- void make_vartbl(void)
- {
- int i;
- struct sym_s *vp;
-
- vp= vars.tbl= (struct sym_s *) xmalloc(nsym * sizeof(struct sym_s));
- vars.strings = strings;
- for (i = 0; i < nsym; ++i) {
- int typ = namelist[i].n_type & ~N_EXT;
-
- if (typ == N_DATA || typ == N_BSS) {
- vp->addr = namelist[i].n_value;
- vp->name = namelist[i].n_un.n_strx;
- ++vp;
- }
- }
- vars.nsym = vp - vars.tbl;
-
- if (Debug > 1)
- fprintf(stderr, "%d data/bss symbols\n", vars.nsym);
-
- qsort(vars.tbl, vars.nsym, sizeof(struct sym_s), (__compar_fn_t) varcmp);
- }
-
-
- /*
- * write table tbl to descriptor fd, header structure dbtdl is updated
- */
- int write_tbl(int fd, struct dbtbl_s *dbtbl, struct tbl_s *tbl)
- {
- int i;
- struct sym_s *p;
- char *s;
- int strsize, symsize;
-
- dbtbl->off = lseek(fd, 0L, SEEK_CUR);
- s= tbl->strings= xmalloc(stringsize);
- for (i = tbl->nsym, p = tbl->tbl; i--; ) {
- strcpy(s, strings + p->name);
- p->name = s - tbl->strings;
- ++p;
- s += strlen(s) + 1;
- }
- symsize = tbl->nsym * sizeof(struct sym_s);
- if (write(fd, (char *) tbl->tbl, symsize) != symsize)
- return -1;
- strsize = (s - tbl->strings + 3) & ~3;
- if (write(fd, tbl->strings, strsize) != strsize)
- return -1;
-
- dbtbl->size = strsize + symsize;
- dbtbl->nsym = tbl->nsym;
-
- return(0);
- }
-
- /*
- * fncs are sorted on address
- */
- __compar_fn_t addrcmp(struct sym_s *p1, struct sym_s *p2)
- {
- return((__compar_fn_t)(p1->addr - p2->addr));
- }
-
-
-
- /*
- * vars are sorted on name
- */
- __compar_fn_t varcmp(struct sym_s *p1, struct sym_s *p2)
- {
- return((__compar_fn_t)strcmp(vars.strings + p1->name,
- vars.strings + p2->name));
- }
-
-
-
- /*
- * get address of data symbol
- */
- unsigned long k_addr(char *sym)
- {
- struct sym_s *p, key;
-
- if (vars.tbl == NULL)
- read_tbl(&db_hdr.vars, &vars);
-
- key.name = sym - vars.strings;
- p = (struct sym_s *) bsearch(&key, vars.tbl, vars.nsym,
- sizeof(struct sym_s), (__compar_fn_t) varcmp);
- return(p ? p->addr : -1);
- }
-
-
-