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