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