Bug Summary

File:src/usr.bin/nm/nm.c
Warning:line 353, column 5
Use of memory after it is freed

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 false
23
Taking true branch
284 if (fread(magic, sizeof(magic), (size_t)1, fp) != 1 ||
24
Assuming the condition is false
26
Taking false branch
285 strncmp(magic, ARMAG"!<arch>\n", SARMAG8)) {
25
Assuming the condition is false
286 warnx("%s: not object file or archive", fname);
287 (void)fclose(fp);
288 return(1);
289 }
290 retval = show_archive(count, fname, fp);
27
Calling 'show_archive'
291 } else
292 retval = show_file(count, 1, fname, fp, 0, &exec_head);
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
44.1
'nametab' is null
&& 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] == '#') &&
45
Assuming the condition is true
48
Taking true branch
330 (arh->ar_name[1] == '1') &&
46
Assuming the condition is true
331 (arh->ar_name[2] == '/') &&
47
Assuming the condition is true
332 (isdigit((unsigned char)arh->ar_name[3]))) {
333 int len = atoi(&arh->ar_name[3]);
334
335 if (len > *namelen) {
49
Assuming the condition is true
50
Taking true branch
336 p -= (long)*name;
337 if ((*name = realloc(*name, baselen+len)) == NULL((void *)0))
51
Memory is released
52
Assuming the condition is false
53
Taking false branch
338 err(1, NULL((void *)0));
339 *namelen = len;
340 p += (long)*name;
341 }
342 if (fread(p, len, 1, fp) != 1) {
54
Assuming the condition is false
55
Taking false branch
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';
56
Use of memory after it is freed
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
27.1
'posix_output' is 0
)
28
Taking false branch
498 baselen += 2;
499 namelen = sizeof(ar_head.ar_name);
500 if ((name = malloc(baselen + namelen)) == NULL((void *)0))
29
Memory is allocated
30
Assuming the condition is false
31
Taking false branch
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) {
32
Assuming the condition is true
33
Loop condition is true. Entering loop body
510 /* bad archive entry - stop processing this archive */
511 if (memcmp(ar_head.ar_fmag, ARFMAG"`\n", sizeof(ar_head.ar_fmag))) {
34
Assuming the condition is false
35
Taking false branch
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",
36
Assuming the condition is false
37
Taking false branch
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"/ ",
38
Assuming the condition is false
39
Taking false branch
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"//",
40
Assuming the condition is false
41
Taking false branch
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
41.1
'issize' is not equal to 0
&& 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
41.2
'posix_output' is 0
)
42
Taking false branch
587 snprintf(name, baselen - 1, "%s[", fname);
588 else if (count
42.1
'count' is <= 1
> 1)
43
Taking false branch
589 snprintf(name, baselen - 1, "%s:", fname);
590
591 if (mmbr_name(&ar_head, &name, baselen, &namelen, fp)) {
44
Calling 'mmbr_name'
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;
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')
&&
644 head->elf32.e_ident[EI_CLASS4] == ELFCLASS321 &&
645 head->elf32.e_ident[EI_VERSION6] == ELF_TARG_VER1) {
646 void *shdr;
647
648 if (!(shdr = elf32_load_shdrs(name, fp, foff, &head->elf32)))
649 return (1);
650
651 i = issize?
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)
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) {
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)
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++) {
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}