Use kldsym(2) to lookup symbol values. This avoids the kvm_mkdb juggling

and is module aware.  Yes, this means that kvm_nlist(3) will find symbols
in loaded modules.  The emulation of the nlist struct is pretty crude but
seems to work well enough for all the users in the tree that I found.
This commit is contained in:
Peter Wemm 1999-12-27 07:14:58 +00:00
parent c2696359ab
commit c4a7cdb3b6
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=55127
11 changed files with 59 additions and 128 deletions

View File

@ -40,7 +40,7 @@
static char sccsid[] = "@(#)kvm.c 8.2 (Berkeley) 2/13/94";
#else
static const char rcsid[] =
"$FreeBSD$";
"$FreeBSD$";
#endif
#endif /* LIBC_SCCS and not lint */
@ -50,6 +50,7 @@ static const char rcsid[] =
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
@ -58,7 +59,6 @@ static const char rcsid[] =
#include <machine/vmparam.h>
#include <ctype.h>
#include <db.h>
#include <fcntl.h>
#include <kvm.h>
#include <limits.h>
@ -71,8 +71,6 @@ static const char rcsid[] =
#include "kvm_private.h"
static int kvm_dbopen __P((kvm_t *, const char *));
char *
kvm_geterr(kd)
kvm_t *kd;
@ -180,7 +178,6 @@ _kvm_open(kd, uf, mf, flag, errout)
kd->pmfd = -1;
kd->nlfd = -1;
kd->vmst = 0;
kd->db = 0;
kd->procbase = 0;
kd->argspc = 0;
kd->argv = 0;
@ -225,19 +222,6 @@ _kvm_open(kd, uf, mf, flag, errout)
goto failed;
}
}
/*
* Open kvm nlist database. We go ahead and do this
* here so that we don't have to hold on to the kernel
* path name. Since a kvm application will surely do
* a kvm_nlist(), this probably won't be a wasted effort.
* If the database cannot be opened, open the namelist
* argument so we revert to slow nlist() calls.
*/
if (kvm_dbopen(kd, uf) < 0 &&
(kd->nlfd = open(uf, O_RDONLY, 0)) < 0) {
_kvm_syserr(kd, kd->program, "%s", uf);
goto failed;
}
} else {
/*
* This is a crash dump.
@ -314,8 +298,6 @@ kvm_close(kd)
error |= close(kd->vmfd);
if (kd->nlfd >= 0)
error |= close(kd->nlfd);
if (kd->db != 0)
error |= (kd->db->close)(kd->db);
if (kd->vmst)
_kvm_freevtop(kd);
if (kd->procbase != 0)
@ -327,72 +309,6 @@ kvm_close(kd)
return (0);
}
/*
* Set up state necessary to do queries on the kernel namelist
* data base. If the data base is out-of-data/incompatible with
* given executable, set up things so we revert to standard nlist call.
* Only called for live kernels. Return 0 on success, -1 on failure.
*/
static int
kvm_dbopen(kd, uf)
kvm_t *kd;
const char *uf;
{
char *cp;
DBT rec;
int dbversionlen;
struct nlist nitem;
char dbversion[_POSIX2_LINE_MAX];
char kversion[_POSIX2_LINE_MAX];
char dbname[MAXPATHLEN];
if ((cp = rindex(uf, '/')) != 0)
uf = cp + 1;
(void)snprintf(dbname, sizeof(dbname), "%skvm_%s.db", _PATH_VARDB, uf);
kd->db = dbopen(dbname, O_RDONLY, 0, DB_HASH, NULL);
if (kd->db == 0)
return (-1);
/*
* read version out of database
*/
rec.data = VRS_KEY;
rec.size = sizeof(VRS_KEY) - 1;
if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0))
goto close;
if (rec.data == 0 || rec.size > sizeof(dbversion))
goto close;
bcopy(rec.data, dbversion, rec.size);
dbversionlen = rec.size;
/*
* Read version string from kernel memory.
* Since we are dealing with a live kernel, we can call kvm_read()
* at this point.
*/
rec.data = VRS_SYM;
rec.size = sizeof(VRS_SYM) - 1;
if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0))
goto close;
if (rec.data == 0 || rec.size != sizeof(struct nlist))
goto close;
bcopy((char *)rec.data, (char *)&nitem, sizeof(nitem));
if (kvm_read(kd, (u_long)nitem.n_value, kversion, dbversionlen) !=
dbversionlen)
goto close;
/*
* If they match, we win - otherwise clear out kd->db so
* we revert to slow nlist().
*/
if (bcmp(dbversion, kversion, dbversionlen) == 0)
return (0);
close:
(void)(kd->db->close)(kd->db);
kd->db = 0;
return (-1);
}
int
kvm_nlist(kd, nl)
kvm_t *kd;
@ -400,44 +316,37 @@ kvm_nlist(kd, nl)
{
register struct nlist *p;
register int nvalid;
struct kld_sym_lookup lookup;
/*
* If we can't use the data base, revert to the
* If we can't use the kld symbol lookup, revert to the
* slow library call.
*/
if (kd->db == 0)
if (!ISALIVE(kd))
return (__fdnlist(kd->nlfd, nl));
/*
* We can use the kvm data base. Go through each nlist entry
* and look it up with a db query.
* We can use the kld lookup syscall. Go through each nlist entry
* and look it up with a kldsym(2) syscall.
*/
nvalid = 0;
for (p = nl; p->n_name && p->n_name[0]; ++p) {
register int len;
DBT rec;
lookup.version = sizeof(lookup);
lookup.symname = p->n_name;
lookup.symvalue = 0;
lookup.symsize = 0;
if ((len = strlen(p->n_name)) > 4096) {
/* sanity */
_kvm_err(kd, kd->program, "symbol too large");
return (-1);
if (lookup.symname[0] == '_')
lookup.symname++;
if (kldsym(0, KLDSYM_LOOKUP, &lookup) != -1) {
p->n_type = N_TEXT;
p->n_other = 0;
p->n_desc = 0;
p->n_value = lookup.symvalue;
++nvalid;
/* lookup.symsize */
}
rec.data = p->n_name;
rec.size = len;
if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0))
continue;
if (rec.data == 0 || rec.size != sizeof(struct nlist))
continue;
++nvalid;
/*
* Avoid alignment issues.
*/
bcopy((char *)&((struct nlist *)rec.data)->n_type,
(char *)&p->n_type,
sizeof(p->n_type));
bcopy((char *)&((struct nlist *)rec.data)->n_value,
(char *)&p->n_value,
sizeof(p->n_value));
}
/*
* Return the number of entries that weren't found.

View File

@ -42,7 +42,6 @@
#include <vm/vm_param.h>
#include <limits.h>
#include <db.h>
#include <stdlib.h>
#include <machine/pmap.h>
#include "kvm_private.h"

View File

@ -36,7 +36,12 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
static char sccsid[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93";
#else
static const char rcsid[] =
"$FreeBSD$";
#endif
#endif /* LIBC_SCCS and not lint */
/*
@ -57,7 +62,6 @@ static char sccsid[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93";
#include <vm/vm_param.h>
#include <limits.h>
#include <db.h>
#include "kvm_private.h"

View File

@ -32,7 +32,12 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
static char sccsid[] = "@(#)kvm_file.c 8.1 (Berkeley) 6/4/93";
#else
static const char rcsid[] =
"$FreeBSD$";
#endif
#endif /* LIBC_SCCS and not lint */
/*

View File

@ -32,7 +32,12 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
static char sccsid[] = "@(#)kvm_getloadavg.c 8.1 (Berkeley) 6/4/93";
#else
static const char rcsid[] =
"$FreeBSD$";
#endif
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
@ -43,7 +48,6 @@ static char sccsid[] = "@(#)kvm_getloadavg.c 8.1 (Berkeley) 6/4/93";
#include <vm/vm_param.h>
#include <stdlib.h>
#include <db.h>
#include <fcntl.h>
#include <limits.h>
#include <nlist.h>

View File

@ -28,7 +28,6 @@ static const char rcsid[] =
#include <err.h>
#include <fcntl.h>
#include <kvm.h>
#include <limits.h>
#include <nlist.h>
#include <stdio.h>
#include <stdlib.h>

View File

@ -36,7 +36,12 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
static char sccsid[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93";
#else
static const char rcsid[] =
"$FreeBSD$";
#endif
#endif /* LIBC_SCCS and not lint */
/*
@ -57,7 +62,6 @@ static char sccsid[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93";
#include <vm/vm_param.h>
#include <limits.h>
#include <db.h>
#include "kvm_private.h"

View File

@ -60,12 +60,10 @@ Each symbol is looked up using the n_name field, and if found, the
corresponding n_type and n_value fields are filled in. These fields are set
to 0 if the symbol is not found.
.Pp
The program
.Xr kvm_mkdb 8
builds a database from the running kernel's namelist.
If the database matches the opened kernel,
.Fn kvm_nlist
uses it to speed lookups.
.Xr kldsym 2
is used to locate the symbol. This is a less than perfect emulation
of the nlist values but has the advantage of being aware of kernel modules
and is reasonably fast.
.Sh RETURN VALUES
The
.Fn kvm_nlist
@ -76,6 +74,7 @@ If the kernel symbol table was unreadable, -1 is returned.
.It Pa /var/db/kvm_kernel.db
.El
.Sh SEE ALSO
.Xr kldsym 2 ,
.Xr kvm 3 ,
.Xr kvm_close 3 ,
.Xr kvm_getargv 3 ,
@ -85,5 +84,4 @@ If the kernel symbol table was unreadable, -1 is returned.
.Xr kvm_open 3 ,
.Xr kvm_openfiles 3 ,
.Xr kvm_read 3 ,
.Xr kvm_write 3 ,
.Xr kvm_mkdb 8
.Xr kvm_write 3

View File

@ -35,6 +35,7 @@
* SUCH DAMAGE.
*
* @(#)kvm_private.h 8.1 (Berkeley) 6/4/93
* $FreeBSD$
*/
struct __kvm {
@ -46,7 +47,6 @@ struct __kvm {
const char *program;
char *errp; /* XXX this can probably go away */
char errbuf[_POSIX2_LINE_MAX];
DB *db;
#define ISALIVE(kd) ((kd)->vmfd >= 0)
int pmfd; /* physical memory file (or crashdump) */
int vmfd; /* virtual memory file (-1 if crashdump) */

View File

@ -70,7 +70,6 @@ static char sccsid[] = "@(#)kvm_proc.c 8.3 (Berkeley) 9/23/93";
#include <limits.h>
#include <memory.h>
#include <db.h>
#include <paths.h>
#include "kvm_private.h"
@ -675,6 +674,12 @@ kvm_getargv(kd, kp, nchr)
static char **bufp;
static int argc;
if (!ISALIVE(kd)) {
_kvm_err(kd, kd->program,
"cannot read user space from dead kernel");
return (0);
}
if (!buflen) {
l = sizeof(buflen);
i = sysctlbyname("kern.ps_arg_cache_limit",

View File

@ -36,7 +36,12 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
static char sccsid[] = "@(#)kvm_sparc.c 8.1 (Berkeley) 6/4/93";
#else
static const char rcsid[] =
"$FreeBSD$";
#endif
#endif /* LIBC_SCCS and not lint */
/*
@ -56,7 +61,6 @@ static char sccsid[] = "@(#)kvm_sparc.c 8.1 (Berkeley) 6/4/93";
#include <vm/vm_param.h>
#include <limits.h>
#include <db.h>
#include "kvm_private.h"