Bug Summary

File:src/usr.bin/nm/nm.c
Warning:line 475, column 2
Attempt to free released memory

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name nm.c -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 -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -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/llvm16/lib/clang/16 -I /usr/src/usr.bin/nm -internal-isystem /usr/local/llvm16/lib/clang/16/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 -fcf-protection=branch -fno-jump-tables -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/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.bin/nm/nm.c
1/* $OpenBSD: nm.c,v 1.55 2022/12/04 23:50:49 cheloha 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 214
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 default:
210 usage();
211 }
212 }
213
214 if (posix_output)
7
Assuming 'posix_output' is 0
8
Taking false branch
215 (void)snprintf(posix_fmtstr, sizeof posix_fmtstr, "%%%c %%%c",
216 posix_radix, posix_radix);
217 if (demangle)
9
Assuming 'demangle' is 0
10
Taking false branch
218 pipe2cppfilt();
219
220 if (pledge("stdio rpath", NULL((void *)0)) == -1)
11
Assuming the condition is false
12
Taking false branch
221 err(1, "pledge");
222
223 argv += optind;
224 argc -= optind;
225
226 if (rev && sfunc == fname)
13
Assuming 'rev' is 0
227 sfunc = rname;
228
229 eval = 0;
230 if (*argv)
14
Assuming the condition is false
15
Taking false branch
231 do {
232 eval |= process_file(argc, *argv);
233 } while (*++argv);
234 else
235 eval |= process_file(1, "a.out");
16
Calling 'process_file'
236
237 if (issize && print_totals)
238 printf("\n%lu\t%lu\t%lu\t%lu\t%lx\tTOTAL\n",
239 total_text, total_data, total_bss,
240 total_total, total_total);
241 exit(eval);
242}
243
244/*
245 * process_file()
246 * show symbols in the file given as an argument. Accepts archive and
247 * object files as input.
248 */
249int
250process_file(int count, const char *fname)
251{
252 union hdr exec_head;
253 FILE *fp;
254 int retval;
255 size_t bytes;
256 char magic[SARMAG8];
257
258 if (!(fp = fopen(fname, "r"))) {
17
Assuming 'fp' is non-null
259 warn("cannot read %s", fname);
260 return(1);
261 }
262
263 if (!issize && count > 1)
18
Assuming 'issize' is not equal to 0
264 (void)printf("\n%s:\n", fname);
265
266 /*
267 * first check whether this is an object file - read a object
268 * header, and skip back to the beginning
269 */
270 bzero(&exec_head, sizeof(exec_head));
271 bytes = fread((char *)&exec_head, 1, sizeof(exec_head), fp);
272 if (bytes < sizeof(exec_head)) {
19
Assuming the condition is false
20
Taking false branch
273 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')
) {
274 warnx("%s: bad format", fname);
275 (void)fclose(fp);
276 return(1);
277 }
278 }
279 rewind(fp);
280
281 /* this could be an archive */
282 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')
) {
21
Assuming the condition is false
283 if (fread(magic, sizeof(magic), (size_t)1, fp) != 1 ||
22
Assuming the condition is false
24
Taking false branch
284 strncmp(magic, ARMAG"!<arch>\n", SARMAG8)) {
23
Assuming the condition is false
285 warnx("%s: not object file or archive", fname);
286 (void)fclose(fp);
287 return(1);
288 }
289 retval = show_archive(count, fname, fp);
25
Calling 'show_archive'
290 } else
291 retval = show_file(count, 1, fname, fp, 0, &exec_head);
292 (void)fclose(fp);
293 return(retval);
294}
295
296char *nametab;
297
298/*
299 *
300 * given the archive member header -- produce member name
301 */
302int
303mmbr_name(struct ar_hdr *arh, char **name, int baselen, int *namelen, FILE *fp)
304{
305 char *p = *name + strlen(*name);
306 long i;
307
308 if (nametab && arh->ar_name[0] == '/') {
70
Assuming 'nametab' is null
309 int len;
310
311 i = atol(&arh->ar_name[1]);
312 len = strlen(&nametab[i]) + 1;
313 if (len > *namelen) {
314 p -= (long)*name;
315 if ((*name = realloc(*name, baselen+len)) == NULL((void *)0))
316 err(1, NULL((void *)0));
317 *namelen = len;
318 p += (long)*name;
319 }
320 strlcpy(p, &nametab[i], len);
321 p += len - 1;
322 } else
323#ifdef AR_EFMT1"#1/"
324 /*
325 * BSD 4.4 extended AR format: #1/<namelen>, with name as the
326 * first <namelen> bytes of the file
327 */
328 if ((arh->ar_name[0] == '#') &&
71
Assuming the condition is true
75
Taking true branch
329 (arh->ar_name[1] == '1') &&
72
Assuming the condition is true
330 (arh->ar_name[2] == '/') &&
73
Assuming the condition is true
331 (isdigit((unsigned char)arh->ar_name[3]))) {
74
Assuming the character is a digit
332 int len = atoi(&arh->ar_name[3]);
333
334 if (len > *namelen) {
76
Assuming the condition is false
77
Taking false branch
335 p -= (long)*name;
336 if ((*name = realloc(*name, baselen+len)) == NULL((void *)0))
337 err(1, NULL((void *)0));
338 *namelen = len;
339 p += (long)*name;
340 }
341 if (fread(p, len, 1, fp) != 1) {
78
Assuming the condition is true
79
Taking true branch
342 warnx("%s: premature EOF", *name);
343 free(*name);
80
Memory is released
344 return(1);
345 }
346 p += len;
347 } else
348#endif
349 for (i = 0; i < sizeof(arh->ar_name); ++i)
350 if (arh->ar_name[i] && arh->ar_name[i] != ' ')
351 *p++ = arh->ar_name[i];
352 *p = '\0';
353 if (p[-1] == '/')
354 *--p = '\0';
355
356 return (0);
357}
358
359/*
360 * show_symtab()
361 * show archive ranlib index (fs5)
362 */
363int
364show_symtab(off_t off, u_long len, const char *name, FILE *fp)
365{
366 struct ar_hdr ar_head;
367 int *symtab, *ps;
368 char *strtab, *p;
369 int num, rval = 0;
370 int namelen;
371 off_t restore;
372
373 restore = ftello(fp);
374
375 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)
;
376 if (symtab == MAP_FAILED((void *)-1))
377 return (1);
378
379 namelen = sizeof(ar_head.ar_name);
380 if ((p = malloc(sizeof(ar_head.ar_name))) == NULL((void *)0)) {
381 warn("%s: malloc", name);
382 MUNMAP(symtab, len)do { if (usemmap) munmap(symtab, len); else free(symtab); symtab
= ((void *)0); } while (0)
;
383 return (1);
384 }
385
386 printf("\nArchive index:\n");
387 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))
;
388 strtab = (char *)(symtab + num + 1);
389 for (ps = symtab + 1; num--; ps++, strtab += strlen(strtab) + 1) {
390 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)) {
391 warn("%s: fseeko", name);
392 rval = 1;
393 break;
394 }
395
396 if (fread(&ar_head, sizeof(ar_head), 1, fp) != 1 ||
397 memcmp(ar_head.ar_fmag, ARFMAG"`\n", sizeof(ar_head.ar_fmag))) {
398 warnx("%s: member fseeko", name);
399 rval = 1;
400 break;
401 }
402
403 *p = '\0';
404 if (mmbr_name(&ar_head, &p, 0, &namelen, fp)) {
405 rval = 1;
406 break;
407 }
408
409 printf("%s in %s\n", strtab, p);
410 }
411
412 fseeko(fp, restore, SEEK_SET0);
413
414 free(p);
415 MUNMAP(symtab, len)do { if (usemmap) munmap(symtab, len); else free(symtab); symtab
= ((void *)0); } while (0)
;
416 return (rval);
417}
418
419/*
420 * show_symdef()
421 * show archive ranlib index (gob)
422 */
423int
424show_symdef(off_t off, u_long len, const char *name, FILE *fp)
425{
426 struct ranlib *prn, *eprn;
427 struct ar_hdr ar_head;
428 char *symdef;
429 char *strtab, *p;
430 u_long size;
431 int namelen, rval = 0;
432
433 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)
;
53
Assuming '__isthreaded' is 0
54
'?' condition is true
55
Assuming the condition is false
56
Taking false branch
57
Loop condition is false. Exiting loop
434 if (symdef == MAP_FAILED((void *)-1))
58
Taking false branch
435 return (1);
436 if (usemmap
58.1
'usemmap' is 0
)
59
Taking false branch
437 (void)madvise(symdef, len, MADV_SEQUENTIAL2);
438
439 namelen = sizeof(ar_head.ar_name);
440 if ((p = malloc(sizeof(ar_head.ar_name))) == NULL((void *)0)) {
60
Memory is allocated
61
Assuming the condition is false
62
Taking false branch
441 warn("%s: malloc", name);
442 MUNMAP(symdef, len)do { if (usemmap) munmap(symdef, len); else free(symdef); symdef
= ((void *)0); } while (0)
;
443 return (1);
444 }
445
446 size = *(u_long *)symdef;
447 prn = (struct ranlib *)(symdef + sizeof(u_long));
448 eprn = prn + size / sizeof(*prn);
449 strtab = symdef + sizeof(u_long) + size + sizeof(u_long);
450
451 printf("\nArchive index:\n");
452 for (; prn < eprn; prn++) {
63
Assuming 'prn' is < 'eprn'
64
Loop condition is true. Entering loop body
453 if (fseeko(fp, prn->ran_off, SEEK_SET0)) {
65
Assuming the condition is false
454 warn("%s: fseeko", name);
455 rval = 1;
456 break;
457 }
458
459 if (fread(&ar_head, sizeof(ar_head), 1, fp) != 1 ||
66
Assuming the condition is false
68
Taking false branch
460 memcmp(ar_head.ar_fmag, ARFMAG"`\n", sizeof(ar_head.ar_fmag))) {
67
Assuming the condition is false
461 warnx("%s: member fseeko", name);
462 rval = 1;
463 break;
464 }
465
466 *p = '\0';
467 if (mmbr_name(&ar_head, &p, 0, &namelen, fp)) {
69
Calling 'mmbr_name'
81
Returning; memory was released via 2nd parameter
82
Taking true branch
468 rval = 1;
469 break;
470 }
471
472 printf("%s in %s\n", strtab + prn->ran_un.ran_strx, p);
473 }
474
475 free(p);
83
Attempt to free released memory
476 MUNMAP(symdef, len)do { if (usemmap) munmap(symdef, len); else free(symdef); symdef
= ((void *)0); } while (0)
;
477 return (rval);
478}
479
480/*
481 * show_archive()
482 * show symbols in the given archive file
483 */
484int
485show_archive(int count, const char *fname, FILE *fp)
486{
487 struct ar_hdr ar_head;
488 union hdr exec_head;
489 int i, rval;
490 off_t last_ar_off, foff, symtaboff;
491 char *name;
492 int baselen, namelen;
493 u_long mmbrlen, symtablen;
494
495 baselen = strlen(fname) + 3;
496 if (posix_output
25.1
'posix_output' is 0
)
26
Taking false branch
497 baselen += 2;
498 namelen = sizeof(ar_head.ar_name);
499 if ((name = malloc(baselen + namelen)) == NULL((void *)0))
27
Assuming the condition is false
28
Taking false branch
500 err(1, NULL((void *)0));
501
502 rval = 0;
503 nametab = NULL((void *)0);
504 symtaboff = 0;
505 symtablen = 0;
506
507 /* while there are more entries in the archive */
508 while (fread(&ar_head, sizeof(ar_head), 1, fp) == 1) {
29
Assuming the condition is true
30
Loop condition is true. Entering loop body
46
Assuming the condition is true
47
Loop condition is true. Entering loop body
509 /* bad archive entry - stop processing this archive */
510 if (memcmp(ar_head.ar_fmag, ARFMAG"`\n", sizeof(ar_head.ar_fmag))) {
31
Assuming the condition is false
32
Taking false branch
48
Assuming the condition is false
49
Taking false branch
511 warnx("%s: bad format archive header", fname);
512 rval = 1;
513 break;
514 }
515
516 /* remember start position of current archive object */
517 last_ar_off = ftello(fp);
518 mmbrlen = atol(ar_head.ar_size);
519
520 if (strncmp(ar_head.ar_name, RANLIBMAG"__.SYMDEF",
33
Assuming the condition is false
34
Taking false branch
50
Assuming the condition is true
521 sizeof(RANLIBMAG"__.SYMDEF") - 1) == 0) {
522 if (!issize
50.1
'issize' is 0
&& armap &&
51
Assuming 'armap' is not equal to 0
523 show_symdef(last_ar_off, mmbrlen, fname, fp)) {
52
Calling 'show_symdef'
524 rval = 1;
525 break;
526 }
527 goto skip;
528 } else if (strncmp(ar_head.ar_name, SYMTABMAG"/ ",
35
Assuming the condition is false
36
Taking false branch
529 sizeof(SYMTABMAG"/ ") - 1) == 0) {
530 /* if nametab hasn't been seen yet -- doit later */
531 if (!nametab) {
532 symtablen = mmbrlen;
533 symtaboff = last_ar_off;
534 goto skip;
535 }
536
537 /* load the Sys5 long names table */
538 } else if (strncmp(ar_head.ar_name, STRTABMAG"//",
37
Assuming the condition is false
539 sizeof(STRTABMAG"//") - 1) == 0) {
540 char *p;
541
542 if ((nametab = malloc(mmbrlen)) == NULL((void *)0)) {
543 warn("%s: nametab", fname);
544 rval = 1;
545 break;
546 }
547
548 if (fread(nametab, mmbrlen, (size_t)1, fp) != 1) {
549 warnx("%s: premature EOF", fname);
550 rval = 1;
551 break;
552 }
553
554 for (p = nametab, i = mmbrlen; i--; p++)
555 if (*p == '\n')
556 *p = '\0';
557
558 if (issize || !armap || !symtablen || !symtaboff)
559 goto skip;
560 }
561#ifdef __mips64
562 else if (memcmp(ar_head.ar_name, SYM64MAG"/SYM64/ ",
563 sizeof(ar_head.ar_name)) == 0) {
564 /* IRIX6-compatible archive map */
565 goto skip;
566 }
567#endif
568
569 if (!issize
37.1
'issize' is not equal to 0
&& armap && symtablen && symtaboff) {
570 if (show_symtab(symtaboff, symtablen, fname, fp)) {
571 rval = 1;
572 break;
573 } else {
574 symtaboff = 0;
575 symtablen = 0;
576 }
577 }
578
579 /*
580 * construct a name of the form "archive.a:obj.o:" for the
581 * current archive entry if the object name is to be printed
582 * on each output line
583 */
584 *name = '\0';
585 if (posix_output
37.2
'posix_output' is 0
)
38
Taking false branch
586 snprintf(name, baselen - 1, "%s[", fname);
587 else if (count
38.1
'count' is <= 1
> 1)
39
Taking false branch
588 snprintf(name, baselen - 1, "%s:", fname);
589
590 if (mmbr_name(&ar_head, &name, baselen, &namelen, fp)) {
40
Taking false branch
591 rval = 1;
592 break;
593 }
594
595 if (posix_output
40.1
'posix_output' is 0
)
41
Taking false branch
596 strlcat(name, "]", baselen + namelen);
597
598 foff = ftello(fp);
599
600 /* get and check current object's header */
601 if (fread((char *)&exec_head, sizeof(exec_head),
42
Assuming the condition is false
43
Taking false branch
602 (size_t)1, fp) != 1) {
603 warnx("%s: premature EOF", fname);
604 rval = 1;
605 break;
606 }
607
608 rval |= show_file(2, non_object_warning, name, fp, foff, &exec_head);
609 /*
610 * skip to next archive object - it starts at the next
611 * even byte boundary
612 */
613#define even(x)(((x) + 1) & ~1) (((x) + 1) & ~1)
614skip: if (fseeko(fp, last_ar_off + even(mmbrlen)(((mmbrlen) + 1) & ~1), SEEK_SET0)) {
44
Assuming the condition is false
45
Taking false branch
615 warn("%s", fname);
616 rval = 1;
617 break;
618 }
619 }
620 free(nametab);
621 nametab = NULL((void *)0);
622 free(name);
623 return(rval);
624}
625
626char *stab;
627
628/*
629 * show_file()
630 * show symbols from the object file pointed to by fp. The current
631 * file pointer for fp is expected to be at the beginning of an object
632 * file header.
633 */
634int
635show_file(int count, int warn_fmt, const char *name, FILE *fp, off_t foff, union hdr *head)
636{
637 u_long text, data, bss, total;
638 struct xnlist *np, *names, **snames;
639 int i, nrawnames, nnames;
640 size_t stabsize;
641
642 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')
&&
643 head->elf32.e_ident[EI_CLASS4] == ELFCLASS321 &&
644 head->elf32.e_ident[EI_VERSION6] == ELF_TARG_VER1) {
645 void *shdr;
646
647 if (!(shdr = elf32_load_shdrs(name, fp, foff, &head->elf32)))
648 return (1);
649
650 i = issize?
651 elf32_size(&head->elf32, shdr, &text, &data, &bss) :
652 elf32_symload(name, fp, foff, &head->elf32, shdr,
653 &names, &snames, &stabsize, &nrawnames);
654 free(shdr);
655 if (i)
656 return (i);
657
658 } 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')
&&
659 head->elf64.e_ident[EI_CLASS4] == ELFCLASS642 &&
660 head->elf64.e_ident[EI_VERSION6] == ELF_TARG_VER1) {
661 void *shdr;
662
663 if (!(shdr = elf64_load_shdrs(name, fp, foff, &head->elf64)))
664 return (1);
665
666 i = issize?
667 elf64_size(&head->elf64, shdr, &text, &data, &bss) :
668 elf64_symload(name, fp, foff, &head->elf64, shdr,
669 &names, &snames, &stabsize, &nrawnames);
670 free(shdr);
671 if (i)
672 return (i);
673 } else {
674 if (warn_fmt)
675 warnx("%s: bad format", name);
676 return (1);
677 }
678
679 if (issize) {
680 static int first = 1;
681
682 if (first) {
683 first = 0;
684 printf("text\tdata\tbss\tdec\thex\n");
685 }
686
687 total = text + data + bss;
688 printf("%lu\t%lu\t%lu\t%lu\t%lx",
689 text, data, bss, total, total);
690 if (count > 1)
691 (void)printf("\t%s", name);
692
693 total_text += text;
694 total_data += data;
695 total_bss += bss;
696 total_total += total;
697
698 printf("\n");
699 return (0);
700 }
701 /* else we are nm */
702
703 /*
704 * it seems that string table is sequential
705 * relative to the symbol table order
706 */
707 if (sfunc == NULL((void *)0) && usemmap)
708 (void)madvise(stab, stabsize, MADV_SEQUENTIAL2);
709
710 /*
711 * fix up the symbol table and filter out unwanted entries
712 *
713 * common symbols are characterized by a n_type of N_UNDF and a
714 * non-zero n_value -- change n_type to N_COMM for all such
715 * symbols to make life easier later.
716 *
717 * filter out all entries which we don't want to print anyway
718 */
719 for (np = names, i = nnames = 0; i < nrawnames; np++, i++) {
720 /*
721 * make n_un.n_name a character pointer by adding the string
722 * table's base to n_un.n_strx
723 *
724 * don't mess with zero offsets
725 */
726 if (np->nl.n_un.n_strx)
727 np->nl.n_un.n_name = stab + np->nl.n_un.n_strx;
728 else
729 np->nl.n_un.n_name = "";
730 if (print_only_external_symbols && !IS_EXTERNAL(np->nl.n_type)((np->nl.n_type) & 0x01))
731 continue;
732 if (print_only_undefined_symbols &&
733 SYMBOL_TYPE(np->nl.n_type)((np->nl.n_type) & (0x1e | 0x0e0)) != N_UNDF0x00)
734 continue;
735
736 snames[nnames++] = np;
737 }
738
739 /* sort the symbol table if applicable */
740 if (sfunc)
741 qsort(snames, (size_t)nnames, sizeof(*snames), sfunc);
742
743 if (count > 1)
744 (void)printf("\n%s:\n", name);
745
746 /* print out symbols */
747 for (i = 0; i < nnames; i++)
748 print_symbol(name, snames[i]);
749
750 free(snames);
751 free(names);
752 MUNMAP(stab, stabsize)do { if (usemmap) munmap(stab, stabsize); else free(stab); stab
= ((void *)0); } while (0)
;
753 return(0);
754}
755
756char *
757symname(struct xnlist *sym)
758{
759 return sym->nl.n_un.n_name;
760}
761
762/*
763 * print_symbol()
764 * show one symbol
765 */
766void
767print_symbol(const char *name, struct xnlist *sym)
768{
769 if (print_file_each_line) {
770 if (posix_output)
771 (void)printf("%s: ", name);
772 else
773 (void)printf("%s:", name);
774 }
775
776 if (posix_output) {
777 (void)printf("%s %c ", symname(sym), typeletter(sym));
778 if (SYMBOL_TYPE(sym->nl.n_type)((sym->nl.n_type) & (0x1e | 0x0e0)) != N_UNDF0x00)
779 (void)printf(posix_fmtstr, sym->nl.n_value,
780 sym->n_size);
781 (void)printf("\n");
782 } else {
783 /*
784 * handle undefined-only format especially (no space is
785 * left for symbol values, no type field is printed)
786 */
787 if (!print_only_undefined_symbols) {
788 /* print symbol's value */
789 if (SYMBOL_TYPE(sym->nl.n_type)((sym->nl.n_type) & (0x1e | 0x0e0)) == N_UNDF0x00)
790 (void)printf(" ");
791 else
792 (void)printf("%08lx", sym->nl.n_value);
793
794 /* print type information */
795 if (show_extensions)
796 (void)printf(" %c ", typeletter(sym));
797 else
798 (void)printf(" %c ", typeletter(sym));
799 }
800
801 (void)puts(symname(sym));
802 }
803}
804
805/*
806 * typeletter()
807 * return a description letter for the given basic type code of an
808 * symbol table entry. The return value will be upper case for
809 * external, lower case for internal symbols.
810 */
811char
812typeletter(struct xnlist *np)
813{
814 int ext = IS_EXTERNAL(np->nl.n_type)((np->nl.n_type) & 0x01);
815
816 if (np->nl.n_other)
817 return np->nl.n_other;
818
819 switch(SYMBOL_TYPE(np->nl.n_type)((np->nl.n_type) & (0x1e | 0x0e0))) {
820 case N_ABS0x02:
821 return(ext? 'A' : 'a');
822 case N_BSS0x08:
823 return(ext? 'B' : 'b');
824 case N_COMM0x12:
825 return(ext? 'C' : 'c');
826 case N_DATA0x06:
827 return(ext? 'D' : 'd');
828 case N_FN0x1e:
829 /* NOTE: N_FN == N_WARNING,
830 * in this case, the N_EXT bit is to considered as
831 * part of the symbol's type itself.
832 */
833 return(ext? 'F' : 'W');
834 case N_TEXT0x04:
835 return(ext? 'T' : 't');
836 case N_SIZE0x0c:
837 return(ext? 'S' : 's');
838 case N_UNDF0x00:
839 return(ext? 'U' : 'u');
840 }
841 return('?');
842}
843
844int
845fname(const void *a0, const void *b0)
846{
847 struct xnlist * const *a = a0, * const *b = b0;
848
849 return(strcmp((*a)->nl.n_un.n_name, (*b)->nl.n_un.n_name));
850}
851
852int
853rname(const void *a0, const void *b0)
854{
855 struct xnlist * const *a = a0, * const *b = b0;
856
857 return(strcmp((*b)->nl.n_un.n_name, (*a)->nl.n_un.n_name));
858}
859
860int
861value(const void *a0, const void *b0)
862{
863 struct xnlist * const *a = a0, * const *b = b0;
864
865 if (SYMBOL_TYPE((*a)->nl.n_type)(((*a)->nl.n_type) & (0x1e | 0x0e0)) == N_UNDF0x00)
866 if (SYMBOL_TYPE((*b)->nl.n_type)(((*b)->nl.n_type) & (0x1e | 0x0e0)) == N_UNDF0x00)
867 return(0);
868 else
869 return(-1);
870 else if (SYMBOL_TYPE((*b)->nl.n_type)(((*b)->nl.n_type) & (0x1e | 0x0e0)) == N_UNDF0x00)
871 return(1);
872 if (rev) {
873 if ((*a)->nl.n_value == (*b)->nl.n_value)
874 return(rname(a0, b0));
875 return((*b)->nl.n_value > (*a)->nl.n_value ? 1 : -1);
876 } else {
877 if ((*a)->nl.n_value == (*b)->nl.n_value)
878 return(fname(a0, b0));
879 return((*a)->nl.n_value > (*b)->nl.n_value ? 1 : -1);
880 }
881}
882
883#define CPPFILT"/usr/bin/c++filt" "/usr/bin/c++filt"
884
885void
886pipe2cppfilt(void)
887{
888 int pip[2];
889 char *argv[2];
890
891 argv[0] = "c++filt";
892 argv[1] = NULL((void *)0);
893
894 if (pipe(pip) == -1)
895 err(1, "pipe");
896 switch(fork()) {
897 case -1:
898 err(1, "fork");
899 default:
900 dup2(pip[0], 0);
901 close(pip[0]);
902 close(pip[1]);
903 execve(CPPFILT"/usr/bin/c++filt", argv, NULL((void *)0));
904 err(1, "execve");
905 case 0:
906 dup2(pip[1], 1);
907 close(pip[1]);
908 close(pip[0]);
909 }
910}
911
912void
913usage(void)
914{
915 extern char *__progname;
916
917 if (issize)
918 fprintf(stderr(&__sF[2]), "usage: %s [-tw] [file ...]\n", __progname);
919 else
920 fprintf(stderr(&__sF[2]), "usage: %s [-AaCDegnoPprsuw] [-t d|o|x] [file ...]\n",
921 __progname);
922 exit(1);
923}