Imported Upstream version 0.153
[platform/upstream/elfutils.git] / src / objdump.c
1 /* Print information from ELF file in human-readable form.
2    Copyright (C) 2005, 2006, 2007, 2009, 2011, 2012 Red Hat, Inc.
3    This file is part of Red Hat elfutils.
4    Written by Ulrich Drepper <drepper@redhat.com>, 2005.
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 <inttypes.h>
35 #include <libintl.h>
36 #include <locale.h>
37 #include <mcheck.h>
38 #include <stdbool.h>
39 #include <stdio.h>
40 #include <stdio_ext.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <unistd.h>
44 #include <sys/param.h>
45
46 #include <system.h>
47 #include "../libebl/libeblP.h"
48
49
50 /* Name and version of program.  */
51 static void print_version (FILE *stream, struct argp_state *state);
52 ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
53
54 /* Bug report address.  */
55 ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
56
57
58 /* Definitions of arguments for argp functions.  */
59 static const struct argp_option options[] =
60 {
61   { NULL, 0, NULL, 0, N_("Mode selection:"), 0 },
62   { "reloc", 'r', NULL, 0, N_("Display relocation information."), 0 },
63   { "full-contents", 's', NULL, 0,
64     N_("Display the full contents of all sections requested"), 0 },
65   { "disassemble", 'd', NULL, 0,
66     N_("Display assembler code of executable sections"), 0 },
67
68   { NULL, 0, NULL, 0, N_("Output content selection:"), 0 },
69   { "section", 'j', "NAME", 0,
70     N_("Only display information for section NAME."), 0 },
71
72   { NULL, 0, NULL, 0, NULL, 0 }
73 };
74
75 /* Short description of program.  */
76 static const char doc[] = N_("\
77 Show information from FILEs (a.out by default).");
78
79 /* Strings for arguments in help texts.  */
80 static const char args_doc[] = N_("[FILE...]");
81
82 /* Prototype for option handler.  */
83 static error_t parse_opt (int key, char *arg, struct argp_state *state);
84
85 /* Parser children.  */
86 static struct argp_child argp_children[] =
87   {
88     { &color_argp, 0, N_("Output formatting"), 2 },
89     { NULL, 0, NULL, 0}
90   };
91
92 /* Data structure to communicate with argp functions.  */
93 static const struct argp argp =
94 {
95   options, parse_opt, args_doc, doc, argp_children, NULL, NULL
96 };
97
98
99 /* Print symbols in file named FNAME.  */
100 static int process_file (const char *fname, bool more_than_one);
101
102 /* Handle content of archive.  */
103 static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
104                       const char *suffix);
105
106 /* Handle ELF file.  */
107 static int handle_elf (Elf *elf, const char *prefix, const char *fname,
108                        const char *suffix);
109
110
111 #define INTERNAL_ERROR(fname) \
112   error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s-%s): %s"),      \
113          fname, __LINE__, PACKAGE_VERSION, __DATE__, elf_errmsg (-1))
114
115
116 /* List of sections which should be used.  */
117 static struct section_list
118 {
119   bool is_name;
120   union
121   {
122     const char *name;
123     uint32_t scnndx;
124   };
125   struct section_list *next;
126 } *section_list;
127
128
129 /* If true print archive index.  */
130 static bool print_relocs;
131
132 /* If true print full contents of requested sections.  */
133 static bool print_full_content;
134
135 /* If true print disassembled output..  */
136 static bool print_disasm;
137
138
139 int
140 main (int argc, char *argv[])
141 {
142   /* Make memory leak detection possible.  */
143   mtrace ();
144
145   /* We use no threads here which can interfere with handling a stream.  */
146   (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
147   (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
148   (void) __fsetlocking (stderr, FSETLOCKING_BYCALLER);
149
150   /* Set locale.  */
151   (void) setlocale (LC_ALL, "");
152
153   /* Make sure the message catalog can be found.  */
154   (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
155
156   /* Initialize the message catalog.  */
157   (void) textdomain (PACKAGE_TARNAME);
158
159   /* Parse and process arguments.  */
160   int remaining;
161   (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL);
162
163   /* Tell the library which version we are expecting.  */
164   (void) elf_version (EV_CURRENT);
165
166   int result = 0;
167   if (remaining == argc)
168     /* The user didn't specify a name so we use a.out.  */
169     result = process_file ("a.out", false);
170   else
171     {
172       /* Process all the remaining files.  */
173       const bool more_than_one = remaining + 1 < argc;
174
175       do
176         result |= process_file (argv[remaining], more_than_one);
177       while (++remaining < argc);
178     }
179
180   return result;
181 }
182
183
184 /* Print the version information.  */
185 static void
186 print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
187 {
188   fprintf (stream, "objdump (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
189   fprintf (stream, gettext ("\
190 Copyright (C) %s Red Hat, Inc.\n\
191 This is free software; see the source for copying conditions.  There is NO\n\
192 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
193 "), "2012");
194   fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
195 }
196
197
198 /* Handle program arguments.  */
199 static error_t
200 parse_opt (int key, char *arg,
201            struct argp_state *state __attribute__ ((unused)))
202 {
203   /* True if any of the control options is set.  */
204   static bool any_control_option;
205
206   switch (key)
207     {
208     case 'j':
209       {
210         struct section_list *newp = xmalloc (sizeof (*newp));
211         char *endp;
212         newp->scnndx = strtoul (arg, &endp, 0);
213         if (*endp == 0)
214           newp->is_name = false;
215         else
216           {
217             newp->name = arg;
218             newp->is_name = true;
219           }
220         newp->next = section_list;
221         section_list = newp;
222       }
223       any_control_option = true;
224       break;
225
226     case 'd':
227       print_disasm = true;
228       any_control_option = true;
229       break;
230
231     case 'r':
232       print_relocs = true;
233       any_control_option = true;
234       break;
235
236     case 's':
237       print_full_content = true;
238       any_control_option = true;
239       break;
240
241     case ARGP_KEY_FINI:
242       if (! any_control_option)
243         {
244           fputs (gettext ("No operation specified.\n"), stderr);
245           argp_help (&argp, stderr, ARGP_HELP_SEE,
246                      program_invocation_short_name);
247           exit (EXIT_FAILURE);
248         }
249
250     default:
251       return ARGP_ERR_UNKNOWN;
252     }
253   return 0;
254 }
255
256
257 /* Open the file and determine the type.  */
258 static int
259 process_file (const char *fname, bool more_than_one)
260 {
261   /* Open the file.  */
262   int fd = open (fname, O_RDONLY);
263   if (fd == -1)
264     {
265       error (0, errno, gettext ("cannot open %s"), fname);
266       return 1;
267     }
268
269   /* Now get the ELF descriptor.  */
270   Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
271   if (elf != NULL)
272     {
273       if (elf_kind (elf) == ELF_K_ELF)
274         {
275           int result = handle_elf (elf, more_than_one ? "" : NULL,
276                                    fname, NULL);
277
278           if (elf_end (elf) != 0)
279             INTERNAL_ERROR (fname);
280
281           if (close (fd) != 0)
282             error (EXIT_FAILURE, errno, gettext ("while close `%s'"), fname);
283
284           return result;
285         }
286       else if (elf_kind (elf) == ELF_K_AR)
287         {
288           int result = handle_ar (fd, elf, NULL, fname, NULL);
289
290           if (elf_end (elf) != 0)
291             INTERNAL_ERROR (fname);
292
293           if (close (fd) != 0)
294             error (EXIT_FAILURE, errno, gettext ("while close `%s'"), fname);
295
296           return result;
297         }
298
299       /* We cannot handle this type.  Close the descriptor anyway.  */
300       if (elf_end (elf) != 0)
301         INTERNAL_ERROR (fname);
302     }
303
304   error (0, 0, gettext ("%s: File format not recognized"), fname);
305
306   return 1;
307 }
308
309
310 static int
311 handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
312            const char *suffix)
313 {
314   size_t fname_len = strlen (fname) + 1;
315   size_t prefix_len = prefix != NULL ? strlen (prefix) : 0;
316   char new_prefix[prefix_len + fname_len + 2];
317   size_t suffix_len = suffix != NULL ? strlen (suffix) : 0;
318   char new_suffix[suffix_len + 2];
319   Elf *subelf;
320   Elf_Cmd cmd = ELF_C_READ_MMAP;
321   int result = 0;
322
323   char *cp = new_prefix;
324   if (prefix != NULL)
325     cp = stpcpy (cp, prefix);
326   cp = stpcpy (cp, fname);
327   stpcpy (cp, "[");
328
329   cp = new_suffix;
330   if (suffix != NULL)
331     cp = stpcpy (cp, suffix);
332   stpcpy (cp, "]");
333
334   /* Process all the files contained in the archive.  */
335   while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
336     {
337       /* The the header for this element.  */
338       Elf_Arhdr *arhdr = elf_getarhdr (subelf);
339
340       /* Skip over the index entries.  */
341       if (strcmp (arhdr->ar_name, "/") != 0
342           && strcmp (arhdr->ar_name, "//") != 0)
343         {
344           if (elf_kind (subelf) == ELF_K_ELF)
345             result |= handle_elf (subelf, new_prefix, arhdr->ar_name,
346                                   new_suffix);
347           else if (elf_kind (subelf) == ELF_K_AR)
348             result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name,
349                                  new_suffix);
350           else
351             {
352               error (0, 0, gettext ("%s%s%s: file format not recognized"),
353                      new_prefix, arhdr->ar_name, new_suffix);
354               result = 1;
355             }
356         }
357
358       /* Get next archive element.  */
359       cmd = elf_next (subelf);
360       if (elf_end (subelf) != 0)
361         INTERNAL_ERROR (fname);
362     }
363
364   return result;
365 }
366
367
368 static void
369 show_relocs_x (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *symdata,
370                Elf_Data *xndxdata, size_t symstrndx, size_t shstrndx,
371                GElf_Addr r_offset, GElf_Xword r_info, GElf_Sxword r_addend)
372 {
373   int elfclass = gelf_getclass (ebl->elf);
374   char buf[128];
375
376   printf ("%0*" PRIx64 " %-20s ",
377           elfclass == ELFCLASS32 ? 8 : 16, r_offset,
378           ebl_reloc_type_name (ebl, GELF_R_TYPE (r_info), buf, sizeof (buf)));
379
380   Elf32_Word xndx;
381   GElf_Sym symmem;
382   GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (r_info),
383                                     &symmem, &xndx);
384
385   if (sym == NULL)
386     printf ("<%s %ld>",
387             gettext ("INVALID SYMBOL"), (long int) GELF_R_SYM (r_info));
388   else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
389     printf ("%s",
390             elf_strptr (ebl->elf, symstrndx, sym->st_name));
391   else
392     {
393       GElf_Shdr destshdr_mem;
394       GElf_Shdr *destshdr;
395       destshdr = gelf_getshdr (elf_getscn (ebl->elf,
396                                            sym->st_shndx == SHN_XINDEX
397                                            ? xndx : sym->st_shndx),
398                                &destshdr_mem);
399
400       if (shdr == NULL)
401         printf ("<%s %ld>",
402                 gettext ("INVALID SECTION"),
403                 (long int) (sym->st_shndx == SHN_XINDEX
404                             ? xndx : sym->st_shndx));
405       else
406         printf ("%s",
407                 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
408     }
409
410   if (r_addend != 0)
411     {
412       char sign = '+';
413       if (r_addend < 0)
414         {
415           sign = '-';
416           r_addend = -r_addend;
417         }
418       printf ("%c%#" PRIx64, sign, r_addend);
419     }
420   putchar ('\n');
421 }
422
423
424 static void
425 show_relocs_rel (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data,
426                  Elf_Data *symdata, Elf_Data *xndxdata, size_t symstrndx,
427                  size_t shstrndx)
428 {
429   int nentries = shdr->sh_size / shdr->sh_entsize;
430
431   for (int cnt = 0; cnt < nentries; ++cnt)
432     {
433       GElf_Rel relmem;
434       GElf_Rel *rel;
435
436       rel = gelf_getrel (data, cnt, &relmem);
437       if (rel != NULL)
438         show_relocs_x (ebl, shdr, symdata, xndxdata, symstrndx, shstrndx,
439                        rel->r_offset, rel->r_info, 0);
440     }
441 }
442
443
444 static void
445 show_relocs_rela (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data,
446                   Elf_Data *symdata, Elf_Data *xndxdata, size_t symstrndx,
447                   size_t shstrndx)
448 {
449   int nentries = shdr->sh_size / shdr->sh_entsize;
450
451   for (int cnt = 0; cnt < nentries; ++cnt)
452     {
453       GElf_Rela relmem;
454       GElf_Rela *rel;
455
456       rel = gelf_getrela (data, cnt, &relmem);
457       if (rel != NULL)
458         show_relocs_x (ebl, shdr, symdata, xndxdata, symstrndx, shstrndx,
459                        rel->r_offset, rel->r_info, rel->r_addend);
460     }
461 }
462
463
464 static bool
465 section_match (Elf *elf, uint32_t scnndx, GElf_Shdr *shdr, size_t shstrndx)
466 {
467   if (section_list == NULL)
468     return true;
469
470   struct section_list *runp = section_list;
471
472   do
473     {
474       if (runp->is_name)
475         {
476           if (strcmp (runp->name,
477                       elf_strptr (elf, shstrndx, shdr->sh_name)) == 0)
478             return true;
479         }
480       else
481         {
482           if (runp->scnndx == scnndx)
483             return true;
484         }
485
486       runp = runp->next;
487     }
488   while (runp != NULL);
489
490   return false;
491 }
492
493
494 static int
495 show_relocs (Ebl *ebl, const char *fname, uint32_t shstrndx)
496 {
497   int elfclass = gelf_getclass (ebl->elf);
498
499   Elf_Scn *scn = NULL;
500   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
501     {
502       GElf_Shdr shdr_mem;
503       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
504
505       if (shdr == NULL)
506         INTERNAL_ERROR (fname);
507
508       if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
509         {
510           if  (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
511             continue;
512
513           GElf_Shdr destshdr_mem;
514           GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf,
515                                                           shdr->sh_info),
516                                               &destshdr_mem);
517
518           printf (gettext ("\nRELOCATION RECORDS FOR [%s]:\n"
519                            "%-*s TYPE                 VALUE\n"),
520                   elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
521                   elfclass == ELFCLASS32 ? 8 : 16, gettext ("OFFSET"));
522
523           /* Get the data of the section.  */
524           Elf_Data *data = elf_getdata (scn, NULL);
525           if (data == NULL)
526             continue;
527
528           /* Get the symbol table information.  */
529           Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
530           GElf_Shdr symshdr_mem;
531           GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
532           Elf_Data *symdata = elf_getdata (symscn, NULL);
533
534           /* Search for the optional extended section index table.  */
535           Elf_Data *xndxdata = NULL;
536           Elf_Scn *xndxscn = NULL;
537           while ((xndxscn = elf_nextscn (ebl->elf, xndxscn)) != NULL)
538             {
539               GElf_Shdr xndxshdr_mem;
540               GElf_Shdr *xndxshdr;
541
542               xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
543               if (xndxshdr != NULL && xndxshdr->sh_type == SHT_SYMTAB_SHNDX
544                   && xndxshdr->sh_link == elf_ndxscn (symscn))
545                 {
546                   /* Found it.  */
547                   xndxdata = elf_getdata (xndxscn, NULL);
548                   break;
549                 }
550             }
551
552           if (shdr->sh_type == SHT_REL)
553             show_relocs_rel (ebl, shdr, data, symdata, xndxdata,
554                              symshdr->sh_link, shstrndx);
555           else
556             show_relocs_rela (ebl, shdr, data, symdata, xndxdata,
557                               symshdr->sh_link, shstrndx);
558
559           putchar ('\n');
560         }
561     }
562
563   return 0;
564 }
565
566
567 static int
568 show_full_content (Ebl *ebl, const char *fname, uint32_t shstrndx)
569 {
570   Elf_Scn *scn = NULL;
571   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
572     {
573       GElf_Shdr shdr_mem;
574       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
575
576       if (shdr == NULL)
577         INTERNAL_ERROR (fname);
578
579       if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0)
580         {
581           if  (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
582             continue;
583
584           printf (gettext ("Contents of section %s:\n"),
585                   elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
586
587           /* Get the data of the section.  */
588           Elf_Data *data = elf_getdata (scn, NULL);
589           if (data == NULL)
590             continue;
591
592           unsigned char *cp = data->d_buf;
593           size_t cnt;
594           for (cnt = 0; cnt + 16 < data->d_size; cp += 16, cnt += 16)
595             {
596               printf (" %04zx ", cnt);
597
598               for (size_t inner = 0; inner < 16; inner += 4)
599                 printf ("%02hhx%02hhx%02hhx%02hhx ",
600                         cp[inner], cp[inner + 1], cp[inner + 2],
601                         cp[inner + 3]);
602               fputc_unlocked (' ', stdout);
603
604               for (size_t inner = 0; inner < 16; ++inner)
605                 fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner])
606                                 ? cp[inner] : '.', stdout);
607               fputc_unlocked ('\n', stdout);
608             }
609
610           printf (" %04zx ", cnt);
611
612           size_t remaining = data->d_size - cnt;
613           size_t inner;
614           for (inner = 0; inner + 4 <= remaining; inner += 4)
615             printf ("%02hhx%02hhx%02hhx%02hhx ",
616                     cp[inner], cp[inner + 1], cp[inner + 2], cp[inner + 3]);
617
618           for (; inner < remaining; ++inner)
619             printf ("%02hhx", cp[inner]);
620
621           for (inner = 2 * (16 - inner) + (16 - inner + 3) / 4 + 1; inner > 0;
622                --inner)
623             fputc_unlocked (' ', stdout);
624
625           for (inner = 0; inner < remaining; ++inner)
626             fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner])
627                             ? cp[inner] : '.', stdout);
628           fputc_unlocked ('\n', stdout);
629
630           fputc_unlocked ('\n', stdout);
631         }
632     }
633
634   return 0;
635 }
636
637
638 struct disasm_info
639 {
640   GElf_Addr addr;
641   const uint8_t *cur;
642   const uint8_t *last_end;
643   const char *address_color;
644   const char *bytes_color;
645 };
646
647
648 // XXX This is not the preferred output for all architectures.  Needs
649 // XXX customization, too.
650 static int
651 disasm_output (char *buf, size_t buflen, void *arg)
652 {
653   struct disasm_info *info = (struct disasm_info *) arg;
654
655   if (info->address_color != NULL)
656     printf ("%s%8" PRIx64 "%s:   ",
657             info->address_color, (uint64_t) info->addr, color_off);
658   else
659     printf ("%8" PRIx64 ":   ", (uint64_t) info->addr);
660
661   if (info->bytes_color != NULL)
662     fputs_unlocked (info->bytes_color, stdout);
663   size_t cnt;
664   for (cnt = 0; cnt < (size_t) MIN (info->cur - info->last_end, 8); ++cnt)
665     printf (" %02" PRIx8, info->last_end[cnt]);
666   if (info->bytes_color != NULL)
667     fputs_unlocked (color_off, stdout);
668
669   printf ("%*s %.*s\n",
670           (int) (8 - cnt) * 3 + 1, "", (int) buflen, buf);
671
672   info->addr += cnt;
673
674   /* We limit the number of bytes printed before the mnemonic to 8.
675      Print the rest on a separate, following line.  */
676   if (info->cur - info->last_end > 8)
677     {
678       if (info->address_color != NULL)
679         printf ("%s%8" PRIx64 "%s:   ",
680                 info->address_color, (uint64_t) info->addr, color_off);
681       else
682         printf ("%8" PRIx64 ":   ", (uint64_t) info->addr);
683
684       if (info->bytes_color != NULL)
685         fputs_unlocked (info->bytes_color, stdout);
686       for (; cnt < (size_t) (info->cur - info->last_end); ++cnt)
687         printf (" %02" PRIx8, info->last_end[cnt]);
688       if (info->bytes_color != NULL)
689         fputs_unlocked (color_off, stdout);
690       putchar_unlocked ('\n');
691       info->addr += info->cur - info->last_end - 8;
692     }
693
694   info->last_end = info->cur;
695
696   return 0;
697 }
698
699
700 static int
701 show_disasm (Ebl *ebl, const char *fname, uint32_t shstrndx)
702 {
703   DisasmCtx_t *ctx = disasm_begin (ebl, ebl->elf, NULL /* XXX TODO */);
704   if (ctx == NULL)
705     error (EXIT_FAILURE, 0, gettext ("cannot disassemble"));
706
707   Elf_Scn *scn = NULL;
708   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
709     {
710       GElf_Shdr shdr_mem;
711       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
712
713       if (shdr == NULL)
714         INTERNAL_ERROR (fname);
715
716       if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0
717           && (shdr->sh_flags & SHF_EXECINSTR) != 0)
718         {
719           if  (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
720             continue;
721
722           Elf_Data *data = elf_getdata (scn, NULL);
723           if (data == NULL)
724             continue;
725
726           printf ("Disassembly of section %s:\n\n",
727                   elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
728
729           struct disasm_info info;
730           info.addr = shdr->sh_addr;
731           info.last_end = info.cur = data->d_buf;
732           char *fmt;
733           if (color_mode)
734             {
735               info.address_color = color_address;
736               info.bytes_color = color_bytes;
737
738               if (asprintf (&fmt, "%s%%7m %s%%.1o,%s%%.2o,%s%%.3o%%34a %s%%l",
739                             color_mnemonic ?: "",
740                             color_operand1 ?: "",
741                             color_operand2 ?: "",
742                             color_operand3 ?: "",
743                             color_label ?: "") < 0)
744                 error (EXIT_FAILURE, errno, _("cannot allocate memory"));
745             }
746           else
747             {
748               info.address_color = info.bytes_color = NULL;
749
750               fmt = "%7m %.1o,%.2o,%.3o%34a %l";
751             }
752
753           disasm_cb (ctx, &info.cur, info.cur + data->d_size, info.addr,
754                      fmt, disasm_output, &info, NULL /* XXX */);
755
756           if (color_mode)
757             free (fmt);
758         }
759     }
760
761   (void) disasm_end (ctx);
762
763   return 0;
764 }
765
766
767 static int
768 handle_elf (Elf *elf, const char *prefix, const char *fname,
769             const char *suffix)
770 {
771
772   /* Get the backend for this object file type.  */
773   Ebl *ebl = ebl_openbackend (elf);
774
775   printf ("%s: elf%d-%s\n\n",
776           fname, gelf_getclass (elf) == ELFCLASS32 ? 32 : 64,
777           ebl_backend_name (ebl));
778
779   /* Create the full name of the file.  */
780   size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
781   size_t suffix_len = suffix == NULL ? 0 : strlen (suffix);
782   size_t fname_len = strlen (fname) + 1;
783   char fullname[prefix_len + 1 + fname_len + suffix_len];
784   char *cp = fullname;
785   if (prefix != NULL)
786     cp = mempcpy (cp, prefix, prefix_len);
787   cp = mempcpy (cp, fname, fname_len);
788   if (suffix != NULL)
789     memcpy (cp - 1, suffix, suffix_len + 1);
790
791   /* Get the section header string table index.  */
792   size_t shstrndx;
793   if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
794     error (EXIT_FAILURE, 0,
795            gettext ("cannot get section header string table index"));
796
797   int result = 0;
798   if (print_disasm)
799     result = show_disasm (ebl, fullname, shstrndx);
800   if (print_relocs && !print_disasm)
801     result = show_relocs (ebl, fullname, shstrndx);
802   if (print_full_content)
803     result = show_full_content (ebl, fullname, shstrndx);
804
805   /* Close the ELF backend library descriptor.  */
806   ebl_closebackend (ebl);
807
808   return result;
809 }
810
811
812 #include "debugpred.h"