Add lots of DT_MIPS_* symbols.
[deliverable/binutils-gdb.git] / binutils / readelf.c
CommitLineData
76466873
NC
1/* readelf.c -- display contents of an ELF format file
2 Copyright (C) 1998 Free Software Foundation, Inc.
3
4 Originally developed by Eric Youngdale <eric@andante.jic.com>
5 Modifications by Nick Clifton <nickc@cygnus.com>
19808d3f 6
76466873
NC
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. */
ebb64169 23\f
76466873
NC
24
25#include <assert.h>
76466873 26#include <sys/stat.h>
ebb64169 27#include <stdio.h>
76466873 28
cb436f39
NC
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
ebb64169 37#include "bucomm.h"
c18f8aef 38#include "getopt.h"
76466873
NC
39
40#ifdef ANSI_PROTOTYPES
41#include <stdarg.h>
42#else
43#include <varargs.h>
44#endif
45
cb436f39
NC
46char * program_name = "readelf";
47unsigned int dynamic_addr;
48unsigned int dynamic_size;
49unsigned int rela_addr;
50unsigned int rela_size;
51char * dynamic_strings;
52char * string_table;
53Elf_Internal_Sym * dynamic_symbols;
54char program_interpreter [64];
55int dynamic_info [DT_JMPREL + 1];
56int version_info [16];
57int loadaddr = 0;
58Elf_Internal_Ehdr elf_header;
59Elf_Internal_Shdr * section_headers;
60int show_name;
61int do_dynamic;
62int do_syms;
63int do_reloc;
64int do_sections;
65int do_segments;
66int do_using_dynamic;
67int do_header;
68int do_dump;
69int do_version;
70
d76c93e6 71static unsigned long int (* byte_get) PARAMS ((unsigned char *, int));
76466873
NC
72
73#define NUM_DUMP_SECTS 100
cb436f39
NC
74char dump_sects [NUM_DUMP_SECTS];
75
76466873
NC
76#define HEX_DUMP 1
77#define DISASS_DUMP 2
78
79/* Forward declarations for dumb compilers. */
ebb64169 80static char * get_dynamic_type PARAMS ((unsigned long));
cb436f39
NC
81static char * get_i386_rel_type PARAMS ((unsigned long rtype));
82static char * get_m68k_rel_type PARAMS ((unsigned long rtype));
83static char * get_sparc_rel_type PARAMS ((unsigned long rtype));
84static char * get_m32r_rel_type PARAMS ((unsigned long rtype));
85static char * get_v850_rel_type PARAMS ((unsigned long rtype));
86static char * get_d10v_rel_type PARAMS ((unsigned long rtype));
2f300fe6 87/* start-sanitize-d30v */
cb436f39 88static char * get_d30v_rel_type PARAMS ((unsigned long rtype));
2f300fe6 89/* end-sanitize-d30v */
cb436f39
NC
90static char * get_sh_rel_type PARAMS ((unsigned long rtype));
91static char * get_mn10300_rel_type PARAMS ((unsigned long rtype));
92static char * get_mn10200_rel_type PARAMS ((unsigned long rtype));
93static char * get_ppc_rel_type PARAMS ((unsigned long rtype));
94static int dump_relocations
95 PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Sym *, char *));
ebb64169
NC
96static char * get_file_type PARAMS ((unsigned e_type));
97static char * get_machine_name PARAMS ((unsigned e_machine));
98static char * get_machine_data PARAMS ((unsigned e_data));
99static char * get_machine_flags PARAMS ((unsigned, unsigned e_machine));
100static char * get_segment_type PARAMS ((unsigned long p_type));
76466873 101static char * get_section_type_name PARAMS ((unsigned int sh_type));
ebb64169
NC
102static char * get_symbol_binding PARAMS ((unsigned int binding));
103static char * get_symbol_type PARAMS ((unsigned int type));
76466873
NC
104static void usage PARAMS ((void));
105static void parse_args PARAMS ((int argc, char ** argv));
ebb64169 106static int process_file_header PARAMS ((void));
cb436f39
NC
107static int process_program_headers PARAMS ((FILE *));
108static int process_section_headers PARAMS ((FILE *));
109static int process_dynamic_segment PARAMS ((FILE *));
110static int process_symbol_table PARAMS ((FILE *));
111static int process_section_contents PARAMS ((FILE *));
76466873 112static void process_file PARAMS ((char * file_name));
cb436f39
NC
113static int process_relocs PARAMS ((FILE *));
114static int process_version_sections PARAMS ((FILE *));
19808d3f
UD
115static char * get_ver_flags PARAMS ((unsigned int flags));
116static char * get_symbol_index_type PARAMS ((unsigned int type));
cb436f39
NC
117static int get_section_headers PARAMS ((FILE * file));
118static int get_file_header PARAMS ((FILE * file));
119static Elf_Internal_Sym * get_elf_symbols
120 PARAMS ((FILE * file, unsigned long offset, unsigned long number));
121static 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]))
76466873 130
ebb64169
NC
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); \
cb436f39 135 return 0; \
ebb64169
NC
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); \
cb436f39 143 return 0; \
ebb64169
NC
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; \
cb436f39 151 return 0; \
19808d3f
UD
152 }
153
ebb64169
NC
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); \
cb436f39 159 return 0; \
ebb64169
NC
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); \
cb436f39 164 return 0; \
ebb64169 165 }
76466873
NC
166
167#ifdef ANSI_PROTOTYPES
168static void
169error (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}
19808d3f 179
76466873
NC
180static void
181warn (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
192static void
193error (va_alist)
d76c93e6 194 va_dcl
76466873
NC
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
207static void
208warn (va_alist)
d76c93e6 209 va_dcl
76466873
NC
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
cb436f39
NC
223static unsigned long int
224byte_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
249static unsigned long int
250byte_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}
76466873
NC
273
274static char *
275get_i386_rel_type (rtype)
cb436f39 276 unsigned long rtype;
76466873
NC
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";
19808d3f 294 case 23: return "R_386_max";
76466873
NC
295 default: return _("*INVALID*");
296 }
297}
298
299static char *
300get_m68k_rel_type (rtype)
cb436f39 301 unsigned long rtype;
76466873
NC
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
333static char *
334get_sparc_rel_type (rtype)
cb436f39 335 unsigned long rtype;
76466873
NC
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
395static char *
396get_m32r_rel_type (rtype)
cb436f39 397 unsigned long rtype;
76466873
NC
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
417static char *
418get_v850_rel_type (rtype)
cb436f39 419 unsigned long rtype;
76466873
NC
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
453static char *
454get_d10v_rel_type (rtype)
cb436f39 455 unsigned long rtype;
76466873
NC
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
2f300fe6 470/* start-sanitize-d30v */
76466873
NC
471static char *
472get_d30v_rel_type (rtype)
cb436f39 473 unsigned long rtype;
76466873
NC
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
2f300fe6 494/* end-sanitize-d30v */
76466873
NC
495static char *
496get_sh_rel_type (rtype)
cb436f39 497 unsigned long rtype;
76466873
NC
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
524static char *
525get_mn10300_rel_type (rtype)
cb436f39 526 unsigned long rtype;
76466873
NC
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
542static char *
543get_mn10200_rel_type (rtype)
cb436f39 544 unsigned long rtype;
76466873
NC
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
a09db9ba
MM
561static char *
562get_ppc_rel_type (rtype)
cb436f39 563 unsigned long rtype;
a09db9ba
MM
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
ebb64169
NC
624/* Display the contents of the relocation data
625 found at the specified offset. */
cb436f39 626static int
ebb64169 627dump_relocations (file, rel_offset, rel_size, symtab, strtab)
cb436f39
NC
628 FILE * file;
629 unsigned long rel_offset;
630 unsigned long rel_size;
631 Elf_Internal_Sym * symtab;
632 char * strtab;
76466873 633{
cb436f39
NC
634 unsigned int i;
635 int is_rela;
636 Elf_Internal_Rel * rels;
637 Elf_Internal_Rela * relas;
76466873 638
19808d3f 639
ebb64169
NC
640 /* Compute number of relocations and read them in. */
641 switch (elf_header.e_machine)
76466873
NC
642 {
643 case EM_386:
644 case EM_486:
645 case EM_CYGNUS_M32R:
646 case EM_CYGNUS_D10V:
cb436f39
NC
647 {
648 Elf32_External_Rel * erels;
19808d3f 649
cb436f39
NC
650 GET_DATA_ALLOC (rel_offset, rel_size, erels,
651 Elf32_External_Rel *, "relocs");
19808d3f 652
cb436f39
NC
653 rel_size = rel_size / sizeof (Elf32_External_Rel);
654
655 rels = (Elf_Internal_Rel *) malloc (rel_size *
656 sizeof (Elf_Internal_Rel));
19808d3f 657
cb436f39
NC
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 }
76466873 663
cb436f39 664 free (erels);
19808d3f 665
cb436f39
NC
666 is_rela = 0;
667 relas = (Elf_Internal_Rela *) rels;
668 }
669 break;
19808d3f 670
76466873
NC
671 case EM_68K:
672 case EM_SPARC:
a09db9ba 673 case EM_PPC:
76466873 674 case EM_CYGNUS_V850:
2f300fe6 675 /* start-sanitize-d30v */
76466873 676 case EM_CYGNUS_D30V:
2f300fe6 677 /* end-sanitize-d30v */
76466873
NC
678 case EM_CYGNUS_MN10200:
679 case EM_CYGNUS_MN10300:
680 case EM_SH:
cb436f39
NC
681 {
682 Elf32_External_Rela * erelas;
19808d3f 683
cb436f39
NC
684 GET_DATA_ALLOC (rel_offset, rel_size, erelas,
685 Elf32_External_Rela *, "relocs");
19808d3f 686
cb436f39
NC
687 rel_size = rel_size / sizeof (Elf32_External_Rela);
688
689 relas = (Elf_Internal_Rela *) malloc (rel_size *
690 sizeof (Elf_Internal_Rela));
19808d3f 691
cb436f39
NC
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);
19808d3f 700
cb436f39
NC
701 is_rela = 1;
702 rels = (Elf_Internal_Rel *) relas;
703 }
704 break;
19808d3f 705
76466873
NC
706 default:
707 warn (_("Don't know about relocations on this machine architecture\n"));
cb436f39 708 return 0;
76466873
NC
709 }
710
711 if (is_rela)
ebb64169
NC
712 printf
713 (_(" Offset Value Type Symbol's Value Symbol's Name Addend\n"));
76466873 714 else
ebb64169
NC
715 printf
716 (_(" Offset Value Type Symbol's Value Symbol's Name\n"));
19808d3f 717
76466873
NC
718 for (i = 0; i < rel_size; i++)
719 {
cb436f39
NC
720 char * rtype;
721 unsigned long offset;
722 unsigned long info;
723 int symtab_index;
ebb64169 724
76466873 725 if (is_rela)
ebb64169
NC
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 }
19808d3f 735
ebb64169 736 printf (" %8.8lx %5.5lx ", offset, info);
19808d3f 737
ebb64169 738 switch (elf_header.e_machine)
76466873 739 {
c18f8aef 740 default:
ebb64169 741 rtype = "<unknown>";
c18f8aef 742 break;
19808d3f 743
76466873 744 case EM_CYGNUS_M32R:
ebb64169 745 rtype = get_m32r_rel_type (ELF32_R_TYPE (info));
76466873 746 break;
19808d3f 747
76466873
NC
748 case EM_386:
749 case EM_486:
ebb64169 750 rtype = get_i386_rel_type (ELF32_R_TYPE (info));
76466873 751 break;
19808d3f 752
76466873 753 case EM_68K:
ebb64169 754 rtype = get_m68k_rel_type (ELF32_R_TYPE (info));
76466873 755 break;
19808d3f 756
76466873 757 case EM_SPARC:
ebb64169 758 rtype = get_sparc_rel_type (ELF32_R_TYPE (info));
76466873 759 break;
19808d3f 760
76466873 761 case EM_CYGNUS_V850:
ebb64169 762 rtype = get_v850_rel_type (ELF32_R_TYPE (info));
76466873 763 break;
19808d3f 764
76466873 765 case EM_CYGNUS_D10V:
ebb64169 766 rtype = get_d10v_rel_type (ELF32_R_TYPE (info));
76466873 767 break;
19808d3f 768
2f300fe6 769 /* start-sanitize-d30v */
76466873 770 case EM_CYGNUS_D30V:
ebb64169 771 rtype = get_d30v_rel_type (ELF32_R_TYPE (info));
76466873 772 break;
19808d3f 773
2f300fe6 774 /* end-sanitize-d30v */
76466873 775 case EM_SH:
ebb64169 776 rtype = get_sh_rel_type (ELF32_R_TYPE (info));
76466873 777 break;
19808d3f 778
76466873 779 case EM_CYGNUS_MN10300:
ebb64169 780 rtype = get_mn10300_rel_type (ELF32_R_TYPE (info));
76466873 781 break;
19808d3f 782
76466873 783 case EM_CYGNUS_MN10200:
ebb64169 784 rtype = get_mn10200_rel_type (ELF32_R_TYPE (info));
76466873 785 break;
a09db9ba
MM
786
787 case EM_PPC:
ebb64169 788 rtype = get_ppc_rel_type (ELF32_R_TYPE (info));
a09db9ba 789 break;
76466873 790 }
19808d3f 791
ebb64169 792 printf ("%-21.21s", rtype);
19808d3f 793
ebb64169 794 symtab_index = ELF32_R_SYM (info);
19808d3f 795
ebb64169 796 if (symtab_index && symtab != NULL)
76466873 797 {
cb436f39 798 Elf_Internal_Sym * psym;
ebb64169 799
76466873 800 psym = symtab + symtab_index;
19808d3f 801
cb436f39 802 printf (" %08lx ", (unsigned long) psym->st_value);
19808d3f 803
76466873 804 if (psym->st_name == 0)
ebb64169
NC
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);
76466873 809 else
ebb64169 810 printf ("%-17.17s", strtab + psym->st_name);
19808d3f 811
76466873 812 if (is_rela)
cb436f39 813 printf (" + %lx", (unsigned long) relas [i].r_addend);
76466873 814 }
19808d3f 815
76466873 816 putchar ('\n');
76466873
NC
817 }
818
ebb64169 819 free (relas);
cb436f39
NC
820
821 return 1;
ebb64169
NC
822}
823
824static char *
825get_dynamic_type (type)
826 unsigned long type;
827{
828 static char buff [32];
19808d3f 829
ebb64169
NC
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");
19808d3f 863
ebb64169
NC
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 }
76466873
NC
871}
872
873static char *
874get_file_type (e_type)
a09db9ba 875 unsigned e_type;
76466873
NC
876{
877 static char buff [32];
19808d3f 878
76466873
NC
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");
19808d3f 886
76466873
NC
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
896static char *
897get_machine_name (e_machine)
a09db9ba 898 unsigned e_machine;
76466873
NC
899{
900 static char buff [32];
19808d3f 901
76466873
NC
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";
ebb64169 915 case EM_OLD_SPARCV9: return "Sparc v9 (old)";
76466873 916 case EM_PARISC: return "HPPA";
19808d3f 917 case EM_PPC_OLD: return "Power PC (old)";
76466873 918 case EM_SPARC32PLUS: return "Sparc v8+" ;
ebb64169 919 case EM_960: return "Intel 90860";
a09db9ba 920 case EM_PPC: return "PowerPC";
ebb64169
NC
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";
76466873 925 case EM_ARM: return "ARM";
ebb64169 926 case EM_OLD_ALPHA: return "Digital Alpha (old)";
76466873 927 case EM_SH: return "Hitachi SH";
ebb64169 928 case EM_SPARCV9: return "Sparc v9";
76466873
NC
929 case EM_ALPHA: return "Alpha";
930 case EM_CYGNUS_D10V: return "d10v";
2f300fe6 931 /* start-sanitize-d30v */
76466873 932 case EM_CYGNUS_D30V: return "d30v";
2f300fe6 933 /* end-sanitize-d30v */
76466873
NC
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";
19808d3f 938
76466873
NC
939 default:
940 sprintf (buff, _("<unknown>: %x"), e_machine);
941 return buff;
942 }
943}
944
a09db9ba
MM
945static char *
946get_machine_flags (e_flags, e_machine)
947 unsigned e_flags;
948 unsigned e_machine;
949{
950 static char buf [1024];
19808d3f 951
a09db9ba
MM
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
1015static char *
1016get_machine_data (e_data)
1017 unsigned e_data;
1018{
1019 static char buff [32];
19808d3f 1020
a09db9ba
MM
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
76466873
NC
1031static char *
1032get_segment_type (p_type)
1033 unsigned long p_type;
1034{
1035 static char buff [32];
19808d3f 1036
76466873
NC
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");
ebb64169 1045 case PT_PHDR: return _("Program Header");
76466873
NC
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
1058static char *
1059get_section_type_name (sh_type)
1060 unsigned int sh_type;
1061{
1062 static char buff [32];
19808d3f 1063
76466873
NC
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");
ebb64169
NC
1070 case SHT_RELA: return _("Relocations");
1071 case SHT_HASH: return _("Symbol hashes");
1072 case SHT_DYNAMIC: return _("Dynamic info");
76466873
NC
1073 case SHT_NOTE: return _("Notes");
1074 case SHT_NOBITS: return _("Space, no data");
ebb64169
NC
1075 case SHT_REL: return _("Relocations");
1076 case SHT_SHLIB: return _("Shared lib info");
1077 case SHT_DYNSYM: return _("Dynamic symbols");
76466873
NC
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))
ebb64169 1088 sprintf (buff, _("cpu defined (%d)"), sh_type - SHT_LOPROC);
76466873 1089 else if ((sh_type >= SHT_LOUSER) && (sh_type <= SHT_HIUSER))
ebb64169 1090 sprintf (buff, _("app defined (%d)"), sh_type - SHT_LOUSER);
76466873 1091 else
ebb64169
NC
1092 sprintf (buff, _("<unknown>: %x"), sh_type);
1093 return buff;
76466873
NC
1094 }
1095}
1096
1097struct option options [] =
1098{
1099 {"all", no_argument, 0, 'a'},
1100 {"file-header", no_argument, 0, 'h'},
1101 {"program-headers", no_argument, 0, 'l'},
ebb64169 1102 {"headers", no_argument, 0, 'e'},
76466873
NC
1103 {"segments", no_argument, 0, 'l'},
1104 {"sections", no_argument, 0, 'S'},
ebb64169 1105 {"section-headers", no_argument, 0, 'S'},
19808d3f 1106 {"symbols", no_argument, 0, 's'},
76466873
NC
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
19808d3f 1116
76466873
NC
1117 {"version", no_argument, 0, 'v'},
1118 {"help", no_argument, 0, 'H'},
1119
1120 {0, no_argument, 0, 0}
1121};
1122
1123static void
1124usage ()
1125{
59bbaa19
ILT
1126 fprintf (stdout, _("Usage: readelf {options} elf-file(s)\n"));
1127 fprintf (stdout, _(" Options are:\n"));
ebb64169 1128 fprintf (stdout, _(" -a or --all Equivalent to: -h -l -S -s -r -d -V\n"));
59bbaa19
ILT
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"));
ebb64169
NC
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"));
59bbaa19
ILT
1135 fprintf (stdout, _(" -s or --symbols Display the symbol table\n"));
1136 fprintf (stdout, _(" -r or --relocs Display the relocations (if present)\n"));
ebb64169 1137 fprintf (stdout, _(" -d or --dynamic Display the dynamic segment (if present)\n"));
59bbaa19
ILT
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"));
19808d3f 1142#ifdef SUPPORT_DISASSEMBLY
59bbaa19
ILT
1143 fprintf (stdout, _(" -i <number> or --instruction-dump=<number>\n"));
1144 fprintf (stdout, _(" Disassemble the contents of section <number>\n"));
19808d3f 1145#endif
59bbaa19
ILT
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"));
19808d3f 1149
76466873
NC
1150 exit (0);
1151}
1152
1153static void
1154parse_args (argc, argv)
1155 int argc;
1156 char ** argv;
1157{
59bbaa19 1158 int c;
19808d3f 1159
76466873
NC
1160 if (argc < 2)
1161 usage ();
1162
1163 while ((c = getopt_long
ebb64169 1164 (argc, argv, "ersahldSDx:i:vV", options, NULL)) != EOF)
76466873
NC
1165 {
1166 char * cp;
1167 int section;
19808d3f 1168
76466873
NC
1169 switch (c)
1170 {
1171 case 'H':
1172 usage ();
1173 break;
19808d3f 1174
76466873 1175 case 'a':
ebb64169
NC
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 ++;
76466873
NC
1188 break;
1189 case 'D':
ebb64169 1190 do_using_dynamic ++;
76466873
NC
1191 break;
1192 case 'r':
ebb64169 1193 do_reloc ++;
76466873
NC
1194 break;
1195 case 'h':
ebb64169 1196 do_header ++;
76466873
NC
1197 break;
1198 case 'l':
ebb64169 1199 do_segments ++;
76466873
NC
1200 break;
1201 case 's':
ebb64169 1202 do_syms ++;
76466873
NC
1203 break;
1204 case 'S':
ebb64169 1205 do_sections ++;
76466873
NC
1206 break;
1207 case 'd':
ebb64169 1208 do_dynamic ++;
76466873
NC
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;
19808d3f 1219#ifdef SUPPORT_DISASSEMBLY
76466873
NC
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
ebb64169
NC
1246 if (!do_dynamic && !do_syms && !do_reloc && !do_sections
1247 && !do_segments && !do_header && !do_dump && !do_version)
76466873
NC
1248 usage ();
1249 else if (argc < 3)
59bbaa19
ILT
1250 {
1251 warn (_("Nothing to do.\n"));
1252 usage();
1253 }
76466873
NC
1254}
1255
ebb64169 1256/* Decode the data held in 'elf_header'. */
76466873 1257static int
ebb64169 1258process_file_header ()
76466873 1259{
ebb64169
NC
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)
76466873 1264 {
ebb64169
NC
1265 error
1266 (_("Not an ELF file - it has the wrong magic bytes at the start\n"));
76466873
NC
1267 return 0;
1268 }
19808d3f 1269
ebb64169 1270 if (elf_header.e_ident [EI_CLASS] != ELFCLASS32)
76466873
NC
1271 {
1272 error (_("Not a 32 bit ELF file\n"));
1273 return 0;
1274 }
19808d3f 1275
76466873
NC
1276 if (do_header)
1277 {
1278 int i;
19808d3f 1279
ebb64169
NC
1280 printf (_("ELF Header:\n"));
1281 printf (_(" Magic: "));
76466873 1282 for (i = 0; i < EI_NIDENT; i ++)
ebb64169 1283 printf ("%2.2x ", elf_header.e_ident [i]);
19808d3f 1284 printf ("\n");
ebb64169
NC
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);
cb436f39 1291 printf (_(" Data: %s\n"),
ebb64169 1292 get_machine_data (elf_header.e_ident [EI_DATA]));
ebb64169
NC
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);
76466873 1314 }
19808d3f 1315
76466873
NC
1316 return 1;
1317}
1318
1319
cb436f39 1320static int
ebb64169
NC
1321process_program_headers (file)
1322 FILE * file;
76466873 1323{
cb436f39
NC
1324 Elf32_External_Phdr * phdrs;
1325 Elf32_Internal_Phdr * program_headers;
1326 Elf32_Internal_Phdr * segment;
1327 unsigned int i;
19808d3f 1328
ebb64169 1329 if (elf_header.e_phnum == 0)
76466873 1330 {
ebb64169
NC
1331 if (do_segments)
1332 printf (_("\nThere are no program headers in this file.\n"));
cb436f39 1333 return 1;
76466873 1334 }
19808d3f 1335
ebb64169 1336 if (do_segments && !do_header)
76466873 1337 {
ebb64169 1338 printf (_("\nElf file is %s\n"), get_file_type (elf_header.e_type));
cb436f39
NC
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);
76466873
NC
1342 }
1343
cb436f39
NC
1344 GET_DATA_ALLOC (elf_header.e_phoff,
1345 elf_header.e_phentsize * elf_header.e_phnum,
1346 phdrs, Elf32_External_Phdr *, "program headers");
19808d3f 1347
cb436f39
NC
1348 program_headers = (Elf32_Internal_Phdr *) malloc
1349 (elf_header.e_phnum * sizeof (Elf32_Internal_Phdr));
1350
1351 if (program_headers == NULL)
76466873 1352 {
cb436f39
NC
1353 error (_("Out of memory\n"));
1354 return 0;
76466873 1355 }
19808d3f 1356
cb436f39
NC
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);
19808d3f 1372
ebb64169 1373 if (do_segments)
76466873 1374 {
ebb64169
NC
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"));
76466873
NC
1379 }
1380
1381 loadaddr = -1;
1382 dynamic_addr = 0;
1383
cb436f39
NC
1384 for (i = 0, segment = program_headers;
1385 i < elf_header.e_phnum;
1386 i ++, segment ++)
76466873 1387 {
ebb64169 1388 if (do_segments)
76466873 1389 {
ebb64169 1390 printf (" %-16.16s ", get_segment_type (segment->p_type));
cb436f39
NC
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);
76466873 1396 printf ("%c%c%c ",
ebb64169
NC
1397 (segment->p_flags & PF_R ? 'R' : ' '),
1398 (segment->p_flags & PF_W ? 'W' : ' '),
1399 (segment->p_flags & PF_X ? 'E' : ' '));
cb436f39 1400 printf ("%#lx", (unsigned long) segment->p_align);
76466873 1401 }
ebb64169
NC
1402
1403 switch (segment->p_type)
76466873 1404 {
ebb64169
NC
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:
76466873 1412 if (dynamic_addr)
ebb64169 1413 error (_("more than one dynamic segment\n"));
19808d3f 1414
ebb64169
NC
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);
19808d3f 1426
ebb64169
NC
1427 if (do_segments)
1428 printf (_("\n [Requesting program interpreter: %s]"),
1429 program_interpreter);
1430 }
1431 break;
76466873 1432 }
19808d3f 1433
ebb64169 1434 if (do_segments)
76466873 1435 putc ('\n', stdout);
76466873
NC
1436 }
1437
ebb64169
NC
1438 if (loadaddr == -1)
1439 {
1440 /* Very strange. */
1441 loadaddr = 0;
1442 }
1443
1444 if (do_segments && section_headers != NULL)
76466873
NC
1445 {
1446 printf (_("\n Section to Segment mapping:\n"));
1447 printf (_(" Segment Sections...\n"));
1448
ebb64169 1449 assert (string_table != NULL);
19808d3f 1450
ebb64169 1451 for (i = 0; i < elf_header.e_phnum; i++)
76466873 1452 {
ebb64169 1453 int j;
cb436f39 1454 Elf32_Internal_Shdr * section;
19808d3f 1455
ebb64169
NC
1456 segment = program_headers + i;
1457 section = section_headers;
19808d3f 1458
76466873 1459 printf (" %2.2d ", i);
19808d3f 1460
ebb64169 1461 for (j = 0; j < elf_header.e_shnum; j++, section ++)
76466873 1462 {
ebb64169
NC
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));
76466873
NC
1474 }
1475
1476 putc ('\n',stdout);
1477 }
1478 }
19808d3f 1479
ebb64169 1480 free (program_headers);
cb436f39
NC
1481
1482 return 1;
76466873
NC
1483}
1484
1485
cb436f39
NC
1486static int
1487get_section_headers (file)
1488 FILE * file;
1489{
1490 Elf32_External_Shdr * shdrs;
1491 Elf32_Internal_Shdr * internal;
1492 unsigned int i;
19808d3f 1493
cb436f39
NC
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 }
19808d3f 1506
cb436f39
NC
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
1528static Elf_Internal_Sym *
1529get_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;
19808d3f 1538
cb436f39
NC
1539 GET_DATA_ALLOC (offset, number * sizeof (Elf32_External_Sym),
1540 esyms, Elf32_External_Sym *, "symbols");
19808d3f 1541
cb436f39 1542 isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym));
19808d3f 1543
cb436f39
NC
1544 if (isyms == NULL)
1545 {
1546 error (_("Out of memory\n"));
1547 free (esyms);
19808d3f 1548
cb436f39
NC
1549 return NULL;
1550 }
19808d3f 1551
cb436f39
NC
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
1569static int
ebb64169
NC
1570process_section_headers (file)
1571 FILE * file;
76466873 1572{
cb436f39 1573 Elf32_Internal_Shdr * section;
ebb64169 1574 int i;
76466873 1575
cb436f39 1576 section_headers = NULL;
19808d3f 1577
ebb64169
NC
1578 if (elf_header.e_shnum == 0)
1579 {
1580 if (do_sections)
1581 printf (_("\nThere are no sections in this file.\n"));
1582
cb436f39 1583 return 1;
ebb64169 1584 }
19808d3f 1585
ebb64169
NC
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
cb436f39
NC
1590 if (! get_section_headers (file))
1591 return 0;
ebb64169
NC
1592
1593 /* Read in the string table, so that we have names to display. */
1594 section = section_headers + elf_header.e_shstrndx;
19808d3f 1595
ebb64169
NC
1596 if (section->sh_size != 0)
1597 {
1598 unsigned long string_table_offset;
19808d3f 1599
ebb64169
NC
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
cb436f39
NC
1622 dynamic_symbols = get_elf_symbols
1623 (file, section->sh_offset, section->sh_size / section->sh_entsize);
ebb64169
NC
1624 }
1625 else if (section->sh_type == SHT_STRTAB
1626 && strcmp (SECTION_NAME (section), ".dynstr") == 0)
76466873 1627 {
ebb64169
NC
1628 if (dynamic_strings != NULL)
1629 {
1630 error (_("File contains multiple dynamic string tables\n"));
1631 continue;
1632 }
19808d3f 1633
ebb64169
NC
1634 GET_DATA_ALLOC (section->sh_offset, section->sh_size,
1635 dynamic_strings, char *, "dynamic strings");
76466873
NC
1636 }
1637 }
ebb64169
NC
1638
1639 if (! do_sections)
cb436f39 1640 return 1;
19808d3f 1641
ebb64169
NC
1642 printf (_("\nSection Header%s:\n"), elf_header.e_shnum > 1 ? "s" : "");
1643 printf
9eaac302 1644 (_(" [Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n"));
19808d3f 1645
ebb64169
NC
1646 for (i = 0, section = section_headers;
1647 i < elf_header.e_shnum;
1648 i ++, section ++)
76466873 1649 {
cb436f39
NC
1650 printf (" [%2d] %-17.17s %-15.15s ",
1651 i,
1652 SECTION_NAME (section),
1653 get_section_type_name (section->sh_type));
19808d3f 1654
c18f8aef 1655 printf ( "%8.8lx %6.6lx %6.6lx %2.2lx",
cb436f39
NC
1656 (unsigned long) section->sh_addr,
1657 (unsigned long) section->sh_offset,
1658 (unsigned long) section->sh_size,
1659 (unsigned long) section->sh_entsize);
19808d3f 1660
cb436f39 1661 printf (" %c%c%c %2ld %3lx %ld \n",
ebb64169
NC
1662 (section->sh_flags & SHF_WRITE ? 'W' : ' '),
1663 (section->sh_flags & SHF_ALLOC ? 'A' : ' '),
1664 (section->sh_flags & SHF_EXECINSTR ? 'X' : ' '),
cb436f39
NC
1665 (unsigned long) section->sh_link,
1666 (unsigned long) section->sh_info,
1667 (unsigned long) section->sh_addralign);
76466873 1668 }
cb436f39
NC
1669
1670 return 1;
76466873
NC
1671}
1672
ebb64169 1673/* Process the reloc section. */
cb436f39 1674static int
ebb64169
NC
1675process_relocs (file)
1676 FILE * file;
76466873 1677{
ebb64169
NC
1678 unsigned long rel_size;
1679 unsigned long rel_offset;
76466873 1680
19808d3f 1681
ebb64169 1682 if (!do_reloc)
cb436f39 1683 return 1;
19808d3f 1684
ebb64169 1685 if (do_using_dynamic)
76466873 1686 {
ebb64169
NC
1687 rel_size = 0;
1688 rel_offset = 0;
19808d3f 1689
ebb64169 1690 if (dynamic_info [DT_REL])
76466873 1691 {
ebb64169
NC
1692 rel_offset = dynamic_info [DT_REL];
1693 rel_size = dynamic_info [DT_RELSZ];
76466873 1694 }
ebb64169 1695 else if (dynamic_info [DT_RELA])
76466873 1696 {
ebb64169
NC
1697 rel_offset = dynamic_info [DT_RELA];
1698 rel_size = dynamic_info [DT_RELASZ];
19808d3f 1699 }
ebb64169
NC
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 {
cb436f39
NC
1708 printf
1709 (_("\nRelocation section at offset 0x%x contains %d bytes:\n"),
1710 rel_offset, rel_size);
19808d3f 1711
ebb64169
NC
1712 dump_relocations (file, rel_offset - loadaddr, rel_size,
1713 dynamic_symbols, dynamic_strings);
76466873 1714 }
ebb64169
NC
1715 else
1716 printf (_("\nThere are no dynamic relocations in this file.\n"));
76466873
NC
1717 }
1718 else
1719 {
cb436f39 1720 Elf32_Internal_Shdr * section;
ebb64169
NC
1721 unsigned long i;
1722 int found = 0;
19808d3f 1723
ebb64169 1724 assert (string_table != NULL);
19808d3f 1725
ebb64169
NC
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;
19808d3f 1733
ebb64169
NC
1734 rel_offset = section->sh_offset;
1735 rel_size = section->sh_size;
19808d3f 1736
ebb64169
NC
1737 if (rel_size)
1738 {
cb436f39
NC
1739 Elf32_Internal_Shdr * strsec;
1740 Elf32_Internal_Shdr * symsec;
1741 Elf_Internal_Sym * symtab;
1742 char * strtab;
19808d3f 1743
cb436f39
NC
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);
ebb64169
NC
1748
1749 symsec = section_headers + section->sh_link;
1750
cb436f39
NC
1751 symtab = get_elf_symbols (file, symsec->sh_offset,
1752 symsec->sh_size / symsec->sh_entsize);
19808d3f 1753
cb436f39
NC
1754 if (symtab == NULL)
1755 continue;
19808d3f 1756
ebb64169
NC
1757 strsec = section_headers + symsec->sh_link;
1758
1759 GET_DATA_ALLOC (strsec->sh_offset, strsec->sh_size, strtab,
1760 char *, "string table");
19808d3f 1761
ebb64169
NC
1762 dump_relocations (file, rel_offset, rel_size, symtab, strtab);
1763
1764 free (strtab);
1765 free (symtab);
1766
1767 found = 1;
1768 }
1769 }
19808d3f 1770
ebb64169
NC
1771 if (! found)
1772 printf (_("\nThere are no relocations in this file.\n"));
76466873 1773 }
cb436f39
NC
1774
1775 return 1;
ebb64169 1776}
76466873 1777
ebb64169
NC
1778
1779/* Parse the dynamic segment */
cb436f39 1780static int
ebb64169
NC
1781process_dynamic_segment (file)
1782 FILE * file;
1783{
cb436f39
NC
1784 Elf_Internal_Dyn * dynamic_segment;
1785 Elf_Internal_Dyn * entry;
1786 Elf32_External_Dyn * edyn;
ebb64169 1787 unsigned int i;
19808d3f 1788
ebb64169 1789 if (dynamic_size == 0)
76466873 1790 {
ebb64169
NC
1791 if (do_dynamic)
1792 printf (_("\nThere is no dynamic segment in this file.\n"));
1793
cb436f39 1794 return 1;
ebb64169
NC
1795 }
1796
1797 GET_DATA_ALLOC (dynamic_addr, dynamic_size,
cb436f39 1798 edyn, Elf32_External_Dyn *, "dynamic segment");
19808d3f 1799
cb436f39 1800 dynamic_size = dynamic_size / sizeof (Elf32_External_Dyn);
76466873 1801
cb436f39
NC
1802 dynamic_segment = (Elf_Internal_Dyn *)
1803 malloc (dynamic_size * sizeof (Elf_Internal_Dyn));
1804
1805 if (dynamic_segment == NULL)
76466873 1806 {
cb436f39
NC
1807 error (_("Out of memory\n"));
1808 free (edyn);
1809 return 0;
1810 }
19808d3f 1811
cb436f39
NC
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);
ebb64169 1818 }
76466873 1819
cb436f39 1820 free (edyn);
19808d3f 1821
ebb64169
NC
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 {
cb436f39
NC
1829 unsigned long offset;
1830 long num_syms;
19808d3f 1831
ebb64169
NC
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. */
19808d3f 1841
ebb64169 1842 offset = entry->d_un.d_val - loadaddr;
19808d3f 1843
ebb64169
NC
1844 if (fseek (file, 0, SEEK_END))
1845 error (_("Unable to seek to end of file!"));
19808d3f 1846
cb436f39 1847 num_syms = (ftell (file) - offset) / sizeof (Elf32_External_Sym);
ebb64169
NC
1848
1849 if (num_syms < 1)
1850 {
1851 error (_("Unable to determine the number of symbols to load\n"));
1852 continue;
1853 }
1854
cb436f39 1855 dynamic_symbols = get_elf_symbols (file, offset, num_syms);
ebb64169
NC
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;
19808d3f 1868
ebb64169
NC
1869 if (entry->d_tag != DT_STRTAB)
1870 continue;
1871
1872 dynamic_info [DT_STRTAB] = entry->d_un.d_val;
19808d3f 1873
ebb64169
NC
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. */
19808d3f 1878
ebb64169
NC
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 {
cb436f39
NC
1886 error
1887 (_("Unable to determine the length of the dynamic string table\n"));
ebb64169
NC
1888 continue;
1889 }
1890
1891 GET_DATA_ALLOC (offset, str_tab_len, dynamic_strings, char *,
1892 "dynamic string table");
1893
1894 break;
1895 }
1896 }
19808d3f 1897
ebb64169 1898 if (do_dynamic && dynamic_addr)
19808d3f 1899 printf (_("\nDynamic segment at offset 0x%x contains %d entries:\n"),
ebb64169
NC
1900 dynamic_addr, dynamic_size);
1901 if (do_dynamic)
19808d3f
UD
1902 printf (_(" Tag Type Name/Value\n"));
1903
ebb64169
NC
1904 for (i = 0, entry = dynamic_segment;
1905 i < dynamic_size;
1906 i++, entry ++)
1907 {
1908 if (do_dynamic)
19808d3f 1909 printf (_(" 0x%-8.8lx (%s)%*s"),
cb436f39 1910 (unsigned long) entry->d_tag,
19808d3f
UD
1911 get_dynamic_type (entry->d_tag),
1912 12 - strlen (get_dynamic_type (entry->d_tag)),
1913 " ");
1914
ebb64169
NC
1915 switch (entry->d_tag)
1916 {
1917 case DT_AUXILIARY:
1918 case DT_FILTER:
1919 if (do_dynamic)
1920 {
1921 if (entry->d_tag == DT_AUXILIARY)
1922 printf (_("Auxiliary library"));
1923 else
1924 printf (_("Filter library"));
1925
1926 if (dynamic_strings)
19808d3f 1927 printf (": [%s]\n", dynamic_strings + entry->d_un.d_val);
ebb64169 1928 else
cb436f39 1929 printf (": %#lx\n", (long) entry->d_un.d_val);
ebb64169
NC
1930 }
1931 break;
19808d3f 1932
76466873
NC
1933 case DT_NULL :
1934 case DT_NEEDED :
1935 case DT_PLTRELSZ:
1936 case DT_PLTGOT :
1937 case DT_HASH :
1938 case DT_STRTAB :
1939 case DT_SYMTAB :
1940 case DT_RELA :
1941 case DT_RELASZ :
1942 case DT_RELAENT :
1943 case DT_STRSZ :
1944 case DT_SYMENT :
1945 case DT_INIT :
1946 case DT_FINI :
1947 case DT_SONAME :
1948 case DT_RPATH :
1949 case DT_SYMBOLIC:
1950 case DT_REL :
1951 case DT_RELSZ :
1952 case DT_RELENT :
1953 case DT_PLTREL :
1954 case DT_DEBUG :
1955 case DT_TEXTREL :
1956 case DT_JMPREL :
ebb64169 1957 dynamic_info [entry->d_tag] = entry->d_un.d_val;
19808d3f 1958
76466873
NC
1959 if (do_dynamic)
1960 {
ebb64169
NC
1961 char * name;
1962
1963 if (dynamic_strings == NULL)
1964 name = NULL;
1965 else
1966 name = dynamic_strings + entry->d_un.d_val;
19808d3f 1967
ebb64169 1968 if (name)
76466873 1969 {
ebb64169 1970 switch (entry->d_tag)
76466873
NC
1971 {
1972 case DT_NEEDED:
ebb64169 1973 printf (_("Shared library: [%s]"), name);
19808d3f 1974
ebb64169 1975 if (strcmp (name, program_interpreter))
76466873
NC
1976 printf ("\n");
1977 else
1978 printf (_(" program interpreter\n"));
1979 break;
1980
1981 case DT_SONAME:
ebb64169 1982 printf (_("Library soname: [%s]\n"), name);
76466873
NC
1983 break;
1984
1985 case DT_RPATH:
ebb64169 1986 printf (_("Library rpath: [%s]\n"), name);
76466873
NC
1987 break;
1988
1989 default:
cb436f39 1990 printf ("%#lx\n", (long) entry->d_un.d_val);
76466873
NC
1991 }
1992 }
1993 else
cb436f39 1994 printf ("%#lx\n", (long) entry->d_un.d_val);
76466873
NC
1995 }
1996 break;
1997
1998 default:
ebb64169 1999 if ((entry->d_tag >= DT_VERSYM) && (entry->d_tag <= DT_VERNEEDNUM))
76466873 2000 {
ebb64169
NC
2001 version_info [DT_VERSIONTAGIDX (entry->d_tag)] =
2002 entry->d_un.d_val;
76466873
NC
2003
2004 if (do_dynamic)
cb436f39 2005 printf ("%#lx\n", (long) entry->d_un.d_ptr);
76466873 2006 }
76466873
NC
2007 break;
2008 }
ebb64169 2009 }
19808d3f 2010
ebb64169 2011 free (dynamic_segment);
cb436f39
NC
2012
2013 return 1;
ebb64169
NC
2014}
2015
2016static char *
d76c93e6 2017get_ver_flags (flags)
19808d3f 2018 unsigned int flags;
ebb64169
NC
2019{
2020 static char buff [32];
2021
2022 buff[0] = 0;
2023
2024 if (flags == 0)
2025 return _("none");
19808d3f 2026
ebb64169
NC
2027 if (flags & VER_FLG_BASE)
2028 strcat (buff, "BASE ");
2029
2030 if (flags & VER_FLG_WEAK)
2031 {
2032 if (flags & VER_FLG_BASE)
2033 strcat (buff, "| ");
19808d3f 2034
ebb64169 2035 strcat (buff, "WEAK ");
76466873
NC
2036 }
2037
ebb64169
NC
2038 if (flags & ~(VER_FLG_BASE | VER_FLG_WEAK))
2039 strcat (buff, "| <unknown>");
2040
2041 return buff;
2042}
2043
2044/* Display the contents of the version sections. */
cb436f39 2045static int
ebb64169
NC
2046process_version_sections (file)
2047 FILE * file;
2048{
cb436f39 2049 Elf32_Internal_Shdr * section;
ebb64169
NC
2050 unsigned i;
2051 int found = 0;
19808d3f 2052
ebb64169 2053 if (! do_version)
cb436f39 2054 return 1;
19808d3f 2055
ebb64169
NC
2056 for (i = 0, section = section_headers;
2057 i < elf_header.e_shnum;
2058 i++, section ++)
76466873 2059 {
ebb64169 2060 switch (section->sh_type)
76466873 2061 {
ebb64169
NC
2062 case SHT_GNU_verdef:
2063 {
cb436f39
NC
2064 Elf_External_Verdef * edefs;
2065 unsigned int idx;
2066 unsigned int cnt;
19808d3f 2067
cb436f39 2068 found = 1;
19808d3f 2069
cb436f39
NC
2070 printf
2071 (_("\nVersion definition section '%s' contains %d entries:\n"),
2072 SECTION_NAME (section), section->sh_info);
19808d3f 2073
ebb64169
NC
2074 printf (_(" Addr: %#08x Offset: %#08x Link: %x (%s)\n"),
2075 section->sh_addr, section->sh_offset, section->sh_link,
2076 SECTION_NAME (section_headers + section->sh_link));
76466873 2077
ebb64169 2078 GET_DATA_ALLOC (section->sh_offset, section->sh_size,
cb436f39 2079 edefs, Elf_External_Verdef *,
ebb64169 2080 "version definition section");
19808d3f 2081
ebb64169
NC
2082 for (idx = cnt = 0; cnt < section->sh_info; ++ cnt)
2083 {
cb436f39
NC
2084 char * vstart;
2085 Elf_External_Verdef * edef;
2086 Elf_Internal_Verdef ent;
2087 Elf_External_Verdaux * eaux;
2088 Elf_Internal_Verdaux aux;
2089 int j;
2090 int isum;
2091
2092 vstart = ((char *) edefs) + idx;
19808d3f 2093
cb436f39
NC
2094 edef = (Elf_External_Verdef *) vstart;
2095
2096 ent.vd_version = BYTE_GET (edef->vd_version);
2097 ent.vd_flags = BYTE_GET (edef->vd_flags);
2098 ent.vd_ndx = BYTE_GET (edef->vd_ndx);
2099 ent.vd_cnt = BYTE_GET (edef->vd_cnt);
2100 ent.vd_hash = BYTE_GET (edef->vd_hash);
2101 ent.vd_aux = BYTE_GET (edef->vd_aux);
2102 ent.vd_next = BYTE_GET (edef->vd_next);
19808d3f 2103
ebb64169 2104 printf (_(" %#06x: Rev: %d Flags: %s"),
cb436f39 2105 idx, ent.vd_version, get_ver_flags (ent.vd_flags));
19808d3f 2106
cb436f39 2107 printf (_(" Index: %ld Cnt: %ld "), ent.vd_ndx, ent.vd_cnt);
ebb64169 2108
cb436f39 2109 vstart += ent.vd_aux;
19808d3f 2110
cb436f39 2111 eaux = (Elf_External_Verdaux *) vstart;
19808d3f 2112
cb436f39
NC
2113 aux.vda_name = BYTE_GET (eaux->vda_name);
2114 aux.vda_next = BYTE_GET (eaux->vda_next);
19808d3f 2115
ebb64169 2116 if (dynamic_strings)
cb436f39 2117 printf (_("Name: %s\n"), dynamic_strings + aux.vda_name);
ebb64169 2118 else
cb436f39 2119 printf (_("Name index: %ld\n"), aux.vda_name);
19808d3f 2120
cb436f39 2121 isum = idx + ent.vd_aux;
19808d3f 2122
cb436f39 2123 for (j = 1; j < ent.vd_cnt; j ++)
ebb64169 2124 {
cb436f39
NC
2125 isum += aux.vda_next;
2126 vstart += aux.vda_next;
19808d3f 2127
cb436f39 2128 eaux = (Elf_External_Verdaux *) vstart;
19808d3f 2129
cb436f39
NC
2130 aux.vda_name = BYTE_GET (eaux->vda_name);
2131 aux.vda_next = BYTE_GET (eaux->vda_next);
19808d3f 2132
ebb64169
NC
2133 if (dynamic_strings)
2134 printf (_(" %#06x: Parent %d: %s\n"),
cb436f39 2135 isum, j, dynamic_strings + aux.vda_name);
ebb64169 2136 else
cb436f39
NC
2137 printf (_(" %#06x: Parent %d, name index: %ld\n"),
2138 isum, j, aux.vda_name);
ebb64169
NC
2139 }
2140
cb436f39 2141 idx += ent.vd_next;
ebb64169 2142 }
19808d3f 2143
cb436f39 2144 free (edefs);
ebb64169
NC
2145 }
2146 break;
19808d3f 2147
ebb64169
NC
2148 case SHT_GNU_verneed:
2149 {
cb436f39
NC
2150 Elf_External_Verneed * eneed;
2151 unsigned int idx;
2152 unsigned int cnt;
19808d3f 2153
ebb64169 2154 found = 1;
19808d3f 2155
ebb64169
NC
2156 printf (_("\nVersion needs section '%s' contains %d entries:\n"),
2157 SECTION_NAME (section), section->sh_info);
19808d3f 2158
cb436f39
NC
2159 printf
2160 (_(" Addr: %#08x Offset: %#08x Link to section: %d (%s)\n"),
2161 section->sh_addr, section->sh_offset, section->sh_link,
2162 SECTION_NAME (section_headers + section->sh_link));
ebb64169
NC
2163
2164 GET_DATA_ALLOC (section->sh_offset, section->sh_size,
cb436f39 2165 eneed, Elf_External_Verneed *,
ebb64169 2166 "version need section");
19808d3f 2167
ebb64169
NC
2168 for (idx = cnt = 0; cnt < section->sh_info; ++cnt)
2169 {
cb436f39
NC
2170 Elf_External_Verneed * entry;
2171 Elf_Internal_Verneed ent;
2172 int j;
2173 int isum;
2174 char * vstart;
19808d3f 2175
cb436f39 2176 vstart = ((char *) eneed) + idx;
19808d3f 2177
cb436f39 2178 entry = (Elf_External_Verneed *) vstart;
19808d3f 2179
cb436f39
NC
2180 ent.vn_version = BYTE_GET (entry->vn_version);
2181 ent.vn_cnt = BYTE_GET (entry->vn_cnt);
2182 ent.vn_file = BYTE_GET (entry->vn_file);
2183 ent.vn_aux = BYTE_GET (entry->vn_aux);
2184 ent.vn_next = BYTE_GET (entry->vn_next);
19808d3f 2185
cb436f39 2186 printf (_(" %#06x: Version: %d"), idx, ent.vn_version);
ebb64169
NC
2187
2188 if (dynamic_strings)
cb436f39 2189 printf (_(" File: %s"), dynamic_strings + ent.vn_file);
ebb64169 2190 else
cb436f39 2191 printf (_(" File: %lx"), ent.vn_file);
19808d3f 2192
cb436f39
NC
2193 printf (_(" Cnt: %d\n"), ent.vn_cnt);
2194
2195 vstart += ent.vn_aux;
19808d3f 2196
cb436f39 2197 for (j = 0, isum = idx + ent.vn_aux; j < ent.vn_cnt; ++j)
ebb64169 2198 {
cb436f39
NC
2199 Elf_External_Vernaux * eaux;
2200 Elf_Internal_Vernaux aux;
19808d3f 2201
cb436f39 2202 eaux = (Elf_External_Vernaux *) vstart;
19808d3f 2203
cb436f39
NC
2204 aux.vna_hash = BYTE_GET (eaux->vna_hash);
2205 aux.vna_flags = BYTE_GET (eaux->vna_flags);
2206 aux.vna_other = BYTE_GET (eaux->vna_other);
2207 aux.vna_name = BYTE_GET (eaux->vna_name);
2208 aux.vna_next = BYTE_GET (eaux->vna_next);
ebb64169
NC
2209
2210 if (dynamic_strings)
2211 printf (_(" %#06x: Name: %s"),
cb436f39 2212 isum, dynamic_strings + aux.vna_name);
ebb64169 2213 else
cb436f39
NC
2214 printf (_(" %#06x: Name index: %lx"),
2215 isum, aux.vna_name);
19808d3f 2216
ebb64169 2217 printf (_(" Flags: %s Version: %d\n"),
cb436f39 2218 get_ver_flags (aux.vna_flags), aux.vna_other);
19808d3f 2219
cb436f39
NC
2220 isum += aux.vna_next;
2221 vstart += aux.vna_next;
ebb64169 2222 }
19808d3f 2223
cb436f39 2224 idx += ent.vn_next;
ebb64169 2225 }
cb436f39
NC
2226
2227 free (eneed);
ebb64169
NC
2228 }
2229 break;
19808d3f 2230
ebb64169
NC
2231 case SHT_GNU_versym:
2232 {
cb436f39
NC
2233 Elf32_Internal_Shdr * link_section;
2234 int total;
2235 int cnt;
2236 unsigned char * edata;
2237 unsigned short * data;
2238 char * strtab;
2239 Elf_Internal_Sym * symbols;
2240 Elf32_Internal_Shdr * string_sec;
2241
2242 link_section = section_headers + section->sh_link;
2243 total = section->sh_size / section->sh_entsize;
19808d3f 2244
ebb64169
NC
2245 found = 1;
2246
cb436f39
NC
2247 symbols = get_elf_symbols
2248 (file, link_section->sh_offset,
2249 link_section->sh_size / link_section->sh_entsize);
19808d3f 2250
ebb64169
NC
2251 string_sec = section_headers + link_section->sh_link;
2252
2253 GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size,
2254 strtab, char *, "version string table");
19808d3f 2255
ebb64169
NC
2256 printf (_("\nVersion symbols section '%s' contains %d entries:\n"),
2257 SECTION_NAME (section), total);
19808d3f 2258
ebb64169
NC
2259 printf (_(" Addr: %#08x Offset: %#08x Link: %x (%s)\n"),
2260 section->sh_addr, section->sh_offset, section->sh_link,
2261 SECTION_NAME (link_section));
2262
cb436f39
NC
2263 GET_DATA_ALLOC (version_info [DT_VERSIONTAGIDX (DT_VERSYM)]
2264 - loadaddr,
2265 total * sizeof (short), edata,
2266 char *, "version symbol data");
ebb64169 2267
cb436f39 2268 data = (unsigned short *) malloc (total * sizeof (short));
19808d3f 2269
cb436f39
NC
2270 for (cnt = total; cnt --;)
2271 data [cnt] = byte_get (edata + cnt * sizeof (short), sizeof (short));
2272
2273 free (edata);
19808d3f 2274
ebb64169
NC
2275 for (cnt = 0; cnt < total; cnt += 4)
2276 {
2277 int j, nn;
19808d3f 2278
ebb64169 2279 printf (" %03x:", cnt);
19808d3f 2280
ebb64169 2281 for (j = 0; (j < 4) && (cnt + j) < total; ++j)
cb436f39 2282 switch (data [cnt + j])
ebb64169
NC
2283 {
2284 case 0:
19808d3f 2285 fputs (_(" 0 (*local*) "), stdout);
ebb64169 2286 break;
19808d3f 2287
ebb64169 2288 case 1:
19808d3f 2289 fputs (_(" 1 (*global*) "), stdout);
ebb64169 2290 break;
19808d3f 2291
ebb64169 2292 default:
cb436f39
NC
2293 nn = printf ("%4x%c", data [cnt + j] & 0x7fff,
2294 data [cnt + j] & 0x8000 ? 'h' : ' ');
ebb64169
NC
2295
2296 if (symbols [cnt + j].st_shndx < SHN_LORESERVE
2297 && section_headers[symbols [cnt + j].st_shndx].sh_type
2298 == SHT_NOBITS)
2299 {
2300 /* We must test both. */
cb436f39
NC
2301 Elf_Internal_Verneed ivn;
2302 unsigned long offset;
ebb64169
NC
2303
2304 offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)]
2305 - loadaddr;
19808d3f 2306
ebb64169
NC
2307 do
2308 {
cb436f39
NC
2309 Elf_External_Verneed evn;
2310 Elf_External_Vernaux evna;
2311 Elf_Internal_Vernaux ivna;
2312 unsigned long vna_off;
ebb64169 2313
cb436f39 2314 GET_DATA (offset, evn, "version need");
ebb64169 2315
cb436f39
NC
2316 ivn.vn_aux = BYTE_GET (evn.vn_aux);
2317 ivn.vn_next = BYTE_GET (evn.vn_next);
19808d3f 2318
cb436f39 2319 vna_off = offset + ivn.vn_aux;
ebb64169
NC
2320
2321 do
2322 {
cb436f39 2323 GET_DATA (vna_off, evna,
ebb64169
NC
2324 "version need aux (1)");
2325
cb436f39
NC
2326 ivna.vna_next = BYTE_GET (evna.vna_next);
2327 ivna.vna_other = BYTE_GET (evna.vna_other);
19808d3f 2328
cb436f39 2329 vna_off += ivna.vna_next;
ebb64169 2330 }
cb436f39
NC
2331 while (ivna.vna_other != data [cnt + j]
2332 && ivna.vna_next != 0);
19808d3f 2333
cb436f39 2334 if (ivna.vna_other == data [cnt + j])
ebb64169 2335 {
cb436f39 2336 ivna.vna_name = BYTE_GET (evna.vna_name);
19808d3f
UD
2337
2338 nn += printf ("(%s%-*s",
2339 strtab + ivna.vna_name,
2340 12 - strlen (strtab
2341 + ivna.vna_name),
2342 ")");
ebb64169
NC
2343 break;
2344 }
cb436f39 2345 else if (ivn.vn_next == 0)
ebb64169 2346 {
cb436f39 2347 if (data [cnt + j] != 0x8001)
ebb64169 2348 {
cb436f39
NC
2349 Elf_Internal_Verdef ivd;
2350 Elf_External_Verdef evd;
ebb64169
NC
2351
2352 offset = version_info
2353 [DT_VERSIONTAGIDX (DT_VERDEF)]
2354 - loadaddr;
19808d3f 2355
ebb64169
NC
2356 do
2357 {
cb436f39 2358 GET_DATA (offset, evd,
ebb64169
NC
2359 "version definition");
2360
cb436f39
NC
2361 ivd.vd_next = BYTE_GET (evd.vd_next);
2362 ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
19808d3f 2363
cb436f39 2364 offset += ivd.vd_next;
ebb64169 2365 }
cb436f39
NC
2366 while (ivd.vd_ndx
2367 != (data [cnt + j] & 0x7fff)
2368 && ivd.vd_next != 0);
ebb64169 2369
cb436f39
NC
2370 if (ivd.vd_ndx
2371 == (data [cnt + j] & 0x7fff))
ebb64169 2372 {
cb436f39
NC
2373 Elf_External_Verdaux evda;
2374 Elf_Internal_Verdaux ivda;
19808d3f 2375
cb436f39 2376 ivd.vd_aux = BYTE_GET (evd.vd_aux);
ebb64169 2377
cb436f39 2378 GET_DATA (offset + ivd.vd_aux, evda,
ebb64169 2379 "version definition aux");
19808d3f 2380
cb436f39
NC
2381 ivda.vda_name =
2382 BYTE_GET (evda.vda_name);
19808d3f 2383
cb436f39 2384 nn +=
19808d3f
UD
2385 printf ("(%s%-*s",
2386 strtab + ivda.vda_name,
2387 12
2388 - strlen (strtab
2389 + ivda.vda_name),
2390 ")");
ebb64169
NC
2391 }
2392 }
19808d3f 2393
ebb64169
NC
2394 break;
2395 }
2396 else
cb436f39 2397 offset += ivn.vn_next;
ebb64169 2398 }
cb436f39 2399 while (ivn.vn_next);
ebb64169
NC
2400 }
2401 else if (symbols [cnt + j].st_shndx == SHN_UNDEF)
2402 {
cb436f39
NC
2403 Elf_Internal_Verneed ivn;
2404 unsigned long offset;
19808d3f 2405
ebb64169
NC
2406 offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)]
2407 - loadaddr;
2408
2409 do
2410 {
cb436f39
NC
2411 Elf_Internal_Vernaux ivna;
2412 Elf_External_Verneed evn;
2413 Elf_External_Vernaux evna;
2414 unsigned long a_off;
ebb64169 2415
cb436f39 2416 GET_DATA (offset, evn, "version need");
ebb64169 2417
cb436f39
NC
2418 ivn.vn_aux = BYTE_GET (evn.vn_aux);
2419 ivn.vn_next = BYTE_GET (evn.vn_next);
19808d3f 2420
cb436f39 2421 a_off = offset + ivn.vn_aux;
19808d3f 2422
ebb64169
NC
2423 do
2424 {
cb436f39
NC
2425 GET_DATA (a_off, evna,
2426 "version need aux (2)");
2427
2428 ivna.vna_next = BYTE_GET (evna.vna_next);
2429 ivna.vna_other = BYTE_GET (evna.vna_other);
19808d3f 2430
cb436f39 2431 a_off += ivna.vna_next;
ebb64169 2432 }
cb436f39
NC
2433 while (ivna.vna_other != data [cnt + j]
2434 && ivna.vna_next != 0);
19808d3f 2435
cb436f39 2436 if (ivna.vna_other == data [cnt + j])
ebb64169 2437 {
cb436f39 2438 ivna.vna_name = BYTE_GET (evna.vna_name);
19808d3f
UD
2439
2440 nn += printf ("(%s%-*s",
2441 strtab + ivna.vna_name,
2442 12 - strlen (strtab
2443 + ivna.vna_name),
2444 ")");
ebb64169
NC
2445 break;
2446 }
2447
cb436f39 2448 offset += ivn.vn_next;
ebb64169 2449 }
cb436f39 2450 while (ivn.vn_next);
ebb64169 2451 }
cb436f39 2452 else if (data [cnt + j] != 0x8001)
ebb64169 2453 {
cb436f39
NC
2454 Elf_Internal_Verdef ivd;
2455 Elf_External_Verdef evd;
2456 unsigned long offset;
19808d3f 2457
cb436f39
NC
2458 offset = version_info
2459 [DT_VERSIONTAGIDX (DT_VERDEF)] - loadaddr;
19808d3f 2460
cb436f39 2461 do
ebb64169 2462 {
cb436f39 2463 GET_DATA (offset, evd, "version def");
ebb64169 2464
cb436f39
NC
2465 ivd.vd_next = BYTE_GET (evd.vd_next);
2466 ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
19808d3f 2467
cb436f39
NC
2468 offset += ivd.vd_next;
2469 }
2470 while (ivd.vd_ndx != (data [cnt + j] & 0x7fff)
2471 && ivd.vd_next != 0);
19808d3f 2472
cb436f39
NC
2473 if (ivd.vd_ndx == (data [cnt + j] & 0x7fff))
2474 {
2475 Elf_External_Verdaux evda;
2476 Elf_Internal_Verdaux ivda;
19808d3f 2477
cb436f39 2478 ivd.vd_aux = BYTE_GET (evd.vd_aux);
19808d3f 2479
cb436f39
NC
2480 GET_DATA (offset - ivd.vd_next + ivd.vd_aux,
2481 evda, "version def aux");
19808d3f 2482
cb436f39 2483 ivda.vda_name = BYTE_GET (evda.vda_name);
19808d3f
UD
2484
2485 nn += printf ("(%s%-*s",
2486 strtab + ivda.vda_name,
2487 12 - strlen (strtab
2488 + ivda.vda_name),
2489 ")");
ebb64169
NC
2490 }
2491 }
19808d3f 2492
ebb64169
NC
2493 if (nn < 18)
2494 printf ("%*c", 18 - nn, ' ');
2495 }
19808d3f 2496
ebb64169
NC
2497 putchar ('\n');
2498 }
2499
cb436f39 2500 free (data);
ebb64169
NC
2501 free (strtab);
2502 free (symbols);
2503 }
2504 break;
19808d3f 2505
ebb64169 2506 default:
4775a8a5 2507 break;
76466873
NC
2508 }
2509 }
19808d3f 2510
ebb64169
NC
2511 if (! found)
2512 printf (_("\nNo version information found in this file.\n"));
cb436f39
NC
2513
2514 return 1;
ebb64169
NC
2515}
2516
2517static char *
2518get_symbol_binding (binding)
2519 unsigned int binding;
2520{
2521 static char buff [32];
19808d3f 2522
ebb64169
NC
2523 switch (binding)
2524 {
2525 case STB_LOCAL: return _("LOCAL");
2526 case STB_GLOBAL: return _("GLOBAL");
2527 case STB_WEAK: return _("WEAK");
2528 default:
2529 if (binding >= STB_LOPROC && binding <= STB_HIPROC)
2530 sprintf (buff, _("<processor specific>: %d"), binding);
2531 else
2532 sprintf (buff, _("<unknown>: %d"), binding);
2533 return buff;
2534 }
2535}
2536
2537static char *
2538get_symbol_type (type)
2539 unsigned int type;
2540{
2541 static char buff [32];
19808d3f 2542
ebb64169
NC
2543 switch (type)
2544 {
2545 case STT_NOTYPE: return _("NOTYPE");
2546 case STT_OBJECT: return _("OBJECT");
2547 case STT_FUNC: return _("FUNC");
2548 case STT_SECTION: return _("SECTION");
2549 case STT_FILE: return _("FILE");
2550 default:
2551 if (type >= STT_LOPROC && type <= STT_HIPROC)
2552 sprintf (buff, _("<processor specific>: %d"), type);
2553 else
2554 sprintf (buff, _("<unknown>: %d"), type);
2555 return buff;
2556 }
2557}
2558
2559static char *
2560get_symbol_index_type (type)
19808d3f 2561 unsigned int type;
ebb64169
NC
2562{
2563 switch (type)
2564 {
2565 case SHN_UNDEF: return "UND";
2566 case SHN_ABS: return "ABS";
2567 case SHN_COMMON: return "COM";
2568 default:
2569 if (type >= SHN_LOPROC && type <= SHN_HIPROC)
2570 return "PRC";
2571 else if (type >= SHN_LORESERVE && type <= SHN_HIRESERVE)
2572 return "RSV";
2573 else
2574 {
2575 static char buff [32];
19808d3f 2576
ebb64169
NC
2577 sprintf (buff, "%3d", type);
2578 return buff;
2579 }
2580 }
76466873
NC
2581}
2582
ebb64169 2583
cb436f39
NC
2584static int *
2585get_dynamic_data (file, number)
2586 FILE * file;
2587 unsigned int number;
2588{
2589 char * e_data;
2590 int * i_data;
19808d3f 2591
cb436f39 2592 e_data = (char *) malloc (number * 4);
19808d3f 2593
cb436f39
NC
2594 if (e_data == NULL)
2595 {
2596 error (_("Out of memory\n"));
2597 return NULL;
2598 }
19808d3f 2599
cb436f39
NC
2600 if (fread (e_data, 4, number, file) != number)
2601 {
2602 error (_("Unable to read in dynamic data\n"));
2603 return NULL;
2604 }
19808d3f 2605
cb436f39
NC
2606 i_data = (int *) malloc (number * sizeof (* i_data));
2607
2608 if (i_data == NULL)
2609 {
2610 error (_("Out of memory\n"));
2611 free (e_data);
2612 return NULL;
2613 }
19808d3f 2614
cb436f39
NC
2615 while (number--)
2616 i_data [number] = byte_get (e_data + number * 4, 4);
19808d3f 2617
cb436f39
NC
2618 free (e_data);
2619
2620 return i_data;
2621}
2622
76466873 2623/* Dump the symbol table */
cb436f39 2624static int
ebb64169
NC
2625process_symbol_table (file)
2626 FILE * file;
76466873 2627{
cb436f39 2628 Elf32_Internal_Shdr * section;
19808d3f 2629
76466873 2630 if (! do_syms)
cb436f39 2631 return 1;
19808d3f 2632
ebb64169 2633 if (dynamic_info [DT_HASH] && do_using_dynamic && dynamic_strings != NULL)
76466873 2634 {
cb436f39
NC
2635 char nb [4];
2636 char nc [4];
2637 int nbuckets;
2638 int nchains;
2639 int * buckets;
2640 int * chains;
2641 int hn;
2642 int si;
76466873 2643
ebb64169
NC
2644 if (fseek (file, dynamic_info [DT_HASH] - loadaddr, SEEK_SET))
2645 {
2646 error (_("Unable to seek to start of dynamic information"));
cb436f39 2647 return 0;
ebb64169
NC
2648 }
2649
cb436f39 2650 if (fread (& nb, sizeof (nb), 1, file) != 1)
ebb64169
NC
2651 {
2652 error (_("Failed to read in number of buckets\n"));
cb436f39 2653 return 0;
ebb64169 2654 }
19808d3f 2655
cb436f39 2656 if (fread (& nc, sizeof (nc), 1, file) != 1)
ebb64169
NC
2657 {
2658 error (_("Failed to read in number of chains\n"));
cb436f39 2659 return 0;
ebb64169
NC
2660 }
2661
cb436f39
NC
2662 nbuckets = byte_get (nb, 4);
2663 nchains = byte_get (nc, 4);
19808d3f 2664
cb436f39
NC
2665 buckets = get_dynamic_data (file, nbuckets);
2666 chains = get_dynamic_data (file, nchains);
ebb64169 2667
cb436f39
NC
2668 if (buckets == NULL || chains == NULL)
2669 return 0;
19808d3f 2670
ebb64169 2671 printf (_("\nSymbol table for image:\n"));
76466873 2672 printf (_(" Num Buc: Value Size Type Bind Ot Ndx Name\n"));
19808d3f 2673
ebb64169 2674 for (hn = 0; hn < nbuckets; hn++)
76466873 2675 {
ebb64169 2676 if (! buckets [hn])
76466873 2677 continue;
19808d3f 2678
ebb64169 2679 for (si = buckets [hn]; si; si = chains [si])
76466873 2680 {
cb436f39 2681 Elf_Internal_Sym * psym;
ebb64169
NC
2682
2683 psym = dynamic_symbols + si;
19808d3f 2684
cb436f39
NC
2685 printf (" %3d %3d: %8lx %5ld %6s %6s %2d ",
2686 si, hn,
2687 (unsigned long) psym->st_value,
2688 (unsigned long) psym->st_size,
ebb64169
NC
2689 get_symbol_type (ELF_ST_TYPE (psym->st_info)),
2690 get_symbol_binding (ELF_ST_BIND (psym->st_info)),
2691 psym->st_other);
2692
2693 printf ("%3.3s", get_symbol_index_type (psym->st_shndx));
19808d3f 2694
ebb64169 2695 printf (" %s\n", dynamic_strings + psym->st_name);
76466873
NC
2696 }
2697 }
ebb64169
NC
2698
2699 free (buckets);
2700 free (chains);
76466873
NC
2701 }
2702 else if (!do_using_dynamic)
2703 {
ebb64169 2704 unsigned int i;
19808d3f 2705
ebb64169
NC
2706 for (i = 0, section = section_headers;
2707 i < elf_header.e_shnum;
2708 i++, section++)
76466873 2709 {
cb436f39
NC
2710 unsigned int si;
2711 char * strtab;
2712 Elf_Internal_Sym * symtab;
2713 Elf_Internal_Sym * psym;
ebb64169 2714
19808d3f 2715
ebb64169
NC
2716 if ( section->sh_type != SHT_SYMTAB
2717 && section->sh_type != SHT_DYNSYM)
76466873 2718 continue;
19808d3f 2719
ebb64169
NC
2720 printf (_("\nSymbol table '%s' contains %d entries:\n"),
2721 SECTION_NAME (section),
2722 section->sh_size / section->sh_entsize);
19808d3f
UD
2723 fputs (_(" Num: Value Size Type Bind Ot Ndx Name\n"),
2724 stdout);
76466873 2725
cb436f39
NC
2726 symtab = get_elf_symbols (file, section->sh_offset,
2727 section->sh_size / section->sh_entsize);
2728 if (symtab == NULL)
2729 continue;
19808d3f 2730
ebb64169
NC
2731 if (section->sh_link == elf_header.e_shstrndx)
2732 strtab = string_table;
2733 else
2734 {
cb436f39 2735 Elf32_Internal_Shdr * string_sec;
19808d3f 2736
cb436f39 2737 string_sec = section_headers + section->sh_link;
19808d3f 2738
ebb64169
NC
2739 GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size,
2740 strtab, char *, "string table");
2741 }
19808d3f 2742
ebb64169
NC
2743 for (si = 0, psym = symtab;
2744 si < section->sh_size / section->sh_entsize;
2745 si ++, psym ++)
2746 {
cb436f39
NC
2747 printf (" %3d: %8lx %5ld %-7s %-6s %2d ",
2748 si,
2749 (unsigned long) psym->st_value,
2750 (unsigned long) psym->st_size,
ebb64169
NC
2751 get_symbol_type (ELF_ST_TYPE (psym->st_info)),
2752 get_symbol_binding (ELF_ST_BIND (psym->st_info)),
76466873 2753 psym->st_other);
19808d3f 2754
76466873 2755 if (psym->st_shndx == 0)
19808d3f 2756 fputs ("UND", stdout);
76466873 2757 else if ((psym->st_shndx & 0xffff) == 0xfff1)
19808d3f 2758 fputs ("ABS", stdout);
76466873 2759 else if ((psym->st_shndx & 0xffff) == 0xfff2)
19808d3f 2760 fputs ("COM", stdout);
76466873
NC
2761 else
2762 printf ("%3d", psym->st_shndx);
19808d3f 2763
ebb64169 2764 printf (" %s", strtab + psym->st_name);
19808d3f 2765
ebb64169
NC
2766 if (section->sh_type == SHT_DYNSYM &&
2767 version_info [DT_VERSIONTAGIDX (DT_VERSYM)] != 0)
76466873 2768 {
cb436f39 2769 unsigned char data[2];
ebb64169
NC
2770 unsigned short vers_data;
2771 unsigned long offset;
2772 int is_nobits;
2773 int check_def;
19808d3f 2774
ebb64169
NC
2775 offset = version_info [DT_VERSIONTAGIDX (DT_VERSYM)]
2776 - loadaddr;
2777
cb436f39 2778 GET_DATA (offset + si * sizeof (vers_data), data,
ebb64169
NC
2779 "version data");
2780
cb436f39 2781 vers_data = byte_get (data, 2);
ebb64169
NC
2782
2783 is_nobits = psym->st_shndx < SHN_LORESERVE ?
2784 (section_headers [psym->st_shndx].sh_type == SHT_NOBITS)
2785 : 0;
19808d3f 2786
ebb64169 2787 check_def = (psym->st_shndx != SHN_UNDEF);
19808d3f 2788
ebb64169 2789 if ((vers_data & 0x8000) || vers_data > 1)
76466873 2790 {
ebb64169 2791 if (is_nobits || ! check_def)
76466873 2792 {
cb436f39
NC
2793 Elf_External_Verneed evn;
2794 Elf_Internal_Verneed ivn;
2795 Elf_Internal_Vernaux ivna;
19808d3f 2796
ebb64169
NC
2797 /* We must test both. */
2798 offset = version_info
2799 [DT_VERSIONTAGIDX (DT_VERNEED)] - loadaddr;
2800
cb436f39 2801 GET_DATA (offset, evn, "version need");
76466873 2802
cb436f39
NC
2803 ivn.vn_aux = BYTE_GET (evn.vn_aux);
2804 ivn.vn_next = BYTE_GET (evn.vn_next);
19808d3f 2805
ebb64169
NC
2806 do
2807 {
2808 unsigned long vna_off;
19808d3f 2809
cb436f39 2810 vna_off = offset + ivn.vn_aux;
ebb64169
NC
2811
2812 do
2813 {
cb436f39 2814 Elf_External_Vernaux evna;
19808d3f 2815
cb436f39 2816 GET_DATA (vna_off, evna,
ebb64169
NC
2817 "version need aux (3)");
2818
cb436f39
NC
2819 ivna.vna_other = BYTE_GET (evna.vna_other);
2820 ivna.vna_next = BYTE_GET (evna.vna_next);
19808d3f 2821 ivna.vna_name = BYTE_GET (evna.vna_name);
ebb64169 2822
cb436f39 2823 vna_off += ivna.vna_next;
ebb64169 2824 }
cb436f39
NC
2825 while (ivna.vna_other != vers_data
2826 && ivna.vna_next != 0);
19808d3f 2827
cb436f39 2828 if (ivna.vna_other == vers_data)
ebb64169 2829 break;
19808d3f 2830
cb436f39 2831 offset += ivn.vn_next;
76466873 2832 }
cb436f39 2833 while (ivn.vn_next != 0);
19808d3f 2834
cb436f39 2835 if (ivna.vna_other == vers_data)
19808d3f
UD
2836 {
2837 printf ("@%s (%d)",
2838 strtab + ivna.vna_name, ivna.vna_other);
2839 check_def = 0;
2840 }
ebb64169
NC
2841 else if (! is_nobits)
2842 error (_("bad dynamic symbol"));
2843 else
2844 check_def = 1;
76466873 2845 }
19808d3f 2846
ebb64169 2847 if (check_def)
76466873 2848 {
ebb64169
NC
2849 if (vers_data != 0x8001)
2850 {
cb436f39
NC
2851 Elf_Internal_Verdef ivd;
2852 Elf_Internal_Verdaux ivda;
2853 Elf_External_Verdaux evda;
2854 unsigned long offset;
ebb64169
NC
2855
2856 offset =
2857 version_info [DT_VERSIONTAGIDX (DT_VERDEF)]
2858 - loadaddr;
2859
2860 do
2861 {
cb436f39 2862 Elf_External_Verdef evd;
19808d3f 2863
cb436f39 2864 GET_DATA (offset, evd, "version def");
ebb64169 2865
cb436f39
NC
2866 ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
2867 ivd.vd_aux = BYTE_GET (evd.vd_aux);
2868 ivd.vd_next = BYTE_GET (evd.vd_next);
19808d3f 2869
cb436f39 2870 offset += ivd.vd_next;
ebb64169 2871 }
cb436f39
NC
2872 while (ivd.vd_ndx != (vers_data & 0x7fff)
2873 && ivd.vd_next != 0);
ebb64169 2874
cb436f39
NC
2875 offset -= ivd.vd_next;
2876 offset += ivd.vd_aux;
ebb64169 2877
cb436f39 2878 GET_DATA (offset, evda, "version def aux");
19808d3f 2879
cb436f39 2880 ivda.vda_name = BYTE_GET (evda.vda_name);
19808d3f 2881
cb436f39 2882 if (psym->st_name != ivda.vda_name)
ebb64169
NC
2883 printf ((vers_data & 0x8000)
2884 ? "@%s" : "@@%s",
cb436f39 2885 strtab + ivda.vda_name);
ebb64169 2886 }
76466873 2887 }
76466873
NC
2888 }
2889 }
19808d3f 2890
ebb64169 2891 putchar ('\n');
76466873 2892 }
76466873 2893
ebb64169
NC
2894 free (symtab);
2895 if (strtab != string_table)
2896 free (strtab);
76466873
NC
2897 }
2898 }
ebb64169
NC
2899 else
2900 printf
2901 (_("\nDynamic symbol information is not available for displaying symbols.\n"));
cb436f39
NC
2902
2903 return 1;
76466873
NC
2904}
2905
cb436f39 2906static int
ebb64169
NC
2907process_section_contents (file)
2908 FILE * file;
76466873 2909{
cb436f39 2910 Elf32_Internal_Shdr * section;
ebb64169 2911 unsigned int i;
76466873
NC
2912
2913 if (! do_dump)
cb436f39 2914 return 1;
76466873 2915
ebb64169
NC
2916 for (i = 0, section = section_headers;
2917 i < elf_header.e_shnum;
2918 i ++, section ++)
76466873 2919 {
76466873
NC
2920#ifdef SUPPORT_DISASSEMBLY
2921 /* See if we need an assembly dump of this section */
19808d3f 2922
76466873
NC
2923 if ((i < NUM_DUMP_SECTS) && (dump_sects[i] & DISASS_DUMP))
2924 {
ebb64169
NC
2925 printf (_("\nAssembly dump of section %s\n"),
2926 SECTION_NAME (section));
19808d3f 2927
ebb64169
NC
2928 /* XXX -- to be done --- XXX */
2929 }
2930#endif
2931 /* See if we need a hex dump of this section. */
2932 if ((i < NUM_DUMP_SECTS) && (dump_sects[i] & HEX_DUMP))
2933 {
cb436f39
NC
2934 int bytes;
2935 int addr;
ebb64169 2936 unsigned char * data;
cb436f39 2937 char * start;
19808d3f 2938
ebb64169 2939 printf (_("\nHex dump of section '%s':\n"), SECTION_NAME (section));
19808d3f 2940
ebb64169
NC
2941 bytes = section->sh_size;
2942 addr = section->sh_addr;
2943
2944 GET_DATA_ALLOC (section->sh_offset, bytes, start, char *,
2945 "section data");
2946
2947 data = start;
19808d3f 2948
ebb64169 2949 while (bytes)
76466873 2950 {
ebb64169
NC
2951 int j;
2952 int k;
2953 int lbytes;
19808d3f 2954
ebb64169 2955 lbytes = (bytes > 16 ? 16 : bytes);
19808d3f 2956
ebb64169 2957 printf (" 0x%8.8x ", addr);
19808d3f 2958
ebb64169 2959 switch (elf_header.e_ident [EI_DATA])
76466873 2960 {
ebb64169
NC
2961 case ELFDATA2LSB:
2962 for (j = 15; j >= 0; j --)
2963 {
2964 if (j < lbytes)
2965 printf ("%2.2x", data [j]);
2966 else
2967 printf (" ");
19808d3f 2968
ebb64169
NC
2969 if (!(j & 0x3))
2970 printf (" ");
2971 }
2972 break;
19808d3f 2973
ebb64169
NC
2974 case ELFDATA2MSB:
2975 for (j = 0; j < 16; j++)
2976 {
2977 if (j < lbytes)
2978 printf ("%2.2x", data [j]);
2979 else
2980 printf (" ");
19808d3f 2981
ebb64169
NC
2982 if ((j & 3) == 3)
2983 printf (" ");
2984 }
2985 break;
2986 }
19808d3f 2987
ebb64169
NC
2988 for (j = 0; j < lbytes; j++)
2989 {
2990 k = data [j];
2991 if (k >= ' ' && k < 0x80)
2992 printf ("%c", k);
2993 else
2994 printf (".");
2995 }
19808d3f 2996
ebb64169 2997 putchar ('\n');
19808d3f 2998
ebb64169
NC
2999 data += lbytes;
3000 addr += lbytes;
3001 bytes -= lbytes;
3002 }
3003
3004 free (start);
3005 }
76466873 3006 }
cb436f39
NC
3007
3008 return 1;
3009}
3010
3011static int
3012get_file_header (file)
3013 FILE * file;
3014{
3015 Elf32_External_Ehdr ehdr;
3016
3017 if (fread (& ehdr, sizeof (ehdr), 1, file) != 1)
3018 return 0;
3019
3020 memcpy (elf_header.e_ident, ehdr.e_ident, EI_NIDENT);
3021
3022 if (elf_header.e_ident [EI_DATA] == ELFDATA2LSB)
3023 byte_get = byte_get_little_endian;
3024 else
3025 byte_get = byte_get_big_endian;
3026
3027 elf_header.e_entry = BYTE_GET (ehdr.e_entry);
3028 elf_header.e_phoff = BYTE_GET (ehdr.e_phoff);
3029 elf_header.e_shoff = BYTE_GET (ehdr.e_shoff);
3030 elf_header.e_version = BYTE_GET (ehdr.e_version);
3031 elf_header.e_flags = BYTE_GET (ehdr.e_flags);
3032 elf_header.e_type = BYTE_GET (ehdr.e_type);
3033 elf_header.e_machine = BYTE_GET (ehdr.e_machine);
3034 elf_header.e_ehsize = BYTE_GET (ehdr.e_ehsize);
3035 elf_header.e_phentsize = BYTE_GET (ehdr.e_phentsize);
3036 elf_header.e_phnum = BYTE_GET (ehdr.e_phnum);
3037 elf_header.e_shentsize = BYTE_GET (ehdr.e_shentsize);
3038 elf_header.e_shnum = BYTE_GET (ehdr.e_shnum);
3039 elf_header.e_shstrndx = BYTE_GET (ehdr.e_shstrndx);
3040
3041 return 1;
76466873
NC
3042}
3043
3044static void
3045process_file (file_name)
3046 char * file_name;
3047{
ebb64169 3048 FILE * file;
76466873 3049 struct stat statbuf;
ebb64169 3050 unsigned int i;
19808d3f 3051
ebb64169
NC
3052 if (stat (file_name, & statbuf) < 0)
3053 {
3054 error (_("Cannot stat input file %s.\n"), file_name);
3055 return;
3056 }
3057
3058 file = fopen (file_name, "rb");
3059 if (file == NULL)
76466873
NC
3060 {
3061 error (_("Input file %s not found.\n"), file_name);
3062 return;
3063 }
cb436f39
NC
3064
3065 if (! get_file_header (file))
76466873 3066 {
ebb64169
NC
3067 error (_("%s: Failed to read file header\n"), file_name);
3068 fclose (file);
76466873
NC
3069 return;
3070 }
19808d3f 3071
ebb64169 3072 /* Initialise per file variables. */
ebb64169
NC
3073 for (i = NUM_ELEM (version_info); i--;)
3074 version_info [i] = 0;
19808d3f 3075
ebb64169
NC
3076 for (i = NUM_ELEM (dynamic_info); i--;)
3077 dynamic_info [i] = 0;
76466873 3078
19808d3f 3079
ebb64169 3080 /* Process the file. */
76466873
NC
3081 if (show_name)
3082 printf (_("\nFile: %s\n"), file_name);
19808d3f 3083
ebb64169 3084 if (! process_file_header ())
76466873 3085 {
ebb64169 3086 fclose (file);
76466873
NC
3087 return;
3088 }
76466873 3089
ebb64169 3090 process_section_headers (file);
76466873 3091
ebb64169 3092 process_program_headers (file);
19808d3f 3093
ebb64169
NC
3094 process_dynamic_segment (file);
3095
3096 process_relocs (file);
19808d3f 3097
ebb64169 3098 process_symbol_table (file);
76466873 3099
ebb64169 3100 process_version_sections (file);
76466873 3101
ebb64169 3102 process_section_contents (file);
19808d3f 3103
ebb64169 3104 fclose (file);
19808d3f 3105
ebb64169
NC
3106 if (section_headers)
3107 {
3108 free (section_headers);
3109 section_headers = NULL;
3110 }
76466873 3111
ebb64169 3112 if (string_table)
76466873 3113 {
ebb64169
NC
3114 free (string_table);
3115 string_table = NULL;
3116 }
76466873 3117
ebb64169
NC
3118 if (dynamic_strings)
3119 {
3120 free (dynamic_strings);
3121 dynamic_strings = NULL;
3122 }
3123
3124 if (dynamic_symbols)
3125 {
3126 free (dynamic_symbols);
3127 dynamic_symbols = NULL;
76466873
NC
3128 }
3129}
3130
3131#ifdef SUPPORT_DISASSEMBLY
3132/* Needed by the i386 disassembler. For extra credit, someone could
3133fix this so that we insert symbolic addresses here, esp for GOT/PLT
3134symbols */
3135
3136void
3137print_address (unsigned int addr, FILE * outfile)
3138{
3139 fprintf (outfile,"0x%8.8x", addr);
3140}
3141
3142/* Needed by the i386 disassembler. */
3143void
3144db_task_printsym (unsigned int addr)
3145{
3146 print_address (addr, stderr);
3147}
3148#endif
3149
3150int
3151main (argc, argv)
3152 int argc;
3153 char ** argv;
3154{
3155 parse_args (argc, argv);
3156
76466873
NC
3157 if (optind < (argc - 1))
3158 show_name = 1;
19808d3f 3159
76466873
NC
3160 while (optind < argc)
3161 process_file (argv [optind ++]);
3162
3163 return 0;
3164}
This page took 0.174918 seconds and 4 git commands to generate.