Bug Summary

File:src/usr.bin/nm/nm.c
Warning:line 720, column 10
Assigned value is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name nm.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/nm/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.bin/nm -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/nm/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/nm/nm.c
1/* $OpenBSD: nm.c,v 1.54 2019/03/03 16:07:39 schwarze Exp $ */
2/* $NetBSD: nm.c,v 1.7 1996/01/14 23:04:03 pk Exp $ */
3
4/*
5 * Copyright (c) 1989, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Hans Huebner.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#include <sys/types.h>
37#include <sys/mman.h>
38#include <a.out.h>
39#include <elf.h>
40#include <ar.h>
41#include <ranlib.h>
42#include <unistd.h>
43#include <err.h>
44#include <errno(*__errno()).h>
45#include <ctype.h>
46#include <link.h>
47
48#include <stdio.h>
49#include <stdlib.h>
50#include <string.h>
51#include <getopt.h>
52#include "util.h"
53#include "elfuncs.h"
54
55#define SYMTABMAG"/ " "/ "
56#define STRTABMAG"//" "//"
57#define SYM64MAG"/SYM64/ " "/SYM64/ "
58
59union hdr {
60 Elf32_Ehdr elf32;
61 Elf64_Ehdr elf64;
62};
63
64int armap;
65int demangle;
66int non_object_warning;
67int print_only_external_symbols;
68int print_only_undefined_symbols;
69int print_all_symbols;
70int print_file_each_line;
71int show_extensions;
72int issize;
73char posix_fmtstr[6];
74int posix_output;
75char posix_radix = 'x';
76int usemmap = 1;
77int dynamic_only;
78
79/* size vars */
80unsigned long total_text, total_data, total_bss, total_total;
81int non_object_warning, print_totals;
82
83int rev;
84int fname(const void *, const void *);
85int rname(const void *, const void *);
86int value(const void *, const void *);
87char *otherstring(struct xnlist *);
88int (*sfunc)(const void *, const void *) = fname;
89char typeletter(struct xnlist *);
90int mmbr_name(struct ar_hdr *, char **, int, int *, FILE *);
91int show_symtab(off_t, u_long, const char *, FILE *);
92int show_symdef(off_t, u_long, const char *, FILE *);
93
94/* some macros for symbol type (nlist.n_type) handling */
95#define IS_EXTERNAL(x)((x) & 0x01) ((x) & N_EXT0x01)
96#define SYMBOL_TYPE(x)((x) & (0x1e | 0x0e0)) ((x) & (N_TYPE0x1e | N_STAB0x0e0))
97
98void pipe2cppfilt(void);
99void usage(void);
100char *symname(struct xnlist *);
101int process_file(int, const char *);
102int show_archive(int, const char *, FILE *);
103int show_file(int, int, const char *, FILE *fp, off_t, union hdr *);
104void print_symbol(const char *, struct xnlist *);
105
106#define OPTSTRING_NM"aABCDegnopPrst:uvw" "aABCDegnopPrst:uvw"
107const struct option longopts_nm[] = {
108 { "debug-syms", no_argument0, 0, 'a' },
109 { "demangle", no_argument0, 0, 'C' },
110 { "dynamic", no_argument0, 0, 'D' },
111 { "extern-only", no_argument0, 0, 'g' },
112/* { "line-numbers", no_argument, 0, 'l' }, */
113 { "no-sort", no_argument0, 0, 'p' },
114 { "numeric-sort", no_argument0, 0, 'n' },
115 { "print-armap", no_argument0, 0, 's' },
116 { "print-file-name", no_argument0, 0, 'o' },
117 { "reverse-sort", no_argument0, 0, 'r' },
118/* { "size-sort", no_argument, &szval, 1 }, */
119 { "undefined-only", no_argument0, 0, 'u' },
120 { "help", no_argument0, 0, '?' },
121 { NULL((void *)0) }
122};
123
124/*
125 * main()
126 * parse command line, execute process_file() for each file
127 * specified on the command line.
128 */
129int
130main(int argc, char *argv[])
131{
132 extern char *__progname;
133 extern int optind;
134 const char *optstr;
135 const struct option *lopts;
136 int ch, eval;
137
138 if (pledge("stdio rpath proc exec", NULL((void *)0)) == -1)
1
Assuming the condition is false
2
Taking false branch
139 err(1, "pledge");
140
141 optstr = OPTSTRING_NM"aABCDegnopPrst:uvw";
142 lopts = longopts_nm;
143 if (!strcmp(__progname, "size")) {
3
Assuming the condition is false
4
Taking false branch
144 if (pledge("stdio rpath", NULL((void *)0)) == -1)
145 err(1, "pledge");
146
147 issize = 1;
148 optstr = "tw";
149 lopts = NULL((void *)0);
150 }
151
152 while ((ch = getopt_long(argc, argv, optstr, lopts, NULL((void *)0))) != -1) {
5
Assuming the condition is false
6
Loop condition is false. Execution continues on line 215
153 switch (ch) {
154 case 'a':
155 print_all_symbols = 1;
156 break;
157 case 'B':
158 /* no-op, compat with gnu-nm */
159 break;
160 case 'C':
161 demangle = 1;
162 break;
163 case 'D':
164 dynamic_only = 1;
165 break;
166 case 'e':
167 show_extensions = 1;
168 break;
169 case 'g':
170 print_only_external_symbols = 1;
171 break;
172 case 'n':
173 case 'v':
174 sfunc = value;
175 break;
176 case 'A':
177 case 'o':
178 print_file_each_line = 1;
179 break;
180 case 'p':
181 sfunc = NULL((void *)0);
182 break;
183 case 'P':
184 posix_output = 1;
185 break;
186 case 'r':
187 rev = 1;
188 break;
189 case 's':
190 armap = 1;
191 break;
192 case 'u':
193 print_only_undefined_symbols = 1;
194 break;
195 case 'w':
196 non_object_warning = 1;
197 break;
198 case 't':
199 if (issize) {
200 print_totals = 1;
201 } else {
202 posix_radix = *optarg;
203 if (strlen(optarg) != 1 ||
204 (posix_radix != 'd' && posix_radix != 'o' &&
205 posix_radix != 'x'))
206 usage();
207 }
208 break;
209 case '?':
210 default:
211 usage();
212 }
213 }
214
215 if (posix_output)
7
Assuming 'posix_output' is 0
8
Taking false branch
216 (void)snprintf(posix_fmtstr, sizeof posix_fmtstr, "%%%c %%%c",
217 posix_radix, posix_radix);
218 if (demangle)
9
Assuming 'demangle' is 0
10
Taking false branch
219 pipe2cppfilt();
220
221 if (pledge("stdio rpath", NULL((void *)0)) == -1)
11
Assuming the condition is false
12
Taking false branch
222 err(1, "pledge");
223
224 argv += optind;
225 argc -= optind;
226
227 if (rev && sfunc == fname)
13
Assuming 'rev' is 0
228 sfunc = rname;
229
230 eval = 0;
231 if (*argv)
14
Assuming the condition is false
15
Taking false branch
232 do {
233 eval |= process_file(argc, *argv);
234 } while (*++argv);
235 else
236 eval |= process_file(1, "a.out");
16
Calling 'process_file'
237
238 if (issize && print_totals)
239 printf("\n%lu\t%lu\t%lu\t%lu\t%lx\tTOTAL\n",
240 total_text, total_data, total_bss,
241 total_total, total_total);
242 exit(eval);
243}
244
245/*
246 * process_file()
247 * show symbols in the file given as an argument. Accepts archive and
248 * object files as input.
249 */
250int
251process_file(int count, const char *fname)
252{
253 union hdr exec_head;
254 FILE *fp;
255 int retval;
256 size_t bytes;
257 char magic[SARMAG8];
258
259 if (!(fp = fopen(fname, "r"))) {
17
Assuming 'fp' is non-null
18
Taking false branch
260 warn("cannot read %s", fname);
261 return(1);
262 }
263
264 if (!issize && count > 1)
19
Assuming 'issize' is not equal to 0
265 (void)printf("\n%s:\n", fname);
266
267 /*
268 * first check whether this is an object file - read a object
269 * header, and skip back to the beginning
270 */
271 bzero(&exec_head, sizeof(exec_head));
272 bytes = fread((char *)&exec_head, 1, sizeof(exec_head), fp);
273 if (bytes < sizeof(exec_head)) {
20
Assuming the condition is false
21
Taking false branch
274 if (bytes < sizeof(exec_head.elf32) || IS_ELF(exec_head.elf32)((exec_head.elf32).e_ident[0] == 0x7f && (exec_head.elf32
).e_ident[1] == 'E' && (exec_head.elf32).e_ident[2] ==
'L' && (exec_head.elf32).e_ident[3] == 'F')
) {
275 warnx("%s: bad format", fname);
276 (void)fclose(fp);
277 return(1);
278 }
279 }
280 rewind(fp);
281
282 /* this could be an archive */
283 if (!IS_ELF(exec_head.elf32)((exec_head.elf32).e_ident[0] == 0x7f && (exec_head.elf32
).e_ident[1] == 'E' && (exec_head.elf32).e_ident[2] ==
'L' && (exec_head.elf32).e_ident[3] == 'F')
) {
22
Assuming the condition is true
23
Assuming the condition is true
24
Assuming the condition is true
25
Assuming the condition is true
26
Taking false branch
284 if (fread(magic, sizeof(magic), (size_t)1, fp) != 1 ||
285 strncmp(magic, ARMAG"!<arch>\n", SARMAG8)) {
286 warnx("%s: not object file or archive", fname);
287 (void)fclose(fp);
288 return(1);
289 }
290 retval = show_archive(count, fname, fp);
291 } else
292 retval = show_file(count, 1, fname, fp, 0, &exec_head);
27
Calling 'show_file'
293 (void)fclose(fp);
294 return(retval);
295}
296
297char *nametab;
298
299/*
300 *
301 * given the archive member header -- produce member name
302 */
303int
304mmbr_name(struct ar_hdr *arh, char **name, int baselen, int *namelen, FILE *fp)
305{
306 char *p = *name + strlen(*name);
307 long i;
308
309 if (nametab && arh->ar_name[0] == '/') {
310 int len;
311
312 i = atol(&arh->ar_name[1]);
313 len = strlen(&nametab[i]) + 1;
314 if (len > *namelen) {
315 p -= (long)*name;
316 if ((*name = realloc(*name, baselen+len)) == NULL((void *)0))
317 err(1, NULL((void *)0));
318 *namelen = len;
319 p += (long)*name;
320 }
321 strlcpy(p, &nametab[i], len);
322 p += len - 1;
323 } else
324#ifdef AR_EFMT1"#1/"
325 /*
326 * BSD 4.4 extended AR format: #1/<namelen>, with name as the
327 * first <namelen> bytes of the file
328 */
329 if ((arh->ar_name[0] == '#') &&
330 (arh->ar_name[1] == '1') &&
331 (arh->ar_name[2] == '/') &&
332 (isdigit((unsigned char)arh->ar_name[3]))) {
333 int len = atoi(&arh->ar_name[3]);
334
335 if (len > *namelen) {
336 p -= (long)*name;
337 if ((*name = realloc(*name, baselen+len)) == NULL((void *)0))
338 err(1, NULL((void *)0));
339 *namelen = len;
340 p += (long)*name;
341 }
342 if (fread(p, len, 1, fp) != 1) {
343 warnx("%s: premature EOF", *name);
344 free(*name);
345 return(1);
346 }
347 p += len;
348 } else
349#endif
350 for (i = 0; i < sizeof(arh->ar_name); ++i)
351 if (arh->ar_name[i] && arh->ar_name[i] != ' ')
352 *p++ = arh->ar_name[i];
353 *p = '\0';
354 if (p[-1] == '/')
355 *--p = '\0';
356
357 return (0);
358}
359
360/*
361 * show_symtab()
362 * show archive ranlib index (fs5)
363 */
364int
365show_symtab(off_t off, u_long len, const char *name, FILE *fp)
366{
367 struct ar_hdr ar_head;
368 int *symtab, *ps;
369 char *strtab, *p;
370 int num, rval = 0;
371 int namelen;
372 off_t restore;
373
374 restore = ftello(fp);
375
376 MMAP(symtab, len, PROT_READ, MAP_PRIVATE|MAP_FILE, fileno(fp), off)do { if ((symtab = mmap(((void *)0), len, 0x01, 0x0002|0, (!__isthreaded
? ((fp)->_file) : (fileno)(fp)), off)) == ((void *)-1)) {
usemmap = 0; if ((*__errno()) != 22) warn("mmap"); else if (
(symtab = malloc(len)) == ((void *)0)) { symtab = ((void *)-1
); warn("malloc"); } else if (pread((!__isthreaded ? ((fp)->
_file) : (fileno)(fp)), symtab, len, off) != len) { free(symtab
); symtab = ((void *)-1); warn("pread"); } } } while (0)
;
377 if (symtab == MAP_FAILED((void *)-1))
378 return (1);
379
380 namelen = sizeof(ar_head.ar_name);
381 if ((p = malloc(sizeof(ar_head.ar_name))) == NULL((void *)0)) {
382 warn("%s: malloc", name);
383 MUNMAP(symtab, len)do { if (usemmap) munmap(symtab, len); else free(symtab); symtab
= ((void *)0); } while (0)
;
384 return (1);
385 }
386
387 printf("\nArchive index:\n");
388 num = betoh32(*symtab)(__uint32_t)(__builtin_constant_p(*symtab) ? (__uint32_t)(((__uint32_t
)(*symtab) & 0xff) << 24 | ((__uint32_t)(*symtab) &
0xff00) << 8 | ((__uint32_t)(*symtab) & 0xff0000) >>
8 | ((__uint32_t)(*symtab) & 0xff000000) >> 24) : __swap32md
(*symtab))
;
389 strtab = (char *)(symtab + num + 1);
390 for (ps = symtab + 1; num--; ps++, strtab += strlen(strtab) + 1) {
391 if (fseeko(fp, betoh32(*ps)(__uint32_t)(__builtin_constant_p(*ps) ? (__uint32_t)(((__uint32_t
)(*ps) & 0xff) << 24 | ((__uint32_t)(*ps) & 0xff00
) << 8 | ((__uint32_t)(*ps) & 0xff0000) >> 8 |
((__uint32_t)(*ps) & 0xff000000) >> 24) : __swap32md
(*ps))
, SEEK_SET0)) {
392 warn("%s: fseeko", name);
393 rval = 1;
394 break;
395 }
396
397 if (fread(&ar_head, sizeof(ar_head), 1, fp) != 1 ||
398 memcmp(ar_head.ar_fmag, ARFMAG"`\n", sizeof(ar_head.ar_fmag))) {
399 warnx("%s: member fseeko", name);
400 rval = 1;
401 break;
402 }
403
404 *p = '\0';
405 if (mmbr_name(&ar_head, &p, 0, &namelen, fp)) {
406 rval = 1;
407 break;
408 }
409
410 printf("%s in %s\n", strtab, p);
411 }
412
413 fseeko(fp, restore, SEEK_SET0);
414
415 free(p);
416 MUNMAP(symtab, len)do { if (usemmap) munmap(symtab, len); else free(symtab); symtab
= ((void *)0); } while (0)
;
417 return (rval);
418}
419
420/*
421 * show_symdef()
422 * show archive ranlib index (gob)
423 */
424int
425show_symdef(off_t off, u_long len, const char *name, FILE *fp)
426{
427 struct ranlib *prn, *eprn;
428 struct ar_hdr ar_head;
429 char *symdef;
430 char *strtab, *p;
431 u_long size;
432 int namelen, rval = 0;
433
434 MMAP(symdef, len, PROT_READ, MAP_PRIVATE|MAP_FILE, fileno(fp), off)do { if ((symdef = mmap(((void *)0), len, 0x01, 0x0002|0, (!__isthreaded
? ((fp)->_file) : (fileno)(fp)), off)) == ((void *)-1)) {
usemmap = 0; if ((*__errno()) != 22) warn("mmap"); else if (
(symdef = malloc(len)) == ((void *)0)) { symdef = ((void *)-1
); warn("malloc"); } else if (pread((!__isthreaded ? ((fp)->
_file) : (fileno)(fp)), symdef, len, off) != len) { free(symdef
); symdef = ((void *)-1); warn("pread"); } } } while (0)
;
435 if (symdef == MAP_FAILED((void *)-1))
436 return (1);
437 if (usemmap)
438 (void)madvise(symdef, len, MADV_SEQUENTIAL2);
439
440 namelen = sizeof(ar_head.ar_name);
441 if ((p = malloc(sizeof(ar_head.ar_name))) == NULL((void *)0)) {
442 warn("%s: malloc", name);
443 MUNMAP(symdef, len)do { if (usemmap) munmap(symdef, len); else free(symdef); symdef
= ((void *)0); } while (0)
;
444 return (1);
445 }
446
447 size = *(u_long *)symdef;
448 prn = (struct ranlib *)(symdef + sizeof(u_long));
449 eprn = prn + size / sizeof(*prn);
450 strtab = symdef + sizeof(u_long) + size + sizeof(u_long);
451
452 printf("\nArchive index:\n");
453 for (; prn < eprn; prn++) {
454 if (fseeko(fp, prn->ran_off, SEEK_SET0)) {
455 warn("%s: fseeko", name);
456 rval = 1;
457 break;
458 }
459
460 if (fread(&ar_head, sizeof(ar_head), 1, fp) != 1 ||
461 memcmp(ar_head.ar_fmag, ARFMAG"`\n", sizeof(ar_head.ar_fmag))) {
462 warnx("%s: member fseeko", name);
463 rval = 1;
464 break;
465 }
466
467 *p = '\0';
468 if (mmbr_name(&ar_head, &p, 0, &namelen, fp)) {
469 rval = 1;
470 break;
471 }
472
473 printf("%s in %s\n", strtab + prn->ran_un.ran_strx, p);
474 }
475
476 free(p);
477 MUNMAP(symdef, len)do { if (usemmap) munmap(symdef, len); else free(symdef); symdef
= ((void *)0); } while (0)
;
478 return (rval);
479}
480
481/*
482 * show_archive()
483 * show symbols in the given archive file
484 */
485int
486show_archive(int count, const char *fname, FILE *fp)
487{
488 struct ar_hdr ar_head;
489 union hdr exec_head;
490 int i, rval;
491 off_t last_ar_off, foff, symtaboff;
492 char *name;
493 int baselen, namelen;
494 u_long mmbrlen, symtablen;
495
496 baselen = strlen(fname) + 3;
497 if (posix_output)
498 baselen += 2;
499 namelen = sizeof(ar_head.ar_name);
500 if ((name = malloc(baselen + namelen)) == NULL((void *)0))
501 err(1, NULL((void *)0));
502
503 rval = 0;
504 nametab = NULL((void *)0);
505 symtaboff = 0;
506 symtablen = 0;
507
508 /* while there are more entries in the archive */
509 while (fread(&ar_head, sizeof(ar_head), 1, fp) == 1) {
510 /* bad archive entry - stop processing this archive */
511 if (memcmp(ar_head.ar_fmag, ARFMAG"`\n", sizeof(ar_head.ar_fmag))) {
512 warnx("%s: bad format archive header", fname);
513 rval = 1;
514 break;
515 }
516
517 /* remember start position of current archive object */
518 last_ar_off = ftello(fp);
519 mmbrlen = atol(ar_head.ar_size);
520
521 if (strncmp(ar_head.ar_name, RANLIBMAG"__.SYMDEF",
522 sizeof(RANLIBMAG"__.SYMDEF") - 1) == 0) {
523 if (!issize && armap &&
524 show_symdef(last_ar_off, mmbrlen, fname, fp)) {
525 rval = 1;
526 break;
527 }
528 goto skip;
529 } else if (strncmp(ar_head.ar_name, SYMTABMAG"/ ",
530 sizeof(SYMTABMAG"/ ") - 1) == 0) {
531 /* if nametab hasn't been seen yet -- doit later */
532 if (!nametab) {
533 symtablen = mmbrlen;
534 symtaboff = last_ar_off;
535 goto skip;
536 }
537
538 /* load the Sys5 long names table */
539 } else if (strncmp(ar_head.ar_name, STRTABMAG"//",
540 sizeof(STRTABMAG"//") - 1) == 0) {
541 char *p;
542
543 if ((nametab = malloc(mmbrlen)) == NULL((void *)0)) {
544 warn("%s: nametab", fname);
545 rval = 1;
546 break;
547 }
548
549 if (fread(nametab, mmbrlen, (size_t)1, fp) != 1) {
550 warnx("%s: premature EOF", fname);
551 rval = 1;
552 break;
553 }
554
555 for (p = nametab, i = mmbrlen; i--; p++)
556 if (*p == '\n')
557 *p = '\0';
558
559 if (issize || !armap || !symtablen || !symtaboff)
560 goto skip;
561 }
562#ifdef __mips64
563 else if (memcmp(ar_head.ar_name, SYM64MAG"/SYM64/ ",
564 sizeof(ar_head.ar_name)) == 0) {
565 /* IRIX6-compatible archive map */
566 goto skip;
567 }
568#endif
569
570 if (!issize && armap && symtablen && symtaboff) {
571 if (show_symtab(symtaboff, symtablen, fname, fp)) {
572 rval = 1;
573 break;
574 } else {
575 symtaboff = 0;
576 symtablen = 0;
577 }
578 }
579
580 /*
581 * construct a name of the form "archive.a:obj.o:" for the
582 * current archive entry if the object name is to be printed
583 * on each output line
584 */
585 *name = '\0';
586 if (posix_output)
587 snprintf(name, baselen - 1, "%s[", fname);
588 else if (count > 1)
589 snprintf(name, baselen - 1, "%s:", fname);
590
591 if (mmbr_name(&ar_head, &name, baselen, &namelen, fp)) {
592 rval = 1;
593 break;
594 }
595
596 if (posix_output)
597 strlcat(name, "]", baselen + namelen);
598
599 foff = ftello(fp);
600
601 /* get and check current object's header */
602 if (fread((char *)&exec_head, sizeof(exec_head),
603 (size_t)1, fp) != 1) {
604 warnx("%s: premature EOF", fname);
605 rval = 1;
606 break;
607 }
608
609 rval |= show_file(2, non_object_warning, name, fp, foff, &exec_head);
610 /*
611 * skip to next archive object - it starts at the next
612 * even byte boundary
613 */
614#define even(x)(((x) + 1) & ~1) (((x) + 1) & ~1)
615skip: if (fseeko(fp, last_ar_off + even(mmbrlen)(((mmbrlen) + 1) & ~1), SEEK_SET0)) {
616 warn("%s", fname);
617 rval = 1;
618 break;
619 }
620 }
621 free(nametab);
622 nametab = NULL((void *)0);
623 free(name);
624 return(rval);
625}
626
627char *stab;
628
629/*
630 * show_file()
631 * show symbols from the object file pointed to by fp. The current
632 * file pointer for fp is expected to be at the beginning of an object
633 * file header.
634 */
635int
636show_file(int count, int warn_fmt, const char *name, FILE *fp, off_t foff, union hdr *head)
637{
638 u_long text, data, bss, total;
639 struct xnlist *np, *names, **snames;
28
'names' declared without an initial value
640 int i, nrawnames, nnames;
641 size_t stabsize;
642
643 if (IS_ELF(head->elf32)((head->elf32).e_ident[0] == 0x7f && (head->elf32
).e_ident[1] == 'E' && (head->elf32).e_ident[2] ==
'L' && (head->elf32).e_ident[3] == 'F')
&&
31
Taking true branch
644 head->elf32.e_ident[EI_CLASS4] == ELFCLASS321 &&
29
Assuming the condition is true
645 head->elf32.e_ident[EI_VERSION6] == ELF_TARG_VER1) {
30
Assuming the condition is true
646 void *shdr;
647
648 if (!(shdr = elf32_load_shdrs(name, fp, foff, &head->elf32)))
32
Assuming 'shdr' is non-null
33
Taking false branch
649 return (1);
650
651 i = issize?
34
Assuming 'issize' is not equal to 0
35
'?' condition is true
652 elf32_size(&head->elf32, shdr, &text, &data, &bss) :
653 elf32_symload(name, fp, foff, &head->elf32, shdr,
654 &names, &snames, &stabsize, &nrawnames);
655 free(shdr);
656 if (i)
36
Assuming 'i' is 0
37
Taking false branch
657 return (i);
658
659 } else if (IS_ELF(head->elf64)((head->elf64).e_ident[0] == 0x7f && (head->elf64
).e_ident[1] == 'E' && (head->elf64).e_ident[2] ==
'L' && (head->elf64).e_ident[3] == 'F')
&&
660 head->elf64.e_ident[EI_CLASS4] == ELFCLASS642 &&
661 head->elf64.e_ident[EI_VERSION6] == ELF_TARG_VER1) {
662 void *shdr;
663
664 if (!(shdr = elf64_load_shdrs(name, fp, foff, &head->elf64)))
665 return (1);
666
667 i = issize?
668 elf64_size(&head->elf64, shdr, &text, &data, &bss) :
669 elf64_symload(name, fp, foff, &head->elf64, shdr,
670 &names, &snames, &stabsize, &nrawnames);
671 free(shdr);
672 if (i)
673 return (i);
674 } else {
675 if (warn_fmt)
676 warnx("%s: bad format", name);
677 return (1);
678 }
679
680 if (issize) {
38
Assuming 'issize' is 0
39
Taking false branch
681 static int first = 1;
682
683 if (first) {
684 first = 0;
685 printf("text\tdata\tbss\tdec\thex\n");
686 }
687
688 total = text + data + bss;
689 printf("%lu\t%lu\t%lu\t%lu\t%lx",
690 text, data, bss, total, total);
691 if (count > 1)
692 (void)printf("\t%s", name);
693
694 total_text += text;
695 total_data += data;
696 total_bss += bss;
697 total_total += total;
698
699 printf("\n");
700 return (0);
701 }
702 /* else we are nm */
703
704 /*
705 * it seems that string table is sequential
706 * relative to the symbol table order
707 */
708 if (sfunc == NULL((void *)0) && usemmap)
40
Assuming 'sfunc' is not equal to NULL
709 (void)madvise(stab, stabsize, MADV_SEQUENTIAL2);
710
711 /*
712 * fix up the symbol table and filter out unwanted entries
713 *
714 * common symbols are characterized by a n_type of N_UNDF and a
715 * non-zero n_value -- change n_type to N_COMM for all such
716 * symbols to make life easier later.
717 *
718 * filter out all entries which we don't want to print anyway
719 */
720 for (np = names, i = nnames = 0; i < nrawnames; np++, i++) {
41
Assigned value is garbage or undefined
721 /*
722 * make n_un.n_name a character pointer by adding the string
723 * table's base to n_un.n_strx
724 *
725 * don't mess with zero offsets
726 */
727 if (np->nl.n_un.n_strx)
728 np->nl.n_un.n_name = stab + np->nl.n_un.n_strx;
729 else
730 np->nl.n_un.n_name = "";
731 if (print_only_external_symbols && !IS_EXTERNAL(np->nl.n_type)((np->nl.n_type) & 0x01))
732 continue;
733 if (print_only_undefined_symbols &&
734 SYMBOL_TYPE(np->nl.n_type)((np->nl.n_type) & (0x1e | 0x0e0)) != N_UNDF0x00)
735 continue;
736
737 snames[nnames++] = np;
738 }
739
740 /* sort the symbol table if applicable */
741 if (sfunc)
742 qsort(snames, (size_t)nnames, sizeof(*snames), sfunc);
743
744 if (count > 1)
745 (void)printf("\n%s:\n", name);
746
747 /* print out symbols */
748 for (i = 0; i < nnames; i++)
749 print_symbol(name, snames[i]);
750
751 free(snames);
752 free(names);
753 MUNMAP(stab, stabsize)do { if (usemmap) munmap(stab, stabsize); else free(stab); stab
= ((void *)0); } while (0)
;
754 return(0);
755}
756
757char *
758symname(struct xnlist *sym)
759{
760 return sym->nl.n_un.n_name;
761}
762
763/*
764 * print_symbol()
765 * show one symbol
766 */
767void
768print_symbol(const char *name, struct xnlist *sym)
769{
770 if (print_file_each_line) {
771 if (posix_output)
772 (void)printf("%s: ", name);
773 else
774 (void)printf("%s:", name);
775 }
776
777 if (posix_output) {
778 (void)printf("%s %c ", symname(sym), typeletter(sym));
779 if (SYMBOL_TYPE(sym->nl.n_type)((sym->nl.n_type) & (0x1e | 0x0e0)) != N_UNDF0x00)
780 (void)printf(posix_fmtstr, sym->nl.n_value,
781 sym->n_size);
782 (void)printf("\n");
783 } else {
784 /*
785 * handle undefined-only format especially (no space is
786 * left for symbol values, no type field is printed)
787 */
788 if (!print_only_undefined_symbols) {
789 /* print symbol's value */
790 if (SYMBOL_TYPE(sym->nl.n_type)((sym->nl.n_type) & (0x1e | 0x0e0)) == N_UNDF0x00)
791 (void)printf(" ");
792 else
793 (void)printf("%08lx", sym->nl.n_value);
794
795 /* print type information */
796 if (show_extensions)
797 (void)printf(" %c ", typeletter(sym));
798 else
799 (void)printf(" %c ", typeletter(sym));
800 }
801
802 (void)puts(symname(sym));
803 }
804}
805
806/*
807 * typeletter()
808 * return a description letter for the given basic type code of an
809 * symbol table entry. The return value will be upper case for
810 * external, lower case for internal symbols.
811 */
812char
813typeletter(struct xnlist *np)
814{
815 int ext = IS_EXTERNAL(np->nl.n_type)((np->nl.n_type) & 0x01);
816
817 if (np->nl.n_other)
818 return np->nl.n_other;
819
820 switch(SYMBOL_TYPE(np->nl.n_type)((np->nl.n_type) & (0x1e | 0x0e0))) {
821 case N_ABS0x02:
822 return(ext? 'A' : 'a');
823 case N_BSS0x08:
824 return(ext? 'B' : 'b');
825 case N_COMM0x12:
826 return(ext? 'C' : 'c');
827 case N_DATA0x06:
828 return(ext? 'D' : 'd');
829 case N_FN0x1e:
830 /* NOTE: N_FN == N_WARNING,
831 * in this case, the N_EXT bit is to considered as
832 * part of the symbol's type itself.
833 */
834 return(ext? 'F' : 'W');
835 case N_TEXT0x04:
836 return(ext? 'T' : 't');
837 case N_SIZE0x0c:
838 return(ext? 'S' : 's');
839 case N_UNDF0x00:
840 return(ext? 'U' : 'u');
841 }
842 return('?');
843}
844
845int
846fname(const void *a0, const void *b0)
847{
848 struct xnlist * const *a = a0, * const *b = b0;
849
850 return(strcmp((*a)->nl.n_un.n_name, (*b)->nl.n_un.n_name));
851}
852
853int
854rname(const void *a0, const void *b0)
855{
856 struct xnlist * const *a = a0, * const *b = b0;
857
858 return(strcmp((*b)->nl.n_un.n_name, (*a)->nl.n_un.n_name));
859}
860
861int
862value(const void *a0, const void *b0)
863{
864 struct xnlist * const *a = a0, * const *b = b0;
865
866 if (SYMBOL_TYPE((*a)->nl.n_type)(((*a)->nl.n_type) & (0x1e | 0x0e0)) == N_UNDF0x00)
867 if (SYMBOL_TYPE((*b)->nl.n_type)(((*b)->nl.n_type) & (0x1e | 0x0e0)) == N_UNDF0x00)
868 return(0);
869 else
870 return(-1);
871 else if (SYMBOL_TYPE((*b)->nl.n_type)(((*b)->nl.n_type) & (0x1e | 0x0e0)) == N_UNDF0x00)
872 return(1);
873 if (rev) {
874 if ((*a)->nl.n_value == (*b)->nl.n_value)
875 return(rname(a0, b0));
876 return((*b)->nl.n_value > (*a)->nl.n_value ? 1 : -1);
877 } else {
878 if ((*a)->nl.n_value == (*b)->nl.n_value)
879 return(fname(a0, b0));
880 return((*a)->nl.n_value > (*b)->nl.n_value ? 1 : -1);
881 }
882}
883
884#define CPPFILT"/usr/bin/c++filt" "/usr/bin/c++filt"
885
886void
887pipe2cppfilt(void)
888{
889 int pip[2];
890 char *argv[2];
891
892 argv[0] = "c++filt";
893 argv[1] = NULL((void *)0);
894
895 if (pipe(pip) == -1)
896 err(1, "pipe");
897 switch(fork()) {
898 case -1:
899 err(1, "fork");
900 default:
901 dup2(pip[0], 0);
902 close(pip[0]);
903 close(pip[1]);
904 execve(CPPFILT"/usr/bin/c++filt", argv, NULL((void *)0));
905 err(1, "execve");
906 case 0:
907 dup2(pip[1], 1);
908 close(pip[1]);
909 close(pip[0]);
910 }
911}
912
913void
914usage(void)
915{
916 extern char *__progname;
917
918 if (issize)
919 fprintf(stderr(&__sF[2]), "usage: %s [-tw] [file ...]\n", __progname);
920 else
921 fprintf(stderr(&__sF[2]), "usage: %s [-AaCDegnoPprsuw] [-t d|o|x] [file ...]\n",
922 __progname);
923 exit(1);
924}