1 /* Print information from ELF file in human-readable form.
2 Copyright (C) 2005, 2006, 2007, 2009, 2011, 2012, 2014 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 <mcheck.h>
30 #include <stdbool.h>
31 #include <stdio.h>
32 #include <stdio_ext.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <sys/param.h>
37
38 #include <system.h>
39 #include "../libebl/libeblP.h"
40
41
42 /* Name and version of program. */
43 static void print_version (FILE *stream, struct argp_state *state);
44 ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
45
46 /* Bug report address. */
47 ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
48
49
50 /* Definitions of arguments for argp functions. */
51 static const struct argp_option options[] =
52 {
53 { NULL, 0, NULL, 0, N_("Mode selection:"), 0 },
54 { "reloc", 'r', NULL, 0, N_("Display relocation information."), 0 },
55 { "full-contents", 's', NULL, 0,
56 N_("Display the full contents of all sections requested"), 0 },
57 { "disassemble", 'd', NULL, 0,
58 N_("Display assembler code of executable sections"), 0 },
59
60 { NULL, 0, NULL, 0, N_("Output content selection:"), 0 },
61 { "section", 'j', "NAME", 0,
62 N_("Only display information for section NAME."), 0 },
63
64 { NULL, 0, NULL, 0, NULL, 0 }
65 };
66
67 /* Short description of program. */
68 static const char doc[] = N_("\
69 Show information from FILEs (a.out by default).");
70
71 /* Strings for arguments in help texts. */
72 static const char args_doc[] = N_("[FILE...]");
73
74 /* Prototype for option handler. */
75 static error_t parse_opt (int key, char *arg, struct argp_state *state);
76
77 /* Parser children. */
78 static struct argp_child argp_children[] =
79 {
80 { &color_argp, 0, N_("Output formatting"), 2 },
81 { NULL, 0, NULL, 0}
82 };
83
84 /* Data structure to communicate with argp functions. */
85 static const struct argp argp =
86 {
87 options, parse_opt, args_doc, doc, argp_children, NULL, NULL
88 };
89
90
91 /* Print symbols in file named FNAME. */
92 static int process_file (const char *fname, bool more_than_one);
93
94 /* Handle content of archive. */
95 static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
96 const char *suffix);
97
98 /* Handle ELF file. */
99 static int handle_elf (Elf *elf, const char *prefix, const char *fname,
100 const char *suffix);
101
102
103 #define INTERNAL_ERROR(fname) \
104 error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s-%s): %s"), \
105 fname, __LINE__, PACKAGE_VERSION, __DATE__, elf_errmsg (-1))
106
107
108 /* List of sections which should be used. */
109 static struct section_list
110 {
111 bool is_name;
112 union
113 {
114 const char *name;
115 uint32_t scnndx;
116 };
117 struct section_list *next;
118 } *section_list;
119
120
121 /* If true print archive index. */
122 static bool print_relocs;
123
124 /* If true print full contents of requested sections. */
125 static bool print_full_content;
126
127 /* If true print disassembled output.. */
128 static bool print_disasm;
129
130
131 int
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 "), "2012");
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,
238 program_invocation_short_name);
239 exit (EXIT_FAILURE);
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_x(Ebl * ebl,GElf_Shdr * shdr,Elf_Data * symdata,Elf_Data * xndxdata,size_t symstrndx,size_t shstrndx,GElf_Addr r_offset,GElf_Xword r_info,GElf_Sxword r_addend)361 show_relocs_x (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *symdata,
362 Elf_Data *xndxdata, size_t symstrndx, size_t shstrndx,
363 GElf_Addr r_offset, GElf_Xword r_info, GElf_Sxword r_addend)
364 {
365 int elfclass = gelf_getclass (ebl->elf);
366 char buf[128];
367
368 printf ("%0*" PRIx64 " %-20s ",
369 elfclass == ELFCLASS32 ? 8 : 16, r_offset,
370 ebl_reloc_type_name (ebl, GELF_R_TYPE (r_info), buf, sizeof (buf)));
371
372 Elf32_Word xndx;
373 GElf_Sym symmem;
374 GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (r_info),
375 &symmem, &xndx);
376
377 if (sym == NULL)
378 printf ("<%s %ld>",
379 gettext ("INVALID SYMBOL"), (long int) GELF_R_SYM (r_info));
380 else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
381 printf ("%s",
382 elf_strptr (ebl->elf, symstrndx, sym->st_name));
383 else
384 {
385 GElf_Shdr destshdr_mem;
386 GElf_Shdr *destshdr;
387 destshdr = gelf_getshdr (elf_getscn (ebl->elf,
388 sym->st_shndx == SHN_XINDEX
389 ? xndx : sym->st_shndx),
390 &destshdr_mem);
391
392 if (shdr == NULL || destshdr == NULL)
393 printf ("<%s %ld>",
394 gettext ("INVALID SECTION"),
395 (long int) (sym->st_shndx == SHN_XINDEX
396 ? xndx : sym->st_shndx));
397 else
398 printf ("%s",
399 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
400 }
401
402 if (r_addend != 0)
403 {
404 char sign = '+';
405 if (r_addend < 0)
406 {
407 sign = '-';
408 r_addend = -r_addend;
409 }
410 printf ("%c%#" PRIx64, sign, r_addend);
411 }
412 putchar ('\n');
413 }
414
415
416 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)417 show_relocs_rel (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data,
418 Elf_Data *symdata, Elf_Data *xndxdata, size_t symstrndx,
419 size_t shstrndx)
420 {
421 size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT);
422 int nentries = shdr->sh_size / sh_entsize;
423
424 for (int cnt = 0; cnt < nentries; ++cnt)
425 {
426 GElf_Rel relmem;
427 GElf_Rel *rel;
428
429 rel = gelf_getrel (data, cnt, &relmem);
430 if (rel != NULL)
431 show_relocs_x (ebl, shdr, symdata, xndxdata, symstrndx, shstrndx,
432 rel->r_offset, rel->r_info, 0);
433 }
434 }
435
436
437 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)438 show_relocs_rela (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data,
439 Elf_Data *symdata, Elf_Data *xndxdata, size_t symstrndx,
440 size_t shstrndx)
441 {
442 size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT);
443 int nentries = shdr->sh_size / sh_entsize;
444
445 for (int cnt = 0; cnt < nentries; ++cnt)
446 {
447 GElf_Rela relmem;
448 GElf_Rela *rel;
449
450 rel = gelf_getrela (data, cnt, &relmem);
451 if (rel != NULL)
452 show_relocs_x (ebl, shdr, symdata, xndxdata, symstrndx, shstrndx,
453 rel->r_offset, rel->r_info, rel->r_addend);
454 }
455 }
456
457
458 static bool
section_match(Elf * elf,uint32_t scnndx,GElf_Shdr * shdr,size_t shstrndx)459 section_match (Elf *elf, uint32_t scnndx, GElf_Shdr *shdr, size_t shstrndx)
460 {
461 if (section_list == NULL)
462 return true;
463
464 struct section_list *runp = section_list;
465 const char *name = elf_strptr (elf, shstrndx, shdr->sh_name);
466
467 do
468 {
469 if (runp->is_name)
470 {
471 if (name && strcmp (runp->name, name) == 0)
472 return true;
473 }
474 else
475 {
476 if (runp->scnndx == scnndx)
477 return true;
478 }
479
480 runp = runp->next;
481 }
482 while (runp != NULL);
483
484 return false;
485 }
486
487
488 static int
show_relocs(Ebl * ebl,const char * fname,uint32_t shstrndx)489 show_relocs (Ebl *ebl, const char *fname, uint32_t shstrndx)
490 {
491 int elfclass = gelf_getclass (ebl->elf);
492
493 Elf_Scn *scn = NULL;
494 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
495 {
496 GElf_Shdr shdr_mem;
497 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
498
499 if (shdr == NULL)
500 INTERNAL_ERROR (fname);
501
502 if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
503 {
504 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
505 continue;
506
507 GElf_Shdr destshdr_mem;
508 GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf,
509 shdr->sh_info),
510 &destshdr_mem);
511 if (unlikely (destshdr == NULL))
512 continue;
513
514 printf (gettext ("\nRELOCATION RECORDS FOR [%s]:\n"
515 "%-*s TYPE VALUE\n"),
516 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
517 elfclass == ELFCLASS32 ? 8 : 16, gettext ("OFFSET"));
518
519 /* Get the data of the section. */
520 Elf_Data *data = elf_getdata (scn, NULL);
521 if (data == NULL)
522 continue;
523
524 /* Get the symbol table information. */
525 Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
526 GElf_Shdr symshdr_mem;
527 GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
528 Elf_Data *symdata = elf_getdata (symscn, NULL);
529 if (unlikely (symshdr == NULL || symdata == NULL))
530 continue;
531
532 /* Search for the optional extended section index table. */
533 Elf_Data *xndxdata = NULL;
534 Elf_Scn *xndxscn = NULL;
535 while ((xndxscn = elf_nextscn (ebl->elf, xndxscn)) != NULL)
536 {
537 GElf_Shdr xndxshdr_mem;
538 GElf_Shdr *xndxshdr;
539
540 xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
541 if (xndxshdr != NULL && xndxshdr->sh_type == SHT_SYMTAB_SHNDX
542 && xndxshdr->sh_link == elf_ndxscn (symscn))
543 {
544 /* Found it. */
545 xndxdata = elf_getdata (xndxscn, NULL);
546 break;
547 }
548 }
549
550 if (shdr->sh_type == SHT_REL)
551 show_relocs_rel (ebl, shdr, data, symdata, xndxdata,
552 symshdr->sh_link, shstrndx);
553 else
554 show_relocs_rela (ebl, shdr, data, symdata, xndxdata,
555 symshdr->sh_link, shstrndx);
556
557 putchar ('\n');
558 }
559 }
560
561 return 0;
562 }
563
564
565 static int
show_full_content(Ebl * ebl,const char * fname,uint32_t shstrndx)566 show_full_content (Ebl *ebl, const char *fname, uint32_t shstrndx)
567 {
568 Elf_Scn *scn = NULL;
569 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
570 {
571 GElf_Shdr shdr_mem;
572 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
573
574 if (shdr == NULL)
575 INTERNAL_ERROR (fname);
576
577 if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0)
578 {
579 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
580 continue;
581
582 printf (gettext ("Contents of section %s:\n"),
583 elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
584
585 /* Get the data of the section. */
586 Elf_Data *data = elf_getdata (scn, NULL);
587 if (data == NULL)
588 continue;
589
590 unsigned char *cp = data->d_buf;
591 size_t cnt;
592 for (cnt = 0; cnt + 16 < data->d_size; cp += 16, cnt += 16)
593 {
594 printf (" %04zx ", cnt);
595
596 for (size_t inner = 0; inner < 16; inner += 4)
597 printf ("%02hhx%02hhx%02hhx%02hhx ",
598 cp[inner], cp[inner + 1], cp[inner + 2],
599 cp[inner + 3]);
600 fputc_unlocked (' ', stdout);
601
602 for (size_t inner = 0; inner < 16; ++inner)
603 fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner])
604 ? cp[inner] : '.', stdout);
605 fputc_unlocked ('\n', stdout);
606 }
607
608 printf (" %04zx ", cnt);
609
610 size_t remaining = data->d_size - cnt;
611 size_t inner;
612 for (inner = 0; inner + 4 <= remaining; inner += 4)
613 printf ("%02hhx%02hhx%02hhx%02hhx ",
614 cp[inner], cp[inner + 1], cp[inner + 2], cp[inner + 3]);
615
616 for (; inner < remaining; ++inner)
617 printf ("%02hhx", cp[inner]);
618
619 for (inner = 2 * (16 - inner) + (16 - inner + 3) / 4 + 1; inner > 0;
620 --inner)
621 fputc_unlocked (' ', stdout);
622
623 for (inner = 0; inner < remaining; ++inner)
624 fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner])
625 ? cp[inner] : '.', stdout);
626 fputc_unlocked ('\n', stdout);
627
628 fputc_unlocked ('\n', stdout);
629 }
630 }
631
632 return 0;
633 }
634
635
636 struct disasm_info
637 {
638 GElf_Addr addr;
639 const uint8_t *cur;
640 const uint8_t *last_end;
641 const char *address_color;
642 const char *bytes_color;
643 };
644
645
646 // XXX This is not the preferred output for all architectures. Needs
647 // XXX customization, too.
648 static int
disasm_output(char * buf,size_t buflen,void * arg)649 disasm_output (char *buf, size_t buflen, void *arg)
650 {
651 struct disasm_info *info = (struct disasm_info *) arg;
652
653 if (info->address_color != NULL)
654 printf ("%s%8" PRIx64 "%s: ",
655 info->address_color, (uint64_t) info->addr, color_off);
656 else
657 printf ("%8" PRIx64 ": ", (uint64_t) info->addr);
658
659 if (info->bytes_color != NULL)
660 fputs_unlocked (info->bytes_color, stdout);
661 size_t cnt;
662 for (cnt = 0; cnt < (size_t) MIN (info->cur - info->last_end, 8); ++cnt)
663 printf (" %02" PRIx8, info->last_end[cnt]);
664 if (info->bytes_color != NULL)
665 fputs_unlocked (color_off, stdout);
666
667 printf ("%*s %.*s\n",
668 (int) (8 - cnt) * 3 + 1, "", (int) buflen, buf);
669
670 info->addr += cnt;
671
672 /* We limit the number of bytes printed before the mnemonic to 8.
673 Print the rest on a separate, following line. */
674 if (info->cur - info->last_end > 8)
675 {
676 if (info->address_color != NULL)
677 printf ("%s%8" PRIx64 "%s: ",
678 info->address_color, (uint64_t) info->addr, color_off);
679 else
680 printf ("%8" PRIx64 ": ", (uint64_t) info->addr);
681
682 if (info->bytes_color != NULL)
683 fputs_unlocked (info->bytes_color, stdout);
684 for (; cnt < (size_t) (info->cur - info->last_end); ++cnt)
685 printf (" %02" PRIx8, info->last_end[cnt]);
686 if (info->bytes_color != NULL)
687 fputs_unlocked (color_off, stdout);
688 putchar_unlocked ('\n');
689 info->addr += info->cur - info->last_end - 8;
690 }
691
692 info->last_end = info->cur;
693
694 return 0;
695 }
696
697
698 static int
show_disasm(Ebl * ebl,const char * fname,uint32_t shstrndx)699 show_disasm (Ebl *ebl, const char *fname, uint32_t shstrndx)
700 {
701 DisasmCtx_t *ctx = disasm_begin (ebl, ebl->elf, NULL /* XXX TODO */);
702 if (ctx == NULL)
703 error (EXIT_FAILURE, 0, gettext ("cannot disassemble"));
704
705 Elf_Scn *scn = NULL;
706 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
707 {
708 GElf_Shdr shdr_mem;
709 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
710
711 if (shdr == NULL)
712 INTERNAL_ERROR (fname);
713
714 if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0
715 && (shdr->sh_flags & SHF_EXECINSTR) != 0)
716 {
717 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
718 continue;
719
720 Elf_Data *data = elf_getdata (scn, NULL);
721 if (data == NULL)
722 continue;
723
724 printf ("Disassembly of section %s:\n\n",
725 elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
726
727 struct disasm_info info;
728 info.addr = shdr->sh_addr;
729 info.last_end = info.cur = data->d_buf;
730 char *fmt;
731 if (color_mode)
732 {
733 info.address_color = color_address;
734 info.bytes_color = color_bytes;
735
736 if (asprintf (&fmt, "%s%%7m %s%%.1o,%s%%.2o,%s%%.3o%%34a %s%%l",
737 color_mnemonic ?: "",
738 color_operand1 ?: "",
739 color_operand2 ?: "",
740 color_operand3 ?: "",
741 color_label ?: "") < 0)
742 error (EXIT_FAILURE, errno, _("cannot allocate memory"));
743 }
744 else
745 {
746 info.address_color = info.bytes_color = NULL;
747
748 fmt = "%7m %.1o,%.2o,%.3o%34a %l";
749 }
750
751 disasm_cb (ctx, &info.cur, info.cur + data->d_size, info.addr,
752 fmt, disasm_output, &info, NULL /* XXX */);
753
754 if (color_mode)
755 free (fmt);
756 }
757 }
758
759 (void) disasm_end (ctx);
760
761 return 0;
762 }
763
764
765 static int
handle_elf(Elf * elf,const char * prefix,const char * fname,const char * suffix)766 handle_elf (Elf *elf, const char *prefix, const char *fname,
767 const char *suffix)
768 {
769
770 /* Get the backend for this object file type. */
771 Ebl *ebl = ebl_openbackend (elf);
772
773 printf ("%s: elf%d-%s\n\n",
774 fname, gelf_getclass (elf) == ELFCLASS32 ? 32 : 64,
775 ebl_backend_name (ebl));
776
777 /* Create the full name of the file. */
778 size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
779 size_t suffix_len = suffix == NULL ? 0 : strlen (suffix);
780 size_t fname_len = strlen (fname) + 1;
781 char fullname[prefix_len + 1 + fname_len + suffix_len];
782 char *cp = fullname;
783 if (prefix != NULL)
784 cp = mempcpy (cp, prefix, prefix_len);
785 cp = mempcpy (cp, fname, fname_len);
786 if (suffix != NULL)
787 memcpy (cp - 1, suffix, suffix_len + 1);
788
789 /* Get the section header string table index. */
790 size_t shstrndx;
791 if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
792 error (EXIT_FAILURE, 0,
793 gettext ("cannot get section header string table index"));
794
795 int result = 0;
796 if (print_disasm)
797 result = show_disasm (ebl, fullname, shstrndx);
798 if (print_relocs && !print_disasm)
799 result = show_relocs (ebl, fullname, shstrndx);
800 if (print_full_content)
801 result = show_full_content (ebl, fullname, shstrndx);
802
803 /* Close the ELF backend library descriptor. */
804 ebl_closebackend (ebl);
805
806 return result;
807 }
808
809
810 #include "debugpred.h"
811