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
loaded_mod(const char * name)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
sysvipc(const char * module,const char * name)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
main(int argc,char * argv[])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
setup(char * nam)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
devices(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
modules()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
sysdev(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
memseek(int sym)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
getnlist(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