1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * This command can now print the value of data items 32 * from [1] /dev/kmem is the default, and [2] a named 33 * file passed with the -n argument. If the read is from 34 * /dev/kmem, we also print the value of BSS symbols. 35 * The logic to support this is: if read is from file, 36 * [1] find the section number of .bss, [2] look through 37 * nlist for symbols that are in .bss section and zero 38 * the n_value field. At print time, if the n_value field 39 * is non-zero, print the info. 40 * 41 * This protects us from trying to read a bss symbol from 42 * the file and, possibly, dropping core. 43 * 44 * When reading from /dev/kmem, the n_value field is the 45 * seek address, and the contents are read from that address. 46 * 47 * NOTE: when reading from /dev/kmem, the actual, incore 48 * values will be printed, for example: the current nodename 49 * will be printed, etc. 50 * 51 * the cmn line usage is: sysdef -i -n namelist -h -d -D 52 * (-i for incore, though this is now the default, the option 53 * is left in place for SVID compatibility) 54 */ 55 #include <stdio.h> 56 #include <nlist.h> 57 #include <string.h> 58 #include <sys/types.h> 59 #include <sys/sysmacros.h> 60 #include <sys/var.h> 61 #include <sys/tuneable.h> 62 #include <sys/modctl.h> 63 #include <sys/fcntl.h> 64 #include <sys/utsname.h> 65 #include <sys/resource.h> 66 #include <sys/conf.h> 67 #include <sys/stat.h> 68 #include <sys/signal.h> 69 #include <sys/priocntl.h> 70 #include <sys/procset.h> 71 #include <sys/systeminfo.h> 72 #include <sys/machelf.h> 73 #include <dirent.h> 74 #include <ctype.h> 75 #include <stdlib.h> 76 #include <time.h> 77 #include <unistd.h> 78 #include <fcntl.h> 79 80 #include <libelf.h> 81 82 extern void sysdef_devinfo(void); 83 84 static gid_t egid; 85 86 #define SYM_VALUE(sym) (nl[(sym)].n_value) 87 #define MEMSEEK(sym) memseek(sym) 88 #define MEMREAD(var) fread((char *)&var, sizeof (var), 1, \ 89 (incore ? memfile : sysfile)) 90 91 struct var v; 92 struct tune tune; 93 94 int incore = 1; /* The default is "incore" */ 95 int bss; /* if read from file, don't read bss symbols */ 96 int hostidf = 0; /* 0 == print hostid with other info, */ 97 /* 1 == print just the hostid */ 98 int devflag = 0; /* SunOS4.x devinfo compatible output */ 99 int drvname_flag = 0; /* print the driver name as well as the node */ 100 int nflag = 0; 101 char *os = "/dev/ksyms"; /* Wont always have a /kernel/unix */ 102 /* This wont fully replace it funtionally */ 103 /* but is a reasonable default/placeholder */ 104 105 char *mem = "/dev/kmem"; 106 107 int nstrpush; 108 ssize_t strmsgsz, strctlsz; 109 short ts_maxupri; 110 char sys_name[10]; 111 int nlsize, lnsize; 112 FILE *sysfile, *memfile; 113 114 void setln(char *, int, int, int); 115 void getnlist(void); 116 void memseek(int); 117 void devices(void); 118 void sysdev(void); 119 int setup(char *); 120 void modules(void); 121 122 struct nlist *nl, *nlptr; 123 int vs, tu, utsnm, bdev, pnstrpush, 124 pstrmsgsz, pstrctlsz, endnm, 125 pts_maxupri, psys_name, fd_cur, fd_max; 126 127 #define MAXI 300 128 #define MAXL MAXI/11+10 129 #define EXPAND 99 130 131 struct link { 132 char *l_cfnm; /* config name from master table */ 133 int l_funcidx; /* index into name list structure */ 134 unsigned int l_soft :1; /* software driver flag from master table */ 135 unsigned int l_dtype:1; /* set if block device */ 136 unsigned int l_used :1; /* set when device entry is printed */ 137 } *ln, *lnptr, *majsrch(); 138 139 /* ELF Items */ 140 Elf *elfd = NULL; 141 Ehdr *ehdr = NULL; 142 143 #ifdef _ELF64 144 #define elf_getehdr elf64_getehdr 145 #define elf_getshdr elf64_getshdr 146 #else 147 #define elf_getehdr elf32_getehdr 148 #define elf_getshdr elf32_getshdr 149 #endif 150 151 /* This procedure checks if module "name" is currently loaded */ 152 153 int 154 loaded_mod(const char *name) 155 { 156 struct modinfo modinfo; 157 158 /* mi_nextid of -1 means we're getting info on all modules */ 159 modinfo.mi_id = modinfo.mi_nextid = -1; 160 modinfo.mi_info = MI_INFO_ALL; 161 162 while (modctl(MODINFO, modinfo.mi_id, &modinfo) >= 0) 163 if (strcmp(modinfo.mi_name, name) == 0) 164 return (1); 165 166 return (0); 167 } 168 169 const char *sysv_transition = 170 "*\n* IPC %s\n*\n" 171 "* The IPC %s module no longer has system-wide limits.\n" 172 "* Please see the \"Solaris Tunable Parameters Reference Manual\" for\n" 173 "* information on how the old limits map to resource controls and\n" 174 "* the prctl(1) and getrctl(2) manual pages for information on\n" 175 "* observing the new limits.\n*\n"; 176 177 const char *sysv_notloaded = 178 "*\n* IPC %s module is not loaded\n*\n"; 179 180 /* 181 * Emit a message pointing script writers to the new source for 182 * System V IPC information. 183 */ 184 void 185 sysvipc(const char *module, const char *name) 186 { 187 if (loaded_mod(module)) 188 (void) printf(sysv_transition, name, name); 189 else 190 (void) printf(sysv_notloaded, name); 191 } 192 193 int 194 main(int argc, char *argv[]) 195 { 196 struct utsname utsname; 197 Elf_Scn *scn; 198 Shdr *shdr; 199 char *name; 200 int ndx; 201 int i; 202 char hostid[256], *end; 203 unsigned long hostval; 204 uint_t rlim_fd_cur, rlim_fd_max; 205 206 egid = getegid(); 207 setegid(getgid()); 208 209 while ((i = getopt(argc, argv, "dihDn:?")) != EOF) { 210 switch (i) { 211 case 'D': 212 drvname_flag++; 213 break; 214 case 'd': 215 devflag++; 216 break; 217 case 'h': 218 hostidf++; 219 break; 220 case 'i': 221 incore++; /* In case "-i and -n" passed */ 222 break; /* Not logical, but not disallowed */ 223 case 'n': 224 nflag = 1; 225 incore--; /* Not incore, use specified file */ 226 os = optarg; 227 break; 228 default: 229 fprintf(stderr, 230 "usage: %s [-D -d -i -h -n namelist]\n", 231 argv[0]); 232 return (1); 233 } 234 } 235 236 /* 237 * Prints hostid of machine. 238 */ 239 if (sysinfo(SI_HW_SERIAL, hostid, sizeof (hostid)) == -1) { 240 fprintf(stderr, "hostid: sysinfo failed\n"); 241 return (1); 242 } 243 hostval = strtoul(hostid, &end, 10); 244 if (hostval == 0 && end == hostid) { 245 fprintf(stderr, "hostid: hostid string returned by " 246 "sysinfo not numeric: \"%s\"\n", hostid); 247 return (1); 248 } 249 if (!devflag) 250 fprintf(stdout, "*\n* Hostid\n*\n %8.8x\n", hostval); 251 252 if (hostidf) 253 return (0); 254 255 if (((sysfile = fopen(os, "r")) == NULL) && nflag) { 256 fprintf(stderr, "cannot open %s\n", os); 257 return (1); 258 } 259 260 if (sysfile) { 261 if (incore) { 262 int memfd; 263 264 setegid(egid); 265 if ((memfile = fopen(mem, "r")) == NULL) { 266 fprintf(stderr, "cannot open %s\n", mem); 267 return (1); 268 } 269 setegid(getgid()); 270 271 memfd = fileno(memfile); 272 fcntl(memfd, F_SETFD, 273 fcntl(memfd, F_GETFD, 0) | FD_CLOEXEC); 274 } 275 276 /* 277 * Use libelf to read both COFF and ELF namelists 278 */ 279 280 if ((elf_version(EV_CURRENT)) == EV_NONE) { 281 fprintf(stderr, "ELF Access Library out of date\n"); 282 return (1); 283 } 284 285 if ((elfd = elf_begin(fileno(sysfile), ELF_C_READ, 286 NULL)) == NULL) { 287 fprintf(stderr, "Unable to elf begin %s (%s)\n", 288 os, elf_errmsg(-1)); 289 return (1); 290 } 291 292 if ((ehdr = elf_getehdr(elfd)) == NULL) { 293 fprintf(stderr, "%s: Can't read Exec header (%s)\n", 294 os, elf_errmsg(-1)); 295 return (1); 296 } 297 298 if ((((elf_kind(elfd)) != ELF_K_ELF) && 299 ((elf_kind(elfd)) != ELF_K_COFF)) || 300 (ehdr->e_type != ET_EXEC)) { 301 fprintf(stderr, "%s: invalid file\n", os); 302 elf_end(elfd); 303 return (1); 304 } 305 306 /* 307 * If this is a file read, look for .bss section 308 */ 309 310 if (!incore) { 311 ndx = 1; 312 scn = NULL; 313 while ((scn = elf_nextscn(elfd, scn)) != NULL) { 314 if ((shdr = elf_getshdr(scn)) == NULL) { 315 fprintf(stderr, 316 "%s: Error reading Shdr (%s)\n", 317 os, elf_errmsg(-1)); 318 return (1); 319 } 320 name = elf_strptr(elfd, ehdr->e_shstrndx, 321 (size_t)shdr->sh_name); 322 if ((name) && ((strcmp(name, ".bss")) == 0)) { 323 bss = ndx; 324 } 325 ndx++; 326 } 327 } /* (!incore) */ 328 } 329 330 uname(&utsname); 331 if (!devflag) 332 printf("*\n* %s Configuration\n*\n", utsname.machine); 333 334 if (sysfile) { 335 nlsize = MAXI; 336 lnsize = MAXL; 337 nl = (struct nlist *)calloc(nlsize, sizeof (struct nlist)); 338 ln = (struct link *)calloc(lnsize, sizeof (struct link)); 339 nlptr = nl; 340 lnptr = ln; 341 342 bdev = setup("bdevsw"); 343 setup(""); 344 345 getnlist(); 346 347 if (!devflag) 348 printf("*\n* Devices\n*\n"); 349 devices(); 350 if (devflag) 351 return (0); 352 353 printf("*\n* Loadable Objects\n"); 354 355 modules(); 356 } 357 358 printf("*\n* System Configuration\n*\n"); 359 360 sysdev(); 361 362 if (sysfile) { 363 /* easy stuff */ 364 printf("*\n* Tunable Parameters\n*\n"); 365 nlptr = nl; 366 vs = setup("v"); 367 tu = setup("tune"); 368 utsnm = setup("utsname"); 369 pnstrpush = setup("nstrpush"); 370 pstrmsgsz = setup("strmsgsz"); 371 pstrctlsz = setup("strctlsz"); 372 pts_maxupri = setup("ts_maxupri"); 373 psys_name = setup("sys_name"); 374 fd_cur = setup("rlim_fd_cur"); 375 fd_max = setup("rlim_fd_max"); 376 377 /* 378 * This assignment to endnm must follow all calls to setup(). 379 */ 380 endnm = setup(""); 381 382 getnlist(); 383 384 for (nlptr = &nl[vs]; nlptr != &nl[endnm]; nlptr++) { 385 if (nlptr->n_value == 0 && 386 (incore || nlptr->n_scnum != bss)) { 387 fprintf(stderr, "namelist error on <%s>\n", 388 nlptr->n_name); 389 /* return (1); */ 390 } 391 } 392 if (SYM_VALUE(vs)) { 393 MEMSEEK(vs); 394 MEMREAD(v); 395 } 396 printf("%8d maximum memory allowed in buffer cache " 397 "(bufhwm)\n", v.v_bufhwm * 1024); 398 printf("%8d maximum number of processes (v.v_proc)\n", 399 v.v_proc); 400 printf("%8d maximum global priority in sys class " 401 "(MAXCLSYSPRI)\n", v.v_maxsyspri); 402 printf("%8d maximum processes per user id (v.v_maxup)\n", 403 v.v_maxup); 404 printf("%8d auto update time limit in seconds (NAUTOUP)\n", 405 v.v_autoup); 406 if (SYM_VALUE(tu)) { 407 MEMSEEK(tu); 408 MEMREAD(tune); 409 } 410 printf("%8d page stealing low water mark (GPGSLO)\n", 411 tune.t_gpgslo); 412 printf("%8d fsflush run rate (FSFLUSHR)\n", 413 tune.t_fsflushr); 414 printf("%8d minimum resident memory for avoiding " 415 "deadlock (MINARMEM)\n", tune.t_minarmem); 416 printf("%8d minimum swapable memory for avoiding deadlock " 417 "(MINASMEM)\n", tune.t_minasmem); 418 } 419 420 printf("*\n* Utsname Tunables\n*\n"); 421 if (sysfile && SYM_VALUE(utsnm)) { 422 MEMSEEK(utsnm); 423 MEMREAD(utsname); 424 } 425 printf("%8s release (REL)\n", utsname.release); 426 printf("%8s node name (NODE)\n", utsname.nodename); 427 printf("%8s system name (SYS)\n", utsname.sysname); 428 printf("%8s version (VER)\n", utsname.version); 429 430 if (sysfile) { 431 printf("*\n* Process Resource Limit Tunables " 432 "(Current:Maximum)\n*\n"); 433 if (SYM_VALUE(fd_cur)) { 434 MEMSEEK(fd_cur); 435 MEMREAD(rlim_fd_cur); 436 } 437 if (SYM_VALUE(fd_max)) { 438 MEMSEEK(fd_max); 439 MEMREAD(rlim_fd_max); 440 } 441 442 printf("0x%16.16x:", rlim_fd_cur); 443 printf("0x%16.16x", rlim_fd_max); 444 printf("\tfile descriptors\n"); 445 446 printf("*\n* Streams Tunables\n*\n"); 447 if (SYM_VALUE(pnstrpush)) { 448 MEMSEEK(pnstrpush); MEMREAD(nstrpush); 449 printf("%6d maximum number of pushes allowed " 450 "(NSTRPUSH)\n", nstrpush); 451 } 452 if (SYM_VALUE(pstrmsgsz)) { 453 MEMSEEK(pstrmsgsz); MEMREAD(strmsgsz); 454 printf("%6ld maximum stream message size " 455 "(STRMSGSZ)\n", strmsgsz); 456 } 457 if (SYM_VALUE(pstrctlsz)) { 458 MEMSEEK(pstrctlsz); MEMREAD(strctlsz); 459 printf("%6ld max size of ctl part of message " 460 "(STRCTLSZ)\n", strctlsz); 461 } 462 } 463 464 sysvipc("msgsys", "Messages"); 465 sysvipc("semsys", "Semaphores"); 466 sysvipc("shmsys", "Shared Memory"); 467 468 if (sysfile) { 469 if (SYM_VALUE(pts_maxupri)) { 470 printf("*\n* Time Sharing Scheduler Tunables\n*\n"); 471 MEMSEEK(pts_maxupri); MEMREAD(ts_maxupri); 472 printf("%d maximum time sharing user " 473 "priority (TSMAXUPRI)\n", ts_maxupri); 474 } 475 476 if (SYM_VALUE(psys_name)) { 477 MEMSEEK(psys_name); MEMREAD(sys_name); 478 printf("%s system class name (SYS_NAME)\n", 479 sys_name); 480 } 481 482 if (elfd) 483 elf_end(elfd); 484 } 485 return (0); 486 } 487 488 /* 489 * setup - add an entry to a namelist structure array 490 */ 491 int 492 setup(char *nam) 493 { 494 int idx; 495 496 if (nlptr >= &nl[nlsize]) { 497 if ((nl = (struct nlist *)realloc(nl, 498 (nlsize + EXPAND) * sizeof (struct nlist))) == NULL) { 499 fprintf(stderr, "Namelist space allocation failed\n"); 500 exit(1); 501 } 502 nlptr = &nl[nlsize]; 503 nlsize += EXPAND; 504 } 505 506 nlptr->n_name = malloc(strlen(nam) + 1); /* pointer to next string */ 507 strcpy(nlptr->n_name, nam); /* move name into string table */ 508 nlptr->n_type = 0; 509 nlptr->n_value = 0; 510 idx = nlptr++ - nl; 511 return (idx); 512 } 513 514 /* 515 * Handle the configured devices 516 */ 517 void 518 devices(void) 519 { 520 setegid(egid); 521 sysdef_devinfo(); 522 setegid(getgid()); 523 } 524 525 char *LS_MODULES = "/bin/ls -R -p -i -1 "; 526 char *MODULES_TMPFILE = "/tmp/sysdef.sort.XXXXXX"; 527 528 void 529 modules() 530 { 531 int i; 532 int n_dirs = 0; 533 ino_t *inodes; 534 char *curr, *next; 535 char **dirs; 536 char *modpath, *ls_cmd; 537 char *tmpf; 538 int curr_len, modpathlen; 539 int ls_cmd_len = strlen(LS_MODULES); 540 int sfd; 541 542 if ((modctl(MODGETPATHLEN, NULL, &modpathlen)) != 0) { 543 fprintf(stderr, "sysdef: fail to get module path length\n"); 544 exit(1); 545 } 546 if ((modpath = malloc(modpathlen + 1)) == NULL) { 547 fprintf(stderr, "sysdef: malloc failed\n"); 548 exit(1); 549 } 550 if (modctl(MODGETPATH, NULL, modpath) != 0) { 551 fprintf(stderr, "sysdef: fail to get module path\n"); 552 exit(1); 553 } 554 555 /* 556 * Figure out number of directory entries in modpath. 557 * Module paths are stored in a space separated string 558 */ 559 curr = modpath; 560 while (curr) { 561 n_dirs++; 562 curr = strchr(curr + 1, ' '); 563 } 564 565 if (((inodes = (ino_t *)malloc(n_dirs * sizeof (ino_t))) == NULL) || 566 ((dirs = (char **)malloc(n_dirs * sizeof (char *))) == NULL)) { 567 fprintf(stderr, "sysdef: malloc failed\n"); 568 exit(1); 569 } 570 571 if ((tmpf = malloc(strlen(MODULES_TMPFILE) + 1)) == NULL) { 572 fprintf(stderr, "sysdef: malloc failed\n"); 573 exit(1); 574 } 575 576 curr = modpath; 577 for (i = 0; i < n_dirs; i++) { 578 int j, len, inode, ino; 579 char line[100], path[100], *pathptr = ""; 580 char srtbuf[100], *sorted_fname; 581 FILE *lspipe, *srtpipe, *fp; 582 struct stat stat_buf; 583 584 if (next = strchr(curr, ' ')) { 585 *next = '\0'; 586 } 587 588 /* 589 * Make sure the module path is present. 590 */ 591 if (stat(curr, &stat_buf) == -1) { 592 curr = next ? next + 1 : NULL; 593 inodes[i] = (ino_t)-1; 594 continue; 595 } 596 597 /* 598 * On sparcs, /platform/SUNW,... can be symbolic link to 599 * /platform/sun4x. We check the inode number of directory 600 * and skip any duplication. 601 */ 602 dirs[i] = curr; 603 inodes[i] = stat_buf.st_ino; 604 605 for (j = 0; inodes[i] != inodes[j]; j++) 606 ; 607 if (j != i) { 608 curr = next ? next + 1 : NULL; 609 continue; 610 } 611 612 printf("*\n* Loadable Object Path = %s\n*\n", curr); 613 614 curr_len = strlen(curr); 615 if ((ls_cmd = malloc(ls_cmd_len + curr_len + 1)) == NULL) { 616 fprintf(stderr, "sysdef: malloc failed\n"); 617 exit(1); 618 } 619 620 (void) sprintf(ls_cmd, "%s%s", LS_MODULES, curr); 621 622 /* 623 * List the loadable objects in the directory tree, sorting 624 * them by inode so as to note any hard links. A temporary 625 * file in /tmp is used to store output from sort before 626 * listing. 627 */ 628 if ((lspipe = popen(ls_cmd, "r")) == NULL) { 629 fprintf(stderr, "sysdef: cannot open ls pipe\n"); 630 exit(1); 631 } 632 free(ls_cmd); 633 634 (void) strcpy(tmpf, MODULES_TMPFILE); 635 if ((sorted_fname = mktemp(tmpf)) == NULL || 636 (strcmp(sorted_fname, "") == 0)) { 637 fprintf(stderr, 638 "sysdef: cannot create unique tmp file name\n"); 639 exit(1); 640 } 641 642 if ((sfd = open(sorted_fname, O_RDWR|O_CREAT|O_EXCL, 643 0600)) == -1) { 644 fprintf(stderr, "sysdef: cannot open %s\n", 645 sorted_fname); 646 exit(1); 647 } 648 649 sprintf(srtbuf, "/bin/sort - > %s", sorted_fname); 650 if ((srtpipe = popen(srtbuf, "w")) == NULL) { 651 fprintf(stderr, "sysdef: cannot open sort pipe\n"); 652 exit(1); 653 } 654 655 while (fgets(line, 99, lspipe) != NULL) { 656 char *tmp; 657 /* 658 * 'line' has <cr>, skip blank lines & dir entries 659 */ 660 if (((len = strlen(line)) <= 1) || 661 (line[len-2] == '/')) 662 continue; 663 664 /* remember path of each subdirectory */ 665 666 if (line[0] == '/') { 667 (void) strcpy(path, &line[curr_len]); 668 tmp = strtok(&path[1], ":"); 669 if ((tmp == NULL) || (tmp[0] == '\n')) { 670 continue; 671 } 672 pathptr = &path[1]; 673 (void) strcat(pathptr, "/"); 674 continue; 675 } else { 676 char *tmp1 = strtok(line, " "); 677 tmp = strtok(NULL, "\n"); 678 /* 679 * eliminate .conf file 680 */ 681 if (strstr(tmp, ".conf")) { 682 continue; 683 } 684 /* 685 * Printing the (inode, path, module) 686 * ripple. 687 */ 688 fprintf(srtpipe, "%s %s%s\n", 689 tmp1, pathptr, tmp); 690 } 691 } 692 (void) pclose(lspipe); 693 (void) pclose(srtpipe); 694 695 /* 696 * A note on data synchronization. We opened sfd above, 697 * before calling popen, to ensure that the tempfile 698 * was created exclusively to prevent a malicious user 699 * from creating a link in /tmp to make us overwrite 700 * another file. We have never read from sfd, there 701 * can be no stale data cached anywhere. 702 */ 703 if ((fp = fdopen(sfd, "r")) == NULL) { 704 fprintf(stderr, "sysdef: cannot open sorted file: %s", 705 sorted_fname); 706 exit(1); 707 } 708 inode = -1; 709 while (fgets(line, 99, fp) != NULL) { 710 711 sscanf(line, "%d %s", &ino, path); 712 if (ino == inode) 713 printf("\thard link: "); 714 printf("%s\n", path); 715 inode = ino; 716 } 717 (void) fclose(fp); 718 (void) unlink(sorted_fname); 719 curr = next ? next + 1 : NULL; 720 } 721 free(tmpf); 722 free(modpath); 723 } 724 725 void 726 sysdev(void) 727 { 728 printf(" swap files\n"); 729 fflush(stdout); 730 if (system("/usr/sbin/swap -l") < 0) 731 fprintf(stderr, "unknown swap file(s)\n"); 732 } 733 734 void 735 memseek(int sym) 736 { 737 Elf_Scn *scn; 738 Shdr *eshdr; 739 long eoff; 740 741 if (incore) { 742 if ((fseek(memfile, nl[sym].n_value, 0)) != 0) { 743 fprintf(stderr, "%s: fseek error (in memseek)\n", mem); 744 exit(1); 745 } 746 } else { 747 if ((scn = elf_getscn(elfd, nl[sym].n_scnum)) == NULL) { 748 fprintf(stderr, "%s: Error reading Scn %d (%s)\n", 749 os, nl[sym].n_scnum, elf_errmsg(-1)); 750 exit(1); 751 } 752 753 if ((eshdr = elf_getshdr(scn)) == NULL) { 754 fprintf(stderr, "%s: Error reading Shdr %d (%s)\n", 755 os, nl[sym].n_scnum, elf_errmsg(-1)); 756 exit(1); 757 } 758 759 eoff = (long)(nl[sym].n_value - eshdr->sh_addr + 760 eshdr->sh_offset); 761 762 if ((fseek(sysfile, eoff, 0)) != 0) { 763 fprintf(stderr, "%s: fseek error (in memseek)\n", os); 764 exit(1); 765 } 766 } 767 } 768 769 /* 770 * filter out bss symbols if the reads are from the file 771 */ 772 void 773 getnlist(void) 774 { 775 struct nlist *p; 776 777 nlist(os, nl); 778 779 /* 780 * The nlist is done. If any symbol is a bss 781 * and we are not reading from incore, zero 782 * the n_value field. (Won't be printed if 783 * n_value == 0.) 784 */ 785 if (!incore) { 786 for (p = nl; p->n_name && p->n_name[0]; p++) { 787 if (p->n_scnum == bss) { 788 p->n_value = 0; 789 } 790 } 791 } 792 } 793