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