146309Sbostic /*-
2*61838Sbostic * Copyright (c) 1990, 1993
3*61838Sbostic * The Regents of the University of California. All rights reserved.
446309Sbostic *
546309Sbostic * %sccs.include.redist.c%
646309Sbostic */
746309Sbostic
846309Sbostic #ifndef lint
9*61838Sbostic static char sccsid[] = "@(#)nlist.c 8.1 (Berkeley) 06/06/93";
1046309Sbostic #endif /* not lint */
1146309Sbostic
1246309Sbostic #include <sys/param.h>
1359022Sbostic
1446309Sbostic #include <a.out.h>
1546947Sbostic #include <db.h>
1659022Sbostic #include <err.h>
1746396Sbostic #include <errno.h>
1859022Sbostic #include <fcntl.h>
1946309Sbostic #include <kvm.h>
2059022Sbostic #include <limits.h>
2146309Sbostic #include <stdio.h>
2259022Sbostic #include <stdlib.h>
2346396Sbostic #include <string.h>
2459022Sbostic #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
3259022Sbostic #define badfmt(str) errx(1, "%s: %s: %s", kfile, str, strerror(EFTYPE))
3359022Sbostic
3453326Sbostic static void badread __P((int, char *));
3553326Sbostic
3646309Sbostic static char *kfile;
3746309Sbostic
3853326Sbostic void
create_knlist(name,db)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)
5359022Sbostic err(1, "%s", name);
5446309Sbostic
5546396Sbostic /* Read in exec structure. */
5659022Sbostic 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);
7759022Sbostic if (!(strtab = malloc(strsize)))
7859022Sbostic 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")))
8459022Sbostic err(1, "%s", name);
8546396Sbostic if (fseek(fp, N_SYMOFF(ebuf), SEEK_SET) == -1)
8659022Sbostic 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");
9759022Sbostic 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);
10459022Sbostic if (db->put(db, &key, &data, 0))
10559022Sbostic 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);
13959022Sbostic if (db->put(db, &key, &data, 0))
14059022Sbostic 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
badread(nr,p)15346396Sbostic badread(nr, p)
15446396Sbostic int nr;
15546396Sbostic char *p;
15646396Sbostic {
15746396Sbostic if (nr < 0)
15859022Sbostic err(1, "%s", kfile);
15946396Sbostic badfmt(p);
16046396Sbostic }
161