Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/elftoolchain/nm/nm.c
39478 views
1
/*-
2
* Copyright (c) 2007 Hyogeol Lee <[email protected]>
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer
10
* in this position and unchanged.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
*/
26
27
#include <sys/queue.h>
28
#include <sys/types.h>
29
#include <sys/stat.h>
30
#include <ar.h>
31
#include <assert.h>
32
#include <capsicum_helpers.h>
33
#include <ctype.h>
34
#include <dwarf.h>
35
#include <err.h>
36
#include <errno.h>
37
#include <fcntl.h>
38
#include <gelf.h>
39
#include <getopt.h>
40
#include <inttypes.h>
41
#include <libdwarf.h>
42
#include <libelftc.h>
43
#include <stdbool.h>
44
#include <stdio.h>
45
#include <stdlib.h>
46
#include <string.h>
47
#include <strings.h>
48
#include <unistd.h>
49
50
#include <libcasper.h>
51
#include <casper/cap_fileargs.h>
52
53
#include "_elftc.h"
54
55
ELFTC_VCSID("$Id: nm.c 3722 2019-03-23 17:01:58Z jkoshy $");
56
57
/* symbol information list */
58
STAILQ_HEAD(sym_head, sym_entry);
59
60
struct sym_entry {
61
char *name;
62
GElf_Sym *sym;
63
STAILQ_ENTRY(sym_entry) sym_entries;
64
};
65
66
typedef int (*fn_sort)(const void *, const void *);
67
typedef void (*fn_elem_print)(char, const char *, const GElf_Sym *, const char *);
68
typedef void (*fn_sym_print)(const GElf_Sym *);
69
typedef int (*fn_filter)(char, const GElf_Sym *, const char *);
70
71
/* output filter list */
72
static SLIST_HEAD(filter_head, filter_entry) nm_out_filter =
73
SLIST_HEAD_INITIALIZER(nm_out_filter);
74
75
struct filter_entry {
76
fn_filter fn;
77
SLIST_ENTRY(filter_entry) filter_entries;
78
};
79
80
struct sym_print_data {
81
struct sym_head *headp;
82
size_t sh_num, list_num;
83
const char *t_table, **s_table, *filename, *objname;
84
};
85
86
struct nm_prog_info {
87
const char *name;
88
const char *def_filename;
89
};
90
91
/* List for line number information. */
92
struct line_info_entry {
93
uint64_t addr; /* address */
94
uint64_t line; /* line number */
95
char *file; /* file name with path */
96
SLIST_ENTRY(line_info_entry) entries;
97
};
98
SLIST_HEAD(line_info_head, line_info_entry);
99
100
/* List for function line number information. */
101
struct func_info_entry {
102
char *name; /* function name */
103
char *file; /* file name with path */
104
uint64_t lowpc; /* low address */
105
uint64_t highpc; /* high address */
106
uint64_t line; /* line number */
107
SLIST_ENTRY(func_info_entry) entries;
108
};
109
SLIST_HEAD(func_info_head, func_info_entry);
110
111
/* List for variable line number information. */
112
struct var_info_entry {
113
char *name; /* variable name */
114
char *file; /* file name with path */
115
uint64_t addr; /* address */
116
uint64_t line; /* line number */
117
SLIST_ENTRY(var_info_entry) entries;
118
};
119
SLIST_HEAD(var_info_head, var_info_entry);
120
121
/* output numric type */
122
enum radix {
123
RADIX_OCT,
124
RADIX_HEX,
125
RADIX_DEC
126
};
127
128
/* output symbol type, PRINT_SYM_DYN for dynamic symbol only */
129
enum print_symbol {
130
PRINT_SYM_SYM,
131
PRINT_SYM_DYN
132
};
133
134
/* output name type */
135
enum print_name {
136
PRINT_NAME_NONE,
137
PRINT_NAME_FULL,
138
PRINT_NAME_MULTI
139
};
140
141
struct nm_prog_options {
142
enum print_symbol print_symbol;
143
enum print_name print_name;
144
enum radix t;
145
int demangle_type;
146
bool print_debug;
147
bool print_armap;
148
int print_size;
149
bool debug_line;
150
int def_only;
151
bool undef_only;
152
int sort_size;
153
bool sort_reverse;
154
int no_demangle;
155
156
/*
157
* function pointer to sort symbol list.
158
* possible function - cmp_name, cmp_none, cmp_size, cmp_value
159
*/
160
fn_sort sort_fn;
161
162
/*
163
* function pointer to print symbol elem.
164
* possible function - sym_elem_print_all
165
* sym_elem_print_all_portable
166
* sym_elem_print_all_sysv
167
*/
168
fn_elem_print elem_print_fn;
169
170
fn_sym_print value_print_fn;
171
fn_sym_print size_print_fn;
172
173
fileargs_t *fileargs;
174
};
175
176
#define CHECK_SYM_PRINT_DATA(p) (p->headp == NULL || p->sh_num == 0 || \
177
p->t_table == NULL || p->s_table == NULL || p->filename == NULL)
178
#define IS_SYM_TYPE(t) ((t) == '?' || isalpha((t)) != 0)
179
#define IS_UNDEF_SYM_TYPE(t) ((t) == 'U' || (t) == 'v' || (t) == 'w')
180
#define UNUSED(p) ((void)p)
181
182
static int cmp_name(const void *, const void *);
183
static int cmp_none(const void *, const void *);
184
static int cmp_size(const void *, const void *);
185
static int cmp_value(const void *, const void *);
186
static void enter_cap_mode(int, char **);
187
static void filter_dest(void);
188
static int filter_insert(fn_filter);
189
static void get_opt(int *, char ***);
190
static int get_sym(Elf *, struct sym_head *, int, size_t, size_t,
191
const char *, const char **, int);
192
static const char * get_sym_name(Elf *, const GElf_Sym *, size_t,
193
const char **, int);
194
static char get_sym_type(const GElf_Sym *, const char *);
195
static void global_dest(void);
196
static void global_init(void);
197
static bool is_sec_data(GElf_Shdr *);
198
static bool is_sec_debug(const char *);
199
static bool is_sec_nobits(GElf_Shdr *);
200
static bool is_sec_readonly(GElf_Shdr *);
201
static bool is_sec_text(GElf_Shdr *);
202
static void print_ar_index(int, Elf *);
203
static void print_header(const char *, const char *);
204
static void print_version(void);
205
static int read_elf(Elf *, const char *, Elf_Kind);
206
static int read_object(const char *);
207
static int read_files(int, char **);
208
static void set_opt_value_print_fn(enum radix);
209
static int sym_elem_def(char, const GElf_Sym *, const char *);
210
static int sym_elem_global(char, const GElf_Sym *, const char *);
211
static int sym_elem_global_static(char, const GElf_Sym *,
212
const char *);
213
static int sym_elem_nondebug(char, const GElf_Sym *, const char *);
214
static int sym_elem_nonzero_size(char, const GElf_Sym *,
215
const char *);
216
static void sym_elem_print_all(char, const char *,
217
const GElf_Sym *, const char *);
218
static void sym_elem_print_all_portable(char, const char *,
219
const GElf_Sym *, const char *);
220
static void sym_elem_print_all_sysv(char, const char *,
221
const GElf_Sym *, const char *);
222
static int sym_elem_undef(char, const GElf_Sym *, const char *);
223
static void sym_list_dest(struct sym_head *);
224
static int sym_list_insert(struct sym_head *, const char *,
225
const GElf_Sym *);
226
static void sym_list_print(struct sym_print_data *,
227
struct func_info_head *, struct var_info_head *,
228
struct line_info_head *);
229
static void sym_list_print_each(struct sym_entry *,
230
struct sym_print_data *, struct func_info_head *,
231
struct var_info_head *, struct line_info_head *);
232
static struct sym_entry *sym_list_sort(struct sym_print_data *);
233
static void sym_size_oct_print(const GElf_Sym *);
234
static void sym_size_hex_print(const GElf_Sym *);
235
static void sym_size_dec_print(const GElf_Sym *);
236
static void sym_value_oct_print(const GElf_Sym *);
237
static void sym_value_hex_print(const GElf_Sym *);
238
static void sym_value_dec_print(const GElf_Sym *);
239
static void usage(int);
240
241
static struct nm_prog_info nm_info;
242
static struct nm_prog_options nm_opts;
243
static int nm_elfclass;
244
245
/*
246
* Point to current sym_print_data to use portable qsort function.
247
* (e.g. There is no qsort_r function in NetBSD.)
248
*
249
* Using in sym_list_sort.
250
*/
251
static struct sym_print_data *nm_print_data;
252
253
static const struct option nm_longopts[] = {
254
{ "debug-syms", no_argument, NULL, 'a' },
255
{ "defined-only", no_argument, &nm_opts.def_only, 1},
256
{ "demangle", optional_argument, NULL, 'C' },
257
{ "dynamic", no_argument, NULL, 'D' },
258
{ "extern-only", no_argument, NULL, 'g' },
259
{ "format", required_argument, NULL, 'F' },
260
{ "help", no_argument, NULL, 'h' },
261
{ "line-numbers", no_argument, NULL, 'l' },
262
{ "no-demangle", no_argument, &nm_opts.no_demangle,
263
1},
264
{ "no-sort", no_argument, NULL, 'p' },
265
{ "numeric-sort", no_argument, NULL, 'v' },
266
{ "print-armap", no_argument, NULL, 's' },
267
{ "print-file-name", no_argument, NULL, 'A' },
268
{ "print-size", no_argument, NULL, 'S' },
269
{ "radix", required_argument, NULL, 't' },
270
{ "reverse-sort", no_argument, NULL, 'r' },
271
{ "size-sort", no_argument, &nm_opts.sort_size, 1},
272
{ "undefined-only", no_argument, NULL, 'u' },
273
{ "version", no_argument, NULL, 'V' },
274
{ NULL, 0, NULL, 0 }
275
};
276
277
#if defined(ELFTC_NEED_BYTEORDER_EXTENSIONS)
278
static __inline uint32_t
279
be32dec(const void *pp)
280
{
281
unsigned char const *p = (unsigned char const *)pp;
282
283
return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
284
}
285
286
static __inline uint32_t
287
le32dec(const void *pp)
288
{
289
unsigned char const *p = (unsigned char const *)pp;
290
291
return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]);
292
}
293
294
static __inline uint64_t
295
be64dec(const void *pp)
296
{
297
unsigned char const *p = (unsigned char const *)pp;
298
299
return (((uint64_t)be32dec(p) << 32) | be32dec(p + 4));
300
}
301
302
static __inline uint64_t
303
le64dec(const void *pp)
304
{
305
unsigned char const *p = (unsigned char const *)pp;
306
307
return (((uint64_t)le32dec(p + 4) << 32) | le32dec(p));
308
}
309
#endif
310
311
static int
312
cmp_name(const void *l, const void *r)
313
{
314
315
assert(l != NULL);
316
assert(r != NULL);
317
assert(((const struct sym_entry *)l)->name != NULL);
318
assert(((const struct sym_entry *)r)->name != NULL);
319
320
return (strcmp(((const struct sym_entry *)l)->name,
321
((const struct sym_entry *)r)->name));
322
}
323
324
static int
325
cmp_none(const void *l, const void *r)
326
{
327
328
UNUSED(l);
329
UNUSED(r);
330
331
return (0);
332
}
333
334
/* Size comparison. If l and r have same size, compare their name. */
335
static int
336
cmp_size(const void *lp, const void *rp)
337
{
338
const struct sym_entry *l, *r;
339
340
l = lp;
341
r = rp;
342
343
assert(l != NULL);
344
assert(l->name != NULL);
345
assert(l->sym != NULL);
346
assert(r != NULL);
347
assert(r->name != NULL);
348
assert(r->sym != NULL);
349
350
if (l->sym->st_size == r->sym->st_size)
351
return (strcmp(l->name, r->name));
352
353
return (l->sym->st_size - r->sym->st_size);
354
}
355
356
/* Value comparison. Undefined symbols come first. */
357
static int
358
cmp_value(const void *lp, const void *rp)
359
{
360
const struct sym_entry *l, *r;
361
const char *ttable;
362
int l_is_undef, r_is_undef;
363
364
l = lp;
365
r = rp;
366
367
assert(nm_print_data != NULL);
368
ttable = nm_print_data->t_table;
369
370
assert(l != NULL);
371
assert(l->name != NULL);
372
assert(l->sym != NULL);
373
assert(r != NULL);
374
assert(r->name != NULL);
375
assert(r->sym != NULL);
376
assert(ttable != NULL);
377
378
l_is_undef = IS_UNDEF_SYM_TYPE(get_sym_type(l->sym, ttable)) ? 1 : 0;
379
r_is_undef = IS_UNDEF_SYM_TYPE(get_sym_type(r->sym, ttable)) ? 1 : 0;
380
381
assert(l_is_undef + r_is_undef >= 0);
382
assert(l_is_undef + r_is_undef <= 2);
383
384
switch (l_is_undef + r_is_undef) {
385
case 0:
386
/* Both defined */
387
if (l->sym->st_value == r->sym->st_value)
388
return (strcmp(l->name, r->name));
389
return (l->sym->st_value > r->sym->st_value ? 1 : -1);
390
case 1:
391
/* One undefined */
392
return (l_is_undef == 0 ? 1 : -1);
393
case 2:
394
/* Both undefined */
395
return (strcmp(l->name, r->name));
396
}
397
/* NOTREACHED */
398
399
return (l->sym->st_value - r->sym->st_value);
400
}
401
402
static void
403
enter_cap_mode(int argc, char **argv)
404
{
405
cap_rights_t rights;
406
fileargs_t *fa;
407
char *defaultfn;
408
409
cap_rights_init(&rights, CAP_FSTAT, CAP_MMAP_R);
410
411
if (argc == 0) {
412
defaultfn = strdup(nm_info.def_filename);
413
if (defaultfn == NULL)
414
err(EXIT_FAILURE, "strdup");
415
argc = 1;
416
argv = &defaultfn;
417
}
418
419
fa = fileargs_init(argc, argv, O_RDONLY, 0, &rights, FA_OPEN);
420
if (fa == NULL)
421
err(EXIT_FAILURE, "failed to initialize fileargs");
422
423
caph_cache_catpages();
424
if (caph_limit_stdio() < 0)
425
err(EXIT_FAILURE, "failed to limit stdio rights");
426
if (caph_enter_casper() < 0)
427
err(EXIT_FAILURE, "failed to enter capability mode");
428
429
nm_opts.fileargs = fa;
430
}
431
432
static void
433
filter_dest(void)
434
{
435
struct filter_entry *e;
436
437
while (!SLIST_EMPTY(&nm_out_filter)) {
438
e = SLIST_FIRST(&nm_out_filter);
439
SLIST_REMOVE_HEAD(&nm_out_filter, filter_entries);
440
free(e);
441
}
442
}
443
444
static int
445
filter_insert(fn_filter filter_fn)
446
{
447
struct filter_entry *e;
448
449
assert(filter_fn != NULL);
450
451
if ((e = malloc(sizeof(struct filter_entry))) == NULL) {
452
warn("malloc");
453
return (0);
454
}
455
e->fn = filter_fn;
456
SLIST_INSERT_HEAD(&nm_out_filter, e, filter_entries);
457
458
return (1);
459
}
460
461
static int
462
parse_demangle_option(const char *opt)
463
{
464
465
if (opt == NULL)
466
return (ELFTC_DEM_UNKNOWN);
467
else if (!strncasecmp(opt, "gnu-v2", 6))
468
return (ELFTC_DEM_GNU2);
469
else if (!strncasecmp(opt, "gnu-v3", 6))
470
return (ELFTC_DEM_GNU3);
471
else if (!strncasecmp(opt, "arm", 3))
472
return (ELFTC_DEM_ARM);
473
else
474
errx(EXIT_FAILURE, "unknown demangling style '%s'", opt);
475
476
/* NOTREACHED */
477
return (0);
478
}
479
480
static void
481
get_opt(int *argc, char ***argv)
482
{
483
int ch;
484
bool is_posix, oflag;
485
486
if (*argc <= 0 || *argv == NULL)
487
return;
488
489
oflag = is_posix = false;
490
nm_opts.t = RADIX_HEX;
491
while ((ch = getopt_long(*argc, *argv, "ABCDF:PSVaefghlnoprst:uvx",
492
nm_longopts, NULL)) != -1) {
493
switch (ch) {
494
case 'A':
495
nm_opts.print_name = PRINT_NAME_FULL;
496
break;
497
case 'B':
498
nm_opts.elem_print_fn = &sym_elem_print_all;
499
break;
500
case 'C':
501
nm_opts.demangle_type = parse_demangle_option(optarg);
502
break;
503
case 'D':
504
nm_opts.print_symbol = PRINT_SYM_DYN;
505
break;
506
case 'F':
507
/* sysv, bsd, posix */
508
switch (optarg[0]) {
509
case 'B':
510
case 'b':
511
nm_opts.elem_print_fn = &sym_elem_print_all;
512
break;
513
case 'P':
514
case 'p':
515
is_posix = true;
516
nm_opts.elem_print_fn =
517
&sym_elem_print_all_portable;
518
break;
519
case 'S':
520
case 's':
521
nm_opts.elem_print_fn =
522
&sym_elem_print_all_sysv;
523
break;
524
default:
525
warnx("%s: Invalid format", optarg);
526
usage(1);
527
}
528
529
break;
530
case 'P':
531
is_posix = true;
532
nm_opts.elem_print_fn = &sym_elem_print_all_portable;
533
break;
534
case 'S':
535
nm_opts.print_size = 1;
536
break;
537
case 'V':
538
print_version();
539
/* NOTREACHED */
540
case 'a':
541
nm_opts.print_debug = true;
542
break;
543
case 'e':
544
filter_insert(sym_elem_global_static);
545
break;
546
case 'f':
547
break;
548
case 'g':
549
filter_insert(sym_elem_global);
550
break;
551
case 'h':
552
usage(0);
553
break;
554
case 'l':
555
nm_opts.debug_line = true;
556
break;
557
case 'n':
558
case 'v':
559
nm_opts.sort_fn = &cmp_value;
560
break;
561
case 'o':
562
oflag = true;
563
break;
564
case 'p':
565
nm_opts.sort_fn = &cmp_none;
566
break;
567
case 'r':
568
nm_opts.sort_reverse = true;
569
break;
570
case 's':
571
nm_opts.print_armap = true;
572
break;
573
case 't':
574
/* t require always argument to getopt_long */
575
switch (optarg[0]) {
576
case 'd':
577
nm_opts.t = RADIX_DEC;
578
break;
579
case 'o':
580
nm_opts.t = RADIX_OCT;
581
break;
582
case 'x':
583
nm_opts.t = RADIX_HEX;
584
break;
585
default:
586
warnx("%s: Invalid radix", optarg);
587
usage(1);
588
}
589
break;
590
case 'u':
591
filter_insert(sym_elem_undef);
592
nm_opts.undef_only = true;
593
break;
594
/* case 'v': see case 'n' above. */
595
case 'x':
596
nm_opts.t = RADIX_HEX;
597
break;
598
case 0:
599
if (nm_opts.sort_size != 0) {
600
nm_opts.sort_fn = &cmp_size;
601
filter_insert(sym_elem_def);
602
filter_insert(sym_elem_nonzero_size);
603
}
604
if (nm_opts.def_only != 0)
605
filter_insert(sym_elem_def);
606
if (nm_opts.no_demangle != 0)
607
nm_opts.demangle_type = -1;
608
break;
609
default :
610
usage(1);
611
}
612
}
613
*argc -= optind;
614
*argv += optind;
615
616
/*
617
* In POSIX mode, the '-o' option controls the output radix.
618
* In non-POSIX mode, the option is a synonym for the '-A' and
619
* '--print-file-name' options.
620
*/
621
if (oflag) {
622
if (is_posix)
623
nm_opts.t = RADIX_OCT;
624
else
625
nm_opts.print_name = PRINT_NAME_FULL;
626
}
627
628
assert(nm_opts.sort_fn != NULL && "nm_opts.sort_fn is null");
629
assert(nm_opts.elem_print_fn != NULL &&
630
"nm_opts.elem_print_fn is null");
631
assert(nm_opts.value_print_fn != NULL &&
632
"nm_opts.value_print_fn is null");
633
634
set_opt_value_print_fn(nm_opts.t);
635
636
if (nm_opts.undef_only == true) {
637
if (nm_opts.sort_fn == &cmp_size)
638
errx(EXIT_FAILURE,
639
"--size-sort with -u is meaningless");
640
if (nm_opts.def_only != 0)
641
errx(EXIT_FAILURE,
642
"-u with --defined-only is meaningless");
643
}
644
if (nm_opts.print_debug == false)
645
filter_insert(sym_elem_nondebug);
646
if (nm_opts.sort_reverse == true && nm_opts.sort_fn == cmp_none)
647
nm_opts.sort_reverse = false;
648
}
649
650
/*
651
* Get symbol information from elf.
652
*/
653
static int
654
get_sym(Elf *elf, struct sym_head *headp, int shnum, size_t dynndx,
655
size_t strndx, const char *type_table, const char **sec_table,
656
int sec_table_size)
657
{
658
Elf_Scn *scn;
659
Elf_Data *data;
660
GElf_Shdr shdr;
661
GElf_Sym sym;
662
struct filter_entry *fep;
663
size_t ndx;
664
int rtn;
665
const char *sym_name;
666
char type;
667
bool filter;
668
int i, j;
669
670
assert(elf != NULL);
671
assert(headp != NULL);
672
673
rtn = 0;
674
for (i = 1; i < shnum; i++) {
675
if ((scn = elf_getscn(elf, i)) == NULL) {
676
warnx("elf_getscn failed: %s", elf_errmsg(-1));
677
continue;
678
}
679
if (gelf_getshdr(scn, &shdr) != &shdr) {
680
warnx("gelf_getshdr failed: %s", elf_errmsg(-1));
681
continue;
682
}
683
if (shdr.sh_type == SHT_SYMTAB) {
684
if (nm_opts.print_symbol != PRINT_SYM_SYM)
685
continue;
686
} else if (shdr.sh_type == SHT_DYNSYM) {
687
if (nm_opts.print_symbol != PRINT_SYM_DYN)
688
continue;
689
} else
690
continue;
691
692
ndx = shdr.sh_type == SHT_DYNSYM ? dynndx : strndx;
693
694
data = NULL;
695
while ((data = elf_getdata(scn, data)) != NULL) {
696
j = 1;
697
while (gelf_getsym(data, j++, &sym) != NULL) {
698
sym_name = get_sym_name(elf, &sym, ndx,
699
sec_table, sec_table_size);
700
filter = false;
701
type = get_sym_type(&sym, type_table);
702
SLIST_FOREACH(fep, &nm_out_filter,
703
filter_entries) {
704
if (!fep->fn(type, &sym, sym_name)) {
705
filter = true;
706
break;
707
}
708
}
709
if (filter == false) {
710
if (sym_list_insert(headp, sym_name,
711
&sym) == 0)
712
return (0);
713
rtn++;
714
}
715
}
716
}
717
}
718
719
return (rtn);
720
}
721
722
static const char *
723
get_sym_name(Elf *elf, const GElf_Sym *sym, size_t ndx, const char **sec_table,
724
int sec_table_size)
725
{
726
const char *sym_name;
727
728
sym_name = NULL;
729
730
/* Show section name as symbol name for STT_SECTION symbols. */
731
if (GELF_ST_TYPE(sym->st_info) == STT_SECTION) {
732
if (sec_table != NULL && sym->st_shndx < sec_table_size)
733
sym_name = sec_table[sym->st_shndx];
734
} else
735
sym_name = elf_strptr(elf, ndx, sym->st_name);
736
737
if (sym_name == NULL)
738
sym_name = "(null)";
739
740
return (sym_name);
741
}
742
743
static char
744
get_sym_type(const GElf_Sym *sym, const char *type_table)
745
{
746
bool is_local;
747
748
if (sym == NULL || type_table == NULL)
749
return ('?');
750
751
is_local = sym->st_info >> 4 == STB_LOCAL;
752
753
if (sym->st_shndx == SHN_ABS) /* absolute */
754
return (is_local ? 'a' : 'A');
755
756
if (sym->st_shndx == SHN_COMMON) /* common */
757
return ('C');
758
759
if ((sym->st_info) >> 4 == STB_WEAK) { /* weak */
760
if ((sym->st_info & 0xf) == STT_OBJECT)
761
return (sym->st_shndx == SHN_UNDEF ? 'v' : 'V');
762
763
return (sym->st_shndx == SHN_UNDEF ? 'w' : 'W');
764
}
765
766
if (sym->st_shndx == SHN_UNDEF) /* undefined */
767
return ('U');
768
769
return (is_local == true && type_table[sym->st_shndx] != 'N' ?
770
tolower((unsigned char) type_table[sym->st_shndx]) :
771
type_table[sym->st_shndx]);
772
}
773
774
static void
775
global_dest(void)
776
{
777
778
filter_dest();
779
}
780
781
static void
782
global_init(void)
783
{
784
785
if (elf_version(EV_CURRENT) == EV_NONE)
786
errx(EXIT_FAILURE, "elf_version error");
787
788
nm_info.name = ELFTC_GETPROGNAME();
789
nm_info.def_filename = "a.out";
790
nm_opts.print_symbol = PRINT_SYM_SYM;
791
nm_opts.print_name = PRINT_NAME_NONE;
792
nm_opts.demangle_type = -1;
793
nm_opts.print_debug = false;
794
nm_opts.print_armap = false;
795
nm_opts.print_size = 0;
796
nm_opts.debug_line = false;
797
nm_opts.def_only = 0;
798
nm_opts.undef_only = false;
799
nm_opts.sort_size = 0;
800
nm_opts.sort_reverse = false;
801
nm_opts.no_demangle = 0;
802
nm_opts.sort_fn = &cmp_name;
803
nm_opts.elem_print_fn = &sym_elem_print_all;
804
nm_opts.value_print_fn = &sym_value_dec_print;
805
nm_opts.size_print_fn = &sym_size_dec_print;
806
nm_opts.fileargs = NULL;
807
SLIST_INIT(&nm_out_filter);
808
}
809
810
static bool
811
is_sec_data(GElf_Shdr *s)
812
{
813
814
assert(s != NULL && "shdr is NULL");
815
816
return (((s->sh_flags & SHF_ALLOC) != 0) && s->sh_type != SHT_NOBITS);
817
}
818
819
static bool
820
is_sec_debug(const char *shname)
821
{
822
const char *dbg_sec[] = {
823
".debug",
824
".gnu.linkonce.wi.",
825
".line",
826
".rel.debug",
827
".rela.debug",
828
".stab",
829
NULL
830
};
831
const char **p;
832
833
if (shname == NULL)
834
return (false);
835
836
for (p = dbg_sec; *p; p++) {
837
if (!strncmp(shname, *p, strlen(*p)))
838
return (true);
839
}
840
841
return (false);
842
}
843
844
static bool
845
is_sec_nobits(GElf_Shdr *s)
846
{
847
848
assert(s != NULL && "shdr is NULL");
849
850
return (s->sh_type == SHT_NOBITS);
851
}
852
853
static bool
854
is_sec_readonly(GElf_Shdr *s)
855
{
856
857
assert(s != NULL && "shdr is NULL");
858
859
return ((s->sh_flags & SHF_WRITE) == 0);
860
}
861
862
static bool
863
is_sec_text(GElf_Shdr *s)
864
{
865
866
assert(s != NULL && "shdr is NULL");
867
868
return ((s->sh_flags & SHF_EXECINSTR) != 0);
869
}
870
871
static void
872
print_ar_index(int fd, Elf *arf)
873
{
874
Elf *elf;
875
Elf_Arhdr *arhdr;
876
Elf_Arsym *arsym;
877
Elf_Cmd cmd;
878
off_t start;
879
size_t arsym_size;
880
881
if (arf == NULL)
882
return;
883
884
if ((arsym = elf_getarsym(arf, &arsym_size)) == NULL)
885
return;
886
887
printf("\nArchive index:\n");
888
889
start = arsym->as_off;
890
cmd = ELF_C_READ;
891
while (arsym_size > 1) {
892
if (elf_rand(arf, arsym->as_off) == arsym->as_off &&
893
(elf = elf_begin(fd, cmd, arf)) != NULL) {
894
if ((arhdr = elf_getarhdr(elf)) != NULL)
895
printf("%s in %s\n", arsym->as_name,
896
arhdr->ar_name != NULL ?
897
arhdr->ar_name : arhdr->ar_rawname);
898
elf_end(elf);
899
}
900
++arsym;
901
--arsym_size;
902
}
903
904
elf_rand(arf, start);
905
}
906
907
#define DEMANGLED_BUFFER_SIZE (8 * 1024)
908
#define PRINT_DEMANGLED_NAME(FORMAT, NAME) do { \
909
char _demangled[DEMANGLED_BUFFER_SIZE]; \
910
if (nm_opts.demangle_type < 0 || \
911
elftc_demangle((NAME), _demangled, sizeof(_demangled), \
912
nm_opts.demangle_type) < 0) \
913
printf((FORMAT), (NAME)); \
914
else \
915
printf((FORMAT), _demangled); \
916
} while (0)
917
918
static void
919
print_header(const char *file, const char *obj)
920
{
921
922
if (file == NULL)
923
return;
924
925
if (nm_opts.elem_print_fn == &sym_elem_print_all_sysv) {
926
printf("\n\n%s from %s",
927
nm_opts.undef_only == false ? "Symbols" :
928
"Undefined symbols", file);
929
if (obj != NULL)
930
printf("[%s]", obj);
931
printf(":\n\n");
932
933
printf("\
934
Name Value Class Type Size Line Section\n\n");
935
} else {
936
/* archive file without -A option and POSIX */
937
if (nm_opts.print_name != PRINT_NAME_FULL && obj != NULL) {
938
if (nm_opts.elem_print_fn ==
939
sym_elem_print_all_portable)
940
printf("%s[%s]:\n", file, obj);
941
else if (nm_opts.elem_print_fn == sym_elem_print_all)
942
printf("\n%s:\n", obj);
943
/* multiple files(not archive) without -A option */
944
} else if (nm_opts.print_name == PRINT_NAME_MULTI) {
945
if (nm_opts.elem_print_fn == sym_elem_print_all)
946
printf("\n");
947
printf("%s:\n", file);
948
}
949
}
950
}
951
952
static void
953
print_version(void)
954
{
955
956
(void) printf("%s (%s)\n", nm_info.name, elftc_version());
957
exit(0);
958
}
959
960
static uint64_t
961
get_block_value(Dwarf_Debug dbg, Dwarf_Block *block)
962
{
963
Elf *elf;
964
GElf_Ehdr eh;
965
Dwarf_Error de;
966
967
if (dwarf_get_elf(dbg, &elf, &de) != DW_DLV_OK) {
968
warnx("dwarf_get_elf failed: %s", dwarf_errmsg(de));
969
return (0);
970
}
971
972
if (gelf_getehdr(elf, &eh) != &eh) {
973
warnx("gelf_getehdr failed: %s", elf_errmsg(-1));
974
return (0);
975
}
976
977
if (block->bl_len == 5) {
978
if (eh.e_ident[EI_DATA] == ELFDATA2LSB)
979
return (le32dec((uint8_t *) block->bl_data + 1));
980
else
981
return (be32dec((uint8_t *) block->bl_data + 1));
982
} else if (block->bl_len == 9) {
983
if (eh.e_ident[EI_DATA] == ELFDATA2LSB)
984
return (le64dec((uint8_t *) block->bl_data + 1));
985
else
986
return (be64dec((uint8_t *) block->bl_data + 1));
987
}
988
989
return (0);
990
}
991
992
static char *
993
find_object_name(Dwarf_Debug dbg, Dwarf_Die die)
994
{
995
Dwarf_Die ret_die;
996
Dwarf_Attribute at;
997
Dwarf_Off off;
998
Dwarf_Error de;
999
const char *str;
1000
char *name;
1001
1002
if (dwarf_attrval_string(die, DW_AT_name, &str, &de) == DW_DLV_OK) {
1003
if ((name = strdup(str)) == NULL) {
1004
warn("strdup");
1005
return (NULL);
1006
}
1007
return (name);
1008
}
1009
1010
if (dwarf_attr(die, DW_AT_specification, &at, &de) != DW_DLV_OK)
1011
return (NULL);
1012
1013
if (dwarf_global_formref(at, &off, &de) != DW_DLV_OK)
1014
return (NULL);
1015
1016
if (dwarf_offdie(dbg, off, &ret_die, &de) != DW_DLV_OK)
1017
return (NULL);
1018
1019
return (find_object_name(dbg, ret_die));
1020
}
1021
1022
static void
1023
search_line_attr(Dwarf_Debug dbg, struct func_info_head *func_info,
1024
struct var_info_head *var_info, Dwarf_Die die, char **src_files,
1025
Dwarf_Signed filecount)
1026
{
1027
Dwarf_Attribute at;
1028
Dwarf_Unsigned udata;
1029
Dwarf_Half tag;
1030
Dwarf_Block *block;
1031
Dwarf_Bool flag;
1032
Dwarf_Die ret_die;
1033
Dwarf_Error de;
1034
struct func_info_entry *func;
1035
struct var_info_entry *var;
1036
int ret;
1037
1038
if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
1039
warnx("dwarf_tag failed: %s", dwarf_errmsg(de));
1040
goto cont_search;
1041
}
1042
1043
/* We're interested in DIEs which define functions or variables. */
1044
if (tag != DW_TAG_subprogram && tag != DW_TAG_entry_point &&
1045
tag != DW_TAG_inlined_subroutine && tag != DW_TAG_variable)
1046
goto cont_search;
1047
1048
if (tag == DW_TAG_variable) {
1049
1050
/* Ignore "artificial" variable. */
1051
if (dwarf_attrval_flag(die, DW_AT_artificial, &flag, &de) ==
1052
DW_DLV_OK && flag)
1053
goto cont_search;
1054
1055
/* Ignore pure declaration. */
1056
if (dwarf_attrval_flag(die, DW_AT_declaration, &flag, &de) ==
1057
DW_DLV_OK && flag)
1058
goto cont_search;
1059
1060
/* Ignore stack varaibles. */
1061
if (dwarf_attrval_flag(die, DW_AT_external, &flag, &de) !=
1062
DW_DLV_OK || !flag)
1063
goto cont_search;
1064
1065
if ((var = calloc(1, sizeof(*var))) == NULL) {
1066
warn("calloc failed");
1067
goto cont_search;
1068
}
1069
1070
if (dwarf_attrval_unsigned(die, DW_AT_decl_file, &udata,
1071
&de) == DW_DLV_OK && udata > 0 &&
1072
(Dwarf_Signed) (udata - 1) < filecount) {
1073
var->file = strdup(src_files[udata - 1]);
1074
if (var->file == NULL) {
1075
warn("strdup");
1076
free(var);
1077
goto cont_search;
1078
}
1079
}
1080
1081
if (dwarf_attrval_unsigned(die, DW_AT_decl_line, &udata, &de) ==
1082
DW_DLV_OK)
1083
var->line = udata;
1084
1085
var->name = find_object_name(dbg, die);
1086
if (var->name == NULL) {
1087
if (var->file)
1088
free(var->file);
1089
free(var);
1090
goto cont_search;
1091
}
1092
1093
if (dwarf_attr(die, DW_AT_location, &at, &de) == DW_DLV_OK &&
1094
dwarf_formblock(at, &block, &de) == DW_DLV_OK) {
1095
/*
1096
* Since we ignored stack variables, the rest are the
1097
* external varaibles which should always use DW_OP_addr
1098
* operator for DW_AT_location value.
1099
*/
1100
if (*((uint8_t *)block->bl_data) == DW_OP_addr)
1101
var->addr = get_block_value(dbg, block);
1102
}
1103
1104
SLIST_INSERT_HEAD(var_info, var, entries);
1105
1106
} else {
1107
1108
if ((func = calloc(1, sizeof(*func))) == NULL) {
1109
warn("calloc failed");
1110
goto cont_search;
1111
}
1112
1113
/*
1114
* Note that dwarf_attrval_unsigned() handles DW_AT_abstract_origin
1115
* internally, so it can retrieve DW_AT_decl_file/DW_AT_decl_line
1116
* attributes for inlined functions as well.
1117
*/
1118
if (dwarf_attrval_unsigned(die, DW_AT_decl_file, &udata,
1119
&de) == DW_DLV_OK && udata > 0 &&
1120
(Dwarf_Signed) (udata - 1) < filecount) {
1121
func->file = strdup(src_files[udata - 1]);
1122
if (func->file == NULL) {
1123
warn("strdup");
1124
free(func);
1125
goto cont_search;
1126
}
1127
}
1128
1129
if (dwarf_attrval_unsigned(die, DW_AT_decl_line, &udata, &de) ==
1130
DW_DLV_OK)
1131
func->line = udata;
1132
1133
func->name = find_object_name(dbg, die);
1134
if (func->name == NULL) {
1135
if (func->file)
1136
free(func->file);
1137
free(func);
1138
goto cont_search;
1139
}
1140
1141
if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &udata, &de) ==
1142
DW_DLV_OK)
1143
func->lowpc = udata;
1144
if (dwarf_attrval_unsigned(die, DW_AT_high_pc, &udata, &de) ==
1145
DW_DLV_OK)
1146
func->highpc = udata;
1147
1148
SLIST_INSERT_HEAD(func_info, func, entries);
1149
}
1150
1151
cont_search:
1152
1153
/* Search children. */
1154
ret = dwarf_child(die, &ret_die, &de);
1155
if (ret == DW_DLV_ERROR)
1156
warnx("dwarf_child: %s", dwarf_errmsg(de));
1157
else if (ret == DW_DLV_OK)
1158
search_line_attr(dbg, func_info, var_info, ret_die, src_files,
1159
filecount);
1160
1161
/* Search sibling. */
1162
ret = dwarf_siblingof(dbg, die, &ret_die, &de);
1163
if (ret == DW_DLV_ERROR)
1164
warnx("dwarf_siblingof: %s", dwarf_errmsg(de));
1165
else if (ret == DW_DLV_OK)
1166
search_line_attr(dbg, func_info, var_info, ret_die, src_files,
1167
filecount);
1168
1169
dwarf_dealloc(dbg, die, DW_DLA_DIE);
1170
}
1171
1172
/*
1173
* Read elf file and collect symbol information, sort them, print.
1174
* Return 1 at failed, 0 at success.
1175
*/
1176
static int
1177
read_elf(Elf *elf, const char *filename, Elf_Kind kind)
1178
{
1179
Dwarf_Debug dbg;
1180
Dwarf_Die die;
1181
Dwarf_Error de;
1182
Dwarf_Half tag;
1183
Elf_Arhdr *arhdr;
1184
Elf_Scn *scn;
1185
GElf_Shdr shdr;
1186
Dwarf_Line *lbuf;
1187
Dwarf_Unsigned lineno;
1188
Dwarf_Signed lcount, filecount;
1189
Dwarf_Addr lineaddr;
1190
struct sym_print_data p_data;
1191
struct sym_head list_head;
1192
struct line_info_head *line_info;
1193
struct func_info_head *func_info;
1194
struct var_info_head *var_info;
1195
struct line_info_entry *lie;
1196
struct func_info_entry *func;
1197
struct var_info_entry *var;
1198
const char *shname, *objname;
1199
char *type_table, **sec_table, *sfile, **src_files;
1200
size_t i, shstrndx, shnum, dynndx, strndx;
1201
int ret, rtn, e_err;
1202
1203
#define OBJNAME (objname == NULL ? filename : objname)
1204
1205
assert(filename != NULL && "filename is null");
1206
1207
STAILQ_INIT(&list_head);
1208
type_table = NULL;
1209
sec_table = NULL;
1210
line_info = NULL;
1211
func_info = NULL;
1212
var_info = NULL;
1213
objname = NULL;
1214
dynndx = SHN_UNDEF;
1215
strndx = SHN_UNDEF;
1216
rtn = 0;
1217
1218
nm_elfclass = gelf_getclass(elf);
1219
1220
if (kind == ELF_K_AR) {
1221
if ((arhdr = elf_getarhdr(elf)) == NULL)
1222
goto next_cmd;
1223
objname = arhdr->ar_name != NULL ? arhdr->ar_name :
1224
arhdr->ar_rawname;
1225
}
1226
if (!elf_getshnum(elf, &shnum)) {
1227
if ((e_err = elf_errno()) != 0)
1228
warnx("%s: %s", OBJNAME, "File format not recognized");
1229
else
1230
warnx("%s: cannot get section number", OBJNAME);
1231
rtn = 1;
1232
goto next_cmd;
1233
}
1234
if (shnum == 0) {
1235
warnx("%s: has no section", OBJNAME);
1236
rtn = 1;
1237
goto next_cmd;
1238
}
1239
if (!elf_getshstrndx(elf, &shstrndx)) {
1240
warnx("%s: cannot get str index", OBJNAME);
1241
rtn = 1;
1242
goto next_cmd;
1243
}
1244
/* type_table for type determine */
1245
if ((type_table = malloc(sizeof(char) * shnum)) == NULL) {
1246
warn("%s: malloc", OBJNAME);
1247
rtn = 1;
1248
goto next_cmd;
1249
}
1250
/* sec_table for section name to display in sysv format */
1251
if ((sec_table = calloc(shnum, sizeof(char *))) == NULL) {
1252
warn("%s: calloc", OBJNAME);
1253
rtn = 1;
1254
goto next_cmd;
1255
}
1256
1257
type_table[0] = 'U';
1258
if ((sec_table[0] = strdup("*UND*")) == NULL) {
1259
warn("strdup");
1260
goto next_cmd;
1261
}
1262
1263
for (i = 1; i < shnum; ++i) {
1264
type_table[i] = 'U';
1265
if ((scn = elf_getscn(elf, i)) == NULL) {
1266
if ((e_err = elf_errno()) != 0)
1267
warnx("%s: %s", OBJNAME, elf_errmsg(e_err));
1268
else
1269
warnx("%s: cannot get section", OBJNAME);
1270
rtn = 1;
1271
goto next_cmd;
1272
}
1273
if (gelf_getshdr(scn, &shdr) == NULL)
1274
goto next_cmd;
1275
1276
/*
1277
* Cannot test by type and attribute for dynstr, strtab
1278
*/
1279
shname = elf_strptr(elf, shstrndx, (size_t) shdr.sh_name);
1280
if (shname != NULL) {
1281
if ((sec_table[i] = strdup(shname)) == NULL) {
1282
warn("strdup");
1283
goto next_cmd;
1284
}
1285
if (!strncmp(shname, ".dynstr", 7)) {
1286
dynndx = elf_ndxscn(scn);
1287
if (dynndx == SHN_UNDEF) {
1288
warnx("%s: elf_ndxscn failed: %s",
1289
OBJNAME, elf_errmsg(-1));
1290
goto next_cmd;
1291
}
1292
}
1293
if (!strncmp(shname, ".strtab", 7)) {
1294
strndx = elf_ndxscn(scn);
1295
if (strndx == SHN_UNDEF) {
1296
warnx("%s: elf_ndxscn failed: %s",
1297
OBJNAME, elf_errmsg(-1));
1298
goto next_cmd;
1299
}
1300
}
1301
} else {
1302
sec_table[i] = strdup("*UND*");
1303
if (sec_table[i] == NULL) {
1304
warn("strdup");
1305
goto next_cmd;
1306
}
1307
}
1308
1309
1310
if (is_sec_text(&shdr))
1311
type_table[i] = 'T';
1312
else if (is_sec_data(&shdr)) {
1313
if (is_sec_readonly(&shdr))
1314
type_table[i] = 'R';
1315
else
1316
type_table[i] = 'D';
1317
} else if (is_sec_nobits(&shdr))
1318
type_table[i] = 'B';
1319
else if (is_sec_debug(shname))
1320
type_table[i] = 'N';
1321
else if (is_sec_readonly(&shdr) && !is_sec_nobits(&shdr))
1322
type_table[i] = 'n';
1323
}
1324
1325
print_header(filename, objname);
1326
1327
if ((dynndx == SHN_UNDEF && nm_opts.print_symbol == PRINT_SYM_DYN) ||
1328
(strndx == SHN_UNDEF && nm_opts.print_symbol == PRINT_SYM_SYM)) {
1329
warnx("%s: no symbols", OBJNAME);
1330
/* This is not an error case */
1331
goto next_cmd;
1332
}
1333
1334
STAILQ_INIT(&list_head);
1335
1336
if (!nm_opts.debug_line)
1337
goto process_sym;
1338
1339
/*
1340
* Collect dwarf line number information.
1341
*/
1342
1343
if (dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dbg, &de) !=
1344
DW_DLV_OK) {
1345
warnx("dwarf_elf_init failed: %s", dwarf_errmsg(de));
1346
goto process_sym;
1347
}
1348
1349
line_info = malloc(sizeof(struct line_info_head));
1350
func_info = malloc(sizeof(struct func_info_head));
1351
var_info = malloc(sizeof(struct var_info_head));
1352
if (line_info != NULL)
1353
SLIST_INIT(line_info);
1354
if (func_info != NULL)
1355
SLIST_INIT(func_info);
1356
if (var_info != NULL)
1357
SLIST_INIT(var_info);
1358
if (line_info == NULL || func_info == NULL || var_info == NULL) {
1359
warn("malloc");
1360
(void) dwarf_finish(dbg, &de);
1361
goto process_sym;
1362
}
1363
1364
while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL,
1365
&de)) == DW_DLV_OK) {
1366
die = NULL;
1367
while (dwarf_siblingof(dbg, die, &die, &de) == DW_DLV_OK) {
1368
if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
1369
warnx("dwarf_tag failed: %s",
1370
dwarf_errmsg(de));
1371
continue;
1372
}
1373
/* XXX: What about DW_TAG_partial_unit? */
1374
if (tag == DW_TAG_compile_unit)
1375
break;
1376
}
1377
if (die == NULL) {
1378
warnx("could not find DW_TAG_compile_unit die");
1379
continue;
1380
}
1381
1382
/* Retrieve source file list. */
1383
ret = dwarf_srcfiles(die, &src_files, &filecount, &de);
1384
if (ret == DW_DLV_ERROR)
1385
warnx("dwarf_srclines: %s", dwarf_errmsg(de));
1386
if (ret != DW_DLV_OK)
1387
continue;
1388
1389
/*
1390
* Retrieve line number information from .debug_line section.
1391
*/
1392
1393
ret = dwarf_srclines(die, &lbuf, &lcount, &de);
1394
if (ret == DW_DLV_ERROR)
1395
warnx("dwarf_srclines: %s", dwarf_errmsg(de));
1396
if (ret != DW_DLV_OK)
1397
goto line_attr;
1398
for (i = 0; (Dwarf_Signed) i < lcount; i++) {
1399
if (dwarf_lineaddr(lbuf[i], &lineaddr, &de)) {
1400
warnx("dwarf_lineaddr: %s", dwarf_errmsg(de));
1401
continue;
1402
}
1403
if (dwarf_lineno(lbuf[i], &lineno, &de)) {
1404
warnx("dwarf_lineno: %s", dwarf_errmsg(de));
1405
continue;
1406
}
1407
if (dwarf_linesrc(lbuf[i], &sfile, &de)) {
1408
warnx("dwarf_linesrc: %s", dwarf_errmsg(de));
1409
continue;
1410
}
1411
if ((lie = malloc(sizeof(*lie))) == NULL) {
1412
warn("malloc");
1413
continue;
1414
}
1415
lie->addr = lineaddr;
1416
lie->line = lineno;
1417
lie->file = strdup(sfile);
1418
if (lie->file == NULL) {
1419
warn("strdup");
1420
free(lie);
1421
continue;
1422
}
1423
SLIST_INSERT_HEAD(line_info, lie, entries);
1424
}
1425
1426
line_attr:
1427
/* Retrieve line number information from DIEs. */
1428
search_line_attr(dbg, func_info, var_info, die, src_files, filecount);
1429
}
1430
1431
(void) dwarf_finish(dbg, &de);
1432
1433
process_sym:
1434
1435
p_data.list_num = get_sym(elf, &list_head, shnum, dynndx, strndx,
1436
type_table, (void *) sec_table, shnum);
1437
1438
if (p_data.list_num == 0)
1439
goto next_cmd;
1440
1441
p_data.headp = &list_head;
1442
p_data.sh_num = shnum;
1443
p_data.t_table = type_table;
1444
p_data.s_table = (void *) sec_table;
1445
p_data.filename = filename;
1446
p_data.objname = objname;
1447
1448
sym_list_print(&p_data, func_info, var_info, line_info);
1449
1450
next_cmd:
1451
if (nm_opts.debug_line) {
1452
if (func_info != NULL) {
1453
while (!SLIST_EMPTY(func_info)) {
1454
func = SLIST_FIRST(func_info);
1455
SLIST_REMOVE_HEAD(func_info, entries);
1456
free(func->file);
1457
free(func->name);
1458
free(func);
1459
}
1460
free(func_info);
1461
func_info = NULL;
1462
}
1463
if (var_info != NULL) {
1464
while (!SLIST_EMPTY(var_info)) {
1465
var = SLIST_FIRST(var_info);
1466
SLIST_REMOVE_HEAD(var_info, entries);
1467
free(var->file);
1468
free(var->name);
1469
free(var);
1470
}
1471
free(var_info);
1472
var_info = NULL;
1473
}
1474
if (line_info != NULL) {
1475
while (!SLIST_EMPTY(line_info)) {
1476
lie = SLIST_FIRST(line_info);
1477
SLIST_REMOVE_HEAD(line_info, entries);
1478
free(lie->file);
1479
free(lie);
1480
}
1481
free(line_info);
1482
line_info = NULL;
1483
}
1484
}
1485
1486
if (sec_table != NULL)
1487
for (i = 0; i < shnum; ++i)
1488
free(sec_table[i]);
1489
free(sec_table);
1490
free(type_table);
1491
1492
sym_list_dest(&list_head);
1493
1494
return (rtn);
1495
1496
#undef OBJNAME
1497
}
1498
1499
static int
1500
read_object(const char *filename)
1501
{
1502
Elf *elf, *arf;
1503
Elf_Cmd elf_cmd;
1504
Elf_Kind kind;
1505
int fd, rtn, e_err;
1506
1507
assert(filename != NULL && "filename is null");
1508
1509
if ((fd = fileargs_open(nm_opts.fileargs, filename)) == -1) {
1510
warn("'%s'", filename);
1511
return (1);
1512
}
1513
1514
elf_cmd = ELF_C_READ;
1515
if ((arf = elf_begin(fd, elf_cmd, (Elf *) NULL)) == NULL) {
1516
if ((e_err = elf_errno()) != 0)
1517
warnx("elf_begin error: %s", elf_errmsg(e_err));
1518
else
1519
warnx("elf_begin error");
1520
close(fd);
1521
return (1);
1522
}
1523
1524
assert(arf != NULL && "arf is null.");
1525
1526
rtn = 0;
1527
if ((kind = elf_kind(arf)) == ELF_K_NONE) {
1528
warnx("%s: File format not recognized", filename);
1529
elf_end(arf);
1530
close(fd);
1531
return (1);
1532
}
1533
if (kind == ELF_K_AR) {
1534
if (nm_opts.print_name == PRINT_NAME_MULTI &&
1535
nm_opts.elem_print_fn == sym_elem_print_all)
1536
printf("\n%s:\n", filename);
1537
if (nm_opts.print_armap == true)
1538
print_ar_index(fd, arf);
1539
}
1540
1541
while ((elf = elf_begin(fd, elf_cmd, arf)) != NULL) {
1542
rtn |= read_elf(elf, filename, kind);
1543
1544
/*
1545
* If file is not archive, elf_next return ELF_C_NULL and
1546
* stop the loop.
1547
*/
1548
elf_cmd = elf_next(elf);
1549
elf_end(elf);
1550
}
1551
1552
elf_end(arf);
1553
close(fd);
1554
1555
return (rtn);
1556
}
1557
1558
static int
1559
read_files(int argc, char **argv)
1560
{
1561
int rtn = 0;
1562
1563
if (argc < 0 || argv == NULL)
1564
return (1);
1565
1566
if (argc == 0)
1567
rtn |= read_object(nm_info.def_filename);
1568
else {
1569
if (nm_opts.print_name == PRINT_NAME_NONE && argc > 1)
1570
nm_opts.print_name = PRINT_NAME_MULTI;
1571
while (argc > 0) {
1572
rtn |= read_object(*argv);
1573
--argc;
1574
++argv;
1575
}
1576
}
1577
1578
return (rtn);
1579
}
1580
1581
static void
1582
print_lineno(struct sym_entry *ep, struct func_info_head *func_info,
1583
struct var_info_head *var_info, struct line_info_head *line_info)
1584
{
1585
struct func_info_entry *func;
1586
struct var_info_entry *var;
1587
struct line_info_entry *lie;
1588
1589
/* For function symbol, search the function line information list. */
1590
if ((ep->sym->st_info & 0xf) == STT_FUNC && func_info != NULL) {
1591
SLIST_FOREACH(func, func_info, entries) {
1592
if (func->name != NULL &&
1593
!strcmp(ep->name, func->name) &&
1594
ep->sym->st_value >= func->lowpc &&
1595
ep->sym->st_value < func->highpc) {
1596
printf("\t%s:%" PRIu64, func->file, func->line);
1597
return;
1598
}
1599
}
1600
}
1601
1602
/* For variable symbol, search the variable line information list. */
1603
if ((ep->sym->st_info & 0xf) == STT_OBJECT && var_info != NULL) {
1604
SLIST_FOREACH(var, var_info, entries) {
1605
if (!strcmp(ep->name, var->name) &&
1606
ep->sym->st_value == var->addr) {
1607
printf("\t%s:%" PRIu64, var->file, var->line);
1608
return;
1609
}
1610
}
1611
}
1612
1613
/* Otherwise search line number information the .debug_line section. */
1614
if (line_info != NULL) {
1615
SLIST_FOREACH(lie, line_info, entries) {
1616
if (ep->sym->st_value == lie->addr) {
1617
printf("\t%s:%" PRIu64, lie->file, lie->line);
1618
return;
1619
}
1620
}
1621
}
1622
}
1623
1624
static void
1625
set_opt_value_print_fn(enum radix t)
1626
{
1627
1628
switch (t) {
1629
case RADIX_OCT:
1630
nm_opts.value_print_fn = &sym_value_oct_print;
1631
nm_opts.size_print_fn = &sym_size_oct_print;
1632
1633
break;
1634
case RADIX_DEC:
1635
nm_opts.value_print_fn = &sym_value_dec_print;
1636
nm_opts.size_print_fn = &sym_size_dec_print;
1637
1638
break;
1639
case RADIX_HEX:
1640
default :
1641
nm_opts.value_print_fn = &sym_value_hex_print;
1642
nm_opts.size_print_fn = &sym_size_hex_print;
1643
}
1644
1645
assert(nm_opts.value_print_fn != NULL &&
1646
"nm_opts.value_print_fn is null");
1647
}
1648
1649
static void
1650
sym_elem_print_all(char type, const char *sec, const GElf_Sym *sym,
1651
const char *name)
1652
{
1653
1654
if (sec == NULL || sym == NULL || name == NULL ||
1655
nm_opts.value_print_fn == NULL)
1656
return;
1657
1658
if (IS_UNDEF_SYM_TYPE(type)) {
1659
if (nm_opts.t == RADIX_HEX && nm_elfclass == ELFCLASS32)
1660
printf("%-8s", "");
1661
else
1662
printf("%-16s", "");
1663
} else {
1664
switch ((nm_opts.sort_fn == & cmp_size ? 2 : 0) +
1665
nm_opts.print_size) {
1666
case 3:
1667
if (sym->st_size != 0) {
1668
nm_opts.value_print_fn(sym);
1669
printf(" ");
1670
nm_opts.size_print_fn(sym);
1671
}
1672
break;
1673
1674
case 2:
1675
if (sym->st_size != 0)
1676
nm_opts.size_print_fn(sym);
1677
break;
1678
1679
case 1:
1680
nm_opts.value_print_fn(sym);
1681
if (sym->st_size != 0) {
1682
printf(" ");
1683
nm_opts.size_print_fn(sym);
1684
}
1685
break;
1686
1687
case 0:
1688
default:
1689
nm_opts.value_print_fn(sym);
1690
}
1691
}
1692
1693
printf(" %c ", type);
1694
PRINT_DEMANGLED_NAME("%s", name);
1695
}
1696
1697
static void
1698
sym_elem_print_all_portable(char type, const char *sec, const GElf_Sym *sym,
1699
const char *name)
1700
{
1701
1702
if (sec == NULL || sym == NULL || name == NULL ||
1703
nm_opts.value_print_fn == NULL)
1704
return;
1705
1706
PRINT_DEMANGLED_NAME("%s", name);
1707
printf(" %c ", type);
1708
if (!IS_UNDEF_SYM_TYPE(type)) {
1709
nm_opts.value_print_fn(sym);
1710
printf(" ");
1711
if (sym->st_size != 0)
1712
nm_opts.size_print_fn(sym);
1713
} else
1714
printf(" ");
1715
}
1716
1717
static void
1718
sym_elem_print_all_sysv(char type, const char *sec, const GElf_Sym *sym,
1719
const char *name)
1720
{
1721
1722
if (sec == NULL || sym == NULL || name == NULL ||
1723
nm_opts.value_print_fn == NULL)
1724
return;
1725
1726
PRINT_DEMANGLED_NAME("%-20s|", name);
1727
if (IS_UNDEF_SYM_TYPE(type))
1728
printf(" ");
1729
else
1730
nm_opts.value_print_fn(sym);
1731
1732
printf("| %c |", type);
1733
1734
switch (sym->st_info & 0xf) {
1735
case STT_OBJECT:
1736
printf("%18s|", "OBJECT");
1737
break;
1738
1739
case STT_FUNC:
1740
printf("%18s|", "FUNC");
1741
break;
1742
1743
case STT_SECTION:
1744
printf("%18s|", "SECTION");
1745
break;
1746
1747
case STT_FILE:
1748
printf("%18s|", "FILE");
1749
break;
1750
1751
case STT_LOPROC:
1752
printf("%18s|", "LOPROC");
1753
break;
1754
1755
case STT_HIPROC:
1756
printf("%18s|", "HIPROC");
1757
break;
1758
1759
case STT_NOTYPE:
1760
default:
1761
printf("%18s|", "NOTYPE");
1762
}
1763
1764
if (sym->st_size != 0)
1765
nm_opts.size_print_fn(sym);
1766
else
1767
printf(" ");
1768
1769
printf("| |%s", sec);
1770
}
1771
1772
static int
1773
sym_elem_def(char type, const GElf_Sym *sym, const char *name)
1774
{
1775
1776
assert(IS_SYM_TYPE((unsigned char) type));
1777
1778
UNUSED(sym);
1779
UNUSED(name);
1780
1781
return (!IS_UNDEF_SYM_TYPE((unsigned char) type));
1782
}
1783
1784
static int
1785
sym_elem_global(char type, const GElf_Sym *sym, const char *name)
1786
{
1787
1788
assert(IS_SYM_TYPE((unsigned char) type));
1789
1790
UNUSED(sym);
1791
UNUSED(name);
1792
1793
/* weak symbols resemble global. */
1794
return (isupper((unsigned char) type) || type == 'w');
1795
}
1796
1797
static int
1798
sym_elem_global_static(char type, const GElf_Sym *sym, const char *name)
1799
{
1800
unsigned char info;
1801
1802
assert(sym != NULL);
1803
1804
UNUSED(type);
1805
UNUSED(name);
1806
1807
info = sym->st_info >> 4;
1808
1809
return (info == STB_LOCAL ||
1810
info == STB_GLOBAL ||
1811
info == STB_WEAK);
1812
}
1813
1814
static int
1815
sym_elem_nondebug(char type, const GElf_Sym *sym, const char *name)
1816
{
1817
1818
assert(sym != NULL);
1819
1820
UNUSED(type);
1821
UNUSED(name);
1822
1823
if (sym->st_value == 0 && (sym->st_info & 0xf) == STT_FILE)
1824
return (0);
1825
if (sym->st_name == 0)
1826
return (0);
1827
1828
return (1);
1829
}
1830
1831
static int
1832
sym_elem_nonzero_size(char type, const GElf_Sym *sym, const char *name)
1833
{
1834
1835
assert(sym != NULL);
1836
1837
UNUSED(type);
1838
UNUSED(name);
1839
1840
return (sym->st_size > 0);
1841
}
1842
1843
static int
1844
sym_elem_undef(char type, const GElf_Sym *sym, const char *name)
1845
{
1846
1847
assert(IS_SYM_TYPE((unsigned char) type));
1848
1849
UNUSED(sym);
1850
UNUSED(name);
1851
1852
return (IS_UNDEF_SYM_TYPE((unsigned char) type));
1853
}
1854
1855
static void
1856
sym_list_dest(struct sym_head *headp)
1857
{
1858
struct sym_entry *ep, *ep_n;
1859
1860
if (headp == NULL)
1861
return;
1862
1863
ep = STAILQ_FIRST(headp);
1864
while (ep != NULL) {
1865
ep_n = STAILQ_NEXT(ep, sym_entries);
1866
free(ep->sym);
1867
free(ep->name);
1868
free(ep);
1869
ep = ep_n;
1870
}
1871
}
1872
1873
static int
1874
sym_list_insert(struct sym_head *headp, const char *name, const GElf_Sym *sym)
1875
{
1876
struct sym_entry *e;
1877
1878
if (headp == NULL || name == NULL || sym == NULL)
1879
return (0);
1880
if ((e = malloc(sizeof(struct sym_entry))) == NULL) {
1881
warn("malloc");
1882
return (0);
1883
}
1884
if ((e->name = strdup(name)) == NULL) {
1885
warn("strdup");
1886
free(e);
1887
return (0);
1888
}
1889
if ((e->sym = malloc(sizeof(GElf_Sym))) == NULL) {
1890
warn("malloc");
1891
free(e->name);
1892
free(e);
1893
return (0);
1894
}
1895
1896
memcpy(e->sym, sym, sizeof(GElf_Sym));
1897
1898
/* Display size instead of value for common symbol. */
1899
if (sym->st_shndx == SHN_COMMON)
1900
e->sym->st_value = sym->st_size;
1901
1902
STAILQ_INSERT_TAIL(headp, e, sym_entries);
1903
1904
return (1);
1905
}
1906
1907
/* If file has not .debug_info, line_info will be NULL */
1908
static void
1909
sym_list_print(struct sym_print_data *p, struct func_info_head *func_info,
1910
struct var_info_head *var_info, struct line_info_head *line_info)
1911
{
1912
struct sym_entry *e_v;
1913
size_t si;
1914
int i;
1915
1916
if (p == NULL || CHECK_SYM_PRINT_DATA(p))
1917
return;
1918
if ((e_v = sym_list_sort(p)) == NULL)
1919
return;
1920
if (nm_opts.sort_reverse == false)
1921
for (si = 0; si != p->list_num; ++si)
1922
sym_list_print_each(&e_v[si], p, func_info, var_info,
1923
line_info);
1924
else
1925
for (i = p->list_num - 1; i != -1; --i)
1926
sym_list_print_each(&e_v[i], p, func_info, var_info,
1927
line_info);
1928
1929
free(e_v);
1930
}
1931
1932
/* If file has not .debug_info, line_info will be NULL */
1933
static void
1934
sym_list_print_each(struct sym_entry *ep, struct sym_print_data *p,
1935
struct func_info_head *func_info, struct var_info_head *var_info,
1936
struct line_info_head *line_info)
1937
{
1938
const char *sec;
1939
char type;
1940
1941
if (ep == NULL || CHECK_SYM_PRINT_DATA(p))
1942
return;
1943
1944
assert(ep->name != NULL);
1945
assert(ep->sym != NULL);
1946
1947
type = get_sym_type(ep->sym, p->t_table);
1948
1949
if (nm_opts.print_name == PRINT_NAME_FULL) {
1950
printf("%s", p->filename);
1951
if (nm_opts.elem_print_fn == &sym_elem_print_all_portable) {
1952
if (p->objname != NULL)
1953
printf("[%s]", p->objname);
1954
printf(": ");
1955
} else {
1956
if (p->objname != NULL)
1957
printf(":%s", p->objname);
1958
printf(":");
1959
}
1960
}
1961
1962
switch (ep->sym->st_shndx) {
1963
case SHN_LOPROC:
1964
/* LOPROC or LORESERVE */
1965
sec = "*LOPROC*";
1966
break;
1967
case SHN_HIPROC:
1968
sec = "*HIPROC*";
1969
break;
1970
case SHN_LOOS:
1971
sec = "*LOOS*";
1972
break;
1973
case SHN_HIOS:
1974
sec = "*HIOS*";
1975
break;
1976
case SHN_ABS:
1977
sec = "*ABS*";
1978
break;
1979
case SHN_COMMON:
1980
sec = "*COM*";
1981
break;
1982
case SHN_HIRESERVE:
1983
/* HIRESERVE or XINDEX */
1984
sec = "*HIRESERVE*";
1985
break;
1986
default:
1987
if (ep->sym->st_shndx > p->sh_num)
1988
return;
1989
sec = p->s_table[ep->sym->st_shndx];
1990
break;
1991
}
1992
1993
nm_opts.elem_print_fn(type, sec, ep->sym, ep->name);
1994
1995
if (nm_opts.debug_line == true && !IS_UNDEF_SYM_TYPE(type))
1996
print_lineno(ep, func_info, var_info, line_info);
1997
1998
printf("\n");
1999
}
2000
2001
static struct sym_entry *
2002
sym_list_sort(struct sym_print_data *p)
2003
{
2004
struct sym_entry *ep, *e_v;
2005
int idx;
2006
2007
if (p == NULL || CHECK_SYM_PRINT_DATA(p))
2008
return (NULL);
2009
2010
if ((e_v = malloc(sizeof(struct sym_entry) * p->list_num)) == NULL) {
2011
warn("malloc");
2012
return (NULL);
2013
}
2014
2015
idx = 0;
2016
STAILQ_FOREACH(ep, p->headp, sym_entries) {
2017
if (ep->name != NULL && ep->sym != NULL) {
2018
e_v[idx].name = ep->name;
2019
e_v[idx].sym = ep->sym;
2020
++idx;
2021
}
2022
}
2023
2024
assert((size_t)idx == p->list_num);
2025
2026
if (nm_opts.sort_fn != &cmp_none) {
2027
nm_print_data = p;
2028
assert(nm_print_data != NULL);
2029
qsort(e_v, p->list_num, sizeof(struct sym_entry),
2030
nm_opts.sort_fn);
2031
}
2032
2033
return (e_v);
2034
}
2035
2036
static void
2037
sym_size_oct_print(const GElf_Sym *sym)
2038
{
2039
2040
assert(sym != NULL && "sym is null");
2041
printf("%016" PRIo64, sym->st_size);
2042
}
2043
2044
static void
2045
sym_size_hex_print(const GElf_Sym *sym)
2046
{
2047
2048
assert(sym != NULL && "sym is null");
2049
if (nm_elfclass == ELFCLASS32)
2050
printf("%08" PRIx64, sym->st_size);
2051
else
2052
printf("%016" PRIx64, sym->st_size);
2053
}
2054
2055
static void
2056
sym_size_dec_print(const GElf_Sym *sym)
2057
{
2058
2059
assert(sym != NULL && "sym is null");
2060
printf("%016" PRId64, sym->st_size);
2061
}
2062
2063
static void
2064
sym_value_oct_print(const GElf_Sym *sym)
2065
{
2066
2067
assert(sym != NULL && "sym is null");
2068
printf("%016" PRIo64, sym->st_value);
2069
}
2070
2071
static void
2072
sym_value_hex_print(const GElf_Sym *sym)
2073
{
2074
2075
assert(sym != NULL && "sym is null");
2076
if (nm_elfclass == ELFCLASS32)
2077
printf("%08" PRIx64, sym->st_value);
2078
else
2079
printf("%016" PRIx64, sym->st_value);
2080
}
2081
2082
static void
2083
sym_value_dec_print(const GElf_Sym *sym)
2084
{
2085
2086
assert(sym != NULL && "sym is null");
2087
printf("%016" PRId64, sym->st_value);
2088
}
2089
2090
static void
2091
usage(int exitcode)
2092
{
2093
2094
printf("Usage: %s [options] file ...\
2095
\n Display symbolic information in file.\n\
2096
\n Options: \
2097
\n -A, --print-file-name Write the full pathname or library name of an\
2098
\n object on each line.\
2099
\n -a, --debug-syms Display all symbols include debugger-only\
2100
\n symbols.", nm_info.name);
2101
printf("\
2102
\n -B Equivalent to specifying \"--format=bsd\".\
2103
\n -C, --demangle[=style] Decode low-level symbol names.\
2104
\n --no-demangle Do not demangle low-level symbol names.\
2105
\n -D, --dynamic Display only dynamic symbols.\
2106
\n -e Display only global and static symbols.");
2107
printf("\
2108
\n -f Produce full output (default).\
2109
\n --format=format Display output in specific format. Allowed\
2110
\n formats are: \"bsd\", \"posix\" and \"sysv\".\
2111
\n -g, --extern-only Display only global symbol information.\
2112
\n -h, --help Show this help message.\
2113
\n -l, --line-numbers Display filename and linenumber using\
2114
\n debugging information.\
2115
\n -n, --numeric-sort Sort symbols numerically by value.");
2116
printf("\
2117
\n -o Write numeric values in octal. Equivalent to\
2118
\n specifying \"-t o\".\
2119
\n -p, --no-sort Do not sort symbols.\
2120
\n -P Write information in a portable output format.\
2121
\n Equivalent to specifying \"--format=posix\".\
2122
\n -r, --reverse-sort Reverse the order of the sort.\
2123
\n -S, --print-size Print symbol sizes instead values.\
2124
\n -s, --print-armap Include an index of archive members.\
2125
\n --size-sort Sort symbols by size.");
2126
printf("\
2127
\n -t, --radix=format Write each numeric value in the specified\
2128
\n format:\
2129
\n d In decimal,\
2130
\n o In octal,\
2131
\n x In hexadecimal.");
2132
printf("\
2133
\n -u, --undefined-only Display only undefined symbols.\
2134
\n --defined-only Display only defined symbols.\
2135
\n -V, --version Show the version identifier for %s.\
2136
\n -v Sort output by value.\
2137
\n -x Write numeric values in hexadecimal.\
2138
\n Equivalent to specifying \"-t x\".",
2139
nm_info.name);
2140
printf("\n\
2141
\n The default options are: output in bsd format, use a hexadecimal radix,\
2142
\n sort by symbol name, do not demangle names.\n");
2143
2144
exit(exitcode);
2145
}
2146
2147
/*
2148
* Display symbolic information in file.
2149
* Return 0 at success, >0 at failed.
2150
*/
2151
int
2152
main(int argc, char **argv)
2153
{
2154
int rtn;
2155
2156
global_init();
2157
get_opt(&argc, &argv);
2158
enter_cap_mode(argc, argv);
2159
rtn = read_files(argc, argv);
2160
global_dest();
2161
2162
exit(rtn);
2163
}
2164
2165