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