1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1988 AT&T
24 * All Rights Reserved
25 *
26 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
27 * Copyright 2018, Joyent, Inc.
28 */
29
30 /* Get definitions for the relocation types supported. */
31 #define ELF_TARGET_ALL
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <locale.h>
36 #include <unistd.h>
37 #include <libelf.h>
38 #include <sys/link.h>
39 #include <sys/elf.h>
40 #include <sys/machelf.h>
41 #include <fcntl.h>
42 #include <sys/stat.h>
43 #include <errno.h>
44 #include <string.h>
45 #include "sgs.h"
46 #include "conv.h"
47 #include "dump.h"
48
49
50 #define OPTSTR "agcd:fhn:oprstvCLT:V?" /* option string for getopt() */
51
52 const char *UNKNOWN = "<unknown>";
53
54 static SCNTAB *p_symtab, *p_head_scns, *p_dynsym;
55
56 static int
57 x_flag = 0, /* option requires section header table */
58 z_flag = 0, /* process files within an archive */
59 rn_flag = 0; /* dump named relocation information */
60
61 static int
62 /* flags: ?_flag corresponds to ? option */
63 a_flag = 0, /* dump archive header of each member of archive */
64 g_flag = 0, /* dump archive symbol table */
65 c_flag = 0, /* dump the string table */
66 d_flag = 0, /* dump range of sections */
67 f_flag = 0, /* dump each file header */
68 h_flag = 0, /* dump section headers */
69 n_flag = 0, /* dump named section */
70 o_flag = 0, /* dump each program execution header */
71 r_flag = 0, /* dump relocation information */
72 s_flag = 0, /* dump section contents */
73 t_flag = 0, /* dump symbol table entries */
74 C_flag = 0, /* dump decoded C++ symbol names */
75 L_flag = 0, /* dump dynamic linking information */
76 T_flag = 0, /* dump symbol table range */
77 V_flag = 0; /* dump version information */
78
79 int p_flag = 0, /* suppress printing of headings */
80 v_flag = 0; /* print information in verbose form */
81
82 static int
83 d_low = 0, /* range for use with -d */
84 d_hi = 0,
85 d_num = 0;
86
87 static int
88 T_low = 0, /* range for use with -T */
89 T_hi = 0,
90 T_num = 0;
91
92 static char *name = NULL; /* for use with -n option */
93 char *prog_name;
94 static int errflag = 0;
95
96 static struct stab_list_s {
97 struct stab_list_s *next;
98 char *strings;
99 size_t size;
100 } *StringTableList = (void *)0;
101
102 extern void ar_sym_read();
103 extern void dump_exec_header();
104
105
106 /*
107 * Get the section descriptor and set the size of the
108 * data returned. Data is byte-order converted.
109 */
110 void *
get_scndata(Elf_Scn * fd_scn,size_t * size)111 get_scndata(Elf_Scn *fd_scn, size_t *size)
112 {
113 Elf_Data *p_data;
114
115 p_data = 0;
116 if ((p_data = elf_getdata(fd_scn, p_data)) == 0 ||
117 p_data->d_size == 0) {
118 return (NULL);
119 }
120 *size = p_data->d_size;
121 return (p_data->d_buf);
122 }
123
124 /*
125 * Get the section descriptor and set the size of the
126 * data returned. Data is raw (i.e., not byte-order converted).
127 */
128 static void *
get_rawscn(Elf_Scn * fd_scn,size_t * size)129 get_rawscn(Elf_Scn *fd_scn, size_t *size)
130 {
131 Elf_Data *p_data;
132
133 p_data = 0;
134 if ((p_data = elf_rawdata(fd_scn, p_data)) == 0 ||
135 p_data->d_size == 0) {
136 return (NULL);
137 }
138
139 *size = p_data->d_size;
140 return (p_data->d_buf);
141 }
142
143 /*
144 * Print out a usage message in short form when program is invoked
145 * with insufficient or no arguments, and in long form when given
146 * either a ? or an invalid option.
147 */
148 static void
usage()149 usage()
150 {
151 (void) fprintf(stderr,
152 "Usage: %s [-%s] file(s) ...\n", prog_name, OPTSTR);
153 if (errflag) {
154 (void) fprintf(stderr,
155 "\t\t[-a dump archive header of each member of archive]\n\
156 [-g dump archive global symbol table]\n\
157 [-c dump the string table]\n\
158 [-d dump range of sections]\n\
159 [-f dump each file header]\n\
160 [-h dump section headers]\n\
161 [-n dump named section]\n\
162 [-o dump each program execution header]\n\
163 [-p suppress printing of headings]\n\
164 [-r dump relocation information]\n\
165 [-s dump section contents]\n\
166 [-t dump symbol table entries]\n\
167 [-v print information in verbose form]\n\
168 [-C dump decoded C++ symbol names]\n\
169 [-L dump the .dynamic structure]\n\
170 [-T dump symbol table range]\n\
171 [-V dump version information]\n");
172 }
173 }
174
175 /*
176 * Set a range. Input is a character string, a lower
177 * bound and an upper bound. This function converts
178 * a character string into its correct integer values,
179 * setting the first value as the lower bound, and
180 * the second value as the upper bound. If more values
181 * are given they are ignored with a warning.
182 */
183 static void
set_range(char * s,int * low,int * high)184 set_range(char *s, int *low, int *high)
185 {
186 char *w;
187 char *lasts;
188
189 while ((w = strtok_r(s, ",", &lasts)) != NULL) {
190 if (!(*low))
191 /* LINTED */
192 *low = (int)atol(w);
193 else
194 if (!(*high))
195 /* LINTED */
196 *high = (int)atol(w);
197 else {
198 (void) fprintf(stderr,
199 "%s: too many arguments - %s ignored\n",
200 prog_name, w);
201 return;
202 }
203 s = NULL;
204 } /* end while */
205 }
206
207
208 /*
209 * Print static shared library information.
210 */
211 static void
print_static(SCNTAB * l_scns,char * filename)212 print_static(SCNTAB *l_scns, char *filename)
213 {
214 size_t section_size;
215 unsigned char *strtab;
216 unsigned char *path, buf[1024];
217 unsigned long *temp;
218 unsigned long total, topath;
219
220 (void) printf("\n **** STATIC SHARED LIBRARY INFORMATION ****\n");
221 (void) printf("\n%s:\n", filename);
222 (void) printf("\t");
223 section_size = 0;
224 if ((strtab = (unsigned char *)
225 get_scndata(l_scns->p_sd, §ion_size)) == NULL) {
226 return;
227 }
228
229 while (section_size != 0) {
230 /* LINTED */
231 temp = (unsigned long *)strtab;
232 total = temp[0];
233 topath = temp[1];
234 path = strtab + (topath*sizeof (long));
235 (void) strncpy((char *)buf, (char *)path,
236 (total - topath)*sizeof (long));
237 (void) fprintf(stdout, "%s\n", buf);
238 strtab += total*sizeof (long);
239 section_size -= (total*sizeof (long));
240 }
241 }
242
243 /*
244 * Print raw data in hexidecimal. Input is the section data to
245 * be printed out and the size of the data. Output is relative
246 * to a table lookup in dumpmap.h.
247 */
248 static void
print_rawdata(unsigned char * p_sec,size_t size)249 print_rawdata(unsigned char *p_sec, size_t size)
250 {
251 size_t j;
252 size_t count;
253
254 count = 1;
255
256 (void) printf("\t");
257 for (j = size/sizeof (short); j != 0; --j, ++count) {
258 (void) printf("%.2x %.2x ", p_sec[0], p_sec[1]);
259 p_sec += 2;
260 if (count == 12) {
261 (void) printf("\n\t");
262 count = 0;
263 }
264 }
265
266 /*
267 * take care of last byte if odd byte section
268 */
269 if ((size & 0x1L) == 1L)
270 (void) printf("%.2x", *p_sec);
271 (void) printf("\n");
272 }
273
274
275
276 /*
277 * Print relocation data of type SHT_RELA
278 * If d_flag, print data corresponding only to
279 * the section or range of sections specified.
280 * If n_flag, print data corresponding only to
281 * the named section.
282 */
283 static void
print_rela(Elf * elf_file,SCNTAB * p_scns,Elf_Data * rdata,Elf_Data * sym_data,GElf_Ehdr * p_ehdr,size_t reloc_size,size_t sym_size,char * filename,SCNTAB * reloc_symtab)284 print_rela(Elf *elf_file, SCNTAB *p_scns, Elf_Data *rdata, Elf_Data *sym_data,
285 GElf_Ehdr * p_ehdr, size_t reloc_size, size_t sym_size, char *filename,
286 SCNTAB *reloc_symtab)
287 {
288 GElf_Rela rela;
289 GElf_Sym sym;
290 size_t no_entries;
291 size_t rel_entsize;
292 size_t no_syms;
293 int type, symid;
294 static int n_title = 0;
295 int ndx = 0;
296 char *sym_name;
297 int adj = 0;
298
299 if (gelf_getclass(elf_file) == ELFCLASS64)
300 adj = 8;
301
302 rel_entsize = p_scns->p_shdr.sh_entsize;
303 if ((rel_entsize == 0) ||
304 (rel_entsize > p_scns->p_shdr.sh_size)) {
305 rel_entsize = gelf_fsize(elf_file, ELF_T_RELA, 1,
306 EV_CURRENT);
307 }
308 no_entries = reloc_size / rel_entsize;
309
310 no_syms = sym_size / gelf_fsize(elf_file, ELF_T_SYM, 1, EV_CURRENT);
311 while (no_entries--) {
312 (void) gelf_getrela(rdata, ndx, &rela);
313 /* LINTED */
314 type = (int)GELF_R_TYPE(rela.r_info);
315 /* LINTED */
316 symid = (int)GELF_R_SYM(rela.r_info);
317 /* LINTED */
318 if ((symid > (no_syms - 1)) || (symid < 0)) {
319 (void) fprintf(stderr, "%s: %s: invalid symbol table "
320 "offset - %d - in %s\n", prog_name, filename,
321 symid, p_scns->scn_name);
322 ndx++;
323 continue;
324 }
325 (void) gelf_getsym(sym_data, symid, &sym);
326 sym_name = (char *)elf_strptr(elf_file,
327 reloc_symtab->p_shdr.sh_link, sym.st_name);
328 if (sym_name == NULL)
329 sym_name = (char *)UNKNOWN;
330 if (r_flag && rn_flag) {
331 if (strcmp(name, p_scns->scn_name) != 0) {
332 ndx++;
333 continue;
334 }
335 if (!n_title) {
336 (void) printf("\n%s:\n", p_scns->scn_name);
337 (void) printf("%-*s%-*s%-*s%s\n\n",
338 12 + adj, "Offset", 22, "Symndx",
339 16, "Type", "Addend");
340 n_title = 1;
341 }
342 }
343 if (d_flag) {
344 if (!d_hi)
345 d_hi = d_low;
346 if ((symid < d_low) || (symid > d_hi)) {
347 ndx++;
348 continue;
349 }
350 }
351
352 (void) printf("%-#*llx", 12 + adj, EC_XWORD(rela.r_offset));
353 if (!v_flag) {
354 (void) printf("%-22d%-18d", symid, type);
355 } else {
356 Conv_inv_buf_t inv_buf;
357
358 if (strlen(sym_name)) {
359 size_t len = strlen(sym_name) + 1;
360 char tmpstr[10];
361 if (len > 22) {
362 (void) sprintf(tmpstr, "%%-%ds",
363 /* LINTED */
364 (int)len);
365 /*LINTED: E_SEC_PRINTF_VAR_FMT*/
366 (void) printf(tmpstr, sym_name);
367 } else
368 (void) printf("%-22s", sym_name);
369 } else {
370 (void) printf("%-22d", symid);
371 }
372 (void) printf("%-20s",
373 conv_reloc_type(p_ehdr->e_machine,
374 type, DUMP_CONVFMT, &inv_buf));
375 }
376 (void) printf("%lld\n", EC_SXWORD(rela.r_addend));
377 ndx++;
378 }
379 }
380
381 /*
382 * Print relocation data of type SHT_REL.
383 * If d_flag, print data corresponding only to
384 * the section or range of sections specified.
385 * If n_flag, print data corresponding only to
386 * the named section.
387 */
388 static void
print_rel(Elf * elf_file,SCNTAB * p_scns,Elf_Data * rdata,Elf_Data * sym_data,GElf_Ehdr * p_ehdr,size_t reloc_size,size_t sym_size,char * filename,SCNTAB * reloc_symtab)389 print_rel(Elf *elf_file, SCNTAB *p_scns, Elf_Data *rdata, Elf_Data *sym_data,
390 GElf_Ehdr *p_ehdr, size_t reloc_size, size_t sym_size, char *filename,
391 SCNTAB *reloc_symtab)
392 {
393 GElf_Rel rel;
394 GElf_Sym sym;
395 size_t no_entries;
396 size_t rel_entsize;
397 int type, symid;
398 size_t no_syms;
399 static int n_title = 0;
400 int ndx = 0;
401 char *sym_name;
402 int adj = 0;
403
404 if (gelf_getclass(elf_file) == ELFCLASS64)
405 adj = 8;
406
407 rel_entsize = p_scns->p_shdr.sh_entsize;
408 if ((rel_entsize == 0) ||
409 (rel_entsize > p_scns->p_shdr.sh_size)) {
410 rel_entsize = gelf_fsize(elf_file, ELF_T_REL, 1,
411 EV_CURRENT);
412 }
413 no_entries = reloc_size / rel_entsize;
414
415 no_syms = sym_size / gelf_fsize(elf_file, ELF_T_SYM, 1, EV_CURRENT);
416 while (no_entries--) {
417 (void) gelf_getrel(rdata, ndx, &rel);
418 /* LINTED */
419 type = (int)GELF_R_TYPE(rel.r_info);
420 /* LINTED */
421 symid = (int)GELF_R_SYM(rel.r_info);
422 /* LINTED */
423 if ((symid > (no_syms - 1)) || (symid < 0)) {
424 (void) fprintf(stderr, "%s: %s: invalid symbol table "
425 "offset - %d - in %s\n", prog_name, filename,
426 symid, p_scns->scn_name);
427 ndx++;
428 continue;
429 }
430 (void) gelf_getsym(sym_data, symid, &sym);
431 sym_name = (char *)elf_strptr(elf_file,
432 reloc_symtab->p_shdr.sh_link, sym.st_name);
433 if (sym_name == NULL)
434 sym_name = (char *)UNKNOWN;
435 if (r_flag && rn_flag) {
436 if (strcmp(name, p_scns->scn_name) != 0) {
437 ndx++;
438 continue;
439 }
440 if (!n_title) {
441 (void) printf("\n%s:\n", p_scns->scn_name);
442 (void) printf("%-*s%-*s%s\n\n",
443 12 + adj, "Offset", 20, "Symndx", "Type");
444 n_title = 1;
445 }
446 }
447 if (d_flag) {
448 if (!d_hi)
449 d_hi = d_low;
450 if ((symid < d_low) || (symid > d_hi)) {
451 ndx++;
452 continue;
453 }
454 }
455
456 (void) printf("%-#*llx", 12 + adj, EC_ADDR(rel.r_offset));
457 if (!v_flag) {
458 (void) printf("%-20d%-18d", symid, type);
459 } else {
460 Conv_inv_buf_t inv_buf;
461
462 if (strlen(sym_name))
463 (void) printf("%-20s", sym_name);
464 else {
465 (void) printf("%-20d", sym.st_name);
466 }
467 (void) printf("%-20s",
468 conv_reloc_type(p_ehdr->e_machine,
469 type, DUMP_CONVFMT, &inv_buf));
470 }
471 (void) printf("\n");
472 ndx++;
473 }
474 }
475
476 /* demangle C++ names */
477 static char *
demangled_name(char * s)478 demangled_name(char *s)
479 {
480 static char *buf = NULL;
481 size_t buflen = 0;
482 char *dn;
483 size_t len;
484
485 dn = (char *)conv_demangle_name(s);
486
487 /*
488 * If not demangled, just return the symbol name
489 */
490 if (dn == s)
491 return (s);
492
493 len = strlen(dn) + strlen(s) + 4;
494
495 if (buflen < len) {
496 free(buf);
497 if ((buf = malloc(len)) == NULL)
498 return (s);
499 buflen = len;
500 }
501
502 /*
503 * Demangled. Format it
504 */
505 (void) snprintf(buf, buflen, "%s\t[%s]", dn, s);
506 free(dn);
507 return (buf);
508 }
509
510 /*
511 * Print the symbol table. Input is an ELF file descriptor, a
512 * pointer to the symbol table SCNTAB structure,
513 * the number of symbols, a range of symbols to print,
514 * an index which is the number of the
515 * section in the file, and the filename. The number of sections,
516 * the range, and the index are set in
517 * dump_symbol_table, depending on whether -n or -T were set.
518 */
519 static void
print_symtab(Elf * elf_file,SCNTAB * p_symtab,Elf_Data * sym_data,long range,int index)520 print_symtab(Elf *elf_file, SCNTAB *p_symtab, Elf_Data *sym_data,
521 long range, int index)
522 {
523 GElf_Sym sym;
524 int adj = 0; /* field adjustment for elf64 */
525 Elf32_Word *symshndx = 0;
526 unsigned int nosymshndx = 0;
527 Conv_inv_buf_t inv_buf;
528
529
530 if (gelf_getclass(elf_file) == ELFCLASS64)
531 adj = 8;
532
533 while (range > 0) {
534 char *sym_name = NULL;
535 int type, bind;
536 int specsec;
537 unsigned int shndx;
538
539 (void) gelf_getsym(sym_data, index, &sym);
540 type = (int)GELF_ST_TYPE(sym.st_info);
541 bind = (int)GELF_ST_BIND(sym.st_info);
542
543 if ((sym.st_shndx == SHN_XINDEX) &&
544 (symshndx == 0) && (nosymshndx == 0)) {
545 Elf_Scn *_scn;
546 GElf_Shdr _shdr;
547 size_t symscnndx;
548
549 symscnndx = elf_ndxscn(p_symtab->p_sd);
550 _scn = 0;
551 while ((_scn = elf_nextscn(elf_file, _scn)) != 0) {
552 if (gelf_getshdr(_scn, &_shdr) == 0)
553 break;
554 if ((_shdr.sh_type == SHT_SYMTAB_SHNDX) &&
555 /* LINTED */
556 (_shdr.sh_link == (GElf_Word)symscnndx)) {
557 Elf_Data *_data;
558
559 if ((_data = elf_getdata(_scn, 0)) == 0)
560 continue;
561
562 symshndx = (Elf32_Word *)_data->d_buf;
563 nosymshndx = 0;
564 break;
565 }
566 }
567 nosymshndx = 1;
568 }
569
570 if ((symshndx) && (sym.st_shndx == SHN_XINDEX)) {
571 shndx = symshndx[index];
572 specsec = 0;
573 } else {
574 shndx = sym.st_shndx;
575 if ((sym.st_shndx == SHN_UNDEF) ||
576 (sym.st_shndx >= SHN_LORESERVE))
577 specsec = 1;
578 else
579 specsec = 0;
580 }
581
582
583 (void) printf("[%d]\t ", index++);
584
585 if (v_flag && (type == STT_SPARC_REGISTER)) {
586 /*
587 * The strings "REG_G1" through "REG_G7" are intended
588 * to be consistent with output from elfdump(1).
589 */
590 (void) printf("%-*s", 12 + adj,
591 conv_sym_SPARC_value(sym.st_value,
592 DUMP_CONVFMT, &inv_buf));
593 } else {
594 (void) printf("0x%-*llx", 10 + adj,
595 EC_ADDR(sym.st_value));
596 }
597
598 (void) printf("%-*lld", 9 + adj, EC_XWORD(sym.st_size));
599
600 if (!v_flag) {
601 (void) printf("%d\t\t%d\t%d\t%#x\t",
602 type, bind, (int)sym.st_other, (int)shndx);
603 } else {
604 GElf_Ehdr p_ehdr;
605 (void) gelf_getehdr(elf_file, &p_ehdr);
606 (void) printf("%s\t",
607 conv_sym_info_type(p_ehdr.e_machine, type,
608 DUMP_CONVFMT, &inv_buf));
609 (void) printf("%s",
610 conv_sym_info_bind(bind, DUMP_CONVFMT, &inv_buf));
611 (void) printf("\t %d\t", EC_WORD(sym.st_other));
612
613 if (specsec)
614 (void) printf("%s",
615 conv_sym_shndx(p_ehdr.e_ident[EI_OSABI],
616 p_ehdr.e_machine, shndx,
617 CONV_FMT_DECIMAL, &inv_buf));
618 else
619 (void) printf("%d", EC_WORD(shndx));
620 (void) printf("\t");
621 }
622
623 /* support machines where NULL-deref causes core dump */
624 if (sym.st_name == 0)
625 sym_name = (char *)UNKNOWN;
626 else
627 if (C_flag)
628 sym_name = demangled_name(
629 (char *)elf_strptr(elf_file,
630 p_symtab->p_shdr.sh_link,
631 sym.st_name));
632 else
633 sym_name = (char *)elf_strptr(elf_file,
634 p_symtab->p_shdr.sh_link, sym.st_name);
635 if (sym_name == NULL)
636 sym_name = (char *)UNKNOWN;
637 (void) printf("%s\n", sym_name);
638
639 range--;
640 } /* end while */
641 }
642
643 /*
644 * Print the section header table. Input is the SCNTAB structure,
645 * the number of sections, an index which is the number of the
646 * section in the file, and the filename. The values of the SCNTAB
647 * structure, the number of sections, and the index are set in
648 * dump_shdr depending on whether the -n or -d modifiers were set.
649 */
650 static void
print_shdr(Elf * elf_file,SCNTAB * s,int num_scns,int index)651 print_shdr(Elf *elf_file, SCNTAB *s, int num_scns, int index)
652 {
653 SCNTAB *p;
654 int num;
655 int field;
656 GElf_Ehdr p_ehdr;
657
658 if (gelf_getclass(elf_file) == ELFCLASS64)
659 field = 21;
660 else
661 field = 13;
662
663 p = s;
664 (void) gelf_getehdr(elf_file, &p_ehdr);
665
666 for (num = 0; num < num_scns; num++, p++) {
667 (void) printf("[%d]\t", index++);
668 if (!v_flag) {
669 (void) printf("%u\t%llu\t",
670 EC_WORD(p->p_shdr.sh_type),
671 EC_XWORD(p->p_shdr.sh_flags));
672 } else {
673 Conv_inv_buf_t inv_buf;
674
675 /*LINTED: E_SEC_PRINTF_VAR_FMT*/
676 (void) printf(conv_sec_type(
677 p_ehdr.e_ident[EI_OSABI], p_ehdr.e_machine,
678 p->p_shdr.sh_type, DUMP_CONVFMT, &inv_buf));
679 (void) printf(" ");
680
681 if (p->p_shdr.sh_flags & SHF_WRITE)
682 (void) printf("W");
683 else
684 (void) printf("-");
685 if (p->p_shdr.sh_flags & SHF_ALLOC)
686 (void) printf("A");
687 else
688 (void) printf("-");
689 if (p->p_shdr.sh_flags & SHF_EXECINSTR)
690 (void) printf("I");
691 else
692 (void) printf("-");
693
694 if (p->p_shdr.sh_flags & SHF_ORDERED)
695 (void) printf("O");
696 if (p->p_shdr.sh_flags & SHF_EXCLUDE)
697 (void) printf("E");
698
699 (void) printf("\t");
700
701 }
702 (void) printf("%-#*llx%-#*llx%-#*llx%s%s\n",
703 field, EC_ADDR(p->p_shdr.sh_addr),
704 field, EC_OFF(p->p_shdr.sh_offset),
705 field, EC_XWORD(p->p_shdr.sh_size),
706 /* compatibility: tab for elf32 */
707 (field == 13) ? "\t" : " ", p->scn_name);
708
709 (void) printf("\t%u\t%u\t%-#*llx%-#*llx\n\n",
710 EC_WORD(p->p_shdr.sh_link),
711 EC_WORD(p->p_shdr.sh_info),
712 field, EC_XWORD(p->p_shdr.sh_addralign),
713 field, EC_XWORD(p->p_shdr.sh_entsize));
714 }
715 }
716
717 /*
718 * Check that a range of numbers is valid. Input is
719 * a lower bound, an upper bound, a boundary condition,
720 * and the filename. Negative numbers and numbers greater
721 * than the bound are invalid. low must be smaller than hi.
722 * The returned integer is the number of items in the
723 * range if it is valid and -1 otherwise.
724 */
725 static int
check_range(int low,int hi,size_t bound,char * filename)726 check_range(int low, int hi, size_t bound, char *filename)
727 {
728 if (((size_t)low > bound) || (low <= 0)) {
729 (void) fprintf(stderr,
730 "%s: %s: number out of range, %d\n",
731 prog_name, filename, low);
732 return (-1);
733 }
734 if (((size_t)hi > bound) || (hi < 0)) {
735 (void) fprintf(stderr,
736 "%s: %s: number out of range, %d\n",
737 prog_name, filename, hi);
738 return (-1);
739 }
740
741 if (hi && (low > hi)) {
742 (void) fprintf(stderr,
743 "%s: %s: invalid range, %d,%d\n",
744 prog_name, filename, low, hi);
745 return (-1);
746 }
747 if (hi)
748 return (hi - low + 1);
749 else
750 return (1);
751 }
752
753 /*
754 * Print relocation information. Since this information is
755 * machine dependent, new sections must be added for each machine
756 * that is supported. Input is an ELF file descriptor, the ELF header,
757 * the SCNTAB structure, the number of sections, and a filename.
758 * Set up necessary information to print relocation information
759 * and call the appropriate print function depending on the
760 * type of relocation information. If the symbol table is
761 * absent, no relocation data is processed. Input is an
762 * ELF file descriptor, the ELF header, the SCNTAB structure,
763 * and the filename. Set range of d_flag and name if n_flag.
764 */
765 static void
dump_reloc_table(Elf * elf_file,GElf_Ehdr * p_ehdr,SCNTAB * p_scns,int num_scns,char * filename)766 dump_reloc_table(Elf *elf_file, GElf_Ehdr *p_ehdr,
767 SCNTAB *p_scns, int num_scns, char *filename)
768 {
769 Elf_Data *rel_data;
770 Elf_Data *sym_data;
771 size_t sym_size;
772 size_t reloc_size;
773 SCNTAB *reloc_symtab;
774 SCNTAB *head_scns;
775 int r_title = 0;
776 int adj = 0;
777 size_t shnum;
778
779 if (gelf_getclass(elf_file) == ELFCLASS64)
780 adj = 8;
781
782 if ((!p_flag) && (!r_title)) {
783 (void) printf("\n **** RELOCATION INFORMATION ****\n");
784 r_title = 1;
785 }
786
787 while (num_scns-- > 0) {
788 if ((p_scns->p_shdr.sh_type != SHT_RELA) &&
789 (p_scns->p_shdr.sh_type != SHT_REL)) {
790 p_scns++;
791 continue;
792 }
793
794 head_scns = p_head_scns;
795
796 if (elf_getshdrnum(elf_file, &shnum) == -1) {
797 (void) fprintf(stderr,
798 "%s: %s: elf_getshdrnum failed: %s\n",
799 prog_name, filename, elf_errmsg(-1));
800 return;
801 }
802
803 if ((p_scns->p_shdr.sh_link == 0) ||
804 /* LINTED */
805 (p_scns->p_shdr.sh_link >= (GElf_Word)shnum)) {
806 (void) fprintf(stderr, "%s: %s: invalid sh_link field: "
807 "section #: %d sh_link: %d\n",
808 /* LINTED */
809 prog_name, filename, (int)elf_ndxscn(p_scns->p_sd),
810 (int)p_scns->p_shdr.sh_link);
811 return;
812 }
813 head_scns += (p_scns->p_shdr.sh_link -1);
814
815 if (head_scns->p_shdr.sh_type == SHT_SYMTAB) {
816 reloc_symtab = p_symtab;
817 } else if (head_scns->p_shdr.sh_type == SHT_DYNSYM) {
818 reloc_symtab = p_dynsym;
819 } else {
820 (void) fprintf(stderr,
821 "%s: %s: could not get symbol table\n", prog_name, filename);
822 return;
823 }
824
825 sym_data = NULL;
826 sym_size = 0;
827 reloc_size = 0;
828
829 if ((sym_data = elf_getdata(reloc_symtab->p_sd, NULL)) == NULL) {
830 (void) fprintf(stderr,
831 "%s: %s: no symbol table data\n", prog_name, filename);
832 return;
833 }
834 sym_size = sym_data->d_size;
835
836 if (p_scns->p_shdr.sh_type == SHT_RELA) {
837 if (!n_flag && r_flag)
838 (void) printf("\n%s:\n", p_scns->scn_name);
839 if (!p_flag && (!n_flag && r_flag))
840 (void) printf("%-*s%-*s%-*s%s\n\n",
841 12 + adj, "Offset", 22, "Symndx",
842 18, "Type", "Addend");
843 if ((rel_data = elf_getdata(p_scns->p_sd, NULL)) == NULL) {
844 (void) fprintf(stderr,
845 "%s: %s: no relocation information\n", prog_name, filename);
846 return;
847 }
848 reloc_size = rel_data->d_size;
849
850 if (n_flag) {
851 rn_flag = 1;
852 print_rela(elf_file, p_scns, rel_data, sym_data, p_ehdr,
853 reloc_size, sym_size, filename, reloc_symtab);
854 }
855 if (d_flag) {
856 rn_flag = 0;
857 print_rela(elf_file, p_scns, rel_data, sym_data, p_ehdr,
858 reloc_size, sym_size, filename, reloc_symtab);
859 }
860 if (!n_flag && !d_flag)
861 print_rela(elf_file, p_scns, rel_data, sym_data, p_ehdr,
862 reloc_size, sym_size, filename, reloc_symtab);
863 } else {
864 if (p_scns->p_shdr.sh_type == SHT_REL) {
865 if (!n_flag && r_flag)
866 (void) printf("\n%s:\n", p_scns->scn_name);
867 if (!p_flag && (!n_flag && r_flag)) {
868 (void) printf("%-*s%-*s%s\n\n",
869 12 + adj, "Offset", 20, "Symndx", "Type");
870 }
871 if ((rel_data = elf_getdata(p_scns->p_sd, NULL))
872 == NULL) {
873 (void) fprintf(stderr,
874 "%s: %s: no relocation information\n", prog_name, filename);
875 return;
876 }
877 reloc_size = rel_data->d_size;
878 if (n_flag) {
879 rn_flag = 1;
880 print_rel(elf_file, p_scns, rel_data, sym_data,
881 p_ehdr, reloc_size, sym_size,
882 filename, reloc_symtab);
883 }
884 if (d_flag) {
885 rn_flag = 0;
886 print_rel(elf_file, p_scns, rel_data, sym_data,
887 p_ehdr, reloc_size, sym_size,
888 filename, reloc_symtab);
889 }
890 if (!n_flag && !d_flag)
891 print_rel(elf_file, p_scns, rel_data, sym_data,
892 p_ehdr, reloc_size, sym_size,
893 filename, reloc_symtab);
894 }
895 }
896 p_scns++;
897 }
898 }
899
900 /*
901 * Print out the string tables. Input is an opened ELF file,
902 * the SCNTAB structure, the number of sections, and the filename.
903 * Since there can be more than one string table, all sections are
904 * examined and any with the correct type are printed out.
905 */
906 static void
dump_string_table(SCNTAB * s,int num_scns)907 dump_string_table(SCNTAB *s, int num_scns)
908 {
909 size_t section_size;
910 unsigned char *strtab;
911 int beg_of_string;
912 int counter = 0;
913 int str_off;
914 int i;
915
916 if (!p_flag) {
917 (void) printf("\n **** STRING TABLE INFORMATION ****\n");
918 }
919
920 for (i = 0; i < num_scns; i++, s++) {
921 if (s->p_shdr.sh_type != SHT_STRTAB)
922 continue;
923
924 str_off = 0;
925
926 if (!p_flag) {
927 (void) printf("\n%s:\n", s->scn_name);
928 (void) printf(" <offset> \tName\n");
929 }
930 section_size = 0;
931 if ((strtab = (unsigned char *)
932 get_scndata(s->p_sd, §ion_size)) == NULL) {
933 continue;
934 }
935
936 if (section_size != 0) {
937 (void) printf(" <%d> \t", str_off);
938 beg_of_string = 0;
939 while (section_size--) {
940 unsigned char c = *strtab++;
941
942 if (beg_of_string) {
943 (void) printf(" <%d> \t", str_off);
944 counter++;
945 beg_of_string = 0;
946 }
947 str_off++;
948 switch (c) {
949 case '\0':
950 (void) printf("\n");
951 beg_of_string = 1;
952 break;
953 default:
954 (void) putchar(c);
955 }
956 }
957 }
958 }
959 (void) printf("\n");
960 }
961
962 /*
963 * Print the symbol table. This function does not print the contents
964 * of the symbol table but sets up the parameters and then calls
965 * print_symtab to print the symbols. Calling another function to print
966 * the symbols allows both -T and -n to work correctly
967 * simultaneously. Input is an opened ELF file, a pointer to the
968 * symbol table SCNTAB structure, and the filename.
969 * Set the range of symbols to print if T_flag, and set
970 * name of symbol to print if n_flag.
971 */
972 static void
dump_symbol_table(Elf * elf_file,SCNTAB * p_symtab,char * filename)973 dump_symbol_table(Elf *elf_file, SCNTAB *p_symtab, char *filename)
974 {
975 Elf_Data *sym_data;
976 GElf_Sym T_range, n_range; /* for use with -T and -n */
977 size_t count = 0;
978 size_t sym_size;
979 int index = 1;
980 int found_it = 0;
981 int i;
982 int adj = 0; /* field adjustment for elf64 */
983
984 if (gelf_getclass(elf_file) == ELFCLASS64)
985 adj = 8;
986
987 if (p_symtab == NULL) {
988 (void) fprintf(stderr,
989 "%s: %s: could not get symbol table\n", prog_name, filename);
990 return;
991 }
992
993 /* get symbol table data */
994 sym_data = NULL;
995 sym_size = 0;
996 if ((sym_data =
997 elf_getdata(p_symtab->p_sd, NULL)) == NULL) {
998 (void) printf("\n%s:\n", p_symtab->scn_name);
999 (void) printf("No symbol table data\n");
1000 return;
1001 }
1002 sym_size = sym_data->d_size;
1003
1004 count = sym_size / p_symtab->p_shdr.sh_entsize;
1005
1006 if (n_flag && t_flag && !T_flag) {
1007 /* LINTED */
1008 for (i = 1; i < count; i++) {
1009 (void) gelf_getsym(sym_data, i, &n_range);
1010 if (strcmp(name, (char *)
1011 elf_strptr(elf_file,
1012 p_symtab->p_shdr.sh_link,
1013 n_range.st_name)) != 0) {
1014 continue;
1015 } else {
1016 found_it = 1;
1017 if (!p_flag) {
1018 (void) printf(
1019 "\n ***** SYMBOL TABLE INFORMATION *****\n");
1020 (void) printf(
1021 "[Index] %-*s%-*sType\tBind\tOther\tShndx\tName",
1022 12 + adj, "Value", 9 + adj, "Size");
1023 }
1024 (void) printf("\n%s:\n", p_symtab->scn_name);
1025 print_symtab(elf_file, p_symtab, sym_data,
1026 1, i);
1027 }
1028 } /* end for */
1029 if (!found_it) {
1030 (void) fprintf(stderr, "%s: %s: %s not found\n",
1031 prog_name, filename, name);
1032 }
1033 } else if (T_flag) {
1034 T_num = check_range(T_low, T_hi, count, filename);
1035 if (T_num < 0)
1036 return;
1037
1038 (void) gelf_getsym(sym_data, T_low-1, &T_range);
1039 index = T_low;
1040
1041 if (!p_flag) {
1042 (void) printf(
1043 "\n ***** SYMBOL TABLE INFORMATION *****\n");
1044 (void) printf(
1045 "[Index] %-*s%-*sType\tBind\tOther\tShndx\tName",
1046 12 + adj, "Value", 9 + adj, "Size");
1047 }
1048 (void) printf("\n%s:\n", p_symtab->scn_name);
1049 print_symtab(elf_file, p_symtab, sym_data, T_num, index);
1050 } else {
1051 if (!p_flag) {
1052 (void) printf(
1053 "\n ***** SYMBOL TABLE INFORMATION *****\n");
1054 (void) printf(
1055 "[Index] %-*s%-*sType\tBind\tOther\tShndx\tName",
1056 12 + adj, "Value", 9 + adj, "Size");
1057 }
1058 (void) printf("\n%s:\n", p_symtab->scn_name);
1059 print_symtab(elf_file, p_symtab, sym_data, count-1, 1);
1060 }
1061 }
1062
1063
1064 /*
1065 * Print dynamic linking information. Input is an ELF
1066 * file descriptor, the SCNTAB structure, the number of
1067 * sections, and the filename.
1068 */
1069 static void
dump_dynamic(Elf * elf_file,SCNTAB * p_scns,int num_scns,char * filename)1070 dump_dynamic(Elf *elf_file, SCNTAB *p_scns, int num_scns, char *filename)
1071 {
1072 #define pdyn_Fmtptr "%#llx"
1073
1074 Elf_Data *dyn_data;
1075 GElf_Dyn p_dyn;
1076 GElf_Phdr p_phdr;
1077 GElf_Ehdr p_ehdr;
1078 int index = 1;
1079 int lib_scns = num_scns;
1080 SCNTAB *l_scns = p_scns;
1081 int header_num = 0;
1082 const char *str;
1083
1084 (void) gelf_getehdr(elf_file, &p_ehdr);
1085
1086 if (!p_flag)
1087 (void) printf("\n **** DYNAMIC SECTION INFORMATION ****\n");
1088
1089 for (; num_scns > 0; num_scns--, p_scns++) {
1090 GElf_Word link;
1091 int ii;
1092
1093
1094 if (p_scns->p_shdr.sh_type != SHT_DYNAMIC)
1095 continue;
1096
1097 if (!p_flag) {
1098 (void) printf("%s:\n", p_scns->scn_name);
1099 (void) printf("[INDEX]\tTag Value\n");
1100 }
1101
1102 if ((dyn_data = elf_getdata(p_scns->p_sd, NULL)) == 0) {
1103 (void) fprintf(stderr, "%s: %s: no data in "
1104 "%s section\n", prog_name, filename,
1105 p_scns->scn_name);
1106 return;
1107 }
1108
1109 link = p_scns->p_shdr.sh_link;
1110 ii = 0;
1111
1112 (void) gelf_getdyn(dyn_data, ii++, &p_dyn);
1113 while (p_dyn.d_tag != DT_NULL) {
1114 union {
1115 Conv_inv_buf_t inv;
1116 Conv_dyn_flag_buf_t dyn_flag;
1117 Conv_dyn_flag1_buf_t dyn_flag1;
1118 Conv_dyn_feature1_buf_t dyn_feature1;
1119 Conv_dyn_posflag1_buf_t dyn_posflag1;
1120 } conv_buf;
1121
1122 (void) printf("[%d]\t%-15.15s ", index++,
1123 conv_dyn_tag(p_dyn.d_tag,
1124 p_ehdr.e_ident[EI_OSABI], p_ehdr.e_machine,
1125 DUMP_CONVFMT, &conv_buf.inv));
1126
1127 /*
1128 * It would be nice to use a table driven loop
1129 * here, but the address space is too sparse
1130 * and irregular. A switch is simple and robust.
1131 */
1132 switch (p_dyn.d_tag) {
1133 /*
1134 * Items with an address value
1135 */
1136 case DT_PLTGOT:
1137 case DT_HASH:
1138 case DT_STRTAB:
1139 case DT_RELA:
1140 case DT_SYMTAB:
1141 case DT_INIT:
1142 case DT_FINI:
1143 case DT_REL:
1144 case DT_DEBUG:
1145 case DT_TEXTREL:
1146 case DT_JMPREL:
1147 case DT_INIT_ARRAY:
1148 case DT_FINI_ARRAY:
1149 case DT_INIT_ARRAYSZ:
1150 case DT_FINI_ARRAYSZ:
1151 case DT_PREINIT_ARRAY:
1152 case DT_PREINIT_ARRAYSZ:
1153 case DT_SUNW_RTLDINF:
1154 case DT_SUNW_CAP:
1155 case DT_SUNW_CAPINFO:
1156 case DT_SUNW_CAPCHAIN:
1157 case DT_SUNW_SYMTAB:
1158 case DT_SUNW_SYMSORT:
1159 case DT_SUNW_TLSSORT:
1160 case DT_PLTPAD:
1161 case DT_MOVETAB:
1162 case DT_SYMINFO:
1163 case DT_RELACOUNT:
1164 case DT_RELCOUNT:
1165 case DT_VERSYM:
1166 case DT_VERDEF:
1167 case DT_VERDEFNUM:
1168 case DT_VERNEED:
1169 (void) printf(pdyn_Fmtptr,
1170 EC_ADDR(p_dyn.d_un.d_ptr));
1171 break;
1172
1173 /*
1174 * Items with a string value
1175 */
1176 case DT_NEEDED:
1177 case DT_SONAME:
1178 case DT_RPATH:
1179 case DT_RUNPATH:
1180 case DT_SUNW_AUXILIARY:
1181 case DT_SUNW_FILTER:
1182 case DT_CONFIG:
1183 case DT_DEPAUDIT:
1184 case DT_AUDIT:
1185 case DT_AUXILIARY:
1186 case DT_USED:
1187 case DT_FILTER:
1188 if (v_flag) { /* Look up the string */
1189 str = (char *)elf_strptr(elf_file, link,
1190 p_dyn.d_un.d_ptr);
1191 if (!(str && *str))
1192 str = (char *)UNKNOWN;
1193 (void) printf("%s", str);
1194 } else { /* Show the address */
1195 (void) printf(pdyn_Fmtptr,
1196 EC_ADDR(p_dyn.d_un.d_ptr));
1197 }
1198 break;
1199
1200 /*
1201 * Items with a literal value
1202 */
1203 case DT_PLTRELSZ:
1204 case DT_RELASZ:
1205 case DT_RELAENT:
1206 case DT_STRSZ:
1207 case DT_SYMENT:
1208 case DT_RELSZ:
1209 case DT_RELENT:
1210 case DT_PLTREL:
1211 case DT_BIND_NOW:
1212 case DT_CHECKSUM:
1213 case DT_PLTPADSZ:
1214 case DT_MOVEENT:
1215 case DT_MOVESZ:
1216 case DT_SYMINSZ:
1217 case DT_SYMINENT:
1218 case DT_VERNEEDNUM:
1219 case DT_SPARC_REGISTER:
1220 case DT_SUNW_SYMSZ:
1221 case DT_SUNW_SORTENT:
1222 case DT_SUNW_SYMSORTSZ:
1223 case DT_SUNW_TLSSORTSZ:
1224 case DT_SUNW_STRPAD:
1225 case DT_SUNW_CAPCHAINENT:
1226 case DT_SUNW_CAPCHAINSZ:
1227 case DT_SUNW_ASLR:
1228 case DT_SUNW_KMOD:
1229 (void) printf(pdyn_Fmtptr,
1230 EC_XWORD(p_dyn.d_un.d_val));
1231 break;
1232
1233 /*
1234 * Integer items that are bitmasks, or which
1235 * can be otherwise formatted in symbolic form.
1236 */
1237 case DT_FLAGS:
1238 case DT_FEATURE_1:
1239 case DT_POSFLAG_1:
1240 case DT_FLAGS_1:
1241 case DT_SUNW_LDMACH:
1242 str = NULL;
1243 if (v_flag) {
1244 switch (p_dyn.d_tag) {
1245 case DT_FLAGS:
1246 str = conv_dyn_flag(
1247 p_dyn.d_un.d_val,
1248 DUMP_CONVFMT,
1249 &conv_buf.dyn_flag);
1250 break;
1251 case DT_FEATURE_1:
1252 str = conv_dyn_feature1(
1253 p_dyn.d_un.d_val,
1254 DUMP_CONVFMT,
1255 &conv_buf.dyn_feature1);
1256 break;
1257 case DT_POSFLAG_1:
1258 str = conv_dyn_posflag1(
1259 p_dyn.d_un.d_val,
1260 DUMP_CONVFMT,
1261 &conv_buf.dyn_posflag1);
1262 break;
1263 case DT_FLAGS_1:
1264 str = conv_dyn_flag1(
1265 p_dyn.d_un.d_val, 0,
1266 &conv_buf.dyn_flag1);
1267 break;
1268 case DT_SUNW_LDMACH:
1269 str = conv_ehdr_mach(
1270 p_dyn.d_un.d_val, 0,
1271 &conv_buf.inv);
1272 break;
1273 }
1274 }
1275 if (str) { /* Show as string */
1276 (void) printf("%s", str);
1277 } else { /* Numeric form */
1278 (void) printf(pdyn_Fmtptr,
1279 EC_ADDR(p_dyn.d_un.d_ptr));
1280 }
1281 break;
1282
1283 /*
1284 * Depreciated items with a literal value
1285 */
1286 case DT_DEPRECATED_SPARC_REGISTER:
1287 (void) printf(pdyn_Fmtptr
1288 " (deprecated value)",
1289 EC_XWORD(p_dyn.d_un.d_val));
1290 break;
1291
1292 /* Ignored items */
1293 case DT_SYMBOLIC:
1294 (void) printf("(ignored)");
1295 break;
1296 }
1297 (void) printf("\n");
1298 (void) gelf_getdyn(dyn_data, ii++, &p_dyn);
1299 }
1300 }
1301
1302 /*
1303 * Check for existence of static shared library information.
1304 */
1305 while (header_num < p_ehdr.e_phnum) {
1306 (void) gelf_getphdr(elf_file, header_num, &p_phdr);
1307 if (p_phdr.p_type == PT_SHLIB) {
1308 while (--lib_scns > 0) {
1309 if (strcmp(l_scns->scn_name, ".lib") == 0) {
1310 print_static(l_scns, filename);
1311 }
1312 l_scns++;
1313 }
1314 }
1315 header_num++;
1316 }
1317 #undef pdyn_Fmtptr
1318 }
1319
1320 /*
1321 * Print the ELF header. Input is an ELF file descriptor
1322 * and the filename. If f_flag is set, the ELF header is
1323 * printed to stdout, otherwise the function returns after
1324 * setting the pointer to the ELF header. Any values which
1325 * are not known are printed in decimal. Fields must be updated
1326 * as new values are added.
1327 */
1328 static GElf_Ehdr *
dump_elf_header(Elf * elf_file,char * filename,GElf_Ehdr * elf_head_p)1329 dump_elf_header(Elf *elf_file, char *filename, GElf_Ehdr * elf_head_p)
1330 {
1331 int class;
1332 int field;
1333
1334 if (gelf_getehdr(elf_file, elf_head_p) == NULL) {
1335 (void) fprintf(stderr, "%s: %s: %s\n", prog_name, filename,
1336 elf_errmsg(-1));
1337 return (NULL);
1338 }
1339
1340 class = (int)elf_head_p->e_ident[4];
1341
1342 if (class == ELFCLASS64)
1343 field = 21;
1344 else
1345 field = 13;
1346
1347 if (!f_flag)
1348 return (elf_head_p);
1349
1350 if (!p_flag) {
1351 (void) printf("\n **** ELF HEADER ****\n");
1352 (void) printf("%-*s%-11s%-*sMachine Version\n",
1353 field, "Class", "Data", field, "Type");
1354 (void) printf("%-*s%-11s%-*sFlags Ehsize\n",
1355 field, "Entry", "Phoff", field, "Shoff");
1356 (void) printf("%-*s%-11s%-*sShnum Shstrndx\n\n",
1357 field, "Phentsize", "Phnum", field, "Shentsz");
1358 }
1359
1360 if (!v_flag) {
1361 (void) printf("%-*d%-11d%-*d%-12d%d\n",
1362 field, elf_head_p->e_ident[4], elf_head_p->e_ident[5],
1363 field, (int)elf_head_p->e_type, (int)elf_head_p->e_machine,
1364 elf_head_p->e_version);
1365 } else {
1366 Conv_inv_buf_t inv_buf;
1367
1368 (void) printf("%-*s", field,
1369 conv_ehdr_class(class, DUMP_CONVFMT, &inv_buf));
1370 (void) printf("%-11s",
1371 conv_ehdr_data(elf_head_p->e_ident[5], DUMP_CONVFMT,
1372 &inv_buf));
1373 (void) printf("%-*s", field,
1374 conv_ehdr_type(elf_head_p->e_ident[EI_OSABI],
1375 elf_head_p->e_type, DUMP_CONVFMT, &inv_buf));
1376 (void) printf("%-12s",
1377 conv_ehdr_mach(elf_head_p->e_machine, DUMP_CONVFMT,
1378 &inv_buf));
1379 (void) printf("%s\n",
1380 conv_ehdr_vers(elf_head_p->e_version, DUMP_CONVFMT,
1381 &inv_buf));
1382 }
1383 (void) printf("%-#*llx%-#11llx%-#*llx%-#12x%#x\n",
1384 field, EC_ADDR(elf_head_p->e_entry), EC_OFF(elf_head_p->e_phoff),
1385 field, EC_OFF(elf_head_p->e_shoff), EC_WORD(elf_head_p->e_flags),
1386 EC_WORD(elf_head_p->e_ehsize));
1387 if (!v_flag || (elf_head_p->e_shstrndx != SHN_XINDEX)) {
1388 (void) printf("%-#*x%-11u%-#*x%-12u%u\n",
1389 field, EC_WORD(elf_head_p->e_phentsize),
1390 EC_WORD(elf_head_p->e_phnum),
1391 field, EC_WORD(elf_head_p->e_shentsize),
1392 EC_WORD(elf_head_p->e_shnum),
1393 EC_WORD(elf_head_p->e_shstrndx));
1394 } else {
1395 (void) printf("%-#*x%-11u%-#*x%-12uXINDEX\n",
1396 field, EC_WORD(elf_head_p->e_phentsize),
1397 EC_WORD(elf_head_p->e_phnum),
1398 field, EC_WORD(elf_head_p->e_shentsize),
1399 EC_WORD(elf_head_p->e_shnum));
1400 }
1401 if ((elf_head_p->e_shnum == 0) && (elf_head_p->e_shoff > 0)) {
1402 Elf_Scn *scn;
1403 GElf_Shdr shdr0;
1404 int field;
1405
1406 if (gelf_getclass(elf_file) == ELFCLASS64)
1407 field = 21;
1408 else
1409 field = 13;
1410 if (!p_flag) {
1411 (void) printf("\n **** SECTION HEADER[0] "
1412 "{Elf Extensions} ****\n");
1413 (void) printf(
1414 "[No]\tType\tFlags\t%-*s %-*s%-*s%sName\n",
1415 field, "Addr", field, "Offset", field,
1416 "Size(shnum)",
1417 /* compatibility: tab for elf32 */
1418 (field == 13) ? "\t" : " ");
1419 (void) printf("\tLn(strndx) Info\t%-*s Entsize\n",
1420 field, "Adralgn");
1421 }
1422 if ((scn = elf_getscn(elf_file, 0)) == NULL) {
1423 (void) fprintf(stderr,
1424 "%s: %s: elf_getscn failed: %s\n",
1425 prog_name, filename, elf_errmsg(-1));
1426 return (NULL);
1427 }
1428 if (gelf_getshdr(scn, &shdr0) == 0) {
1429 (void) fprintf(stderr,
1430 "%s: %s: gelf_getshdr: %s\n",
1431 prog_name, filename, elf_errmsg(-1));
1432 return (NULL);
1433 }
1434 (void) printf("[0]\t%u\t%llu\t", EC_WORD(shdr0.sh_type),
1435 EC_XWORD(shdr0.sh_flags));
1436
1437 (void) printf("%-#*llx %-#*llx%-*llu%s%-*u\n",
1438 field, EC_ADDR(shdr0.sh_addr),
1439 field, EC_OFF(shdr0.sh_offset),
1440 field, EC_XWORD(shdr0.sh_size),
1441 /* compatibility: tab for elf32 */
1442 ((field == 13) ? "\t" : " "),
1443 field, EC_WORD(shdr0.sh_name));
1444
1445 (void) printf("\t%u\t%u\t%-#*llx %-#*llx\n",
1446 EC_WORD(shdr0.sh_link),
1447 EC_WORD(shdr0.sh_info),
1448 field, EC_XWORD(shdr0.sh_addralign),
1449 field, EC_XWORD(shdr0.sh_entsize));
1450 }
1451 (void) printf("\n");
1452
1453 return (elf_head_p);
1454 }
1455
1456 /*
1457 * Print section contents. Input is an ELF file descriptor,
1458 * the ELF header, the SCNTAB structure,
1459 * the number of symbols, and the filename.
1460 * The number of sections,
1461 * and the offset into the SCNTAB structure will be
1462 * set in dump_section if d_flag or n_flag are set.
1463 * If v_flag is set, sections which can be interpreted will
1464 * be interpreted, otherwise raw data will be output in hexidecimal.
1465 */
1466 static void
print_section(Elf * elf_file,GElf_Ehdr * p_ehdr,SCNTAB * p,int num_scns,char * filename)1467 print_section(Elf *elf_file,
1468 GElf_Ehdr *p_ehdr, SCNTAB *p, int num_scns, char *filename)
1469 {
1470 unsigned char *p_sec;
1471 int i;
1472 size_t size;
1473
1474 for (i = 0; i < num_scns; i++, p++) {
1475 GElf_Shdr shdr;
1476
1477 size = 0;
1478 if (s_flag && !v_flag)
1479 p_sec = (unsigned char *)get_rawscn(p->p_sd, &size);
1480 else
1481 p_sec = (unsigned char *)get_scndata(p->p_sd, &size);
1482
1483 if ((gelf_getshdr(p->p_sd, &shdr) != NULL) &&
1484 (shdr.sh_type == SHT_NOBITS)) {
1485 continue;
1486 }
1487 if (s_flag && !v_flag) {
1488 (void) printf("\n%s:\n", p->scn_name);
1489 print_rawdata(p_sec, size);
1490 continue;
1491 }
1492 if (shdr.sh_type == SHT_SYMTAB) {
1493 dump_symbol_table(elf_file, p, filename);
1494 continue;
1495 }
1496 if (shdr.sh_type == SHT_DYNSYM) {
1497 dump_symbol_table(elf_file, p, filename);
1498 continue;
1499 }
1500 if (shdr.sh_type == SHT_STRTAB) {
1501 dump_string_table(p, 1);
1502 continue;
1503 }
1504 if (shdr.sh_type == SHT_RELA) {
1505 dump_reloc_table(elf_file, p_ehdr, p, 1, filename);
1506 continue;
1507 }
1508 if (shdr.sh_type == SHT_REL) {
1509 dump_reloc_table(elf_file, p_ehdr, p, 1, filename);
1510 continue;
1511 }
1512 if (shdr.sh_type == SHT_DYNAMIC) {
1513 dump_dynamic(elf_file, p, 1, filename);
1514 continue;
1515 }
1516
1517 (void) printf("\n%s:\n", p->scn_name);
1518 print_rawdata(p_sec, size);
1519 }
1520 (void) printf("\n");
1521 }
1522
1523 /*
1524 * Print section contents. This function does not print the contents
1525 * of the sections but sets up the parameters and then calls
1526 * print_section to print the contents. Calling another function to print
1527 * the contents allows both -d and -n to work correctly
1528 * simultaneously. Input is an ELF file descriptor, the ELF header,
1529 * the SCNTAB structure, the number of sections, and the filename.
1530 * Set the range of sections if d_flag, and set section name if
1531 * n_flag.
1532 */
1533 static void
dump_section(Elf * elf_file,GElf_Ehdr * p_ehdr,SCNTAB * s,int num_scns,char * filename)1534 dump_section(Elf *elf_file,
1535 GElf_Ehdr *p_ehdr, SCNTAB *s, int num_scns, char *filename)
1536 {
1537 SCNTAB *n_range, *d_range; /* for use with -n and -d modifiers */
1538 int i;
1539 int found_it = 0; /* for use with -n section_name */
1540
1541 if (n_flag) {
1542 n_range = s;
1543
1544 for (i = 0; i < num_scns; i++, n_range++) {
1545 if ((strcmp(name, n_range->scn_name)) != 0)
1546 continue;
1547 else {
1548 found_it = 1;
1549 print_section(elf_file, p_ehdr,
1550 n_range, 1, filename);
1551 }
1552 }
1553
1554 if (!found_it) {
1555 (void) fprintf(stderr, "%s: %s: %s not found\n",
1556 prog_name, filename, name);
1557 }
1558 } /* end n_flag */
1559
1560 if (d_flag) {
1561 d_range = s;
1562 d_num = check_range(d_low, d_hi, num_scns, filename);
1563 if (d_num < 0)
1564 return;
1565 d_range += d_low - 1;
1566
1567 print_section(elf_file, p_ehdr, d_range, d_num, filename);
1568 } /* end d_flag */
1569
1570 if (!n_flag && !d_flag)
1571 print_section(elf_file, p_ehdr, s, num_scns, filename);
1572 }
1573
1574 /*
1575 * Print the section header table. This function does not print the contents
1576 * of the section headers but sets up the parameters and then calls
1577 * print_shdr to print the contents. Calling another function to print
1578 * the contents allows both -d and -n to work correctly
1579 * simultaneously. Input is the SCNTAB structure,
1580 * the number of sections from the ELF header, and the filename.
1581 * Set the range of section headers to print if d_flag, and set
1582 * name of section header to print if n_flag.
1583 */
1584 static void
dump_shdr(Elf * elf_file,SCNTAB * s,int num_scns,char * filename)1585 dump_shdr(Elf *elf_file, SCNTAB *s, int num_scns, char *filename)
1586 {
1587
1588 SCNTAB *n_range, *d_range; /* for use with -n and -d modifiers */
1589 int field;
1590 int i;
1591 int found_it = 0; /* for use with -n section_name */
1592
1593 if (gelf_getclass(elf_file) == ELFCLASS64)
1594 field = 21;
1595 else
1596 field = 13;
1597
1598 if (!p_flag) {
1599 (void) printf("\n **** SECTION HEADER TABLE ****\n");
1600 (void) printf("[No]\tType\tFlags\t%-*s %-*s %-*s%sName\n",
1601 field, "Addr", field, "Offset", field, "Size",
1602 /* compatibility: tab for elf32 */
1603 (field == 13) ? "\t" : " ");
1604 (void) printf("\tLink\tInfo\t%-*s Entsize\n\n",
1605 field, "Adralgn");
1606 }
1607
1608 if (n_flag) {
1609 n_range = s;
1610
1611 for (i = 1; i <= num_scns; i++, n_range++) {
1612 if ((strcmp(name, n_range->scn_name)) != 0)
1613 continue;
1614 else {
1615 found_it = 1;
1616 print_shdr(elf_file, n_range, 1, i);
1617 }
1618 }
1619
1620 if (!found_it) {
1621 (void) fprintf(stderr, "%s: %s: %s not found\n",
1622 prog_name, filename, name);
1623 }
1624 } /* end n_flag */
1625
1626 if (d_flag) {
1627 d_range = s;
1628 d_num = check_range(d_low, d_hi, num_scns, filename);
1629 if (d_num < 0)
1630 return;
1631 d_range += d_low - 1;
1632
1633 print_shdr(elf_file, d_range, d_num, d_low);
1634 } /* end d_flag */
1635
1636 if (!n_flag && !d_flag)
1637 print_shdr(elf_file, s, num_scns, 1);
1638 }
1639
1640 /*
1641 * Process all of the command line options (except
1642 * for -a, -g, -f, and -o). All of the options processed
1643 * by this function require the presence of the section
1644 * header table and will not be processed if it is not present.
1645 * Set up a buffer containing section name, section header,
1646 * and section descriptor for each section in the file. This
1647 * structure is used to avoid duplicate calls to libelf functions.
1648 * Structure members for the symbol table, the debugging information,
1649 * and the line number information are global. All of the
1650 * rest are local.
1651 */
1652 static void
dump_section_table(Elf * elf_file,GElf_Ehdr * elf_head_p,char * filename)1653 dump_section_table(Elf *elf_file, GElf_Ehdr *elf_head_p, char *filename)
1654 {
1655
1656 static SCNTAB *buffer, *p_scns;
1657 Elf_Scn *scn = 0;
1658 char *s_name = NULL;
1659 int found = 0;
1660 unsigned int num_scns;
1661 size_t shstrndx;
1662 size_t shnum;
1663
1664
1665 if (elf_getshdrnum(elf_file, &shnum) == -1) {
1666 (void) fprintf(stderr,
1667 "%s: %s: elf_getshdrnum failed: %s\n",
1668 prog_name, filename, elf_errmsg(-1));
1669 return;
1670 }
1671 if (elf_getshdrstrndx(elf_file, &shstrndx) == -1) {
1672 (void) fprintf(stderr,
1673 "%s: %s: elf_getshdrstrndx failed: %s\n",
1674 prog_name, filename, elf_errmsg(-1));
1675 return;
1676 }
1677
1678 if ((buffer = calloc(shnum, sizeof (SCNTAB))) == NULL) {
1679 (void) fprintf(stderr, "%s: %s: cannot calloc space\n",
1680 prog_name, filename);
1681 return;
1682 }
1683 /* LINTED */
1684 num_scns = (int)shnum - 1;
1685
1686 p_symtab = (SCNTAB *)0;
1687 p_dynsym = (SCNTAB *)0;
1688 p_scns = buffer;
1689 p_head_scns = buffer;
1690
1691 while ((scn = elf_nextscn(elf_file, scn)) != 0) {
1692 if ((gelf_getshdr(scn, &buffer->p_shdr)) == 0) {
1693 (void) fprintf(stderr,
1694 "%s: %s: %s\n", prog_name, filename,
1695 elf_errmsg(-1));
1696 return;
1697 }
1698 s_name = (char *)
1699 elf_strptr(elf_file, shstrndx, buffer->p_shdr.sh_name);
1700 buffer->scn_name = s_name ? s_name : (char *)UNKNOWN;
1701 buffer->p_sd = scn;
1702
1703 if (buffer->p_shdr.sh_type == SHT_SYMTAB) {
1704 found += 1;
1705 p_symtab = buffer;
1706 }
1707 if (buffer->p_shdr.sh_type == SHT_DYNSYM)
1708 p_dynsym = buffer;
1709 buffer++;
1710 }
1711
1712 /*
1713 * These functions depend upon the presence of the section header table
1714 * and will not be invoked in its absence
1715 */
1716 if (h_flag) {
1717 dump_shdr(elf_file, p_scns, num_scns, filename);
1718 }
1719 if (p_symtab && (t_flag || T_flag)) {
1720 dump_symbol_table(elf_file, p_symtab, filename);
1721 }
1722 if (c_flag) {
1723 dump_string_table(p_scns, num_scns);
1724 }
1725 if (r_flag) {
1726 dump_reloc_table(elf_file, elf_head_p,
1727 p_scns, num_scns, filename);
1728 }
1729 if (L_flag) {
1730 dump_dynamic(elf_file, p_scns, num_scns, filename);
1731 }
1732 if (s_flag) {
1733 dump_section(elf_file, elf_head_p, p_scns,
1734 num_scns, filename);
1735 }
1736 }
1737
1738 /*
1739 * Load the archive string table(s) (for extended-length strings)
1740 * into an in-core table/list
1741 */
1742 static struct stab_list_s *
load_arstring_table(struct stab_list_s * STabList,int fd,Elf * elf_file,Elf_Arhdr * p_ar,char * filename)1743 load_arstring_table(struct stab_list_s *STabList,
1744 int fd, Elf *elf_file, Elf_Arhdr *p_ar, char *filename)
1745 {
1746 off_t here;
1747 struct stab_list_s *STL_entry, *STL_next;
1748
1749 if (p_ar) {
1750 STL_entry = malloc(sizeof (struct stab_list_s));
1751 STL_entry->next = 0;
1752 STL_entry->strings = 0;
1753 STL_entry->size = 0;
1754
1755 if (!STabList)
1756 STabList = STL_entry;
1757 else {
1758 STL_next = STabList;
1759 while (STL_next->next != (void *)0)
1760 STL_next = STL_next->next;
1761 STL_next->next = STL_entry;
1762 }
1763
1764 STL_entry->size = p_ar->ar_size;
1765 STL_entry->strings = malloc(p_ar->ar_size);
1766 here = elf_getbase(elf_file);
1767 if ((lseek(fd, here, 0)) != here) {
1768 (void) fprintf(stderr,
1769 "%s: %s: could not lseek\n", prog_name, filename);
1770 }
1771
1772 if ((read(fd, STL_entry->strings, p_ar->ar_size)) == -1) {
1773 (void) fprintf(stderr,
1774 "%s: %s: could not read\n", prog_name, filename);
1775 }
1776 }
1777 return (STabList);
1778 }
1779
1780 /*
1781 * Print the archive header for each member of an archive.
1782 * Also call ar_sym_read to print the symbols in the
1783 * archive symbol table if g_flag. Input is a file descriptor,
1784 * an ELF file descriptor, and the filename. Putting the call
1785 * to dump the archive symbol table in this function is more
1786 * efficient since it is necessary to examine the archive member
1787 * name in the archive header to determine which member is the
1788 * symbol table.
1789 */
1790 static void
dump_ar_hdr(int fd,Elf * elf_file,char * filename)1791 dump_ar_hdr(int fd, Elf *elf_file, char *filename)
1792 {
1793 extern int v_flag, g_flag, a_flag, p_flag;
1794 Elf_Arhdr *p_ar;
1795 Elf *arf;
1796 Elf_Cmd cmd;
1797 int title = 0;
1798 int err = 0;
1799
1800 char buf[DATESIZE];
1801
1802 cmd = ELF_C_READ;
1803 while ((arf = elf_begin(fd, cmd, elf_file)) != 0) {
1804 p_ar = elf_getarhdr(arf);
1805 if (p_ar == NULL) {
1806 (void) fprintf(stderr,
1807 "%s: %s: %s\n", prog_name, filename,
1808 elf_errmsg(-1));
1809 continue;
1810 }
1811 if ((strcmp(p_ar->ar_name, "/") == 0) ||
1812 (strcmp(p_ar->ar_name, "/SYM64/") == 0)) {
1813 if (g_flag)
1814 ar_sym_read(elf_file, filename);
1815 } else if (strcmp(p_ar->ar_name, "//") == 0) {
1816 StringTableList = load_arstring_table(
1817 StringTableList, fd, arf, p_ar, filename);
1818 cmd = elf_next(arf);
1819 (void) elf_end(arf);
1820 continue;
1821 } else {
1822 if (a_flag) {
1823 (void) printf("%s[%s]:\n", filename,
1824 p_ar->ar_name);
1825 if (!p_flag && title == 0) {
1826 if (!v_flag)
1827 (void) printf(
1828 "\n\n\t\t\t***ARCHIVE HEADER***"
1829 "\n Date Uid Gid Mode Size Member Name\n\n");
1830 else
1831 (void) printf(
1832 "\n\n\t\t\t***ARCHIVE HEADER***"
1833 "\n Date Uid Gid Mode Size Member Name\n\n");
1834 title = 1;
1835 }
1836 if (!v_flag) {
1837 (void) printf(
1838 "\t0x%.8lx %6d %6d 0%.6ho 0x%.8lx %-s\n\n",
1839 p_ar->ar_date, (int)p_ar->ar_uid,
1840 (int)p_ar->ar_gid,
1841 (int)p_ar->ar_mode,
1842 p_ar->ar_size, p_ar->ar_name);
1843 } else {
1844 if ((strftime(buf, DATESIZE,
1845 "%b %d %H:%M:%S %Y",
1846 localtime(
1847 &(p_ar->ar_date)))) == 0) {
1848 (void) fprintf(stderr,
1849 "%s: %s: don't have enough space to store the date\n", prog_name, filename);
1850 exit(1);
1851 }
1852 (void) printf(
1853 "\t%s %6d %6d 0%.6ho 0x%.8lx %-s\n\n",
1854 buf, (int)p_ar->ar_uid,
1855 (int)p_ar->ar_gid,
1856 (int)p_ar->ar_mode,
1857 p_ar->ar_size, p_ar->ar_name);
1858 }
1859 }
1860 }
1861 cmd = elf_next(arf);
1862 (void) elf_end(arf);
1863 } /* end while */
1864
1865 err = elf_errno();
1866 if (err != 0) {
1867 (void) fprintf(stderr,
1868 "%s: %s: %s\n", prog_name, filename, elf_errmsg(err));
1869 }
1870 }
1871
1872 /*
1873 * Process member files of an archive. This function provides
1874 * a loop through an archive equivalent the processing of
1875 * each_file for individual object files.
1876 */
1877 static void
dump_ar_files(int fd,Elf * elf_file,char * filename)1878 dump_ar_files(int fd, Elf *elf_file, char *filename)
1879 {
1880 Elf_Arhdr *p_ar;
1881 Elf *arf;
1882 Elf_Cmd cmd;
1883 Elf_Kind file_type;
1884 GElf_Ehdr elf_head;
1885 char *fullname;
1886
1887 cmd = ELF_C_READ;
1888 while ((arf = elf_begin(fd, cmd, elf_file)) != 0) {
1889 size_t len;
1890
1891 p_ar = elf_getarhdr(arf);
1892 if (p_ar == NULL) {
1893 (void) fprintf(stderr, "%s: %s: %s\n",
1894 prog_name, filename, elf_errmsg(-1));
1895 return;
1896 }
1897 if (p_ar->ar_name[0] == '/') {
1898 cmd = elf_next(arf);
1899 (void) elf_end(arf);
1900 continue;
1901 }
1902
1903 len = strlen(filename) + strlen(p_ar->ar_name) + 3;
1904 if ((fullname = malloc(len)) == NULL)
1905 return;
1906 (void) snprintf(fullname, len, "%s[%s]", filename,
1907 p_ar->ar_name);
1908 (void) printf("\n%s:\n", fullname);
1909 file_type = elf_kind(arf);
1910 if (file_type == ELF_K_ELF) {
1911 if (dump_elf_header(arf, fullname, &elf_head) == NULL)
1912 return;
1913 if (o_flag)
1914 dump_exec_header(arf,
1915 (unsigned)elf_head.e_phnum, fullname);
1916 if (x_flag)
1917 dump_section_table(arf, &elf_head, fullname);
1918 } else {
1919 (void) fprintf(stderr, "%s: %s: invalid file type\n",
1920 prog_name, fullname);
1921 cmd = elf_next(arf);
1922 (void) elf_end(arf);
1923 continue;
1924 }
1925
1926 cmd = elf_next(arf);
1927 (void) elf_end(arf);
1928 } /* end while */
1929 }
1930
1931 /*
1932 * Takes a filename as input. Test first for a valid version
1933 * of libelf.a and exit on error. Process each valid file
1934 * or archive given as input on the command line. Check
1935 * for file type. If it is an archive, process the archive-
1936 * specific options first, then files within the archive.
1937 * If it is an ELF object file, process it; otherwise
1938 * warn that it is an invalid file type.
1939 * All options except the archive-specific and program
1940 * execution header are processed in the function, dump_section_table.
1941 */
1942 static void
each_file(char * filename)1943 each_file(char *filename)
1944 {
1945 Elf *elf_file;
1946 GElf_Ehdr elf_head;
1947 int fd;
1948 Elf_Kind file_type;
1949
1950 struct stat buf;
1951
1952 Elf_Cmd cmd;
1953 errno = 0;
1954
1955 if (stat(filename, &buf) == -1) {
1956 int err = errno;
1957 (void) fprintf(stderr, "%s: %s: %s", prog_name, filename,
1958 strerror(err));
1959 return;
1960 }
1961
1962 if ((fd = open((filename), O_RDONLY)) == -1) {
1963 (void) fprintf(stderr, "%s: %s: cannot read\n", prog_name,
1964 filename);
1965 return;
1966 }
1967 cmd = ELF_C_READ;
1968 if ((elf_file = elf_begin(fd, cmd, (Elf *)0)) == NULL) {
1969 (void) fprintf(stderr, "%s: %s: %s\n", prog_name, filename,
1970 elf_errmsg(-1));
1971 return;
1972 }
1973
1974 file_type = elf_kind(elf_file);
1975 if (file_type == ELF_K_AR) {
1976 if (a_flag || g_flag) {
1977 dump_ar_hdr(fd, elf_file, filename);
1978 elf_file = elf_begin(fd, cmd, (Elf *)0);
1979 }
1980 if (z_flag)
1981 dump_ar_files(fd, elf_file, filename);
1982 } else {
1983 if (file_type == ELF_K_ELF) {
1984 (void) printf("\n%s:\n", filename);
1985 if (dump_elf_header(elf_file, filename, &elf_head)) {
1986 if (o_flag)
1987 dump_exec_header(elf_file,
1988 (unsigned)elf_head.e_phnum,
1989 filename);
1990 if (x_flag)
1991 dump_section_table(elf_file,
1992 &elf_head, filename);
1993 }
1994 } else {
1995 (void) fprintf(stderr, "%s: %s: invalid file type\n",
1996 prog_name, filename);
1997 }
1998 }
1999 (void) elf_end(elf_file);
2000 (void) close(fd);
2001 }
2002
2003 /*
2004 * Sets up flags for command line options given and then
2005 * calls each_file() to process each file.
2006 */
2007 int
main(int argc,char * argv[],char * envp[])2008 main(int argc, char *argv[], char *envp[])
2009 {
2010 char *optstr = OPTSTR; /* option string used by getopt() */
2011 int optchar;
2012
2013 prog_name = argv[0];
2014
2015 (void) setlocale(LC_ALL, "");
2016 while ((optchar = getopt(argc, argv, optstr)) != -1) {
2017 switch (optchar) {
2018 case 'a':
2019 a_flag = 1;
2020 x_flag = 1;
2021 break;
2022 case 'g':
2023 g_flag = 1;
2024 x_flag = 1;
2025 break;
2026 case 'v':
2027 v_flag = 1;
2028 break;
2029 case 'p':
2030 p_flag = 1;
2031 break;
2032 case 'f':
2033 f_flag = 1;
2034 z_flag = 1;
2035 break;
2036 case 'o':
2037 o_flag = 1;
2038 z_flag = 1;
2039 break;
2040 case 'h':
2041 h_flag = 1;
2042 x_flag = 1;
2043 z_flag = 1;
2044 break;
2045 case 's':
2046 s_flag = 1;
2047 x_flag = 1;
2048 z_flag = 1;
2049 break;
2050 case 'd':
2051 d_flag = 1;
2052 x_flag = 1;
2053 z_flag = 1;
2054 set_range(optarg, &d_low, &d_hi);
2055 break;
2056 case 'n':
2057 n_flag++;
2058 x_flag = 1;
2059 z_flag = 1;
2060 name = optarg;
2061 break;
2062 case 'r':
2063 r_flag = 1;
2064 x_flag = 1;
2065 z_flag = 1;
2066 break;
2067 case 't':
2068 t_flag = 1;
2069 x_flag = 1;
2070 z_flag = 1;
2071 break;
2072 case 'C':
2073 C_flag = 1;
2074 t_flag = 1;
2075 x_flag = 1;
2076 z_flag = 1;
2077 break;
2078 case 'T':
2079 T_flag = 1;
2080 x_flag = 1;
2081 z_flag = 1;
2082 set_range(optarg, &T_low, &T_hi);
2083 break;
2084 case 'c':
2085 c_flag = 1;
2086 x_flag = 1;
2087 z_flag = 1;
2088 break;
2089 case 'L':
2090 L_flag = 1;
2091 x_flag = 1;
2092 z_flag = 1;
2093 break;
2094 case 'V':
2095 V_flag = 1;
2096 (void) fprintf(stderr, "dump: %s %s\n",
2097 (const char *)SGU_PKG,
2098 (const char *)SGU_REL);
2099 break;
2100 case '?':
2101 errflag += 1;
2102 break;
2103 default:
2104 break;
2105 }
2106 }
2107
2108 if (errflag || (optind >= argc) || (!z_flag && !x_flag)) {
2109 if (!(V_flag && (argc == 2))) {
2110 usage();
2111 exit(269);
2112 }
2113 }
2114
2115 if (elf_version(EV_CURRENT) == EV_NONE) {
2116 (void) fprintf(stderr, "%s: libelf is out of date\n",
2117 prog_name);
2118 exit(101);
2119 }
2120
2121 while (optind < argc) {
2122 each_file(argv[optind]);
2123 optind++;
2124 }
2125 return (0);
2126 }
2127