Bug Summary

File:src/usr.bin/nm/nm.c
Warning:line 687, column 16
The left operand of '+' is a garbage value

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 true
22
Assuming the condition is true
23
Assuming the condition is true
24
Assuming the condition is true
25
Taking false branch
283 if (fread(magic, sizeof(magic), (size_t)1, fp) != 1 ||
284 strncmp(magic, ARMAG"!<arch>\n", SARMAG8)) {
285 warnx("%s: not object file or archive", fname);
286 (void)fclose(fp);
287 return(1);
288 }
289 retval = show_archive(count, fname, fp);
290 } else
291 retval = show_file(count, 1, fname, fp, 0, &exec_head);
26
Calling 'show_file'
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] == '/') {
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] == '#') &&
329 (arh->ar_name[1] == '1') &&
330 (arh->ar_name[2] == '/') &&
331 (isdigit((unsigned char)arh->ar_name[3]))) {
332 int len = atoi(&arh->ar_name[3]);
333
334 if (len > *namelen) {
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) {
342 warnx("%s: premature EOF", *name);
343 free(*name);
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)
;
434 if (symdef == MAP_FAILED((void *)-1))
435 return (1);
436 if (usemmap)
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)) {
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++) {
453 if (fseeko(fp, prn->ran_off, SEEK_SET0)) {
454 warn("%s: fseeko", name);
455 rval = 1;
456 break;
457 }
458
459 if (fread(&ar_head, sizeof(ar_head), 1, fp) != 1 ||
460 memcmp(ar_head.ar_fmag, ARFMAG"`\n", sizeof(ar_head.ar_fmag))) {
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)) {
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);
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)
497 baselen += 2;
498 namelen = sizeof(ar_head.ar_name);
499 if ((name = malloc(baselen + namelen)) == NULL((void *)0))
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) {
509 /* bad archive entry - stop processing this archive */
510 if (memcmp(ar_head.ar_fmag, ARFMAG"`\n", sizeof(ar_head.ar_fmag))) {
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",
521 sizeof(RANLIBMAG"__.SYMDEF") - 1) == 0) {
522 if (!issize && armap &&
523 show_symdef(last_ar_off, mmbrlen, fname, fp)) {
524 rval = 1;
525 break;
526 }
527 goto skip;
528 } else if (strncmp(ar_head.ar_name, SYMTABMAG"/ ",
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"//",
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 && 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)
586 snprintf(name, baselen - 1, "%s[", fname);
587 else if (count > 1)
588 snprintf(name, baselen - 1, "%s:", fname);
589
590 if (mmbr_name(&ar_head, &name, baselen, &namelen, fp)) {
591 rval = 1;
592 break;
593 }
594
595 if (posix_output)
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),
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)) {
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;
27
'text' declared without an initial value
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')
&&
30
Taking true branch
643 head->elf32.e_ident[EI_CLASS4] == ELFCLASS321 &&
28
Assuming the condition is true
644 head->elf32.e_ident[EI_VERSION6] == ELF_TARG_VER1) {
29
Assuming the condition is true
645 void *shdr;
646
647 if (!(shdr = elf32_load_shdrs(name, fp, foff, &head->elf32)))
31
Assuming 'shdr' is non-null
648 return (1);
649
650 i = issize?
32
Taking false branch
33
Assuming 'issize' is 0
34
'?' condition is false
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)
35
Assuming 'i' is 0
36
Taking false branch
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) {
37
Assuming 'issize' is not equal to 0
38
Taking true branch
680 static int first = 1;
681
682 if (first
38.1
'first' is 1
) {
39
Taking true branch
683 first = 0;
684 printf("text\tdata\tbss\tdec\thex\n");
685 }
686
687 total = text + data + bss;
40
The left operand of '+' is a garbage value
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}