Allow modload to load symbols for use by DDB.
This commit is contained in:
parent
114c430bbb
commit
0c70fedcac
|
@ -1,4 +1,4 @@
|
|||
.\" $NetBSD: modload.8,v 1.7 1997/09/15 09:27:53 darrenr Exp $
|
||||
.\" $NetBSD: modload.8,v 1.8 1999/01/13 23:07:30 sommerfe Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1993 Christopher G. Demetriou
|
||||
.\" All rights reserved.
|
||||
|
@ -33,7 +33,7 @@
|
|||
.Nd load a kernel module
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl dv
|
||||
.Op Fl dvs
|
||||
.Op Fl A Ar kernel
|
||||
.Op Fl e Ar entry
|
||||
.Op Fl p Ar postinstall
|
||||
|
@ -55,6 +55,8 @@ Debug. Used to debug
|
|||
itself.
|
||||
.It Fl v
|
||||
Print comments about the loading process.
|
||||
.It Fl s
|
||||
Suppress loading of the symbol table.
|
||||
.It Fl A Ar kernel
|
||||
Specify the file that is passed to the linker
|
||||
to resolve module references to external symbols.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: modload.c,v 1.21 1998/07/28 19:22:55 mycroft Exp $ */
|
||||
/* $NetBSD: modload.c,v 1.22 1999/01/13 23:07:30 sommerfe Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1993 Terrence R. Lambert.
|
||||
|
@ -34,7 +34,7 @@
|
|||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: modload.c,v 1.21 1998/07/28 19:22:55 mycroft Exp $");
|
||||
__RCSID("$NetBSD: modload.c,v 1.22 1999/01/13 23:07:30 sommerfe Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
|
@ -42,6 +42,7 @@ __RCSID("$NetBSD: modload.c,v 1.21 1998/07/28 19:22:55 mycroft Exp $");
|
|||
#include <sys/conf.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/lkm.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
#include <a.out.h>
|
||||
#include <err.h>
|
||||
|
@ -53,6 +54,9 @@ __RCSID("$NetBSD: modload.c,v 1.21 1998/07/28 19:22:55 mycroft Exp $");
|
|||
#include <nlist.h>
|
||||
#include "pathnames.h"
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#ifndef DFLT_ENTRY
|
||||
#define DFLT_ENTRY "xxxinit"
|
||||
#endif /* !DFLT_ENTRY */
|
||||
|
@ -83,6 +87,7 @@ int verify_entry __P((char *, char *));
|
|||
|
||||
int debug = 0;
|
||||
int verbose = 0;
|
||||
int symtab = 1;
|
||||
|
||||
int
|
||||
linkcmd(kernel, entry, outfile, address, object)
|
||||
|
@ -196,14 +201,18 @@ main(argc, argv)
|
|||
char *modobj;
|
||||
char modout[80], *p;
|
||||
struct exec info_buf;
|
||||
struct stat stb;
|
||||
u_int modsize; /* XXX */
|
||||
u_int modentry; /* XXX */
|
||||
struct nlist *nlp;
|
||||
int strtablen, numsyms;
|
||||
|
||||
struct lmc_loadbuf ldbuf;
|
||||
int sz, bytesleft;
|
||||
int sz, bytesleft, old = FALSE;
|
||||
char buf[MODIOBUF];
|
||||
char *symbuf;
|
||||
|
||||
while ((c = getopt(argc, argv, "dvA:e:p:o:")) != -1) {
|
||||
while ((c = getopt(argc, argv, "dvsA:e:p:o:")) != -1) {
|
||||
switch (c) {
|
||||
case 'd':
|
||||
debug = 1;
|
||||
|
@ -223,6 +232,9 @@ main(argc, argv)
|
|||
case 'o':
|
||||
out = optarg;
|
||||
break; /* output file */
|
||||
case 's':
|
||||
symtab = 0;
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
default:
|
||||
|
@ -302,6 +314,11 @@ main(argc, argv)
|
|||
*/
|
||||
if (read(modfd, &info_buf, sizeof(struct exec)) == -1)
|
||||
err(3, "read `%s'", out);
|
||||
/*
|
||||
* stat for filesize to figure out string table size
|
||||
*/
|
||||
if (fstat(modfd, &stb) == -1)
|
||||
err(3, "fstat `%s'", out);
|
||||
|
||||
/*
|
||||
* Close the dummy module -- we have our sizing information.
|
||||
|
@ -328,8 +345,25 @@ main(argc, argv)
|
|||
resrv.name = modout; /* objname w/o ".o" */
|
||||
resrv.slot = -1; /* returned */
|
||||
resrv.addr = 0; /* returned */
|
||||
if (ioctl(devfd, LMRESERV, &resrv) == -1)
|
||||
strtablen = stb.st_size - N_STROFF(info_buf);
|
||||
if (symtab) {
|
||||
/* XXX TODO: grovel through symbol table looking
|
||||
for just the symbol table stuff from the new module,
|
||||
and skip the stuff from the kernel. */
|
||||
resrv.sym_size = info_buf.a_syms + strtablen;
|
||||
resrv.sym_symsize = info_buf.a_syms;
|
||||
} else
|
||||
resrv.sym_size = resrv.sym_symsize = 0;
|
||||
|
||||
if (ioctl(devfd, LMRESERV, &resrv) == -1) {
|
||||
if (symtab)
|
||||
warn("not loading symbols: kernel does not support symbol table loading");
|
||||
doold:
|
||||
symtab = 0;
|
||||
if (ioctl(devfd, LMRESERV_O, &resrv) == -1)
|
||||
err(9, "can't reserve memory");
|
||||
old = TRUE;
|
||||
}
|
||||
fileopen |= PART_RESRV;
|
||||
|
||||
/*
|
||||
|
@ -379,6 +413,69 @@ main(argc, argv)
|
|||
err(11, "error transferring buffer");
|
||||
}
|
||||
|
||||
|
||||
if (symtab) {
|
||||
/*
|
||||
* Seek to the symbol table to start loading it...
|
||||
*/
|
||||
if (lseek(modfd, N_SYMOFF(info_buf), SEEK_SET) == -1)
|
||||
err(12, "lseek");
|
||||
|
||||
/*
|
||||
* Transfer the symbol table entries. First, read them all in,
|
||||
* then adjust their string table pointers, then
|
||||
* copy in bulk. Then copy the string table itself.
|
||||
*/
|
||||
|
||||
symbuf = malloc(info_buf.a_syms);
|
||||
if (symbuf == 0)
|
||||
err(13, "malloc");
|
||||
|
||||
if (read(modfd, symbuf, info_buf.a_syms) != info_buf.a_syms)
|
||||
err(14, "read");
|
||||
numsyms = info_buf.a_syms / sizeof(struct nlist);
|
||||
for (nlp = (struct nlist *)symbuf;
|
||||
(char *)nlp < symbuf + info_buf.a_syms;
|
||||
nlp++) {
|
||||
register int strx;
|
||||
strx = nlp->n_un.n_strx;
|
||||
if (strx != 0) {
|
||||
/* If a valid name, set the name ptr to point at the
|
||||
* loaded address for the string in the string table.
|
||||
*/
|
||||
if (strx > strtablen)
|
||||
nlp->n_un.n_name = 0;
|
||||
else
|
||||
nlp->n_un.n_name =
|
||||
(char *)(strx + resrv.sym_addr + info_buf.a_syms);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* we've fixed the symbol table entries, now load them
|
||||
*/
|
||||
for (bytesleft = info_buf.a_syms;
|
||||
bytesleft > 0;
|
||||
bytesleft -= sz) {
|
||||
sz = MIN(bytesleft, MODIOBUF);
|
||||
ldbuf.cnt = sz;
|
||||
ldbuf.data = symbuf;
|
||||
if (ioctl(devfd, LMLOADSYMS, &ldbuf) == -1)
|
||||
err(11, "error transferring sym buffer");
|
||||
symbuf += sz;
|
||||
}
|
||||
free(symbuf - info_buf.a_syms);
|
||||
/* and now read the string table and load it. */
|
||||
for (bytesleft = strtablen;
|
||||
bytesleft > 0;
|
||||
bytesleft -= sz) {
|
||||
sz = MIN(bytesleft, MODIOBUF);
|
||||
read(modfd, buf, sz);
|
||||
ldbuf.cnt = sz;
|
||||
ldbuf.data = buf;
|
||||
if (ioctl(devfd, LMLOADSYMS, &ldbuf) == -1)
|
||||
err(11, "error transferring stringtable buffer");
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Save ourselves before disaster (potentitally) strikes...
|
||||
*/
|
||||
|
@ -390,9 +487,19 @@ main(argc, argv)
|
|||
* is maintained on success, or blow everything back to ground
|
||||
* zero on failure.
|
||||
*/
|
||||
if (ioctl(devfd, LMREADY, &modentry) == -1)
|
||||
err(14, "error initializing module");
|
||||
|
||||
if (ioctl(devfd, LMREADY, &modentry) == -1) {
|
||||
if (errno == EINVAL && !old) {
|
||||
if (fileopen & MOD_OPEN)
|
||||
close(modfd);
|
||||
/* PART_RESRV is not true since the kernel cleans up
|
||||
after a failed LMREADY */
|
||||
fileopen &= ~(MOD_OPEN|PART_RESRV);
|
||||
/* try using oldstyle */
|
||||
warn("module failed to load using new version; trying old version");
|
||||
goto doold;
|
||||
} else
|
||||
err(14, "error initializing module");
|
||||
}
|
||||
/*
|
||||
* Success!
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue