From 047fa82dd05146cf34e7c0f9fe16e2f4a5fa741f Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 27 Dec 1999 07:14:58 +0000 Subject: 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. --- lib/libkvm/kvm.c | 135 +++++++------------------------------------ lib/libkvm/kvm_alpha.c | 1 - lib/libkvm/kvm_amd64.c | 6 +- lib/libkvm/kvm_file.c | 5 ++ lib/libkvm/kvm_getloadavg.c | 6 +- lib/libkvm/kvm_getswapinfo.c | 1 - lib/libkvm/kvm_i386.c | 6 +- lib/libkvm/kvm_nlist.3 | 14 ++--- lib/libkvm/kvm_private.h | 2 +- lib/libkvm/kvm_proc.c | 7 ++- lib/libkvm/kvm_sparc.c | 6 +- 11 files changed, 60 insertions(+), 129 deletions(-) (limited to 'lib') diff --git a/lib/libkvm/kvm.c b/lib/libkvm/kvm.c index b35eceb..55c33f8 100644 --- a/lib/libkvm/kvm.c +++ b/lib/libkvm/kvm.c @@ -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 #include #include +#include #include #include @@ -58,7 +59,6 @@ static const char rcsid[] = #include #include -#include #include #include #include @@ -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; - - if ((len = strlen(p->n_name)) > 4096) { - /* sanity */ - _kvm_err(kd, kd->program, "symbol too large"); - return (-1); + lookup.version = sizeof(lookup); + lookup.symname = p->n_name; + lookup.symvalue = 0; + lookup.symsize = 0; + + 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. diff --git a/lib/libkvm/kvm_alpha.c b/lib/libkvm/kvm_alpha.c index 391a955..98417a0 100644 --- a/lib/libkvm/kvm_alpha.c +++ b/lib/libkvm/kvm_alpha.c @@ -42,7 +42,6 @@ #include #include -#include #include #include #include "kvm_private.h" diff --git a/lib/libkvm/kvm_amd64.c b/lib/libkvm/kvm_amd64.c index d36b922..0b727fd 100644 --- a/lib/libkvm/kvm_amd64.c +++ b/lib/libkvm/kvm_amd64.c @@ -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 #include -#include #include "kvm_private.h" diff --git a/lib/libkvm/kvm_file.c b/lib/libkvm/kvm_file.c index 4af6b71..a80ba8e 100644 --- a/lib/libkvm/kvm_file.c +++ b/lib/libkvm/kvm_file.c @@ -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 */ /* diff --git a/lib/libkvm/kvm_getloadavg.c b/lib/libkvm/kvm_getloadavg.c index 3368e63..7963831 100644 --- a/lib/libkvm/kvm_getloadavg.c +++ b/lib/libkvm/kvm_getloadavg.c @@ -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 @@ -43,7 +48,6 @@ static char sccsid[] = "@(#)kvm_getloadavg.c 8.1 (Berkeley) 6/4/93"; #include #include -#include #include #include #include diff --git a/lib/libkvm/kvm_getswapinfo.c b/lib/libkvm/kvm_getswapinfo.c index 05aeedf..4c85e82 100644 --- a/lib/libkvm/kvm_getswapinfo.c +++ b/lib/libkvm/kvm_getswapinfo.c @@ -28,7 +28,6 @@ static const char rcsid[] = #include #include #include -#include #include #include #include diff --git a/lib/libkvm/kvm_i386.c b/lib/libkvm/kvm_i386.c index d36b922..0b727fd 100644 --- a/lib/libkvm/kvm_i386.c +++ b/lib/libkvm/kvm_i386.c @@ -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 #include -#include #include "kvm_private.h" diff --git a/lib/libkvm/kvm_nlist.3 b/lib/libkvm/kvm_nlist.3 index f5611b3..b01930b 100644 --- a/lib/libkvm/kvm_nlist.3 +++ b/lib/libkvm/kvm_nlist.3 @@ -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 diff --git a/lib/libkvm/kvm_private.h b/lib/libkvm/kvm_private.h index 2d6d07f..402b9ee 100644 --- a/lib/libkvm/kvm_private.h +++ b/lib/libkvm/kvm_private.h @@ -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) */ diff --git a/lib/libkvm/kvm_proc.c b/lib/libkvm/kvm_proc.c index feba974..3490bd4 100644 --- a/lib/libkvm/kvm_proc.c +++ b/lib/libkvm/kvm_proc.c @@ -70,7 +70,6 @@ static char sccsid[] = "@(#)kvm_proc.c 8.3 (Berkeley) 9/23/93"; #include #include -#include #include #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", diff --git a/lib/libkvm/kvm_sparc.c b/lib/libkvm/kvm_sparc.c index a7b9594..7a538d8 100644 --- a/lib/libkvm/kvm_sparc.c +++ b/lib/libkvm/kvm_sparc.c @@ -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 #include -#include #include "kvm_private.h" -- cgit v1.1