LCOV - code coverage report
Current view: top level - src - objdump.c (source / functions) Hit Total Coverage
Test: elfutils-0.173 Lines: 147 301 48.8 %
Date: 2018-06-29 23:49:12 Functions: 10 13 76.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13