146309Sbostic /*- 2*59022Sbostic * Copyright (c) 1990, 1993 The Regents of the University of California. 346309Sbostic * All rights reserved. 446309Sbostic * 546309Sbostic * %sccs.include.redist.c% 646309Sbostic */ 746309Sbostic 846309Sbostic #ifndef lint 9*59022Sbostic static char sccsid[] = "@(#)nlist.c 5.8 (Berkeley) 04/10/93"; 1046309Sbostic #endif /* not lint */ 1146309Sbostic 1246309Sbostic #include <sys/param.h> 13*59022Sbostic 1446309Sbostic #include <a.out.h> 1546947Sbostic #include <db.h> 16*59022Sbostic #include <err.h> 1746396Sbostic #include <errno.h> 18*59022Sbostic #include <fcntl.h> 1946309Sbostic #include <kvm.h> 20*59022Sbostic #include <limits.h> 2146309Sbostic #include <stdio.h> 22*59022Sbostic #include <stdlib.h> 2346396Sbostic #include <string.h> 24*59022Sbostic #include <unistd.h> 2546309Sbostic 2653326Sbostic #include "extern.h" 2753326Sbostic 2846309Sbostic typedef struct nlist NLIST; 2946309Sbostic #define _strx n_un.n_strx 3046309Sbostic #define _name n_un.n_name 3146309Sbostic 32*59022Sbostic #define badfmt(str) errx(1, "%s: %s: %s", kfile, str, strerror(EFTYPE)) 33*59022Sbostic 3453326Sbostic static void badread __P((int, char *)); 3553326Sbostic 3646309Sbostic static char *kfile; 3746309Sbostic 3853326Sbostic void 3946309Sbostic create_knlist(name, db) 4046309Sbostic char *name; 4146947Sbostic DB *db; 4246309Sbostic { 4346396Sbostic register int nsyms; 4446309Sbostic struct exec ebuf; 4546396Sbostic FILE *fp; 4646309Sbostic NLIST nbuf; 4746947Sbostic DBT data, key; 4846396Sbostic int fd, nr, strsize; 4946396Sbostic char *strtab, buf[1024]; 5046309Sbostic 5146309Sbostic kfile = name; 5246396Sbostic if ((fd = open(name, O_RDONLY, 0)) < 0) 53*59022Sbostic err(1, "%s", name); 5446309Sbostic 5546396Sbostic /* Read in exec structure. */ 56*59022Sbostic nr = read(fd, &ebuf, sizeof(struct exec)); 5746396Sbostic if (nr != sizeof(struct exec)) 5853326Sbostic badfmt("no exec header"); 5946396Sbostic 6046396Sbostic /* Check magic number and symbol count. */ 6146309Sbostic if (N_BADMAG(ebuf)) 6246309Sbostic badfmt("bad magic number"); 6346396Sbostic if (!ebuf.a_syms) 6446309Sbostic badfmt("stripped"); 6546309Sbostic 6646396Sbostic /* Seek to string table. */ 6746396Sbostic if (lseek(fd, N_STROFF(ebuf), SEEK_SET) == -1) 6846396Sbostic badfmt("corrupted string table"); 6946309Sbostic 7046396Sbostic /* Read in the size of the symbol table. */ 7146396Sbostic nr = read(fd, (char *)&strsize, sizeof(strsize)); 7246396Sbostic if (nr != sizeof(strsize)) 7346396Sbostic badread(nr, "no symbol table"); 7446309Sbostic 7546396Sbostic /* Read in the string table. */ 7646396Sbostic strsize -= sizeof(strsize); 77*59022Sbostic if (!(strtab = malloc(strsize))) 78*59022Sbostic err(1, NULL); 7946396Sbostic if ((nr = read(fd, strtab, strsize)) != strsize) 8046396Sbostic badread(nr, "corrupted symbol table"); 8146396Sbostic 8246396Sbostic /* Seek to symbol table. */ 8346396Sbostic if (!(fp = fdopen(fd, "r"))) 84*59022Sbostic err(1, "%s", name); 8546396Sbostic if (fseek(fp, N_SYMOFF(ebuf), SEEK_SET) == -1) 86*59022Sbostic err(1, "%s", name); 8746396Sbostic 8846947Sbostic data.data = (u_char *)&nbuf; 8946947Sbostic data.size = sizeof(NLIST); 9046309Sbostic 9146396Sbostic /* Read each symbol and enter it into the database. */ 9246396Sbostic nsyms = ebuf.a_syms / sizeof(struct nlist); 9346396Sbostic while (nsyms--) { 9446396Sbostic if (fread((char *)&nbuf, sizeof (NLIST), 1, fp) != 1) { 9546396Sbostic if (feof(fp)) 9646396Sbostic badfmt("corrupted symbol table"); 97*59022Sbostic err(1, "%s", name); 9846396Sbostic } 9946309Sbostic if (!nbuf._strx || nbuf.n_type&N_STAB) 10046309Sbostic continue; 10146309Sbostic 10246947Sbostic key.data = (u_char *)strtab + nbuf._strx - sizeof(long); 10346947Sbostic key.size = strlen((char *)key.data); 104*59022Sbostic if (db->put(db, &key, &data, 0)) 105*59022Sbostic err(1, "record enter"); 10646309Sbostic 10753326Sbostic if (strcmp((char *)key.data, VRS_SYM) == 0) { 10854587Sbostic long cur_off, voff; 10953326Sbostic #ifndef KERNTEXTOFF 11053326Sbostic #define KERNTEXTOFF KERNBASE 11146309Sbostic #endif 11246309Sbostic /* 11353326Sbostic * Calculate offset relative to a normal (non-kernel) 11453326Sbostic * a.out. KERNTEXTOFF is where the kernel is really 11553326Sbostic * loaded; N_TXTADDR is where a normal file is loaded. 11653326Sbostic * From there, locate file offset in text or data. 11746309Sbostic */ 11853326Sbostic voff = nbuf.n_value - KERNTEXTOFF + N_TXTADDR(ebuf); 11953326Sbostic if ((nbuf.n_type & N_TYPE) == N_TEXT) 12053326Sbostic voff += N_TXTOFF(ebuf) - N_TXTADDR(ebuf); 12153326Sbostic else 12253326Sbostic voff += N_DATOFF(ebuf) - N_DATADDR(ebuf); 12346396Sbostic cur_off = ftell(fp); 12453326Sbostic if (fseek(fp, voff, SEEK_SET) == -1) 12546309Sbostic badfmt("corrupted string table"); 12646309Sbostic 12746309Sbostic /* 12846309Sbostic * Read version string up to, and including newline. 12946309Sbostic * This code assumes that a newline terminates the 13046309Sbostic * version line. 13146309Sbostic */ 13246396Sbostic if (fgets(buf, sizeof(buf), fp) == NULL) 13346309Sbostic badfmt("corrupted string table"); 13446309Sbostic 13546947Sbostic key.data = (u_char *)VRS_KEY; 13646947Sbostic key.size = sizeof(VRS_KEY) - 1; 13746947Sbostic data.data = (u_char *)buf; 13846947Sbostic data.size = strlen(buf); 139*59022Sbostic if (db->put(db, &key, &data, 0)) 140*59022Sbostic err(1, "record enter"); 14146309Sbostic 14246309Sbostic /* Restore to original values. */ 14346947Sbostic data.data = (u_char *)&nbuf; 14446947Sbostic data.size = sizeof(NLIST); 14546396Sbostic if (fseek(fp, cur_off, SEEK_SET) == -1) 14646396Sbostic badfmt("corrupted string table"); 14746309Sbostic } 14846309Sbostic } 14946396Sbostic (void)fclose(fp); 15046309Sbostic } 15146309Sbostic 15253326Sbostic static void 15346396Sbostic badread(nr, p) 15446396Sbostic int nr; 15546396Sbostic char *p; 15646396Sbostic { 15746396Sbostic if (nr < 0) 158*59022Sbostic err(1, "%s", kfile); 15946396Sbostic badfmt(p); 16046396Sbostic } 161