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