configure.in: Add -lXext to mips_extra_libs
[deliverable/binutils-gdb.git] / binutils / readelf.c
CommitLineData
76466873
NC
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. */
59bbaa19
ILT
23
24#include "bfd.h"
25#include "bucomm.h"
76466873
NC
26
27#include <assert.h>
28#include <sys/mman.h>
76466873 29#include <sys/stat.h>
76466873
NC
30
31#include "readelf.h"
c18f8aef 32#include "getopt.h"
76466873
NC
33
34#ifdef ANSI_PROTOTYPES
35#include <stdarg.h>
36#else
37#include <varargs.h>
38#endif
39
40unsigned int dynamic_addr;
41unsigned int dynamic_size;
42char * pint = "";
43char * program_name = "readelf";
44
45int dynamic_info [DT_JMPREL + 1];
46int version_info [16];
47
48int must_swap = 0;
49
50unsigned int rel_size;
51int loadaddr = -1;
52
53unsigned int rela_addr;
54unsigned int rela_size;
55char * strtab;
56int symtab_index;
57int lastmapped;
58char * header;
59
60Elf_Dyn * dpnt;
61Elf_Rel * rpnt;
62Elf_Shdr * elf_sections;
63Elf_Ehdr * epnt;
64Elf_Sym * symtab;
65
66int show_name;
67int do_dynamic;
68int do_syms;
69int do_reloc;
70int do_section;
71int do_load;
72int do_using_dynamic;
73int do_header;
74int do_dump;
75int do_version;
76long int expected_endian;
77
78char * dyntype[] =
79{
80 "NULL", "NEEDED","PLTRELSZ","PLTGOT","HASH","STRTAB","SYMTAB","RELA",
81 "RELASZ","RELAENT","STRSZ","SYMENT","INIT","FINI","SONAME","RPATH",
82 "SYMBOLIC","REL","RELSZ","RELENT","PLTREL","DEBUG","TEXTREL","JMPREL"
83};
84
85char * vertype[] =
86{
87 "VERNEEDNUM", "VERNEED", "VERDEFNUM", "VERDEF",
88 "", "", "", "", "", "", "", "", "", "", "", "VERSYM"
89};
90
91char * filtertype[] =
92{
93 "FILTER", "USED", "AUXILIARY"
94};
95
96
97char * sttinfo[] = {"NOTYPE","OBJECT","FUNC","SECTION","FILE"};
98char * stbinfo[] = {"LOCAL","GLOBAL","WEAK"};
99
100#define SECTION_NAME(X) (& header [lastmapped + (X)->sh_name])
101
102#define NUM_DUMP_SECTS 100
103char dump_sects [NUM_DUMP_SECTS];
104#define HEX_DUMP 1
105#define DISASS_DUMP 2
106
107/* Forward declarations for dumb compilers. */
108static char * get_i386_rel_type PARAMS ((bfd_vma rtype));
109static char * get_m68k_rel_type PARAMS ((bfd_vma rtype));
110static char * get_sparc_rel_type PARAMS ((bfd_vma rtype));
111static char * get_m32r_rel_type PARAMS ((bfd_vma rtype));
112static char * get_v850_rel_type PARAMS ((bfd_vma rtype));
113static char * get_d10v_rel_type PARAMS ((bfd_vma rtype));
2f300fe6 114/* start-sanitize-d30v */
76466873 115static char * get_d30v_rel_type PARAMS ((bfd_vma rtype));
2f300fe6 116/* end-sanitize-d30v */
76466873
NC
117static char * get_sh_rel_type PARAMS ((bfd_vma rtype));
118static char * get_mn10300_rel_type PARAMS ((bfd_vma rtype));
119static char * get_mn10200_rel_type PARAMS ((bfd_vma rtype));
a09db9ba 120static char * get_ppc_rel_type PARAMS ((bfd_vma rtype));
76466873 121static void dump_relocations PARAMS ((Elf_Rel * rpnt, int rel_size));
a09db9ba
MM
122static char * get_file_type PARAMS ((unsigned e_type));
123static char * get_machine_name PARAMS ((unsigned e_machine));
124static char * get_machine_data PARAMS ((unsigned e_data));
125static char * get_machine_flags PARAMS ((unsigned e_flags, unsigned e_machine));
76466873
NC
126static char * get_segment_type PARAMS ((unsigned long p_type));
127static char * get_section_type_name PARAMS ((unsigned int sh_type));
128static void usage PARAMS ((void));
129static void parse_args PARAMS ((int argc, char ** argv));
130static int process_elf_header PARAMS ((void));
131static void process_program_headers PARAMS ((void));
132static void process_section_headers PARAMS ((void));
133static void process_dynamic_segment PARAMS ((void));
134static void process_symbol_table PARAMS ((void));
135static void process_section_contents PARAMS ((void));
136static void process_file PARAMS ((char * file_name));
137
138
139#define SWAP2(val) ( (((val) << 8) & (0xff << 8)) \
140 | (((val) >> 8) & (0xff << 0)))
141
142#define SWAP4(val) ( (((val) << 24) & (0xff << 24)) \
143 | (((val) << 8) & (0xff << 16)) \
144 | (((val) >> 8) & (0xff << 8)) \
145 | (((val) >> 24) & (0xff << 0)))
146
147/* Warning: This macro assumes 8 bits in a char. */
148#define BYTE_SWAP(pointer, field) \
149 if (sizeof ((pointer)->field) == 2) \
150 { \
151 unsigned short val = (pointer)->field ; \
152 new_header->field = SWAP2 (val); \
153 } \
154 else if (sizeof ((pointer)->field) != 4) \
155 abort (); \
156 else \
157 { \
158 unsigned long val = (pointer)->field ; \
159 new_header->field = SWAP4 (val); \
160 }
161
162
163#ifdef ANSI_PROTOTYPES
164static void
165error (const char * message, ...)
166{
167 va_list args;
168
169 fprintf (stderr, _("%s: Error: "), program_name);
170 va_start (args, message);
171 vfprintf (stderr, message, args);
172 va_end (args);
173 return;
174}
175
176static void
177warn (const char * message, ...)
178{
179 va_list args;
180
181 fprintf (stderr, _("%s: Warning: "), program_name);
182 va_start (args, message);
183 vfprintf (stderr, message, args);
184 va_end (args);
185 return;
186}
187#else
188static void
189error (va_alist)
190{
191 char * message;
192 va_list args;
193
194 fprintf (stderr, _("%s: Error: "), program_name);
195 va_start (args);
196 message = va_arg (args, char *);
197 vfprintf (stderr, message, args);
198 va_end (args);
199 return;
200}
201
202static void
203warn (va_alist)
204 va_dcl;
205{
206 char * message;
207 va_list args;
208
209 fprintf (stderr, _("%s: Warning: "), program_name);
210 va_start (args);
211 message = va_arg (args, char *);
212 vfprintf (stderr, message, args);
213 va_end (args);
214 return;
215}
216#endif
217
218
219static char *
220get_i386_rel_type (rtype)
221 bfd_vma rtype;
222{
223 switch (rtype)
224 {
225 case 0: return "R_386_NONE";
226 case 1: return "R_386_32";
227 case 2: return "R_386_PC32";
228 case 3: return "R_386_GOT32";
229 case 4: return "R_386_PLT32";
230 case 5: return "R_386_COPY";
231 case 6: return "R_386_GLOB_DAT";
232 case 7: return "R_386_JMP_SLOT";
233 case 8: return "R_386_RELATIVE";
234 case 9: return "R_386_GOTOFF";
235 case 10: return "R_386_GOTPC";
236 case 20: return "R_386_16";
237 case 21: return "R_386_PC16";
238 case 22: return "R_386_PC8";
239 case 23: return "R_386_max";
240 default: return _("*INVALID*");
241 }
242}
243
244static char *
245get_m68k_rel_type (rtype)
246 bfd_vma rtype;
247{
248 switch (rtype)
249 {
250 case 0: return "R_68K_NONE";
251 case 1: return "R_68K_32";
252 case 2: return "R_68K_16";
253 case 3: return "R_68K_8";
254 case 4: return "R_68K_PC32";
255 case 5: return "R_68K_PC16";
256 case 6: return "R_68K_PC8";
257 case 7: return "R_68K_GOT32";
258 case 8: return "R_68K_GOT16";
259 case 9: return "R_68K_GOT8";
260 case 10: return "R_68K_GOT32O";
261 case 11: return "R_68K_GOT16O";
262 case 12: return "R_68K_GOT8O";
263 case 13: return "R_68K_PLT32";
264 case 14: return "R_68K_PLT16";
265 case 15: return "R_68K_PLT8";
266 case 16: return "R_68K_PLT32O";
267 case 17: return "R_68K_PLT16O";
268 case 18: return "R_68K_PLT8O";
269 case 19: return "R_68K_COPY";
270 case 20: return "R_68K_GLOB_DAT";
271 case 21: return "R_68K_JMP_SLOT";
272 case 22: return "R_68K_RELATIVE";
273 default: return _("*INVALID*");
274 }
275}
276
277
278static char *
279get_sparc_rel_type (rtype)
280 bfd_vma rtype;
281{
282 switch (rtype)
283 {
284 case 0: return "R_SPARC_NONE";
285 case 1: return "R_SPARC_8";
286 case 2: return "R_SPARC_16";
287 case 3: return "R_SPARC_32";
288 case 4: return "R_SPARC_DISP8";
289 case 5: return "R_SPARC_DISP16";
290 case 6: return "R_SPARC_DISP32";
291 case 7: return "R_SPARC_WDISP30";
292 case 8: return "R_SPARC_WDISP22";
293 case 9: return "R_SPARC_HI22";
294 case 10: return "R_SPARC_22";
295 case 11: return "R_SPARC_13";
296 case 12: return "R_SPARC_LO10";
297 case 13: return "R_SPARC_GOT10";
298 case 14: return "R_SPARC_GOT13";
299 case 15: return "R_SPARC_GOT22";
300 case 16: return "R_SPARC_PC10";
301 case 17: return "R_SPARC_PC22";
302 case 18: return "R_SPARC_WPLT30";
303 case 19: return "R_SPARC_COPY";
304 case 20: return "R_SPARC_GLOB_DAT";
305 case 21: return "R_SPARC_JMP_SLOT";
306 case 22: return "R_SPARC_RELATIVE";
307 case 23: return "R_SPARC_UA32";
308 case 24: return "R_SPARC_10";
309 case 25: return "R_SPARC_11";
310 case 26: return "R_SPARC_64";
311 case 27: return "R_SPARC_OLO10";
312 case 28: return "R_SPARC_HH22";
313 case 29: return "R_SPARC_HM10";
314 case 30: return "R_SPARC_LM22";
315 case 31: return "R_SPARC_PC_HH22";
316 case 32: return "R_SPARC_PC_HM10";
317 case 33: return "R_SPARC_PC_LM22";
318 case 34: return "R_SPARC_WDISP16";
319 case 35: return "R_SPARC_WDISP19";
320 case 36: return "R_SPARC_UNUSED_42";
321 case 37: return "R_SPARC_7";
322 case 38: return "R_SPARC_5";
323 case 39: return "R_SPARC_6";
324 case 40: return "R_SPARC_DISP64";
325 case 41: return "R_SPARC_PLT64";
326 case 42: return "R_SPARC_HIX22";
327 case 43: return "R_SPARC_LOX10";
328 case 44: return "R_SPARC_H44";
329 case 45: return "R_SPARC_M44";
330 case 46: return "R_SPARC_L44";
331 case 47: return "R_SPARC_REGISTER";
332 case 48: return "R_SPARC_UA64";
333 case 49: return "R_SPARC_UA16";
334 case 50: return "R_SPARC_32LE";
335 default: return _("*INVALID*");
336 }
337}
338
339
340static char *
341get_m32r_rel_type (rtype)
342 bfd_vma rtype;
343{
344 switch (rtype)
345 {
346 case 0: return "R_M32R_NONE";
347 case 1: return "R_M32R_16";
348 case 2: return "R_M32R_32";
349 case 3: return "R_M32R_24";
350 case 4: return "R_M32R_10_PCREL";
351 case 5: return "R_M32R_18_PCREL";
352 case 6: return "R_M32R_26_PCREL";
353 case 7: return "R_M32R_HI16_ULO";
354 case 8: return "R_M32R_HI16_SLO";
355 case 9: return "R_M32R_LO16";
356 case 10: return "R_M32R_SDA16";
357 default: return _("*INVALID*");
358 }
359}
360
361
362static char *
363get_v850_rel_type (rtype)
364 bfd_vma rtype;
365{
366 switch (rtype)
367 {
368 case 0: return "R_V850_NONE";
369 case 1: return "R_V850_9_PCREL";
370 case 2: return "R_V850_22_PCREL";
371 case 3: return "R_V850_HI16_S";
372 case 4: return "R_V850_HI16";
373 case 5: return "R_V850_LO16";
374 case 6: return "R_V850_32";
375 case 7: return "R_V850_16";
376 case 8: return "R_V850_8";
377 case 9: return "R_V850_SDA_16_16_OFFSET";
378 case 10: return "R_V850_SDA_15_16_OFFSET";
379 case 11: return "R_V850_ZDA_16_16_OFFSET";
380 case 12: return "R_V850_ZDA_15_16_OFFSET";
381 case 13: return "R_V850_TDA_6_8_OFFSET";
382 case 14: return "R_V850_TDA_7_8_OFFSET";
383 case 15: return "R_V850_TDA_7_7_OFFSET";
384 case 16: return "R_V850_TDA_16_16_OFFSET";
385/* start-sanitize-v850e */
386 case 17: return "R_V850_TDA_4_5_OFFSET";
387 case 18: return "R_V850_TDA_4_4_OFFSET";
388 case 19: return "R_V850_SDA_16_16_SPLIT_OFFSET";
389 case 20: return "R_V850_ZDA_16_16_SPLIT_OFFSET";
390 case 21: return "R_V850_CALLT_6_7_OFFSET";
391 case 22: return "R_V850_CALLT_16_16_OFFSET";
392/* end-sanitize-v850e */
393 default: return _("*INVALID*");
394 }
395}
396
397
398static char *
399get_d10v_rel_type (rtype)
400 bfd_vma rtype;
401{
402 switch (rtype)
403 {
404 case 0: return "R_D10V_NONE";
405 case 1: return "R_D10V_10_PCREL_R";
406 case 2: return "R_D10V_10_PCREL_L";
407 case 3: return "R_D10V_16";
408 case 4: return "R_D10V_18";
409 case 5: return "R_D10V_18_PCREL";
410 case 6: return "R_D10V_32";
411 default: return _("*INVALID*");
412 }
413}
414
2f300fe6 415/* start-sanitize-d30v */
76466873
NC
416static char *
417get_d30v_rel_type (rtype)
418 bfd_vma rtype;
419{
420 switch (rtype)
421 {
422 case 0: return "R_D30V_NONE";
423 case 1: return "R_D30V_6";
424 case 2: return "R_D30V_9_PCREL";
425 case 3: return "R_D30V_9_PCREL_R";
426 case 4: return "R_D30V_15";
427 case 5: return "R_D30V_15_PCREL";
428 case 6: return "R_D30V_15_PCREL_R";
429 case 7: return "R_D30V_21";
430 case 8: return "R_D30V_21_PCREL";
431 case 9: return "R_D30V_21_PCREL_R";
432 case 10: return "R_D30V_32";
433 case 11: return "R_D30V_32_PCREL";
434 case 12: return "R_D30V_32_NORMAL";
435 default: return _("*INVALID*");
436 }
437}
438
2f300fe6 439/* end-sanitize-d30v */
76466873
NC
440static char *
441get_sh_rel_type (rtype)
442 bfd_vma rtype;
443{
444 switch (rtype)
445 {
446 case 0: return "R_SH_NONE";
447 case 1: return "R_SH_DIR32";
448 case 2: return "R_SH_REL32";
449 case 3: return "R_SH_DIR8WPN";
450 case 4: return "R_SH_IND12W";
451 case 5: return "R_SH_DIR8WPL";
452 case 6: return "R_SH_DIR8WPZ";
453 case 7: return "R_SH_DIR8BP";
454 case 8: return "R_SH_DIR8W";
455 case 9: return "R_SH_DIR8L";
456 case 25: return "R_SH_SWITCH16";
457 case 26: return "R_SH_SWITCH32";
458 case 27: return "R_SH_USES";
459 case 28: return "R_SH_COUNT";
460 case 29: return "R_SH_ALIGN";
461 case 30: return "R_SH_CODE";
462 case 31: return "R_SH_DATA";
463 case 32: return "R_SH_LABEL";
464 default: return _("*INVALID*");
465 }
466}
467
468
469static char *
470get_mn10300_rel_type (rtype)
471 bfd_vma rtype;
472{
473 switch (rtype)
474 {
475 case 0: return "R_MN10300_NONE";
476 case 1: return "R_MN10300_32";
477 case 2: return "R_MN10300_16";
478 case 3: return "R_MN10300_8";
479 case 4: return "R_MN10300_PCREL32";
480 case 5: return "R_MN10300_PCREL16";
481 case 6: return "R_MN10300_PCREL8";
482 default: return _("*INVALID*");
483 }
484}
485
486
487static char *
488get_mn10200_rel_type (rtype)
489 bfd_vma rtype;
490{
491 switch (rtype)
492 {
493 case 0: return "R_MN10200_NONE";
494 case 1: return "R_MN10200_32";
495 case 2: return "R_MN10200_16";
496 case 3: return "R_MN10200_8";
497 case 4: return "R_MN10200_24";
498 case 5: return "R_MN10200_PCREL8";
499 case 6: return "R_MN10200_PCREL16";
500 case 7: return "R_MN10200_PCREL24";
501 default: return _("*INVALID*");
502 }
503}
504
505
a09db9ba
MM
506static char *
507get_ppc_rel_type (rtype)
508 bfd_vma rtype;
509{
510 switch (rtype)
511 {
512 case 0: return "R_PPC_NONE,";
513 case 1: return "R_PPC_ADDR32,";
514 case 2: return "R_PPC_ADDR24,";
515 case 3: return "R_PPC_ADDR16,";
516 case 4: return "R_PPC_ADDR16_LO,";
517 case 5: return "R_PPC_ADDR16_HI,";
518 case 6: return "R_PPC_ADDR16_HA,";
519 case 7: return "R_PPC_ADDR14,";
520 case 8: return "R_PPC_ADDR14_BRTAKEN,";
521 case 9: return "R_PPC_ADDR14_BRNTAKEN,";
522 case 10: return "R_PPC_REL24,";
523 case 11: return "R_PPC_REL14,";
524 case 12: return "R_PPC_REL14_BRTAKEN,";
525 case 13: return "R_PPC_REL14_BRNTAKEN,";
526 case 14: return "R_PPC_GOT16,";
527 case 15: return "R_PPC_GOT16_LO,";
528 case 16: return "R_PPC_GOT16_HI,";
529 case 17: return "R_PPC_GOT16_HA,";
530 case 18: return "R_PPC_PLT24,";
531 case 19: return "R_PPC_COPY,";
532 case 21: return "R_PPC_JMP_SLOT,";
533 case 22: return "R_PPC_RELATIVE,";
534 case 23: return "R_PPC_LOCAL24PC,";
535 case 24: return "R_PPC_UADDR32,";
536 case 25: return "R_PPC_UADDR16,";
537 case 26: return "R_PPC_REL32,";
538 case 27: return "R_PPC_PLT32,";
539 case 28: return "R_PPC_PLTREL32,";
540 case 29: return "R_PPC_PLT16_LO,";
541 case 30: return "R_PPC_PLT16_HI,";
542 case 31: return "R_PPC_PLT16_HA,";
543 case 32: return "R_PPC_SDAREL,";
544 case 33: return "R_PPC_SECTOFF,";
545 case 34: return "R_PPC_SECTOFF_LO,";
546 case 35: return "R_PPC_SECTOFF_HI,";
547 case 36: return "R_PPC_SECTOFF_HA,";
548 case 101: return "R_PPC_EMB_NADDR32,";
549 case 102: return "R_PPC_EMB_NADDR16,";
550 case 103: return "R_PPC_EMB_NADDR16_LO,";
551 case 104: return "R_PPC_EMB_NADDR16_HI,";
552 case 105: return "R_PPC_EMB_NADDR16_HA,";
553 case 106: return "R_PPC_EMB_SDAI16,";
554 case 107: return "R_PPC_EMB_SDA2I16,";
555 case 108: return "R_PPC_EMB_SDA2REL,";
556 case 109: return "R_PPC_EMB_SDA21,";
557 case 110: return "R_PPC_EMB_MRKREF,";
558 case 111: return "R_PPC_EMB_RELSEC16,";
559 case 112: return "R_PPC_EMB_RELST_LO,";
560 case 113: return "R_PPC_EMB_RELST_HI,";
561 case 114: return "R_PPC_EMB_RELST_HA,";
562 case 115: return "R_PPC_EMB_BIT_FLD,";
563 case 116: return "R_PPC_EMB_RELSDA,";
564 default: return _("*INVALID*");
565 }
566}
567
568
76466873
NC
569static void
570dump_relocations (rpnt, rel_size)
571 Elf_Rel * rpnt;
572 int rel_size;
573{
574 int i;
575 int is_rela;
576 Elf_Rela * rapnt;
577 Elf_Rela * relocs = NULL;
578
579
580 rapnt = (Elf_Rela *) rpnt;
581
582 /* Compute number of relocations. */
583 switch (epnt->e_machine)
584 {
585 case EM_386:
586 case EM_486:
587 case EM_CYGNUS_M32R:
588 case EM_CYGNUS_D10V:
589 rel_size = rel_size / sizeof (Elf_Rel);
590
591 if (must_swap)
592 {
593 Elf_Rel * new_header = malloc (sizeof (* new_header) * rel_size);
594
595 if (new_header == NULL)
596 {
597 error (_("out of memory\n"));
598 return;
599 }
600
601 memcpy (new_header, rpnt, sizeof (* new_header) * rel_size);
602
603 rpnt = new_header;
604 relocs = (Elf_Rela *) new_header;
605
606 for (i = 0; i < rel_size; i++)
607 {
608 BYTE_SWAP (rpnt + i, r_offset);
609 BYTE_SWAP (rpnt + i, r_info);
610
611 new_header ++;
612 }
613 }
614
615 is_rela = 0;
616 break;
617
618 case EM_68K:
619 case EM_SPARC:
a09db9ba 620 case EM_PPC:
76466873 621 case EM_CYGNUS_V850:
2f300fe6 622 /* start-sanitize-d30v */
76466873 623 case EM_CYGNUS_D30V:
2f300fe6 624 /* end-sanitize-d30v */
76466873
NC
625 case EM_CYGNUS_MN10200:
626 case EM_CYGNUS_MN10300:
627 case EM_SH:
628 rel_size = rel_size / sizeof (Elf_Rela);
629
630 if (must_swap)
631 {
632 Elf_Rela * new_header = malloc (sizeof (* new_header) * rel_size);
633
634 if (new_header == NULL)
635 {
636 error (_("out of memory\n"));
637 return;
638 }
639
640 memcpy (new_header, rpnt, sizeof (* new_header) * rel_size);
641
642 relocs = rapnt = new_header;
643
644 for (i = rel_size; i--;)
645 {
646 BYTE_SWAP (new_header, r_offset);
647 BYTE_SWAP (new_header, r_info);
648 BYTE_SWAP (new_header, r_addend);
649
650 new_header ++;
651 }
652 }
653
654 is_rela = 1;
655 break;
656
657 default:
658 warn (_("Don't know about relocations on this machine architecture\n"));
659 return;
660 }
661
662 if (is_rela)
663 printf (_(" Offset Value Type Symbol's Value Symbol Name Addend\n"));
664 else
665 printf (_(" Offset Value Type Symbol's Value Symbol Name\n"));
666
667 for (i = 0; i < rel_size; i++)
668 {
669 char * rtype;
670
671 if (is_rela)
672 rpnt = (Elf_Rel *) rapnt;
673
c18f8aef 674 printf (" %5.5lx %5.5lx ", rpnt->r_offset, rpnt->r_info);
76466873
NC
675
676 switch (epnt->e_machine)
677 {
c18f8aef
NC
678 default:
679 rtype = "UGG!";
680 break;
681
76466873
NC
682 case EM_CYGNUS_M32R:
683 rtype = get_m32r_rel_type (ELF32_R_TYPE (rpnt->r_info));
684 break;
685
686 case EM_386:
687 case EM_486:
688 rtype = get_i386_rel_type (ELF32_R_TYPE (rpnt->r_info));
689 break;
690
691 case EM_68K:
692 rtype = get_m68k_rel_type (ELF32_R_TYPE (rpnt->r_info));
693 break;
694
695 case EM_SPARC:
696 rtype = get_sparc_rel_type (ELF32_R_TYPE (rapnt->r_info));
697 break;
698
699 case EM_CYGNUS_V850:
700 rtype = get_v850_rel_type (ELF32_R_TYPE (rpnt->r_info));
701 break;
702
703 case EM_CYGNUS_D10V:
704 rtype = get_d10v_rel_type (ELF32_R_TYPE (rpnt->r_info));
705 break;
706
2f300fe6 707 /* start-sanitize-d30v */
76466873
NC
708 case EM_CYGNUS_D30V:
709 rtype = get_d30v_rel_type (ELF32_R_TYPE (rpnt->r_info));
710 break;
711
2f300fe6 712 /* end-sanitize-d30v */
76466873
NC
713 case EM_SH:
714 rtype = get_sh_rel_type (ELF32_R_TYPE (rpnt->r_info));
715 break;
716
717 case EM_CYGNUS_MN10300:
718 rtype = get_mn10300_rel_type (ELF32_R_TYPE (rpnt->r_info));
719 break;
720
721 case EM_CYGNUS_MN10200:
722 rtype = get_mn10200_rel_type (ELF32_R_TYPE (rpnt->r_info));
723 break;
a09db9ba
MM
724
725 case EM_PPC:
726 rtype = get_ppc_rel_type (ELF32_R_TYPE (rpnt->r_info));
727 break;
76466873
NC
728 }
729
730 printf ("%-18s", rtype);
731
732 symtab_index = ELF32_R_SYM (rpnt->r_info);
733
734 if (symtab_index)
735 {
736 Elf_Sym ssym;
737 Elf_Sym * psym;
738
739 psym = symtab + symtab_index;
740
741 if (must_swap)
742 {
743 Elf_Sym * new_header = & ssym;
744
745 ssym = * psym;
746
747 BYTE_SWAP (psym, st_name);
748 BYTE_SWAP (psym, st_value);
749 /* BYTE_SWAP (psym, st_size); */
750 BYTE_SWAP (psym, st_shndx);
751
752 psym = new_header;
753 }
754
755 if (psym->st_name == 0)
c18f8aef 756 printf (" %08lx %-15s", psym->st_value,
76466873
NC
757 SECTION_NAME (elf_sections + psym->st_shndx));
758 else
c18f8aef 759 printf (" %08lx %-15s", psym->st_value, strtab + psym->st_name);
76466873
NC
760
761 if (is_rela)
c18f8aef 762 printf (" + %lx", rapnt->r_addend);
76466873
NC
763 }
764
765 putchar ('\n');
766 rapnt ++;
767 rpnt ++;
768 }
769
770 if (relocs != NULL)
771 free (relocs);
772}
773
774static char *
775get_file_type (e_type)
a09db9ba 776 unsigned e_type;
76466873
NC
777{
778 static char buff [32];
779
780 switch (e_type)
781 {
782 case ET_NONE: return _("None");
783 case ET_REL: return _("Relocatable file");
784 case ET_EXEC: return _("Executable file");
785 case ET_DYN: return _("Shared object file");
786 case ET_CORE: return _("Core file");
787
788 default:
789 if ((e_type >= ET_LOPROC) && (e_type <= ET_HIPROC))
790 sprintf (buff, _("Processor Specific: (%x)"), e_type);
791 else
792 sprintf (buff, _("<unknown>: %x"), e_type);
793 return buff;
794 }
795}
796
797static char *
798get_machine_name (e_machine)
a09db9ba 799 unsigned e_machine;
76466873
NC
800{
801 static char buff [32];
802
803 switch (e_machine)
804 {
805 case EM_NONE: return _("None");
806 case EM_M32: return "WE32100";
807 case EM_SPARC: return "Sparc";
808 case EM_386: return "80386";
809 case EM_68K: return "MC68000";
810 case EM_88K: return "MC88000";
811 case EM_486: return "Intel 80486";
812 case EM_860: return "Intel 80860";
813 case EM_MIPS: return "MIPS R3000 big-endian";
814 case EM_S370: return "Amdahl";
815 case EM_MIPS_RS4_BE: return "MIPS R400 big-endian";
816 case EM_PARISC: return "HPPA";
817 case EM_SPARC32PLUS: return "Sparc v8+" ;
a09db9ba 818 case EM_PPC: return "PowerPC";
76466873
NC
819 case EM_SPARCV9: return "Sparc v9";
820 case EM_ARM: return "ARM";
821 case EM_SH: return "Hitachi SH";
822 case EM_ALPHA: return "Alpha";
823 case EM_CYGNUS_D10V: return "d10v";
2f300fe6 824 /* start-sanitize-d30v */
76466873 825 case EM_CYGNUS_D30V: return "d30v";
2f300fe6 826 /* end-sanitize-d30v */
76466873
NC
827 case EM_CYGNUS_M32R: return "M32r";
828 case EM_CYGNUS_V850: return "v850";
829 case EM_CYGNUS_MN10300: return "mn10300";
830 case EM_CYGNUS_MN10200: return "mn10200";
831
832 default:
833 sprintf (buff, _("<unknown>: %x"), e_machine);
834 return buff;
835 }
836}
837
a09db9ba
MM
838static char *
839get_machine_flags (e_flags, e_machine)
840 unsigned e_flags;
841 unsigned e_machine;
842{
843 static char buf [1024];
844
845 buf[0] = '\0';
846 if (e_flags)
847 {
848 switch (e_machine)
849 {
850 default:
851 break;
852
853 case EM_PPC:
854 if (e_flags & EF_PPC_EMB)
855 strcat (buf, ", emb");
856
857 if (e_flags & EF_PPC_RELOCATABLE)
858 strcat (buf, ", relocatable");
859
860 if (e_flags & EF_PPC_RELOCATABLE_LIB)
861 strcat (buf, ", relocatable-lib");
862 break;
863
864 case EM_CYGNUS_M32R:
865 if ((e_flags & EF_M32R_ARCH) == E_M32R_ARCH)
866 strcat (buf, ", m32r");
867
868 /* start-sanitize-m32rx */
869#ifdef E_M32RX_ARCH
870 if ((e_flags & EF_M32R_ARCH) == E_M32RX_ARCH)
871 strcat (buf, ", m32rx");
872#endif
873 /* end-sanitize-m32rx */
874 break;
875
876 case EM_MIPS:
877 case EM_MIPS_RS4_BE:
878 if (e_flags & EF_MIPS_NOREORDER)
879 strcat (buf, ", noreorder");
880
881 if (e_flags & EF_MIPS_PIC)
882 strcat (buf, ", pic");
883
884 if (e_flags & EF_MIPS_CPIC)
885 strcat (buf, ", cpic");
886
887 if (e_flags & EF_MIPS_ABI2)
888 strcat (buf, ", abi2");
889
890 if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_1)
891 strcat (buf, ", mips1");
892
893 if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_2)
894 strcat (buf, ", mips2");
895
896 if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_3)
897 strcat (buf, ", mips3");
898
899 if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_4)
900 strcat (buf, ", mips4");
901 break;
902 }
903 }
904
905 return buf;
906}
907
908static char *
909get_machine_data (e_data)
910 unsigned e_data;
911{
912 static char buff [32];
913
914 switch (e_data)
915 {
916 case ELFDATA2LSB: return _("ELFDATA2LSB (little endian)");
917 case ELFDATA2MSB: return _("ELFDATA2MSB (big endian)");
918 default:
919 sprintf (buff, _("<unknown>: %x"), e_data);
920 return buff;
921 }
922}
923
76466873
NC
924static char *
925get_segment_type (p_type)
926 unsigned long p_type;
927{
928 static char buff [32];
929
930 switch (p_type)
931 {
932 case PT_NULL: return _("Unused");
933 case PT_LOAD: return _("Loadable");
934 case PT_DYNAMIC: return _("Dynamic link info");
935 case PT_INTERP: return _("Interpreter");
936 case PT_NOTE: return _("Auxillary Info");
937 case PT_SHLIB: return _("Shared Library");
938 case PT_PHDR: return _("Program Headers");
939
940 default:
941 if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC))
942 return _("processor specific");
943 else
944 {
945 sprintf (buff, _("<unknown>: %x"), p_type);
946 return buff;
947 }
948 }
949}
950
951static char *
952get_section_type_name (sh_type)
953 unsigned int sh_type;
954{
955 static char buff [32];
956
957 switch (sh_type)
958 {
959 case SHT_NULL: return _("Unused");
960 case SHT_PROGBITS: return _("Program data");
961 case SHT_SYMTAB: return _("Symbol table");
962 case SHT_STRTAB: return _("String table");
963 case SHT_RELA: return _("Relocs, addends");
964 case SHT_HASH: return _("Symbol hash table");
965 case SHT_DYNAMIC: return _("Dynamic linking info");
966 case SHT_NOTE: return _("Notes");
967 case SHT_NOBITS: return _("Space, no data");
968 case SHT_REL: return _("Relocs, no addends");
969 case SHT_SHLIB: return _("Shared Library info");
970 case SHT_DYNSYM: return _("Dynamic linker symbols");
971 case SHT_GNU_verdef: return _("Version definition");
972 case SHT_GNU_verneed: return _("Version needs");
973 case SHT_GNU_versym: return _("Version symbols");
974 case 0x6ffffff0: return "VERSYM";
975 case 0x6ffffffc: return "VERDEF";
976 case 0x7ffffffd: return "AUXILIARY";
977 case 0x7fffffff: return "FILTER";
978
979 default:
980 if ((sh_type >= SHT_LOPROC) && (sh_type <= SHT_HIPROC))
981 return _("processor specific");
982 else if ((sh_type >= SHT_LOUSER) && (sh_type <= SHT_HIUSER))
983 return _("application specific");
984 else
985 {
986 sprintf (buff, _("<unknown>: %x"), sh_type);
987 return buff;
988 }
989 }
990}
991
992struct option options [] =
993{
994 {"all", no_argument, 0, 'a'},
995 {"file-header", no_argument, 0, 'h'},
996 {"program-headers", no_argument, 0, 'l'},
997 {"segments", no_argument, 0, 'l'},
998 {"sections", no_argument, 0, 'S'},
999 {"symbols", no_argument, 0, 's'},
1000 {"relocs", no_argument, 0, 'r'},
1001 {"dynamic", no_argument, 0, 'd'},
1002 {"version-info", no_argument, 0, 'V'},
1003 {"use-dynamic", no_argument, 0, 'D'},
1004
1005 {"hex-dump", required_argument, 0, 'x'},
1006#ifdef SUPPORT_DISASSEMBLY
1007 {"instruction-dump", required_argument, 0, 'i'},
1008#endif
1009
1010 {"version", no_argument, 0, 'v'},
1011 {"help", no_argument, 0, 'H'},
1012
1013 {0, no_argument, 0, 0}
1014};
1015
1016static void
1017usage ()
1018{
59bbaa19
ILT
1019 fprintf (stdout, _("Usage: readelf {options} elf-file(s)\n"));
1020 fprintf (stdout, _(" Options are:\n"));
1021 fprintf (stdout, _(" -a or --all Display all the information\n"));
1022 fprintf (stdout, _(" -h or --file-header Display the ELF file header\n"));
1023 fprintf (stdout, _(" -l or --program-headers or --segments\n"));
1024 fprintf (stdout, _(" Display the program headers\n"));
1025 fprintf (stdout, _(" -S or --sections Display the sections' headers\n"));
1026 fprintf (stdout, _(" -s or --symbols Display the symbol table\n"));
1027 fprintf (stdout, _(" -r or --relocs Display the relocations (if present)\n"));
1028 fprintf (stdout, _(" -d or --dynamic Display the dynamic section (if present)\n"));
1029 fprintf (stdout, _(" -V or --version-info Display the version sections (if present)\n"));
1030 fprintf (stdout, _(" -D or --use-dynamic Use the dynamic section info when displaying symbols\n"));
1031 fprintf (stdout, _(" -x <number> or --hex-dump=<number>\n"));
1032 fprintf (stdout, _(" Dump the contents of section <number>\n"));
76466873 1033#ifdef SUPPORT_DISASSEMBLY
59bbaa19
ILT
1034 fprintf (stdout, _(" -i <number> or --instruction-dump=<number>\n"));
1035 fprintf (stdout, _(" Disassemble the contents of section <number>\n"));
76466873 1036#endif
59bbaa19
ILT
1037 fprintf (stdout, _(" -v or --version Display the version number of readelf\n"));
1038 fprintf (stdout, _(" -H or --help Display this information\n"));
1039 fprintf (stdout, _("Report bugs to bug-gnu-utils@gnu.org\n"));
76466873
NC
1040
1041 exit (0);
1042}
1043
1044static void
1045parse_args (argc, argv)
1046 int argc;
1047 char ** argv;
1048{
59bbaa19
ILT
1049 int c;
1050
76466873
NC
1051 if (argc < 2)
1052 usage ();
1053
1054 while ((c = getopt_long
1055 (argc, argv, "rsahldSDx:i:vV", options, NULL)) != EOF)
1056 {
1057 char * cp;
1058 int section;
1059
1060 switch (c)
1061 {
1062 case 'H':
1063 usage ();
1064 break;
1065
1066 case 'a':
1067 do_syms++;
1068 do_reloc++;
1069 do_dynamic++;
1070 do_header++;
1071 do_section++;
1072 do_load++;
1073 do_version++;
1074 break;
1075 case 'D':
1076 do_using_dynamic++;
1077 break;
1078 case 'r':
1079 do_reloc++;
1080 break;
1081 case 'h':
1082 do_header++;
1083 break;
1084 case 'l':
1085 do_load++;
1086 break;
1087 case 's':
1088 do_syms++;
1089 break;
1090 case 'S':
1091 do_section++;
1092 break;
1093 case 'd':
1094 do_dynamic++;
1095 break;
1096 case 'x':
1097 do_dump ++;
1098 section = strtoul (optarg, & cp, 0);
1099 if (! * cp && section >= 0 && section < NUM_DUMP_SECTS)
1100 {
1101 dump_sects [section] |= HEX_DUMP;
1102 break;
1103 }
1104 goto oops;
1105#ifdef SUPPORT_DISASSEMBLY
1106 case 'i':
1107 do_dump ++;
1108 section = strtoul (optarg, & cp, 0);
1109 if (! * cp && section >= 0 && section < NUM_DUMP_SECTS)
1110 {
1111 dump_sects [section] |= DISASS_DUMP;
1112 break;
1113 }
1114 goto oops;
1115#endif
1116 case 'v':
1117 print_version (program_name);
1118 break;
1119 case 'V':
1120 do_version ++;
1121 break;
1122 default:
1123 oops:
1124 /* xgettext:c-format */
1125 error (_("Invalid option '-%c'\n"), c);
1126 /* Drop through. */
1127 case '?':
1128 usage ();
1129 }
1130 }
1131
1132 if (!do_dynamic && !do_syms && !do_reloc && !do_section
1133 && !do_load && !do_header && !do_dump && !do_version)
1134 usage ();
1135 else if (argc < 3)
59bbaa19
ILT
1136 {
1137 warn (_("Nothing to do.\n"));
1138 usage();
1139 }
76466873
NC
1140}
1141
1142static int
1143process_elf_header ()
1144{
1145 if ( epnt->e_ident [EI_MAG0] != ELFMAG0
1146 || epnt->e_ident [EI_MAG1] != ELFMAG1
1147 || epnt->e_ident [EI_MAG2] != ELFMAG2
1148 || epnt->e_ident [EI_MAG3] != ELFMAG3)
1149 {
1150 error (_("Not an ELF file - it has the wrong magic bytes at the start\n"));
1151 return 0;
1152 }
1153
1154 if (epnt->e_ident [EI_CLASS] != ELFCLASS32)
1155 {
1156 error (_("Not a 32 bit ELF file\n"));
1157 return 0;
1158 }
1159
1160 if (epnt->e_ident [EI_DATA] != expected_endian)
1161 must_swap = 1;
1162
1163 if (must_swap)
1164 {
1165 Elf_Ehdr * new_header = malloc (sizeof (* new_header));
1166
1167 if (new_header == NULL)
1168 {
1169 error (_("out of memory\n"));
1170 return 0;
1171 }
1172
1173 memcpy (new_header, epnt, sizeof (* new_header));
1174
1175 BYTE_SWAP (epnt, e_type);
1176 BYTE_SWAP (epnt, e_machine);
1177 BYTE_SWAP (epnt, e_version);
1178 BYTE_SWAP (epnt, e_entry);
1179 BYTE_SWAP (epnt, e_phoff);
1180 BYTE_SWAP (epnt, e_shoff);
1181 BYTE_SWAP (epnt, e_flags);
1182 BYTE_SWAP (epnt, e_ehsize);
1183 BYTE_SWAP (epnt, e_phentsize);
1184 BYTE_SWAP (epnt, e_phnum);
1185 BYTE_SWAP (epnt, e_shentsize);
1186 BYTE_SWAP (epnt, e_shnum);
1187 BYTE_SWAP (epnt, e_shstrndx);
1188
1189 epnt = new_header;
1190 }
1191
1192 if (do_header)
1193 {
1194 int i;
1195
1196 printf (_("ELF Header....\n"));
1197 printf (_(" Magic: "));
1198 for (i = 0; i < EI_NIDENT; i ++)
1199 printf ("%2.2x ", epnt->e_ident [i]);
1200 printf ("\n");
1201 printf (_(" Type: %s\n"), get_file_type (epnt->e_type));
1202 printf (_(" Machine: %s\n"), get_machine_name (epnt->e_machine));
a09db9ba
MM
1203 printf (_(" Version: 0x%lx\n"), (unsigned long)epnt->e_version);
1204 printf (_(" Data: %s\n"), get_machine_data (epnt->e_ident [EI_DATA]));
1205 printf (_(" Entry point address: 0x%lx\n"), (unsigned long)epnt->e_entry);
1206 printf (_(" Start of program headers: %ld (bytes into file)\n"), (long)epnt->e_phoff);
1207 printf (_(" Start of section headers: %ld (bytes into file)\n"), (long)epnt->e_shoff);
1208 printf (_(" Flags: 0x%lx%s\n"), (unsigned long)epnt->e_flags,
1209 get_machine_flags (epnt->e_flags, epnt->e_machine));
1210 printf (_(" Size of this header: %ld (bytes)\n"), (long)epnt->e_ehsize);
1211 printf (_(" Size of program headers: %ld (bytes)\n"), (long)epnt->e_phentsize);
1212 printf (_(" Number of program headers: %ld\n"), (long)epnt->e_phnum);
1213 printf (_(" Size of section headers: %ld (bytes)\n"), (long)epnt->e_shentsize);
1214 printf (_(" Number of section headers: %ld\n"), (long)epnt->e_shnum);
1215 printf (_(" Section header string table index: %ld\n"), (long)epnt->e_shstrndx);
76466873
NC
1216 }
1217
1218 return 1;
1219}
1220
1221
1222static void
1223process_program_headers ()
1224{
1225 Elf_Phdr * elf_segments;
1226 Elf_Phdr * ppnt;
1227 int i;
1228
1229 if (epnt->e_phnum == 0)
1230 {
1231 if (do_load)
1232 printf (_("\nThere are no program headers in this file\n"));
1233 return;
1234 }
1235
1236 if (do_load && !do_header)
1237 {
1238 printf (_("\nElf file is %s\n"), get_file_type (epnt->e_type));
1239 printf (_("Entry point 0x%x\n"), epnt->e_entry);
1240 printf (_("There are %d program headers, starting at offset %x:\n"),
1241 epnt->e_phnum, epnt->e_phoff);
1242 }
1243
1244 if (must_swap)
1245 {
1246 Elf_Phdr * new_header = malloc (sizeof (* new_header) * epnt->e_phnum);
1247
1248 if (new_header == NULL)
1249 {
1250 error (_("out of memory\n"));
1251 return;
1252 }
1253
1254 memcpy (new_header, & header [epnt->e_phoff],
1255 sizeof (* new_header) * epnt->e_phnum);
1256
1257 elf_segments = ppnt = new_header;
1258
1259 for (i = 0; i < epnt->e_phnum; i++)
1260 {
1261 BYTE_SWAP (ppnt + i, p_type);
1262 BYTE_SWAP (ppnt + i, p_flags);
1263 BYTE_SWAP (ppnt + i, p_offset);
1264 BYTE_SWAP (ppnt + i, p_vaddr);
1265 BYTE_SWAP (ppnt + i, p_paddr);
1266 BYTE_SWAP (ppnt + i, p_filesz);
1267 BYTE_SWAP (ppnt + i, p_memsz);
1268 BYTE_SWAP (ppnt + i, p_align);
1269
1270 new_header ++;
1271 }
1272 }
1273 else
1274 {
1275 ppnt = (Elf_Phdr *) & header [epnt->e_phoff];
1276 elf_segments = NULL;
1277 }
1278
1279 if (do_load)
1280 {
1281 printf (_("\nProgram Header%s....\n"), epnt->e_phnum > 1 ? "s" : "");
1282 printf (_(" Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align\n"));
1283 }
1284
1285 loadaddr = -1;
1286 dynamic_addr = 0;
1287
1288 for (i = 0; i < epnt->e_phnum; i++)
1289 {
1290 if (loadaddr == -1 && ppnt->p_type == PT_LOAD)
1291 loadaddr = (ppnt->p_vaddr & 0xfffff000)
1292 - (ppnt->p_offset & 0xfffff000);
1293
1294 if (do_load)
1295 {
1296 printf (" %-10s ", get_segment_type (ppnt->p_type));
c18f8aef
NC
1297 printf ("0x%5.5lx ",ppnt->p_offset);
1298 printf ("0x%8.8lx ",ppnt->p_vaddr);
1299 printf ("0x%8.8lx ",ppnt->p_paddr);
1300 printf ("0x%5.5lx 0x%5.5lx ",ppnt->p_filesz, ppnt->p_memsz);
76466873
NC
1301 printf ("%c%c%c ",
1302 (ppnt->p_flags & 4 ? 'R' : ' '),
1303 (ppnt->p_flags & 2 ? 'W' : ' '),
1304 (ppnt->p_flags & 1 ? 'E' : ' '));
c18f8aef 1305 printf ("%#lx", ppnt->p_align);
76466873
NC
1306 }
1307
1308 if (ppnt->p_type == PT_DYNAMIC)
1309 {
1310 if (dynamic_addr)
1311 error (_("more than one dynamic section\n"));
1312
1313 dynamic_addr = ppnt->p_offset;
1314 dynamic_size = ppnt->p_filesz;
1315 }
1316
1317 if (ppnt->p_type == PT_INTERP)
1318 {
1319 if (do_load)
1320 printf (_("\nRequesting program interpreter [%s]"),
1321 & header [ppnt->p_offset]);
1322 pint = strdup (& header [ppnt->p_offset]);
1323 }
1324
1325 if (do_load)
1326 putc ('\n', stdout);
1327
1328 ppnt ++;
1329 }
1330
1331 if (do_load)
1332 {
1333 printf (_("\n Section to Segment mapping:\n"));
1334 printf (_(" Segment Sections...\n"));
1335
1336 if (elf_segments)
1337 ppnt = elf_segments;
1338 else
1339 ppnt = (Elf_Phdr *) & header [epnt->e_phoff];
1340
1341 for (i = 0; i < epnt->e_phnum; i++, ppnt++)
1342 {
1343 int j;
1344 Elf_Shdr * spnt;
1345
1346 printf (" %2.2d ", i);
1347
1348 spnt = (Elf_Shdr *) & header [epnt->e_shoff];
1349
1350 if (must_swap)
1351 {
1352 lastmapped = SWAP4 (spnt[epnt->e_shstrndx].sh_offset);
1353
1354 for (j = 0; j < epnt->e_shnum; j++)
1355 {
1356 bfd_vma addr;
1357 bfd_size_type size;
1358 unsigned int name;
1359
1360 addr = SWAP4 (spnt[j].sh_addr);
1361 size = SWAP4 (spnt[j].sh_size);
1362 name = SWAP4 (spnt[j].sh_name);
1363
1364 if (size > 0
1365 && (addr >= ppnt->p_vaddr)
1366 && (addr + size) <= (ppnt->p_vaddr + ppnt->p_memsz))
1367 printf ("%s ", header + lastmapped + name);
1368 }
1369 }
1370 else
1371 {
1372 lastmapped = spnt[epnt->e_shstrndx].sh_offset;
1373
1374 for (j = 0; j < epnt->e_shnum; j++, spnt++)
1375 {
1376 if (spnt->sh_size > 0
1377 && (spnt->sh_addr >= ppnt->p_vaddr)
1378 && (spnt->sh_addr + spnt->sh_size)
1379 <= (ppnt->p_vaddr + ppnt->p_memsz))
1380 printf ("%s ", SECTION_NAME (spnt));
1381 }
1382 }
1383
1384 putc ('\n',stdout);
1385 }
1386 }
1387
1388 if (elf_segments)
1389 free (elf_segments);
1390}
1391
1392
1393static void
1394process_section_headers ()
1395{
1396 Elf_Shdr * spnt;
1397 int i;
1398
1399 if (must_swap)
1400 {
1401 Elf_Shdr * new_header = malloc (sizeof (* new_header) * epnt->e_shnum);
1402
1403 if (new_header == NULL)
1404 {
1405 error (_("out of memory\n"));
1406 return;
1407 }
1408
1409 memcpy (new_header, & header [epnt->e_shoff],
1410 sizeof (* new_header) * epnt->e_shnum);
1411
1412 elf_sections = spnt = new_header;
1413
1414 for (i = 0; i < epnt->e_shnum; i++)
1415 {
1416 BYTE_SWAP (spnt + i, sh_name);
1417 BYTE_SWAP (spnt + i, sh_type);
1418 BYTE_SWAP (spnt + i, sh_flags);
1419 BYTE_SWAP (spnt + i, sh_addr);
1420 BYTE_SWAP (spnt + i, sh_offset);
1421 BYTE_SWAP (spnt + i, sh_size);
1422 BYTE_SWAP (spnt + i, sh_link);
1423 BYTE_SWAP (spnt + i, sh_info);
1424 BYTE_SWAP (spnt + i, sh_addralign);
1425 BYTE_SWAP (spnt + i, sh_entsize);
1426
1427 new_header ++;
1428 }
1429 }
1430 else
1431 {
1432 elf_sections = spnt = (Elf_Shdr *) & header [epnt->e_shoff];
1433 }
1434
1435 spnt += epnt->e_shstrndx;
1436 lastmapped = spnt->sh_offset;
1437 spnt = elf_sections;
1438
1439 if (! do_section || (epnt->e_shnum == 0))
1440 return;
1441
1442 if (! do_header)
1443 printf (_("There are %d section headers, starting at offset %x:\n"),
1444 epnt->e_shnum, epnt->e_shoff);
1445
1446 printf (_("\nSection Header%s....\n"), epnt->e_shnum > 1 ? "s" : "");
1e3d6cc4 1447 printf (_(" [Nr] Name Type Addr Off Size ES Flg Lk In Al\n"));
76466873
NC
1448
1449 for (i = 0; i < epnt->e_shnum; i++)
1450 {
1e3d6cc4 1451 printf (" [%2d] %-17s", i, SECTION_NAME (spnt));
76466873 1452
1e3d6cc4 1453 printf (" %-15s ",get_section_type_name (spnt->sh_type));
c18f8aef 1454 printf ( "%8.8lx %6.6lx %6.6lx %2.2lx",
76466873
NC
1455 spnt->sh_addr,
1456 spnt->sh_offset,
1457 spnt->sh_size,
1458 spnt->sh_entsize);
1459
c18f8aef 1460 printf (" %c%c%c %2ld %2lx %ld \n",
76466873
NC
1461 (spnt->sh_flags & 1 ? 'W' : ' '),
1462 (spnt->sh_flags & 2 ? 'A' : ' '),
1463 (spnt->sh_flags & 4 ? 'X' : ' '),
1464 spnt->sh_link,
1465 spnt->sh_info,
1466 spnt->sh_addralign);
1467 spnt ++;
1468 }
1469}
1470
1471/* Parse the dynamic segment */
1472static void
1473process_dynamic_segment ()
1474{
1475 Elf_Dyn * elf_dynamic;
1476 unsigned int i;
1477
1478 dynamic_size = dynamic_size / sizeof (Elf_Dyn);
1479
1480 if (must_swap)
1481 {
1482 Elf_Dyn * new_header = malloc (sizeof (* new_header) * dynamic_size);
1483
1484 if (new_header == NULL)
1485 {
1486 error (_("out of memory\n"));
1487 return;
1488 }
1489
1490 memcpy (new_header, & header [dynamic_addr],
1491 sizeof (* new_header) * dynamic_size);
1492
1493 elf_dynamic = dpnt = new_header;
1494
1495 for (i = 0; i < dynamic_size; i++)
1496 {
1497 BYTE_SWAP (dpnt + i, d_tag);
1498 BYTE_SWAP (dpnt + i, d_un.d_ptr);
1499
1500 new_header ++;
1501 }
1502 }
1503 else
1504 {
1505 dpnt = (Elf_Dyn *) & header [dynamic_addr];
1506 elf_dynamic = NULL;
1507 }
1508
1509 /* Find symtab. */
1510 for (i = 0; i < dynamic_size; ++i, ++dpnt)
1511 if (dpnt->d_tag == DT_SYMTAB)
1512 {
1513 dynamic_info [DT_SYMTAB] = dpnt->d_un.d_val;
1514 symtab = (Elf_Sym *) (header - loadaddr
1515 + dynamic_info[DT_SYMTAB]);
1516 }
1517 else if (dpnt->d_tag == DT_STRTAB)
1518 {
1519 dynamic_info [DT_STRTAB] = dpnt->d_un.d_val;
1520 strtab = (char *) (header - loadaddr + dynamic_info[DT_STRTAB]);
1521 }
1522
1523 if (do_dynamic && dynamic_addr)
1524 {
1525 printf (_("\n Dynamic section data: %x, %d entries\n"),
1526 dynamic_addr, dynamic_size );
1527 }
1528
1529 for (i = 0; i < dynamic_size; i++)
1530 {
1531 if (do_dynamic)
1532 printf (_(" Tag: %#10x: "), dpnt->d_tag);
1533
1534 switch (dpnt->d_tag)
1535 {
1536 case DT_AUXILIARY:
1537 case DT_FILTER:
1538 if (do_dynamic)
1539 {
1540 printf ("(%-11s)", filtertype [DT_FILTER - dpnt->d_tag]);
1541
1542 if (dynamic_info [DT_STRTAB])
1543 {
1544 if (dpnt->d_tag == DT_AUXILIARY)
1545 printf (_("Auxiliary library"));
1546 else
1547 printf (_("Filter library"));
1548
1549 printf (": [%s]\n", (dpnt->d_un.d_val + strtab));
1550 }
1551 else
1552 printf (_("Value %x\n"), dpnt->d_un.d_val);
1553 }
1554 break;
1555
1556 case DT_NULL :
1557 case DT_NEEDED :
1558 case DT_PLTRELSZ:
1559 case DT_PLTGOT :
1560 case DT_HASH :
1561 case DT_STRTAB :
1562 case DT_SYMTAB :
1563 case DT_RELA :
1564 case DT_RELASZ :
1565 case DT_RELAENT :
1566 case DT_STRSZ :
1567 case DT_SYMENT :
1568 case DT_INIT :
1569 case DT_FINI :
1570 case DT_SONAME :
1571 case DT_RPATH :
1572 case DT_SYMBOLIC:
1573 case DT_REL :
1574 case DT_RELSZ :
1575 case DT_RELENT :
1576 case DT_PLTREL :
1577 case DT_DEBUG :
1578 case DT_TEXTREL :
1579 case DT_JMPREL :
1580 dynamic_info [dpnt->d_tag] = dpnt->d_un.d_val;
1581
1582 if (do_dynamic)
1583 {
1584 printf ("(%-11s)", dyntype [dpnt->d_tag]);
1585
1586 if (dynamic_info [DT_STRTAB])
1587 {
1588 switch (dpnt->d_tag)
1589 {
1590 case DT_NEEDED:
1591 printf (_("Shared library: [%s]\n"),
1592 (dpnt->d_un.d_val + strtab));
1593
1594 if (strcmp (dpnt->d_un.d_val + strtab, pint))
1595 printf ("\n");
1596 else
1597 printf (_(" program interpreter\n"));
1598 break;
1599
1600 case DT_SONAME:
1601 printf (_("Library soname: [%s]\n"),
1602 (dpnt->d_un.d_val + strtab));
1603 break;
1604
1605 case DT_RPATH:
1606 printf (_("Library rpath: [%s]\n"),
1607 (dpnt->d_un.d_val + strtab));
1608 break;
1609
1610 default:
1611 printf (_("Value %x\n"), dpnt->d_un.d_val);
1612 }
1613 }
1614 else
1615 printf (_("Value %x\n"), dpnt->d_un.d_val);
1616 }
1617 break;
1618
1619 default:
1620 if ((dpnt->d_tag >= DT_VERSYM) && (dpnt->d_tag <= DT_VERNEEDNUM))
1621 {
1622 version_info [DT_VERSIONTAGIDX (dpnt->d_tag)] = dpnt->d_un.d_val;
1623
1624 if (do_dynamic)
1625 printf (_("(%-11s) Value %#x\n"),
1626 vertype [DT_VERSIONTAGIDX (dpnt->d_tag)],
1627 dpnt->d_un.d_ptr);
1628 }
1629 else
1630 warn (_("<Invalid> Value %#x\n"), dpnt->d_un.d_ptr);
1631 break;
1632 }
1633
1634 dpnt ++;
1635 }
1636
1637 if (do_reloc)
1638 {
1639 if (do_using_dynamic)
1640 {
1641 if (dynamic_info [DT_REL])
1642 {
1643 rpnt = (Elf_Rel *) (header + dynamic_info [DT_REL] - loadaddr);
1644 rel_size = dynamic_info [DT_RELSZ];
1645 if (rel_size)
1646 {
1647 printf (_("\nRelocation section data: %x %x\n"),
1648 dynamic_info[DT_REL], rel_size);
1649 dump_relocations (rpnt, rel_size);
1650 }
1651 else
1652 printf (_("\nNo Relocations in this file\n"));
1653 }
1654
1655 if (dynamic_info[DT_RELA])
1656 {
1657 rpnt = (Elf_Rel *) (header + dynamic_info[DT_RELA] - loadaddr);
1658 rel_size = dynamic_info[DT_RELASZ];
1659 if (rel_size)
1660 {
1661 printf (_("\nRelocation section data: %x %x\n"),
1662 dynamic_info[DT_RELA], rel_size);
1663 dump_relocations (rpnt, rel_size);
1664 }
1665 else
1666 printf (_("\nNo Relocations in this file\n"));
1667 }
1668
1669 if (dynamic_info[DT_JMPREL])
1670 {
1671 rpnt = (Elf_Rel *) (header + dynamic_info[DT_JMPREL]
1672 - loadaddr);
1673 rel_size = dynamic_info[DT_PLTRELSZ];
1674 if (rel_size)
1675 {
1676 printf (_("\nJumptable Relocation section data: %x %x\n"),
1677 dynamic_info[DT_JMPREL], rel_size);
1678 dump_relocations (rpnt, rel_size);
1679 }
1680 else
1681 printf (_("\nNo Relocations in this file\n"));
1682 }
1683 }
1684 else
1685 {
1686 Elf_Shdr * spnt;
1687
1688 spnt = elf_sections;
1689
1690 for (i = 0; i < epnt->e_shnum; i++, spnt++)
1691 {
1692 Elf_Shdr * symsec;
1693
1694
1695 if (spnt->sh_type != SHT_RELA && spnt->sh_type != SHT_REL)
1696 continue;
1697
1698 rpnt = (Elf_Rel *) (header + spnt->sh_offset);
1699
1700 rel_size = spnt->sh_size;
1701
1702 if (rel_size)
1703 {
1704 printf (_("\nRelocation section data: %s (%#x entries)\n"),
1705 SECTION_NAME (spnt), rel_size / spnt->sh_entsize);
1706
1707 symsec = & elf_sections [spnt->sh_link];
1708 symtab = (Elf_Sym *) (header + symsec->sh_offset);
1709 strtab = (char *) (header
1710 + elf_sections [symsec->sh_link].sh_offset);
1711
1712 dump_relocations (rpnt, rel_size);
1713 }
1714 else
1715 printf (_("\nNo Relocations in this file\n"));
1716 }
1717 }
1718 }
1719
1720 if (elf_dynamic)
1721 free (elf_dynamic);
1722}
1723
1724/* Dump the symbol table */
1725static void
1726process_symbol_table ()
1727{
1728 char * pnt;
1729 int i;
1730 Elf_Shdr * spnt;
1731
1732 if (! do_syms)
1733 return;
1734
1735 if (dynamic_info [DT_HASH] && do_using_dynamic)
1736 {
1737 int nbucket;
1738 int nchain;
1739 int * elf_buckets;
1740 int * chains;
1741 int hn;
1742 int si;
1743 int * hash_addr;
1744
1745 hash_addr = (int *) (dynamic_info [DT_HASH] + header - loadaddr);
1746
1747 nbucket = *hash_addr++;
1748 nchain = *hash_addr++;
1749 elf_buckets = hash_addr;
1750 hash_addr += nbucket;
1751 chains = hash_addr;
1752
1753 printf (_("\n Symbol table for image\n"));
1754 printf (_(" Num Buc: Value Size Type Bind Ot Ndx Name\n"));
1755
1756 for (hn = 0; hn < nbucket; hn++)
1757 {
1758 if (! elf_buckets [hn])
1759 continue;
1760
1761 for (si = elf_buckets[hn]; si; si = chains[si])
1762 {
1763 pnt = strtab + symtab[si].st_name;
1764
c18f8aef 1765 printf ("%3d %3d: %8lx %5ld %6s %6s %2d ", si, hn,
76466873
NC
1766 symtab[si].st_value,
1767 symtab[si].st_size,
1768 sttinfo [ELF_ST_TYPE (symtab[si].st_info)],
1769 stbinfo [ELF_ST_BIND (symtab[si].st_info)],
1770 symtab[si].st_other);
1771
1772 if (symtab[si].st_shndx == 0)
1773 printf ("UND");
1774 else if ((symtab[si].st_shndx & 0xffff) == 0xfff1)
1775 printf ("ABS");
1776 else if ((symtab[si].st_shndx & 0xffff) == 0xfff2)
1777 printf ("COM");
1778 else
1779 printf ("%3d", symtab[si].st_shndx);
1780 printf (" %s\n", pnt);
1781 }
1782 }
1783 }
1784 else if (!do_using_dynamic)
1785 {
1786 int i;
1787 unsigned short * vers_addr;
1788
1789 spnt = elf_sections;
1790 vers_addr = (short *) (version_info [DT_VERNEEDNUM - DT_VERSYM]
1791 + header - loadaddr);
1792
1793 for (i = 0; i < epnt->e_shnum; i++, spnt++)
1794 {
1795 unsigned int si;
1796
1797 if (spnt->sh_type != SHT_SYMTAB && spnt->sh_type != SHT_DYNSYM)
1798 continue;
1799
1800 printf (_("\nSymbol data for: %s\n"), SECTION_NAME (spnt));
1801 printf (_(" Num: Value Size Type Bind Ot Ndx Name\n"));
1802
1803 symtab = (Elf_Sym *) (header + spnt->sh_offset);
1804 strtab = (char *) (header + elf_sections [spnt->sh_link].sh_offset);
1805
1806 for (si = 0; si < spnt->sh_size / spnt->sh_entsize; si++)
1807 {
1808 Elf_Sym ssym;
1809 Elf_Sym * psym;
1810 Elf_Sym * new_header;
1811
1812 psym = symtab + si;
1813
1814 if (must_swap)
1815 {
1816 ssym = * psym;
1817
1818 new_header = & ssym;
1819
1820 BYTE_SWAP (psym, st_name);
1821 BYTE_SWAP (psym, st_value);
1822 BYTE_SWAP (psym, st_size);
1823 BYTE_SWAP (psym, st_shndx);
1824
1825 psym = new_header;
1826 }
1827
1828 pnt = strtab + psym->st_name;
1829
c18f8aef 1830 printf (" %3d: %8lx %5ld %-7s %-6s %2d ", si,
76466873
NC
1831 psym->st_value,
1832 psym->st_size,
1833 sttinfo [ELF_ST_TYPE (psym->st_info)],
1834 stbinfo [ELF_ST_BIND (psym->st_info)],
1835 psym->st_other);
1836
1837 if (psym->st_shndx == 0)
1838 printf ("UND");
1839 else if ((psym->st_shndx & 0xffff) == 0xfff1)
1840 printf ("ABS");
1841 else if ((psym->st_shndx & 0xffff) == 0xfff2)
1842 printf ("COM");
1843 else
1844 printf ("%3d", psym->st_shndx);
1845 printf (" %s", pnt);
1846
1847 if (spnt->sh_type == SHT_DYNSYM &&
1848 version_info [DT_VERSIONTAGIDX (DT_VERSYM)] != 0 &&
1849 ((vers_addr[si] & 0x8000) || vers_addr[si] > 1))
1850 {
1851 Elf_Vernaux * a;
1852
1853 if (elf_sections [psym->st_shndx].sh_type == SHT_NOBITS
1854 || psym->st_shndx == SHN_UNDEF)
1855 {
1856 Elf_Verneed * v;
1857
1858 /* We must test both. */
1859 v = (Elf_Verneed *)
1860 (version_info [DT_VERSIONTAGIDX (DT_VERNEED)]
1861 + header - loadaddr);
1862
1863 for (;;)
1864 {
1865 a = (Elf_Vernaux *)((char *)v + v->vn_aux);
1866
1867 while (a->vna_other != vers_addr[si]
1868 && a->vna_next != 0)
1869 a = (Elf_Vernaux *)((char *)a + a->vna_next);
1870
1871 if (a->vna_other == vers_addr[si])
1872 break;
1873
1874 if (v->vn_next == 0)
1875 {
1876 if (elf_sections [psym->st_shndx].sh_type
1877 != SHT_NOBITS)
1878 error (_("bad dynamic symbol"));
1879
1880 a = NULL;
1881 break;
1882 }
1883
1884 v = (Elf_Verneed *)((char *)v + v->vn_next);
1885 }
1886
1887 if (a != NULL)
1888 printf ("@%s (%d)", strtab + a->vna_name, a->vna_other);
1889 }
1890 else if ((elf_sections [psym->st_shndx].sh_type
1891 == SHT_NOBITS && a == NULL)
1892 || psym->st_shndx != SHN_UNDEF)
1893 {
1894 Elf_Verdef * v;
1895 Elf_Verdaux * b;
1896
1897 v = (Elf_Verdef *)
1898 (version_info [DT_VERSIONTAGIDX (DT_VERDEF)]
1899 + header - loadaddr);
1900
1901 if (vers_addr[si] == 0x8001)
1902 pnt = "";
1903 else
1904 {
1905 while (v->vd_ndx != (vers_addr [si] & 0x7fff))
1906 v = (Elf_Verdef *)((char *)v + v->vd_next);
1907
1908 b = (Elf_Verdaux *) ((char *)v + v->vd_aux);
1909
1910 if (psym->st_name != b->vda_name)
1911 pnt = strtab + b->vda_name;
1912 else
1913 pnt = NULL;
1914 }
1915
1916 if (pnt)
1917 printf ((vers_addr [si] & 0x8000)
1918 ? "@%s" : "@@%s", pnt);
1919 }
1920 }
1921
1922 puts ("");
1923 }
1924 }
1925 }
1926
1927 if (! do_version)
1928 return;
1929
1930 spnt = elf_sections;
1931
1932 for (i = 0; i < epnt->e_shnum; i++, spnt++)
1933 {
1934 if (spnt->sh_type == SHT_GNU_verdef)
1935 {
1936 Elf_Shdr * dspnt = &elf_sections[spnt->sh_link];
1937 unsigned int idx;
1938 unsigned int cnt;
1939
1940 strtab = (char *) (header - loadaddr + dynamic_info[DT_STRTAB]);
1941
1942 printf (_("\n Version definitions:%s (%#0x entries)\n"),
1943 SECTION_NAME(spnt), spnt->sh_info);
1944 printf (_("Addr: %#08x Offset: %#08x Link: %x (%s)\n"),
1945 spnt->sh_addr, spnt->sh_offset, spnt->sh_link,
1946 SECTION_NAME(dspnt));
1947
1948 for (idx = cnt = 0; cnt < spnt->sh_info; ++cnt)
1949 {
1950 Elf_Verdef * ent = (Elf_Verdef *)
1951 ((char *) header + spnt->sh_offset + idx);
1952 Elf_Verdaux * aux = (Elf_Verdaux *)
1953 ((char *) ent + ent->vd_aux);
1954 int j, isum;
1955
1956 printf (_("%#06x: Rev: %d Flags: "), idx, ent->vd_version);
1957
1958 if (ent->vd_flags == 0)
1959 printf (_("none"));
1960 else
1961 {
1962 int f = 1;
1963 if (ent->vd_flags & 0x1)
1964 {
1965 printf (_("BASE"));
1966 f = 0;
1967 }
1968 if (ent->vd_flags & 0x2)
1969 {
1970 printf (_("%sWEAK"), f ? "" : "|");
1971 f = 0;
1972 }
1973 }
1974 printf (_(" Index: %d Cnt: %d Name: %s\n"),
1975 ent->vd_ndx, ent->vd_cnt, strtab + aux->vda_name);
1976 j = 1;
1977 isum = idx + ent->vd_aux;
1978 while (j < ent->vd_cnt)
1979 {
1980 isum += aux->vda_next;
1981 aux = (Elf_Verdaux *)((char *)aux + aux->vda_next);
1982 printf (_(" %#06x: Parent %d: %s\n"), isum, j,
1983 strtab + aux->vda_name);
1984 ++j;
1985 }
1986
1987 idx += ent->vd_next;
1988 }
1989 }
1990
1991 if (spnt->sh_type == SHT_GNU_verneed)
1992 {
1993 Elf_Shdr * dspnt = &elf_sections[spnt->sh_link];
1994 unsigned int idx;
1995 unsigned int cnt;
1996
1997 strtab = (char *) (header - loadaddr + dynamic_info[DT_STRTAB]);
1998 printf (_("\n Needed versions:%s (%#0x entries)\n"),
1999 SECTION_NAME (spnt), spnt->sh_info);
2000 printf (_("Addr: %#08x Offset: %#08x Link: %x (%s)\n"),
2001 spnt->sh_addr, spnt->sh_offset, spnt->sh_link,
2002 SECTION_NAME (dspnt));
2003
2004 for (idx = cnt = 0; cnt < spnt->sh_info; ++cnt)
2005 {
2006 Elf_Verneed * ent = (Elf_Verneed *)
2007 ((char *) header + spnt->sh_offset + idx);
2008 Elf_Vernaux * aux = (Elf_Vernaux *)
2009 ((char *) ent + ent->vn_aux);
2010 int j, isum;
2011
2012 printf (_("%#06x: Version: %d File: %s Cnt: %d\n"),
2013 idx, ent->vn_version, strtab + ent->vn_file,ent->vn_cnt);
2014
2015 for (j = 0, isum = idx + ent->vn_aux; j < ent->vn_cnt; ++j)
2016 {
2017 printf (_(" %#06x: Name: %s Flags: %s Version: %d\n"),
2018 isum, strtab+aux->vna_name,
2019 aux->vna_flags & 0x2 ? "WEAK" : "none",
2020 aux->vna_other);
2021 isum += aux->vna_next;
2022 aux = (Elf_Vernaux *)((char *) aux + aux->vna_next);
2023 }
2024
2025 idx += ent->vn_next;
2026 }
2027 }
2028
2029 if (spnt->sh_type == SHT_GNU_versym)
2030 {
2031 Elf_Shdr * dspnt = &elf_sections[spnt->sh_link];
2032 int total = spnt->sh_size / spnt->sh_entsize;
2033 int cnt;
2034 unsigned short * p = (short *)
2035 (version_info[DT_VERNEEDNUM - DT_VERSYM] + header - loadaddr);
2036
2037 symtab = (Elf_Sym *) (header + dspnt->sh_offset);
2038 strtab = (char *) (header + elf_sections[dspnt->sh_link].sh_offset);
2039
2040 printf (_("\n Version symbols:%s (%#0x entries)\n"),
2041 SECTION_NAME (spnt), total);
2042 printf (_("Addr: %#08x Offset: %#08x Link: %x (%s)\n"),
2043 spnt->sh_addr, spnt->sh_offset, spnt->sh_link,
2044 SECTION_NAME (dspnt));
2045
2046 for (cnt = 0; cnt < total; cnt += 4)
2047 {
2048 int j, nn;
2049
2050 printf ("%#08x:", cnt);
2051
2052 for (j = 0; (j < 4) && (cnt + j) < total; ++j)
2053 switch (p[cnt + j])
2054 {
2055 case 0:
2056 printf (" 0 (*local*) ");
2057 break;
2058 case 1:
2059 printf (" 1 (*global*) ");
2060 break;
2061 default:
2062 nn = printf ("%4x%c", p[cnt + j] & 0x7fff,
2063 p[cnt + j] & 0x8000 ? 'h' : ' ');
2064 if (elf_sections[symtab[cnt + j].st_shndx].sh_type
2065 == SHT_NOBITS)
2066 {
2067 /* We must test both. */
2068 Elf_Verneed * v = (Elf_Verneed *)
2069 (version_info [DT_VERNEEDNUM - DT_VERNEED]
2070 + header - loadaddr);
2071 Elf_Vernaux * a = NULL;
2072
2073 for (;;)
2074 {
2075 a = (Elf_Vernaux *)((char *) v + v->vn_aux);
2076
2077 while (a->vna_other != p[cnt + j]
2078 && a->vna_next != 0)
2079 a = (Elf_Vernaux *)((char *) a + a->vna_next);
2080
2081 if (a->vna_other == p[cnt + j])
2082 break;
2083
2084 if (v->vn_next == 0)
2085 {
2086 a = NULL;
2087 break;
2088 }
2089
2090 v = (Elf_Verneed *)((char *)v + v->vn_next);
2091 }
2092
2093 if (a != NULL)
2094 nn += printf ("(%s)", strtab + a->vna_name);
2095 else
2096 {
2097 Elf_Verdef * v = (Elf_Verdef *)
2098 (version_info [DT_VERNEEDNUM - DT_VERDEF]
2099 + header - loadaddr);
2100 Elf_Verdaux * a;
2101
2102 if (p[cnt + j] == 0x8001)
2103 pnt = "";
2104 else
2105 {
2106 while (v->vd_ndx != (p[cnt + j]&0x7fff))
2107 v = (Elf_Verdef *)((char *)v + v->vd_next);
2108
2109 a = (Elf_Verdaux *) ((char *) v + v->vd_aux);
2110 pnt = strtab + a->vda_name;
2111 }
2112
2113 if (pnt)
2114 nn += printf ("(%s)", pnt);
2115 }
2116
2117 if (nn <16)
2118 printf ("%*c", 16 - nn, ' ');
2119 }
2120 else if (symtab[cnt + j].st_shndx ==SHN_UNDEF)
2121 {
2122 Elf_Verneed * v = (Elf_Verneed *)
2123 (version_info [DT_VERNEEDNUM - DT_VERNEED]
2124 + header - loadaddr);
2125 Elf_Vernaux * a;
2126
2127 for (;;)
2128 {
2129 a = (Elf_Vernaux *)((char *) v + v->vn_aux);
2130
2131 while (a->vna_other != p[cnt + j]
2132 && a->vna_next != 0)
2133 a = (Elf_Vernaux *)((char *)a + a->vna_next);
2134
2135 if (a->vna_other == p[cnt + j])
2136 break;
2137
2138 v = (Elf_Verneed *)((char *) v + v->vn_next);
2139 }
2140
2141 nn += printf ("(%s)", strtab + a->vna_name);
2142
2143 if (nn <16)
2144 printf ("%*c", 16 - nn, ' ');
2145 }
2146 else
2147 {
2148 Elf_Verdef * v = (Elf_Verdef *)
2149 (version_info [DT_VERNEEDNUM - DT_VERDEF]
2150 + header - loadaddr);
2151 Elf_Verdaux * a;
2152
2153 if (p[cnt + j] == 0x8001)
2154 pnt = "";
2155 else
2156 {
2157 while (v->vd_ndx != (p[cnt + j] & 0x7fff))
2158 v = (Elf_Verdef *)((char *) v + v->vd_next);
2159
2160 a = (Elf_Verdaux *) ((char *) v + v->vd_aux);
2161 pnt = strtab + a->vda_name;
2162 }
2163
2164 if (pnt)
2165 nn += printf ("(%s)", pnt);
2166
2167 if (nn <16)
2168 printf ("%*c", 16 - nn, ' ');
2169 }
2170 }
2171
2172 printf ("\n");
2173 }
2174 }
2175 }
2176}
2177
2178static void
2179process_section_contents ()
2180{
2181 Elf_Shdr * spnt;
2182 int i;
2183
2184 if (! do_dump)
2185 return;
2186
2187 spnt = elf_sections;
2188
2189 for (i = 0; i < epnt->e_shnum; i++, spnt++)
2190 {
2191 int bytes;
2192 int addr;
2193 int lbytes;
2194 unsigned char * my_addr;
2195
2196#ifdef SUPPORT_DISASSEMBLY
2197 /* See if we need an assembly dump of this section */
2198
2199 if ((i < NUM_DUMP_SECTS) && (dump_sects[i] & DISASS_DUMP))
2200 {
2201 printf (_("\nAssembly dump of section %s\n"), SECTION_NAME (spnt));
2202
2203 bytes = spnt->sh_size;
2204 addr = spnt->sh_addr;
2205 my_addr = (unsigned char *) (header + spnt->sh_offset);
2206
2207 while (bytes > 0)
2208 {
2209 printf ("0x%8.8x ", addr);
2210
2211 switch (epnt->e_machine)
2212 {
2213 case EM_386:
2214 case EM_486:
2215 lbytes = db_disasm ((unsigned int) my_addr, 0, 0) -
2216 ((unsigned int) my_addr);
2217 break;
2218 case EM_68K:
2219 lbytes = (m68k_disass ((unsigned int) my_addr, addr)
2220 - (unsigned int) my_addr);
2221 break;
2222 default:
2223 warn (_("Unable to disassemble code for this platform\n"));
2224 return;
2225 }
2226
2227 addr += lbytes;
2228 my_addr += lbytes;
2229 bytes -= lbytes;
2230
2231 printf ("\n");
2232 }
2233 }
2234#endif
2235
2236 /* OK, see if we need a hex dump of this section. */
2237 if ((i < NUM_DUMP_SECTS) && (dump_sects[i] & HEX_DUMP))
2238 {
2239 int j;
2240 int k;
2241
2242 printf (_("\nHex dump of section %s\n"), SECTION_NAME (spnt));
2243
2244 bytes = spnt->sh_size;
2245 addr = spnt->sh_addr;
2246 my_addr = (unsigned char *) (header + spnt->sh_offset);
2247
2248 while (bytes)
2249 {
2250 lbytes = (bytes > 16 ? 16 : bytes);
2251
2252 printf ("0x%8.8x ",addr);
2253
2254 switch (epnt->e_ident [EI_DATA])
2255 {
2256 case ELFDATA2LSB:
2257 for (j = 15; j >= 0; j --)
2258 {
2259 if (j < lbytes)
2260 printf ("%2.2x", my_addr[j]);
2261 else
2262 printf (" ");
2263
2264 if (!(j & 0x3))
2265 printf (" ");
2266 }
2267 break;
2268
2269 case ELFDATA2MSB:
2270 for (j = 0; j < 16; j++)
2271 {
2272 if (j < lbytes)
2273 printf ("%2.2x", my_addr[j]);
2274 else
2275 printf (" ");
2276
2277 if ((j & 3) == 3)
2278 printf (" ");
2279 }
2280 break;
2281 }
2282
2283 for (j = 0; j < lbytes; j++)
2284 {
2285 k = my_addr [j];
2286 if (k >= ' ' && k < 0x80)
2287 printf ("%c", k);
2288 else
2289 printf (".");
2290 }
2291
2292 printf ("\n");
2293
2294 my_addr += lbytes;
2295 addr += lbytes;
2296 bytes -= lbytes;
2297 }
2298 }
2299 }
2300}
2301
2302static void
2303process_file (file_name)
2304 char * file_name;
2305{
2306 int fd;
2307 struct stat statbuf;
2308
2309 must_swap = 0;
2310
2311 fd = open (file_name, O_RDONLY);
2312 if (fd == -1)
2313 {
2314 error (_("Input file %s not found.\n"), file_name);
2315 return;
2316 }
2317
2318 if (fstat (fd, & statbuf) < 0)
2319 {
2320 error (_("Cannot stat input file %s.\n"), file_name);
2321 close (fd);
2322 return;
2323 }
2324
2325 header = mmap (0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
2326
2327 if ((header == (char *) -1) || (header == NULL))
2328 {
2329 error (_("Cannot mmap %s: %s\n"), file_name, strerror (errno));
2330 close (fd);
2331 return;
2332 }
2333
2334 close (fd);
2335
2336 epnt = (Elf_Ehdr *) header;
2337
2338 if (show_name)
2339 printf (_("\nFile: %s\n"), file_name);
2340
2341 if (! process_elf_header ())
2342 {
2343 munmap (header, statbuf.st_size);
2344 return;
2345 }
2346
2347 process_program_headers ();
2348
2349 if (loadaddr == -1)
2350 {
2351 /* Very strange. */
2352 loadaddr = 0;
2353 }
2354
2355 process_section_headers ();
2356
2357 process_dynamic_segment ();
2358
2359 process_symbol_table ();
2360
2361 process_section_contents ();
2362
2363 munmap (header, statbuf.st_size);
2364
2365 if (must_swap)
2366 {
2367 if (epnt)
2368 {
2369 free (epnt);
2370 epnt = NULL;
2371 }
2372
2373 if (elf_sections)
2374 {
2375 free (elf_sections);
2376 elf_sections = NULL;
2377 }
2378 }
2379}
2380
2381#ifdef SUPPORT_DISASSEMBLY
2382/* Needed by the i386 disassembler. For extra credit, someone could
2383fix this so that we insert symbolic addresses here, esp for GOT/PLT
2384symbols */
2385
2386void
2387print_address (unsigned int addr, FILE * outfile)
2388{
2389 fprintf (outfile,"0x%8.8x", addr);
2390}
2391
2392/* Needed by the i386 disassembler. */
2393void
2394db_task_printsym (unsigned int addr)
2395{
2396 print_address (addr, stderr);
2397}
2398#endif
2399
2400int
2401main (argc, argv)
2402 int argc;
2403 char ** argv;
2404{
2405 parse_args (argc, argv);
2406
2407 expected_endian = 0x12345678;
2408
2409 if (* ((char *) & expected_endian) == 0x12)
2410 expected_endian = ELFDATA2MSB;
2411 else
2412 expected_endian = ELFDATA2LSB;
2413
2414 if (optind < (argc - 1))
2415 show_name = 1;
2416
2417 while (optind < argc)
2418 process_file (argv [optind ++]);
2419
2420 return 0;
2421}
This page took 0.113136 seconds and 4 git commands to generate.