Deleted Added
full compact
kvm.c (52117) kvm.c (55127)
1/*-
2 * Copyright (c) 1989, 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software developed by the Computer Systems
6 * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
7 * BG 91-66 and contributed to Berkeley.
8 *

--- 26 unchanged lines hidden (view full) ---

35 * SUCH DAMAGE.
36 */
37
38#if defined(LIBC_SCCS) && !defined(lint)
39#if 0
40static char sccsid[] = "@(#)kvm.c 8.2 (Berkeley) 2/13/94";
41#else
42static const char rcsid[] =
1/*-
2 * Copyright (c) 1989, 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software developed by the Computer Systems
6 * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
7 * BG 91-66 and contributed to Berkeley.
8 *

--- 26 unchanged lines hidden (view full) ---

35 * SUCH DAMAGE.
36 */
37
38#if defined(LIBC_SCCS) && !defined(lint)
39#if 0
40static char sccsid[] = "@(#)kvm.c 8.2 (Berkeley) 2/13/94";
41#else
42static const char rcsid[] =
43 "$FreeBSD: head/lib/libkvm/kvm.c 52117 1999-10-11 05:01:17Z peter $";
43 "$FreeBSD: head/lib/libkvm/kvm.c 55127 1999-12-27 07:14:58Z peter $";
44#endif
45#endif /* LIBC_SCCS and not lint */
46
47#include <sys/param.h>
48#include <sys/user.h>
49#include <sys/proc.h>
50#include <sys/ioctl.h>
51#include <sys/stat.h>
52#include <sys/sysctl.h>
44#endif
45#endif /* LIBC_SCCS and not lint */
46
47#include <sys/param.h>
48#include <sys/user.h>
49#include <sys/proc.h>
50#include <sys/ioctl.h>
51#include <sys/stat.h>
52#include <sys/sysctl.h>
53#include <sys/linker.h>
53
54#include <vm/vm.h>
55#include <vm/vm_param.h>
56#include <vm/swap_pager.h>
57
58#include <machine/vmparam.h>
59
60#include <ctype.h>
54
55#include <vm/vm.h>
56#include <vm/vm_param.h>
57#include <vm/swap_pager.h>
58
59#include <machine/vmparam.h>
60
61#include <ctype.h>
61#include <db.h>
62#include <fcntl.h>
63#include <kvm.h>
64#include <limits.h>
65#include <nlist.h>
66#include <paths.h>
67#include <stdio.h>
68#include <stdlib.h>
69#include <string.h>
70#include <unistd.h>
71
72#include "kvm_private.h"
73
62#include <fcntl.h>
63#include <kvm.h>
64#include <limits.h>
65#include <nlist.h>
66#include <paths.h>
67#include <stdio.h>
68#include <stdlib.h>
69#include <string.h>
70#include <unistd.h>
71
72#include "kvm_private.h"
73
74static int kvm_dbopen __P((kvm_t *, const char *));
75
76char *
77kvm_geterr(kd)
78 kvm_t *kd;
79{
80 return (kd->errbuf);
81}
82
83#if __STDC__

--- 91 unchanged lines hidden (view full) ---

175 char *errout;
176{
177 struct stat st;
178
179 kd->vmfd = -1;
180 kd->pmfd = -1;
181 kd->nlfd = -1;
182 kd->vmst = 0;
74char *
75kvm_geterr(kd)
76 kvm_t *kd;
77{
78 return (kd->errbuf);
79}
80
81#if __STDC__

--- 91 unchanged lines hidden (view full) ---

173 char *errout;
174{
175 struct stat st;
176
177 kd->vmfd = -1;
178 kd->pmfd = -1;
179 kd->nlfd = -1;
180 kd->vmst = 0;
183 kd->db = 0;
184 kd->procbase = 0;
185 kd->argspc = 0;
186 kd->argv = 0;
187
188 if (uf == 0)
189 uf = getbootfile();
190 else if (strlen(uf) >= MAXPATHLEN) {
191 _kvm_err(kd, kd->program, "exec file name too long");

--- 28 unchanged lines hidden (view full) ---

220 "%s: not physical memory device", mf);
221 goto failed;
222 } else {
223 if ((kd->vmfd = open(_PATH_KMEM, flag)) < 0) {
224 _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM);
225 goto failed;
226 }
227 }
181 kd->procbase = 0;
182 kd->argspc = 0;
183 kd->argv = 0;
184
185 if (uf == 0)
186 uf = getbootfile();
187 else if (strlen(uf) >= MAXPATHLEN) {
188 _kvm_err(kd, kd->program, "exec file name too long");

--- 28 unchanged lines hidden (view full) ---

217 "%s: not physical memory device", mf);
218 goto failed;
219 } else {
220 if ((kd->vmfd = open(_PATH_KMEM, flag)) < 0) {
221 _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM);
222 goto failed;
223 }
224 }
228 /*
229 * Open kvm nlist database. We go ahead and do this
230 * here so that we don't have to hold on to the kernel
231 * path name. Since a kvm application will surely do
232 * a kvm_nlist(), this probably won't be a wasted effort.
233 * If the database cannot be opened, open the namelist
234 * argument so we revert to slow nlist() calls.
235 */
236 if (kvm_dbopen(kd, uf) < 0 &&
237 (kd->nlfd = open(uf, O_RDONLY, 0)) < 0) {
238 _kvm_syserr(kd, kd->program, "%s", uf);
239 goto failed;
240 }
241 } else {
242 /*
243 * This is a crash dump.
244 * Initialize the virtual address translation machinery,
245 * but first setup the namelist fd.
246 */
247 if ((kd->nlfd = open(uf, O_RDONLY, 0)) < 0) {
248 _kvm_syserr(kd, kd->program, "%s", uf);

--- 60 unchanged lines hidden (view full) ---

309 register int error = 0;
310
311 if (kd->pmfd >= 0)
312 error |= close(kd->pmfd);
313 if (kd->vmfd >= 0)
314 error |= close(kd->vmfd);
315 if (kd->nlfd >= 0)
316 error |= close(kd->nlfd);
225 } else {
226 /*
227 * This is a crash dump.
228 * Initialize the virtual address translation machinery,
229 * but first setup the namelist fd.
230 */
231 if ((kd->nlfd = open(uf, O_RDONLY, 0)) < 0) {
232 _kvm_syserr(kd, kd->program, "%s", uf);

--- 60 unchanged lines hidden (view full) ---

293 register int error = 0;
294
295 if (kd->pmfd >= 0)
296 error |= close(kd->pmfd);
297 if (kd->vmfd >= 0)
298 error |= close(kd->vmfd);
299 if (kd->nlfd >= 0)
300 error |= close(kd->nlfd);
317 if (kd->db != 0)
318 error |= (kd->db->close)(kd->db);
319 if (kd->vmst)
320 _kvm_freevtop(kd);
321 if (kd->procbase != 0)
322 free((void *)kd->procbase);
323 if (kd->argv != 0)
324 free((void *)kd->argv);
325 free((void *)kd);
326
327 return (0);
328}
329
301 if (kd->vmst)
302 _kvm_freevtop(kd);
303 if (kd->procbase != 0)
304 free((void *)kd->procbase);
305 if (kd->argv != 0)
306 free((void *)kd->argv);
307 free((void *)kd);
308
309 return (0);
310}
311
330/*
331 * Set up state necessary to do queries on the kernel namelist
332 * data base. If the data base is out-of-data/incompatible with
333 * given executable, set up things so we revert to standard nlist call.
334 * Only called for live kernels. Return 0 on success, -1 on failure.
335 */
336static int
337kvm_dbopen(kd, uf)
338 kvm_t *kd;
339 const char *uf;
340{
341 char *cp;
342 DBT rec;
343 int dbversionlen;
344 struct nlist nitem;
345 char dbversion[_POSIX2_LINE_MAX];
346 char kversion[_POSIX2_LINE_MAX];
347 char dbname[MAXPATHLEN];
348
349 if ((cp = rindex(uf, '/')) != 0)
350 uf = cp + 1;
351
352 (void)snprintf(dbname, sizeof(dbname), "%skvm_%s.db", _PATH_VARDB, uf);
353 kd->db = dbopen(dbname, O_RDONLY, 0, DB_HASH, NULL);
354 if (kd->db == 0)
355 return (-1);
356 /*
357 * read version out of database
358 */
359 rec.data = VRS_KEY;
360 rec.size = sizeof(VRS_KEY) - 1;
361 if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0))
362 goto close;
363 if (rec.data == 0 || rec.size > sizeof(dbversion))
364 goto close;
365
366 bcopy(rec.data, dbversion, rec.size);
367 dbversionlen = rec.size;
368 /*
369 * Read version string from kernel memory.
370 * Since we are dealing with a live kernel, we can call kvm_read()
371 * at this point.
372 */
373 rec.data = VRS_SYM;
374 rec.size = sizeof(VRS_SYM) - 1;
375 if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0))
376 goto close;
377 if (rec.data == 0 || rec.size != sizeof(struct nlist))
378 goto close;
379 bcopy((char *)rec.data, (char *)&nitem, sizeof(nitem));
380 if (kvm_read(kd, (u_long)nitem.n_value, kversion, dbversionlen) !=
381 dbversionlen)
382 goto close;
383 /*
384 * If they match, we win - otherwise clear out kd->db so
385 * we revert to slow nlist().
386 */
387 if (bcmp(dbversion, kversion, dbversionlen) == 0)
388 return (0);
389close:
390 (void)(kd->db->close)(kd->db);
391 kd->db = 0;
392
393 return (-1);
394}
395
396int
397kvm_nlist(kd, nl)
398 kvm_t *kd;
399 struct nlist *nl;
400{
401 register struct nlist *p;
402 register int nvalid;
312int
313kvm_nlist(kd, nl)
314 kvm_t *kd;
315 struct nlist *nl;
316{
317 register struct nlist *p;
318 register int nvalid;
319 struct kld_sym_lookup lookup;
403
404 /*
320
321 /*
405 * If we can't use the data base, revert to the
322 * If we can't use the kld symbol lookup, revert to the
406 * slow library call.
407 */
323 * slow library call.
324 */
408 if (kd->db == 0)
325 if (!ISALIVE(kd))
409 return (__fdnlist(kd->nlfd, nl));
410
411 /*
326 return (__fdnlist(kd->nlfd, nl));
327
328 /*
412 * We can use the kvm data base. Go through each nlist entry
413 * and look it up with a db query.
329 * We can use the kld lookup syscall. Go through each nlist entry
330 * and look it up with a kldsym(2) syscall.
414 */
415 nvalid = 0;
416 for (p = nl; p->n_name && p->n_name[0]; ++p) {
331 */
332 nvalid = 0;
333 for (p = nl; p->n_name && p->n_name[0]; ++p) {
417 register int len;
418 DBT rec;
334 lookup.version = sizeof(lookup);
335 lookup.symname = p->n_name;
336 lookup.symvalue = 0;
337 lookup.symsize = 0;
419
338
420 if ((len = strlen(p->n_name)) > 4096) {
421 /* sanity */
422 _kvm_err(kd, kd->program, "symbol too large");
423 return (-1);
339 if (lookup.symname[0] == '_')
340 lookup.symname++;
341
342 if (kldsym(0, KLDSYM_LOOKUP, &lookup) != -1) {
343 p->n_type = N_TEXT;
344 p->n_other = 0;
345 p->n_desc = 0;
346 p->n_value = lookup.symvalue;
347 ++nvalid;
348 /* lookup.symsize */
424 }
349 }
425 rec.data = p->n_name;
426 rec.size = len;
427 if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0))
428 continue;
429 if (rec.data == 0 || rec.size != sizeof(struct nlist))
430 continue;
431 ++nvalid;
432 /*
433 * Avoid alignment issues.
434 */
435 bcopy((char *)&((struct nlist *)rec.data)->n_type,
436 (char *)&p->n_type,
437 sizeof(p->n_type));
438 bcopy((char *)&((struct nlist *)rec.data)->n_value,
439 (char *)&p->n_value,
440 sizeof(p->n_value));
441 }
442 /*
443 * Return the number of entries that weren't found.
444 */
445 return ((p - nl) - nvalid);
446}
447
448ssize_t

--- 95 unchanged lines hidden ---
350 }
351 /*
352 * Return the number of entries that weren't found.
353 */
354 return ((p - nl) - nvalid);
355}
356
357ssize_t

--- 95 unchanged lines hidden ---