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