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

Generated by: LCOV version 1.12