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