diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 1998-08-20 00:14:04 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 1998-08-20 00:14:04 +0000 |
commit | 990468bc4164351196f9b0f93e5dbd0a6d1c3903 (patch) | |
tree | 00482e5769522f9357ceed3f9b0f238a3ee674bf /usr.sbin/kvm_mkdb | |
parent | 95a8a9dfc0fc50484b6abf5c5cab6ad8d2f4fe32 (diff) |
ecoff support, based on libc/gen/nlist.c
Diffstat (limited to 'usr.sbin/kvm_mkdb')
-rw-r--r-- | usr.sbin/kvm_mkdb/nlist.c | 136 |
1 files changed, 132 insertions, 4 deletions
diff --git a/usr.sbin/kvm_mkdb/nlist.c b/usr.sbin/kvm_mkdb/nlist.c index 650f658364e..ddeee01854f 100644 --- a/usr.sbin/kvm_mkdb/nlist.c +++ b/usr.sbin/kvm_mkdb/nlist.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nlist.c,v 1.9 1998/08/19 07:43:40 millert Exp $ */ +/* $OpenBSD: nlist.c,v 1.10 1998/08/20 00:14:03 millert Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "from: @(#)nlist.c 8.1 (Berkeley) 6/6/93"; #else -static char *rcsid = "$OpenBSD: nlist.c,v 1.9 1998/08/19 07:43:40 millert Exp $"; +static char *rcsid = "$OpenBSD: nlist.c,v 1.10 1998/08/20 00:14:03 millert Exp $"; #endif #endif /* not lint */ @@ -65,6 +65,10 @@ static char *rcsid = "$OpenBSD: nlist.c,v 1.9 1998/08/19 07:43:40 millert Exp $" #include <elf_abi.h> #endif +#ifdef _NLIST_DO_ECOFF +#include <sys/exec_ecoff.h> +#endif + typedef struct nlist NLIST; #define _strx n_un.n_strx #define _name n_un.n_name @@ -117,7 +121,7 @@ __aout_knlist(name, db) if (lseek(fd, N_STROFF(ebuf), SEEK_SET) == -1) badfmt("corrupted string table"); - /* Read in the size of the symbol table. */ + /* Read in the size of the string table. */ nr = read(fd, (char *)&strsize, sizeof(strsize)); if (nr != sizeof(strsize)) badread(nr, "no symbol table"); @@ -409,12 +413,136 @@ __elf_knlist(name, db) #endif /* _NLIST_DO_ELF */ #ifdef _NLIST_DO_ECOFF + +#define check(off, size) ((off < 0) || (off + size > mappedsize)) +#define BAD do { rv = -1; goto out; } while (0) +#define BADUNMAP do { rv = -1; goto unmap; } while (0) +#define ECOFF_INTXT(p, e) ((p) > (e)->a.text_start && \ + (p) < (e)->a.text_start + (e)->a.tsize) +#define ECOFF_INDAT(p, e) ((p) > (e)->a.data_start && \ + (p) < (e)->a.data_start + (e)->a.dsize) + int __ecoff_knlist(name, db) char *name; DB *db; { - return (-1); + struct ecoff_exechdr *exechdrp; + struct ecoff_symhdr *symhdrp; + struct ecoff_extsym *esyms; + struct stat st; + char *mappedfile, *cp; + size_t mappedsize; + u_long symhdroff, extstroff, off; + u_int symhdrsize; + int rv = 0; + long i, nesyms; + DBT data, key; + NLIST nbuf; + int fd; + char *sname = NULL; + size_t len, snamesize = 0; + + kfile = name; + if ((fd = open(name, O_RDONLY)) == -1) + err(1, "%s", name); + + if (fstat(fd, &st) < 0) + err(1, "can't stat %s", name); + if (st.st_size > SIZE_T_MAX) { + fmterr = "file too large"; + BAD; + } + + mappedsize = st.st_size; + mappedfile = mmap(NULL, mappedsize, PROT_READ, MAP_COPY|MAP_FILE, fd, 0); + if (mappedfile == MAP_FAILED) { + fmterr = "unable to mmap"; + BAD; + } + + if (check(0, sizeof *exechdrp)) + BADUNMAP; + exechdrp = (struct ecoff_exechdr *)&mappedfile[0]; + + if (ECOFF_BADMAG(exechdrp)) + BADUNMAP; + + symhdroff = exechdrp->f.f_symptr; + symhdrsize = exechdrp->f.f_nsyms; + if (symhdrsize == 0) + badfmt("stripped"); + + if (check(symhdroff, sizeof *symhdrp) || + sizeof *symhdrp != symhdrsize) + BADUNMAP; + symhdrp = (struct ecoff_symhdr *)&mappedfile[symhdroff]; + + nesyms = symhdrp->esymMax; + if (check(symhdrp->cbExtOffset, nesyms * sizeof *esyms)) + BADUNMAP; + esyms = (struct ecoff_extsym *)&mappedfile[symhdrp->cbExtOffset]; + extstroff = symhdrp->cbSsExtOffset; + + data.data = (u_char *)&nbuf; + data.size = sizeof(NLIST); + + for (i = 0; i < nesyms; i++) { + /* Need to prepend a '_' */ + len = strlen(&mappedfile[extstroff + esyms[i].es_strindex]); + if (len >= snamesize) + sname = malloc(len + 1024); + if (sname == NULL) + errx(1, "cannot allocate memory"); + *sname = '_'; + strcpy(sname+1, &mappedfile[extstroff + esyms[i].es_strindex]); + + /* Fill in NLIST */ + bzero(&nbuf, sizeof(nbuf)); + nbuf.n_value = esyms[i].es_value; + nbuf.n_type = N_EXT; /* XXX */ + + /* Store entry in db */ + key.data = (u_char *)sname; + key.size = strlen(sname); + if (db->put(db, &key, &data, 0)) + err(1, "record enter"); + + if (strcmp(sname, VRS_SYM) == 0) { + key.data = (u_char *)VRS_KEY; + key.size = sizeof(VRS_KEY) - 1; + + /* Version string may be in either text or data segs */ + if (ECOFF_INTXT(nbuf.n_value, exechdrp)) + off = nbuf.n_value - exechdrp->a.text_start + + ECOFF_TXTOFF(exechdrp); + else if (ECOFF_INDAT(nbuf.n_value, exechdrp)) + off = nbuf.n_value - exechdrp->a.data_start + + ECOFF_DATOFF(exechdrp); + else + err(1, "unable to find version string"); + + /* Version string should end in newline but... */ + data.data = &mappedfile[off]; + if ((cp = strchr(data.data, '\n')) != NULL) + data.size = cp - (char *)data.data; + else + data.size = strlen((char *)data.data); + + if (db->put(db, &key, &data, 0)) + err(1, "record enter"); + + /* Restore to original values */ + data.data = (u_char *)&nbuf; + data.size = sizeof(nbuf); + } + + } + +unmap: + munmap(mappedfile, mappedsize); +out: + return (rv); } #endif /* _NLIST_DO_ECOFF */ |