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

Generated by: LCOV version 1.13