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