]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/elftoolchain/elfdump/elfdump.c
Upgrade to OpenSSH 7.2p2.
[FreeBSD/FreeBSD.git] / contrib / elftoolchain / elfdump / elfdump.c
1 /*-
2  * Copyright (c) 2007-2012 Kai Wang
3  * Copyright (c) 2003 David O'Brien.  All rights reserved.
4  * Copyright (c) 2001 Jake Burkholder
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 #include <sys/param.h>
30 #include <sys/queue.h>
31 #include <sys/stat.h>
32
33 #include <ar.h>
34 #include <assert.h>
35 #include <err.h>
36 #include <fcntl.h>
37 #include <gelf.h>
38 #include <getopt.h>
39 #include <libelftc.h>
40 #include <inttypes.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45
46 #ifdef USE_LIBARCHIVE_AR
47 #include <archive.h>
48 #include <archive_entry.h>
49 #endif
50
51 #include "_elftc.h"
52
53 ELFTC_VCSID("$Id: elfdump.c 3391 2016-02-05 19:43:01Z emaste $");
54
55 #if defined(ELFTC_NEED_ELF_NOTE_DEFINITION)
56 #include "native-elf-format.h"
57 #if ELFTC_CLASS == ELFCLASS32
58 typedef Elf32_Nhdr      Elf_Note;
59 #else
60 typedef Elf64_Nhdr      Elf_Note;
61 #endif
62 #endif
63
64 /* elfdump(1) options. */
65 #define ED_DYN          (1<<0)
66 #define ED_EHDR         (1<<1)
67 #define ED_GOT          (1<<2)
68 #define ED_HASH         (1<<3)
69 #define ED_INTERP       (1<<4)
70 #define ED_NOTE         (1<<5)
71 #define ED_PHDR         (1<<6)
72 #define ED_REL          (1<<7)
73 #define ED_SHDR         (1<<8)
74 #define ED_SYMTAB       (1<<9)
75 #define ED_SYMVER       (1<<10)
76 #define ED_CHECKSUM     (1<<11)
77 #define ED_ALL          ((1<<12)-1)
78
79 /* elfdump(1) run control flags. */
80 #define SOLARIS_FMT             (1<<0)
81 #define PRINT_FILENAME          (1<<1)
82 #define PRINT_ARSYM             (1<<2)
83 #define ONLY_ARSYM              (1<<3)
84
85 /* Convenient print macro. */
86 #define PRT(...)        fprintf(ed->out, __VA_ARGS__)
87
88 /* Internal data structure for sections. */
89 struct section {
90         const char      *name;          /* section name */
91         Elf_Scn         *scn;           /* section scn */
92         uint64_t         off;           /* section offset */
93         uint64_t         sz;            /* section size */
94         uint64_t         entsize;       /* section entsize */
95         uint64_t         align;         /* section alignment */
96         uint64_t         type;          /* section type */
97         uint64_t         flags;         /* section flags */
98         uint64_t         addr;          /* section virtual addr */
99         uint32_t         link;          /* section link ndx */
100         uint32_t         info;          /* section info ndx */
101 };
102
103 struct spec_name {
104         const char      *name;
105         STAILQ_ENTRY(spec_name) sn_list;
106 };
107
108 /* Structure encapsulates the global data for readelf(1). */
109 struct elfdump {
110         FILE            *out;           /* output redirection. */
111         const char      *filename;      /* current processing file. */
112         const char      *archive;       /* archive name */
113         int              options;       /* command line options. */
114         int              flags;         /* run control flags. */
115         Elf             *elf;           /* underlying ELF descriptor. */
116 #ifndef USE_LIBARCHIVE_AR
117         Elf             *ar;            /* ar(1) archive descriptor. */
118 #endif
119         GElf_Ehdr        ehdr;          /* ELF header. */
120         int              ec;            /* ELF class. */
121         size_t           shnum;         /* #sections. */
122         struct section  *sl;            /* list of sections. */
123         STAILQ_HEAD(, spec_name) snl;   /* list of names specified by -N. */
124 };
125
126 /* Relocation entry. */
127 struct rel_entry {
128         union {
129                 GElf_Rel rel;
130                 GElf_Rela rela;
131         } u_r;
132         const char *symn;
133         uint32_t type;
134 };
135
136 #if defined(ELFTC_NEED_BYTEORDER_EXTENSIONS)
137 static __inline uint32_t
138 be32dec(const void *pp)
139 {
140         unsigned char const *p = (unsigned char const *)pp;
141
142         return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
143 }
144
145 static __inline uint32_t
146 le32dec(const void *pp)
147 {
148         unsigned char const *p = (unsigned char const *)pp;
149
150         return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]);
151 }
152 #endif
153
154 /* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#tag_encodings */
155 static const char *
156 d_tags(uint64_t tag)
157 {
158         static char unknown_buf[64];
159
160         switch (tag) {
161         case DT_NULL:           return "DT_NULL";
162         case DT_NEEDED:         return "DT_NEEDED";
163         case DT_PLTRELSZ:       return "DT_PLTRELSZ";
164         case DT_PLTGOT:         return "DT_PLTGOT";
165         case DT_HASH:           return "DT_HASH";
166         case DT_STRTAB:         return "DT_STRTAB";
167         case DT_SYMTAB:         return "DT_SYMTAB";
168         case DT_RELA:           return "DT_RELA";
169         case DT_RELASZ:         return "DT_RELASZ";
170         case DT_RELAENT:        return "DT_RELAENT";
171         case DT_STRSZ:          return "DT_STRSZ";
172         case DT_SYMENT:         return "DT_SYMENT";
173         case DT_INIT:           return "DT_INIT";
174         case DT_FINI:           return "DT_FINI";
175         case DT_SONAME:         return "DT_SONAME";
176         case DT_RPATH:          return "DT_RPATH";
177         case DT_SYMBOLIC:       return "DT_SYMBOLIC";
178         case DT_REL:            return "DT_REL";
179         case DT_RELSZ:          return "DT_RELSZ";
180         case DT_RELENT:         return "DT_RELENT";
181         case DT_PLTREL:         return "DT_PLTREL";
182         case DT_DEBUG:          return "DT_DEBUG";
183         case DT_TEXTREL:        return "DT_TEXTREL";
184         case DT_JMPREL:         return "DT_JMPREL";
185         case DT_BIND_NOW:       return "DT_BIND_NOW";
186         case DT_INIT_ARRAY:     return "DT_INIT_ARRAY";
187         case DT_FINI_ARRAY:     return "DT_FINI_ARRAY";
188         case DT_INIT_ARRAYSZ:   return "DT_INIT_ARRAYSZ";
189         case DT_FINI_ARRAYSZ:   return "DT_FINI_ARRAYSZ";
190         case DT_RUNPATH:        return "DT_RUNPATH";
191         case DT_FLAGS:          return "DT_FLAGS";
192         case DT_PREINIT_ARRAY:  return "DT_PREINIT_ARRAY"; /* XXX DT_ENCODING */
193         case DT_PREINIT_ARRAYSZ:return "DT_PREINIT_ARRAYSZ";
194         /* 0x6000000D - 0x6ffff000 operating system-specific semantics */
195         case 0x6ffffdf5:        return "DT_GNU_PRELINKED";
196         case 0x6ffffdf6:        return "DT_GNU_CONFLICTSZ";
197         case 0x6ffffdf7:        return "DT_GNU_LIBLISTSZ";
198         case 0x6ffffdf8:        return "DT_SUNW_CHECKSUM";
199         case DT_PLTPADSZ:       return "DT_PLTPADSZ";
200         case DT_MOVEENT:        return "DT_MOVEENT";
201         case DT_MOVESZ:         return "DT_MOVESZ";
202         case 0x6ffffdfc:        return "DT_FEATURE";
203         case DT_POSFLAG_1:      return "DT_POSFLAG_1";
204         case DT_SYMINSZ:        return "DT_SYMINSZ";
205         case DT_SYMINENT:       return "DT_SYMINENT (DT_VALRNGHI)";
206         case DT_ADDRRNGLO:      return "DT_ADDRRNGLO";
207         case DT_GNU_HASH:       return "DT_GNU_HASH";
208         case 0x6ffffef8:        return "DT_GNU_CONFLICT";
209         case 0x6ffffef9:        return "DT_GNU_LIBLIST";
210         case 0x6ffffefa:        return "DT_CONFIG";
211         case 0x6ffffefb:        return "DT_DEPAUDIT";
212         case 0x6ffffefc:        return "DT_AUDIT";
213         case 0x6ffffefd:        return "DT_PLTPAD";
214         case 0x6ffffefe:        return "DT_MOVETAB";
215         case DT_SYMINFO:        return "DT_SYMINFO (DT_ADDRRNGHI)";
216         case DT_RELACOUNT:      return "DT_RELACOUNT";
217         case DT_RELCOUNT:       return "DT_RELCOUNT";
218         case DT_FLAGS_1:        return "DT_FLAGS_1";
219         case DT_VERDEF:         return "DT_VERDEF";
220         case DT_VERDEFNUM:      return "DT_VERDEFNUM";
221         case DT_VERNEED:        return "DT_VERNEED";
222         case DT_VERNEEDNUM:     return "DT_VERNEEDNUM";
223         case 0x6ffffff0:        return "DT_GNU_VERSYM";
224         /* 0x70000000 - 0x7fffffff processor-specific semantics */
225         case 0x70000000:        return "DT_IA_64_PLT_RESERVE";
226         case 0x7ffffffd:        return "DT_SUNW_AUXILIARY";
227         case 0x7ffffffe:        return "DT_SUNW_USED";
228         case 0x7fffffff:        return "DT_SUNW_FILTER";
229         }
230
231         snprintf(unknown_buf, sizeof(unknown_buf),
232                 "<unknown: %#llx>", (unsigned long long)tag);
233         return (unknown_buf);
234 }
235
236 static const char *
237 e_machines(unsigned int mach)
238 {
239         static char machdesc[64];
240
241         switch (mach) {
242         case EM_NONE:   return "EM_NONE";
243         case EM_M32:    return "EM_M32";
244         case EM_SPARC:  return "EM_SPARC";
245         case EM_386:    return "EM_386";
246         case EM_68K:    return "EM_68K";
247         case EM_88K:    return "EM_88K";
248         case EM_IAMCU:  return "EM_IAMCU";
249         case EM_860:    return "EM_860";
250         case EM_MIPS:   return "EM_MIPS";
251         case EM_PPC:    return "EM_PPC";
252         case EM_PPC64:  return "EM_PPC64";
253         case EM_ARM:    return "EM_ARM";
254         case EM_ALPHA:  return "EM_ALPHA (legacy)";
255         case EM_SPARCV9:return "EM_SPARCV9";
256         case EM_IA_64:  return "EM_IA_64";
257         case EM_X86_64: return "EM_X86_64";
258         case EM_AARCH64:return "EM_AARCH64";
259         case EM_RISCV:  return "EM_RISCV";
260         }
261         snprintf(machdesc, sizeof(machdesc),
262             "(unknown machine) -- type 0x%x", mach);
263         return (machdesc);
264 }
265
266 static const char *e_types[] = {
267         "ET_NONE", "ET_REL", "ET_EXEC", "ET_DYN", "ET_CORE"
268 };
269
270 static const char *ei_versions[] = {
271         "EV_NONE", "EV_CURRENT"
272 };
273
274 static const char *ei_classes[] = {
275         "ELFCLASSNONE", "ELFCLASS32", "ELFCLASS64"
276 };
277
278 static const char *ei_data[] = {
279         "ELFDATANONE", "ELFDATA2LSB", "ELFDATA2MSB"
280 };
281
282 static const char *ei_abis[256] = {
283         "ELFOSABI_NONE", "ELFOSABI_HPUX", "ELFOSABI_NETBSD", "ELFOSABI_LINUX",
284         "ELFOSABI_HURD", "ELFOSABI_86OPEN", "ELFOSABI_SOLARIS", "ELFOSABI_AIX",
285         "ELFOSABI_IRIX", "ELFOSABI_FREEBSD", "ELFOSABI_TRU64",
286         "ELFOSABI_MODESTO", "ELFOSABI_OPENBSD",
287         [255] = "ELFOSABI_STANDALONE"
288 };
289
290 static const char *p_types[] = {
291         "PT_NULL", "PT_LOAD", "PT_DYNAMIC", "PT_INTERP", "PT_NOTE",
292         "PT_SHLIB", "PT_PHDR", "PT_TLS"
293 };
294
295 static const char *p_flags[] = {
296         "", "PF_X", "PF_W", "PF_X|PF_W", "PF_R", "PF_X|PF_R", "PF_W|PF_R",
297         "PF_X|PF_W|PF_R"
298 };
299
300 static const char *
301 sh_name(struct elfdump *ed, int ndx)
302 {
303         static char num[10];
304
305         switch (ndx) {
306         case SHN_UNDEF: return "UNDEF";
307         case SHN_ABS: return "ABS";
308         case SHN_COMMON: return "COMMON";
309         default:
310                 if ((uint64_t)ndx < ed->shnum)
311                         return (ed->sl[ndx].name);
312                 else {
313                         snprintf(num, sizeof(num), "%d", ndx);
314                         return (num);
315                 }
316         }
317 }
318
319 /* http://www.sco.com/developers/gabi/latest/ch4.sheader.html#sh_type */
320 static const char *
321 sh_types(uint64_t mach, uint64_t sht) {
322         static char unknown_buf[64];
323
324         if (sht < 0x60000000) {
325                 switch (sht) {
326                 case SHT_NULL:          return "SHT_NULL";
327                 case SHT_PROGBITS:      return "SHT_PROGBITS";
328                 case SHT_SYMTAB:        return "SHT_SYMTAB";
329                 case SHT_STRTAB:        return "SHT_STRTAB";
330                 case SHT_RELA:          return "SHT_RELA";
331                 case SHT_HASH:          return "SHT_HASH";
332                 case SHT_DYNAMIC:       return "SHT_DYNAMIC";
333                 case SHT_NOTE:          return "SHT_NOTE";
334                 case SHT_NOBITS:        return "SHT_NOBITS";
335                 case SHT_REL:           return "SHT_REL";
336                 case SHT_SHLIB:         return "SHT_SHLIB";
337                 case SHT_DYNSYM:        return "SHT_DYNSYM";
338                 case SHT_INIT_ARRAY:    return "SHT_INIT_ARRAY";
339                 case SHT_FINI_ARRAY:    return "SHT_FINI_ARRAY";
340                 case SHT_PREINIT_ARRAY: return "SHT_PREINIT_ARRAY";
341                 case SHT_GROUP:         return "SHT_GROUP";
342                 case SHT_SYMTAB_SHNDX:  return "SHT_SYMTAB_SHNDX";
343                 }
344         } else if (sht < 0x70000000) {
345                 /* 0x60000000-0x6fffffff operating system-specific semantics */
346                 switch (sht) {
347                 case 0x6ffffff0:        return "XXX:VERSYM";
348                 case SHT_SUNW_dof:      return "SHT_SUNW_dof";
349                 case SHT_GNU_HASH:      return "SHT_GNU_HASH";
350                 case 0x6ffffff7:        return "SHT_GNU_LIBLIST";
351                 case 0x6ffffffc:        return "XXX:VERDEF";
352                 case SHT_SUNW_verdef:   return "SHT_SUNW(GNU)_verdef";
353                 case SHT_SUNW_verneed:  return "SHT_SUNW(GNU)_verneed";
354                 case SHT_SUNW_versym:   return "SHT_SUNW(GNU)_versym";
355                 }
356         } else if (sht < 0x80000000) {
357                 /* 0x70000000 - 0x7fffffff processor-specific semantics */
358                 switch (mach) {
359                 case EM_ARM:
360                         switch (sht) {
361                         case SHT_ARM_EXIDX: return "SHT_ARM_EXIDX";
362                         case SHT_ARM_PREEMPTMAP: return "SHT_ARM_PREEMPTMAP";
363                         case SHT_ARM_ATTRIBUTES: return "SHT_ARM_ATTRIBUTES";
364                         case SHT_ARM_DEBUGOVERLAY:
365                             return "SHT_ARM_DEBUGOVERLAY";
366                         case SHT_ARM_OVERLAYSECTION:
367                             return "SHT_ARM_OVERLAYSECTION";
368                         }
369                         break;
370                 case EM_IA_64:
371                         switch (sht) {
372                         case 0x70000000: return "SHT_IA_64_EXT";
373                         case 0x70000001: return "SHT_IA_64_UNWIND";
374                         }
375                         break;
376                 case EM_MIPS:
377                         switch (sht) {
378                         case SHT_MIPS_REGINFO: return "SHT_MIPS_REGINFO";
379                         case SHT_MIPS_OPTIONS: return "SHT_MIPS_OPTIONS";
380                         case SHT_MIPS_ABIFLAGS: return "SHT_MIPS_ABIFLAGS";
381                         }
382                         break;
383                 }
384                 switch (sht) {
385                 case 0x7ffffffd: return "XXX:AUXILIARY";
386                 case 0x7fffffff: return "XXX:FILTER";
387                 }
388         }
389         /* 0x80000000 - 0xffffffff application programs */
390
391         snprintf(unknown_buf, sizeof(unknown_buf),
392                 "<unknown: %#llx>", (unsigned long long)sht);
393         return (unknown_buf);
394 }
395
396 /*
397  * Define known section flags. These flags are defined in the order
398  * they are to be printed out.
399  */
400 #define DEFINE_SHFLAGS()                        \
401         DEFINE_SHF(WRITE)                       \
402         DEFINE_SHF(ALLOC)                       \
403         DEFINE_SHF(EXECINSTR)                   \
404         DEFINE_SHF(MERGE)                       \
405         DEFINE_SHF(STRINGS)                     \
406         DEFINE_SHF(INFO_LINK)                   \
407         DEFINE_SHF(LINK_ORDER)                  \
408         DEFINE_SHF(OS_NONCONFORMING)            \
409         DEFINE_SHF(GROUP)                       \
410         DEFINE_SHF(TLS)
411
412 #undef  DEFINE_SHF
413 #define DEFINE_SHF(F) "SHF_" #F "|"
414 #define ALLSHFLAGS      DEFINE_SHFLAGS()
415
416 static const char *
417 sh_flags(uint64_t shf)
418 {
419         static char     flg[sizeof(ALLSHFLAGS)+1];
420
421         flg[0] = '\0';
422
423 #undef  DEFINE_SHF
424 #define DEFINE_SHF(N)                           \
425         if (shf & SHF_##N)                      \
426                 strcat(flg, "SHF_" #N "|");     \
427
428         DEFINE_SHFLAGS()
429
430         flg[strlen(flg) - 1] = '\0'; /* Remove the trailing "|". */
431
432         return (flg);
433 }
434
435 static const char *
436 st_type(unsigned int mach, unsigned int type)
437 {
438         static char s_type[32];
439
440         switch (type) {
441         case STT_NOTYPE: return "STT_NOTYPE";
442         case STT_OBJECT: return "STT_OBJECT";
443         case STT_FUNC: return "STT_FUNC";
444         case STT_SECTION: return "STT_SECTION";
445         case STT_FILE: return "STT_FILE";
446         case STT_COMMON: return "STT_COMMON";
447         case STT_TLS: return "STT_TLS";
448         case 13:
449                 if (mach == EM_SPARCV9)
450                         return "STT_SPARC_REGISTER";
451                 break;
452         }
453         snprintf(s_type, sizeof(s_type), "<unknown: %#x>", type);
454         return (s_type);
455 }
456
457 static const char *
458 st_type_S(unsigned int type)
459 {
460         static char s_type[32];
461
462         switch (type) {
463         case STT_NOTYPE: return "NOTY";
464         case STT_OBJECT: return "OBJT";
465         case STT_FUNC: return "FUNC";
466         case STT_SECTION: return "SECT";
467         case STT_FILE: return "FILE";
468         }
469         snprintf(s_type, sizeof(s_type), "<unknown: %#x>", type);
470         return (s_type);
471 }
472
473 static const char *
474 st_bindings(unsigned int sbind)
475 {
476         static char s_sbind[32];
477
478         switch (sbind) {
479         case STB_LOCAL: return "STB_LOCAL";
480         case STB_GLOBAL: return "STB_GLOBAL";
481         case STB_WEAK: return "STB_WEAK";
482         case STB_GNU_UNIQUE: return "STB_GNU_UNIQUE";
483         default:
484                 if (sbind >= STB_LOOS && sbind <= STB_HIOS)
485                         return "OS";
486                 else if (sbind >= STB_LOPROC && sbind <= STB_HIPROC)
487                         return "PROC";
488                 else
489                         snprintf(s_sbind, sizeof(s_sbind), "<unknown: %#x>",
490                             sbind);
491                 return (s_sbind);
492         }
493 }
494
495 static const char *
496 st_bindings_S(unsigned int sbind)
497 {
498         static char s_sbind[32];
499
500         switch (sbind) {
501         case STB_LOCAL: return "LOCL";
502         case STB_GLOBAL: return "GLOB";
503         case STB_WEAK: return "WEAK";
504         case STB_GNU_UNIQUE: return "UNIQ";
505         default:
506                 if (sbind >= STB_LOOS && sbind <= STB_HIOS)
507                         return "OS";
508                 else if (sbind >= STB_LOPROC && sbind <= STB_HIPROC)
509                         return "PROC";
510                 else
511                         snprintf(s_sbind, sizeof(s_sbind), "<%#x>",
512                             sbind);
513                 return (s_sbind);
514         }
515 }
516
517 static unsigned char st_others[] = {
518         'D', 'I', 'H', 'P'
519 };
520
521 static const char *
522 r_type(unsigned int mach, unsigned int type)
523 {
524         switch(mach) {
525         case EM_NONE: return "";
526         case EM_386:
527         case EM_IAMCU:
528                 switch(type) {
529                 case 0: return "R_386_NONE";
530                 case 1: return "R_386_32";
531                 case 2: return "R_386_PC32";
532                 case 3: return "R_386_GOT32";
533                 case 4: return "R_386_PLT32";
534                 case 5: return "R_386_COPY";
535                 case 6: return "R_386_GLOB_DAT";
536                 case 7: return "R_386_JUMP_SLOT";
537                 case 8: return "R_386_RELATIVE";
538                 case 9: return "R_386_GOTOFF";
539                 case 10: return "R_386_GOTPC";
540                 case 14: return "R_386_TLS_TPOFF";
541                 case 15: return "R_386_TLS_IE";
542                 case 16: return "R_386_TLS_GOTIE";
543                 case 17: return "R_386_TLS_LE";
544                 case 18: return "R_386_TLS_GD";
545                 case 19: return "R_386_TLS_LDM";
546                 case 24: return "R_386_TLS_GD_32";
547                 case 25: return "R_386_TLS_GD_PUSH";
548                 case 26: return "R_386_TLS_GD_CALL";
549                 case 27: return "R_386_TLS_GD_POP";
550                 case 28: return "R_386_TLS_LDM_32";
551                 case 29: return "R_386_TLS_LDM_PUSH";
552                 case 30: return "R_386_TLS_LDM_CALL";
553                 case 31: return "R_386_TLS_LDM_POP";
554                 case 32: return "R_386_TLS_LDO_32";
555                 case 33: return "R_386_TLS_IE_32";
556                 case 34: return "R_386_TLS_LE_32";
557                 case 35: return "R_386_TLS_DTPMOD32";
558                 case 36: return "R_386_TLS_DTPOFF32";
559                 case 37: return "R_386_TLS_TPOFF32";
560                 default: return "";
561                 }
562         case EM_ARM:
563                 switch(type) {
564                 case 0: return "R_ARM_NONE";
565                 case 1: return "R_ARM_PC24";
566                 case 2: return "R_ARM_ABS32";
567                 case 3: return "R_ARM_REL32";
568                 case 4: return "R_ARM_PC13";
569                 case 5: return "R_ARM_ABS16";
570                 case 6: return "R_ARM_ABS12";
571                 case 7: return "R_ARM_THM_ABS5";
572                 case 8: return "R_ARM_ABS8";
573                 case 9: return "R_ARM_SBREL32";
574                 case 10: return "R_ARM_THM_PC22";
575                 case 11: return "R_ARM_THM_PC8";
576                 case 12: return "R_ARM_AMP_VCALL9";
577                 case 13: return "R_ARM_SWI24";
578                 case 14: return "R_ARM_THM_SWI8";
579                 case 15: return "R_ARM_XPC25";
580                 case 16: return "R_ARM_THM_XPC22";
581                 case 20: return "R_ARM_COPY";
582                 case 21: return "R_ARM_GLOB_DAT";
583                 case 22: return "R_ARM_JUMP_SLOT";
584                 case 23: return "R_ARM_RELATIVE";
585                 case 24: return "R_ARM_GOTOFF";
586                 case 25: return "R_ARM_GOTPC";
587                 case 26: return "R_ARM_GOT32";
588                 case 27: return "R_ARM_PLT32";
589                 case 100: return "R_ARM_GNU_VTENTRY";
590                 case 101: return "R_ARM_GNU_VTINHERIT";
591                 case 250: return "R_ARM_RSBREL32";
592                 case 251: return "R_ARM_THM_RPC22";
593                 case 252: return "R_ARM_RREL32";
594                 case 253: return "R_ARM_RABS32";
595                 case 254: return "R_ARM_RPC24";
596                 case 255: return "R_ARM_RBASE";
597                 default: return "";
598                 }
599         case EM_IA_64:
600                 switch(type) {
601                 case 0: return "R_IA_64_NONE";
602                 case 33: return "R_IA_64_IMM14";
603                 case 34: return "R_IA_64_IMM22";
604                 case 35: return "R_IA_64_IMM64";
605                 case 36: return "R_IA_64_DIR32MSB";
606                 case 37: return "R_IA_64_DIR32LSB";
607                 case 38: return "R_IA_64_DIR64MSB";
608                 case 39: return "R_IA_64_DIR64LSB";
609                 case 42: return "R_IA_64_GPREL22";
610                 case 43: return "R_IA_64_GPREL64I";
611                 case 44: return "R_IA_64_GPREL32MSB";
612                 case 45: return "R_IA_64_GPREL32LSB";
613                 case 46: return "R_IA_64_GPREL64MSB";
614                 case 47: return "R_IA_64_GPREL64LSB";
615                 case 50: return "R_IA_64_LTOFF22";
616                 case 51: return "R_IA_64_LTOFF64I";
617                 case 58: return "R_IA_64_PLTOFF22";
618                 case 59: return "R_IA_64_PLTOFF64I";
619                 case 62: return "R_IA_64_PLTOFF64MSB";
620                 case 63: return "R_IA_64_PLTOFF64LSB";
621                 case 67: return "R_IA_64_FPTR64I";
622                 case 68: return "R_IA_64_FPTR32MSB";
623                 case 69: return "R_IA_64_FPTR32LSB";
624                 case 70: return "R_IA_64_FPTR64MSB";
625                 case 71: return "R_IA_64_FPTR64LSB";
626                 case 72: return "R_IA_64_PCREL60B";
627                 case 73: return "R_IA_64_PCREL21B";
628                 case 74: return "R_IA_64_PCREL21M";
629                 case 75: return "R_IA_64_PCREL21F";
630                 case 76: return "R_IA_64_PCREL32MSB";
631                 case 77: return "R_IA_64_PCREL32LSB";
632                 case 78: return "R_IA_64_PCREL64MSB";
633                 case 79: return "R_IA_64_PCREL64LSB";
634                 case 82: return "R_IA_64_LTOFF_FPTR22";
635                 case 83: return "R_IA_64_LTOFF_FPTR64I";
636                 case 84: return "R_IA_64_LTOFF_FPTR32MSB";
637                 case 85: return "R_IA_64_LTOFF_FPTR32LSB";
638                 case 86: return "R_IA_64_LTOFF_FPTR64MSB";
639                 case 87: return "R_IA_64_LTOFF_FPTR64LSB";
640                 case 92: return "R_IA_64_SEGREL32MSB";
641                 case 93: return "R_IA_64_SEGREL32LSB";
642                 case 94: return "R_IA_64_SEGREL64MSB";
643                 case 95: return "R_IA_64_SEGREL64LSB";
644                 case 100: return "R_IA_64_SECREL32MSB";
645                 case 101: return "R_IA_64_SECREL32LSB";
646                 case 102: return "R_IA_64_SECREL64MSB";
647                 case 103: return "R_IA_64_SECREL64LSB";
648                 case 108: return "R_IA_64_REL32MSB";
649                 case 109: return "R_IA_64_REL32LSB";
650                 case 110: return "R_IA_64_REL64MSB";
651                 case 111: return "R_IA_64_REL64LSB";
652                 case 116: return "R_IA_64_LTV32MSB";
653                 case 117: return "R_IA_64_LTV32LSB";
654                 case 118: return "R_IA_64_LTV64MSB";
655                 case 119: return "R_IA_64_LTV64LSB";
656                 case 121: return "R_IA_64_PCREL21BI";
657                 case 122: return "R_IA_64_PCREL22";
658                 case 123: return "R_IA_64_PCREL64I";
659                 case 128: return "R_IA_64_IPLTMSB";
660                 case 129: return "R_IA_64_IPLTLSB";
661                 case 133: return "R_IA_64_SUB";
662                 case 134: return "R_IA_64_LTOFF22X";
663                 case 135: return "R_IA_64_LDXMOV";
664                 case 145: return "R_IA_64_TPREL14";
665                 case 146: return "R_IA_64_TPREL22";
666                 case 147: return "R_IA_64_TPREL64I";
667                 case 150: return "R_IA_64_TPREL64MSB";
668                 case 151: return "R_IA_64_TPREL64LSB";
669                 case 154: return "R_IA_64_LTOFF_TPREL22";
670                 case 166: return "R_IA_64_DTPMOD64MSB";
671                 case 167: return "R_IA_64_DTPMOD64LSB";
672                 case 170: return "R_IA_64_LTOFF_DTPMOD22";
673                 case 177: return "R_IA_64_DTPREL14";
674                 case 178: return "R_IA_64_DTPREL22";
675                 case 179: return "R_IA_64_DTPREL64I";
676                 case 180: return "R_IA_64_DTPREL32MSB";
677                 case 181: return "R_IA_64_DTPREL32LSB";
678                 case 182: return "R_IA_64_DTPREL64MSB";
679                 case 183: return "R_IA_64_DTPREL64LSB";
680                 case 186: return "R_IA_64_LTOFF_DTPREL22";
681                 default: return "";
682                 }
683         case EM_MIPS:
684                 switch(type) {
685                 case 0: return "R_MIPS_NONE";
686                 case 1: return "R_MIPS_16";
687                 case 2: return "R_MIPS_32";
688                 case 3: return "R_MIPS_REL32";
689                 case 4: return "R_MIPS_26";
690                 case 5: return "R_MIPS_HI16";
691                 case 6: return "R_MIPS_LO16";
692                 case 7: return "R_MIPS_GPREL16";
693                 case 8: return "R_MIPS_LITERAL";
694                 case 9: return "R_MIPS_GOT16";
695                 case 10: return "R_MIPS_PC16";
696                 case 11: return "R_MIPS_CALL16";
697                 case 12: return "R_MIPS_GPREL32";
698                 case 21: return "R_MIPS_GOTHI16";
699                 case 22: return "R_MIPS_GOTLO16";
700                 case 30: return "R_MIPS_CALLHI16";
701                 case 31: return "R_MIPS_CALLLO16";
702                 default: return "";
703                 }
704         case EM_PPC:
705                 switch(type) {
706                 case 0: return "R_PPC_NONE";
707                 case 1: return "R_PPC_ADDR32";
708                 case 2: return "R_PPC_ADDR24";
709                 case 3: return "R_PPC_ADDR16";
710                 case 4: return "R_PPC_ADDR16_LO";
711                 case 5: return "R_PPC_ADDR16_HI";
712                 case 6: return "R_PPC_ADDR16_HA";
713                 case 7: return "R_PPC_ADDR14";
714                 case 8: return "R_PPC_ADDR14_BRTAKEN";
715                 case 9: return "R_PPC_ADDR14_BRNTAKEN";
716                 case 10: return "R_PPC_REL24";
717                 case 11: return "R_PPC_REL14";
718                 case 12: return "R_PPC_REL14_BRTAKEN";
719                 case 13: return "R_PPC_REL14_BRNTAKEN";
720                 case 14: return "R_PPC_GOT16";
721                 case 15: return "R_PPC_GOT16_LO";
722                 case 16: return "R_PPC_GOT16_HI";
723                 case 17: return "R_PPC_GOT16_HA";
724                 case 18: return "R_PPC_PLTREL24";
725                 case 19: return "R_PPC_COPY";
726                 case 20: return "R_PPC_GLOB_DAT";
727                 case 21: return "R_PPC_JMP_SLOT";
728                 case 22: return "R_PPC_RELATIVE";
729                 case 23: return "R_PPC_LOCAL24PC";
730                 case 24: return "R_PPC_UADDR32";
731                 case 25: return "R_PPC_UADDR16";
732                 case 26: return "R_PPC_REL32";
733                 case 27: return "R_PPC_PLT32";
734                 case 28: return "R_PPC_PLTREL32";
735                 case 29: return "R_PPC_PLT16_LO";
736                 case 30: return "R_PPC_PLT16_HI";
737                 case 31: return "R_PPC_PLT16_HA";
738                 case 32: return "R_PPC_SDAREL16";
739                 case 33: return "R_PPC_SECTOFF";
740                 case 34: return "R_PPC_SECTOFF_LO";
741                 case 35: return "R_PPC_SECTOFF_HI";
742                 case 36: return "R_PPC_SECTOFF_HA";
743                 case 67: return "R_PPC_TLS";
744                 case 68: return "R_PPC_DTPMOD32";
745                 case 69: return "R_PPC_TPREL16";
746                 case 70: return "R_PPC_TPREL16_LO";
747                 case 71: return "R_PPC_TPREL16_HI";
748                 case 72: return "R_PPC_TPREL16_HA";
749                 case 73: return "R_PPC_TPREL32";
750                 case 74: return "R_PPC_DTPREL16";
751                 case 75: return "R_PPC_DTPREL16_LO";
752                 case 76: return "R_PPC_DTPREL16_HI";
753                 case 77: return "R_PPC_DTPREL16_HA";
754                 case 78: return "R_PPC_DTPREL32";
755                 case 79: return "R_PPC_GOT_TLSGD16";
756                 case 80: return "R_PPC_GOT_TLSGD16_LO";
757                 case 81: return "R_PPC_GOT_TLSGD16_HI";
758                 case 82: return "R_PPC_GOT_TLSGD16_HA";
759                 case 83: return "R_PPC_GOT_TLSLD16";
760                 case 84: return "R_PPC_GOT_TLSLD16_LO";
761                 case 85: return "R_PPC_GOT_TLSLD16_HI";
762                 case 86: return "R_PPC_GOT_TLSLD16_HA";
763                 case 87: return "R_PPC_GOT_TPREL16";
764                 case 88: return "R_PPC_GOT_TPREL16_LO";
765                 case 89: return "R_PPC_GOT_TPREL16_HI";
766                 case 90: return "R_PPC_GOT_TPREL16_HA";
767                 case 101: return "R_PPC_EMB_NADDR32";
768                 case 102: return "R_PPC_EMB_NADDR16";
769                 case 103: return "R_PPC_EMB_NADDR16_LO";
770                 case 104: return "R_PPC_EMB_NADDR16_HI";
771                 case 105: return "R_PPC_EMB_NADDR16_HA";
772                 case 106: return "R_PPC_EMB_SDAI16";
773                 case 107: return "R_PPC_EMB_SDA2I16";
774                 case 108: return "R_PPC_EMB_SDA2REL";
775                 case 109: return "R_PPC_EMB_SDA21";
776                 case 110: return "R_PPC_EMB_MRKREF";
777                 case 111: return "R_PPC_EMB_RELSEC16";
778                 case 112: return "R_PPC_EMB_RELST_LO";
779                 case 113: return "R_PPC_EMB_RELST_HI";
780                 case 114: return "R_PPC_EMB_RELST_HA";
781                 case 115: return "R_PPC_EMB_BIT_FLD";
782                 case 116: return "R_PPC_EMB_RELSDA";
783                 default: return "";
784                 }
785         case EM_SPARC:
786         case EM_SPARCV9:
787                 switch(type) {
788                 case 0: return "R_SPARC_NONE";
789                 case 1: return "R_SPARC_8";
790                 case 2: return "R_SPARC_16";
791                 case 3: return "R_SPARC_32";
792                 case 4: return "R_SPARC_DISP8";
793                 case 5: return "R_SPARC_DISP16";
794                 case 6: return "R_SPARC_DISP32";
795                 case 7: return "R_SPARC_WDISP30";
796                 case 8: return "R_SPARC_WDISP22";
797                 case 9: return "R_SPARC_HI22";
798                 case 10: return "R_SPARC_22";
799                 case 11: return "R_SPARC_13";
800                 case 12: return "R_SPARC_LO10";
801                 case 13: return "R_SPARC_GOT10";
802                 case 14: return "R_SPARC_GOT13";
803                 case 15: return "R_SPARC_GOT22";
804                 case 16: return "R_SPARC_PC10";
805                 case 17: return "R_SPARC_PC22";
806                 case 18: return "R_SPARC_WPLT30";
807                 case 19: return "R_SPARC_COPY";
808                 case 20: return "R_SPARC_GLOB_DAT";
809                 case 21: return "R_SPARC_JMP_SLOT";
810                 case 22: return "R_SPARC_RELATIVE";
811                 case 23: return "R_SPARC_UA32";
812                 case 24: return "R_SPARC_PLT32";
813                 case 25: return "R_SPARC_HIPLT22";
814                 case 26: return "R_SPARC_LOPLT10";
815                 case 27: return "R_SPARC_PCPLT32";
816                 case 28: return "R_SPARC_PCPLT22";
817                 case 29: return "R_SPARC_PCPLT10";
818                 case 30: return "R_SPARC_10";
819                 case 31: return "R_SPARC_11";
820                 case 32: return "R_SPARC_64";
821                 case 33: return "R_SPARC_OLO10";
822                 case 34: return "R_SPARC_HH22";
823                 case 35: return "R_SPARC_HM10";
824                 case 36: return "R_SPARC_LM22";
825                 case 37: return "R_SPARC_PC_HH22";
826                 case 38: return "R_SPARC_PC_HM10";
827                 case 39: return "R_SPARC_PC_LM22";
828                 case 40: return "R_SPARC_WDISP16";
829                 case 41: return "R_SPARC_WDISP19";
830                 case 42: return "R_SPARC_GLOB_JMP";
831                 case 43: return "R_SPARC_7";
832                 case 44: return "R_SPARC_5";
833                 case 45: return "R_SPARC_6";
834                 case 46: return "R_SPARC_DISP64";
835                 case 47: return "R_SPARC_PLT64";
836                 case 48: return "R_SPARC_HIX22";
837                 case 49: return "R_SPARC_LOX10";
838                 case 50: return "R_SPARC_H44";
839                 case 51: return "R_SPARC_M44";
840                 case 52: return "R_SPARC_L44";
841                 case 53: return "R_SPARC_REGISTER";
842                 case 54: return "R_SPARC_UA64";
843                 case 55: return "R_SPARC_UA16";
844                 case 56: return "R_SPARC_TLS_GD_HI22";
845                 case 57: return "R_SPARC_TLS_GD_LO10";
846                 case 58: return "R_SPARC_TLS_GD_ADD";
847                 case 59: return "R_SPARC_TLS_GD_CALL";
848                 case 60: return "R_SPARC_TLS_LDM_HI22";
849                 case 61: return "R_SPARC_TLS_LDM_LO10";
850                 case 62: return "R_SPARC_TLS_LDM_ADD";
851                 case 63: return "R_SPARC_TLS_LDM_CALL";
852                 case 64: return "R_SPARC_TLS_LDO_HIX22";
853                 case 65: return "R_SPARC_TLS_LDO_LOX10";
854                 case 66: return "R_SPARC_TLS_LDO_ADD";
855                 case 67: return "R_SPARC_TLS_IE_HI22";
856                 case 68: return "R_SPARC_TLS_IE_LO10";
857                 case 69: return "R_SPARC_TLS_IE_LD";
858                 case 70: return "R_SPARC_TLS_IE_LDX";
859                 case 71: return "R_SPARC_TLS_IE_ADD";
860                 case 72: return "R_SPARC_TLS_LE_HIX22";
861                 case 73: return "R_SPARC_TLS_LE_LOX10";
862                 case 74: return "R_SPARC_TLS_DTPMOD32";
863                 case 75: return "R_SPARC_TLS_DTPMOD64";
864                 case 76: return "R_SPARC_TLS_DTPOFF32";
865                 case 77: return "R_SPARC_TLS_DTPOFF64";
866                 case 78: return "R_SPARC_TLS_TPOFF32";
867                 case 79: return "R_SPARC_TLS_TPOFF64";
868                 default: return "";
869                 }
870         case EM_X86_64:
871                 switch(type) {
872                 case 0: return "R_X86_64_NONE";
873                 case 1: return "R_X86_64_64";
874                 case 2: return "R_X86_64_PC32";
875                 case 3: return "R_X86_64_GOT32";
876                 case 4: return "R_X86_64_PLT32";
877                 case 5: return "R_X86_64_COPY";
878                 case 6: return "R_X86_64_GLOB_DAT";
879                 case 7: return "R_X86_64_JUMP_SLOT";
880                 case 8: return "R_X86_64_RELATIVE";
881                 case 9: return "R_X86_64_GOTPCREL";
882                 case 10: return "R_X86_64_32";
883                 case 11: return "R_X86_64_32S";
884                 case 12: return "R_X86_64_16";
885                 case 13: return "R_X86_64_PC16";
886                 case 14: return "R_X86_64_8";
887                 case 15: return "R_X86_64_PC8";
888                 case 16: return "R_X86_64_DTPMOD64";
889                 case 17: return "R_X86_64_DTPOFF64";
890                 case 18: return "R_X86_64_TPOFF64";
891                 case 19: return "R_X86_64_TLSGD";
892                 case 20: return "R_X86_64_TLSLD";
893                 case 21: return "R_X86_64_DTPOFF32";
894                 case 22: return "R_X86_64_GOTTPOFF";
895                 case 23: return "R_X86_64_TPOFF32";
896                 default: return "";
897                 }
898         default: return "";
899         }
900 }
901
902 static void     add_name(struct elfdump *ed, const char *name);
903 static void     elf_print_object(struct elfdump *ed);
904 static void     elf_print_elf(struct elfdump *ed);
905 static void     elf_print_ehdr(struct elfdump *ed);
906 static void     elf_print_phdr(struct elfdump *ed);
907 static void     elf_print_shdr(struct elfdump *ed);
908 static void     elf_print_symtab(struct elfdump *ed, int i);
909 static void     elf_print_symtabs(struct elfdump *ed);
910 static void     elf_print_symver(struct elfdump *ed);
911 static void     elf_print_verdef(struct elfdump *ed, struct section *s);
912 static void     elf_print_verneed(struct elfdump *ed, struct section *s);
913 static void     elf_print_interp(struct elfdump *ed);
914 static void     elf_print_dynamic(struct elfdump *ed);
915 static void     elf_print_rel_entry(struct elfdump *ed, struct section *s,
916     int j, struct rel_entry *r);
917 static void     elf_print_rela(struct elfdump *ed, struct section *s,
918     Elf_Data *data);
919 static void     elf_print_rel(struct elfdump *ed, struct section *s,
920     Elf_Data *data);
921 static void     elf_print_reloc(struct elfdump *ed);
922 static void     elf_print_got(struct elfdump *ed);
923 static void     elf_print_got_section(struct elfdump *ed, struct section *s);
924 static void     elf_print_note(struct elfdump *ed);
925 static void     elf_print_svr4_hash(struct elfdump *ed, struct section *s);
926 static void     elf_print_svr4_hash64(struct elfdump *ed, struct section *s);
927 static void     elf_print_gnu_hash(struct elfdump *ed, struct section *s);
928 static void     elf_print_hash(struct elfdump *ed);
929 static void     elf_print_checksum(struct elfdump *ed);
930 static void     find_gotrel(struct elfdump *ed, struct section *gs,
931     struct rel_entry *got);
932 static struct spec_name *find_name(struct elfdump *ed, const char *name);
933 static int      get_ent_count(const struct section *s, int *ent_count);
934 static const char *get_symbol_name(struct elfdump *ed, int symtab, int i);
935 static const char *get_string(struct elfdump *ed, int strtab, size_t off);
936 static void     get_versym(struct elfdump *ed, int i, uint16_t **vs, int *nvs);
937 static void     load_sections(struct elfdump *ed);
938 static void     unload_sections(struct elfdump *ed);
939 static void     usage(void);
940 #ifdef  USE_LIBARCHIVE_AR
941 static int      ac_detect_ar(int fd);
942 static void     ac_print_ar(struct elfdump *ed, int fd);
943 #else
944 static void     elf_print_ar(struct elfdump *ed, int fd);
945 #endif  /* USE_LIBARCHIVE_AR */
946
947 static struct option elfdump_longopts[] =
948 {
949         { "help",       no_argument,    NULL,   'H' },
950         { "version",    no_argument,    NULL,   'V' },
951         { NULL,         0,              NULL,   0   }
952 };
953
954 int
955 main(int ac, char **av)
956 {
957         struct elfdump          *ed, ed_storage;
958         struct spec_name        *sn;
959         int                      ch, i;
960
961         ed = &ed_storage;
962         memset(ed, 0, sizeof(*ed));
963         STAILQ_INIT(&ed->snl);
964         ed->out = stdout;
965         while ((ch = getopt_long(ac, av, "acdeiGHhknN:prsSvVw:",
966                 elfdump_longopts, NULL)) != -1)
967                 switch (ch) {
968                 case 'a':
969                         ed->options = ED_ALL;
970                         break;
971                 case 'c':
972                         ed->options |= ED_SHDR;
973                         break;
974                 case 'd':
975                         ed->options |= ED_DYN;
976                         break;
977                 case 'e':
978                         ed->options |= ED_EHDR;
979                         break;
980                 case 'i':
981                         ed->options |= ED_INTERP;
982                         break;
983                 case 'G':
984                         ed->options |= ED_GOT;
985                         break;
986                 case 'h':
987                         ed->options |= ED_HASH;
988                         break;
989                 case 'k':
990                         ed->options |= ED_CHECKSUM;
991                         break;
992                 case 'n':
993                         ed->options |= ED_NOTE;
994                         break;
995                 case 'N':
996                         add_name(ed, optarg);
997                         break;
998                 case 'p':
999                         ed->options |= ED_PHDR;
1000                         break;
1001                 case 'r':
1002                         ed->options |= ED_REL;
1003                         break;
1004                 case 's':
1005                         ed->options |= ED_SYMTAB;
1006                         break;
1007                 case 'S':
1008                         ed->flags |= SOLARIS_FMT;
1009                         break;
1010                 case 'v':
1011                         ed->options |= ED_SYMVER;
1012                         break;
1013                 case 'V':
1014                         (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(),
1015                             elftc_version());
1016                         exit(EXIT_SUCCESS);
1017                         break;
1018                 case 'w':
1019                         if ((ed->out = fopen(optarg, "w")) == NULL)
1020                                 err(EXIT_FAILURE, "%s", optarg);
1021                         break;
1022                 case '?':
1023                 case 'H':
1024                 default:
1025                         usage();
1026                 }
1027
1028         ac -= optind;
1029         av += optind;
1030
1031         if (ed->options == 0)
1032                 ed->options = ED_ALL;
1033         sn = NULL;
1034         if (ed->options & ED_SYMTAB &&
1035             (STAILQ_EMPTY(&ed->snl) || (sn = find_name(ed, "ARSYM")) != NULL)) {
1036                 ed->flags |= PRINT_ARSYM;
1037                 if (sn != NULL) {
1038                         STAILQ_REMOVE(&ed->snl, sn, spec_name, sn_list);
1039                         if (STAILQ_EMPTY(&ed->snl))
1040                                 ed->flags |= ONLY_ARSYM;
1041                 }
1042         }
1043         if (ac == 0)
1044                 usage();
1045         if (ac > 1)
1046                 ed->flags |= PRINT_FILENAME;
1047         if (elf_version(EV_CURRENT) == EV_NONE)
1048                 errx(EXIT_FAILURE, "ELF library initialization failed: %s",
1049                     elf_errmsg(-1));
1050
1051         for (i = 0; i < ac; i++) {
1052                 ed->filename = av[i];
1053                 ed->archive = NULL;
1054                 elf_print_object(ed);
1055         }
1056
1057         exit(EXIT_SUCCESS);
1058 }
1059
1060 #ifdef USE_LIBARCHIVE_AR
1061
1062 /* Archive symbol table entry. */
1063 struct arsym_entry {
1064         char *sym_name;
1065         size_t off;
1066 };
1067
1068 /*
1069  * Convenient wrapper for general libarchive error handling.
1070  */
1071 #define AC(CALL) do {                                                   \
1072         if ((CALL)) {                                                   \
1073                 warnx("%s", archive_error_string(a));                   \
1074                 return;                                                 \
1075         }                                                               \
1076 } while (0)
1077
1078 /*
1079  * Detect an ar(1) archive using libarchive(3).
1080  */
1081 static int
1082 ac_detect_ar(int fd)
1083 {
1084         struct archive          *a;
1085         struct archive_entry    *entry;
1086         int                      r;
1087
1088         r = -1;
1089         if ((a = archive_read_new()) == NULL)
1090                 return (0);
1091         archive_read_support_format_ar(a);
1092         if (archive_read_open_fd(a, fd, 10240) == ARCHIVE_OK)
1093                 r = archive_read_next_header(a, &entry);
1094         archive_read_close(a);
1095         archive_read_free(a);
1096
1097         return (r == ARCHIVE_OK);
1098 }
1099
1100 /*
1101  * Dump an ar(1) archive using libarchive(3).
1102  */
1103 static void
1104 ac_print_ar(struct elfdump *ed, int fd)
1105 {
1106         struct archive          *a;
1107         struct archive_entry    *entry;
1108         struct arsym_entry      *arsym;
1109         const char              *name;
1110         char                     idx[10], *b;
1111         void                    *buff;
1112         size_t                   size;
1113         uint32_t                 cnt;
1114         int                      i, r;
1115
1116         if (lseek(fd, 0, SEEK_SET) == -1)
1117                 err(EXIT_FAILURE, "lseek failed");
1118         if ((a = archive_read_new()) == NULL)
1119                 errx(EXIT_FAILURE, "%s", archive_error_string(a));
1120         archive_read_support_format_ar(a);
1121         AC(archive_read_open_fd(a, fd, 10240));
1122         for(;;) {
1123                 r = archive_read_next_header(a, &entry);
1124                 if (r == ARCHIVE_FATAL)
1125                         errx(EXIT_FAILURE, "%s", archive_error_string(a));
1126                 if (r == ARCHIVE_EOF)
1127                         break;
1128                 if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY)
1129                         warnx("%s", archive_error_string(a));
1130                 if (r == ARCHIVE_RETRY)
1131                         continue;
1132                 name = archive_entry_pathname(entry);
1133                 size = archive_entry_size(entry);
1134                 if (size == 0)
1135                         continue;
1136                 if ((buff = malloc(size)) == NULL) {
1137                         warn("malloc failed");
1138                         continue;
1139                 }
1140                 if (archive_read_data(a, buff, size) != (ssize_t)size) {
1141                         warnx("%s", archive_error_string(a));
1142                         free(buff);
1143                         continue;
1144                 }
1145
1146                 /*
1147                  * Note that when processing arsym via libarchive, there is
1148                  * no way to tell which member a certain symbol belongs to,
1149                  * since we can not just "lseek" to a member offset and read
1150                  * the member header.
1151                  */
1152                 if (!strcmp(name, "/") && ed->flags & PRINT_ARSYM) {
1153                         b = buff;
1154                         cnt = be32dec(b);
1155                         if (cnt == 0) {
1156                                 free(buff);
1157                                 continue;
1158                         }
1159                         arsym = calloc(cnt, sizeof(*arsym));
1160                         if (arsym == NULL)
1161                                 err(EXIT_FAILURE, "calloc failed");
1162                         b += sizeof(uint32_t);
1163                         for (i = 0; (size_t)i < cnt; i++) {
1164                                 arsym[i].off = be32dec(b);
1165                                 b += sizeof(uint32_t);
1166                         }
1167                         for (i = 0; (size_t)i < cnt; i++) {
1168                                 arsym[i].sym_name = b;
1169                                 b += strlen(b) + 1;
1170                         }
1171                         if (ed->flags & SOLARIS_FMT) {
1172                                 PRT("\nSymbol Table: (archive)\n");
1173                                 PRT("     index    offset    symbol\n");
1174                         } else
1175                                 PRT("\nsymbol table (archive):\n");
1176                         for (i = 0; (size_t)i < cnt; i++) {
1177                                 if (ed->flags & SOLARIS_FMT) {
1178                                         snprintf(idx, sizeof(idx), "[%d]", i);
1179                                         PRT("%10s  ", idx);
1180                                         PRT("0x%8.8jx  ",
1181                                             (uintmax_t)arsym[i].off);
1182                                         PRT("%s\n", arsym[i].sym_name);
1183                                 } else {
1184                                         PRT("\nentry: %d\n", i);
1185                                         PRT("\toffset: %#jx\n",
1186                                             (uintmax_t)arsym[i].off);
1187                                         PRT("\tsymbol: %s\n",
1188                                             arsym[i].sym_name);
1189                                 }
1190                         }
1191                         free(arsym);
1192                         free(buff);
1193                         /* No need to continue if we only dump ARSYM. */
1194                         if (ed->flags & ONLY_ARSYM) {
1195                                 AC(archive_read_close(a));
1196                                 AC(archive_read_free(a));
1197                                 return;
1198                         }
1199                         continue;
1200                 }
1201                 if ((ed->elf = elf_memory(buff, size)) == NULL) {
1202                         warnx("elf_memroy() failed: %s",
1203                               elf_errmsg(-1));
1204                         free(buff);
1205                         continue;
1206                 }
1207                 /* Skip non-ELF member. */
1208                 if (elf_kind(ed->elf) == ELF_K_ELF) {
1209                         printf("\n%s(%s):\n", ed->archive, name);
1210                         elf_print_elf(ed);
1211                 }
1212                 elf_end(ed->elf);
1213                 free(buff);
1214         }
1215         AC(archive_read_close(a));
1216         AC(archive_read_free(a));
1217 }
1218
1219 #else  /* USE_LIBARCHIVE_AR */
1220
1221 /*
1222  * Dump an ar(1) archive.
1223  */
1224 static void
1225 elf_print_ar(struct elfdump *ed, int fd)
1226 {
1227         Elf             *e;
1228         Elf_Arhdr       *arh;
1229         Elf_Arsym       *arsym;
1230         Elf_Cmd          cmd;
1231         char             idx[10];
1232         size_t           cnt;
1233         int              i;
1234
1235         ed->ar = ed->elf;
1236
1237         if (ed->flags & PRINT_ARSYM) {
1238                 cnt = 0;
1239                 if ((arsym = elf_getarsym(ed->ar, &cnt)) == NULL) {
1240                         warnx("elf_getarsym failed: %s", elf_errmsg(-1));
1241                         goto print_members;
1242                 }
1243                 if (cnt == 0)
1244                         goto print_members;
1245                 if (ed->flags & SOLARIS_FMT) {
1246                         PRT("\nSymbol Table: (archive)\n");
1247                         PRT("     index    offset    member name and symbol\n");
1248                 } else
1249                         PRT("\nsymbol table (archive):\n");
1250                 for (i = 0; (size_t)i < cnt - 1; i++) {
1251                         if (elf_rand(ed->ar, arsym[i].as_off) !=
1252                             arsym[i].as_off) {
1253                                 warnx("elf_rand failed: %s", elf_errmsg(-1));
1254                                 break;
1255                         }
1256                         if ((e = elf_begin(fd, ELF_C_READ, ed->ar)) == NULL) {
1257                                 warnx("elf_begin failed: %s", elf_errmsg(-1));
1258                                 break;
1259                         }
1260                         if ((arh = elf_getarhdr(e)) == NULL) {
1261                                 warnx("elf_getarhdr failed: %s",
1262                                     elf_errmsg(-1));
1263                                 break;
1264                         }
1265                         if (ed->flags & SOLARIS_FMT) {
1266                                 snprintf(idx, sizeof(idx), "[%d]", i);
1267                                 PRT("%10s  ", idx);
1268                                 PRT("0x%8.8jx  ",
1269                                     (uintmax_t)arsym[i].as_off);
1270                                 PRT("(%s):%s\n", arh->ar_name,
1271                                     arsym[i].as_name);
1272                         } else {
1273                                 PRT("\nentry: %d\n", i);
1274                                 PRT("\toffset: %#jx\n",
1275                                     (uintmax_t)arsym[i].as_off);
1276                                 PRT("\tmember: %s\n", arh->ar_name);
1277                                 PRT("\tsymbol: %s\n", arsym[i].as_name);
1278                         }
1279                         elf_end(e);
1280                 }
1281
1282                 /* No need to continue if we only dump ARSYM. */
1283                 if (ed->flags & ONLY_ARSYM)
1284                         return;
1285         }
1286
1287 print_members:
1288
1289         /* Rewind the archive. */
1290         if (elf_rand(ed->ar, SARMAG) != SARMAG) {
1291                 warnx("elf_rand failed: %s", elf_errmsg(-1));
1292                 return;
1293         }
1294
1295         /* Dump each member of the archive. */
1296         cmd = ELF_C_READ;
1297         while ((ed->elf = elf_begin(fd, cmd, ed->ar)) != NULL) {
1298                 /* Skip non-ELF member. */
1299                 if (elf_kind(ed->elf) == ELF_K_ELF) {
1300                         if ((arh = elf_getarhdr(ed->elf)) == NULL) {
1301                                 warnx("elf_getarhdr failed: %s",
1302                                     elf_errmsg(-1));
1303                                 break;
1304                         }
1305                         printf("\n%s(%s):\n", ed->archive, arh->ar_name);
1306                         elf_print_elf(ed);
1307                 }
1308                 cmd = elf_next(ed->elf);
1309                 elf_end(ed->elf);
1310         }
1311 }
1312
1313 #endif  /* USE_LIBARCHIVE_AR */
1314
1315 /*
1316  * Dump an object. (ELF object or ar(1) archive)
1317  */
1318 static void
1319 elf_print_object(struct elfdump *ed)
1320 {
1321         int fd;
1322
1323         if ((fd = open(ed->filename, O_RDONLY)) == -1) {
1324                 warn("open %s failed", ed->filename);
1325                 return;
1326         }
1327
1328 #ifdef  USE_LIBARCHIVE_AR
1329         if (ac_detect_ar(fd)) {
1330                 ed->archive = ed->filename;
1331                 ac_print_ar(ed, fd);
1332                 return;
1333         }
1334 #endif  /* USE_LIBARCHIVE_AR */
1335
1336         if ((ed->elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
1337                 warnx("elf_begin() failed: %s", elf_errmsg(-1));
1338                 return;
1339         }
1340
1341         switch (elf_kind(ed->elf)) {
1342         case ELF_K_NONE:
1343                 warnx("Not an ELF file.");
1344                 return;
1345         case ELF_K_ELF:
1346                 if (ed->flags & PRINT_FILENAME)
1347                         printf("\n%s:\n", ed->filename);
1348                 elf_print_elf(ed);
1349                 break;
1350         case ELF_K_AR:
1351 #ifndef USE_LIBARCHIVE_AR
1352                 ed->archive = ed->filename;
1353                 elf_print_ar(ed, fd);
1354 #endif
1355                 break;
1356         default:
1357                 warnx("Internal: libelf returned unknown elf kind.");
1358                 return;
1359         }
1360
1361         elf_end(ed->elf);
1362 }
1363
1364 /*
1365  * Dump an ELF object.
1366  */
1367 static void
1368 elf_print_elf(struct elfdump *ed)
1369 {
1370
1371         if (gelf_getehdr(ed->elf, &ed->ehdr) == NULL) {
1372                 warnx("gelf_getehdr failed: %s", elf_errmsg(-1));
1373                 return;
1374         }
1375         if ((ed->ec = gelf_getclass(ed->elf)) == ELFCLASSNONE) {
1376                 warnx("gelf_getclass failed: %s", elf_errmsg(-1));
1377                 return;
1378         }
1379
1380         if (ed->options & (ED_SHDR | ED_DYN | ED_REL | ED_GOT | ED_SYMTAB |
1381             ED_SYMVER | ED_NOTE | ED_HASH))
1382                 load_sections(ed);
1383
1384         if (ed->options & ED_EHDR)
1385                 elf_print_ehdr(ed);
1386         if (ed->options & ED_PHDR)
1387                 elf_print_phdr(ed);
1388         if (ed->options & ED_INTERP)
1389                 elf_print_interp(ed);
1390         if (ed->options & ED_SHDR)
1391                 elf_print_shdr(ed);
1392         if (ed->options & ED_DYN)
1393                 elf_print_dynamic(ed);
1394         if (ed->options & ED_REL)
1395                 elf_print_reloc(ed);
1396         if (ed->options & ED_GOT)
1397                 elf_print_got(ed);
1398         if (ed->options & ED_SYMTAB)
1399                 elf_print_symtabs(ed);
1400         if (ed->options & ED_SYMVER)
1401                 elf_print_symver(ed);
1402         if (ed->options & ED_NOTE)
1403                 elf_print_note(ed);
1404         if (ed->options & ED_HASH)
1405                 elf_print_hash(ed);
1406         if (ed->options & ED_CHECKSUM)
1407                 elf_print_checksum(ed);
1408
1409         unload_sections(ed);
1410 }
1411
1412 /*
1413  * Read the section headers from ELF object and store them in the
1414  * internal cache.
1415  */
1416 static void
1417 load_sections(struct elfdump *ed)
1418 {
1419         struct section  *s;
1420         const char      *name;
1421         Elf_Scn         *scn;
1422         GElf_Shdr        sh;
1423         size_t           shstrndx, ndx;
1424         int              elferr;
1425
1426         assert(ed->sl == NULL);
1427
1428         if (!elf_getshnum(ed->elf, &ed->shnum)) {
1429                 warnx("elf_getshnum failed: %s", elf_errmsg(-1));
1430                 return;
1431         }
1432         if (ed->shnum == 0)
1433                 return;
1434         if ((ed->sl = calloc(ed->shnum, sizeof(*ed->sl))) == NULL)
1435                 err(EXIT_FAILURE, "calloc failed");
1436         if (!elf_getshstrndx(ed->elf, &shstrndx)) {
1437                 warnx("elf_getshstrndx failed: %s", elf_errmsg(-1));
1438                 return;
1439         }
1440         if ((scn = elf_getscn(ed->elf, 0)) == NULL) {
1441                 warnx("elf_getscn failed: %s", elf_errmsg(-1));
1442                 return;
1443         }
1444         (void) elf_errno();
1445         do {
1446                 if (gelf_getshdr(scn, &sh) == NULL) {
1447                         warnx("gelf_getshdr failed: %s", elf_errmsg(-1));
1448                         (void) elf_errno();
1449                         continue;
1450                 }
1451                 if ((name = elf_strptr(ed->elf, shstrndx, sh.sh_name)) == NULL) {
1452                         (void) elf_errno();
1453                         name = "ERROR";
1454                 }
1455                 if ((ndx = elf_ndxscn(scn)) == SHN_UNDEF)
1456                         if ((elferr = elf_errno()) != 0) {
1457                                 warnx("elf_ndxscn failed: %s",
1458                                     elf_errmsg(elferr));
1459                                 continue;
1460                         }
1461                 if (ndx >= ed->shnum) {
1462                         warnx("section index of '%s' out of range", name);
1463                         continue;
1464                 }
1465                 s = &ed->sl[ndx];
1466                 s->name = name;
1467                 s->scn = scn;
1468                 s->off = sh.sh_offset;
1469                 s->sz = sh.sh_size;
1470                 s->entsize = sh.sh_entsize;
1471                 s->align = sh.sh_addralign;
1472                 s->type = sh.sh_type;
1473                 s->flags = sh.sh_flags;
1474                 s->addr = sh.sh_addr;
1475                 s->link = sh.sh_link;
1476                 s->info = sh.sh_info;
1477         } while ((scn = elf_nextscn(ed->elf, scn)) != NULL);
1478         elferr = elf_errno();
1479         if (elferr != 0)
1480                 warnx("elf_nextscn failed: %s", elf_errmsg(elferr));
1481 }
1482
1483 /*
1484  * Release section related resources.
1485  */
1486 static void
1487 unload_sections(struct elfdump *ed)
1488 {
1489         if (ed->sl != NULL) {
1490                 free(ed->sl);
1491                 ed->sl = NULL;
1492         }
1493 }
1494
1495 /*
1496  * Add a name to the '-N' name list.
1497  */
1498 static void
1499 add_name(struct elfdump *ed, const char *name)
1500 {
1501         struct spec_name *sn;
1502
1503         if (find_name(ed, name))
1504                 return;
1505         if ((sn = malloc(sizeof(*sn))) == NULL) {
1506                 warn("malloc failed");
1507                 return;
1508         }
1509         sn->name = name;
1510         STAILQ_INSERT_TAIL(&ed->snl, sn, sn_list);
1511 }
1512
1513 /*
1514  * Lookup a name in the '-N' name list.
1515  */
1516 static struct spec_name *
1517 find_name(struct elfdump *ed, const char *name)
1518 {
1519         struct spec_name *sn;
1520
1521         STAILQ_FOREACH(sn, &ed->snl, sn_list) {
1522                 if (!strcmp(sn->name, name))
1523                         return (sn);
1524         }
1525
1526         return (NULL);
1527 }
1528
1529 /*
1530  * Retrieve the name of a symbol using the section index of the symbol
1531  * table and the index of the symbol within that table.
1532  */
1533 static const char *
1534 get_symbol_name(struct elfdump *ed, int symtab, int i)
1535 {
1536         static char      sname[64];
1537         struct section  *s;
1538         const char      *name;
1539         GElf_Sym         sym;
1540         Elf_Data        *data;
1541         int              elferr;
1542
1543         s = &ed->sl[symtab];
1544         if (s->type != SHT_SYMTAB && s->type != SHT_DYNSYM)
1545                 return ("");
1546         (void) elf_errno();
1547         if ((data = elf_getdata(s->scn, NULL)) == NULL) {
1548                 elferr = elf_errno();
1549                 if (elferr != 0)
1550                         warnx("elf_getdata failed: %s", elf_errmsg(elferr));
1551                 return ("");
1552         }
1553         if (gelf_getsym(data, i, &sym) != &sym)
1554                 return ("");
1555         if (GELF_ST_TYPE(sym.st_info) == STT_SECTION) {
1556                 if (sym.st_shndx < ed->shnum) {
1557                         snprintf(sname, sizeof(sname), "%s (section)",
1558                             ed->sl[sym.st_shndx].name);
1559                         return (sname);
1560                 } else
1561                         return ("");
1562         }
1563         if ((name = elf_strptr(ed->elf, s->link, sym.st_name)) == NULL)
1564                 return ("");
1565
1566         return (name);
1567 }
1568
1569 /*
1570  * Retrieve a string using string table section index and the string offset.
1571  */
1572 static const char*
1573 get_string(struct elfdump *ed, int strtab, size_t off)
1574 {
1575         const char *name;
1576
1577         if ((name = elf_strptr(ed->elf, strtab, off)) == NULL)
1578                 return ("");
1579
1580         return (name);
1581 }
1582
1583 /*
1584  * Dump the ELF Executable Header.
1585  */
1586 static void
1587 elf_print_ehdr(struct elfdump *ed)
1588 {
1589
1590         if (!STAILQ_EMPTY(&ed->snl))
1591                 return;
1592
1593         if (ed->flags & SOLARIS_FMT) {
1594                 PRT("\nELF Header\n");
1595                 PRT("  ei_magic:   { %#x, %c, %c, %c }\n",
1596                     ed->ehdr.e_ident[0], ed->ehdr.e_ident[1],
1597                     ed->ehdr.e_ident[2], ed->ehdr.e_ident[3]);
1598                 PRT("  ei_class:   %-18s",
1599                     ei_classes[ed->ehdr.e_ident[EI_CLASS]]);
1600                 PRT("  ei_data:      %s\n", ei_data[ed->ehdr.e_ident[EI_DATA]]);
1601                 PRT("  e_machine:  %-18s", e_machines(ed->ehdr.e_machine));
1602                 PRT("  e_version:    %s\n", ei_versions[ed->ehdr.e_version]);
1603                 PRT("  e_type:     %s\n", e_types[ed->ehdr.e_type]);
1604                 PRT("  e_flags:    %18d\n", ed->ehdr.e_flags);
1605                 PRT("  e_entry:    %#18jx", (uintmax_t)ed->ehdr.e_entry);
1606                 PRT("  e_ehsize: %6d", ed->ehdr.e_ehsize);
1607                 PRT("  e_shstrndx:%5d\n", ed->ehdr.e_shstrndx);
1608                 PRT("  e_shoff:    %#18jx", (uintmax_t)ed->ehdr.e_shoff);
1609                 PRT("  e_shentsize: %3d", ed->ehdr.e_shentsize);
1610                 PRT("  e_shnum:   %5d\n", ed->ehdr.e_shnum);
1611                 PRT("  e_phoff:    %#18jx", (uintmax_t)ed->ehdr.e_phoff);
1612                 PRT("  e_phentsize: %3d", ed->ehdr.e_phentsize);
1613                 PRT("  e_phnum:   %5d\n", ed->ehdr.e_phnum);
1614         } else {
1615                 PRT("\nelf header:\n");
1616                 PRT("\n");
1617                 PRT("\te_ident: %s %s %s\n",
1618                     ei_classes[ed->ehdr.e_ident[EI_CLASS]],
1619                     ei_data[ed->ehdr.e_ident[EI_DATA]],
1620                     ei_abis[ed->ehdr.e_ident[EI_OSABI]]);
1621                 PRT("\te_type: %s\n", e_types[ed->ehdr.e_type]);
1622                 PRT("\te_machine: %s\n", e_machines(ed->ehdr.e_machine));
1623                 PRT("\te_version: %s\n", ei_versions[ed->ehdr.e_version]);
1624                 PRT("\te_entry: %#jx\n", (uintmax_t)ed->ehdr.e_entry);
1625                 PRT("\te_phoff: %ju\n", (uintmax_t)ed->ehdr.e_phoff);
1626                 PRT("\te_shoff: %ju\n", (uintmax_t) ed->ehdr.e_shoff);
1627                 PRT("\te_flags: %u\n", ed->ehdr.e_flags);
1628                 PRT("\te_ehsize: %u\n", ed->ehdr.e_ehsize);
1629                 PRT("\te_phentsize: %u\n", ed->ehdr.e_phentsize);
1630                 PRT("\te_phnum: %u\n", ed->ehdr.e_phnum);
1631                 PRT("\te_shentsize: %u\n", ed->ehdr.e_shentsize);
1632                 PRT("\te_shnum: %u\n", ed->ehdr.e_shnum);
1633                 PRT("\te_shstrndx: %u\n", ed->ehdr.e_shstrndx);
1634         }
1635 }
1636
1637 /*
1638  * Dump the ELF Program Header Table.
1639  */
1640 static void
1641 elf_print_phdr(struct elfdump *ed)
1642 {
1643         GElf_Phdr        ph;
1644         size_t           phnum;
1645         int              header, i;
1646
1647         if (elf_getphnum(ed->elf, &phnum) == 0) {
1648                 warnx("elf_getphnum failed: %s", elf_errmsg(-1));
1649                 return;
1650         }
1651         header = 0;
1652         for (i = 0; (u_int64_t) i < phnum; i++) {
1653                 if (gelf_getphdr(ed->elf, i, &ph) != &ph) {
1654                         warnx("elf_getphdr failed: %s", elf_errmsg(-1));
1655                         continue;
1656                 }
1657                 if (!STAILQ_EMPTY(&ed->snl) &&
1658                     find_name(ed, p_types[ph.p_type & 0x7]) == NULL)
1659                         continue;
1660                 if (ed->flags & SOLARIS_FMT) {
1661                         PRT("\nProgram Header[%d]:\n", i);
1662                         PRT("    p_vaddr:      %#-14jx", (uintmax_t)ph.p_vaddr);
1663                         PRT("  p_flags:    [ %s ]\n", p_flags[ph.p_flags]);
1664                         PRT("    p_paddr:      %#-14jx", (uintmax_t)ph.p_paddr);
1665                         PRT("  p_type:     [ %s ]\n", p_types[ph.p_type & 0x7]);
1666                         PRT("    p_filesz:     %#-14jx",
1667                             (uintmax_t)ph.p_filesz);
1668                         PRT("  p_memsz:    %#jx\n", (uintmax_t)ph.p_memsz);
1669                         PRT("    p_offset:     %#-14jx",
1670                             (uintmax_t)ph.p_offset);
1671                         PRT("  p_align:    %#jx\n", (uintmax_t)ph.p_align);
1672                 } else {
1673                         if (!header) {
1674                                 PRT("\nprogram header:\n");
1675                                 header = 1;
1676                         }
1677                         PRT("\n");
1678                         PRT("entry: %d\n", i);
1679                         PRT("\tp_type: %s\n", p_types[ph.p_type & 0x7]);
1680                         PRT("\tp_offset: %ju\n", (uintmax_t)ph.p_offset);
1681                         PRT("\tp_vaddr: %#jx\n", (uintmax_t)ph.p_vaddr);
1682                         PRT("\tp_paddr: %#jx\n", (uintmax_t)ph.p_paddr);
1683                         PRT("\tp_filesz: %ju\n", (uintmax_t)ph.p_filesz);
1684                         PRT("\tp_memsz: %ju\n", (uintmax_t)ph.p_memsz);
1685                         PRT("\tp_flags: %s\n", p_flags[ph.p_flags]);
1686                         PRT("\tp_align: %ju\n", (uintmax_t)ph.p_align);
1687                 }
1688         }
1689 }
1690
1691 /*
1692  * Dump the ELF Section Header Table.
1693  */
1694 static void
1695 elf_print_shdr(struct elfdump *ed)
1696 {
1697         struct section *s;
1698         int i;
1699
1700         if (!STAILQ_EMPTY(&ed->snl))
1701                 return;
1702
1703         if ((ed->flags & SOLARIS_FMT) == 0)
1704                 PRT("\nsection header:\n");
1705         for (i = 0; (size_t)i < ed->shnum; i++) {
1706                 s = &ed->sl[i];
1707                 if (ed->flags & SOLARIS_FMT) {
1708                         if (i == 0)
1709                                 continue;
1710                         PRT("\nSection Header[%d]:", i);
1711                         PRT("  sh_name: %s\n", s->name);
1712                         PRT("    sh_addr:      %#-14jx", (uintmax_t)s->addr);
1713                         if (s->flags != 0)
1714                                 PRT("  sh_flags:   [ %s ]\n", sh_flags(s->flags));
1715                         else
1716                                 PRT("  sh_flags:   0\n");
1717                         PRT("    sh_size:      %#-14jx", (uintmax_t)s->sz);
1718                         PRT("  sh_type:    [ %s ]\n",
1719                             sh_types(ed->ehdr.e_machine, s->type));
1720                         PRT("    sh_offset:    %#-14jx", (uintmax_t)s->off);
1721                         PRT("  sh_entsize: %#jx\n", (uintmax_t)s->entsize);
1722                         PRT("    sh_link:      %-14u", s->link);
1723                         PRT("  sh_info:    %u\n", s->info);
1724                         PRT("    sh_addralign: %#jx\n", (uintmax_t)s->align);
1725                 } else {
1726                         PRT("\n");
1727                         PRT("entry: %ju\n", (uintmax_t)i);
1728                         PRT("\tsh_name: %s\n", s->name);
1729                         PRT("\tsh_type: %s\n",
1730                             sh_types(ed->ehdr.e_machine, s->type));
1731                         PRT("\tsh_flags: %s\n", sh_flags(s->flags));
1732                         PRT("\tsh_addr: %#jx\n", (uintmax_t)s->addr);
1733                         PRT("\tsh_offset: %ju\n", (uintmax_t)s->off);
1734                         PRT("\tsh_size: %ju\n", (uintmax_t)s->sz);
1735                         PRT("\tsh_link: %u\n", s->link);
1736                         PRT("\tsh_info: %u\n", s->info);
1737                         PRT("\tsh_addralign: %ju\n", (uintmax_t)s->align);
1738                         PRT("\tsh_entsize: %ju\n", (uintmax_t)s->entsize);
1739                 }
1740         }
1741 }
1742
1743 /*
1744  * Return number of entries in the given section. We'd prefer ent_count be a
1745  * size_t, but libelf APIs already use int for section indices.
1746  */
1747 static int
1748 get_ent_count(const struct section *s, int *ent_count)
1749 {
1750         if (s->entsize == 0) {
1751                 warnx("section %s has entry size 0", s->name);
1752                 return (0);
1753         } else if (s->sz / s->entsize > INT_MAX) {
1754                 warnx("section %s has invalid section count", s->name);
1755                 return (0);
1756         }
1757         *ent_count = (int)(s->sz / s->entsize);
1758         return (1);
1759 }
1760
1761 /*
1762  * Retrieve the content of the corresponding SHT_SUNW_versym section for
1763  * a symbol table section.
1764  */
1765 static void
1766 get_versym(struct elfdump *ed, int i, uint16_t **vs, int *nvs)
1767 {
1768         struct section  *s;
1769         Elf_Data        *data;
1770         int              j, elferr;
1771
1772         s = NULL;
1773         for (j = 0; (size_t)j < ed->shnum; j++) {
1774                 s = &ed->sl[j];
1775                 if (s->type == SHT_SUNW_versym && s->link == (uint32_t)i)
1776                         break;
1777         }
1778         if ((size_t)j >= ed->shnum) {
1779                 *vs = NULL;
1780                 return;
1781         }
1782         (void) elf_errno();
1783         if ((data = elf_getdata(s->scn, NULL)) == NULL) {
1784                 elferr = elf_errno();
1785                 if (elferr != 0)
1786                         warnx("elf_getdata failed: %s", elf_errmsg(elferr));
1787                 *vs = NULL;
1788                 return;
1789         }
1790
1791         *vs = data->d_buf;
1792         assert(data->d_size == s->sz);
1793         if (!get_ent_count(s, nvs))
1794                 *nvs = 0;
1795 }
1796
1797 /*
1798  * Dump the symbol table section.
1799  */
1800 static void
1801 elf_print_symtab(struct elfdump *ed, int i)
1802 {
1803         struct section  *s;
1804         const char      *name;
1805         uint16_t        *vs;
1806         char             idx[10];
1807         Elf_Data        *data;
1808         GElf_Sym         sym;
1809         int              len, j, elferr, nvs;
1810
1811         s = &ed->sl[i];
1812         if (ed->flags & SOLARIS_FMT)
1813                 PRT("\nSymbol Table Section:  %s\n", s->name);
1814         else
1815                 PRT("\nsymbol table (%s):\n", s->name);
1816         (void) elf_errno();
1817         if ((data = elf_getdata(s->scn, NULL)) == NULL) {
1818                 elferr = elf_errno();
1819                 if (elferr != 0)
1820                         warnx("elf_getdata failed: %s", elf_errmsg(elferr));
1821                 return;
1822         }
1823         vs = NULL;
1824         nvs = 0;
1825         assert(data->d_size == s->sz);
1826         if (!get_ent_count(s, &len))
1827                 return;
1828         if (ed->flags & SOLARIS_FMT) {
1829                 if (ed->ec == ELFCLASS32)
1830                         PRT("     index    value       ");
1831                 else
1832                         PRT("     index        value           ");
1833                 PRT("size     type bind oth ver shndx       name\n");
1834                 get_versym(ed, i, &vs, &nvs);
1835                 if (vs != NULL && nvs != len) {
1836                         warnx("#symbol not equal to #versym");
1837                         vs = NULL;
1838                 }
1839         }
1840         for (j = 0; j < len; j++) {
1841                 if (gelf_getsym(data, j, &sym) != &sym) {
1842                         warnx("gelf_getsym failed: %s", elf_errmsg(-1));
1843                         continue;
1844                 }
1845                 name = get_string(ed, s->link, sym.st_name);
1846                 if (ed->flags & SOLARIS_FMT) {
1847                         snprintf(idx, sizeof(idx), "[%d]", j);
1848                         if (ed->ec == ELFCLASS32)
1849                                 PRT("%10s  ", idx);
1850                         else
1851                                 PRT("%10s      ", idx);
1852                         PRT("0x%8.8jx ", (uintmax_t)sym.st_value);
1853                         if (ed->ec == ELFCLASS32)
1854                                 PRT("0x%8.8jx  ", (uintmax_t)sym.st_size);
1855                         else
1856                                 PRT("0x%12.12jx  ", (uintmax_t)sym.st_size);
1857                         PRT("%s ", st_type_S(GELF_ST_TYPE(sym.st_info)));
1858                         PRT("%s  ", st_bindings_S(GELF_ST_BIND(sym.st_info)));
1859                         PRT("%c  ", st_others[sym.st_other]);
1860                         PRT("%3u ", (vs == NULL ? 0 : vs[j]));
1861                         PRT("%-11.11s ", sh_name(ed, sym.st_shndx));
1862                         PRT("%s\n", name);
1863                 } else {
1864                         PRT("\nentry: %d\n", j);
1865                         PRT("\tst_name: %s\n", name);
1866                         PRT("\tst_value: %#jx\n", (uintmax_t)sym.st_value);
1867                         PRT("\tst_size: %ju\n", (uintmax_t)sym.st_size);
1868                         PRT("\tst_info: %s %s\n",
1869                             st_type(ed->ehdr.e_machine,
1870                             GELF_ST_TYPE(sym.st_info)),
1871                             st_bindings(GELF_ST_BIND(sym.st_info)));
1872                         PRT("\tst_shndx: %ju\n", (uintmax_t)sym.st_shndx);
1873                 }
1874         }
1875 }
1876
1877 /*
1878  * Dump the symbol tables. (.dynsym and .symtab)
1879  */
1880 static void
1881 elf_print_symtabs(struct elfdump *ed)
1882 {
1883         int i;
1884
1885         for (i = 0; (size_t)i < ed->shnum; i++)
1886                 if ((ed->sl[i].type == SHT_SYMTAB ||
1887                     ed->sl[i].type == SHT_DYNSYM) &&
1888                     (STAILQ_EMPTY(&ed->snl) || find_name(ed, ed->sl[i].name)))
1889                         elf_print_symtab(ed, i);
1890 }
1891
1892 /*
1893  * Dump the content of .dynamic section.
1894  */
1895 static void
1896 elf_print_dynamic(struct elfdump *ed)
1897 {
1898         struct section  *s;
1899         const char      *name;
1900         char             idx[10];
1901         Elf_Data        *data;
1902         GElf_Dyn         dyn;
1903         int              elferr, i, len;
1904
1905         s = NULL;
1906         for (i = 0; (size_t)i < ed->shnum; i++) {
1907                 s = &ed->sl[i];
1908                 if (s->type == SHT_DYNAMIC &&
1909                     (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name)))
1910                         break;
1911         }
1912         if ((size_t)i >= ed->shnum)
1913                 return;
1914
1915         if (ed->flags & SOLARIS_FMT) {
1916                 PRT("Dynamic Section:  %s\n", s->name);
1917                 PRT("     index  tag               value\n");
1918         } else
1919                 PRT("\ndynamic:\n");
1920         (void) elf_errno();
1921         if ((data = elf_getdata(s->scn, NULL)) == NULL) {
1922                 elferr = elf_errno();
1923                 if (elferr != 0)
1924                         warnx("elf_getdata failed: %s", elf_errmsg(elferr));
1925                 return;
1926         }
1927         assert(data->d_size == s->sz);
1928         if (!get_ent_count(s, &len))
1929                 return;
1930         for (i = 0; i < len; i++) {
1931                 if (gelf_getdyn(data, i, &dyn) != &dyn) {
1932                         warnx("gelf_getdyn failed: %s", elf_errmsg(-1));
1933                         continue;
1934                 }
1935
1936                 if (ed->flags & SOLARIS_FMT) {
1937                         snprintf(idx, sizeof(idx), "[%d]", i);
1938                         PRT("%10s  %-16s ", idx, d_tags(dyn.d_tag));
1939                 } else {
1940                         PRT("\n");
1941                         PRT("entry: %d\n", i);
1942                         PRT("\td_tag: %s\n", d_tags(dyn.d_tag));
1943                 }
1944                 switch(dyn.d_tag) {
1945                 case DT_NEEDED:
1946                 case DT_SONAME:
1947                 case DT_RPATH:
1948                         if ((name = elf_strptr(ed->elf, s->link,
1949                                     dyn.d_un.d_val)) == NULL)
1950                                 name = "";
1951                         if (ed->flags & SOLARIS_FMT)
1952                                 PRT("%#-16jx %s\n", (uintmax_t)dyn.d_un.d_val,
1953                                     name);
1954                         else
1955                                 PRT("\td_val: %s\n", name);
1956                         break;
1957                 case DT_PLTRELSZ:
1958                 case DT_RELA:
1959                 case DT_RELASZ:
1960                 case DT_RELAENT:
1961                 case DT_RELACOUNT:
1962                 case DT_STRSZ:
1963                 case DT_SYMENT:
1964                 case DT_RELSZ:
1965                 case DT_RELENT:
1966                 case DT_PLTREL:
1967                 case DT_VERDEF:
1968                 case DT_VERDEFNUM:
1969                 case DT_VERNEED:
1970                 case DT_VERNEEDNUM:
1971                 case DT_VERSYM:
1972                         if (ed->flags & SOLARIS_FMT)
1973                                 PRT("%#jx\n", (uintmax_t)dyn.d_un.d_val);
1974                         else
1975                                 PRT("\td_val: %ju\n",
1976                                     (uintmax_t)dyn.d_un.d_val);
1977                         break;
1978                 case DT_PLTGOT:
1979                 case DT_HASH:
1980                 case DT_GNU_HASH:
1981                 case DT_STRTAB:
1982                 case DT_SYMTAB:
1983                 case DT_INIT:
1984                 case DT_FINI:
1985                 case DT_REL:
1986                 case DT_JMPREL:
1987                 case DT_DEBUG:
1988                         if (ed->flags & SOLARIS_FMT)
1989                                 PRT("%#jx\n", (uintmax_t)dyn.d_un.d_ptr);
1990                         else
1991                                 PRT("\td_ptr: %#jx\n",
1992                                     (uintmax_t)dyn.d_un.d_ptr);
1993                         break;
1994                 case DT_NULL:
1995                 case DT_SYMBOLIC:
1996                 case DT_TEXTREL:
1997                 default:
1998                         if (ed->flags & SOLARIS_FMT)
1999                                 PRT("\n");
2000                         break;
2001                 }
2002         }
2003 }
2004
2005 /*
2006  * Dump a .rel/.rela section entry.
2007  */
2008 static void
2009 elf_print_rel_entry(struct elfdump *ed, struct section *s, int j,
2010     struct rel_entry *r)
2011 {
2012
2013         if (ed->flags & SOLARIS_FMT) {
2014                 PRT("        %-23s ", r_type(ed->ehdr.e_machine,
2015                         GELF_R_TYPE(r->u_r.rel.r_info)));
2016                 PRT("%#12jx ", (uintmax_t)r->u_r.rel.r_offset);
2017                 if (r->type == SHT_RELA)
2018                         PRT("%10jd  ", (intmax_t)r->u_r.rela.r_addend);
2019                 else
2020                         PRT("    ");
2021                 PRT("%-14s ", s->name);
2022                 PRT("%s\n", r->symn);
2023         } else {
2024                 PRT("\n");
2025                 PRT("entry: %d\n", j);
2026                 PRT("\tr_offset: %#jx\n", (uintmax_t)r->u_r.rel.r_offset);
2027                 if (ed->ec == ELFCLASS32)
2028                         PRT("\tr_info: %#jx\n", (uintmax_t)
2029                             ELF32_R_INFO(ELF64_R_SYM(r->u_r.rel.r_info),
2030                             ELF64_R_TYPE(r->u_r.rel.r_info)));
2031                 else
2032                         PRT("\tr_info: %#jx\n", (uintmax_t)r->u_r.rel.r_info);
2033                 if (r->type == SHT_RELA)
2034                         PRT("\tr_addend: %jd\n",
2035                             (intmax_t)r->u_r.rela.r_addend);
2036         }
2037 }
2038
2039 /*
2040  * Dump a relocation section of type SHT_RELA.
2041  */
2042 static void
2043 elf_print_rela(struct elfdump *ed, struct section *s, Elf_Data *data)
2044 {
2045         struct rel_entry        r;
2046         int                     j, len;
2047
2048         if (ed->flags & SOLARIS_FMT) {
2049                 PRT("\nRelocation Section:  %s\n", s->name);
2050                 PRT("        type                          offset     "
2051                     "addend  section        with respect to\n");
2052         } else
2053                 PRT("\nrelocation with addend (%s):\n", s->name);
2054         r.type = SHT_RELA;
2055         assert(data->d_size == s->sz);
2056         if (!get_ent_count(s, &len))
2057                 return;
2058         for (j = 0; j < len; j++) {
2059                 if (gelf_getrela(data, j, &r.u_r.rela) != &r.u_r.rela) {
2060                         warnx("gelf_getrela failed: %s",
2061                             elf_errmsg(-1));
2062                         continue;
2063                 }
2064                 r.symn = get_symbol_name(ed, s->link,
2065                     GELF_R_SYM(r.u_r.rela.r_info));
2066                 elf_print_rel_entry(ed, s, j, &r);
2067         }
2068 }
2069
2070 /*
2071  * Dump a relocation section of type SHT_REL.
2072  */
2073 static void
2074 elf_print_rel(struct elfdump *ed, struct section *s, Elf_Data *data)
2075 {
2076         struct rel_entry        r;
2077         int                     j, len;
2078
2079         if (ed->flags & SOLARIS_FMT) {
2080                 PRT("\nRelocation Section:  %s\n", s->name);
2081                 PRT("        type                          offset     "
2082                     "section        with respect to\n");
2083         } else
2084                 PRT("\nrelocation (%s):\n", s->name);
2085         r.type = SHT_REL;
2086         assert(data->d_size == s->sz);
2087         if (!get_ent_count(s, &len))
2088                 return;
2089         for (j = 0; j < len; j++) {
2090                 if (gelf_getrel(data, j, &r.u_r.rel) != &r.u_r.rel) {
2091                         warnx("gelf_getrel failed: %s", elf_errmsg(-1));
2092                         continue;
2093                 }
2094                 r.symn = get_symbol_name(ed, s->link,
2095                     GELF_R_SYM(r.u_r.rel.r_info));
2096                 elf_print_rel_entry(ed, s, j, &r);
2097         }
2098 }
2099
2100 /*
2101  * Dump relocation sections.
2102  */
2103 static void
2104 elf_print_reloc(struct elfdump *ed)
2105 {
2106         struct section  *s;
2107         Elf_Data        *data;
2108         int              i, elferr;
2109
2110         for (i = 0; (size_t)i < ed->shnum; i++) {
2111                 s = &ed->sl[i];
2112                 if ((s->type == SHT_REL || s->type == SHT_RELA) &&
2113                     (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) {
2114                         (void) elf_errno();
2115                         if ((data = elf_getdata(s->scn, NULL)) == NULL) {
2116                                 elferr = elf_errno();
2117                                 if (elferr != 0)
2118                                         warnx("elf_getdata failed: %s",
2119                                             elf_errmsg(elferr));
2120                                 continue;
2121                         }
2122                         if (s->type == SHT_REL)
2123                                 elf_print_rel(ed, s, data);
2124                         else
2125                                 elf_print_rela(ed, s, data);
2126                 }
2127         }
2128 }
2129
2130 /*
2131  * Dump the content of PT_INTERP segment.
2132  */
2133 static void
2134 elf_print_interp(struct elfdump *ed)
2135 {
2136         const char *s;
2137         GElf_Phdr phdr;
2138         size_t phnum;
2139         int i;
2140
2141         if (!STAILQ_EMPTY(&ed->snl) && find_name(ed, "PT_INTERP") == NULL)
2142                 return;
2143
2144         if ((s = elf_rawfile(ed->elf, NULL)) == NULL) {
2145                 warnx("elf_rawfile failed: %s", elf_errmsg(-1));
2146                 return;
2147         }
2148         if (!elf_getphnum(ed->elf, &phnum)) {
2149                 warnx("elf_getphnum failed: %s", elf_errmsg(-1));
2150                 return;
2151         }
2152         for (i = 0; (size_t)i < phnum; i++) {
2153                 if (gelf_getphdr(ed->elf, i, &phdr) != &phdr) {
2154                         warnx("elf_getphdr failed: %s", elf_errmsg(-1));
2155                         continue;
2156                 }
2157                 if (phdr.p_type == PT_INTERP) {
2158                         PRT("\ninterp:\n");
2159                         PRT("\t%s\n", s + phdr.p_offset);
2160                 }
2161         }
2162 }
2163
2164 /*
2165  * Search the relocation sections for entries refering to the .got section.
2166  */
2167 static void
2168 find_gotrel(struct elfdump *ed, struct section *gs, struct rel_entry *got)
2169 {
2170         struct section          *s;
2171         struct rel_entry         r;
2172         Elf_Data                *data;
2173         int                      elferr, i, j, k, len;
2174
2175         for(i = 0; (size_t)i < ed->shnum; i++) {
2176                 s = &ed->sl[i];
2177                 if (s->type != SHT_REL && s->type != SHT_RELA)
2178                         continue;
2179                 (void) elf_errno();
2180                 if ((data = elf_getdata(s->scn, NULL)) == NULL) {
2181                         elferr = elf_errno();
2182                         if (elferr != 0)
2183                                 warnx("elf_getdata failed: %s",
2184                                     elf_errmsg(elferr));
2185                         return;
2186                 }
2187                 memset(&r, 0, sizeof(struct rel_entry));
2188                 r.type = s->type;
2189                 assert(data->d_size == s->sz);
2190                 if (!get_ent_count(s, &len))
2191                         return;
2192                 for (j = 0; j < len; j++) {
2193                         if (s->type == SHT_REL) {
2194                                 if (gelf_getrel(data, j, &r.u_r.rel) !=
2195                                     &r.u_r.rel) {
2196                                         warnx("gelf_getrel failed: %s",
2197                                             elf_errmsg(-1));
2198                                         continue;
2199                                 }
2200                         } else {
2201                                 if (gelf_getrela(data, j, &r.u_r.rela) !=
2202                                     &r.u_r.rela) {
2203                                         warnx("gelf_getrel failed: %s",
2204                                             elf_errmsg(-1));
2205                                         continue;
2206                                 }
2207                         }
2208                         if (r.u_r.rel.r_offset >= gs->addr &&
2209                             r.u_r.rel.r_offset < gs->addr + gs->sz) {
2210                                 r.symn = get_symbol_name(ed, s->link,
2211                                     GELF_R_SYM(r.u_r.rel.r_info));
2212                                 k = (r.u_r.rel.r_offset - gs->addr) /
2213                                     gs->entsize;
2214                                 memcpy(&got[k], &r, sizeof(struct rel_entry));
2215                         }
2216                 }
2217         }
2218 }
2219
2220 static void
2221 elf_print_got_section(struct elfdump *ed, struct section *s)
2222 {
2223         struct rel_entry        *got;
2224         Elf_Data                *data, dst;
2225         int                      elferr, i, len;
2226
2227         if (s->entsize == 0) {
2228                 /* XXX IA64 GOT section generated by gcc has entry size 0. */
2229                 if (s->align != 0)
2230                         s->entsize = s->align;
2231                 else
2232                         return;
2233         }
2234
2235         if (!get_ent_count(s, &len))
2236                 return;
2237         if (ed->flags & SOLARIS_FMT)
2238                 PRT("\nGlobal Offset Table Section:  %s  (%d entries)\n",
2239                     s->name, len);
2240         else
2241                 PRT("\nglobal offset table: %s\n", s->name);
2242         (void) elf_errno();
2243         if ((data = elf_getdata(s->scn, NULL)) == NULL) {
2244                 elferr = elf_errno();
2245                 if (elferr != 0)
2246                         warnx("elf_getdata failed: %s", elf_errmsg(elferr));
2247                 return;
2248         }
2249
2250         /*
2251          * GOT section has section type SHT_PROGBITS, thus libelf treats it as
2252          * byte stream and will not perfrom any translation on it. As a result,
2253          * an exlicit call to gelf_xlatetom is needed here. Depends on arch,
2254          * GOT section should be translated to either WORD or XWORD.
2255          */
2256         if (ed->ec == ELFCLASS32)
2257                 data->d_type = ELF_T_WORD;
2258         else
2259                 data->d_type = ELF_T_XWORD;
2260         memcpy(&dst, data, sizeof(Elf_Data));
2261         if (gelf_xlatetom(ed->elf, &dst, data, ed->ehdr.e_ident[EI_DATA]) !=
2262             &dst) {
2263                 warnx("gelf_xlatetom failed: %s", elf_errmsg(-1));
2264                 return;
2265         }
2266         assert(dst.d_size == s->sz);
2267         if (ed->flags & SOLARIS_FMT) {
2268                 /*
2269                  * In verbose/Solaris mode, we search the relocation sections
2270                  * and try to find the corresponding reloc entry for each GOT
2271                  * section entry.
2272                  */
2273                 if ((got = calloc(len, sizeof(struct rel_entry))) == NULL)
2274                         err(EXIT_FAILURE, "calloc failed");
2275                 find_gotrel(ed, s, got);
2276                 if (ed->ec == ELFCLASS32) {
2277                         PRT(" ndx     addr      value    reloc              ");
2278                         PRT("addend   symbol\n");
2279                 } else {
2280                         PRT(" ndx     addr              value             ");
2281                         PRT("reloc              addend       symbol\n");
2282                 }
2283                 for(i = 0; i < len; i++) {
2284                         PRT("[%5.5d]  ", i);
2285                         if (ed->ec == ELFCLASS32) {
2286                                 PRT("%-8.8jx  ",
2287                                     (uintmax_t) (s->addr + i * s->entsize));
2288                                 PRT("%-8.8x ", *((uint32_t *)dst.d_buf + i));
2289                         } else {
2290                                 PRT("%-16.16jx  ",
2291                                     (uintmax_t) (s->addr + i * s->entsize));
2292                                 PRT("%-16.16jx  ",
2293                                     (uintmax_t) *((uint64_t *)dst.d_buf + i));
2294                         }
2295                         PRT("%-18s ", r_type(ed->ehdr.e_machine,
2296                                 GELF_R_TYPE(got[i].u_r.rel.r_info)));
2297                         if (ed->ec == ELFCLASS32)
2298                                 PRT("%-8.8jd ",
2299                                     (intmax_t)got[i].u_r.rela.r_addend);
2300                         else
2301                                 PRT("%-12.12jd ",
2302                                     (intmax_t)got[i].u_r.rela.r_addend);
2303                         if (got[i].symn == NULL)
2304                                 got[i].symn = "";
2305                         PRT("%s\n", got[i].symn);
2306                 }
2307                 free(got);
2308         } else {
2309                 for(i = 0; i < len; i++) {
2310                         PRT("\nentry: %d\n", i);
2311                         if (ed->ec == ELFCLASS32)
2312                                 PRT("\t%#x\n", *((uint32_t *)dst.d_buf + i));
2313                         else
2314                                 PRT("\t%#jx\n",
2315                                     (uintmax_t) *((uint64_t *)dst.d_buf + i));
2316                 }
2317         }
2318 }
2319
2320 /*
2321  * Dump the content of Global Offset Table section.
2322  */
2323 static void
2324 elf_print_got(struct elfdump *ed)
2325 {
2326         struct section  *s;
2327         int              i;
2328
2329         if (!STAILQ_EMPTY(&ed->snl))
2330                 return;
2331
2332         s = NULL;
2333         for (i = 0; (size_t)i < ed->shnum; i++) {
2334                 s = &ed->sl[i];
2335                 if (s->name && !strncmp(s->name, ".got", 4) &&
2336                     (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name)))
2337                         elf_print_got_section(ed, s);
2338         }
2339 }
2340
2341 /*
2342  * Dump the content of .note.ABI-tag section.
2343  */
2344 static void
2345 elf_print_note(struct elfdump *ed)
2346 {
2347         struct section  *s;
2348         Elf_Data        *data;
2349         Elf_Note        *en;
2350         uint32_t         namesz;
2351         uint32_t         descsz;
2352         uint32_t         desc;
2353         size_t           count;
2354         int              elferr, i;
2355         char            *src, idx[10];
2356
2357         s = NULL;
2358         for (i = 0; (size_t)i < ed->shnum; i++) {
2359                 s = &ed->sl[i];
2360                 if (s->type == SHT_NOTE && s->name &&
2361                     !strcmp(s->name, ".note.ABI-tag") &&
2362                     (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name)))
2363                         break;
2364         }
2365         if ((size_t)i >= ed->shnum)
2366                 return;
2367         if (ed->flags & SOLARIS_FMT)
2368                 PRT("\nNote Section:  %s\n", s->name);
2369         else
2370                 PRT("\nnote (%s):\n", s->name);
2371         (void) elf_errno();
2372         if ((data = elf_getdata(s->scn, NULL)) == NULL) {
2373                 elferr = elf_errno();
2374                 if (elferr != 0)
2375                         warnx("elf_getdata failed: %s", elf_errmsg(elferr));
2376                 return;
2377         }
2378         src = data->d_buf;
2379         count = data->d_size;
2380         while (count > sizeof(Elf_Note)) {
2381                 en = (Elf_Note *) (uintptr_t) src;
2382                 namesz = en->n_namesz;
2383                 descsz = en->n_descsz;
2384                 src += sizeof(Elf_Note);
2385                 count -= sizeof(Elf_Note);
2386                 if (ed->flags & SOLARIS_FMT) {
2387                         PRT("\n    type   %#x\n", en->n_type);
2388                         PRT("    namesz %#x:\n", en->n_namesz);
2389                         PRT("%s\n", src);
2390                 } else
2391                         PRT("\t%s ", src);
2392                 src += roundup2(namesz, 4);
2393                 count -= roundup2(namesz, 4);
2394
2395                 /*
2396                  * Note that we dump the whole desc part if we're in
2397                  * "Solaris mode", while in the normal mode, we only look
2398                  * at the first 4 bytes (a 32bit word) of the desc, i.e,
2399                  * we assume that it's always a FreeBSD version number.
2400                  */
2401                 if (ed->flags & SOLARIS_FMT) {
2402                         PRT("    descsz %#x:", en->n_descsz);
2403                         for (i = 0; (uint32_t)i < descsz; i++) {
2404                                 if ((i & 0xF) == 0) {
2405                                         snprintf(idx, sizeof(idx), "desc[%d]",
2406                                             i);
2407                                         PRT("\n      %-9s", idx);
2408                                 } else if ((i & 0x3) == 0)
2409                                         PRT("  ");
2410                                 PRT(" %2.2x", src[i]);
2411                         }
2412                         PRT("\n");
2413                 } else {
2414                         if (ed->ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
2415                                 desc = be32dec(src);
2416                         else
2417                                 desc = le32dec(src);
2418                         PRT("%d\n", desc);
2419                 }
2420                 src += roundup2(descsz, 4);
2421                 count -= roundup2(descsz, 4);
2422         }
2423 }
2424
2425 /*
2426  * Dump a hash table.
2427  */
2428 static void
2429 elf_print_svr4_hash(struct elfdump *ed, struct section *s)
2430 {
2431         Elf_Data        *data;
2432         uint32_t        *buf;
2433         uint32_t        *bucket, *chain;
2434         uint32_t         nbucket, nchain;
2435         uint32_t        *bl, *c, maxl, total;
2436         int              i, j, first, elferr;
2437         char             idx[10];
2438
2439         if (ed->flags & SOLARIS_FMT)
2440                 PRT("\nHash Section:  %s\n", s->name);
2441         else
2442                 PRT("\nhash table (%s):\n", s->name);
2443         (void) elf_errno();
2444         if ((data = elf_getdata(s->scn, NULL)) == NULL) {
2445                 elferr = elf_errno();
2446                 if (elferr != 0)
2447                         warnx("elf_getdata failed: %s",
2448                             elf_errmsg(elferr));
2449                 return;
2450         }
2451         if (data->d_size < 2 * sizeof(uint32_t)) {
2452                 warnx(".hash section too small");
2453                 return;
2454         }
2455         buf = data->d_buf;
2456         nbucket = buf[0];
2457         nchain = buf[1];
2458         if (nbucket <= 0 || nchain <= 0) {
2459                 warnx("Malformed .hash section");
2460                 return;
2461         }
2462         if (data->d_size != (nbucket + nchain + 2) * sizeof(uint32_t)) {
2463                 warnx("Malformed .hash section");
2464                 return;
2465         }
2466         bucket = &buf[2];
2467         chain = &buf[2 + nbucket];
2468
2469         if (ed->flags & SOLARIS_FMT) {
2470                 maxl = 0;
2471                 if ((bl = calloc(nbucket, sizeof(*bl))) == NULL)
2472                         err(EXIT_FAILURE, "calloc failed");
2473                 for (i = 0; (uint32_t)i < nbucket; i++)
2474                         for (j = bucket[i]; j > 0 && (uint32_t)j < nchain;
2475                              j = chain[j])
2476                                 if (++bl[i] > maxl)
2477                                         maxl = bl[i];
2478                 if ((c = calloc(maxl + 1, sizeof(*c))) == NULL)
2479                         err(EXIT_FAILURE, "calloc failed");
2480                 for (i = 0; (uint32_t)i < nbucket; i++)
2481                         c[bl[i]]++;
2482                 PRT("    bucket    symndx    name\n");
2483                 for (i = 0; (uint32_t)i < nbucket; i++) {
2484                         first = 1;
2485                         for (j = bucket[i]; j > 0 && (uint32_t)j < nchain;
2486                              j = chain[j]) {
2487                                 if (first) {
2488                                         PRT("%10d  ", i);
2489                                         first = 0;
2490                                 } else
2491                                         PRT("            ");
2492                                 snprintf(idx, sizeof(idx), "[%d]", j);
2493                                 PRT("%-10s  ", idx);
2494                                 PRT("%s\n", get_symbol_name(ed, s->link, j));
2495                         }
2496                 }
2497                 PRT("\n");
2498                 total = 0;
2499                 for (i = 0; (uint32_t)i <= maxl; i++) {
2500                         total += c[i] * i;
2501                         PRT("%10u  buckets contain %8d symbols\n", c[i], i);
2502                 }
2503                 PRT("%10u  buckets         %8u symbols (globals)\n", nbucket,
2504                     total);
2505         } else {
2506                 PRT("\nnbucket: %u\n", nbucket);
2507                 PRT("nchain: %u\n\n", nchain);
2508                 for (i = 0; (uint32_t)i < nbucket; i++)
2509                         PRT("bucket[%d]:\n\t%u\n\n", i, bucket[i]);
2510                 for (i = 0; (uint32_t)i < nchain; i++)
2511                         PRT("chain[%d]:\n\t%u\n\n", i, chain[i]);
2512         }
2513 }
2514
2515 /*
2516  * Dump a 64bit hash table.
2517  */
2518 static void
2519 elf_print_svr4_hash64(struct elfdump *ed, struct section *s)
2520 {
2521         Elf_Data        *data, dst;
2522         uint64_t        *buf;
2523         uint64_t        *bucket, *chain;
2524         uint64_t         nbucket, nchain;
2525         uint64_t        *bl, *c, maxl, total;
2526         int              i, j, elferr, first;
2527         char             idx[10];
2528
2529         if (ed->flags & SOLARIS_FMT)
2530                 PRT("\nHash Section:  %s\n", s->name);
2531         else
2532                 PRT("\nhash table (%s):\n", s->name);
2533
2534         /*
2535          * ALPHA uses 64-bit hash entries. Since libelf assumes that
2536          * .hash section contains only 32-bit entry, an explicit
2537          * gelf_xlatetom is needed here.
2538          */
2539         (void) elf_errno();
2540         if ((data = elf_rawdata(s->scn, NULL)) == NULL) {
2541                 elferr = elf_errno();
2542                 if (elferr != 0)
2543                         warnx("elf_rawdata failed: %s",
2544                             elf_errmsg(elferr));
2545                 return;
2546         }
2547         data->d_type = ELF_T_XWORD;
2548         memcpy(&dst, data, sizeof(Elf_Data));
2549         if (gelf_xlatetom(ed->elf, &dst, data,
2550                 ed->ehdr.e_ident[EI_DATA]) != &dst) {
2551                 warnx("gelf_xlatetom failed: %s", elf_errmsg(-1));
2552                 return;
2553         }
2554         if (dst.d_size < 2 * sizeof(uint64_t)) {
2555                 warnx(".hash section too small");
2556                 return;
2557         }
2558         buf = dst.d_buf;
2559         nbucket = buf[0];
2560         nchain = buf[1];
2561         if (nbucket <= 0 || nchain <= 0) {
2562                 warnx("Malformed .hash section");
2563                 return;
2564         }
2565         if (dst.d_size != (nbucket + nchain + 2) * sizeof(uint64_t)) {
2566                 warnx("Malformed .hash section");
2567                 return;
2568         }
2569         bucket = &buf[2];
2570         chain = &buf[2 + nbucket];
2571
2572         if (ed->flags & SOLARIS_FMT) {
2573                 maxl = 0;
2574                 if ((bl = calloc(nbucket, sizeof(*bl))) == NULL)
2575                         err(EXIT_FAILURE, "calloc failed");
2576                 for (i = 0; (uint64_t)i < nbucket; i++)
2577                         for (j = bucket[i]; j > 0 && (uint64_t)j < nchain;
2578                              j = chain[j])
2579                                 if (++bl[i] > maxl)
2580                                         maxl = bl[i];
2581                 if ((c = calloc(maxl + 1, sizeof(*c))) == NULL)
2582                         err(EXIT_FAILURE, "calloc failed");
2583                 for (i = 0; (uint64_t)i < nbucket; i++)
2584                         c[bl[i]]++;
2585                 PRT("    bucket    symndx    name\n");
2586                 for (i = 0; (uint64_t)i < nbucket; i++) {
2587                         first = 1;
2588                         for (j = bucket[i]; j > 0 && (uint64_t)j < nchain;
2589                              j = chain[j]) {
2590                                 if (first) {
2591                                         PRT("%10d  ", i);
2592                                         first = 0;
2593                                 } else
2594                                         PRT("            ");
2595                                 snprintf(idx, sizeof(idx), "[%d]", j);
2596                                 PRT("%-10s  ", idx);
2597                                 PRT("%s\n", get_symbol_name(ed, s->link, j));
2598                         }
2599                 }
2600                 PRT("\n");
2601                 total = 0;
2602                 for (i = 0; (uint64_t)i <= maxl; i++) {
2603                         total += c[i] * i;
2604                         PRT("%10ju  buckets contain %8d symbols\n",
2605                             (uintmax_t)c[i], i);
2606                 }
2607                 PRT("%10ju  buckets         %8ju symbols (globals)\n",
2608                     (uintmax_t)nbucket, (uintmax_t)total);
2609         } else {
2610                 PRT("\nnbucket: %ju\n", (uintmax_t)nbucket);
2611                 PRT("nchain: %ju\n\n", (uintmax_t)nchain);
2612                 for (i = 0; (uint64_t)i < nbucket; i++)
2613                         PRT("bucket[%d]:\n\t%ju\n\n", i, (uintmax_t)bucket[i]);
2614                 for (i = 0; (uint64_t)i < nchain; i++)
2615                         PRT("chain[%d]:\n\t%ju\n\n", i, (uintmax_t)chain[i]);
2616         }
2617
2618 }
2619
2620 /*
2621  * Dump a GNU hash table.
2622  */
2623 static void
2624 elf_print_gnu_hash(struct elfdump *ed, struct section *s)
2625 {
2626         struct section  *ds;
2627         Elf_Data        *data;
2628         uint32_t        *buf;
2629         uint32_t        *bucket, *chain;
2630         uint32_t         nbucket, nchain, symndx, maskwords, shift2;
2631         uint32_t        *bl, *c, maxl, total;
2632         int              i, j, first, elferr, dynsymcount;
2633         char             idx[10];
2634
2635         if (ed->flags & SOLARIS_FMT)
2636                 PRT("\nGNU Hash Section:  %s\n", s->name);
2637         else
2638                 PRT("\ngnu hash table (%s):\n", s->name);
2639         (void) elf_errno();
2640         if ((data = elf_getdata(s->scn, NULL)) == NULL) {
2641                 elferr = elf_errno();
2642                 if (elferr != 0)
2643                         warnx("elf_getdata failed: %s",
2644                             elf_errmsg(elferr));
2645                 return;
2646         }
2647         if (data->d_size < 4 * sizeof(uint32_t)) {
2648                 warnx(".gnu.hash section too small");
2649                 return;
2650         }
2651         buf = data->d_buf;
2652         nbucket = buf[0];
2653         symndx = buf[1];
2654         maskwords = buf[2];
2655         shift2 = buf[3];
2656         buf += 4;
2657         ds = &ed->sl[s->link];
2658         if (!get_ent_count(ds, &dynsymcount))
2659                 return;
2660         nchain = dynsymcount - symndx;
2661         if (data->d_size != 4 * sizeof(uint32_t) + maskwords *
2662             (ed->ec == ELFCLASS32 ? sizeof(uint32_t) : sizeof(uint64_t)) +
2663             (nbucket + nchain) * sizeof(uint32_t)) {
2664                 warnx("Malformed .gnu.hash section");
2665                 return;
2666         }
2667         bucket = buf + (ed->ec == ELFCLASS32 ? maskwords : maskwords * 2);
2668         chain = bucket + nbucket;
2669
2670         if (ed->flags & SOLARIS_FMT) {
2671                 maxl = 0;
2672                 if ((bl = calloc(nbucket, sizeof(*bl))) == NULL)
2673                         err(EXIT_FAILURE, "calloc failed");
2674                 for (i = 0; (uint32_t)i < nbucket; i++)
2675                         for (j = bucket[i];
2676                              j > 0 && (uint32_t)j - symndx < nchain;
2677                              j++) {
2678                                 if (++bl[i] > maxl)
2679                                         maxl = bl[i];
2680                                 if (chain[j - symndx] & 1)
2681                                         break;
2682                         }
2683                 if ((c = calloc(maxl + 1, sizeof(*c))) == NULL)
2684                         err(EXIT_FAILURE, "calloc failed");
2685                 for (i = 0; (uint32_t)i < nbucket; i++)
2686                         c[bl[i]]++;
2687                 PRT("    bucket    symndx    name\n");
2688                 for (i = 0; (uint32_t)i < nbucket; i++) {
2689                         first = 1;
2690                         for (j = bucket[i];
2691                              j > 0 && (uint32_t)j - symndx < nchain;
2692                              j++) {
2693                                 if (first) {
2694                                         PRT("%10d  ", i);
2695                                         first = 0;
2696                                 } else
2697                                         PRT("            ");
2698                                 snprintf(idx, sizeof(idx), "[%d]", j );
2699                                 PRT("%-10s  ", idx);
2700                                 PRT("%s\n", get_symbol_name(ed, s->link, j));
2701                                 if (chain[j - symndx] & 1)
2702                                         break;
2703                         }
2704                 }
2705                 PRT("\n");
2706                 total = 0;
2707                 for (i = 0; (uint32_t)i <= maxl; i++) {
2708                         total += c[i] * i;
2709                         PRT("%10u  buckets contain %8d symbols\n", c[i], i);
2710                 }
2711                 PRT("%10u  buckets         %8u symbols (globals)\n", nbucket,
2712                     total);
2713         } else {
2714                 PRT("\nnbucket: %u\n", nbucket);
2715                 PRT("symndx: %u\n", symndx);
2716                 PRT("maskwords: %u\n", maskwords);
2717                 PRT("shift2: %u\n", shift2);
2718                 PRT("nchain: %u\n\n", nchain);
2719                 for (i = 0; (uint32_t)i < nbucket; i++)
2720                         PRT("bucket[%d]:\n\t%u\n\n", i, bucket[i]);
2721                 for (i = 0; (uint32_t)i < nchain; i++)
2722                         PRT("chain[%d]:\n\t%u\n\n", i, chain[i]);
2723         }
2724 }
2725
2726 /*
2727  * Dump hash tables.
2728  */
2729 static void
2730 elf_print_hash(struct elfdump *ed)
2731 {
2732         struct section  *s;
2733         int              i;
2734
2735         for (i = 0; (size_t)i < ed->shnum; i++) {
2736                 s = &ed->sl[i];
2737                 if ((s->type == SHT_HASH || s->type == SHT_GNU_HASH) &&
2738                     (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) {
2739                         if (s->type == SHT_GNU_HASH)
2740                                 elf_print_gnu_hash(ed, s);
2741                         else if (ed->ehdr.e_machine == EM_ALPHA &&
2742                             s->entsize == 8)
2743                                 elf_print_svr4_hash64(ed, s);
2744                         else
2745                                 elf_print_svr4_hash(ed, s);
2746                 }
2747         }
2748 }
2749
2750 /*
2751  * Dump the content of a Version Definition(SHT_SUNW_Verdef) Section.
2752  */
2753 static void
2754 elf_print_verdef(struct elfdump *ed, struct section *s)
2755 {
2756         Elf_Data        *data;
2757         Elf32_Verdef    *vd;
2758         Elf32_Verdaux   *vda;
2759         const char      *str;
2760         char             idx[10];
2761         uint8_t         *buf, *end, *buf2;
2762         int              i, j, elferr, count;
2763
2764         if (ed->flags & SOLARIS_FMT)
2765                 PRT("Version Definition Section:  %s\n", s->name);
2766         else
2767                 PRT("\nversion definition section (%s):\n", s->name);
2768         (void) elf_errno();
2769         if ((data = elf_getdata(s->scn, NULL)) == NULL) {
2770                 elferr = elf_errno();
2771                 if (elferr != 0)
2772                         warnx("elf_getdata failed: %s",
2773                             elf_errmsg(elferr));
2774                 return;
2775         }
2776         buf = data->d_buf;
2777         end = buf + data->d_size;
2778         i = 0;
2779         if (ed->flags & SOLARIS_FMT)
2780                 PRT("     index  version                     dependency\n");
2781         while (buf + sizeof(Elf32_Verdef) <= end) {
2782                 vd = (Elf32_Verdef *) (uintptr_t) buf;
2783                 if (ed->flags & SOLARIS_FMT) {
2784                         snprintf(idx, sizeof(idx), "[%d]", vd->vd_ndx);
2785                         PRT("%10s  ", idx);
2786                 } else {
2787                         PRT("\nentry: %d\n", i++);
2788                         PRT("\tvd_version: %u\n", vd->vd_version);
2789                         PRT("\tvd_flags: %u\n", vd->vd_flags);
2790                         PRT("\tvd_ndx: %u\n", vd->vd_ndx);
2791                         PRT("\tvd_cnt: %u\n", vd->vd_cnt);
2792                         PRT("\tvd_hash: %u\n", vd->vd_hash);
2793                         PRT("\tvd_aux: %u\n", vd->vd_aux);
2794                         PRT("\tvd_next: %u\n\n", vd->vd_next);
2795                 }
2796                 buf2 = buf + vd->vd_aux;
2797                 j = 0;
2798                 count = 0;
2799                 while (buf2 + sizeof(Elf32_Verdaux) <= end && j < vd->vd_cnt) {
2800                         vda = (Elf32_Verdaux *) (uintptr_t) buf2;
2801                         str = get_string(ed, s->link, vda->vda_name);
2802                         if (ed->flags & SOLARIS_FMT) {
2803                                 if (count == 0)
2804                                         PRT("%-26.26s", str);
2805                                 else if (count == 1)
2806                                         PRT("  %-20.20s", str);
2807                                 else {
2808                                         PRT("\n%40.40s", "");
2809                                         PRT("%s", str);
2810                                 }
2811                         } else {
2812                                 PRT("\t\tvda: %d\n", j++);
2813                                 PRT("\t\t\tvda_name: %s\n", str);
2814                                 PRT("\t\t\tvda_next: %u\n", vda->vda_next);
2815                         }
2816                         if (vda->vda_next == 0) {
2817                                 if (ed->flags & SOLARIS_FMT) {
2818                                         if (vd->vd_flags & VER_FLG_BASE) {
2819                                                 if (count == 0)
2820                                                         PRT("%-20.20s", "");
2821                                                 PRT("%s", "[ BASE ]");
2822                                         }
2823                                         PRT("\n");
2824                                 }
2825                                 break;
2826                         }
2827                         if (ed->flags & SOLARIS_FMT)
2828                                 count++;
2829                         buf2 += vda->vda_next;
2830                 }
2831                 if (vd->vd_next == 0)
2832                         break;
2833                 buf += vd->vd_next;
2834         }
2835 }
2836
2837 /*
2838  * Dump the content of a Version Needed(SHT_SUNW_Verneed) Section.
2839  */
2840 static void
2841 elf_print_verneed(struct elfdump *ed, struct section *s)
2842 {
2843         Elf_Data        *data;
2844         Elf32_Verneed   *vn;
2845         Elf32_Vernaux   *vna;
2846         uint8_t         *buf, *end, *buf2;
2847         int              i, j, elferr, first;
2848
2849         if (ed->flags & SOLARIS_FMT)
2850                 PRT("\nVersion Needed Section:  %s\n", s->name);
2851         else
2852                 PRT("\nversion need section (%s):\n", s->name);
2853         (void) elf_errno();
2854         if ((data = elf_getdata(s->scn, NULL)) == NULL) {
2855                 elferr = elf_errno();
2856                 if (elferr != 0)
2857                         warnx("elf_getdata failed: %s",
2858                             elf_errmsg(elferr));
2859                 return;
2860         }
2861         buf = data->d_buf;
2862         end = buf + data->d_size;
2863         if (ed->flags & SOLARIS_FMT)
2864                 PRT("            file                        version\n");
2865         i = 0;
2866         while (buf + sizeof(Elf32_Verneed) <= end) {
2867                 vn = (Elf32_Verneed *) (uintptr_t) buf;
2868                 if (ed->flags & SOLARIS_FMT)
2869                         PRT("            %-26.26s  ",
2870                             get_string(ed, s->link, vn->vn_file));
2871                 else {
2872                         PRT("\nentry: %d\n", i++);
2873                         PRT("\tvn_version: %u\n", vn->vn_version);
2874                         PRT("\tvn_cnt: %u\n", vn->vn_cnt);
2875                         PRT("\tvn_file: %s\n",
2876                             get_string(ed, s->link, vn->vn_file));
2877                         PRT("\tvn_aux: %u\n", vn->vn_aux);
2878                         PRT("\tvn_next: %u\n\n", vn->vn_next);
2879                 }
2880                 buf2 = buf + vn->vn_aux;
2881                 j = 0;
2882                 first = 1;
2883                 while (buf2 + sizeof(Elf32_Vernaux) <= end && j < vn->vn_cnt) {
2884                         vna = (Elf32_Vernaux *) (uintptr_t) buf2;
2885                         if (ed->flags & SOLARIS_FMT) {
2886                                 if (!first)
2887                                         PRT("%40.40s", "");
2888                                 else
2889                                         first = 0;
2890                                 PRT("%s\n", get_string(ed, s->link,
2891                                     vna->vna_name));
2892                         } else {
2893                                 PRT("\t\tvna: %d\n", j++);
2894                                 PRT("\t\t\tvna_hash: %u\n", vna->vna_hash);
2895                                 PRT("\t\t\tvna_flags: %u\n", vna->vna_flags);
2896                                 PRT("\t\t\tvna_other: %u\n", vna->vna_other);
2897                                 PRT("\t\t\tvna_name: %s\n",
2898                                     get_string(ed, s->link, vna->vna_name));
2899                                 PRT("\t\t\tvna_next: %u\n", vna->vna_next);
2900                         }
2901                         if (vna->vna_next == 0)
2902                                 break;
2903                         buf2 += vna->vna_next;
2904                 }
2905                 if (vn->vn_next == 0)
2906                         break;
2907                 buf += vn->vn_next;
2908         }
2909 }
2910
2911 /*
2912  * Dump the symbol-versioning sections.
2913  */
2914 static void
2915 elf_print_symver(struct elfdump *ed)
2916 {
2917         struct section  *s;
2918         int              i;
2919
2920         for (i = 0; (size_t)i < ed->shnum; i++) {
2921                 s = &ed->sl[i];
2922                 if (!STAILQ_EMPTY(&ed->snl) && !find_name(ed, s->name))
2923                         continue;
2924                 if (s->type == SHT_SUNW_verdef)
2925                         elf_print_verdef(ed, s);
2926                 if (s->type == SHT_SUNW_verneed)
2927                         elf_print_verneed(ed, s);
2928         }
2929 }
2930
2931 /*
2932  * Dump the ELF checksum. See gelf_checksum(3) for details.
2933  */
2934 static void
2935 elf_print_checksum(struct elfdump *ed)
2936 {
2937
2938         if (!STAILQ_EMPTY(&ed->snl))
2939                 return;
2940
2941         PRT("\nelf checksum: %#lx\n", gelf_checksum(ed->elf));
2942 }
2943
2944 #define USAGE_MESSAGE   "\
2945 Usage: %s [options] file...\n\
2946   Display information about ELF objects and ar(1) archives.\n\n\
2947   Options:\n\
2948   -a                        Show all information.\n\
2949   -c                        Show shared headers.\n\
2950   -d                        Show dynamic symbols.\n\
2951   -e                        Show the ELF header.\n\
2952   -G                        Show the GOT.\n\
2953   -H | --help               Show a usage message and exit.\n\
2954   -h                        Show hash values.\n\
2955   -i                        Show the dynamic interpreter.\n\
2956   -k                        Show the ELF checksum.\n\
2957   -n                        Show the contents of note sections.\n\
2958   -N NAME                   Show the section named \"NAME\".\n\
2959   -p                        Show the program header.\n\
2960   -r                        Show relocations.\n\
2961   -s                        Show the symbol table.\n\
2962   -S                        Use the Solaris elfdump format.\n\
2963   -v                        Show symbol-versioning information.\n\
2964   -V | --version            Print a version identifier and exit.\n\
2965   -w FILE                   Write output to \"FILE\".\n"
2966
2967 static void
2968 usage(void)
2969 {
2970         fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
2971         exit(EXIT_FAILURE);
2972 }