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