blob: ebad25d5228b0a8f7a9d036fc7c4ae71ed2961d2 [file] [log] [blame]
Ulrich Drepper8a687742005-08-03 02:24:12 +00001/* Print information from ELF file in human-readable form.
Ulrich Drepper3a64a302012-01-21 18:19:24 -05002 Copyright (C) 2005, 2006, 2007, 2009, 2011, 2012 Red Hat, Inc.
Mark Wielaardde2ed972012-06-05 17:15:16 +02003 This file is part of elfutils.
Ulrich Drepper8a687742005-08-03 02:24:12 +00004 Written by Ulrich Drepper <drepper@redhat.com>, 2005.
5
Mark Wielaardde2ed972012-06-05 17:15:16 +02006 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.
Ulrich Drepper8a687742005-08-03 02:24:12 +000010
Mark Wielaardde2ed972012-06-05 17:15:16 +020011 elfutils is distributed in the hope that it will be useful, but
Ulrich Drepper361df7d2006-04-04 21:38:57 +000012 WITHOUT ANY WARRANTY; without even the implied warranty of
Mark Wielaardde2ed972012-06-05 17:15:16 +020013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
Ulrich Drepper361df7d2006-04-04 21:38:57 +000015
Mark Wielaardde2ed972012-06-05 17:15:16 +020016 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/>. */
Ulrich Drepper8a687742005-08-03 02:24:12 +000018
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. */
43static void print_version (FILE *stream, struct argp_state *state);
Ulrich Drepperfdc93e12009-01-17 11:47:10 -080044ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
Ulrich Drepper8a687742005-08-03 02:24:12 +000045
46/* Bug report address. */
Ulrich Drepperfdc93e12009-01-17 11:47:10 -080047ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
Ulrich Drepper8a687742005-08-03 02:24:12 +000048
49
50/* Definitions of arguments for argp functions. */
51static 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
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -050060 { NULL, 0, NULL, 0, N_("Output content selection:"), 0 },
Ulrich Drepper8a687742005-08-03 02:24:12 +000061 { "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. */
68static const char doc[] = N_("\
69Show information from FILEs (a.out by default).");
70
71/* Strings for arguments in help texts. */
72static const char args_doc[] = N_("[FILE...]");
73
74/* Prototype for option handler. */
75static error_t parse_opt (int key, char *arg, struct argp_state *state);
76
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -050077/* Parser children. */
78static struct argp_child argp_children[] =
79 {
80 { &color_argp, 0, N_("Output formatting"), 2 },
81 { NULL, 0, NULL, 0}
82 };
83
Ulrich Drepper8a687742005-08-03 02:24:12 +000084/* Data structure to communicate with argp functions. */
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -050085static const struct argp argp =
Ulrich Drepper8a687742005-08-03 02:24:12 +000086{
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -050087 options, parse_opt, args_doc, doc, argp_children, NULL, NULL
Ulrich Drepper8a687742005-08-03 02:24:12 +000088};
89
90
91/* Print symbols in file named FNAME. */
92static int process_file (const char *fname, bool more_than_one);
93
94/* Handle content of archive. */
95static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
96 const char *suffix);
97
98/* Handle ELF file. */
99static 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"), \
Ulrich Drepperb0243862007-06-06 00:09:36 +0000105 fname, __LINE__, PACKAGE_VERSION, __DATE__, elf_errmsg (-1))
Ulrich Drepper8a687742005-08-03 02:24:12 +0000106
107
108/* List of sections which should be used. */
109static 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. */
122static bool print_relocs;
123
124/* If true print full contents of requested sections. */
125static bool print_full_content;
126
127/* If true print disassembled output.. */
128static bool print_disasm;
129
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -0500130
Ulrich Drepper8a687742005-08-03 02:24:12 +0000131int
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 Drepper3a64a302012-01-21 18:19:24 -0500185"), "2012");
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 {
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -0500502 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
Ulrich Drepper8a687742005-08-03 02:24:12 +0000503 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 {
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -0500573 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
Ulrich Drepper8a687742005-08-03 02:24:12 +0000574 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;
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -0500635 const char *address_color;
636 const char *bytes_color;
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000637};
638
639
640// XXX This is not the preferred output for all architectures. Needs
641// XXX customization, too.
642static int
643disasm_output (char *buf, size_t buflen, void *arg)
644{
645 struct disasm_info *info = (struct disasm_info *) arg;
646
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -0500647 if (info->address_color != NULL)
648 printf ("%s%8" PRIx64 "%s: ",
649 info->address_color, (uint64_t) info->addr, color_off);
650 else
651 printf ("%8" PRIx64 ": ", (uint64_t) info->addr);
652
653 if (info->bytes_color != NULL)
654 fputs_unlocked (info->bytes_color, stdout);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000655 size_t cnt;
656 for (cnt = 0; cnt < (size_t) MIN (info->cur - info->last_end, 8); ++cnt)
657 printf (" %02" PRIx8, info->last_end[cnt]);
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -0500658 if (info->bytes_color != NULL)
659 fputs_unlocked (color_off, stdout);
660
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000661 printf ("%*s %.*s\n",
662 (int) (8 - cnt) * 3 + 1, "", (int) buflen, buf);
663
664 info->addr += cnt;
665
666 /* We limit the number of bytes printed before the mnemonic to 8.
667 Print the rest on a separate, following line. */
668 if (info->cur - info->last_end > 8)
669 {
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -0500670 if (info->address_color != NULL)
671 printf ("%s%8" PRIx64 "%s: ",
672 info->address_color, (uint64_t) info->addr, color_off);
673 else
674 printf ("%8" PRIx64 ": ", (uint64_t) info->addr);
675
676 if (info->bytes_color != NULL)
677 fputs_unlocked (info->bytes_color, stdout);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000678 for (; cnt < (size_t) (info->cur - info->last_end); ++cnt)
679 printf (" %02" PRIx8, info->last_end[cnt]);
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -0500680 if (info->bytes_color != NULL)
681 fputs_unlocked (color_off, stdout);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000682 putchar_unlocked ('\n');
683 info->addr += info->cur - info->last_end - 8;
684 }
685
686 info->last_end = info->cur;
687
688 return 0;
689}
690
691
692static int
693show_disasm (Ebl *ebl, const char *fname, uint32_t shstrndx)
694{
695 DisasmCtx_t *ctx = disasm_begin (ebl, ebl->elf, NULL /* XXX TODO */);
696 if (ctx == NULL)
697 error (EXIT_FAILURE, 0, gettext ("cannot disassemble"));
698
699 Elf_Scn *scn = NULL;
700 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
701 {
702 GElf_Shdr shdr_mem;
703 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
704
705 if (shdr == NULL)
706 INTERNAL_ERROR (fname);
707
708 if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0
709 && (shdr->sh_flags & SHF_EXECINSTR) != 0)
710 {
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -0500711 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000712 continue;
713
714 Elf_Data *data = elf_getdata (scn, NULL);
715 if (data == NULL)
716 continue;
717
718 printf ("Disassembly of section %s:\n\n",
719 elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
720
721 struct disasm_info info;
722 info.addr = shdr->sh_addr;
723 info.last_end = info.cur = data->d_buf;
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -0500724 char *fmt;
725 if (color_mode)
726 {
727 info.address_color = color_address;
728 info.bytes_color = color_bytes;
729
730 if (asprintf (&fmt, "%s%%7m %s%%.1o,%s%%.2o,%s%%.3o%%34a %s%%l",
731 color_mnemonic ?: "",
732 color_operand1 ?: "",
733 color_operand2 ?: "",
734 color_operand3 ?: "",
735 color_label ?: "") < 0)
736 error (EXIT_FAILURE, errno, _("cannot allocate memory"));
737 }
738 else
739 {
740 info.address_color = info.bytes_color = NULL;
741
742 fmt = "%7m %.1o,%.2o,%.3o%34a %l";
743 }
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000744
745 disasm_cb (ctx, &info.cur, info.cur + data->d_size, info.addr,
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -0500746 fmt, disasm_output, &info, NULL /* XXX */);
747
748 if (color_mode)
749 free (fmt);
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000750 }
751 }
752
753 (void) disasm_end (ctx);
Ulrich Drepper8a687742005-08-03 02:24:12 +0000754
755 return 0;
756}
757
758
759static int
760handle_elf (Elf *elf, const char *prefix, const char *fname,
761 const char *suffix)
762{
763
764 /* Get the backend for this object file type. */
765 Ebl *ebl = ebl_openbackend (elf);
766
Ulrich Drepperfd479892008-01-12 03:06:47 +0000767 printf ("%s: elf%d-%s\n\n",
Ulrich Drepper8a687742005-08-03 02:24:12 +0000768 fname, gelf_getclass (elf) == ELFCLASS32 ? 32 : 64,
769 ebl_backend_name (ebl));
770
771 /* Create the full name of the file. */
772 size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
773 size_t suffix_len = suffix == NULL ? 0 : strlen (suffix);
774 size_t fname_len = strlen (fname) + 1;
775 char fullname[prefix_len + 1 + fname_len + suffix_len];
776 char *cp = fullname;
777 if (prefix != NULL)
778 cp = mempcpy (cp, prefix, prefix_len);
779 cp = mempcpy (cp, fname, fname_len);
780 if (suffix != NULL)
781 memcpy (cp - 1, suffix, suffix_len + 1);
782
783 /* Get the section header string table index. */
784 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -0700785 if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
Ulrich Drepper8a687742005-08-03 02:24:12 +0000786 error (EXIT_FAILURE, 0,
787 gettext ("cannot get section header string table index"));
788
789 int result = 0;
790 if (print_disasm)
791 result = show_disasm (ebl, fullname, shstrndx);
792 if (print_relocs && !print_disasm)
793 result = show_relocs (ebl, fullname, shstrndx);
794 if (print_full_content)
795 result = show_full_content (ebl, fullname, shstrndx);
796
797 /* Close the ELF backend library descriptor. */
798 ebl_closebackend (ebl);
799
800 return result;
801}
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000802
803
804#include "debugpred.h"