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