remove d30v sanitization
[binutils-gdb.git] / binutils / readelf.c
1 /* readelf.c -- display contents of an ELF format file
2 Copyright (C) 1998 Free Software Foundation, Inc.
3
4 Originally developed by Eric Youngdale <eric@andante.jic.com>
5 Modifications by Nick Clifton <nickc@cygnus.com>
6
7 This file is part of GNU Binutils.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 02111-1307, USA. */
23 \f
24
25 #include <assert.h>
26 #include <sys/stat.h>
27 #include <stdio.h>
28 #include <time.h>
29
30 #include "bfd.h"
31
32 #include "elf/common.h"
33 #include "elf/external.h"
34 #include "elf/internal.h"
35
36 /* The following headers use the elf/reloc-macros.h file to
37 automatically generate relocation recognition functions
38 such as elf_mips_reloc_type() */
39
40 #define RELOC_MACROS_GEN_FUNC
41
42 #include "elf/i386.h"
43 #include "elf/v850.h"
44 #include "elf/ppc.h"
45 #include "elf/mips.h"
46 #include "elf/alpha.h"
47 #include "elf/arm.h"
48 #include "elf/m68k.h"
49 #include "elf/sparc.h"
50 #include "elf/m32r.h"
51 #include "elf/d10v.h"
52 #include "elf/d30v.h"
53 #include "elf/sh.h"
54 #include "elf/mn10200.h"
55 #include "elf/mn10300.h"
56 #include "elf/hppa.h"
57 #include "elf/arc.h"
58
59 #include "bucomm.h"
60 #include "getopt.h"
61
62 #ifdef ANSI_PROTOTYPES
63 #include <stdarg.h>
64 #else
65 #include <varargs.h>
66 #endif
67
68 char * program_name = "readelf";
69 unsigned int dynamic_addr;
70 unsigned int dynamic_size;
71 unsigned int rela_addr;
72 unsigned int rela_size;
73 char * dynamic_strings;
74 char * string_table;
75 Elf_Internal_Sym * dynamic_symbols;
76 char program_interpreter [64];
77 int dynamic_info [DT_JMPREL + 1];
78 int version_info [16];
79 int loadaddr = 0;
80 Elf_Internal_Ehdr elf_header;
81 Elf_Internal_Shdr * section_headers;
82 Elf_Internal_Dyn * dynamic_segment;
83 int show_name;
84 int do_dynamic;
85 int do_syms;
86 int do_reloc;
87 int do_sections;
88 int do_segments;
89 int do_using_dynamic;
90 int do_header;
91 int do_dump;
92 int do_version;
93
94 static unsigned long int (* byte_get) PARAMS ((unsigned char *, int));
95
96 #define NUM_DUMP_SECTS 100
97 char dump_sects [NUM_DUMP_SECTS];
98
99 #define HEX_DUMP 1
100 #define DISASS_DUMP 2
101
102 /* Forward declarations for dumb compilers. */
103 static const char * get_mips_dynamic_type PARAMS ((unsigned long type));
104 static const char * get_dynamic_type PARAMS ((unsigned long type));
105 static int dump_relocations
106 PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Sym *, char *));
107 static char * get_file_type PARAMS ((unsigned e_type));
108 static char * get_machine_name PARAMS ((unsigned e_machine));
109 static char * get_machine_data PARAMS ((unsigned e_data));
110 static char * get_machine_flags PARAMS ((unsigned, unsigned e_machine));
111 static const char * get_mips_segment_type PARAMS ((unsigned long type));
112 static const char * get_segment_type PARAMS ((unsigned long p_type));
113 static const char * get_mips_section_type_name PARAMS ((unsigned int sh_type));
114 static const char * get_section_type_name PARAMS ((unsigned int sh_type));
115 static char * get_symbol_binding PARAMS ((unsigned int binding));
116 static char * get_symbol_type PARAMS ((unsigned int type));
117 static void usage PARAMS ((void));
118 static void parse_args PARAMS ((int argc, char ** argv));
119 static int process_file_header PARAMS ((void));
120 static int process_program_headers PARAMS ((FILE *));
121 static int process_section_headers PARAMS ((FILE *));
122 static void dynamic_segment_mips_val PARAMS ((Elf_Internal_Dyn *entry));
123 static int process_dynamic_segment PARAMS ((FILE *));
124 static int process_symbol_table PARAMS ((FILE *));
125 static int process_section_contents PARAMS ((FILE *));
126 static void process_file PARAMS ((char * file_name));
127 static int process_relocs PARAMS ((FILE *));
128 static int process_version_sections PARAMS ((FILE *));
129 static char * get_ver_flags PARAMS ((unsigned int flags));
130 static char * get_symbol_index_type PARAMS ((unsigned int type));
131 static int get_section_headers PARAMS ((FILE * file));
132 static int get_file_header PARAMS ((FILE * file));
133 static Elf_Internal_Sym * get_elf_symbols
134 PARAMS ((FILE * file, unsigned long offset, unsigned long number));
135 static int * get_dynamic_data PARAMS ((FILE * file, unsigned int number));
136
137 typedef int Elf32_Word;
138
139 #define SECTION_NAME(X) (string_table + (X)->sh_name)
140
141 #define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
142
143 #define BYTE_GET(field) byte_get (field, sizeof (field))
144
145 #define NUM_ELEM(array) (sizeof (array) / sizeof ((array)[0]))
146
147 #define GET_DATA_ALLOC(offset, size, var, type, reason) \
148 if (fseek (file, offset, SEEK_SET)) \
149 { \
150 error (_("Unable to seek to start of %s at %x\n"), reason, offset); \
151 return 0; \
152 } \
153 \
154 var = (type) malloc (size); \
155 \
156 if (var == NULL) \
157 { \
158 error (_("Out of memory allocating %d bytes for %s\n"), size, reason); \
159 return 0; \
160 } \
161 \
162 if (fread (var, size, 1, file) != 1) \
163 { \
164 error (_("Unable to read in %d bytes of %s\n"), size, reason); \
165 free (var); \
166 var = NULL; \
167 return 0; \
168 }
169
170
171 #define GET_DATA(offset, var, reason) \
172 if (fseek (file, offset, SEEK_SET)) \
173 { \
174 error (_("Unable to seek to %x for %s\n"), offset, reason); \
175 return 0; \
176 } \
177 else if (fread (& var, sizeof (var), 1, file) != 1) \
178 { \
179 error (_("Unable to read data at %x for %s\n"), offset, reason); \
180 return 0; \
181 }
182
183 #ifdef ANSI_PROTOTYPES
184 static void
185 error (const char * message, ...)
186 {
187 va_list args;
188
189 fprintf (stderr, _("%s: Error: "), program_name);
190 va_start (args, message);
191 vfprintf (stderr, message, args);
192 va_end (args);
193 return;
194 }
195
196 static void
197 warn (const char * message, ...)
198 {
199 va_list args;
200
201 fprintf (stderr, _("%s: Warning: "), program_name);
202 va_start (args, message);
203 vfprintf (stderr, message, args);
204 va_end (args);
205 return;
206 }
207 #else
208 static void
209 error (va_alist)
210 va_dcl
211 {
212 char * message;
213 va_list args;
214
215 fprintf (stderr, _("%s: Error: "), program_name);
216 va_start (args);
217 message = va_arg (args, char *);
218 vfprintf (stderr, message, args);
219 va_end (args);
220 return;
221 }
222
223 static void
224 warn (va_alist)
225 va_dcl
226 {
227 char * message;
228 va_list args;
229
230 fprintf (stderr, _("%s: Warning: "), program_name);
231 va_start (args);
232 message = va_arg (args, char *);
233 vfprintf (stderr, message, args);
234 va_end (args);
235 return;
236 }
237 #endif
238
239 static unsigned long int
240 byte_get_little_endian (field, size)
241 unsigned char * field;
242 int size;
243 {
244 switch (size)
245 {
246 case 1:
247 return * field;
248
249 case 2:
250 return ((unsigned int) (field [0]))
251 | (((unsigned int) (field [1])) << 8);
252
253 case 4:
254 return ((unsigned long) (field [0]))
255 | (((unsigned long) (field [1])) << 8)
256 | (((unsigned long) (field [2])) << 16)
257 | (((unsigned long) (field [3])) << 24);
258
259 default:
260 error (_("Unhandled data length: %d\n"), size);
261 abort();
262 }
263 }
264
265 static unsigned long int
266 byte_get_big_endian (field, size)
267 unsigned char * field;
268 int size;
269 {
270 switch (size)
271 {
272 case 1:
273 return * field;
274
275 case 2:
276 return ((unsigned int) (field [1])) | (((int) (field [0])) << 8);
277
278 case 4:
279 return ((unsigned long) (field [3]))
280 | (((unsigned long) (field [2])) << 8)
281 | (((unsigned long) (field [1])) << 16)
282 | (((unsigned long) (field [0])) << 24);
283
284 default:
285 error (_("Unhandled data length: %d\n"), size);
286 abort();
287 }
288 }
289
290
291 /* Display the contents of the relocation data
292 found at the specified offset. */
293 static int
294 dump_relocations (file, rel_offset, rel_size, symtab, strtab)
295 FILE * file;
296 unsigned long rel_offset;
297 unsigned long rel_size;
298 Elf_Internal_Sym * symtab;
299 char * strtab;
300 {
301 unsigned int i;
302 int is_rela;
303 Elf_Internal_Rel * rels;
304 Elf_Internal_Rela * relas;
305
306
307 /* Compute number of relocations and read them in. */
308 switch (elf_header.e_machine)
309 {
310 case EM_386:
311 case EM_486:
312 case EM_CYGNUS_M32R:
313 case EM_CYGNUS_D10V:
314 case EM_MIPS:
315 case EM_MIPS_RS4_BE:
316 case EM_ARM:
317 {
318 Elf32_External_Rel * erels;
319
320 GET_DATA_ALLOC (rel_offset, rel_size, erels,
321 Elf32_External_Rel *, "relocs");
322
323 rel_size = rel_size / sizeof (Elf32_External_Rel);
324
325 rels = (Elf_Internal_Rel *) malloc (rel_size *
326 sizeof (Elf_Internal_Rel));
327
328 for (i = 0; i < rel_size; i++)
329 {
330 rels[i].r_offset = BYTE_GET (erels[i].r_offset);
331 rels[i].r_info = BYTE_GET (erels[i].r_info);
332 }
333
334 free (erels);
335
336 is_rela = 0;
337 relas = (Elf_Internal_Rela *) rels;
338 }
339 break;
340
341 case EM_68K:
342 case EM_SPARC:
343 case EM_PPC:
344 case EM_CYGNUS_V850:
345 case EM_CYGNUS_D30V:
346 case EM_CYGNUS_MN10200:
347 case EM_CYGNUS_MN10300:
348 case EM_SH:
349 case EM_ALPHA:
350 {
351 Elf32_External_Rela * erelas;
352
353 GET_DATA_ALLOC (rel_offset, rel_size, erelas,
354 Elf32_External_Rela *, "relocs");
355
356 rel_size = rel_size / sizeof (Elf32_External_Rela);
357
358 relas = (Elf_Internal_Rela *) malloc (rel_size *
359 sizeof (Elf_Internal_Rela));
360
361 for (i = 0; i < rel_size; i++)
362 {
363 relas[i].r_offset = BYTE_GET (erelas[i].r_offset);
364 relas[i].r_info = BYTE_GET (erelas[i].r_info);
365 relas[i].r_addend = BYTE_GET (erelas[i].r_addend);
366 }
367
368 free (erelas);
369
370 is_rela = 1;
371 rels = (Elf_Internal_Rel *) relas;
372 }
373 break;
374
375 default:
376 warn (_("Don't know about relocations on this machine architecture\n"));
377 return 0;
378 }
379
380 if (is_rela)
381 printf
382 (_(" Offset Value Type Symbol's Value Symbol's Name Addend\n"));
383 else
384 printf
385 (_(" Offset Value Type Symbol's Value Symbol's Name\n"));
386
387 for (i = 0; i < rel_size; i++)
388 {
389 const char * rtype;
390 unsigned long offset;
391 unsigned long info;
392 int symtab_index;
393
394 if (is_rela)
395 {
396 offset = relas [i].r_offset;
397 info = relas [i].r_info;
398 }
399 else
400 {
401 offset = rels [i].r_offset;
402 info = rels [i].r_info;
403 }
404
405 printf (" %8.8lx %5.5lx ", offset, info);
406
407 switch (elf_header.e_machine)
408 {
409 default:
410 rtype = NULL;
411 break;
412
413 case EM_CYGNUS_M32R:
414 rtype = elf_m32r_reloc_type (ELF32_R_TYPE (info));
415 break;
416
417 case EM_386:
418 case EM_486:
419 rtype = elf_i386_reloc_type (ELF32_R_TYPE (info));
420 break;
421
422 case EM_68K:
423 rtype = elf_m68k_reloc_type (ELF32_R_TYPE (info));
424 break;
425
426 case EM_SPARC:
427 rtype = elf_sparc_reloc_type (ELF32_R_TYPE (info));
428 break;
429
430 case EM_CYGNUS_V850:
431 rtype = v850_reloc_type (ELF32_R_TYPE (info));
432 break;
433
434 case EM_CYGNUS_D10V:
435 rtype = elf_d10v_reloc_type (ELF32_R_TYPE (info));
436 break;
437
438 case EM_CYGNUS_D30V:
439 rtype = elf_d30v_reloc_type (ELF32_R_TYPE (info));
440 break;
441
442 case EM_SH:
443 rtype = elf_sh_reloc_type (ELF32_R_TYPE (info));
444 break;
445
446 case EM_CYGNUS_MN10300:
447 rtype = elf_mn10300_reloc_type (ELF32_R_TYPE (info));
448 break;
449
450 case EM_CYGNUS_MN10200:
451 rtype = elf_mn10200_reloc_type (ELF32_R_TYPE (info));
452 break;
453
454 case EM_PPC:
455 rtype = elf_ppc_reloc_type (ELF32_R_TYPE (info));
456 break;
457
458 case EM_MIPS:
459 case EM_MIPS_RS4_BE:
460 rtype = elf_mips_reloc_type (ELF32_R_TYPE (info));
461 break;
462
463 case EM_ALPHA:
464 rtype = elf_alpha_reloc_type (ELF32_R_TYPE (info));
465 break;
466
467 case EM_ARM:
468 rtype = elf_arm_reloc_type (ELF32_R_TYPE (info));
469 break;
470
471 case EM_CYGNUS_ARC:
472 rtype = elf_arc_reloc_type (ELF32_R_TYPE (info));
473 break;
474
475 case EM_PARISC:
476 rtype = elf32_hppa_reloc_type (ELF32_R_TYPE (info));
477 break;
478 }
479
480 if (rtype == NULL)
481 printf (_("unrecognised: %-7x"), ELF32_R_TYPE (info));
482 else
483 printf ("%-21.21s", rtype);
484
485 symtab_index = ELF32_R_SYM (info);
486
487 if (symtab_index && symtab != NULL)
488 {
489 Elf_Internal_Sym * psym;
490
491 psym = symtab + symtab_index;
492
493 printf (" %08lx ", (unsigned long) psym->st_value);
494
495 if (psym->st_name == 0)
496 printf ("%-25.25s",
497 SECTION_NAME (section_headers + psym->st_shndx));
498 else if (strtab == NULL)
499 printf (_("<string table index %3d>"), psym->st_name);
500 else
501 printf ("%-25.25s", strtab + psym->st_name);
502
503 if (is_rela)
504 printf (" + %lx", (unsigned long) relas [i].r_addend);
505 }
506
507 putchar ('\n');
508 }
509
510 free (relas);
511
512 return 1;
513 }
514
515 static const char *
516 get_mips_dynamic_type (type)
517 unsigned long type;
518 {
519 switch (type)
520 {
521 case DT_MIPS_RLD_VERSION: return "MIPS_RLD_VERSION";
522 case DT_MIPS_TIME_STAMP: return "MIPS_TIME_STAMP";
523 case DT_MIPS_ICHECKSUM: return "MIPS_ICHECKSUM";
524 case DT_MIPS_IVERSION: return "MIPS_IVERSION";
525 case DT_MIPS_FLAGS: return "MIPS_FLAGS";
526 case DT_MIPS_BASE_ADDRESS: return "MIPS_BASE_ADDRESS";
527 case DT_MIPS_MSYM: return "MIPS_MSYM";
528 case DT_MIPS_CONFLICT: return "MIPS_CONFLICT";
529 case DT_MIPS_LIBLIST: return "MIPS_LIBLIST";
530 case DT_MIPS_LOCAL_GOTNO: return "MIPS_LOCAL_GOTNO";
531 case DT_MIPS_CONFLICTNO: return "MIPS_CONFLICTNO";
532 case DT_MIPS_LIBLISTNO: return "MIPS_LIBLISTNO";
533 case DT_MIPS_SYMTABNO: return "MIPS_SYMTABNO";
534 case DT_MIPS_UNREFEXTNO: return "MIPS_UNREFEXTNO";
535 case DT_MIPS_GOTSYM: return "MIPS_GOTSYM";
536 case DT_MIPS_HIPAGENO: return "MIPS_HIPAGENO";
537 case DT_MIPS_RLD_MAP: return "MIPS_RLD_MAP";
538 case DT_MIPS_DELTA_CLASS: return "MIPS_DELTA_CLASS";
539 case DT_MIPS_DELTA_CLASS_NO: return "MIPS_DELTA_CLASS_NO";
540 case DT_MIPS_DELTA_INSTANCE: return "MIPS_DELTA_INSTANCE";
541 case DT_MIPS_DELTA_INSTANCE_NO: return "MIPS_DELTA_INSTANCE_NO";
542 case DT_MIPS_DELTA_RELOC: return "MIPS_DELTA_RELOC";
543 case DT_MIPS_DELTA_RELOC_NO: return "MIPS_DELTA_RELOC_NO";
544 case DT_MIPS_DELTA_SYM: return "MIPS_DELTA_SYM";
545 case DT_MIPS_DELTA_SYM_NO: return "MIPS_DELTA_SYM_NO";
546 case DT_MIPS_DELTA_CLASSSYM: return "MIPS_DELTA_CLASSSYM";
547 case DT_MIPS_DELTA_CLASSSYM_NO: return "MIPS_DELTA_CLASSSYM_NO";
548 case DT_MIPS_CXX_FLAGS: return "MIPS_CXX_FLAGS";
549 case DT_MIPS_PIXIE_INIT: return "MIPS_PIXIE_INIT";
550 case DT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB";
551 case DT_MIPS_LOCALPAGE_GOTIDX: return "MIPS_LOCALPAGE_GOTIDX";
552 case DT_MIPS_LOCAL_GOTIDX: return "MIPS_LOCAL_GOTIDX";
553 case DT_MIPS_HIDDEN_GOTIDX: return "MIPS_HIDDEN_GOTIDX";
554 case DT_MIPS_PROTECTED_GOTIDX: return "MIPS_PROTECTED_GOTIDX";
555 case DT_MIPS_OPTIONS: return "MIPS_OPTIONS";
556 case DT_MIPS_INTERFACE: return "MIPS_INTERFACE";
557 case DT_MIPS_DYNSTR_ALIGN: return "MIPS_DYNSTR_ALIGN";
558 case DT_MIPS_INTERFACE_SIZE: return "MIPS_INTERFACE_SIZE";
559 case DT_MIPS_RLD_TEXT_RESOLVE_ADDR: return "MIPS_RLD_TEXT_RESOLVE_ADDR";
560 case DT_MIPS_PERF_SUFFIX: return "MIPS_PERF_SUFFIX";
561 case DT_MIPS_COMPACT_SIZE: return "MIPS_COMPACT_SIZE";
562 case DT_MIPS_GP_VALUE: return "MIPS_GP_VALUE";
563 case DT_MIPS_AUX_DYNAMIC: return "MIPS_AUX_DYNAMIC";
564 default:
565 return NULL;
566 }
567 }
568
569 static const char *
570 get_dynamic_type (type)
571 unsigned long type;
572 {
573 static char buff [32];
574
575 switch (type)
576 {
577 case DT_NULL: return _("NULL");
578 case DT_NEEDED: return _("NEEDED");
579 case DT_PLTRELSZ: return _("PLTRELSZ");
580 case DT_PLTGOT: return _("PLTGOT");
581 case DT_HASH: return _("HASH");
582 case DT_STRTAB: return _("STRTAB");
583 case DT_SYMTAB: return _("SYMTAB");
584 case DT_RELA: return _("RELA");
585 case DT_RELASZ: return _("RELASZ");
586 case DT_RELAENT: return _("RELAENT");
587 case DT_STRSZ: return _("STRSZ");
588 case DT_SYMENT: return _("SYMENT");
589 case DT_INIT: return _("INIT");
590 case DT_FINI: return _("FINI");
591 case DT_SONAME: return _("SONAME");
592 case DT_RPATH: return _("RPATH");
593 case DT_SYMBOLIC: return _("SYMBOLIC");
594 case DT_REL: return _("REL");
595 case DT_RELSZ: return _("RELSZ");
596 case DT_RELENT: return _("RELENT");
597 case DT_PLTREL: return _("PLTREL");
598 case DT_DEBUG: return _("DEBUG");
599 case DT_TEXTREL: return _("TEXTREL");
600 case DT_JMPREL: return _("JMPREL");
601 case DT_VERDEF: return _("VERDEF");
602 case DT_VERDEFNUM: return _("VERDEFNUM");
603 case DT_VERNEED: return _("VERNEED");
604 case DT_VERNEEDNUM: return _("VERNEEDNUM");
605 case DT_VERSYM: return _("VERSYN");
606 case DT_AUXILIARY: return _("AUXILARY");
607 case DT_FILTER: return _("FILTER");
608
609 default:
610 if ((type >= DT_LOPROC) && (type <= DT_HIPROC))
611 {
612 const char *result = NULL;
613 switch (elf_header.e_machine)
614 {
615 case EM_MIPS:
616 case EM_MIPS_RS4_BE:
617 result = get_mips_dynamic_type (type);
618 default:
619 }
620
621 if (result == NULL)
622 {
623 sprintf (buff, _("Processor Specific: (%x)"), type);
624 result = buff;
625 }
626 return result;
627 }
628 else
629 sprintf (buff, _("<unknown>: %x"), type);
630 return buff;
631 }
632 }
633
634 static char *
635 get_file_type (e_type)
636 unsigned e_type;
637 {
638 static char buff [32];
639
640 switch (e_type)
641 {
642 case ET_NONE: return _("NONE (None)");
643 case ET_REL: return _("REL (Relocatable file)");
644 case ET_EXEC: return _("EXEC (Executable file)");
645 case ET_DYN: return _("DYN (Shared object file)");
646 case ET_CORE: return _("CORE (Core file)");
647
648 default:
649 if ((e_type >= ET_LOPROC) && (e_type <= ET_HIPROC))
650 sprintf (buff, _("Processor Specific: (%x)"), e_type);
651 else
652 sprintf (buff, _("<unknown>: %x"), e_type);
653 return buff;
654 }
655 }
656
657 static char *
658 get_machine_name (e_machine)
659 unsigned e_machine;
660 {
661 static char buff [32];
662
663 switch (e_machine)
664 {
665 case EM_NONE: return _("None");
666 case EM_M32: return "WE32100";
667 case EM_SPARC: return "Sparc";
668 case EM_386: return "Intel 80386";
669 case EM_68K: return "MC68000";
670 case EM_88K: return "MC88000";
671 case EM_486: return "Intel 80486";
672 case EM_860: return "Intel 80860";
673 case EM_MIPS: return "MIPS R3000 big-endian";
674 case EM_S370: return "Amdahl";
675 case EM_MIPS_RS4_BE: return "MIPS R4000 big-endian";
676 case EM_OLD_SPARCV9: return "Sparc v9 (old)";
677 case EM_PARISC: return "HPPA";
678 case EM_PPC_OLD: return "Power PC (old)";
679 case EM_SPARC32PLUS: return "Sparc v8+" ;
680 case EM_960: return "Intel 90860";
681 case EM_PPC: return "PowerPC";
682 case EM_V800: return "NEC V800";
683 case EM_FR20: return "Fujitsu FR20";
684 case EM_RH32: return "TRW RH32";
685 case EM_MMA: return "Fujitsu MMA";
686 case EM_ARM: return "ARM";
687 case EM_OLD_ALPHA: return "Digital Alpha (old)";
688 case EM_SH: return "Hitachi SH";
689 case EM_SPARCV9: return "Sparc v9";
690 case EM_ALPHA: return "Alpha";
691 case EM_CYGNUS_D10V: return "d10v";
692 case EM_CYGNUS_D30V: return "d30v";
693 case EM_CYGNUS_ARC: return "Arc";
694 case EM_CYGNUS_M32R: return "M32r";
695 case EM_CYGNUS_V850: return "v850";
696 case EM_CYGNUS_MN10300: return "mn10300";
697 case EM_CYGNUS_MN10200: return "mn10200";
698
699 default:
700 sprintf (buff, _("<unknown>: %x"), e_machine);
701 return buff;
702 }
703 }
704
705 static char *
706 get_machine_flags (e_flags, e_machine)
707 unsigned e_flags;
708 unsigned e_machine;
709 {
710 static char buf [1024];
711
712 buf[0] = '\0';
713 if (e_flags)
714 {
715 switch (e_machine)
716 {
717 default:
718 break;
719
720 case EM_PPC:
721 if (e_flags & EF_PPC_EMB)
722 strcat (buf, ", emb");
723
724 if (e_flags & EF_PPC_RELOCATABLE)
725 strcat (buf, ", relocatable");
726
727 if (e_flags & EF_PPC_RELOCATABLE_LIB)
728 strcat (buf, ", relocatable-lib");
729 break;
730
731 case EM_CYGNUS_M32R:
732 if ((e_flags & EF_M32R_ARCH) == E_M32R_ARCH)
733 strcat (buf, ", m32r");
734
735 /* start-sanitize-m32rx */
736 #ifdef E_M32RX_ARCH
737 if ((e_flags & EF_M32R_ARCH) == E_M32RX_ARCH)
738 strcat (buf, ", m32rx");
739 #endif
740 /* end-sanitize-m32rx */
741 break;
742
743 case EM_MIPS:
744 case EM_MIPS_RS4_BE:
745 if (e_flags & EF_MIPS_NOREORDER)
746 strcat (buf, ", noreorder");
747
748 if (e_flags & EF_MIPS_PIC)
749 strcat (buf, ", pic");
750
751 if (e_flags & EF_MIPS_CPIC)
752 strcat (buf, ", cpic");
753
754 if (e_flags & EF_MIPS_ABI2)
755 strcat (buf, ", abi2");
756
757 if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_1)
758 strcat (buf, ", mips1");
759
760 if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_2)
761 strcat (buf, ", mips2");
762
763 if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_3)
764 strcat (buf, ", mips3");
765
766 if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_4)
767 strcat (buf, ", mips4");
768 break;
769 }
770 }
771
772 return buf;
773 }
774
775 static char *
776 get_machine_data (e_data)
777 unsigned e_data;
778 {
779 static char buff [32];
780
781 switch (e_data)
782 {
783 case ELFDATA2LSB: return _("ELFDATA2LSB (little endian)");
784 case ELFDATA2MSB: return _("ELFDATA2MSB (big endian)");
785 default:
786 sprintf (buff, _("<unknown>: %x"), e_data);
787 return buff;
788 }
789 }
790
791 static const char *
792 get_mips_segment_type (type)
793 unsigned long type;
794 {
795 switch (type)
796 {
797 case PT_MIPS_REGINFO:
798 return "REGINFO";
799 case PT_MIPS_RTPROC:
800 return "RTPROC";
801 case PT_MIPS_OPTIONS:
802 return "OPTIONS";
803 default:
804 break;
805 }
806
807 return NULL;
808 }
809
810 static const char *
811 get_segment_type (p_type)
812 unsigned long p_type;
813 {
814 static char buff [32];
815
816 switch (p_type)
817 {
818 case PT_NULL: return "NULL";
819 case PT_LOAD: return "LOAD";
820 case PT_DYNAMIC: return "DYNAMIC";
821 case PT_INTERP: return "INTERP";
822 case PT_NOTE: return "NOTE";
823 case PT_SHLIB: return "SHLIB";
824 case PT_PHDR: return "PHDR";
825
826 default:
827 if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC))
828 {
829 const char *result;
830 switch (elf_header.e_machine)
831 {
832 case EM_MIPS:
833 case EM_MIPS_RS4_BE:
834 result = get_mips_segment_type (p_type);
835 break;
836 default:
837 result = NULL;
838 break;
839 }
840 if (result == NULL)
841 {
842 sprintf (buff, "LOPROC+%d", p_type - PT_LOPROC);
843 result = buff;
844 }
845 return result;
846 }
847 else
848 {
849 sprintf (buff, _("<unknown>: %x"), p_type);
850 return buff;
851 }
852 }
853 }
854
855 static const char *
856 get_mips_section_type_name (sh_type)
857 unsigned int sh_type;
858 {
859 switch (sh_type)
860 {
861 case SHT_MIPS_LIBLIST:
862 return "MIPS_LIBLIST";
863 case SHT_MIPS_MSYM:
864 return "MIPS_MSYM";
865 case SHT_MIPS_CONFLICT:
866 return "MIPS_CONFLICT";
867 case SHT_MIPS_GPTAB:
868 return "MIPS_GPTAB";
869 case SHT_MIPS_UCODE:
870 return "MIPS_UCODE";
871 case SHT_MIPS_DEBUG:
872 return "MIPS_DEBUG";
873 case SHT_MIPS_REGINFO:
874 return "MIPS_REGINFO";
875 case SHT_MIPS_PACKAGE:
876 return "MIPS_PACKAGE";
877 case SHT_MIPS_PACKSYM:
878 return "MIPS_PACKSYM";
879 case SHT_MIPS_RELD:
880 return "MIPS_RELD";
881 case SHT_MIPS_IFACE:
882 return "MIPS_IFACE";
883 case SHT_MIPS_CONTENT:
884 return "MIPS_CONTENT";
885 case SHT_MIPS_OPTIONS:
886 return "MIPS_OPTIONS";
887 case SHT_MIPS_SHDR:
888 return "MIPS_SHDR";
889 case SHT_MIPS_FDESC:
890 return "MIPS_FDESC";
891 case SHT_MIPS_EXTSYM:
892 return "MIPS_EXTSYM";
893 case SHT_MIPS_DENSE:
894 return "MIPS_DENSE";
895 case SHT_MIPS_PDESC:
896 return "MIPS_PDESC";
897 case SHT_MIPS_LOCSYM:
898 return "MIPS_LOCSYM";
899 case SHT_MIPS_AUXSYM:
900 return "MIPS_AUXSYM";
901 case SHT_MIPS_OPTSYM:
902 return "MIPS_OPTSYM";
903 case SHT_MIPS_LOCSTR:
904 return "MIPS_LOCSTR";
905 case SHT_MIPS_LINE:
906 return "MIPS_LINE";
907 case SHT_MIPS_RFDESC:
908 return "MIPS_RFDESC";
909 case SHT_MIPS_DELTASYM:
910 return "MIPS_DELTASYM";
911 case SHT_MIPS_DELTAINST:
912 return "MIPS_DELTAINST";
913 case SHT_MIPS_DELTACLASS:
914 return "MIPS_DELTACLASS";
915 case SHT_MIPS_DWARF:
916 return "MIPS_DWARF";
917 case SHT_MIPS_DELTADECL:
918 return "MIPS_DELTADECL";
919 case SHT_MIPS_SYMBOL_LIB:
920 return "MIPS_SYMBOL_LIB";
921 case SHT_MIPS_EVENTS:
922 return "MIPS_EVENTS";
923 case SHT_MIPS_TRANSLATE:
924 return "MIPS_TRANSLATE";
925 case SHT_MIPS_PIXIE:
926 return "MIPS_PIXIE";
927 case SHT_MIPS_XLATE:
928 return "MIPS_XLATE";
929 case SHT_MIPS_XLATE_DEBUG:
930 return "MIPS_XLATE_DEBUG";
931 case SHT_MIPS_WHIRL:
932 return "MIPS_WHIRL";
933 case SHT_MIPS_EH_REGION:
934 return "MIPS_EH_REGION";
935 case SHT_MIPS_XLATE_OLD:
936 return "MIPS_XLATE_OLD";
937 case SHT_MIPS_PDR_EXCEPTION:
938 return "MIPS_PDR_EXCEPTION";
939 default:
940 break;
941 }
942 return NULL;
943 }
944
945 static const char *
946 get_section_type_name (sh_type)
947 unsigned int sh_type;
948 {
949 static char buff [32];
950
951 switch (sh_type)
952 {
953 case SHT_NULL: return "NULL";
954 case SHT_PROGBITS: return "PROGBITS";
955 case SHT_SYMTAB: return "SYMTAB";
956 case SHT_STRTAB: return "STRTAB";
957 case SHT_RELA: return "RELA";
958 case SHT_HASH: return "HASH";
959 case SHT_DYNAMIC: return "DYNAMIC";
960 case SHT_NOTE: return "NOTE";
961 case SHT_NOBITS: return "NOBITS";
962 case SHT_REL: return "REL";
963 case SHT_SHLIB: return "SHLIB";
964 case SHT_DYNSYM: return "DYNSYM";
965 case SHT_GNU_verdef: return "VERDEF";
966 case SHT_GNU_verneed: return "VERNEED";
967 case SHT_GNU_versym: return "VERSYM";
968 case 0x6ffffff0: return "VERSYM";
969 case 0x6ffffffc: return "VERDEF";
970 case 0x7ffffffd: return "AUXILIARY";
971 case 0x7fffffff: return "FILTER";
972
973 default:
974 if ((sh_type >= SHT_LOPROC) && (sh_type <= SHT_HIPROC))
975 {
976 const char *result;
977
978 switch (elf_header.e_machine)
979 {
980 case EM_MIPS:
981 case EM_MIPS_RS4_BE:
982 result = get_mips_section_type_name (sh_type);
983 break;
984 default:
985 result = NULL;
986 break;
987 }
988
989 if (result == NULL)
990 {
991 sprintf (buff, _("SHT_LOPROC+%d"), sh_type - SHT_LOPROC);
992 result = buff;
993 }
994 return result;
995 }
996 else if ((sh_type >= SHT_LOUSER) && (sh_type <= SHT_HIUSER))
997 sprintf (buff, _("SHT_LOUSER+%d"), sh_type - SHT_LOUSER);
998 else
999 sprintf (buff, _("<unknown>: %x"), sh_type);
1000 return buff;
1001 }
1002 }
1003
1004 struct option options [] =
1005 {
1006 {"all", no_argument, 0, 'a'},
1007 {"file-header", no_argument, 0, 'h'},
1008 {"program-headers", no_argument, 0, 'l'},
1009 {"headers", no_argument, 0, 'e'},
1010 {"segments", no_argument, 0, 'l'},
1011 {"sections", no_argument, 0, 'S'},
1012 {"section-headers", no_argument, 0, 'S'},
1013 {"symbols", no_argument, 0, 's'},
1014 {"relocs", no_argument, 0, 'r'},
1015 {"dynamic", no_argument, 0, 'd'},
1016 {"version-info", no_argument, 0, 'V'},
1017 {"use-dynamic", no_argument, 0, 'D'},
1018
1019 {"hex-dump", required_argument, 0, 'x'},
1020 #ifdef SUPPORT_DISASSEMBLY
1021 {"instruction-dump", required_argument, 0, 'i'},
1022 #endif
1023
1024 {"version", no_argument, 0, 'v'},
1025 {"help", no_argument, 0, 'H'},
1026
1027 {0, no_argument, 0, 0}
1028 };
1029
1030 static void
1031 usage ()
1032 {
1033 fprintf (stdout, _("Usage: readelf {options} elf-file(s)\n"));
1034 fprintf (stdout, _(" Options are:\n"));
1035 fprintf (stdout, _(" -a or --all Equivalent to: -h -l -S -s -r -d -V\n"));
1036 fprintf (stdout, _(" -h or --file-header Display the ELF file header\n"));
1037 fprintf (stdout, _(" -l or --program-headers or --segments\n"));
1038 fprintf (stdout, _(" Display the program headers\n"));
1039 fprintf (stdout, _(" -S or --section-headers or --sections\n"));
1040 fprintf (stdout, _(" Display the sections' header\n"));
1041 fprintf (stdout, _(" -e or --headers Equivalent to: -h -l -S\n"));
1042 fprintf (stdout, _(" -s or --symbols Display the symbol table\n"));
1043 fprintf (stdout, _(" -r or --relocs Display the relocations (if present)\n"));
1044 fprintf (stdout, _(" -d or --dynamic Display the dynamic segment (if present)\n"));
1045 fprintf (stdout, _(" -V or --version-info Display the version sections (if present)\n"));
1046 fprintf (stdout, _(" -D or --use-dynamic Use the dynamic section info when displaying symbols\n"));
1047 fprintf (stdout, _(" -x <number> or --hex-dump=<number>\n"));
1048 fprintf (stdout, _(" Dump the contents of section <number>\n"));
1049 #ifdef SUPPORT_DISASSEMBLY
1050 fprintf (stdout, _(" -i <number> or --instruction-dump=<number>\n"));
1051 fprintf (stdout, _(" Disassemble the contents of section <number>\n"));
1052 #endif
1053 fprintf (stdout, _(" -v or --version Display the version number of readelf\n"));
1054 fprintf (stdout, _(" -H or --help Display this information\n"));
1055 fprintf (stdout, _("Report bugs to bug-gnu-utils@gnu.org\n"));
1056
1057 exit (0);
1058 }
1059
1060 static void
1061 parse_args (argc, argv)
1062 int argc;
1063 char ** argv;
1064 {
1065 int c;
1066
1067 if (argc < 2)
1068 usage ();
1069
1070 while ((c = getopt_long
1071 (argc, argv, "ersahldSDx:i:vV", options, NULL)) != EOF)
1072 {
1073 char * cp;
1074 int section;
1075
1076 switch (c)
1077 {
1078 case 'H':
1079 usage ();
1080 break;
1081
1082 case 'a':
1083 do_syms ++;
1084 do_reloc ++;
1085 do_dynamic ++;
1086 do_header ++;
1087 do_sections ++;
1088 do_segments ++;
1089 do_version ++;
1090 break;
1091 case 'e':
1092 do_header ++;
1093 do_sections ++;
1094 do_segments ++;
1095 break;
1096 case 'D':
1097 do_using_dynamic ++;
1098 break;
1099 case 'r':
1100 do_reloc ++;
1101 break;
1102 case 'h':
1103 do_header ++;
1104 break;
1105 case 'l':
1106 do_segments ++;
1107 break;
1108 case 's':
1109 do_syms ++;
1110 break;
1111 case 'S':
1112 do_sections ++;
1113 break;
1114 case 'd':
1115 do_dynamic ++;
1116 break;
1117 case 'x':
1118 do_dump ++;
1119 section = strtoul (optarg, & cp, 0);
1120 if (! * cp && section >= 0 && section < NUM_DUMP_SECTS)
1121 {
1122 dump_sects [section] |= HEX_DUMP;
1123 break;
1124 }
1125 goto oops;
1126 #ifdef SUPPORT_DISASSEMBLY
1127 case 'i':
1128 do_dump ++;
1129 section = strtoul (optarg, & cp, 0);
1130 if (! * cp && section >= 0 && section < NUM_DUMP_SECTS)
1131 {
1132 dump_sects [section] |= DISASS_DUMP;
1133 break;
1134 }
1135 goto oops;
1136 #endif
1137 case 'v':
1138 print_version (program_name);
1139 break;
1140 case 'V':
1141 do_version ++;
1142 break;
1143 default:
1144 oops:
1145 /* xgettext:c-format */
1146 error (_("Invalid option '-%c'\n"), c);
1147 /* Drop through. */
1148 case '?':
1149 usage ();
1150 }
1151 }
1152
1153 if (!do_dynamic && !do_syms && !do_reloc && !do_sections
1154 && !do_segments && !do_header && !do_dump && !do_version)
1155 usage ();
1156 else if (argc < 3)
1157 {
1158 warn (_("Nothing to do.\n"));
1159 usage();
1160 }
1161 }
1162
1163 /* Decode the data held in 'elf_header'. */
1164 static int
1165 process_file_header ()
1166 {
1167 if ( elf_header.e_ident [EI_MAG0] != ELFMAG0
1168 || elf_header.e_ident [EI_MAG1] != ELFMAG1
1169 || elf_header.e_ident [EI_MAG2] != ELFMAG2
1170 || elf_header.e_ident [EI_MAG3] != ELFMAG3)
1171 {
1172 error
1173 (_("Not an ELF file - it has the wrong magic bytes at the start\n"));
1174 return 0;
1175 }
1176
1177 if (elf_header.e_ident [EI_CLASS] != ELFCLASS32)
1178 {
1179 error (_("Not a 32 bit ELF file\n"));
1180 return 0;
1181 }
1182
1183 if (do_header)
1184 {
1185 int i;
1186
1187 printf (_("ELF Header:\n"));
1188 printf (_(" Magic: "));
1189 for (i = 0; i < EI_NIDENT; i ++)
1190 printf ("%2.2x ", elf_header.e_ident [i]);
1191 printf ("\n");
1192 printf (_(" Type: %s\n"),
1193 get_file_type (elf_header.e_type));
1194 printf (_(" Machine: %s\n"),
1195 get_machine_name (elf_header.e_machine));
1196 printf (_(" Version: 0x%lx\n"),
1197 (unsigned long) elf_header.e_version);
1198 printf (_(" Data: %s\n"),
1199 get_machine_data (elf_header.e_ident [EI_DATA]));
1200 printf (_(" Entry point address: 0x%lx\n"),
1201 (unsigned long) elf_header.e_entry);
1202 printf (_(" Start of program headers: %ld (bytes into file)\n"),
1203 (long) elf_header.e_phoff);
1204 printf (_(" Start of section headers: %ld (bytes into file)\n"),
1205 (long) elf_header.e_shoff);
1206 printf (_(" Flags: 0x%lx%s\n"),
1207 (unsigned long) elf_header.e_flags,
1208 get_machine_flags (elf_header.e_flags, elf_header.e_machine));
1209 printf (_(" Size of this header: %ld (bytes)\n"),
1210 (long) elf_header.e_ehsize);
1211 printf (_(" Size of program headers: %ld (bytes)\n"),
1212 (long) elf_header.e_phentsize);
1213 printf (_(" Number of program headers: %ld\n"),
1214 (long) elf_header.e_phnum);
1215 printf (_(" Size of section headers: %ld (bytes)\n"),
1216 (long) elf_header.e_shentsize);
1217 printf (_(" Number of section headers: %ld\n"),
1218 (long) elf_header.e_shnum);
1219 printf (_(" Section header string table index: %ld\n"),
1220 (long) elf_header.e_shstrndx);
1221 }
1222
1223 return 1;
1224 }
1225
1226
1227 static int
1228 process_program_headers (file)
1229 FILE * file;
1230 {
1231 Elf32_External_Phdr * phdrs;
1232 Elf32_Internal_Phdr * program_headers;
1233 Elf32_Internal_Phdr * segment;
1234 unsigned int i;
1235
1236 if (elf_header.e_phnum == 0)
1237 {
1238 if (do_segments)
1239 printf (_("\nThere are no program headers in this file.\n"));
1240 return 1;
1241 }
1242
1243 if (do_segments && !do_header)
1244 {
1245 printf (_("\nElf file is %s\n"), get_file_type (elf_header.e_type));
1246 printf (_("Entry point 0x%lx\n"), (unsigned long) elf_header.e_entry);
1247 printf (_("There are %d program headers, starting at offset %lx:\n"),
1248 elf_header.e_phnum, (unsigned long) elf_header.e_phoff);
1249 }
1250
1251 GET_DATA_ALLOC (elf_header.e_phoff,
1252 elf_header.e_phentsize * elf_header.e_phnum,
1253 phdrs, Elf32_External_Phdr *, "program headers");
1254
1255 program_headers = (Elf32_Internal_Phdr *) malloc
1256 (elf_header.e_phnum * sizeof (Elf32_Internal_Phdr));
1257
1258 if (program_headers == NULL)
1259 {
1260 error (_("Out of memory\n"));
1261 return 0;
1262 }
1263
1264 for (i = 0, segment = program_headers;
1265 i < elf_header.e_phnum;
1266 i ++, segment ++)
1267 {
1268 segment->p_type = BYTE_GET (phdrs[i].p_type);
1269 segment->p_offset = BYTE_GET (phdrs[i].p_offset);
1270 segment->p_vaddr = BYTE_GET (phdrs[i].p_vaddr);
1271 segment->p_paddr = BYTE_GET (phdrs[i].p_paddr);
1272 segment->p_filesz = BYTE_GET (phdrs[i].p_filesz);
1273 segment->p_memsz = BYTE_GET (phdrs[i].p_memsz);
1274 segment->p_flags = BYTE_GET (phdrs[i].p_flags);
1275 segment->p_align = BYTE_GET (phdrs[i].p_align);
1276 }
1277
1278 free (phdrs);
1279
1280 if (do_segments)
1281 {
1282 printf
1283 (_("\nProgram Header%s:\n"), elf_header.e_phnum > 1 ? "s" : "");
1284 printf
1285 (_(" Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align\n"));
1286 }
1287
1288 loadaddr = -1;
1289 dynamic_addr = 0;
1290
1291 for (i = 0, segment = program_headers;
1292 i < elf_header.e_phnum;
1293 i ++, segment ++)
1294 {
1295 if (do_segments)
1296 {
1297 printf (" %-11.11s ", get_segment_type (segment->p_type));
1298 printf ("0x%5.5lx ", (unsigned long) segment->p_offset);
1299 printf ("0x%8.8lx ", (unsigned long) segment->p_vaddr);
1300 printf ("0x%8.8lx ", (unsigned long) segment->p_paddr);
1301 printf ("0x%5.5lx ", (unsigned long) segment->p_filesz);
1302 printf ("0x%5.5lx ", (unsigned long) segment->p_memsz);
1303 printf ("%c%c%c ",
1304 (segment->p_flags & PF_R ? 'R' : ' '),
1305 (segment->p_flags & PF_W ? 'W' : ' '),
1306 (segment->p_flags & PF_X ? 'E' : ' '));
1307 printf ("%#lx", (unsigned long) segment->p_align);
1308 }
1309
1310 switch (segment->p_type)
1311 {
1312 case PT_LOAD:
1313 if (loadaddr == -1)
1314 loadaddr = (segment->p_vaddr & 0xfffff000)
1315 - (segment->p_offset & 0xfffff000);
1316 break;
1317
1318 case PT_DYNAMIC:
1319 if (dynamic_addr)
1320 error (_("more than one dynamic segment\n"));
1321
1322 dynamic_addr = segment->p_offset;
1323 dynamic_size = segment->p_filesz;
1324 break;
1325
1326 case PT_INTERP:
1327 if (fseek (file, segment->p_offset, SEEK_SET))
1328 error (_("Unable to find program interpreter name\n"));
1329 else
1330 {
1331 program_interpreter[0] = 0;
1332 fscanf (file, "%63s", program_interpreter);
1333
1334 if (do_segments)
1335 printf (_("\n [Requesting program interpreter: %s]"),
1336 program_interpreter);
1337 }
1338 break;
1339 }
1340
1341 if (do_segments)
1342 putc ('\n', stdout);
1343 }
1344
1345 if (loadaddr == -1)
1346 {
1347 /* Very strange. */
1348 loadaddr = 0;
1349 }
1350
1351 if (do_segments && section_headers != NULL)
1352 {
1353 printf (_("\n Section to Segment mapping:\n"));
1354 printf (_(" Segment Sections...\n"));
1355
1356 assert (string_table != NULL);
1357
1358 for (i = 0; i < elf_header.e_phnum; i++)
1359 {
1360 int j;
1361 Elf32_Internal_Shdr * section;
1362
1363 segment = program_headers + i;
1364 section = section_headers;
1365
1366 printf (" %2.2d ", i);
1367
1368 for (j = 0; j < elf_header.e_shnum; j++, section ++)
1369 {
1370 if (section->sh_size > 0
1371 /* Compare allocated sections by VMA, unallocated
1372 sections by file offset. */
1373 && (section->sh_flags & SHF_ALLOC
1374 ? (section->sh_addr >= segment->p_vaddr
1375 && section->sh_addr + section->sh_size
1376 <= segment->p_vaddr + segment->p_memsz)
1377 : (section->sh_offset >= segment->p_offset
1378 && (section->sh_offset + section->sh_size
1379 <= segment->p_offset + segment->p_filesz))))
1380 printf ("%s ", SECTION_NAME (section));
1381 }
1382
1383 putc ('\n',stdout);
1384 }
1385 }
1386
1387 free (program_headers);
1388
1389 return 1;
1390 }
1391
1392
1393 static int
1394 get_section_headers (file)
1395 FILE * file;
1396 {
1397 Elf32_External_Shdr * shdrs;
1398 Elf32_Internal_Shdr * internal;
1399 unsigned int i;
1400
1401 GET_DATA_ALLOC (elf_header.e_shoff,
1402 elf_header.e_shentsize * elf_header.e_shnum,
1403 shdrs, Elf32_External_Shdr *, "section headers");
1404
1405 section_headers = (Elf32_Internal_Shdr *) malloc
1406 (elf_header.e_shnum * sizeof (Elf32_Internal_Shdr));
1407
1408 if (section_headers == NULL)
1409 {
1410 error (_("Out of memory\n"));
1411 return 0;
1412 }
1413
1414 for (i = 0, internal = section_headers;
1415 i < elf_header.e_shnum;
1416 i ++, internal ++)
1417 {
1418 internal->sh_name = BYTE_GET (shdrs[i].sh_name);
1419 internal->sh_type = BYTE_GET (shdrs[i].sh_type);
1420 internal->sh_flags = BYTE_GET (shdrs[i].sh_flags);
1421 internal->sh_addr = BYTE_GET (shdrs[i].sh_addr);
1422 internal->sh_offset = BYTE_GET (shdrs[i].sh_offset);
1423 internal->sh_size = BYTE_GET (shdrs[i].sh_size);
1424 internal->sh_link = BYTE_GET (shdrs[i].sh_link);
1425 internal->sh_info = BYTE_GET (shdrs[i].sh_info);
1426 internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign);
1427 internal->sh_entsize = BYTE_GET (shdrs[i].sh_entsize);
1428 }
1429
1430 free (shdrs);
1431
1432 return 1;
1433 }
1434
1435 static Elf_Internal_Sym *
1436 get_elf_symbols (file, offset, number)
1437 FILE * file;
1438 unsigned long offset;
1439 unsigned long number;
1440 {
1441 Elf32_External_Sym * esyms;
1442 Elf_Internal_Sym * isyms;
1443 Elf_Internal_Sym * psym;
1444 unsigned int j;
1445
1446 GET_DATA_ALLOC (offset, number * sizeof (Elf32_External_Sym),
1447 esyms, Elf32_External_Sym *, "symbols");
1448
1449 isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym));
1450
1451 if (isyms == NULL)
1452 {
1453 error (_("Out of memory\n"));
1454 free (esyms);
1455
1456 return NULL;
1457 }
1458
1459 for (j = 0, psym = isyms;
1460 j < number;
1461 j ++, psym ++)
1462 {
1463 psym->st_name = BYTE_GET (esyms[j].st_name);
1464 psym->st_value = BYTE_GET (esyms[j].st_value);
1465 psym->st_size = BYTE_GET (esyms[j].st_size);
1466 psym->st_shndx = BYTE_GET (esyms[j].st_shndx);
1467 psym->st_info = BYTE_GET (esyms[j].st_info);
1468 psym->st_other = BYTE_GET (esyms[j].st_other);
1469 }
1470
1471 free (esyms);
1472
1473 return isyms;
1474 }
1475
1476 static int
1477 process_section_headers (file)
1478 FILE * file;
1479 {
1480 Elf32_Internal_Shdr * section;
1481 int i;
1482
1483 section_headers = NULL;
1484
1485 if (elf_header.e_shnum == 0)
1486 {
1487 if (do_sections)
1488 printf (_("\nThere are no sections in this file.\n"));
1489
1490 return 1;
1491 }
1492
1493 if (do_sections && !do_header)
1494 printf (_("There are %d section headers, starting at offset %x:\n"),
1495 elf_header.e_shnum, elf_header.e_shoff);
1496
1497 if (! get_section_headers (file))
1498 return 0;
1499
1500 /* Read in the string table, so that we have names to display. */
1501 section = section_headers + elf_header.e_shstrndx;
1502
1503 if (section->sh_size != 0)
1504 {
1505 unsigned long string_table_offset;
1506
1507 string_table_offset = section->sh_offset;
1508
1509 GET_DATA_ALLOC (section->sh_offset, section->sh_size,
1510 string_table, char *, "string table");
1511 }
1512
1513 /* Scan the sections for the dynamic symbol table
1514 and dynamic string table. */
1515 dynamic_symbols = NULL;
1516 dynamic_strings = NULL;
1517 for (i = 0, section = section_headers;
1518 i < elf_header.e_shnum;
1519 i ++, section ++)
1520 {
1521 if (section->sh_type == SHT_DYNSYM)
1522 {
1523 if (dynamic_symbols != NULL)
1524 {
1525 error (_("File contains multiple dynamic symbol tables\n"));
1526 continue;
1527 }
1528
1529 dynamic_symbols = get_elf_symbols
1530 (file, section->sh_offset, section->sh_size / section->sh_entsize);
1531 }
1532 else if (section->sh_type == SHT_STRTAB
1533 && strcmp (SECTION_NAME (section), ".dynstr") == 0)
1534 {
1535 if (dynamic_strings != NULL)
1536 {
1537 error (_("File contains multiple dynamic string tables\n"));
1538 continue;
1539 }
1540
1541 GET_DATA_ALLOC (section->sh_offset, section->sh_size,
1542 dynamic_strings, char *, "dynamic strings");
1543 }
1544 }
1545
1546 if (! do_sections)
1547 return 1;
1548
1549 printf (_("\nSection Header%s:\n"), elf_header.e_shnum > 1 ? "s" : "");
1550 printf
1551 (_(" [Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n"));
1552
1553 for (i = 0, section = section_headers;
1554 i < elf_header.e_shnum;
1555 i ++, section ++)
1556 {
1557 printf (" [%2d] %-17.17s %-15.15s ",
1558 i,
1559 SECTION_NAME (section),
1560 get_section_type_name (section->sh_type));
1561
1562 printf ( "%8.8lx %6.6lx %6.6lx %2.2lx",
1563 (unsigned long) section->sh_addr,
1564 (unsigned long) section->sh_offset,
1565 (unsigned long) section->sh_size,
1566 (unsigned long) section->sh_entsize);
1567
1568 printf (" %c%c%c %2ld %3lx %ld \n",
1569 (section->sh_flags & SHF_WRITE ? 'W' : ' '),
1570 (section->sh_flags & SHF_ALLOC ? 'A' : ' '),
1571 (section->sh_flags & SHF_EXECINSTR ? 'X' : ' '),
1572 (unsigned long) section->sh_link,
1573 (unsigned long) section->sh_info,
1574 (unsigned long) section->sh_addralign);
1575 }
1576
1577 return 1;
1578 }
1579
1580 /* Process the reloc section. */
1581 static int
1582 process_relocs (file)
1583 FILE * file;
1584 {
1585 unsigned long rel_size;
1586 unsigned long rel_offset;
1587
1588
1589 if (!do_reloc)
1590 return 1;
1591
1592 if (do_using_dynamic)
1593 {
1594 rel_size = 0;
1595 rel_offset = 0;
1596
1597 if (dynamic_info [DT_REL])
1598 {
1599 rel_offset = dynamic_info [DT_REL];
1600 rel_size = dynamic_info [DT_RELSZ];
1601 }
1602 else if (dynamic_info [DT_RELA])
1603 {
1604 rel_offset = dynamic_info [DT_RELA];
1605 rel_size = dynamic_info [DT_RELASZ];
1606 }
1607 else if (dynamic_info [DT_JMPREL])
1608 {
1609 rel_offset = dynamic_info [DT_JMPREL];
1610 rel_size = dynamic_info [DT_PLTRELSZ];
1611 }
1612
1613 if (rel_size)
1614 {
1615 printf
1616 (_("\nRelocation section at offset 0x%x contains %d bytes:\n"),
1617 rel_offset, rel_size);
1618
1619 dump_relocations (file, rel_offset - loadaddr, rel_size,
1620 dynamic_symbols, dynamic_strings);
1621 }
1622 else
1623 printf (_("\nThere are no dynamic relocations in this file.\n"));
1624 }
1625 else
1626 {
1627 Elf32_Internal_Shdr * section;
1628 unsigned long i;
1629 int found = 0;
1630
1631 for (i = 0, section = section_headers;
1632 i < elf_header.e_shnum;
1633 i++, section ++)
1634 {
1635 if ( section->sh_type != SHT_RELA
1636 && section->sh_type != SHT_REL)
1637 continue;
1638
1639 rel_offset = section->sh_offset;
1640 rel_size = section->sh_size;
1641
1642 if (rel_size)
1643 {
1644 Elf32_Internal_Shdr * strsec;
1645 Elf32_Internal_Shdr * symsec;
1646 Elf_Internal_Sym * symtab;
1647 char * strtab;
1648
1649 printf (_("\nRelocation section "));
1650
1651 if (string_table == NULL)
1652 printf ("%d", section->sh_name);
1653 else
1654 printf ("'%s'", SECTION_NAME (section));
1655
1656 printf (_(" at offset 0x%x contains %d entries:\n"),
1657 rel_offset, rel_size / section->sh_entsize);
1658
1659 symsec = section_headers + section->sh_link;
1660
1661 symtab = get_elf_symbols (file, symsec->sh_offset,
1662 symsec->sh_size / symsec->sh_entsize);
1663
1664 if (symtab == NULL)
1665 continue;
1666
1667 strsec = section_headers + symsec->sh_link;
1668
1669 GET_DATA_ALLOC (strsec->sh_offset, strsec->sh_size, strtab,
1670 char *, "string table");
1671
1672 dump_relocations (file, rel_offset, rel_size, symtab, strtab);
1673
1674 free (strtab);
1675 free (symtab);
1676
1677 found = 1;
1678 }
1679 }
1680
1681 if (! found)
1682 printf (_("\nThere are no relocations in this file.\n"));
1683 }
1684
1685 return 1;
1686 }
1687
1688
1689 static void
1690 dynamic_segment_mips_val (entry)
1691 Elf_Internal_Dyn *entry;
1692 {
1693 switch (entry->d_tag)
1694 {
1695 case DT_MIPS_LOCAL_GOTNO:
1696 case DT_MIPS_CONFLICTNO:
1697 case DT_MIPS_LIBLISTNO:
1698 case DT_MIPS_SYMTABNO:
1699 case DT_MIPS_UNREFEXTNO:
1700 case DT_MIPS_HIPAGENO:
1701 case DT_MIPS_DELTA_CLASS_NO:
1702 case DT_MIPS_DELTA_INSTANCE_NO:
1703 case DT_MIPS_DELTA_RELOC_NO:
1704 case DT_MIPS_DELTA_SYM_NO:
1705 case DT_MIPS_DELTA_CLASSSYM_NO:
1706 if (do_dynamic)
1707 printf ("%#ld\n", (long) entry->d_un.d_ptr);
1708 break;
1709 default:
1710 if (do_dynamic)
1711 printf ("%#lx\n", (long) entry->d_un.d_ptr);
1712 }
1713 }
1714
1715 /* Parse the dynamic segment */
1716 static int
1717 process_dynamic_segment (file)
1718 FILE * file;
1719 {
1720 Elf_Internal_Dyn * entry;
1721 Elf32_External_Dyn * edyn;
1722 unsigned int i;
1723
1724 if (dynamic_size == 0)
1725 {
1726 if (do_dynamic)
1727 printf (_("\nThere is no dynamic segment in this file.\n"));
1728
1729 return 1;
1730 }
1731
1732 GET_DATA_ALLOC (dynamic_addr, dynamic_size,
1733 edyn, Elf32_External_Dyn *, "dynamic segment");
1734
1735 /* SGI's ELF has more than one section in the DYNAMIC segment. Determine
1736 how large .dynamic is now. We can do this even before the byte
1737 swapping since the DT_NULL tag is recognizable. */
1738 dynamic_size = 0;
1739 while (*(Elf32_Word *) edyn[dynamic_size++].d_tag != DT_NULL)
1740 ;
1741
1742 dynamic_segment = (Elf_Internal_Dyn *)
1743 malloc (dynamic_size * sizeof (Elf_Internal_Dyn));
1744
1745 if (dynamic_segment == NULL)
1746 {
1747 error (_("Out of memory\n"));
1748 free (edyn);
1749 return 0;
1750 }
1751
1752 for (i = 0, entry = dynamic_segment;
1753 i < dynamic_size;
1754 i ++, entry ++)
1755 {
1756 entry->d_tag = BYTE_GET (edyn [i].d_tag);
1757 entry->d_un.d_val = BYTE_GET (edyn [i].d_un.d_val);
1758 }
1759
1760 free (edyn);
1761
1762 /* Find the appropriate symbol table. */
1763 if (dynamic_symbols == NULL)
1764 {
1765 for (i = 0, entry = dynamic_segment;
1766 i < dynamic_size;
1767 ++i, ++ entry)
1768 {
1769 unsigned long offset;
1770 long num_syms;
1771
1772 if (entry->d_tag != DT_SYMTAB)
1773 continue;
1774
1775 dynamic_info [DT_SYMTAB] = entry->d_un.d_val;
1776
1777 /* Since we do not know how big the symbol table is,
1778 we default to reading in the entire file (!) and
1779 processing that. This is overkill, I know, but it
1780 should work. */
1781
1782 offset = entry->d_un.d_val - loadaddr;
1783
1784 if (fseek (file, 0, SEEK_END))
1785 error (_("Unable to seek to end of file!"));
1786
1787 num_syms = (ftell (file) - offset) / sizeof (Elf32_External_Sym);
1788
1789 if (num_syms < 1)
1790 {
1791 error (_("Unable to determine the number of symbols to load\n"));
1792 continue;
1793 }
1794
1795 dynamic_symbols = get_elf_symbols (file, offset, num_syms);
1796 }
1797 }
1798
1799 /* Similarly find a string table. */
1800 if (dynamic_strings == NULL)
1801 {
1802 for (i = 0, entry = dynamic_segment;
1803 i < dynamic_size;
1804 ++i, ++ entry)
1805 {
1806 unsigned long offset;
1807 long str_tab_len;
1808
1809 if (entry->d_tag != DT_STRTAB)
1810 continue;
1811
1812 dynamic_info [DT_STRTAB] = entry->d_un.d_val;
1813
1814 /* Since we do not know how big the string table is,
1815 we default to reading in the entire file (!) and
1816 processing that. This is overkill, I know, but it
1817 should work. */
1818
1819 offset = entry->d_un.d_val - loadaddr;
1820 if (fseek (file, 0, SEEK_END))
1821 error (_("Unable to seek to end of file\n"));
1822 str_tab_len = ftell (file) - offset;
1823
1824 if (str_tab_len < 1)
1825 {
1826 error
1827 (_("Unable to determine the length of the dynamic string table\n"));
1828 continue;
1829 }
1830
1831 GET_DATA_ALLOC (offset, str_tab_len, dynamic_strings, char *,
1832 "dynamic string table");
1833
1834 break;
1835 }
1836 }
1837
1838 if (do_dynamic && dynamic_addr)
1839 printf (_("\nDynamic segment at offset 0x%x contains %d entries:\n"),
1840 dynamic_addr, dynamic_size);
1841 if (do_dynamic)
1842 printf (_(" Tag Type Name/Value\n"));
1843
1844 for (i = 0, entry = dynamic_segment;
1845 i < dynamic_size;
1846 i++, entry ++)
1847 {
1848 if (do_dynamic)
1849 printf (_(" 0x%-8.8lx (%s)%*s"),
1850 (unsigned long) entry->d_tag,
1851 get_dynamic_type (entry->d_tag),
1852 27 - strlen (get_dynamic_type (entry->d_tag)),
1853 " ");
1854
1855 switch (entry->d_tag)
1856 {
1857 case DT_AUXILIARY:
1858 case DT_FILTER:
1859 if (do_dynamic)
1860 {
1861 if (entry->d_tag == DT_AUXILIARY)
1862 printf (_("Auxiliary library"));
1863 else
1864 printf (_("Filter library"));
1865
1866 if (dynamic_strings)
1867 printf (": [%s]\n", dynamic_strings + entry->d_un.d_val);
1868 else
1869 printf (": %#lx\n", (long) entry->d_un.d_val);
1870 }
1871 break;
1872
1873 case DT_NULL :
1874 case DT_NEEDED :
1875 case DT_PLTRELSZ:
1876 case DT_PLTGOT :
1877 case DT_HASH :
1878 case DT_STRTAB :
1879 case DT_SYMTAB :
1880 case DT_RELA :
1881 case DT_RELASZ :
1882 case DT_RELAENT :
1883 case DT_STRSZ :
1884 case DT_SYMENT :
1885 case DT_INIT :
1886 case DT_FINI :
1887 case DT_SONAME :
1888 case DT_RPATH :
1889 case DT_SYMBOLIC:
1890 case DT_REL :
1891 case DT_RELSZ :
1892 case DT_RELENT :
1893 case DT_PLTREL :
1894 case DT_DEBUG :
1895 case DT_TEXTREL :
1896 case DT_JMPREL :
1897 dynamic_info [entry->d_tag] = entry->d_un.d_val;
1898
1899 if (do_dynamic)
1900 {
1901 char * name;
1902
1903 if (dynamic_strings == NULL)
1904 name = NULL;
1905 else
1906 name = dynamic_strings + entry->d_un.d_val;
1907
1908 if (name)
1909 {
1910 switch (entry->d_tag)
1911 {
1912 case DT_NEEDED:
1913 printf (_("Shared library: [%s]"), name);
1914
1915 if (strcmp (name, program_interpreter))
1916 printf ("\n");
1917 else
1918 printf (_(" program interpreter\n"));
1919 break;
1920
1921 case DT_SONAME:
1922 printf (_("Library soname: [%s]\n"), name);
1923 break;
1924
1925 case DT_RPATH:
1926 printf (_("Library rpath: [%s]\n"), name);
1927 break;
1928
1929 default:
1930 printf ("%#lx\n", (long) entry->d_un.d_val);
1931 }
1932 }
1933 else
1934 printf ("%#lx\n", (long) entry->d_un.d_val);
1935 }
1936 break;
1937
1938 default:
1939 if ((entry->d_tag >= DT_VERSYM) && (entry->d_tag <= DT_VERNEEDNUM))
1940 {
1941 version_info [DT_VERSIONTAGIDX (entry->d_tag)] =
1942 entry->d_un.d_val;
1943
1944 if (do_dynamic)
1945 printf ("%#lx\n", (long) entry->d_un.d_ptr);
1946 }
1947 else
1948 switch (elf_header.e_machine)
1949 {
1950 case EM_MIPS:
1951 case EM_MIPS_RS4_BE:
1952 dynamic_segment_mips_val (entry);
1953 break;
1954 default:
1955 if (do_dynamic)
1956 printf ("%#lx\n", (long) entry->d_un.d_ptr);
1957 }
1958 break;
1959 }
1960 }
1961
1962 return 1;
1963 }
1964
1965 static char *
1966 get_ver_flags (flags)
1967 unsigned int flags;
1968 {
1969 static char buff [32];
1970
1971 buff[0] = 0;
1972
1973 if (flags == 0)
1974 return _("none");
1975
1976 if (flags & VER_FLG_BASE)
1977 strcat (buff, "BASE ");
1978
1979 if (flags & VER_FLG_WEAK)
1980 {
1981 if (flags & VER_FLG_BASE)
1982 strcat (buff, "| ");
1983
1984 strcat (buff, "WEAK ");
1985 }
1986
1987 if (flags & ~(VER_FLG_BASE | VER_FLG_WEAK))
1988 strcat (buff, "| <unknown>");
1989
1990 return buff;
1991 }
1992
1993 /* Display the contents of the version sections. */
1994 static int
1995 process_version_sections (file)
1996 FILE * file;
1997 {
1998 Elf32_Internal_Shdr * section;
1999 unsigned i;
2000 int found = 0;
2001
2002 if (! do_version)
2003 return 1;
2004
2005 for (i = 0, section = section_headers;
2006 i < elf_header.e_shnum;
2007 i++, section ++)
2008 {
2009 switch (section->sh_type)
2010 {
2011 case SHT_GNU_verdef:
2012 {
2013 Elf_External_Verdef * edefs;
2014 unsigned int idx;
2015 unsigned int cnt;
2016
2017 found = 1;
2018
2019 printf
2020 (_("\nVersion definition section '%s' contains %d entries:\n"),
2021 SECTION_NAME (section), section->sh_info);
2022
2023 printf (_(" Addr: %#08x Offset: %#08x Link: %x (%s)\n"),
2024 section->sh_addr, section->sh_offset, section->sh_link,
2025 SECTION_NAME (section_headers + section->sh_link));
2026
2027 GET_DATA_ALLOC (section->sh_offset, section->sh_size,
2028 edefs, Elf_External_Verdef *,
2029 "version definition section");
2030
2031 for (idx = cnt = 0; cnt < section->sh_info; ++ cnt)
2032 {
2033 char * vstart;
2034 Elf_External_Verdef * edef;
2035 Elf_Internal_Verdef ent;
2036 Elf_External_Verdaux * eaux;
2037 Elf_Internal_Verdaux aux;
2038 int j;
2039 int isum;
2040
2041 vstart = ((char *) edefs) + idx;
2042
2043 edef = (Elf_External_Verdef *) vstart;
2044
2045 ent.vd_version = BYTE_GET (edef->vd_version);
2046 ent.vd_flags = BYTE_GET (edef->vd_flags);
2047 ent.vd_ndx = BYTE_GET (edef->vd_ndx);
2048 ent.vd_cnt = BYTE_GET (edef->vd_cnt);
2049 ent.vd_hash = BYTE_GET (edef->vd_hash);
2050 ent.vd_aux = BYTE_GET (edef->vd_aux);
2051 ent.vd_next = BYTE_GET (edef->vd_next);
2052
2053 printf (_(" %#06x: Rev: %d Flags: %s"),
2054 idx, ent.vd_version, get_ver_flags (ent.vd_flags));
2055
2056 printf (_(" Index: %ld Cnt: %ld "), ent.vd_ndx, ent.vd_cnt);
2057
2058 vstart += ent.vd_aux;
2059
2060 eaux = (Elf_External_Verdaux *) vstart;
2061
2062 aux.vda_name = BYTE_GET (eaux->vda_name);
2063 aux.vda_next = BYTE_GET (eaux->vda_next);
2064
2065 if (dynamic_strings)
2066 printf (_("Name: %s\n"), dynamic_strings + aux.vda_name);
2067 else
2068 printf (_("Name index: %ld\n"), aux.vda_name);
2069
2070 isum = idx + ent.vd_aux;
2071
2072 for (j = 1; j < ent.vd_cnt; j ++)
2073 {
2074 isum += aux.vda_next;
2075 vstart += aux.vda_next;
2076
2077 eaux = (Elf_External_Verdaux *) vstart;
2078
2079 aux.vda_name = BYTE_GET (eaux->vda_name);
2080 aux.vda_next = BYTE_GET (eaux->vda_next);
2081
2082 if (dynamic_strings)
2083 printf (_(" %#06x: Parent %d: %s\n"),
2084 isum, j, dynamic_strings + aux.vda_name);
2085 else
2086 printf (_(" %#06x: Parent %d, name index: %ld\n"),
2087 isum, j, aux.vda_name);
2088 }
2089
2090 idx += ent.vd_next;
2091 }
2092
2093 free (edefs);
2094 }
2095 break;
2096
2097 case SHT_GNU_verneed:
2098 {
2099 Elf_External_Verneed * eneed;
2100 unsigned int idx;
2101 unsigned int cnt;
2102
2103 found = 1;
2104
2105 printf (_("\nVersion needs section '%s' contains %d entries:\n"),
2106 SECTION_NAME (section), section->sh_info);
2107
2108 printf
2109 (_(" Addr: %#08x Offset: %#08x Link to section: %d (%s)\n"),
2110 section->sh_addr, section->sh_offset, section->sh_link,
2111 SECTION_NAME (section_headers + section->sh_link));
2112
2113 GET_DATA_ALLOC (section->sh_offset, section->sh_size,
2114 eneed, Elf_External_Verneed *,
2115 "version need section");
2116
2117 for (idx = cnt = 0; cnt < section->sh_info; ++cnt)
2118 {
2119 Elf_External_Verneed * entry;
2120 Elf_Internal_Verneed ent;
2121 int j;
2122 int isum;
2123 char * vstart;
2124
2125 vstart = ((char *) eneed) + idx;
2126
2127 entry = (Elf_External_Verneed *) vstart;
2128
2129 ent.vn_version = BYTE_GET (entry->vn_version);
2130 ent.vn_cnt = BYTE_GET (entry->vn_cnt);
2131 ent.vn_file = BYTE_GET (entry->vn_file);
2132 ent.vn_aux = BYTE_GET (entry->vn_aux);
2133 ent.vn_next = BYTE_GET (entry->vn_next);
2134
2135 printf (_(" %#06x: Version: %d"), idx, ent.vn_version);
2136
2137 if (dynamic_strings)
2138 printf (_(" File: %s"), dynamic_strings + ent.vn_file);
2139 else
2140 printf (_(" File: %lx"), ent.vn_file);
2141
2142 printf (_(" Cnt: %d\n"), ent.vn_cnt);
2143
2144 vstart += ent.vn_aux;
2145
2146 for (j = 0, isum = idx + ent.vn_aux; j < ent.vn_cnt; ++j)
2147 {
2148 Elf_External_Vernaux * eaux;
2149 Elf_Internal_Vernaux aux;
2150
2151 eaux = (Elf_External_Vernaux *) vstart;
2152
2153 aux.vna_hash = BYTE_GET (eaux->vna_hash);
2154 aux.vna_flags = BYTE_GET (eaux->vna_flags);
2155 aux.vna_other = BYTE_GET (eaux->vna_other);
2156 aux.vna_name = BYTE_GET (eaux->vna_name);
2157 aux.vna_next = BYTE_GET (eaux->vna_next);
2158
2159 if (dynamic_strings)
2160 printf (_(" %#06x: Name: %s"),
2161 isum, dynamic_strings + aux.vna_name);
2162 else
2163 printf (_(" %#06x: Name index: %lx"),
2164 isum, aux.vna_name);
2165
2166 printf (_(" Flags: %s Version: %d\n"),
2167 get_ver_flags (aux.vna_flags), aux.vna_other);
2168
2169 isum += aux.vna_next;
2170 vstart += aux.vna_next;
2171 }
2172
2173 idx += ent.vn_next;
2174 }
2175
2176 free (eneed);
2177 }
2178 break;
2179
2180 case SHT_GNU_versym:
2181 {
2182 Elf32_Internal_Shdr * link_section;
2183 int total;
2184 int cnt;
2185 unsigned char * edata;
2186 unsigned short * data;
2187 char * strtab;
2188 Elf_Internal_Sym * symbols;
2189 Elf32_Internal_Shdr * string_sec;
2190
2191 link_section = section_headers + section->sh_link;
2192 total = section->sh_size / section->sh_entsize;
2193
2194 found = 1;
2195
2196 symbols = get_elf_symbols
2197 (file, link_section->sh_offset,
2198 link_section->sh_size / link_section->sh_entsize);
2199
2200 string_sec = section_headers + link_section->sh_link;
2201
2202 GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size,
2203 strtab, char *, "version string table");
2204
2205 printf (_("\nVersion symbols section '%s' contains %d entries:\n"),
2206 SECTION_NAME (section), total);
2207
2208 printf (_(" Addr: %#08x Offset: %#08x Link: %x (%s)\n"),
2209 section->sh_addr, section->sh_offset, section->sh_link,
2210 SECTION_NAME (link_section));
2211
2212 GET_DATA_ALLOC (version_info [DT_VERSIONTAGIDX (DT_VERSYM)]
2213 - loadaddr,
2214 total * sizeof (short), edata,
2215 char *, "version symbol data");
2216
2217 data = (unsigned short *) malloc (total * sizeof (short));
2218
2219 for (cnt = total; cnt --;)
2220 data [cnt] = byte_get (edata + cnt * sizeof (short), sizeof (short));
2221
2222 free (edata);
2223
2224 for (cnt = 0; cnt < total; cnt += 4)
2225 {
2226 int j, nn;
2227
2228 printf (" %03x:", cnt);
2229
2230 for (j = 0; (j < 4) && (cnt + j) < total; ++j)
2231 switch (data [cnt + j])
2232 {
2233 case 0:
2234 fputs (_(" 0 (*local*) "), stdout);
2235 break;
2236
2237 case 1:
2238 fputs (_(" 1 (*global*) "), stdout);
2239 break;
2240
2241 default:
2242 nn = printf ("%4x%c", data [cnt + j] & 0x7fff,
2243 data [cnt + j] & 0x8000 ? 'h' : ' ');
2244
2245 if (symbols [cnt + j].st_shndx < SHN_LORESERVE
2246 && section_headers[symbols [cnt + j].st_shndx].sh_type
2247 == SHT_NOBITS)
2248 {
2249 /* We must test both. */
2250 Elf_Internal_Verneed ivn;
2251 unsigned long offset;
2252
2253 offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)]
2254 - loadaddr;
2255
2256 do
2257 {
2258 Elf_External_Verneed evn;
2259 Elf_External_Vernaux evna;
2260 Elf_Internal_Vernaux ivna;
2261 unsigned long vna_off;
2262
2263 GET_DATA (offset, evn, "version need");
2264
2265 ivn.vn_aux = BYTE_GET (evn.vn_aux);
2266 ivn.vn_next = BYTE_GET (evn.vn_next);
2267
2268 vna_off = offset + ivn.vn_aux;
2269
2270 do
2271 {
2272 GET_DATA (vna_off, evna,
2273 "version need aux (1)");
2274
2275 ivna.vna_next = BYTE_GET (evna.vna_next);
2276 ivna.vna_other = BYTE_GET (evna.vna_other);
2277
2278 vna_off += ivna.vna_next;
2279 }
2280 while (ivna.vna_other != data [cnt + j]
2281 && ivna.vna_next != 0);
2282
2283 if (ivna.vna_other == data [cnt + j])
2284 {
2285 ivna.vna_name = BYTE_GET (evna.vna_name);
2286
2287 nn += printf ("(%s%-*s",
2288 strtab + ivna.vna_name,
2289 12 - strlen (strtab
2290 + ivna.vna_name),
2291 ")");
2292 break;
2293 }
2294 else if (ivn.vn_next == 0)
2295 {
2296 if (data [cnt + j] != 0x8001)
2297 {
2298 Elf_Internal_Verdef ivd;
2299 Elf_External_Verdef evd;
2300
2301 offset = version_info
2302 [DT_VERSIONTAGIDX (DT_VERDEF)]
2303 - loadaddr;
2304
2305 do
2306 {
2307 GET_DATA (offset, evd,
2308 "version definition");
2309
2310 ivd.vd_next = BYTE_GET (evd.vd_next);
2311 ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
2312
2313 offset += ivd.vd_next;
2314 }
2315 while (ivd.vd_ndx
2316 != (data [cnt + j] & 0x7fff)
2317 && ivd.vd_next != 0);
2318
2319 if (ivd.vd_ndx
2320 == (data [cnt + j] & 0x7fff))
2321 {
2322 Elf_External_Verdaux evda;
2323 Elf_Internal_Verdaux ivda;
2324
2325 ivd.vd_aux = BYTE_GET (evd.vd_aux);
2326
2327 GET_DATA (offset + ivd.vd_aux, evda,
2328 "version definition aux");
2329
2330 ivda.vda_name =
2331 BYTE_GET (evda.vda_name);
2332
2333 nn +=
2334 printf ("(%s%-*s",
2335 strtab + ivda.vda_name,
2336 12
2337 - strlen (strtab
2338 + ivda.vda_name),
2339 ")");
2340 }
2341 }
2342
2343 break;
2344 }
2345 else
2346 offset += ivn.vn_next;
2347 }
2348 while (ivn.vn_next);
2349 }
2350 else if (symbols [cnt + j].st_shndx == SHN_UNDEF)
2351 {
2352 Elf_Internal_Verneed ivn;
2353 unsigned long offset;
2354
2355 offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)]
2356 - loadaddr;
2357
2358 do
2359 {
2360 Elf_Internal_Vernaux ivna;
2361 Elf_External_Verneed evn;
2362 Elf_External_Vernaux evna;
2363 unsigned long a_off;
2364
2365 GET_DATA (offset, evn, "version need");
2366
2367 ivn.vn_aux = BYTE_GET (evn.vn_aux);
2368 ivn.vn_next = BYTE_GET (evn.vn_next);
2369
2370 a_off = offset + ivn.vn_aux;
2371
2372 do
2373 {
2374 GET_DATA (a_off, evna,
2375 "version need aux (2)");
2376
2377 ivna.vna_next = BYTE_GET (evna.vna_next);
2378 ivna.vna_other = BYTE_GET (evna.vna_other);
2379
2380 a_off += ivna.vna_next;
2381 }
2382 while (ivna.vna_other != data [cnt + j]
2383 && ivna.vna_next != 0);
2384
2385 if (ivna.vna_other == data [cnt + j])
2386 {
2387 ivna.vna_name = BYTE_GET (evna.vna_name);
2388
2389 nn += printf ("(%s%-*s",
2390 strtab + ivna.vna_name,
2391 12 - strlen (strtab
2392 + ivna.vna_name),
2393 ")");
2394 break;
2395 }
2396
2397 offset += ivn.vn_next;
2398 }
2399 while (ivn.vn_next);
2400 }
2401 else if (data [cnt + j] != 0x8001)
2402 {
2403 Elf_Internal_Verdef ivd;
2404 Elf_External_Verdef evd;
2405 unsigned long offset;
2406
2407 offset = version_info
2408 [DT_VERSIONTAGIDX (DT_VERDEF)] - loadaddr;
2409
2410 do
2411 {
2412 GET_DATA (offset, evd, "version def");
2413
2414 ivd.vd_next = BYTE_GET (evd.vd_next);
2415 ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
2416
2417 offset += ivd.vd_next;
2418 }
2419 while (ivd.vd_ndx != (data [cnt + j] & 0x7fff)
2420 && ivd.vd_next != 0);
2421
2422 if (ivd.vd_ndx == (data [cnt + j] & 0x7fff))
2423 {
2424 Elf_External_Verdaux evda;
2425 Elf_Internal_Verdaux ivda;
2426
2427 ivd.vd_aux = BYTE_GET (evd.vd_aux);
2428
2429 GET_DATA (offset - ivd.vd_next + ivd.vd_aux,
2430 evda, "version def aux");
2431
2432 ivda.vda_name = BYTE_GET (evda.vda_name);
2433
2434 nn += printf ("(%s%-*s",
2435 strtab + ivda.vda_name,
2436 12 - strlen (strtab
2437 + ivda.vda_name),
2438 ")");
2439 }
2440 }
2441
2442 if (nn < 18)
2443 printf ("%*c", 18 - nn, ' ');
2444 }
2445
2446 putchar ('\n');
2447 }
2448
2449 free (data);
2450 free (strtab);
2451 free (symbols);
2452 }
2453 break;
2454
2455 default:
2456 break;
2457 }
2458 }
2459
2460 if (! found)
2461 printf (_("\nNo version information found in this file.\n"));
2462
2463 return 1;
2464 }
2465
2466 static char *
2467 get_symbol_binding (binding)
2468 unsigned int binding;
2469 {
2470 static char buff [32];
2471
2472 switch (binding)
2473 {
2474 case STB_LOCAL: return _("LOCAL");
2475 case STB_GLOBAL: return _("GLOBAL");
2476 case STB_WEAK: return _("WEAK");
2477 default:
2478 if (binding >= STB_LOPROC && binding <= STB_HIPROC)
2479 sprintf (buff, _("<processor specific>: %d"), binding);
2480 else
2481 sprintf (buff, _("<unknown>: %d"), binding);
2482 return buff;
2483 }
2484 }
2485
2486 static char *
2487 get_symbol_type (type)
2488 unsigned int type;
2489 {
2490 static char buff [32];
2491
2492 switch (type)
2493 {
2494 case STT_NOTYPE: return _("NOTYPE");
2495 case STT_OBJECT: return _("OBJECT");
2496 case STT_FUNC: return _("FUNC");
2497 case STT_SECTION: return _("SECTION");
2498 case STT_FILE: return _("FILE");
2499 default:
2500 if (type >= STT_LOPROC && type <= STT_HIPROC)
2501 sprintf (buff, _("<processor specific>: %d"), type);
2502 else
2503 sprintf (buff, _("<unknown>: %d"), type);
2504 return buff;
2505 }
2506 }
2507
2508 static char *
2509 get_symbol_index_type (type)
2510 unsigned int type;
2511 {
2512 switch (type)
2513 {
2514 case SHN_UNDEF: return "UND";
2515 case SHN_ABS: return "ABS";
2516 case SHN_COMMON: return "COM";
2517 default:
2518 if (type >= SHN_LOPROC && type <= SHN_HIPROC)
2519 return "PRC";
2520 else if (type >= SHN_LORESERVE && type <= SHN_HIRESERVE)
2521 return "RSV";
2522 else
2523 {
2524 static char buff [32];
2525
2526 sprintf (buff, "%3d", type);
2527 return buff;
2528 }
2529 }
2530 }
2531
2532
2533 static int *
2534 get_dynamic_data (file, number)
2535 FILE * file;
2536 unsigned int number;
2537 {
2538 char * e_data;
2539 int * i_data;
2540
2541 e_data = (char *) malloc (number * 4);
2542
2543 if (e_data == NULL)
2544 {
2545 error (_("Out of memory\n"));
2546 return NULL;
2547 }
2548
2549 if (fread (e_data, 4, number, file) != number)
2550 {
2551 error (_("Unable to read in dynamic data\n"));
2552 return NULL;
2553 }
2554
2555 i_data = (int *) malloc (number * sizeof (* i_data));
2556
2557 if (i_data == NULL)
2558 {
2559 error (_("Out of memory\n"));
2560 free (e_data);
2561 return NULL;
2562 }
2563
2564 while (number--)
2565 i_data [number] = byte_get (e_data + number * 4, 4);
2566
2567 free (e_data);
2568
2569 return i_data;
2570 }
2571
2572 /* Dump the symbol table */
2573 static int
2574 process_symbol_table (file)
2575 FILE * file;
2576 {
2577 Elf32_Internal_Shdr * section;
2578
2579 if (! do_syms)
2580 return 1;
2581
2582 if (dynamic_info [DT_HASH] && do_using_dynamic && dynamic_strings != NULL)
2583 {
2584 char nb [4];
2585 char nc [4];
2586 int nbuckets;
2587 int nchains;
2588 int * buckets;
2589 int * chains;
2590 int hn;
2591 int si;
2592
2593 if (fseek (file, dynamic_info [DT_HASH] - loadaddr, SEEK_SET))
2594 {
2595 error (_("Unable to seek to start of dynamic information"));
2596 return 0;
2597 }
2598
2599 if (fread (& nb, sizeof (nb), 1, file) != 1)
2600 {
2601 error (_("Failed to read in number of buckets\n"));
2602 return 0;
2603 }
2604
2605 if (fread (& nc, sizeof (nc), 1, file) != 1)
2606 {
2607 error (_("Failed to read in number of chains\n"));
2608 return 0;
2609 }
2610
2611 nbuckets = byte_get (nb, 4);
2612 nchains = byte_get (nc, 4);
2613
2614 buckets = get_dynamic_data (file, nbuckets);
2615 chains = get_dynamic_data (file, nchains);
2616
2617 if (buckets == NULL || chains == NULL)
2618 return 0;
2619
2620 printf (_("\nSymbol table for image:\n"));
2621 printf (_(" Num Buc: Value Size Type Bind Ot Ndx Name\n"));
2622
2623 for (hn = 0; hn < nbuckets; hn++)
2624 {
2625 if (! buckets [hn])
2626 continue;
2627
2628 for (si = buckets [hn]; si; si = chains [si])
2629 {
2630 Elf_Internal_Sym * psym;
2631
2632 psym = dynamic_symbols + si;
2633
2634 printf (" %3d %3d: %8lx %5ld %6s %6s %2d ",
2635 si, hn,
2636 (unsigned long) psym->st_value,
2637 (unsigned long) psym->st_size,
2638 get_symbol_type (ELF_ST_TYPE (psym->st_info)),
2639 get_symbol_binding (ELF_ST_BIND (psym->st_info)),
2640 psym->st_other);
2641
2642 printf ("%3.3s", get_symbol_index_type (psym->st_shndx));
2643
2644 printf (" %s\n", dynamic_strings + psym->st_name);
2645 }
2646 }
2647
2648 free (buckets);
2649 free (chains);
2650 }
2651 else if (!do_using_dynamic)
2652 {
2653 unsigned int i;
2654
2655 for (i = 0, section = section_headers;
2656 i < elf_header.e_shnum;
2657 i++, section++)
2658 {
2659 unsigned int si;
2660 char * strtab;
2661 Elf_Internal_Sym * symtab;
2662 Elf_Internal_Sym * psym;
2663
2664
2665 if ( section->sh_type != SHT_SYMTAB
2666 && section->sh_type != SHT_DYNSYM)
2667 continue;
2668
2669 printf (_("\nSymbol table '%s' contains %d entries:\n"),
2670 SECTION_NAME (section),
2671 section->sh_size / section->sh_entsize);
2672 fputs (_(" Num: Value Size Type Bind Ot Ndx Name\n"),
2673 stdout);
2674
2675 symtab = get_elf_symbols (file, section->sh_offset,
2676 section->sh_size / section->sh_entsize);
2677 if (symtab == NULL)
2678 continue;
2679
2680 if (section->sh_link == elf_header.e_shstrndx)
2681 strtab = string_table;
2682 else
2683 {
2684 Elf32_Internal_Shdr * string_sec;
2685
2686 string_sec = section_headers + section->sh_link;
2687
2688 GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size,
2689 strtab, char *, "string table");
2690 }
2691
2692 for (si = 0, psym = symtab;
2693 si < section->sh_size / section->sh_entsize;
2694 si ++, psym ++)
2695 {
2696 printf (" %3d: %8lx %5ld %-7s %-6s %2d ",
2697 si,
2698 (unsigned long) psym->st_value,
2699 (unsigned long) psym->st_size,
2700 get_symbol_type (ELF_ST_TYPE (psym->st_info)),
2701 get_symbol_binding (ELF_ST_BIND (psym->st_info)),
2702 psym->st_other);
2703
2704 if (psym->st_shndx == 0)
2705 fputs (" UND", stdout);
2706 else if ((psym->st_shndx & 0xffff) == 0xfff1)
2707 fputs (" ABS", stdout);
2708 else if ((psym->st_shndx & 0xffff) == 0xfff2)
2709 fputs (" COM", stdout);
2710 else
2711 printf ("%4x", psym->st_shndx);
2712
2713 printf (" %s", strtab + psym->st_name);
2714
2715 if (section->sh_type == SHT_DYNSYM &&
2716 version_info [DT_VERSIONTAGIDX (DT_VERSYM)] != 0)
2717 {
2718 unsigned char data[2];
2719 unsigned short vers_data;
2720 unsigned long offset;
2721 int is_nobits;
2722 int check_def;
2723
2724 offset = version_info [DT_VERSIONTAGIDX (DT_VERSYM)]
2725 - loadaddr;
2726
2727 GET_DATA (offset + si * sizeof (vers_data), data,
2728 "version data");
2729
2730 vers_data = byte_get (data, 2);
2731
2732 is_nobits = psym->st_shndx < SHN_LORESERVE ?
2733 (section_headers [psym->st_shndx].sh_type == SHT_NOBITS)
2734 : 0;
2735
2736 check_def = (psym->st_shndx != SHN_UNDEF);
2737
2738 if ((vers_data & 0x8000) || vers_data > 1)
2739 {
2740 if (is_nobits || ! check_def)
2741 {
2742 Elf_External_Verneed evn;
2743 Elf_Internal_Verneed ivn;
2744 Elf_Internal_Vernaux ivna;
2745
2746 /* We must test both. */
2747 offset = version_info
2748 [DT_VERSIONTAGIDX (DT_VERNEED)] - loadaddr;
2749
2750 GET_DATA (offset, evn, "version need");
2751
2752 ivn.vn_aux = BYTE_GET (evn.vn_aux);
2753 ivn.vn_next = BYTE_GET (evn.vn_next);
2754
2755 do
2756 {
2757 unsigned long vna_off;
2758
2759 vna_off = offset + ivn.vn_aux;
2760
2761 do
2762 {
2763 Elf_External_Vernaux evna;
2764
2765 GET_DATA (vna_off, evna,
2766 "version need aux (3)");
2767
2768 ivna.vna_other = BYTE_GET (evna.vna_other);
2769 ivna.vna_next = BYTE_GET (evna.vna_next);
2770 ivna.vna_name = BYTE_GET (evna.vna_name);
2771
2772 vna_off += ivna.vna_next;
2773 }
2774 while (ivna.vna_other != vers_data
2775 && ivna.vna_next != 0);
2776
2777 if (ivna.vna_other == vers_data)
2778 break;
2779
2780 offset += ivn.vn_next;
2781 }
2782 while (ivn.vn_next != 0);
2783
2784 if (ivna.vna_other == vers_data)
2785 {
2786 printf ("@%s (%d)",
2787 strtab + ivna.vna_name, ivna.vna_other);
2788 check_def = 0;
2789 }
2790 else if (! is_nobits)
2791 error (_("bad dynamic symbol"));
2792 else
2793 check_def = 1;
2794 }
2795
2796 if (check_def)
2797 {
2798 if (vers_data != 0x8001)
2799 {
2800 Elf_Internal_Verdef ivd;
2801 Elf_Internal_Verdaux ivda;
2802 Elf_External_Verdaux evda;
2803 unsigned long offset;
2804
2805 offset =
2806 version_info [DT_VERSIONTAGIDX (DT_VERDEF)]
2807 - loadaddr;
2808
2809 do
2810 {
2811 Elf_External_Verdef evd;
2812
2813 GET_DATA (offset, evd, "version def");
2814
2815 ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
2816 ivd.vd_aux = BYTE_GET (evd.vd_aux);
2817 ivd.vd_next = BYTE_GET (evd.vd_next);
2818
2819 offset += ivd.vd_next;
2820 }
2821 while (ivd.vd_ndx != (vers_data & 0x7fff)
2822 && ivd.vd_next != 0);
2823
2824 offset -= ivd.vd_next;
2825 offset += ivd.vd_aux;
2826
2827 GET_DATA (offset, evda, "version def aux");
2828
2829 ivda.vda_name = BYTE_GET (evda.vda_name);
2830
2831 if (psym->st_name != ivda.vda_name)
2832 printf ((vers_data & 0x8000)
2833 ? "@%s" : "@@%s",
2834 strtab + ivda.vda_name);
2835 }
2836 }
2837 }
2838 }
2839
2840 putchar ('\n');
2841 }
2842
2843 free (symtab);
2844 if (strtab != string_table)
2845 free (strtab);
2846 }
2847 }
2848 else
2849 printf
2850 (_("\nDynamic symbol information is not available for displaying symbols.\n"));
2851
2852 return 1;
2853 }
2854
2855 static int
2856 process_section_contents (file)
2857 FILE * file;
2858 {
2859 Elf32_Internal_Shdr * section;
2860 unsigned int i;
2861
2862 if (! do_dump)
2863 return 1;
2864
2865 for (i = 0, section = section_headers;
2866 i < elf_header.e_shnum;
2867 i ++, section ++)
2868 {
2869 #ifdef SUPPORT_DISASSEMBLY
2870 /* See if we need an assembly dump of this section */
2871
2872 if ((i < NUM_DUMP_SECTS) && (dump_sects[i] & DISASS_DUMP))
2873 {
2874 printf (_("\nAssembly dump of section %s\n"),
2875 SECTION_NAME (section));
2876
2877 /* XXX -- to be done --- XXX */
2878 }
2879 #endif
2880 /* See if we need a hex dump of this section. */
2881 if ((i < NUM_DUMP_SECTS) && (dump_sects[i] & HEX_DUMP))
2882 {
2883 int bytes;
2884 int addr;
2885 unsigned char * data;
2886 char * start;
2887
2888 printf (_("\nHex dump of section '%s':\n"), SECTION_NAME (section));
2889
2890 bytes = section->sh_size;
2891 addr = section->sh_addr;
2892
2893 GET_DATA_ALLOC (section->sh_offset, bytes, start, char *,
2894 "section data");
2895
2896 data = start;
2897
2898 while (bytes)
2899 {
2900 int j;
2901 int k;
2902 int lbytes;
2903
2904 lbytes = (bytes > 16 ? 16 : bytes);
2905
2906 printf (" 0x%8.8x ", addr);
2907
2908 switch (elf_header.e_ident [EI_DATA])
2909 {
2910 case ELFDATA2LSB:
2911 for (j = 15; j >= 0; j --)
2912 {
2913 if (j < lbytes)
2914 printf ("%2.2x", data [j]);
2915 else
2916 printf (" ");
2917
2918 if (!(j & 0x3))
2919 printf (" ");
2920 }
2921 break;
2922
2923 case ELFDATA2MSB:
2924 for (j = 0; j < 16; j++)
2925 {
2926 if (j < lbytes)
2927 printf ("%2.2x", data [j]);
2928 else
2929 printf (" ");
2930
2931 if ((j & 3) == 3)
2932 printf (" ");
2933 }
2934 break;
2935 }
2936
2937 for (j = 0; j < lbytes; j++)
2938 {
2939 k = data [j];
2940 if (k >= ' ' && k < 0x80)
2941 printf ("%c", k);
2942 else
2943 printf (".");
2944 }
2945
2946 putchar ('\n');
2947
2948 data += lbytes;
2949 addr += lbytes;
2950 bytes -= lbytes;
2951 }
2952
2953 free (start);
2954 }
2955 }
2956
2957 return 1;
2958 }
2959
2960 static void
2961 process_mips_fpe_exception (mask)
2962 int mask;
2963 {
2964 if (mask)
2965 {
2966 int first = 1;
2967 if (mask & OEX_FPU_INEX)
2968 fputs ("INEX", stdout), first = 0;
2969 if (mask & OEX_FPU_UFLO)
2970 printf ("%sUFLO", first ? "" : "|"), first = 0;
2971 if (mask & OEX_FPU_OFLO)
2972 printf ("%sOFLO", first ? "" : "|"), first = 0;
2973 if (mask & OEX_FPU_DIV0)
2974 printf ("%sDIV0", first ? "" : "|"), first = 0;
2975 if (mask & OEX_FPU_INVAL)
2976 printf ("%sINVAL", first ? "" : "|");
2977 }
2978 else
2979 fputs ("0", stdout);
2980 }
2981
2982 static int
2983 process_mips_specific (file)
2984 FILE *file;
2985 {
2986 Elf_Internal_Dyn * entry;
2987 size_t liblist_offset = 0;
2988 size_t liblistno = 0;
2989 size_t options_offset = 0;
2990
2991 /* We have a lot of special sections. Thanks SGI! */
2992 if (dynamic_segment == NULL)
2993 /* No information available. */
2994 return 0;
2995
2996 for (entry = dynamic_segment; entry->d_tag != DT_NULL; ++entry)
2997 switch (entry->d_tag)
2998 {
2999 case DT_MIPS_LIBLIST:
3000 liblist_offset = entry->d_un.d_val - loadaddr;
3001 break;
3002 case DT_MIPS_LIBLISTNO:
3003 liblistno = entry->d_un.d_val;
3004 break;
3005 case DT_MIPS_OPTIONS:
3006 options_offset = entry->d_un.d_val - loadaddr;
3007 break;
3008 default:
3009 break;
3010 }
3011
3012 if (liblist_offset != 0 && liblistno != 0 && do_dynamic)
3013 {
3014 Elf32_External_Lib *elib;
3015 size_t cnt;
3016
3017 GET_DATA_ALLOC (liblist_offset, liblistno * sizeof (Elf32_External_Lib),
3018 elib, Elf32_External_Lib *, "liblist");
3019
3020 printf ("\nSection '.liblist' contains %d entries:\n", liblistno);
3021 fputs (" Library Time Stamp Checksum Version Flags\n",
3022 stdout);
3023
3024 for (cnt = 0; cnt < liblistno; ++cnt)
3025 {
3026 Elf32_Lib liblist;
3027 time_t time;
3028 char timebuf[17];
3029
3030 liblist.l_name = BYTE_GET (elib[cnt].l_name);
3031 time = BYTE_GET (elib[cnt].l_time_stamp);
3032 liblist.l_checksum = BYTE_GET (elib[cnt].l_checksum);
3033 liblist.l_version = BYTE_GET (elib[cnt].l_version);
3034 liblist.l_flags = BYTE_GET (elib[cnt].l_flags);
3035
3036 strftime (timebuf, 17, "%Y-%m-%dT%H:%M", gmtime (&time));
3037
3038 printf ("%3d: %-20s %s %#10lx %-7ld %#lx\n", cnt,
3039 dynamic_strings + liblist.l_name, timebuf,
3040 liblist.l_checksum, liblist.l_version, liblist.l_flags);
3041 }
3042
3043 free (elib);
3044 }
3045
3046 if (options_offset != 0)
3047 {
3048 Elf_External_Options *eopt;
3049 Elf_Internal_Shdr *sect = section_headers;
3050 Elf_Internal_Options *iopt;
3051 Elf_Internal_Options *option;
3052 size_t offset;
3053 int cnt;
3054
3055 /* Find the section header so that we get the size. */
3056 while (sect->sh_type != SHT_MIPS_OPTIONS)
3057 ++sect;
3058
3059 GET_DATA_ALLOC (options_offset, sect->sh_size, eopt,
3060 Elf_External_Options *, "options");
3061
3062 iopt = (Elf_Internal_Options *) malloc ((sect->sh_size / sizeof (eopt))
3063 * sizeof (*iopt));
3064 if (iopt == NULL)
3065 {
3066 error (_("Out of memory"));
3067 return 0;
3068 }
3069
3070 offset = cnt = 0;
3071 option = iopt;
3072 while (offset < sect->sh_size)
3073 {
3074 Elf_External_Options *eoption;
3075
3076 eoption = (Elf_External_Options *) ((char *) eopt + offset);
3077
3078 option->kind = BYTE_GET (eoption->kind);
3079 option->size = BYTE_GET (eoption->size);
3080 option->section = BYTE_GET (eoption->section);
3081 option->info = BYTE_GET (eoption->info);
3082
3083 offset += option->size;
3084 ++option;
3085 ++cnt;
3086 }
3087
3088 printf (_("\nSection '%s' contains %d entries:\n"),
3089 string_table + sect->sh_name, cnt);
3090
3091 option = iopt;
3092 while (cnt-- > 0)
3093 {
3094 size_t len;
3095
3096 switch (option->kind)
3097 {
3098 case ODK_NULL:
3099 /* This shouldn't happen. */
3100 printf (" NULL %d %x", option->section, option->info);
3101 break;
3102 case ODK_REGINFO:
3103 printf (" REGINFO ");
3104 if (elf_header.e_machine == EM_MIPS)
3105 {
3106 /* 32bit form. */
3107 Elf32_External_RegInfo *ereg;
3108 Elf32_RegInfo reginfo;
3109
3110 ereg = (Elf32_External_RegInfo *) (option + 1);
3111 reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask);
3112 reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]);
3113 reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]);
3114 reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]);
3115 reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]);
3116 reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value);
3117
3118 printf ("GPR %08lx GP %ld\n",
3119 reginfo.ri_gprmask, reginfo.ri_gp_value);
3120 printf (" CPR0 %08lx CPR1 %08lx CPR2 %08lx CPR3 %08lx\n",
3121 reginfo.ri_cprmask[0], reginfo.ri_cprmask[1],
3122 reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]);
3123 }
3124 else
3125 {
3126 /* 64 bit form. */
3127 Elf64_External_RegInfo *ereg;
3128 Elf64_Internal_RegInfo reginfo;
3129
3130 ereg = (Elf64_External_RegInfo *) (option + 1);
3131 reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask);
3132 reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]);
3133 reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]);
3134 reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]);
3135 reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]);
3136 reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value);
3137
3138 printf ("GPR %08lx GP %ld\n",
3139 reginfo.ri_gprmask, reginfo.ri_gp_value);
3140 printf (" CPR0 %08lx CPR1 %08lx CPR2 %08lx CPR3 %08lx\n",
3141 reginfo.ri_cprmask[0], reginfo.ri_cprmask[1],
3142 reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]);
3143 }
3144 ++option;
3145 continue;
3146 case ODK_EXCEPTIONS:
3147 fputs (" EXCEPTIONS fpe_min(", stdout);
3148 process_mips_fpe_exception (option->info & OEX_FPU_MIN);
3149 fputs (") fpe_max(", stdout);
3150 process_mips_fpe_exception ((option->info & OEX_FPU_MAX) >> 8);
3151 fputs (")", stdout);
3152
3153 if (option->info & OEX_PAGE0)
3154 fputs (" PAGE0", stdout);
3155 if (option->info & OEX_SMM)
3156 fputs (" SMM", stdout);
3157 if (option->info & OEX_FPDBUG)
3158 fputs (" FPDBUG", stdout);
3159 if (option->info & OEX_DISMISS)
3160 fputs (" DISMISS", stdout);
3161 break;
3162 case ODK_PAD:
3163 fputs (" PAD ", stdout);
3164 if (option->info & OPAD_PREFIX)
3165 fputs (" PREFIX", stdout);
3166 if (option->info & OPAD_POSTFIX)
3167 fputs (" POSTFIX", stdout);
3168 if (option->info & OPAD_SYMBOL)
3169 fputs (" SYMBOL", stdout);
3170 break;
3171 case ODK_HWPATCH:
3172 fputs (" HWPATCH ", stdout);
3173 if (option->info & OHW_R4KEOP)
3174 fputs (" R4KEOP", stdout);
3175 if (option->info & OHW_R8KPFETCH)
3176 fputs (" R8KPFETCH", stdout);
3177 if (option->info & OHW_R5KEOP)
3178 fputs (" R5KEOP", stdout);
3179 if (option->info & OHW_R5KCVTL)
3180 fputs (" R5KCVTL", stdout);
3181 break;
3182 case ODK_FILL:
3183 fputs (" FILL ", stdout);
3184 /* XXX Print content of info word? */
3185 break;
3186 case ODK_TAGS:
3187 fputs (" TAGS ", stdout);
3188 /* XXX Print content of info word? */
3189 break;
3190 case ODK_HWAND:
3191 fputs (" HWAND ", stdout);
3192 if (option->info & OHWA0_R4KEOP_CHECKED)
3193 fputs (" R4KEOP_CHECKED", stdout);
3194 if (option->info & OHWA0_R4KEOP_CLEAN)
3195 fputs (" R4KEOP_CLEAN", stdout);
3196 break;
3197 case ODK_HWOR:
3198 fputs (" HWOR ", stdout);
3199 if (option->info & OHWA0_R4KEOP_CHECKED)
3200 fputs (" R4KEOP_CHECKED", stdout);
3201 if (option->info & OHWA0_R4KEOP_CLEAN)
3202 fputs (" R4KEOP_CLEAN", stdout);
3203 break;
3204 case ODK_GP_GROUP:
3205 printf (" GP_GROUP %#06x self-contained %#06x",
3206 option->info & OGP_GROUP,
3207 (option->info & OGP_SELF) >> 16);
3208 break;
3209 case ODK_IDENT:
3210 printf (" IDENT %#06x self-contained %#06x",
3211 option->info & OGP_GROUP,
3212 (option->info & OGP_SELF) >> 16);
3213 break;
3214 default:
3215 /* This shouldn't happen. */
3216 printf (" %3d ??? %d %x",
3217 option->kind, option->section, option->info);
3218 break;
3219 }
3220
3221 len = sizeof (*eopt);
3222 while (len < option->size)
3223 if (((char *) option)[len] >= ' '
3224 && ((char *) option)[len] < 0x7f)
3225 printf ("%c", ((char *) option)[len++]);
3226 else
3227 printf ("\\%03o", ((char *) option)[len++]);
3228
3229 fputs ("\n", stdout);
3230 ++option;
3231 }
3232
3233 free (eopt);
3234 }
3235
3236 return 1;
3237 }
3238
3239 static int
3240 process_arch_specific (file)
3241 FILE *file;
3242 {
3243 switch (elf_header.e_machine)
3244 {
3245 case EM_MIPS:
3246 case EM_MIPS_RS4_BE:
3247 return process_mips_specific (file);
3248 break;
3249 default:
3250 break;
3251 }
3252 return 1;
3253 }
3254
3255 static int
3256 get_file_header (file)
3257 FILE * file;
3258 {
3259 Elf32_External_Ehdr ehdr;
3260
3261 if (fread (& ehdr, sizeof (ehdr), 1, file) != 1)
3262 return 0;
3263
3264 memcpy (elf_header.e_ident, ehdr.e_ident, EI_NIDENT);
3265
3266 if (elf_header.e_ident [EI_DATA] == ELFDATA2LSB)
3267 byte_get = byte_get_little_endian;
3268 else
3269 byte_get = byte_get_big_endian;
3270
3271 elf_header.e_entry = BYTE_GET (ehdr.e_entry);
3272 elf_header.e_phoff = BYTE_GET (ehdr.e_phoff);
3273 elf_header.e_shoff = BYTE_GET (ehdr.e_shoff);
3274 elf_header.e_version = BYTE_GET (ehdr.e_version);
3275 elf_header.e_flags = BYTE_GET (ehdr.e_flags);
3276 elf_header.e_type = BYTE_GET (ehdr.e_type);
3277 elf_header.e_machine = BYTE_GET (ehdr.e_machine);
3278 elf_header.e_ehsize = BYTE_GET (ehdr.e_ehsize);
3279 elf_header.e_phentsize = BYTE_GET (ehdr.e_phentsize);
3280 elf_header.e_phnum = BYTE_GET (ehdr.e_phnum);
3281 elf_header.e_shentsize = BYTE_GET (ehdr.e_shentsize);
3282 elf_header.e_shnum = BYTE_GET (ehdr.e_shnum);
3283 elf_header.e_shstrndx = BYTE_GET (ehdr.e_shstrndx);
3284
3285 return 1;
3286 }
3287
3288 static void
3289 process_file (file_name)
3290 char * file_name;
3291 {
3292 FILE * file;
3293 struct stat statbuf;
3294 unsigned int i;
3295
3296 if (stat (file_name, & statbuf) < 0)
3297 {
3298 error (_("Cannot stat input file %s.\n"), file_name);
3299 return;
3300 }
3301
3302 file = fopen (file_name, "rb");
3303 if (file == NULL)
3304 {
3305 error (_("Input file %s not found.\n"), file_name);
3306 return;
3307 }
3308
3309 if (! get_file_header (file))
3310 {
3311 error (_("%s: Failed to read file header\n"), file_name);
3312 fclose (file);
3313 return;
3314 }
3315
3316 /* Initialise per file variables. */
3317 for (i = NUM_ELEM (version_info); i--;)
3318 version_info [i] = 0;
3319
3320 for (i = NUM_ELEM (dynamic_info); i--;)
3321 dynamic_info [i] = 0;
3322
3323
3324 /* Process the file. */
3325 if (show_name)
3326 printf (_("\nFile: %s\n"), file_name);
3327
3328 if (! process_file_header ())
3329 {
3330 fclose (file);
3331 return;
3332 }
3333
3334 process_section_headers (file);
3335
3336 process_program_headers (file);
3337
3338 process_dynamic_segment (file);
3339
3340 process_relocs (file);
3341
3342 process_symbol_table (file);
3343
3344 process_version_sections (file);
3345
3346 process_section_contents (file);
3347
3348 process_arch_specific (file);
3349
3350 fclose (file);
3351
3352 if (section_headers)
3353 {
3354 free (section_headers);
3355 section_headers = NULL;
3356 }
3357
3358 if (string_table)
3359 {
3360 free (string_table);
3361 string_table = NULL;
3362 }
3363
3364 if (dynamic_strings)
3365 {
3366 free (dynamic_strings);
3367 dynamic_strings = NULL;
3368 }
3369
3370 if (dynamic_symbols)
3371 {
3372 free (dynamic_symbols);
3373 dynamic_symbols = NULL;
3374 }
3375 }
3376
3377 #ifdef SUPPORT_DISASSEMBLY
3378 /* Needed by the i386 disassembler. For extra credit, someone could
3379 fix this so that we insert symbolic addresses here, esp for GOT/PLT
3380 symbols */
3381
3382 void
3383 print_address (unsigned int addr, FILE * outfile)
3384 {
3385 fprintf (outfile,"0x%8.8x", addr);
3386 }
3387
3388 /* Needed by the i386 disassembler. */
3389 void
3390 db_task_printsym (unsigned int addr)
3391 {
3392 print_address (addr, stderr);
3393 }
3394 #endif
3395
3396 int
3397 main (argc, argv)
3398 int argc;
3399 char ** argv;
3400 {
3401 parse_args (argc, argv);
3402
3403 if (optind < (argc - 1))
3404 show_name = 1;
3405
3406 while (optind < argc)
3407 process_file (argv [optind ++]);
3408
3409 return 0;
3410 }