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 --- |