• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Print size information from ELF file.
2    Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc.
3    This file is part of Red Hat elfutils.
4    Written by Ulrich Drepper <drepper@redhat.com>, 2000.
5 
6    Red Hat elfutils is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by the
8    Free Software Foundation; version 2 of the License.
9 
10    Red Hat elfutils is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License along
16    with Red Hat elfutils; if not, write to the Free Software Foundation,
17    Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
18 
19    Red Hat elfutils is an included package of the Open Invention Network.
20    An included package of the Open Invention Network is a package for which
21    Open Invention Network licensees cross-license their patents.  No patent
22    license is granted, either expressly or impliedly, by designation as an
23    included package.  Should you wish to participate in the Open Invention
24    Network licensing program, please visit www.openinventionnetwork.com
25    <http://www.openinventionnetwork.com>.  */
26 
27 #ifdef HAVE_CONFIG_H
28 # include <config.h>
29 #endif
30 
31 #include <argp.h>
32 #include <error.h>
33 #include <fcntl.h>
34 #include <gelf.h>
35 #include <inttypes.h>
36 #include <libelf.h>
37 #include <libintl.h>
38 #include <locale.h>
39 #include <mcheck.h>
40 #include <stdbool.h>
41 #include <stdio.h>
42 #include <stdio_ext.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46 #include <sys/param.h>
47 
48 #include <system.h>
49 
50 
51 /* Name and version of program.  */
52 static void print_version (FILE *stream, struct argp_state *state);
53 void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
54 
55 /* Bug report address.  */
56 const char *argp_program_bug_address = PACKAGE_BUGREPORT;
57 
58 
59 /* Values for the parameters which have no short form.  */
60 #define OPT_FORMAT	0x100
61 #define OPT_RADIX	0x101
62 
63 /* Definitions of arguments for argp functions.  */
64 static const struct argp_option options[] =
65 {
66   { NULL, 0, NULL, 0, N_("Output format:"), 0 },
67   { "format", OPT_FORMAT, "FORMAT", 0,
68     N_("Use the output format FORMAT.  FORMAT can be `bsd' or `sysv'.  "
69        "The default is `bsd'"), 0 },
70   { NULL, 'A', NULL, 0, N_("Same as `--format=sysv'"), 0 },
71   { NULL, 'B', NULL, 0, N_("Same as `--format=bsd'"), 0 },
72   { "radix", OPT_RADIX, "RADIX", 0, N_("Use RADIX for printing symbol values"),
73     0},
74   { NULL, 'd', NULL, 0, N_("Same as `--radix=10'"), 0 },
75   { NULL, 'o', NULL, 0, N_("Same as `--radix=8'"), 0 },
76   { NULL, 'x', NULL, 0, N_("Same as `--radix=16'"), 0 },
77   { NULL, 'f', NULL, 0,
78     N_("Similar to `--format=sysv' output but in one line"), 0 },
79 
80   { NULL, 0, NULL, 0, N_("Output options:"), 0 },
81   { NULL, 'F', NULL, 0,
82     N_("Print size and permission flags for loadable segments"), 0 },
83   { "totals", 't', NULL, 0, N_("Display the total sizes (bsd only)"), 0 },
84   { NULL, 0, NULL, 0, NULL, 0 }
85 };
86 
87 /* Short description of program.  */
88 static const char doc[] = N_("\
89 List section sizes of FILEs (a.out by default).");
90 
91 /* Strings for arguments in help texts.  */
92 static const char args_doc[] = N_("[FILE...]");
93 
94 /* Prototype for option handler.  */
95 static error_t parse_opt (int key, char *arg, struct argp_state *state);
96 
97 /* Data structure to communicate with argp functions.  */
98 static struct argp argp =
99 {
100   options, parse_opt, args_doc, doc, NULL, NULL, NULL
101 };
102 
103 
104 /* Print symbols in file named FNAME.  */
105 static int process_file (const char *fname);
106 
107 /* Handle content of archive.  */
108 static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname);
109 
110 /* Handle ELF file.  */
111 static void handle_elf (Elf *elf, const char *fullname, const char *fname);
112 
113 /* Show total size.  */
114 static void show_bsd_totals (void);
115 
116 #define INTERNAL_ERROR(fname) \
117   error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s-%s): %s"),      \
118 	 fname, __LINE__, PACKAGE_VERSION, __DATE__, elf_errmsg (-1))
119 
120 
121 /* User-selectable options.  */
122 
123 /* The selected output format.  */
124 static enum
125 {
126   format_bsd = 0,
127   format_sysv,
128   format_sysv_one_line,
129   format_segments
130 } format;
131 
132 /* Radix for printed numbers.  */
133 static enum
134 {
135   radix_decimal = 0,
136   radix_hex,
137   radix_octal
138 } radix;
139 
140 
141 /* Mapping of radix and binary class to length.  */
142 static const int length_map[2][3] =
143 {
144   [ELFCLASS32 - 1] =
145   {
146     [radix_hex] = 8,
147     [radix_decimal] = 10,
148     [radix_octal] = 11
149   },
150   [ELFCLASS64 - 1] =
151   {
152     [radix_hex] = 16,
153     [radix_decimal] = 20,
154     [radix_octal] = 22
155   }
156 };
157 
158 /* True if total sizes should be printed.  */
159 static bool totals;
160 /* To print the total sizes in a reasonable format remember the higest
161    "class" of ELF binaries processed.  */
162 static int totals_class;
163 
164 
165 int
main(int argc,char * argv[])166 main (int argc, char *argv[])
167 {
168   int remaining;
169   int result = 0;
170 
171   /* Make memory leak detection possible.  */
172   mtrace ();
173 
174   /* We use no threads here which can interfere with handling a stream.  */
175   __fsetlocking (stdin, FSETLOCKING_BYCALLER);
176   __fsetlocking (stdout, FSETLOCKING_BYCALLER);
177   __fsetlocking (stderr, FSETLOCKING_BYCALLER);
178 
179   /* Set locale.  */
180   setlocale (LC_ALL, "");
181 
182   /* Make sure the message catalog can be found.  */
183   bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
184 
185   /* Initialize the message catalog.  */
186   textdomain (PACKAGE_TARNAME);
187 
188   /* Parse and process arguments.  */
189   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
190 
191 
192   /* Tell the library which version we are expecting.  */
193   elf_version (EV_CURRENT);
194 
195   if (remaining == argc)
196     /* The user didn't specify a name so we use a.out.  */
197     result = process_file ("a.out");
198   else
199     /* Process all the remaining files.  */
200     do
201       result |= process_file (argv[remaining]);
202     while (++remaining < argc);
203 
204   /* Print the total sizes but only if the output format is BSD and at
205      least one file has been correctly read (i.e., we recognized the
206      class).  */
207   if (totals && format == format_bsd && totals_class != 0)
208     show_bsd_totals ();
209 
210   return result;
211 }
212 
213 
214 /* Print the version information.  */
215 static void
print_version(FILE * stream,struct argp_state * state)216 print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
217 {
218   fprintf (stream, "size (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
219   fprintf (stream, gettext ("\
220 Copyright (C) %s Red Hat, Inc.\n\
221 This is free software; see the source for copying conditions.  There is NO\n\
222 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
223 "), "2008");
224   fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
225 }
226 
227 
228 /* Handle program arguments.  */
229 static error_t
parse_opt(int key,char * arg,struct argp_state * state)230 parse_opt (int key, char *arg,
231 	   struct argp_state *state __attribute__ ((unused)))
232 {
233   switch (key)
234     {
235     case 'd':
236       radix = radix_decimal;
237       break;
238 
239     case 'f':
240       format = format_sysv_one_line;
241       break;
242 
243     case 'o':
244       radix = radix_octal;
245       break;
246 
247     case 'x':
248       radix = radix_hex;
249       break;
250 
251     case 'A':
252       format = format_sysv;
253       break;
254 
255     case 'B':
256       format = format_bsd;
257       break;
258 
259     case 'F':
260       format = format_segments;
261       break;
262 
263     case OPT_FORMAT:
264       if (strcmp (arg, "bsd") == 0 || strcmp (arg, "berkeley") == 0)
265 	format = format_bsd;
266       else if (likely (strcmp (arg, "sysv") == 0))
267 	format = format_sysv;
268       else
269 	error (EXIT_FAILURE, 0, gettext ("Invalid format: %s"), arg);
270       break;
271 
272     case OPT_RADIX:
273       if (strcmp (arg, "x") == 0 || strcmp (arg, "16") == 0)
274 	radix = radix_hex;
275       else if (strcmp (arg, "d") == 0 || strcmp (arg, "10") == 0)
276 	radix = radix_decimal;
277       else if (strcmp (arg, "o") == 0 || strcmp (arg, "8") == 0)
278 	radix = radix_octal;
279       else
280 	error (EXIT_FAILURE, 0, gettext ("Invalid radix: %s"), arg);
281       break;
282 
283     case 't':
284       totals = true;
285       break;
286 
287     default:
288       return ARGP_ERR_UNKNOWN;
289     }
290   return 0;
291 }
292 
293 
294 /* Open the file and determine the type.  */
295 static int
process_file(const char * fname)296 process_file (const char *fname)
297 {
298   int fd = open (fname, O_RDONLY);
299   if (unlikely (fd == -1))
300     {
301       error (0, errno, gettext ("cannot open '%s'"), fname);
302       return 1;
303     }
304 
305   /* Now get the ELF descriptor.  */
306   Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
307   if (likely (elf != NULL))
308     {
309       if (elf_kind (elf) == ELF_K_ELF)
310 	{
311 	  handle_elf (elf, NULL, fname);
312 
313 	  if (unlikely (elf_end (elf) != 0))
314 	    INTERNAL_ERROR (fname);
315 
316 	  if (unlikely (close (fd) != 0))
317 	    error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname);
318 
319 	  return 0;
320 	}
321       else if (likely (elf_kind (elf) == ELF_K_AR))
322 	return handle_ar (fd, elf, NULL, fname);
323 
324       /* We cannot handle this type.  Close the descriptor anyway.  */
325       if (unlikely (elf_end (elf) != 0))
326 	INTERNAL_ERROR (fname);
327     }
328 
329   error (0, 0, gettext ("%s: file format not recognized"), fname);
330 
331   return 1;
332 }
333 
334 
335 /* Print the BSD-style header.  This is done exactly once.  */
336 static void
print_header(Elf * elf)337 print_header (Elf *elf)
338 {
339   static int done;
340 
341   if (! done)
342     {
343       int ddigits = length_map[gelf_getclass (elf) - 1][radix_decimal];
344       int xdigits = length_map[gelf_getclass (elf) - 1][radix_hex];
345 
346       printf ("%*s %*s %*s %*s %*s %s\n",
347 	      ddigits - 2, sgettext ("bsd|text"),
348 	      ddigits - 2, sgettext ("bsd|data"),
349 	      ddigits - 2, sgettext ("bsd|bss"),
350 	      ddigits - 2, sgettext ("bsd|dec"),
351 	      xdigits - 2, sgettext ("bsd|hex"),
352 	      sgettext ("bsd|filename"));
353 
354       done = 1;
355     }
356 }
357 
358 
359 static int
handle_ar(int fd,Elf * elf,const char * prefix,const char * fname)360 handle_ar (int fd, Elf *elf, const char *prefix, const char *fname)
361 {
362   size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
363   size_t fname_len = strlen (fname) + 1;
364   char new_prefix[prefix_len + 1 + fname_len];
365   char *cp = new_prefix;
366 
367   /* Create the full name of the file.  */
368   if (prefix != NULL)
369     {
370       cp = mempcpy (cp, prefix, prefix_len);
371       *cp++ = ':';
372     }
373   memcpy (cp, fname, fname_len);
374 
375   /* Process all the files contained in the archive.  */
376   int result = 0;
377   Elf *subelf;
378   Elf_Cmd cmd = ELF_C_READ_MMAP;
379   while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
380     {
381       /* The the header for this element.  */
382       Elf_Arhdr *arhdr = elf_getarhdr (subelf);
383 
384       if (elf_kind (subelf) == ELF_K_ELF)
385 	handle_elf (subelf, new_prefix, arhdr->ar_name);
386       else if (likely (elf_kind (subelf) == ELF_K_AR))
387 	result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name);
388       /* else signal error??? */
389 
390       /* Get next archive element.  */
391       cmd = elf_next (subelf);
392       if (unlikely (elf_end (subelf) != 0))
393 	INTERNAL_ERROR (fname);
394     }
395 
396   if (unlikely (elf_end (elf) != 0))
397     INTERNAL_ERROR (fname);
398 
399   if (unlikely  (close (fd) != 0))
400     error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname);
401 
402   return result;
403 }
404 
405 
406 /* Show sizes in SysV format.  */
407 static void
show_sysv(Elf * elf,const char * prefix,const char * fname,const char * fullname)408 show_sysv (Elf *elf, const char *prefix, const char *fname,
409 	   const char *fullname)
410 {
411   int maxlen = 10;
412   const int digits = length_map[gelf_getclass (elf) - 1][radix];
413 
414   /* Get the section header string table index.  */
415   size_t shstrndx;
416   if (unlikely (elf_getshstrndx (elf, &shstrndx) < 0))
417     error (EXIT_FAILURE, 0,
418 	   gettext ("cannot get section header string table index"));
419 
420   /* First round over the sections: determine the longest section name.  */
421   Elf_Scn *scn = NULL;
422   while ((scn = elf_nextscn (elf, scn)) != NULL)
423     {
424       GElf_Shdr shdr_mem;
425       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
426 
427       if (shdr == NULL)
428 	INTERNAL_ERROR (fullname);
429 
430       /* Ignore all sections which are not used at runtime.  */
431       if ((shdr->sh_flags & SHF_ALLOC) != 0)
432 	maxlen = MAX (maxlen,
433 		      (int) strlen (elf_strptr (elf, shstrndx,
434 						shdr->sh_name)));
435     }
436 
437   fputs_unlocked (fname, stdout);
438   if (prefix != NULL)
439     printf (gettext (" (ex %s)"), prefix);
440   printf (":\n%-*s %*s %*s\n",
441 	  maxlen, sgettext ("sysv|section"),
442 	  digits - 2, sgettext ("sysv|size"),
443 	  digits, sgettext ("sysv|addr"));
444 
445   const char *fmtstr;
446   if (radix == radix_hex)
447     fmtstr = "%-*s %*" PRIx64 " %*" PRIx64 "\n";
448   else if (radix == radix_decimal)
449     fmtstr = "%-*s %*" PRId64 " %*" PRId64 "\n";
450   else
451     fmtstr = "%-*s %*" PRIo64 " %*" PRIo64 "\n";
452 
453   /* Iterate over all sections.  */
454   GElf_Off total = 0;
455   while ((scn = elf_nextscn (elf, scn)) != NULL)
456     {
457       GElf_Shdr shdr_mem;
458       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
459 
460       /* Ignore all sections which are not used at runtime.  */
461       if ((shdr->sh_flags & SHF_ALLOC) != 0)
462 	{
463 	  printf (fmtstr,
464 		  maxlen, elf_strptr (elf, shstrndx, shdr->sh_name),
465 		  digits - 2, shdr->sh_size,
466 		  digits, shdr->sh_addr);
467 
468 	  total += shdr->sh_size;
469 	}
470     }
471 
472   if (radix == radix_hex)
473     printf ("%-*s %*" PRIx64 "\n\n\n", maxlen, sgettext ("sysv|Total"),
474 	    digits - 2, total);
475   else if (radix == radix_decimal)
476     printf ("%-*s %*" PRId64 "\n\n\n", maxlen, sgettext ("sysv|Total"),
477 	    digits - 2, total);
478   else
479     printf ("%-*s %*" PRIo64 "\n\n\n", maxlen, sgettext ("sysv|Total"),
480 	    digits - 2, total);
481 }
482 
483 
484 /* Show sizes in SysV format in one line.  */
485 static void
show_sysv_one_line(Elf * elf)486 show_sysv_one_line (Elf *elf)
487 {
488   /* Get the section header string table index.  */
489   size_t shstrndx;
490   if (unlikely (elf_getshstrndx (elf, &shstrndx) < 0))
491     error (EXIT_FAILURE, 0,
492 	   gettext ("cannot get section header string table index"));
493 
494   const char *fmtstr;
495   if (radix == radix_hex)
496     fmtstr = "%" PRIx64 "(%s)";
497   else if (radix == radix_decimal)
498     fmtstr = "%" PRId64 "(%s)";
499   else
500     fmtstr = "%" PRIo64 "(%s)";
501 
502   /* Iterate over all sections.  */
503   GElf_Off total = 0;
504   bool first = true;
505   Elf_Scn *scn = NULL;
506   while ((scn = elf_nextscn (elf, scn)) != NULL)
507     {
508       GElf_Shdr shdr_mem;
509       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
510 
511       /* Ignore all sections which are not used at runtime.  */
512       if ((shdr->sh_flags & SHF_ALLOC) == 0)
513 	continue;
514 
515       if (! first)
516 	fputs_unlocked (" + ", stdout);
517       first = false;
518 
519       printf (fmtstr, shdr->sh_size,
520 	      elf_strptr (elf, shstrndx, shdr->sh_name));
521 
522       total += shdr->sh_size;
523     }
524 
525   if (radix == radix_hex)
526     printf (" = %#" PRIx64 "\n", total);
527   else if (radix == radix_decimal)
528     printf (" = %" PRId64 "\n", total);
529   else
530     printf (" = %" PRIo64 "\n", total);
531 }
532 
533 
534 /* Variables to add up the sizes of all files.  */
535 static uintmax_t total_textsize;
536 static uintmax_t total_datasize;
537 static uintmax_t total_bsssize;
538 
539 
540 /* Show sizes in BSD format.  */
541 static void
show_bsd(Elf * elf,const char * prefix,const char * fname,const char * fullname)542 show_bsd (Elf *elf, const char *prefix, const char *fname,
543 	  const char *fullname)
544 {
545   GElf_Off textsize = 0;
546   GElf_Off datasize = 0;
547   GElf_Off bsssize = 0;
548   const int ddigits = length_map[gelf_getclass (elf) - 1][radix_decimal];
549   const int xdigits = length_map[gelf_getclass (elf) - 1][radix_hex];
550 
551   /* Iterate over all sections.  */
552   Elf_Scn *scn = NULL;
553   while ((scn = elf_nextscn (elf, scn)) != NULL)
554     {
555       GElf_Shdr shdr_mem;
556       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
557 
558       if (shdr == NULL)
559 	INTERNAL_ERROR (fullname);
560 
561       /* Ignore all sections which are not marked as loaded.  */
562       if ((shdr->sh_flags & SHF_ALLOC) == 0)
563 	continue;
564 
565       if ((shdr->sh_flags & SHF_WRITE) == 0)
566 	textsize += shdr->sh_size;
567       else if (shdr->sh_type == SHT_NOBITS)
568 	bsssize += shdr->sh_size;
569       else
570 	datasize += shdr->sh_size;
571     }
572 
573   printf ("%*" PRId64 " %*" PRId64 " %*" PRId64 " %*" PRId64 " %*"
574 	  PRIx64 " %s",
575 	  ddigits - 2, textsize,
576 	  ddigits - 2, datasize,
577 	  ddigits - 2, bsssize,
578 	  ddigits - 2, textsize + datasize + bsssize,
579 	  xdigits - 2, textsize + datasize + bsssize,
580 	  fname);
581   if (prefix != NULL)
582     printf (gettext (" (ex %s)"), prefix);
583   fputs_unlocked ("\n", stdout);
584 
585   total_textsize += textsize;
586   total_datasize += datasize;
587   total_bsssize += bsssize;
588 
589   totals_class = MAX (totals_class, gelf_getclass (elf));
590 }
591 
592 
593 /* Show total size.  */
594 static void
show_bsd_totals(void)595 show_bsd_totals (void)
596 {
597   int ddigits = length_map[totals_class - 1][radix_decimal];
598   int xdigits = length_map[totals_class - 1][radix_hex];
599 
600   printf ("%*" PRIuMAX " %*" PRIuMAX " %*" PRIuMAX " %*" PRIuMAX " %*"
601 	  PRIxMAX " %s",
602 	  ddigits - 2, total_textsize,
603 	  ddigits - 2, total_datasize,
604 	  ddigits - 2, total_bsssize,
605 	  ddigits - 2, total_textsize + total_datasize + total_bsssize,
606 	  xdigits - 2, total_textsize + total_datasize + total_bsssize,
607 	  gettext ("(TOTALS)\n"));
608 }
609 
610 
611 /* Show size and permission of loadable segments.  */
612 static void
show_segments(Elf * elf,const char * fullname)613 show_segments (Elf *elf, const char *fullname)
614 {
615   GElf_Ehdr ehdr_mem;
616   GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
617   if (ehdr == NULL)
618     INTERNAL_ERROR (fullname);
619 
620   GElf_Off total = 0;
621   bool first = true;
622   for (size_t cnt = 0; cnt < ehdr->e_phnum; ++cnt)
623     {
624       GElf_Phdr phdr_mem;
625       GElf_Phdr *phdr;
626 
627       phdr = gelf_getphdr (elf, cnt, &phdr_mem);
628       if (phdr == NULL)
629 	INTERNAL_ERROR (fullname);
630 
631       if (phdr->p_type != PT_LOAD)
632 	/* Only load segments.  */
633 	continue;
634 
635       if (! first)
636 	fputs_unlocked (" + ", stdout);
637       first = false;
638 
639       printf (radix == radix_hex ? "%" PRIx64 "(%c%c%c)"
640 	      : (radix == radix_decimal ? "%" PRId64 "(%c%c%c)"
641 		 : "%" PRIo64 "(%c%c%c)"),
642 	      phdr->p_memsz,
643 	      (phdr->p_flags & PF_R) == 0 ? '-' : 'r',
644 	      (phdr->p_flags & PF_W) == 0 ? '-' : 'w',
645 	      (phdr->p_flags & PF_X) == 0 ? '-' : 'x');
646 
647       total += phdr->p_memsz;
648     }
649 
650   if (radix == radix_hex)
651     printf (" = %#" PRIx64 "\n", total);
652   else if (radix == radix_decimal)
653     printf (" = %" PRId64 "\n", total);
654   else
655     printf (" = %" PRIo64 "\n", total);
656 }
657 
658 
659 static void
handle_elf(Elf * elf,const char * prefix,const char * fname)660 handle_elf (Elf *elf, const char *prefix, const char *fname)
661 {
662   size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
663   size_t fname_len = strlen (fname) + 1;
664   char fullname[prefix_len + 1 + fname_len];
665   char *cp = fullname;
666 
667   /* Create the full name of the file.  */
668   if (prefix != NULL)
669     {
670       cp = mempcpy (cp, prefix, prefix_len);
671       *cp++ = ':';
672     }
673   memcpy (cp, fname, fname_len);
674 
675   if (format == format_sysv)
676     show_sysv (elf, prefix, fname, fullname);
677   else if (format == format_sysv_one_line)
678     show_sysv_one_line (elf);
679   else if (format == format_segments)
680     show_segments (elf, fullname);
681   else
682     {
683       print_header (elf);
684 
685       show_bsd (elf, prefix, fname, fullname);
686     }
687 }
688 
689 
690 #include "debugpred.h"
691