+ else if (bfd_asymbol_section (sym)->owner == abfd)
+ {
+ if ((bfd_find_line (abfd, syms, sym, &filename, &lineno)
+ || bfd_find_nearest_line (abfd, bfd_asymbol_section (sym),
+ syms, sym->value, &filename,
+ &functionname, &lineno))
+ && filename != NULL
+ && lineno != 0)
+ printf ("\t%s:%u", filename, lineno);
+ }
+ }
+
+ putchar ('\n');
+}
+\f
+/* Print the symbols when sorting by size. */
+
+static void
+print_size_symbols (bfd * abfd,
+ bfd_boolean is_dynamic,
+ struct size_sym * symsizes,
+ long symcount,
+ bfd * archive_bfd)
+{
+ asymbol *store;
+ struct size_sym *from;
+ struct size_sym *fromend;
+
+ store = bfd_make_empty_symbol (abfd);
+ if (store == NULL)
+ bfd_fatal (bfd_get_filename (abfd));
+
+ from = symsizes;
+ fromend = from + symcount;
+
+ for (; from < fromend; from++)
+ {
+ asymbol *sym;
+
+ sym = bfd_minisymbol_to_symbol (abfd, is_dynamic, from->minisym, store);
+ if (sym == NULL)
+ bfd_fatal (bfd_get_filename (abfd));
+
+ print_symbol (abfd, sym, from->size, archive_bfd);
+ }
+}
+
+\f
+/* Print the symbols of ABFD that are held in MINISYMS.
+
+ If ARCHIVE_BFD is non-NULL, it is the archive containing ABFD.
+
+ SYMCOUNT is the number of symbols in MINISYMS.
+
+ SIZE is the size of a symbol in MINISYMS. */
+
+static void
+print_symbols (bfd * abfd,
+ bfd_boolean is_dynamic,
+ void * minisyms,
+ long symcount,
+ unsigned int size,
+ bfd * archive_bfd)
+{
+ asymbol *store;
+ bfd_byte *from;
+ bfd_byte *fromend;
+
+ store = bfd_make_empty_symbol (abfd);
+ if (store == NULL)
+ bfd_fatal (bfd_get_filename (abfd));
+
+ from = (bfd_byte *) minisyms;
+ fromend = from + symcount * size;
+
+ for (; from < fromend; from += size)
+ {
+ asymbol *sym;
+
+ sym = bfd_minisymbol_to_symbol (abfd, is_dynamic, from, store);
+ if (sym == NULL)
+ bfd_fatal (bfd_get_filename (abfd));
+
+ print_symbol (abfd, sym, (bfd_vma) 0, archive_bfd);
+ }
+}
+
+/* If ARCHIVE_BFD is non-NULL, it is the archive containing ABFD. */
+
+static void
+display_rel_file (bfd *abfd, bfd *archive_bfd)
+{
+ long symcount;
+ void *minisyms;
+ unsigned int size;
+ struct size_sym *symsizes;
+ asymbol *synthsyms = NULL;
+
+ 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)
+ {
+ if (dynamic && bfd_get_error () == bfd_error_no_symbols)
+ {
+ non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
+ return;
+ }
+
+ bfd_fatal (bfd_get_filename (abfd));
+ }
+
+ if (symcount == 0)
+ {
+ non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
+ return;
+ }
+
+ if (show_synthetic && size == sizeof (asymbol *))
+ {
+ asymbol **static_syms = NULL;
+ asymbol **dyn_syms = NULL;
+ long static_count = 0;
+ long dyn_count = 0;
+ long synth_count;
+
+ if (dynamic)
+ {
+ dyn_count = symcount;
+ dyn_syms = (asymbol **) minisyms;
+ }
+ else
+ {
+ long storage = bfd_get_dynamic_symtab_upper_bound (abfd);
+
+ static_count = symcount;
+ static_syms = (asymbol **) minisyms;
+
+ if (storage > 0)
+ {
+ dyn_syms = (asymbol **) xmalloc (storage);
+ dyn_count = bfd_canonicalize_dynamic_symtab (abfd, dyn_syms);
+ if (dyn_count < 0)
+ bfd_fatal (bfd_get_filename (abfd));
+ }
+ }
+
+ synth_count = bfd_get_synthetic_symtab (abfd, static_count, static_syms,
+ dyn_count, dyn_syms, &synthsyms);
+ if (synth_count > 0)
+ {
+ asymbol **symp;
+ long i;
+
+ minisyms = xrealloc (minisyms,
+ (symcount + synth_count + 1) * sizeof (*symp));
+ symp = (asymbol **) minisyms + symcount;
+ for (i = 0; i < synth_count; i++)
+ *symp++ = synthsyms + i;
+ *symp = 0;
+ symcount += synth_count;
+ }
+ }
+
+ /* lto_slim_object is set to false when a bfd is loaded with a compiler
+ LTO plugin. */
+ if (abfd->lto_slim_object)
+ {
+ report_plugin_err = FALSE;
+ non_fatal (_("%s: plugin needed to handle lto object"),
+ bfd_get_filename (abfd));
+ }
+
+ /* 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);
+
+ if (synthsyms)
+ free (synthsyms);
+ free (minisyms);
+ free (symsizes);
+}
+
+/* Construct a formatting string for printing symbol values. */
+
+static const char *
+get_print_format (void)
+{
+ const char * padding;
+ if (print_format == FORMAT_POSIX)
+ {
+ /* POSIX compatible output does not have any padding. */
+ padding = "";
+ }
+ else if (print_width == 32)
+ {
+ padding ="08";
+ }
+ else /* print_width == 64 */
+ {
+ padding = "016";
+ }
+
+ const char * length = "l";
+ if (print_width == 64)
+ {
+#if BFD_HOST_64BIT_LONG
+ ;
+#elif BFD_HOST_64BIT_LONG_LONG
+#ifndef __MSVCRT__
+ length = "ll";
+#else
+ length = "I64";
+#endif
+#endif
+ }
+
+ const char * radix = NULL;
+ switch (print_radix)
+ {
+ case 8: radix = "o"; break;
+ case 10: radix = "d"; break;
+ case 16: radix = "x"; break;
+ }
+
+ return concat ("%", padding, length, radix, NULL);
+}
+
+static void
+set_print_width (bfd *file)
+{
+ print_width = bfd_get_arch_size (file);
+
+ if (print_width == -1)
+ {
+ /* PR binutils/4292
+ Guess the target's bitsize based on its name.
+ We assume here than any 64-bit format will include
+ "64" somewhere in its name. The only known exception
+ is the MMO object file format. */
+ if (strstr (bfd_get_target (file), "64") != NULL
+ || strcmp (bfd_get_target (file), "mmo") == 0)
+ print_width = 64;
+ else
+ print_width = 32;
+ }
+ free ((char *) print_format_string);
+ print_format_string = get_print_format ();
+}
+
+static void
+display_archive (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))
+ {
+ set_print_width (arfile);
+ 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;
+ if (arfile == last_arfile)
+ return;
+ }
+ last_arfile = arfile;
+ }
+
+ if (last_arfile != NULL)
+ {
+ bfd_close (last_arfile);
+ lineno_cache_bfd = NULL;
+ lineno_cache_rel_bfd = NULL;
+ }
+}
+
+static bfd_boolean
+display_file (char *filename)
+{
+ bfd_boolean retval = TRUE;
+ bfd *file;
+ char **matching;
+
+ if (get_file_size (filename) < 1)
+ return FALSE;
+
+ file = bfd_openr (filename, target ? target : plugin_target);
+ if (file == NULL)
+ {
+ bfd_nonfatal (filename);
+ return FALSE;
+ }
+
+ /* If printing line numbers, decompress the debug sections. */
+ if (line_numbers)
+ file->flags |= BFD_DECOMPRESS;
+
+ if (bfd_check_format (file, bfd_archive))
+ {
+ display_archive (file);
+ }
+ else if (bfd_check_format_matches (file, bfd_object, &matching))
+ {
+ set_print_width (file);
+ format->print_object_filename (filename);
+ display_rel_file (file, NULL);
+ }
+ else
+ {
+ bfd_nonfatal (filename);
+ if (bfd_get_error () == bfd_error_file_ambiguously_recognized)