📄 nm.c
字号:
non_fatal (_("data size %ld"), (long) (lim - (char *) &environ)); }#endif exit (retval); return retval;}static voiddisplay_archive (file) bfd *file;{ bfd *arfile = NULL; bfd *last_arfile = NULL; char **matching; (*format->print_archive_filename) (bfd_get_filename (file)); if (print_armap) print_symdef_entry (file); for (;;) { PROGRESS (1); arfile = bfd_openr_next_archived_file (file, arfile); if (arfile == NULL) { if (bfd_get_error () != bfd_error_no_more_archived_files) bfd_fatal (bfd_get_filename (file)); break; } if (bfd_check_format_matches (arfile, bfd_object, &matching)) { (*format->print_archive_member) (bfd_get_filename (file), bfd_get_filename (arfile)); display_rel_file (arfile, file); } else { bfd_nonfatal (bfd_get_filename (arfile)); if (bfd_get_error () == bfd_error_file_ambiguously_recognized) { list_matching_formats (matching); free (matching); } } if (last_arfile != NULL) { bfd_close (last_arfile); lineno_cache_bfd = NULL; lineno_cache_rel_bfd = NULL; } last_arfile = arfile; } if (last_arfile != NULL) { bfd_close (last_arfile); lineno_cache_bfd = NULL; lineno_cache_rel_bfd = NULL; }}static booleandisplay_file (filename) char *filename;{ boolean retval = true; bfd *file; char **matching; file = bfd_openr (filename, target); if (file == NULL) { bfd_nonfatal (filename); return false; } if (bfd_check_format (file, bfd_archive)) { display_archive (file); } else if (bfd_check_format_matches (file, bfd_object, &matching)) { (*format->print_object_filename) (filename); display_rel_file (file, NULL); } else { bfd_nonfatal (filename); if (bfd_get_error () == bfd_error_file_ambiguously_recognized) { list_matching_formats (matching); free (matching); } retval = false; } if (bfd_close (file) == false) bfd_fatal (filename); lineno_cache_bfd = NULL; lineno_cache_rel_bfd = NULL; return retval;}/* These globals are used to pass information into the sorting routines. */static bfd *sort_bfd;static boolean sort_dynamic;static asymbol *sort_x;static asymbol *sort_y;/* Symbol-sorting predicates */#define valueof(x) ((x)->section->vma + (x)->value)/* Numeric sorts. Undefined symbols are always considered "less than" defined symbols with zero values. Common symbols are not treated specially -- i.e., their sizes are used as their "values". */static intnumeric_forward (P_x, P_y) const PTR P_x; const PTR P_y;{ asymbol *x, *y; asection *xs, *ys; x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x); y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y); if (x == NULL || y == NULL) bfd_fatal (bfd_get_filename (sort_bfd)); xs = bfd_get_section (x); ys = bfd_get_section (y); if (bfd_is_und_section (xs)) { if (! bfd_is_und_section (ys)) return -1; } else if (bfd_is_und_section (ys)) return 1; else if (valueof (x) != valueof (y)) return valueof (x) < valueof (y) ? -1 : 1; return non_numeric_forward (P_x, P_y);}static intnumeric_reverse (x, y) const PTR x; const PTR y;{ return - numeric_forward (x, y);}static intnon_numeric_forward (P_x, P_y) const PTR P_x; const PTR P_y;{ asymbol *x, *y; const char *xn, *yn; x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x); y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y); if (x == NULL || y == NULL) bfd_fatal (bfd_get_filename (sort_bfd)); xn = bfd_asymbol_name (x); yn = bfd_asymbol_name (y); return ((xn == NULL) ? ((yn == NULL) ? 0 : -1) : ((yn == NULL) ? 1 : strcmp (xn, yn)));}static intnon_numeric_reverse (x, y) const PTR x; const PTR y;{ return - non_numeric_forward (x, y);}static int (*(sorters[2][2])) PARAMS ((const PTR, const PTR)) ={ { non_numeric_forward, non_numeric_reverse }, { numeric_forward, numeric_reverse }};/* This sort routine is used by sort_symbols_by_size. It is similar to numeric_forward, but when symbols have the same value it sorts by section VMA. This simplifies the sort_symbols_by_size code which handles symbols at the end of sections. Also, this routine tries to sort file names before other symbols with the same value. That will make the file name have a zero size, which will make sort_symbols_by_size choose the non file name symbol, leading to more meaningful output. For similar reasons, this code sorts gnu_compiled_* and gcc2_compiled before other symbols with the same value. */static intsize_forward1 (P_x, P_y) const PTR P_x; const PTR P_y;{ asymbol *x, *y; asection *xs, *ys; const char *xn, *yn; size_t xnl, ynl; int xf, yf; x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x); y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y); if (x == NULL || y == NULL) bfd_fatal (bfd_get_filename (sort_bfd)); xs = bfd_get_section (x); ys = bfd_get_section (y); if (bfd_is_und_section (xs)) abort (); if (bfd_is_und_section (ys)) abort (); if (valueof (x) != valueof (y)) return valueof (x) < valueof (y) ? -1 : 1; if (xs->vma != ys->vma) return xs->vma < ys->vma ? -1 : 1; xn = bfd_asymbol_name (x); yn = bfd_asymbol_name (y); xnl = strlen (xn); ynl = strlen (yn); /* The symbols gnu_compiled and gcc2_compiled convey even less information than the file name, so sort them out first. */ xf = (strstr (xn, "gnu_compiled") != NULL || strstr (xn, "gcc2_compiled") != NULL); yf = (strstr (yn, "gnu_compiled") != NULL || strstr (yn, "gcc2_compiled") != NULL); if (xf && ! yf) return -1; if (! xf && yf) return 1; /* We use a heuristic for the file name. It may not work on non Unix systems, but it doesn't really matter; the only difference is precisely which symbol names get printed. */#define file_symbol(s, sn, snl) \ (((s)->flags & BSF_FILE) != 0 \ || ((sn)[(snl) - 2] == '.' \ && ((sn)[(snl) - 1] == 'o' \ || (sn)[(snl) - 1] == 'a'))) xf = file_symbol (x, xn, xnl); yf = file_symbol (y, yn, ynl); if (xf && ! yf) return -1; if (! xf && yf) return 1; return non_numeric_forward (P_x, P_y);}/* This sort routine is used by sort_symbols_by_size. It is sorting an array of size_sym structures into size order. */static intsize_forward2 (P_x, P_y) const PTR P_x; const PTR P_y;{ const struct size_sym *x = (const struct size_sym *) P_x; const struct size_sym *y = (const struct size_sym *) P_y; if (x->size < y->size) return reverse_sort ? 1 : -1; else if (x->size > y->size) return reverse_sort ? -1 : 1; else return sorters[0][reverse_sort] (x->minisym, y->minisym);}/* Sort the symbols by size. We guess the size by assuming that the difference between the address of a symbol and the address of the next higher symbol is the size. FIXME: ELF actually stores a size with each symbol. We should use it. */static longsort_symbols_by_size (abfd, dynamic, minisyms, symcount, size, symsizesp) bfd *abfd; boolean dynamic; PTR minisyms; long symcount; unsigned int size; struct size_sym **symsizesp;{ struct size_sym *symsizes; bfd_byte *from, *fromend; asymbol *sym = NULL; asymbol *store_sym, *store_next; qsort (minisyms, symcount, size, size_forward1); /* We are going to return a special set of symbols and sizes to print. */ symsizes = (struct size_sym *) xmalloc (symcount * sizeof (struct size_sym)); *symsizesp = symsizes; /* Note that filter_symbols has already removed all absolute and undefined symbols. Here we remove all symbols whose size winds up as zero. */ from = (bfd_byte *) minisyms; fromend = from + symcount * size; store_sym = sort_x; store_next = sort_y; if (from < fromend) { sym = bfd_minisymbol_to_symbol (abfd, dynamic, (const PTR) from, store_sym); if (sym == NULL) bfd_fatal (bfd_get_filename (abfd)); } for (; from < fromend; from += size) { asymbol *next; asection *sec; bfd_vma sz; asymbol *temp; if (from + size < fromend) { next = bfd_minisymbol_to_symbol (abfd, dynamic, (const PTR) (from + size), store_next); if (next == NULL) bfd_fatal (bfd_get_filename (abfd)); } else next = NULL; sec = bfd_get_section (sym); if (bfd_is_com_section (sec)) sz = sym->value; else { if (from + size < fromend && sec == bfd_get_section (next)) sz = valueof (next) - valueof (sym); else sz = (bfd_get_section_vma (abfd, sec) + bfd_section_size (abfd, sec) - valueof (sym)); } if (sz != 0) { symsizes->minisym = (const PTR) from; symsizes->size = sz; ++symsizes; } sym = next; temp = store_sym; store_sym = store_next; store_next = temp; } symcount = symsizes - *symsizesp; /* We must now sort again by size. */ qsort ((PTR) *symsizesp, symcount, sizeof (struct size_sym), size_forward2); return symcount;}/* If ARCHIVE_BFD is non-NULL, it is the archive containing ABFD. */static voiddisplay_rel_file (abfd, archive_bfd) bfd *abfd; bfd *archive_bfd;{ long symcount; PTR minisyms; unsigned int size; struct size_sym *symsizes; if (! dynamic) { if (!(bfd_get_file_flags (abfd) & HAS_SYMS)) { non_fatal (_("%s: no symbols"), bfd_get_filename (abfd)); return; } } symcount = bfd_read_minisymbols (abfd, dynamic, &minisyms, &size); if (symcount < 0) bfd_fatal (bfd_get_filename (abfd)); if (symcount == 0) { non_fatal (_("%s: no symbols"), bfd_get_filename (abfd)); return; } /* Discard the symbols we don't want to print. It's OK to do this in place; we'll free the storage anyway (after printing). */ symcount = filter_symbols (abfd, dynamic, minisyms, symcount, size); symsizes = NULL; if (! no_sort) { sort_bfd = abfd; sort_dynamic = dynamic; sort_x = bfd_make_empty_symbol (abfd); sort_y = bfd_make_empty_symbol (abfd); if (sort_x == NULL || sort_y == NULL) bfd_fatal (bfd_get_filename (abfd)); if (! sort_by_size) qsort (minisyms, symcount, size, sorters[sort_numerically][reverse_sort]); else symcount = sort_symbols_by_size (abfd, dynamic, minisyms, symcount, size, &symsizes); } if (! sort_by_size) print_symbols (abfd, dynamic, minisyms, symcount, size, archive_bfd); else print_size_symbols (abfd, dynamic, symsizes, symcount, archive_bfd); free (minisyms);}/* Choose which symbol entries to print; compact them downward to get rid of the rest. Return the number of symbols to be printed. */static longfilter_symbols (abfd, dynamic, minisyms, symcount, size) bfd *abfd; boolean dynamic; PTR minisyms; long symcount; unsigned int size;{ bfd_byte *from, *fromend, *to; asymbol *store; store = bfd_make_empty_symbol (abfd); if (store == NULL) bfd_fatal (bfd_get_filename (abfd)); from = (bfd_byte *) minisyms; fromend = from + symcount * size; to = (bfd_byte *) minisyms; for (; from < fromend; from += size) { int keep = 0; asymbol *sym; PROGRESS (1); sym = bfd_minisymbol_to_symbol (abfd, dynamic, (const PTR) from, store); if (sym == NULL) bfd_fatal (bfd_get_filename (abfd)); if (undefined_only) keep = bfd_is_und_section (sym->section); else if (external_only) keep = ((sym->flags & BSF_GLOBAL) != 0 || (sym->flags & BSF_WEAK) != 0 || bfd_is_und_section (sym->section) || bfd_is_com_section (sym->section)); else keep = 1; if (keep && ! print_debug_syms && (sym->flags & BSF_DEBUGGING) != 0) keep = 0; if (keep && sort_by_size && (bfd_is_abs_section (sym->section) || bfd_is_und_section (sym->section))) keep = 0; if (keep && defined_only) { if (bfd_is_und_section (sym->section)) keep = 0; } if (keep) { memcpy (to, from, size); to += size; } } return (to - (bfd_byte *) minisyms) / size;}/* Print symbol name NAME, read from ABFD, with printf format FORMAT, demangling it if requested. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -