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