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