1 /*- 2 * Copyright (c) 2007 Hyogeol Lee <hyogeollee@gmail.com> 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