blob: 1234c794ec557cc3649d54508cbf5c74f79c3cb9 [file] [log] [blame]
Ulrich Drepper8a687742005-08-03 02:24:12 +00001/* Print information from ELF file in human-readable form.
Ulrich Drepper44173ed2009-01-01 19:00:41 -08002 Copyright (C) 2005, 2006, 2007, 2009 Red Hat, Inc.
Ulrich Drepper361df7d2006-04-04 21:38:57 +00003 This file is part of Red Hat elfutils.
Ulrich Drepper8a687742005-08-03 02:24:12 +00004 Written by Ulrich Drepper <drepper@redhat.com>, 2005.
5
Ulrich Drepper361df7d2006-04-04 21:38:57 +00006 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.
Ulrich Drepper8a687742005-08-03 02:24:12 +00009
Ulrich Drepper361df7d2006-04-04 21:38:57 +000010 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,
Ulrich Drepper1e9ef502006-04-04 22:29:06 +000017 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
Ulrich Drepper361df7d2006-04-04 21:38:57 +000018
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>. */
Ulrich Drepper8a687742005-08-03 02:24:12 +000026
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. */
51static void print_version (FILE *stream, struct argp_state *state);
Ulrich Drepperfdc93e12009-01-17 11:47:10 -080052ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
Ulrich Drepper8a687742005-08-03 02:24:12 +000053
54/* Bug report address. */
Ulrich Drepperfdc93e12009-01-17 11:47:10 -080055ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
Ulrich Drepper8a687742005-08-03 02:24:12 +000056
57
58/* Definitions of arguments for argp functions. */
59static 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. */
76static const char doc[] = N_("\
77Show information from FILEs (a.out by default).");
78
79/* Strings for arguments in help texts. */
80static const char args_doc[] = N_("[FILE...]");
81
82/* Prototype for option handler. */
83static error_t parse_opt (int key, char *arg, struct argp_state *state);
84
85/* Data structure to communicate with argp functions. */
86static struct argp argp =
87{
88 options, parse_opt, args_doc, doc, NULL, NULL, NULL
89};
90
91
92/* Print symbols in file named FNAME. */
93static int process_file (const char *fname, bool more_than_one);
94
95/* Handle content of archive. */
96static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
97 const char *suffix);
98
99/* Handle ELF file. */
100static 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"), \
Ulrich Drepperb0243862007-06-06 00:09:36 +0000106 fname, __LINE__, PACKAGE_VERSION, __DATE__, elf_errmsg (-1))
Ulrich Drepper8a687742005-08-03 02:24:12 +0000107
108
109/* List of sections which should be used. */
110static 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. */
123static bool print_relocs;
124
125/* If true print full contents of requested sections. */
126static bool print_full_content;
127
128/* If true print disassembled output.. */
129static bool print_disasm;
130
131int
132main (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. */
Ulrich Drepperb0243862007-06-06 00:09:36 +0000146 (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
Ulrich Drepper8a687742005-08-03 02:24:12 +0000147
148 /* Initialize the message catalog. */
Ulrich Drepperb0243862007-06-06 00:09:36 +0000149 (void) textdomain (PACKAGE_TARNAME);
Ulrich Drepper8a687742005-08-03 02:24:12 +0000150
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. */
177static void
178print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
179{
Ulrich Drepperb0243862007-06-06 00:09:36 +0000180 fprintf (stream, "objdump (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
Ulrich Drepper8a687742005-08-03 02:24:12 +0000181 fprintf (stream, gettext ("\
182Copyright (C) %s Red Hat, Inc.\n\
183This is free software; see the source for copying conditions. There is NO\n\
184warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
Ulrich Drepper44173ed2009-01-01 19:00:41 -0800185"), "20089");
Ulrich Drepper8a687742005-08-03 02:24:12 +0000186 fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
187}
188
189
190/* Handle program arguments. */
191static error_t
192parse_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);
Ulrich Drepper5ee720c2009-02-01 16:18:18 -0800237 argp_help (&argp, stderr, ARGP_HELP_SEE,
Ulrich Drepper8a687742005-08-03 02:24:12 +0000238 program_invocation_short_name);
Ulrich Drepper5ee720c2009-02-01 16:18:18 -0800239 exit (EXIT_FAILURE);
Ulrich Drepper8a687742005-08-03 02:24:12 +0000240 }
241
242 default:
243 return ARGP_ERR_UNKNOWN;
244 }
245 return 0;
246}
247
248
249/* Open the file and determine the type. */
250static int
251process_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
302static int
303handle_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
360static void
Ulrich Drepper95fa15e2009-02-01 19:06:10 -0800361show_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];
Ulrich Drepper95fa15e2009-02-01 19:06:10 -0800367
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
Ulrich Drepper51b3f472009-02-05 22:10:39 -0800372 Elf32_Word xndx;
373 GElf_Sym symmem;
374 GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (r_info),
375 &symmem, &xndx);
Ulrich Drepper95fa15e2009-02-01 19:06:10 -0800376
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)
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
416static void
Ulrich Drepper8a687742005-08-03 02:24:12 +0000417show_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{
Ulrich Drepper8a687742005-08-03 02:24:12 +0000421 int nentries = shdr->sh_size / shdr->sh_entsize;
422
423 for (int cnt = 0; cnt < nentries; ++cnt)
424 {
425 GElf_Rel relmem;
426 GElf_Rel *rel;
427
428 rel = gelf_getrel (data, cnt, &relmem);
429 if (rel != NULL)
Ulrich Drepper95fa15e2009-02-01 19:06:10 -0800430 show_relocs_x (ebl, shdr, symdata, xndxdata, symstrndx, shstrndx,
431 rel->r_offset, rel->r_info, 0);
Ulrich Drepper8a687742005-08-03 02:24:12 +0000432 }
433}
434
435
436static void
437show_relocs_rela (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data,
438 Elf_Data *symdata, Elf_Data *xndxdata, size_t symstrndx,
439 size_t shstrndx)
440{
Ulrich Drepper8a687742005-08-03 02:24:12 +0000441 int nentries = shdr->sh_size / shdr->sh_entsize;
442
443 for (int cnt = 0; cnt < nentries; ++cnt)
444 {
445 GElf_Rela relmem;
446 GElf_Rela *rel;
447
448 rel = gelf_getrela (data, cnt, &relmem);
449 if (rel != NULL)
Ulrich Drepper95fa15e2009-02-01 19:06:10 -0800450 show_relocs_x (ebl, shdr, symdata, xndxdata, symstrndx, shstrndx,
451 rel->r_offset, rel->r_info, rel->r_addend);
Ulrich Drepper8a687742005-08-03 02:24:12 +0000452 }
453}
454
455
456static bool
457section_match (Elf *elf, uint32_t scnndx, GElf_Shdr *shdr, size_t shstrndx)
458{
459 if (section_list == NULL)
460 return true;
461
462 struct section_list *runp = section_list;
463
464 do
465 {
466 if (runp->is_name)
467 {
468 if (strcmp (runp->name,
469 elf_strptr (elf, shstrndx, shdr->sh_name)) == 0)
470 return true;
471 }
472 else
473 {
474 if (runp->scnndx == scnndx)
475 return true;
476 }
477
478 runp = runp->next;
479 }
480 while (runp != NULL);
481
482 return false;
483}
484
485
486static int
487show_relocs (Ebl *ebl, const char *fname, uint32_t shstrndx)
488{
489 int elfclass = gelf_getclass (ebl->elf);
490
491 Elf_Scn *scn = NULL;
492 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
493 {
494 GElf_Shdr shdr_mem;
495 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
496
497 if (shdr == NULL)
498 INTERNAL_ERROR (fname);
499
500 if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
501 {
502 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
503 continue;
504
505 GElf_Shdr destshdr_mem;
506 GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf,
507 shdr->sh_info),
508 &destshdr_mem);
509
Ulrich Drepperf44f0ce2009-02-01 21:31:26 -0800510 printf (gettext ("\nRELOCATION RECORDS FOR [%s]:\n"
Ulrich Drepper8a687742005-08-03 02:24:12 +0000511 "%-*s TYPE VALUE\n"),
512 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
513 elfclass == ELFCLASS32 ? 8 : 16, gettext ("OFFSET"));
514
515 /* Get the data of the section. */
516 Elf_Data *data = elf_getdata (scn, NULL);
517 if (data == NULL)
518 continue;
519
520 /* Get the symbol table information. */
521 Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
522 GElf_Shdr symshdr_mem;
523 GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
524 Elf_Data *symdata = elf_getdata (symscn, NULL);
525
526 /* Search for the optional extended section index table. */
527 Elf_Data *xndxdata = NULL;
528 Elf_Scn *xndxscn = NULL;
529 while ((xndxscn = elf_nextscn (ebl->elf, xndxscn)) != NULL)
530 {
531 GElf_Shdr xndxshdr_mem;
532 GElf_Shdr *xndxshdr;
533
534 xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
535 if (xndxshdr != NULL && xndxshdr->sh_type == SHT_SYMTAB_SHNDX
536 && xndxshdr->sh_link == elf_ndxscn (symscn))
537 {
538 /* Found it. */
539 xndxdata = elf_getdata (xndxscn, NULL);
540 break;
541 }
542 }
543
544 if (shdr->sh_type == SHT_REL)
545 show_relocs_rel (ebl, shdr, data, symdata, xndxdata,
546 symshdr->sh_link, shstrndx);
547 else
548 show_relocs_rela (ebl, shdr, data, symdata, xndxdata,
549 symshdr->sh_link, shstrndx);
Ulrich Drepperf44f0ce2009-02-01 21:31:26 -0800550
Ulrich Drepper51b3f472009-02-05 22:10:39 -0800551 putchar ('\n');
Ulrich Drepper8a687742005-08-03 02:24:12 +0000552 }
553 }
554
Ulrich Drepper8a687742005-08-03 02:24:12 +0000555 return 0;
556}
557
558
559static int
560show_full_content (Ebl *ebl, const char *fname, uint32_t shstrndx)
561{
562 Elf_Scn *scn = NULL;
563 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
564 {
565 GElf_Shdr shdr_mem;
566 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
567
568 if (shdr == NULL)
569 INTERNAL_ERROR (fname);
570
571 if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0)
572 {
573 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
574 continue;
575
576 printf (gettext ("Contents of section %s:\n"),
577 elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
578
579 /* Get the data of the section. */
580 Elf_Data *data = elf_getdata (scn, NULL);
581 if (data == NULL)
582 continue;
583
584 unsigned char *cp = data->d_buf;
585 size_t cnt;
586 for (cnt = 0; cnt + 16 < data->d_size; cp += 16, cnt += 16)
587 {
588 printf (" %04zx ", cnt);
589
590 for (size_t inner = 0; inner < 16; inner += 4)
591 printf ("%02hhx%02hhx%02hhx%02hhx ",
592 cp[inner], cp[inner + 1], cp[inner + 2],
593 cp[inner + 3]);
594 fputc_unlocked (' ', stdout);
595
596 for (size_t inner = 0; inner < 16; ++inner)
597 fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner])
598 ? cp[inner] : '.', stdout);
599 fputc_unlocked ('\n', stdout);
600 }
601
602 printf (" %04zx ", cnt);
603
604 size_t remaining = data->d_size - cnt;
605 size_t inner;
606 for (inner = 0; inner + 4 <= remaining; inner += 4)
607 printf ("%02hhx%02hhx%02hhx%02hhx ",
608 cp[inner], cp[inner + 1], cp[inner + 2], cp[inner + 3]);
609
610 for (; inner < remaining; ++inner)
611 printf ("%02hhx", cp[inner]);
612
613 for (inner = 2 * (16 - inner) + (16 - inner + 3) / 4 + 1; inner > 0;
614 --inner)
615 fputc_unlocked (' ', stdout);
616
617 for (inner = 0; inner < remaining; ++inner)
618 fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner])
619 ? cp[inner] : '.', stdout);
620 fputc_unlocked ('\n', stdout);
621
622 fputc_unlocked ('\n', stdout);
623 }
624 }
625
626 return 0;
627}
628
629
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000630struct disasm_info
Ulrich Drepper8a687742005-08-03 02:24:12 +0000631{
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000632 GElf_Addr addr;
633 const uint8_t *cur;
634 const uint8_t *last_end;
635};
636
637
638// XXX This is not the preferred output for all architectures. Needs
639// XXX customization, too.
640static int
641disasm_output (char *buf, size_t buflen, void *arg)
642{
643 struct disasm_info *info = (struct disasm_info *) arg;
644
645 printf ("%8" PRIx64 ": ", (uint64_t) info->addr);
646 size_t cnt;
647 for (cnt = 0; cnt < (size_t) MIN (info->cur - info->last_end, 8); ++cnt)
648 printf (" %02" PRIx8, info->last_end[cnt]);
649 printf ("%*s %.*s\n",
650 (int) (8 - cnt) * 3 + 1, "", (int) buflen, buf);
651
652 info->addr += cnt;
653
654 /* We limit the number of bytes printed before the mnemonic to 8.
655 Print the rest on a separate, following line. */
656 if (info->cur - info->last_end > 8)
657 {
658 printf ("%8" PRIx64 ": ", (uint64_t) info->addr);
659 for (; cnt < (size_t) (info->cur - info->last_end); ++cnt)
660 printf (" %02" PRIx8, info->last_end[cnt]);
661 putchar_unlocked ('\n');
662 info->addr += info->cur - info->last_end - 8;
663 }
664
665 info->last_end = info->cur;
666
667 return 0;
668}
669
670
671static int
672show_disasm (Ebl *ebl, const char *fname, uint32_t shstrndx)
673{
674 DisasmCtx_t *ctx = disasm_begin (ebl, ebl->elf, NULL /* XXX TODO */);
675 if (ctx == NULL)
676 error (EXIT_FAILURE, 0, gettext ("cannot disassemble"));
677
678 Elf_Scn *scn = NULL;
679 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
680 {
681 GElf_Shdr shdr_mem;
682 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
683
684 if (shdr == NULL)
685 INTERNAL_ERROR (fname);
686
687 if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0
688 && (shdr->sh_flags & SHF_EXECINSTR) != 0)
689 {
690 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
691 continue;
692
693 Elf_Data *data = elf_getdata (scn, NULL);
694 if (data == NULL)
695 continue;
696
697 printf ("Disassembly of section %s:\n\n",
698 elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
699
700 struct disasm_info info;
701 info.addr = shdr->sh_addr;
702 info.last_end = info.cur = data->d_buf;
703
704 disasm_cb (ctx, &info.cur, info.cur + data->d_size, info.addr,
Ulrich Drepperfd479892008-01-12 03:06:47 +0000705 "%7m %.1o,%.2o,%.3o%34a %l", disasm_output, &info,
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000706 NULL /* XXX */);
707 }
708 }
709
710 (void) disasm_end (ctx);
Ulrich Drepper8a687742005-08-03 02:24:12 +0000711
712 return 0;
713}
714
715
716static int
717handle_elf (Elf *elf, const char *prefix, const char *fname,
718 const char *suffix)
719{
720
721 /* Get the backend for this object file type. */
722 Ebl *ebl = ebl_openbackend (elf);
723
Ulrich Drepperfd479892008-01-12 03:06:47 +0000724 printf ("%s: elf%d-%s\n\n",
Ulrich Drepper8a687742005-08-03 02:24:12 +0000725 fname, gelf_getclass (elf) == ELFCLASS32 ? 32 : 64,
726 ebl_backend_name (ebl));
727
728 /* Create the full name of the file. */
729 size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
730 size_t suffix_len = suffix == NULL ? 0 : strlen (suffix);
731 size_t fname_len = strlen (fname) + 1;
732 char fullname[prefix_len + 1 + fname_len + suffix_len];
733 char *cp = fullname;
734 if (prefix != NULL)
735 cp = mempcpy (cp, prefix, prefix_len);
736 cp = mempcpy (cp, fname, fname_len);
737 if (suffix != NULL)
738 memcpy (cp - 1, suffix, suffix_len + 1);
739
740 /* Get the section header string table index. */
741 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -0700742 if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
Ulrich Drepper8a687742005-08-03 02:24:12 +0000743 error (EXIT_FAILURE, 0,
744 gettext ("cannot get section header string table index"));
745
746 int result = 0;
747 if (print_disasm)
748 result = show_disasm (ebl, fullname, shstrndx);
749 if (print_relocs && !print_disasm)
750 result = show_relocs (ebl, fullname, shstrndx);
751 if (print_full_content)
752 result = show_full_content (ebl, fullname, shstrndx);
753
754 /* Close the ELF backend library descriptor. */
755 ebl_closebackend (ebl);
756
757 return result;
758}
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000759
760
761#include "debugpred.h"