source: branches/BINUTILS_2-11-2_BRANCH/src/binutils/binutils/nm.c@ 450

Last change on this file since 450 was 450, checked in by (none), 22 years ago

This commit was manufactured by cvs2svn to create branch
'BINUTILS_2-11-2_BRANCH'.

  • Property cvs2svn:cvs-rev set to 1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 38.8 KB
Line 
1/* nm.c -- Describe symbol table of a rel file.
2 Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2001
4 Free Software Foundation, Inc.
5
6 This file is part of GNU Binutils.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 02111-1307, USA. */
22
23#include "bfd.h"
24#include "progress.h"
25#include "bucomm.h"
26#include "getopt.h"
27#include "aout/stab_gnu.h"
28#include "aout/ranlib.h"
29#include "demangle.h"
30#include "libiberty.h"
31
32/* When sorting by size, we use this structure to hold the size and a
33 pointer to the minisymbol. */
34
35struct size_sym
36{
37 const PTR minisym;
38 bfd_vma size;
39};
40
41/* When fetching relocs, we use this structure to pass information to
42 get_relocs. */
43
44struct get_relocs_info
45{
46 asection **secs;
47 arelent ***relocs;
48 long *relcount;
49 asymbol **syms;
50};
51
52static void
53usage PARAMS ((FILE *, int));
54
55static void
56set_print_radix PARAMS ((char *));
57
58static void
59set_output_format PARAMS ((char *));
60
61static void
62display_archive PARAMS ((bfd *));
63
64static boolean
65display_file PARAMS ((char *filename));
66
67static void
68display_rel_file PARAMS ((bfd * file, bfd * archive));
69
70static long
71filter_symbols PARAMS ((bfd *, boolean, PTR, long, unsigned int));
72
73static long
74sort_symbols_by_size PARAMS ((bfd *, boolean, PTR, long, unsigned int,
75 struct size_sym **));
76
77static void
78print_symbols PARAMS ((bfd *, boolean, PTR, long, unsigned int, bfd *));
79
80static void
81print_size_symbols PARAMS ((bfd *, boolean, struct size_sym *, long, bfd *));
82
83static void
84print_symname PARAMS ((const char *, const char *, bfd *));
85
86static void
87print_symbol PARAMS ((bfd *, asymbol *, bfd *));
88
89static void
90print_symdef_entry PARAMS ((bfd * abfd));
91
92/* The sorting functions. */
93
94static int
95numeric_forward PARAMS ((const PTR, const PTR));
96
97static int
98numeric_reverse PARAMS ((const PTR, const PTR));
99
100static int
101non_numeric_forward PARAMS ((const PTR, const PTR));
102
103static int
104non_numeric_reverse PARAMS ((const PTR, const PTR));
105
106static int
107size_forward1 PARAMS ((const PTR, const PTR));
108
109static int
110size_forward2 PARAMS ((const PTR, const PTR));
111
112/* The output formatting functions. */
113
114static void
115print_object_filename_bsd PARAMS ((char *filename));
116
117static void
118print_object_filename_sysv PARAMS ((char *filename));
119
120static void
121print_object_filename_posix PARAMS ((char *filename));
122
123
124static void
125print_archive_filename_bsd PARAMS ((char *filename));
126
127static void
128print_archive_filename_sysv PARAMS ((char *filename));
129
130static void
131print_archive_filename_posix PARAMS ((char *filename));
132
133
134static void
135print_archive_member_bsd PARAMS ((char *archive, CONST char *filename));
136
137static void
138print_archive_member_sysv PARAMS ((char *archive, CONST char *filename));
139
140static void
141print_archive_member_posix PARAMS ((char *archive, CONST char *filename));
142
143
144static void
145print_symbol_filename_bsd PARAMS ((bfd * archive_bfd, bfd * abfd));
146
147static void
148print_symbol_filename_sysv PARAMS ((bfd * archive_bfd, bfd * abfd));
149
150static void
151print_symbol_filename_posix PARAMS ((bfd * archive_bfd, bfd * abfd));
152
153
154static void
155print_value PARAMS ((bfd_vma));
156
157static void
158print_symbol_info_bsd PARAMS ((symbol_info * info, bfd * abfd));
159
160static void
161print_symbol_info_sysv PARAMS ((symbol_info * info, bfd * abfd));
162
163static void
164print_symbol_info_posix PARAMS ((symbol_info * info, bfd * abfd));
165
166static void
167get_relocs PARAMS ((bfd *, asection *, PTR));
168
169/* Support for different output formats. */
170struct output_fns
171 {
172 /* Print the name of an object file given on the command line. */
173 void (*print_object_filename) PARAMS ((char *filename));
174
175 /* Print the name of an archive file given on the command line. */
176 void (*print_archive_filename) PARAMS ((char *filename));
177
178 /* Print the name of an archive member file. */
179 void (*print_archive_member) PARAMS ((char *archive, CONST char *filename));
180
181 /* Print the name of the file (and archive, if there is one)
182 containing a symbol. */
183 void (*print_symbol_filename) PARAMS ((bfd * archive_bfd, bfd * abfd));
184
185 /* Print a line of information about a symbol. */
186 void (*print_symbol_info) PARAMS ((symbol_info * info, bfd * abfd));
187 };
188static struct output_fns formats[] =
189{
190 {print_object_filename_bsd,
191 print_archive_filename_bsd,
192 print_archive_member_bsd,
193 print_symbol_filename_bsd,
194 print_symbol_info_bsd},
195 {print_object_filename_sysv,
196 print_archive_filename_sysv,
197 print_archive_member_sysv,
198 print_symbol_filename_sysv,
199 print_symbol_info_sysv},
200 {print_object_filename_posix,
201 print_archive_filename_posix,
202 print_archive_member_posix,
203 print_symbol_filename_posix,
204 print_symbol_info_posix}
205};
206
207/* Indices in `formats'. */
208#define FORMAT_BSD 0
209#define FORMAT_SYSV 1
210#define FORMAT_POSIX 2
211#define FORMAT_DEFAULT FORMAT_BSD
212
213/* The output format to use. */
214static struct output_fns *format = &formats[FORMAT_DEFAULT];
215
216
217/* Command options. */
218
219static int do_demangle = 0; /* Pretty print C++ symbol names. */
220static int external_only = 0; /* print external symbols only */
221static int defined_only = 0; /* Print defined symbols only */
222static int no_sort = 0; /* don't sort; print syms in order found */
223static int print_debug_syms = 0; /* print debugger-only symbols too */
224static int print_armap = 0; /* describe __.SYMDEF data in archive files. */
225static int reverse_sort = 0; /* sort in downward(alpha or numeric) order */
226static int sort_numerically = 0; /* sort in numeric rather than alpha order */
227static int sort_by_size = 0; /* sort by size of symbol */
228static int undefined_only = 0; /* print undefined symbols only */
229static int dynamic = 0; /* print dynamic symbols. */
230static int show_version = 0; /* show the version number */
231static int show_stats = 0; /* show statistics */
232static int line_numbers = 0; /* print line numbers for symbols */
233
234/* When to print the names of files. Not mutually exclusive in SYSV format. */
235static int filename_per_file = 0; /* Once per file, on its own line. */
236static int filename_per_symbol = 0; /* Once per symbol, at start of line. */
237
238/* Print formats for printing a symbol value. */
239#ifndef BFD64
240static char value_format[] = "%08lx";
241#else
242#if BFD_HOST_64BIT_LONG
243static char value_format[] = "%016lx";
244#else
245/* We don't use value_format for this case. */
246#endif
247#endif
248static int print_radix = 16;
249/* Print formats for printing stab info. */
250static char other_format[] = "%02x";
251static char desc_format[] = "%04x";
252
253static char *target = NULL;
254
255/* Used to cache the line numbers for a BFD. */
256static bfd *lineno_cache_bfd;
257static bfd *lineno_cache_rel_bfd;
258
259#define OPTION_TARGET 200
260
261static struct option long_options[] =
262{
263 {"debug-syms", no_argument, &print_debug_syms, 1},
264 {"demangle", optional_argument, 0, 'C'},
265 {"dynamic", no_argument, &dynamic, 1},
266 {"extern-only", no_argument, &external_only, 1},
267 {"format", required_argument, 0, 'f'},
268 {"help", no_argument, 0, 'h'},
269 {"line-numbers", no_argument, 0, 'l'},
270 {"no-cplus", no_argument, &do_demangle, 0}, /* Linux compatibility. */
271 {"no-demangle", no_argument, &do_demangle, 0},
272 {"no-sort", no_argument, &no_sort, 1},
273 {"numeric-sort", no_argument, &sort_numerically, 1},
274 {"portability", no_argument, 0, 'P'},
275 {"print-armap", no_argument, &print_armap, 1},
276 {"print-file-name", no_argument, 0, 'o'},
277 {"radix", required_argument, 0, 't'},
278 {"reverse-sort", no_argument, &reverse_sort, 1},
279 {"size-sort", no_argument, &sort_by_size, 1},
280 {"stats", no_argument, &show_stats, 1},
281 {"target", required_argument, 0, OPTION_TARGET},
282 {"defined-only", no_argument, &defined_only, 1},
283 {"undefined-only", no_argument, &undefined_only, 1},
284 {"version", no_argument, &show_version, 1},
285 {0, no_argument, 0, 0}
286};
287
288
289/* Some error-reporting functions */
290
291static void
292usage (stream, status)
293 FILE *stream;
294 int status;
295{
296 fprintf (stream, _("Usage: %s [OPTION]... [FILE]...\n"), program_name);
297 fprintf (stream, _("List symbols from FILEs (a.out by default).\n"));
298 fprintf (stream, _("\n\
299 -a, --debug-syms Display debugger-only symbols\n\
300 -A, --print-file-name Print name of the input file before every symbol\n\
301 -B Same as --format=bsd\n\
302 -C, --demangle[=STYLE] Decode low-level symbol names into user-level names\n\
303 The STYLE, if specified, can be `auto' (the default),\n\
304 `gnu', 'lucid', 'arm', 'hp', 'edg' or 'gnu-new-abi'\n\
305 --no-demangle Do not demangle low-level symbol names\n\
306 -D, --dynamic Display dynamic symbols instead of normal symbols\n\
307 --defined-only Display only defined symbols\n\
308 -e (ignored)\n\
309 -f, --format=FORMAT Use the output format FORMAT. FORMAT can be `bsd',\n\
310 `sysv' or `posix'. The default is `bsd'\n\
311 -g, --extern-only Display only external symbols\n\
312 -h, --help Display this information\n\
313 -l, --line-numbers Use debugging information to find a filename and\n\
314 line number for each symbol\n\
315 -n, --numeric-sort Sort symbols numerically by address\n\
316 -o Same as -A\n\
317 -p, --no-sort Do not sort the symbols\n\
318 -P, --portability Same as --format=posix\n\
319 -r, --reverse-sort Reverse the sense of the sort\n\
320 -s, --print-armap Include index for symbols from archive members\n\
321 --size-sort Sort symbols by size\n\
322 -t, --radix=RADIX Use RADIX for printing symbol values\n\
323 --target=BFDNAME Specify the target object format as BFDNAME\n\
324 -u, --undefined-only Display only undefined symbols\n\
325 -V, --version Display this program's version number\n\
326 -X 32_64 (ignored)\n\
327\n"));
328 list_supported_targets (program_name, stream);
329 if (status == 0)
330 fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO);
331 exit (status);
332}
333
334/* Set the radix for the symbol value and size according to RADIX. */
335
336static void
337set_print_radix (radix)
338 char *radix;
339{
340 switch (*radix)
341 {
342 case 'x':
343 break;
344 case 'd':
345 case 'o':
346 if (*radix == 'd')
347 print_radix = 10;
348 else
349 print_radix = 8;
350#ifndef BFD64
351 value_format[4] = *radix;
352#else
353#if BFD_HOST_64BIT_LONG
354 value_format[5] = *radix;
355#else
356 /* This case requires special handling for octal and decimal
357 printing. */
358#endif
359#endif
360 other_format[3] = desc_format[3] = *radix;
361 break;
362 default:
363 fatal (_("%s: invalid radix"), radix);
364 }
365}
366
367static void
368set_output_format (f)
369 char *f;
370{
371 int i;
372
373 switch (*f)
374 {
375 case 'b':
376 case 'B':
377 i = FORMAT_BSD;
378 break;
379 case 'p':
380 case 'P':
381 i = FORMAT_POSIX;
382 break;
383 case 's':
384 case 'S':
385 i = FORMAT_SYSV;
386 break;
387 default:
388 fatal (_("%s: invalid output format"), f);
389 }
390 format = &formats[i];
391}
392
393
394int
395main (argc, argv)
396 int argc;
397 char **argv;
398{
399 int c;
400 int retval;
401
402#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
403 setlocale (LC_MESSAGES, "");
404#endif
405 bindtextdomain (PACKAGE, LOCALEDIR);
406 textdomain (PACKAGE);
407
408#if defined (__EMX__)
409 _wildcard (&argc, &argv);
410 _response (&argc, &argv);
411 program_name = _getname(*argv);
412#else
413 program_name = *argv;
414#endif /* __EMX__ */
415 xmalloc_set_program_name (program_name);
416
417 START_PROGRESS (program_name, 0);
418
419 bfd_init ();
420 set_default_bfd_target ();
421
422 while ((c = getopt_long (argc, argv, "aABCDef:glnopPrst:uvVX:",
423 long_options, (int *) 0)) != EOF)
424 {
425 switch (c)
426 {
427 case 'a':
428 print_debug_syms = 1;
429 break;
430 case 'A':
431 case 'o':
432 filename_per_symbol = 1;
433 break;
434 case 'B': /* For MIPS compatibility. */
435 set_output_format ("bsd");
436 break;
437 case 'C':
438 do_demangle = 1;
439 if (optarg != NULL)
440 {
441 enum demangling_styles style;
442
443 style = cplus_demangle_name_to_style (optarg);
444 if (style == unknown_demangling)
445 fatal (_("unknown demangling style `%s'"),
446 optarg);
447
448 cplus_demangle_set_style (style);
449 }
450 break;
451 case 'D':
452 dynamic = 1;
453 break;
454 case 'e':
455 /* Ignored for HP/UX compatibility. */
456 break;
457 case 'f':
458 set_output_format (optarg);
459 break;
460 case 'g':
461 external_only = 1;
462 break;
463 case 'h':
464 usage (stdout, 0);
465 case 'l':
466 line_numbers = 1;
467 break;
468 case 'n':
469 case 'v':
470 sort_numerically = 1;
471 break;
472 case 'p':
473 no_sort = 1;
474 break;
475 case 'P':
476 set_output_format ("posix");
477 break;
478 case 'r':
479 reverse_sort = 1;
480 break;
481 case 's':
482 print_armap = 1;
483 break;
484 case 't':
485 set_print_radix (optarg);
486 break;
487 case 'u':
488 undefined_only = 1;
489 break;
490 case 'V':
491 show_version = 1;
492 break;
493 case 'X':
494 /* Ignored for (partial) AIX compatibility. On AIX, the
495 argument has values 32, 64, or 32_64, and specfies that
496 only 32-bit, only 64-bit, or both kinds of objects should
497 be examined. The default is 32. So plain AIX nm on a
498 library archive with both kinds of objects will ignore
499 the 64-bit ones. For GNU nm, the default is and always
500 has been -X 32_64, and other options are not supported. */
501 if (strcmp (optarg, "32_64") != 0)
502 fatal (_("Only -X 32_64 is supported"));
503 break;
504
505 case OPTION_TARGET: /* --target */
506 target = optarg;
507 break;
508
509 case 0: /* A long option that just sets a flag. */
510 break;
511
512 default:
513 usage (stderr, 1);
514 }
515 }
516
517 if (show_version)
518 print_version ("nm");
519
520 /* OK, all options now parsed. If no filename specified, do a.out. */
521 if (optind == argc)
522 return !display_file ("a.out");
523
524 retval = 0;
525
526 if (argc - optind > 1)
527 filename_per_file = 1;
528
529 /* We were given several filenames to do. */
530 while (optind < argc)
531 {
532 PROGRESS (1);
533 if (!display_file (argv[optind++]))
534 retval++;
535 }
536
537 END_PROGRESS (program_name);
538
539#ifdef HAVE_SBRK
540 if (show_stats)
541 {
542 char *lim = (char *) sbrk (0);
543
544 non_fatal (_("data size %ld"), (long) (lim - (char *) &environ));
545 }
546#endif
547
548 exit (retval);
549 return retval;
550}
551
552
553static void
554display_archive (file)
555 bfd *file;
556{
557 bfd *arfile = NULL;
558 bfd *last_arfile = NULL;
559 char **matching;
560
561 (*format->print_archive_filename) (bfd_get_filename (file));
562
563 if (print_armap)
564 print_symdef_entry (file);
565
566 for (;;)
567 {
568 PROGRESS (1);
569
570 arfile = bfd_openr_next_archived_file (file, arfile);
571
572 if (arfile == NULL)
573 {
574 if (bfd_get_error () != bfd_error_no_more_archived_files)
575 bfd_fatal (bfd_get_filename (file));
576 break;
577 }
578
579 if (bfd_check_format_matches (arfile, bfd_object, &matching))
580 {
581 (*format->print_archive_member) (bfd_get_filename (file),
582 bfd_get_filename (arfile));
583 display_rel_file (arfile, file);
584 }
585 else
586 {
587 bfd_nonfatal (bfd_get_filename (arfile));
588 if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
589 {
590 list_matching_formats (matching);
591 free (matching);
592 }
593 }
594
595 if (last_arfile != NULL)
596 {
597 bfd_close (last_arfile);
598 lineno_cache_bfd = NULL;
599 lineno_cache_rel_bfd = NULL;
600 }
601 last_arfile = arfile;
602 }
603
604 if (last_arfile != NULL)
605 {
606 bfd_close (last_arfile);
607 lineno_cache_bfd = NULL;
608 lineno_cache_rel_bfd = NULL;
609 }
610}
611
612static boolean
613display_file (filename)
614 char *filename;
615{
616 boolean retval = true;
617 bfd *file;
618 char **matching;
619
620 file = bfd_openr (filename, target);
621 if (file == NULL)
622 {
623 bfd_nonfatal (filename);
624 return false;
625 }
626
627 if (bfd_check_format (file, bfd_archive))
628 {
629 display_archive (file);
630 }
631 else if (bfd_check_format_matches (file, bfd_object, &matching))
632 {
633 (*format->print_object_filename) (filename);
634 display_rel_file (file, NULL);
635 }
636 else
637 {
638 bfd_nonfatal (filename);
639 if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
640 {
641 list_matching_formats (matching);
642 free (matching);
643 }
644 retval = false;
645 }
646
647 if (bfd_close (file) == false)
648 bfd_fatal (filename);
649
650 lineno_cache_bfd = NULL;
651 lineno_cache_rel_bfd = NULL;
652
653 return retval;
654}
655
656
657/* These globals are used to pass information into the sorting
658 routines. */
659static bfd *sort_bfd;
660static boolean sort_dynamic;
661static asymbol *sort_x;
662static asymbol *sort_y;
663
664/* Symbol-sorting predicates */
665#define valueof(x) ((x)->section->vma + (x)->value)
666
667/* Numeric sorts. Undefined symbols are always considered "less than"
668 defined symbols with zero values. Common symbols are not treated
669 specially -- i.e., their sizes are used as their "values". */
670
671static int
672numeric_forward (P_x, P_y)
673 const PTR P_x;
674 const PTR P_y;
675{
676 asymbol *x, *y;
677 asection *xs, *ys;
678
679 x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
680 y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
681 if (x == NULL || y == NULL)
682 bfd_fatal (bfd_get_filename (sort_bfd));
683
684 xs = bfd_get_section (x);
685 ys = bfd_get_section (y);
686
687 if (bfd_is_und_section (xs))
688 {
689 if (! bfd_is_und_section (ys))
690 return -1;
691 }
692 else if (bfd_is_und_section (ys))
693 return 1;
694 else if (valueof (x) != valueof (y))
695 return valueof (x) < valueof (y) ? -1 : 1;
696
697 return non_numeric_forward (P_x, P_y);
698}
699
700static int
701numeric_reverse (x, y)
702 const PTR x;
703 const PTR y;
704{
705 return - numeric_forward (x, y);
706}
707
708static int
709non_numeric_forward (P_x, P_y)
710 const PTR P_x;
711 const PTR P_y;
712{
713 asymbol *x, *y;
714 const char *xn, *yn;
715
716 x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
717 y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
718 if (x == NULL || y == NULL)
719 bfd_fatal (bfd_get_filename (sort_bfd));
720
721 xn = bfd_asymbol_name (x);
722 yn = bfd_asymbol_name (y);
723
724 return ((xn == NULL) ? ((yn == NULL) ? 0 : -1) :
725 ((yn == NULL) ? 1 : strcmp (xn, yn)));
726}
727
728static int
729non_numeric_reverse (x, y)
730 const PTR x;
731 const PTR y;
732{
733 return - non_numeric_forward (x, y);
734}
735
736static int (*(sorters[2][2])) PARAMS ((const PTR, const PTR)) =
737{
738 { non_numeric_forward, non_numeric_reverse },
739 { numeric_forward, numeric_reverse }
740};
741
742/* This sort routine is used by sort_symbols_by_size. It is similar
743 to numeric_forward, but when symbols have the same value it sorts
744 by section VMA. This simplifies the sort_symbols_by_size code
745 which handles symbols at the end of sections. Also, this routine
746 tries to sort file names before other symbols with the same value.
747 That will make the file name have a zero size, which will make
748 sort_symbols_by_size choose the non file name symbol, leading to
749 more meaningful output. For similar reasons, this code sorts
750 gnu_compiled_* and gcc2_compiled before other symbols with the same
751 value. */
752
753static int
754size_forward1 (P_x, P_y)
755 const PTR P_x;
756 const PTR P_y;
757{
758 asymbol *x, *y;
759 asection *xs, *ys;
760 const char *xn, *yn;
761 size_t xnl, ynl;
762 int xf, yf;
763
764 x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
765 y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
766 if (x == NULL || y == NULL)
767 bfd_fatal (bfd_get_filename (sort_bfd));
768
769 xs = bfd_get_section (x);
770 ys = bfd_get_section (y);
771
772 if (bfd_is_und_section (xs))
773 abort ();
774 if (bfd_is_und_section (ys))
775 abort ();
776
777 if (valueof (x) != valueof (y))
778 return valueof (x) < valueof (y) ? -1 : 1;
779
780 if (xs->vma != ys->vma)
781 return xs->vma < ys->vma ? -1 : 1;
782
783 xn = bfd_asymbol_name (x);
784 yn = bfd_asymbol_name (y);
785 xnl = strlen (xn);
786 ynl = strlen (yn);
787
788 /* The symbols gnu_compiled and gcc2_compiled convey even less
789 information than the file name, so sort them out first. */
790
791 xf = (strstr (xn, "gnu_compiled") != NULL
792 || strstr (xn, "gcc2_compiled") != NULL);
793 yf = (strstr (yn, "gnu_compiled") != NULL
794 || strstr (yn, "gcc2_compiled") != NULL);
795
796 if (xf && ! yf)
797 return -1;
798 if (! xf && yf)
799 return 1;
800
801 /* We use a heuristic for the file name. It may not work on non
802 Unix systems, but it doesn't really matter; the only difference
803 is precisely which symbol names get printed. */
804
805#define file_symbol(s, sn, snl) \
806 (((s)->flags & BSF_FILE) != 0 \
807 || ((sn)[(snl) - 2] == '.' \
808 && ((sn)[(snl) - 1] == 'o' \
809 || (sn)[(snl) - 1] == 'a')))
810
811 xf = file_symbol (x, xn, xnl);
812 yf = file_symbol (y, yn, ynl);
813
814 if (xf && ! yf)
815 return -1;
816 if (! xf && yf)
817 return 1;
818
819 return non_numeric_forward (P_x, P_y);
820}
821
822/* This sort routine is used by sort_symbols_by_size. It is sorting
823 an array of size_sym structures into size order. */
824
825static int
826size_forward2 (P_x, P_y)
827 const PTR P_x;
828 const PTR P_y;
829{
830 const struct size_sym *x = (const struct size_sym *) P_x;
831 const struct size_sym *y = (const struct size_sym *) P_y;
832
833 if (x->size < y->size)
834 return reverse_sort ? 1 : -1;
835 else if (x->size > y->size)
836 return reverse_sort ? -1 : 1;
837 else
838 return sorters[0][reverse_sort] (x->minisym, y->minisym);
839}
840
841/* Sort the symbols by size. We guess the size by assuming that the
842 difference between the address of a symbol and the address of the
843 next higher symbol is the size. FIXME: ELF actually stores a size
844 with each symbol. We should use it. */
845
846static long
847sort_symbols_by_size (abfd, dynamic, minisyms, symcount, size, symsizesp)
848 bfd *abfd;
849 boolean dynamic;
850 PTR minisyms;
851 long symcount;
852 unsigned int size;
853 struct size_sym **symsizesp;
854{
855 struct size_sym *symsizes;
856 bfd_byte *from, *fromend;
857 asymbol *sym = NULL;
858 asymbol *store_sym, *store_next;
859
860 qsort (minisyms, symcount, size, size_forward1);
861
862 /* We are going to return a special set of symbols and sizes to
863 print. */
864 symsizes = (struct size_sym *) xmalloc (symcount * sizeof (struct size_sym));
865 *symsizesp = symsizes;
866
867 /* Note that filter_symbols has already removed all absolute and
868 undefined symbols. Here we remove all symbols whose size winds
869 up as zero. */
870
871 from = (bfd_byte *) minisyms;
872 fromend = from + symcount * size;
873
874 store_sym = sort_x;
875 store_next = sort_y;
876
877 if (from < fromend)
878 {
879 sym = bfd_minisymbol_to_symbol (abfd, dynamic, (const PTR) from,
880 store_sym);
881 if (sym == NULL)
882 bfd_fatal (bfd_get_filename (abfd));
883 }
884
885 for (; from < fromend; from += size)
886 {
887 asymbol *next;
888 asection *sec;
889 bfd_vma sz;
890 asymbol *temp;
891
892 if (from + size < fromend)
893 {
894 next = bfd_minisymbol_to_symbol (abfd,
895 dynamic,
896 (const PTR) (from + size),
897 store_next);
898 if (next == NULL)
899 bfd_fatal (bfd_get_filename (abfd));
900 }
901 else
902 next = NULL;
903
904 sec = bfd_get_section (sym);
905
906 if (bfd_is_com_section (sec))
907 sz = sym->value;
908 else
909 {
910 if (from + size < fromend
911 && sec == bfd_get_section (next))
912 sz = valueof (next) - valueof (sym);
913 else
914 sz = (bfd_get_section_vma (abfd, sec)
915 + bfd_section_size (abfd, sec)
916 - valueof (sym));
917 }
918
919 if (sz != 0)
920 {
921 symsizes->minisym = (const PTR) from;
922 symsizes->size = sz;
923 ++symsizes;
924 }
925
926 sym = next;
927
928 temp = store_sym;
929 store_sym = store_next;
930 store_next = temp;
931 }
932
933 symcount = symsizes - *symsizesp;
934
935 /* We must now sort again by size. */
936 qsort ((PTR) *symsizesp, symcount, sizeof (struct size_sym), size_forward2);
937
938 return symcount;
939}
940
941
942/* If ARCHIVE_BFD is non-NULL, it is the archive containing ABFD. */
943
944static void
945display_rel_file (abfd, archive_bfd)
946 bfd *abfd;
947 bfd *archive_bfd;
948{
949 long symcount;
950 PTR minisyms;
951 unsigned int size;
952 struct size_sym *symsizes;
953
954 if (! dynamic)
955 {
956 if (!(bfd_get_file_flags (abfd) & HAS_SYMS))
957 {
958 non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
959 return;
960 }
961 }
962
963 symcount = bfd_read_minisymbols (abfd, dynamic, &minisyms, &size);
964 if (symcount < 0)
965 bfd_fatal (bfd_get_filename (abfd));
966
967 if (symcount == 0)
968 {
969 non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
970 return;
971 }
972
973 /* Discard the symbols we don't want to print.
974 It's OK to do this in place; we'll free the storage anyway
975 (after printing). */
976
977 symcount = filter_symbols (abfd, dynamic, minisyms, symcount, size);
978
979 symsizes = NULL;
980 if (! no_sort)
981 {
982 sort_bfd = abfd;
983 sort_dynamic = dynamic;
984 sort_x = bfd_make_empty_symbol (abfd);
985 sort_y = bfd_make_empty_symbol (abfd);
986 if (sort_x == NULL || sort_y == NULL)
987 bfd_fatal (bfd_get_filename (abfd));
988
989 if (! sort_by_size)
990 qsort (minisyms, symcount, size,
991 sorters[sort_numerically][reverse_sort]);
992 else
993 symcount = sort_symbols_by_size (abfd, dynamic, minisyms, symcount,
994 size, &symsizes);
995 }
996
997 if (! sort_by_size)
998 print_symbols (abfd, dynamic, minisyms, symcount, size, archive_bfd);
999 else
1000 print_size_symbols (abfd, dynamic, symsizes, symcount, archive_bfd);
1001
1002 free (minisyms);
1003}
1004
1005
1006/* Choose which symbol entries to print;
1007 compact them downward to get rid of the rest.
1008 Return the number of symbols to be printed. */
1009
1010static long
1011filter_symbols (abfd, dynamic, minisyms, symcount, size)
1012 bfd *abfd;
1013 boolean dynamic;
1014 PTR minisyms;
1015 long symcount;
1016 unsigned int size;
1017{
1018 bfd_byte *from, *fromend, *to;
1019 asymbol *store;
1020
1021 store = bfd_make_empty_symbol (abfd);
1022 if (store == NULL)
1023 bfd_fatal (bfd_get_filename (abfd));
1024
1025 from = (bfd_byte *) minisyms;
1026 fromend = from + symcount * size;
1027 to = (bfd_byte *) minisyms;
1028
1029 for (; from < fromend; from += size)
1030 {
1031 int keep = 0;
1032 asymbol *sym;
1033
1034 PROGRESS (1);
1035
1036 sym = bfd_minisymbol_to_symbol (abfd, dynamic, (const PTR) from, store);
1037 if (sym == NULL)
1038 bfd_fatal (bfd_get_filename (abfd));
1039
1040 if (undefined_only)
1041 keep = bfd_is_und_section (sym->section);
1042 else if (external_only)
1043 keep = ((sym->flags & BSF_GLOBAL) != 0
1044 || (sym->flags & BSF_WEAK) != 0
1045 || bfd_is_und_section (sym->section)
1046 || bfd_is_com_section (sym->section));
1047 else
1048 keep = 1;
1049
1050 if (keep
1051 && ! print_debug_syms
1052 && (sym->flags & BSF_DEBUGGING) != 0)
1053 keep = 0;
1054
1055 if (keep
1056 && sort_by_size
1057 && (bfd_is_abs_section (sym->section)
1058 || bfd_is_und_section (sym->section)))
1059 keep = 0;
1060
1061 if (keep
1062 && defined_only)
1063 {
1064 if (bfd_is_und_section (sym->section))
1065 keep = 0;
1066 }
1067
1068 if (keep)
1069 {
1070 memcpy (to, from, size);
1071 to += size;
1072 }
1073 }
1074
1075 return (to - (bfd_byte *) minisyms) / size;
1076}
1077
1078
1079/* Print symbol name NAME, read from ABFD, with printf format FORMAT,
1080 demangling it if requested. */
1081
1082static void
1083print_symname (format, name, abfd)
1084 const char *format;
1085 const char *name;
1086 bfd *abfd;
1087{
1088 if (do_demangle && *name)
1089 {
1090 char *res;
1091
1092 /* In this mode, give a user-level view of the symbol name
1093 even if it's not mangled; strip off any leading
1094 underscore. */
1095 if (bfd_get_symbol_leading_char (abfd) == name[0])
1096 name++;
1097
1098 res = cplus_demangle (name, DMGL_ANSI | DMGL_PARAMS);
1099 if (res)
1100 {
1101 printf (format, res);
1102 free (res);
1103 return;
1104 }
1105 }
1106
1107 printf (format, name);
1108}
1109
1110/* Print the symbols. If ARCHIVE_BFD is non-NULL, it is the archive
1111 containing ABFD. */
1112
1113static void
1114print_symbols (abfd, dynamic, minisyms, symcount, size, archive_bfd)
1115 bfd *abfd;
1116 boolean dynamic;
1117 PTR minisyms;
1118 long symcount;
1119 unsigned int size;
1120 bfd *archive_bfd;
1121{
1122 asymbol *store;
1123 bfd_byte *from, *fromend;
1124
1125 store = bfd_make_empty_symbol (abfd);
1126 if (store == NULL)
1127 bfd_fatal (bfd_get_filename (abfd));
1128
1129 from = (bfd_byte *) minisyms;
1130 fromend = from + symcount * size;
1131 for (; from < fromend; from += size)
1132 {
1133 asymbol *sym;
1134
1135 sym = bfd_minisymbol_to_symbol (abfd, dynamic, from, store);
1136 if (sym == NULL)
1137 bfd_fatal (bfd_get_filename (abfd));
1138
1139 print_symbol (abfd, sym, archive_bfd);
1140 }
1141}
1142
1143/* Print the symbols when sorting by size. */
1144
1145static void
1146print_size_symbols (abfd, dynamic, symsizes, symcount, archive_bfd)
1147 bfd *abfd;
1148 boolean dynamic;
1149 struct size_sym *symsizes;
1150 long symcount;
1151 bfd *archive_bfd;
1152{
1153 asymbol *store;
1154 struct size_sym *from, *fromend;
1155
1156 store = bfd_make_empty_symbol (abfd);
1157 if (store == NULL)
1158 bfd_fatal (bfd_get_filename (abfd));
1159
1160 from = symsizes;
1161 fromend = from + symcount;
1162 for (; from < fromend; from++)
1163 {
1164 asymbol *sym;
1165
1166 sym = bfd_minisymbol_to_symbol (abfd, dynamic, from->minisym, store);
1167 if (sym == NULL)
1168 bfd_fatal (bfd_get_filename (abfd));
1169
1170 /* Set the symbol value so that we actually display the symbol
1171 size. */
1172 sym->value = from->size - bfd_section_vma (abfd, bfd_get_section (sym));
1173
1174 print_symbol (abfd, sym, archive_bfd);
1175 }
1176}
1177
1178/* Print a single symbol. */
1179
1180static void
1181print_symbol (abfd, sym, archive_bfd)
1182 bfd *abfd;
1183 asymbol *sym;
1184 bfd *archive_bfd;
1185{
1186 PROGRESS (1);
1187
1188 (*format->print_symbol_filename) (archive_bfd, abfd);
1189
1190 if (undefined_only)
1191 {
1192 if (bfd_is_und_section (bfd_get_section (sym)))
1193 print_symname ("%s", bfd_asymbol_name (sym), abfd);
1194 }
1195 else
1196 {
1197 symbol_info syminfo;
1198
1199 bfd_get_symbol_info (abfd, sym, &syminfo);
1200 (*format->print_symbol_info) (&syminfo, abfd);
1201 }
1202
1203 if (line_numbers)
1204 {
1205 static asymbol **syms;
1206 static long symcount;
1207 const char *filename, *functionname;
1208 unsigned int lineno;
1209
1210 /* We need to get the canonical symbols in order to call
1211 bfd_find_nearest_line. This is inefficient, but, then, you
1212 don't have to use --line-numbers. */
1213 if (abfd != lineno_cache_bfd && syms != NULL)
1214 {
1215 free (syms);
1216 syms = NULL;
1217 }
1218 if (syms == NULL)
1219 {
1220 long symsize;
1221
1222 symsize = bfd_get_symtab_upper_bound (abfd);
1223 if (symsize < 0)
1224 bfd_fatal (bfd_get_filename (abfd));
1225 syms = (asymbol **) xmalloc (symsize);
1226 symcount = bfd_canonicalize_symtab (abfd, syms);
1227 if (symcount < 0)
1228 bfd_fatal (bfd_get_filename (abfd));
1229 lineno_cache_bfd = abfd;
1230 }
1231
1232 if (bfd_is_und_section (bfd_get_section (sym)))
1233 {
1234 static asection **secs;
1235 static arelent ***relocs;
1236 static long *relcount;
1237 static unsigned int seccount;
1238 unsigned int i;
1239 const char *symname;
1240
1241 /* For an undefined symbol, we try to find a reloc for the
1242 symbol, and print the line number of the reloc. */
1243
1244 if (abfd != lineno_cache_rel_bfd && relocs != NULL)
1245 {
1246 for (i = 0; i < seccount; i++)
1247 if (relocs[i] != NULL)
1248 free (relocs[i]);
1249 free (secs);
1250 free (relocs);
1251 free (relcount);
1252 secs = NULL;
1253 relocs = NULL;
1254 relcount = NULL;
1255 }
1256
1257 if (relocs == NULL)
1258 {
1259 struct get_relocs_info info;
1260
1261 seccount = bfd_count_sections (abfd);
1262
1263 secs = (asection **) xmalloc (seccount * sizeof *secs);
1264 relocs = (arelent ***) xmalloc (seccount * sizeof *relocs);
1265 relcount = (long *) xmalloc (seccount * sizeof *relcount);
1266
1267 info.secs = secs;
1268 info.relocs = relocs;
1269 info.relcount = relcount;
1270 info.syms = syms;
1271 bfd_map_over_sections (abfd, get_relocs, (PTR) &info);
1272 lineno_cache_rel_bfd = abfd;
1273 }
1274
1275 symname = bfd_asymbol_name (sym);
1276 for (i = 0; i < seccount; i++)
1277 {
1278 long j;
1279
1280 for (j = 0; j < relcount[i]; j++)
1281 {
1282 arelent *r;
1283
1284 r = relocs[i][j];
1285 if (r->sym_ptr_ptr != NULL
1286 && (*r->sym_ptr_ptr)->section == sym->section
1287 && (*r->sym_ptr_ptr)->value == sym->value
1288 && strcmp (symname,
1289 bfd_asymbol_name (*r->sym_ptr_ptr)) == 0
1290 && bfd_find_nearest_line (abfd, secs[i], syms,
1291 r->address, &filename,
1292 &functionname, &lineno))
1293 {
1294 /* We only print the first one we find. */
1295 printf ("\t%s:%u", filename, lineno);
1296 i = seccount;
1297 break;
1298 }
1299 }
1300 }
1301 }
1302 else if (bfd_get_section (sym)->owner == abfd)
1303 {
1304 if (bfd_find_nearest_line (abfd, bfd_get_section (sym), syms,
1305 sym->value, &filename, &functionname,
1306 &lineno)
1307 && filename != NULL
1308 && lineno != 0)
1309 {
1310 printf ("\t%s:%u", filename, lineno);
1311 }
1312 }
1313 }
1314
1315 putchar ('\n');
1316}
1317
1318
1319/* The following 3 groups of functions are called unconditionally,
1320 once at the start of processing each file of the appropriate type.
1321 They should check `filename_per_file' and `filename_per_symbol',
1322 as appropriate for their output format, to determine whether to
1323 print anything. */
1324
1325
1326/* Print the name of an object file given on the command line. */
1327
1328static void
1329print_object_filename_bsd (filename)
1330 char *filename;
1331{
1332 if (filename_per_file && !filename_per_symbol)
1333 printf ("\n%s:\n", filename);
1334}
1335
1336static void
1337print_object_filename_sysv (filename)
1338 char *filename;
1339{
1340 if (undefined_only)
1341 printf (_("\n\nUndefined symbols from %s:\n\n"), filename);
1342 else
1343 printf (_("\n\nSymbols from %s:\n\n"), filename);
1344 printf (_("\
1345Name Value Class Type Size Line Section\n\n"));
1346}
1347
1348static void
1349print_object_filename_posix (filename)
1350 char *filename;
1351{
1352 if (filename_per_file && !filename_per_symbol)
1353 printf ("%s:\n", filename);
1354}
1355
1356
1357/* Print the name of an archive file given on the command line. */
1358
1359static void
1360print_archive_filename_bsd (filename)
1361 char *filename;
1362{
1363 if (filename_per_file)
1364 printf ("\n%s:\n", filename);
1365}
1366
1367static void
1368print_archive_filename_sysv (filename)
1369 char *filename ATTRIBUTE_UNUSED;
1370{
1371}
1372
1373static void
1374print_archive_filename_posix (filename)
1375 char *filename ATTRIBUTE_UNUSED;
1376{
1377}
1378
1379
1380/* Print the name of an archive member file. */
1381
1382static void
1383print_archive_member_bsd (archive, filename)
1384 char *archive ATTRIBUTE_UNUSED;
1385 CONST char *filename;
1386{
1387 if (!filename_per_symbol)
1388 printf ("\n%s:\n", filename);
1389}
1390
1391static void
1392print_archive_member_sysv (archive, filename)
1393 char *archive;
1394 CONST char *filename;
1395{
1396 if (undefined_only)
1397 printf (_("\n\nUndefined symbols from %s[%s]:\n\n"), archive, filename);
1398 else
1399 printf (_("\n\nSymbols from %s[%s]:\n\n"), archive, filename);
1400 printf (_("\
1401Name Value Class Type Size Line Section\n\n"));
1402}
1403
1404static void
1405print_archive_member_posix (archive, filename)
1406 char *archive;
1407 CONST char *filename;
1408{
1409 if (!filename_per_symbol)
1410 printf ("%s[%s]:\n", archive, filename);
1411}
1412
1413
1414/* Print the name of the file (and archive, if there is one)
1415 containing a symbol. */
1416
1417static void
1418print_symbol_filename_bsd (archive_bfd, abfd)
1419 bfd *archive_bfd, *abfd;
1420{
1421 if (filename_per_symbol)
1422 {
1423 if (archive_bfd)
1424 printf ("%s:", bfd_get_filename (archive_bfd));
1425 printf ("%s:", bfd_get_filename (abfd));
1426 }
1427}
1428
1429static void
1430print_symbol_filename_sysv (archive_bfd, abfd)
1431 bfd *archive_bfd, *abfd;
1432{
1433 if (filename_per_symbol)
1434 {
1435 if (archive_bfd)
1436 printf ("%s:", bfd_get_filename (archive_bfd));
1437 printf ("%s:", bfd_get_filename (abfd));
1438 }
1439}
1440
1441static void
1442print_symbol_filename_posix (archive_bfd, abfd)
1443 bfd *archive_bfd, *abfd;
1444{
1445 if (filename_per_symbol)
1446 {
1447 if (archive_bfd)
1448 printf ("%s[%s]: ", bfd_get_filename (archive_bfd),
1449 bfd_get_filename (abfd));
1450 else
1451 printf ("%s: ", bfd_get_filename (abfd));
1452 }
1453}
1454
1455
1456/* Print a symbol value. */
1457
1458static void
1459print_value (val)
1460 bfd_vma val;
1461{
1462#if ! defined (BFD64) || BFD_HOST_64BIT_LONG
1463 printf (value_format, val);
1464#else
1465 /* We have a 64 bit value to print, but the host is only 32 bit. */
1466 if (print_radix == 16)
1467 fprintf_vma (stdout, val);
1468 else
1469 {
1470 char buf[30];
1471 char *s;
1472
1473 s = buf + sizeof buf;
1474 *--s = '\0';
1475 while (val > 0)
1476 {
1477 *--s = (val % print_radix) + '0';
1478 val /= print_radix;
1479 }
1480 while ((buf + sizeof buf - 1) - s < 16)
1481 *--s = '0';
1482 printf ("%s", s);
1483 }
1484#endif
1485}
1486
1487/* Print a line of information about a symbol. */
1488
1489static void
1490print_symbol_info_bsd (info, abfd)
1491 symbol_info *info;
1492 bfd *abfd;
1493{
1494 if (bfd_is_undefined_symclass (info->type))
1495 {
1496#ifdef BFD64
1497 printf (" ");
1498#endif
1499 printf (" ");
1500 }
1501 else
1502 print_value (info->value);
1503 printf (" %c", info->type);
1504 if (info->type == '-')
1505 {
1506 /* A stab. */
1507 printf (" ");
1508 printf (other_format, info->stab_other);
1509 printf (" ");
1510 printf (desc_format, info->stab_desc);
1511 printf (" %5s", info->stab_name);
1512 }
1513 print_symname (" %s", info->name, abfd);
1514}
1515
1516static void
1517print_symbol_info_sysv (info, abfd)
1518 symbol_info *info;
1519 bfd *abfd;
1520{
1521 print_symname ("%-20s|", info->name, abfd); /* Name */
1522 if (bfd_is_undefined_symclass (info->type))
1523 printf (" "); /* Value */
1524 else
1525 print_value (info->value);
1526 printf ("| %c |", info->type); /* Class */
1527 if (info->type == '-')
1528 {
1529 /* A stab. */
1530 printf ("%18s| ", info->stab_name); /* (C) Type */
1531 printf (desc_format, info->stab_desc); /* Size */
1532 printf ("| |"); /* Line, Section */
1533 }
1534 else
1535 printf (" | | |"); /* Type, Size, Line, Section */
1536}
1537
1538static void
1539print_symbol_info_posix (info, abfd)
1540 symbol_info *info;
1541 bfd *abfd;
1542{
1543 print_symname ("%s ", info->name, abfd);
1544 printf ("%c ", info->type);
1545 if (bfd_is_undefined_symclass (info->type))
1546 printf (" ");
1547 else
1548 print_value (info->value);
1549 /* POSIX.2 wants the symbol size printed here, when applicable;
1550 BFD currently doesn't provide it, so we take the easy way out by
1551 considering it to never be applicable. */
1552}
1553
1554
1555static void
1556print_symdef_entry (abfd)
1557 bfd *abfd;
1558{
1559 symindex idx = BFD_NO_MORE_SYMBOLS;
1560 carsym *thesym;
1561 boolean everprinted = false;
1562
1563 for (idx = bfd_get_next_mapent (abfd, idx, &thesym);
1564 idx != BFD_NO_MORE_SYMBOLS;
1565 idx = bfd_get_next_mapent (abfd, idx, &thesym))
1566 {
1567 bfd *elt;
1568 if (!everprinted)
1569 {
1570 printf (_("\nArchive index:\n"));
1571 everprinted = true;
1572 }
1573 elt = bfd_get_elt_at_index (abfd, idx);
1574 if (elt == NULL)
1575 bfd_fatal ("bfd_get_elt_at_index");
1576 if (thesym->name != (char *) NULL)
1577 {
1578 print_symname ("%s", thesym->name, abfd);
1579 printf (" in %s\n", bfd_get_filename (elt));
1580 }
1581 }
1582}
1583
1584
1585/* This function is used to get the relocs for a particular section.
1586 It is called via bfd_map_over_sections. */
1587
1588static void
1589get_relocs (abfd, sec, dataarg)
1590 bfd *abfd;
1591 asection *sec;
1592 PTR dataarg;
1593{
1594 struct get_relocs_info *data = (struct get_relocs_info *) dataarg;
1595
1596 *data->secs = sec;
1597
1598 if ((sec->flags & SEC_RELOC) == 0)
1599 {
1600 *data->relocs = NULL;
1601 *data->relcount = 0;
1602 }
1603 else
1604 {
1605 long relsize;
1606
1607 relsize = bfd_get_reloc_upper_bound (abfd, sec);
1608 if (relsize < 0)
1609 bfd_fatal (bfd_get_filename (abfd));
1610
1611 *data->relocs = (arelent **) xmalloc (relsize);
1612 *data->relcount = bfd_canonicalize_reloc (abfd, sec, *data->relocs,
1613 data->syms);
1614 if (*data->relcount < 0)
1615 bfd_fatal (bfd_get_filename (abfd));
1616 }
1617
1618 ++data->secs;
1619 ++data->relocs;
1620 ++data->relcount;
1621}
Note: See TracBrowser for help on using the repository browser.