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.
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.
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]
23 * Copyright (c) 1988 AT&T
26 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
29 /* Get definitions for the relocation types supported. */
30 #define ELF_TARGET_ALL
39 #include <sys/machelf.h>
49 #define OPTSTR "agcd:fhn:oprstvCLT:V?" /* option string for getopt() */
51 const char *UNKNOWN
= "<unknown>";
53 static SCNTAB
*p_symtab
, *p_head_scns
, *p_dynsym
;
56 x_flag
= 0, /* option requires section header table */
57 z_flag
= 0, /* process files within an archive */
58 rn_flag
= 0; /* dump named relocation information */
61 /* flags: ?_flag corresponds to ? option */
62 a_flag
= 0, /* dump archive header of each member of archive */
63 g_flag
= 0, /* dump archive symbol table */
64 c_flag
= 0, /* dump the string table */
65 d_flag
= 0, /* dump range of sections */
66 f_flag
= 0, /* dump each file header */
67 h_flag
= 0, /* dump section headers */
68 n_flag
= 0, /* dump named section */
69 o_flag
= 0, /* dump each program execution header */
70 r_flag
= 0, /* dump relocation information */
71 s_flag
= 0, /* dump section contents */
72 t_flag
= 0, /* dump symbol table entries */
73 C_flag
= 0, /* dump decoded C++ symbol names */
74 L_flag
= 0, /* dump dynamic linking information */
75 T_flag
= 0, /* dump symbol table range */
76 V_flag
= 0; /* dump version information */
78 int p_flag
= 0, /* suppress printing of headings */
79 v_flag
= 0; /* print information in verbose form */
82 d_low
= 0, /* range for use with -d */
87 T_low
= 0, /* range for use with -T */
91 static char *name
= NULL
; /* for use with -n option */
93 static int errflag
= 0;
95 static struct stab_list_s
{
96 struct stab_list_s
*next
;
99 } *StringTableList
= NULL
;
101 extern void ar_sym_read();
102 extern void dump_exec_header();
106 * Get the section descriptor and set the size of the
107 * data returned. Data is byte-order converted.
110 get_scndata(Elf_Scn
*fd_scn
, size_t *size
)
115 if ((p_data
= elf_getdata(fd_scn
, p_data
)) == 0 ||
116 p_data
->d_size
== 0) {
119 *size
= p_data
->d_size
;
120 return (p_data
->d_buf
);
124 * Get the section descriptor and set the size of the
125 * data returned. Data is raw (i.e., not byte-order converted).
128 get_rawscn(Elf_Scn
*fd_scn
, size_t *size
)
133 if ((p_data
= elf_rawdata(fd_scn
, p_data
)) == 0 ||
134 p_data
->d_size
== 0) {
138 *size
= p_data
->d_size
;
139 return (p_data
->d_buf
);
143 * Print out a usage message in short form when program is invoked
144 * with insufficient or no arguments, and in long form when given
145 * either a ? or an invalid option.
150 (void) fprintf(stderr
,
151 "Usage: %s [-%s] file(s) ...\n", prog_name
, OPTSTR
);
153 (void) fprintf(stderr
,
154 "\t\t[-a dump archive header of each member of archive]\n\
155 [-g dump archive global symbol table]\n\
156 [-c dump the string table]\n\
157 [-d dump range of sections]\n\
158 [-f dump each file header]\n\
159 [-h dump section headers]\n\
160 [-n dump named section]\n\
161 [-o dump each program execution header]\n\
162 [-p suppress printing of headings]\n\
163 [-r dump relocation information]\n\
164 [-s dump section contents]\n\
165 [-t dump symbol table entries]\n\
166 [-v print information in verbose form]\n\
167 [-C dump decoded C++ symbol names]\n\
168 [-L dump the .dynamic structure]\n\
169 [-T dump symbol table range]\n\
170 [-V dump version information]\n");
175 * Set a range. Input is a character string, a lower
176 * bound and an upper bound. This function converts
177 * a character string into its correct integer values,
178 * setting the first value as the lower bound, and
179 * the second value as the upper bound. If more values
180 * are given they are ignored with a warning.
183 set_range(char *s
, int *low
, int *high
)
188 while ((w
= strtok_r(s
, ",", &lasts
)) != NULL
) {
195 *high
= (int)atol(w
);
197 (void) fprintf(stderr
,
198 "%s: too many arguments - %s ignored\n",
208 * Print static shared library information.
211 print_static(SCNTAB
*l_scns
, char *filename
)
214 unsigned char *strtab
;
215 unsigned char *path
, buf
[1024];
217 unsigned long total
, topath
;
219 (void) printf("\n **** STATIC SHARED LIBRARY INFORMATION ****\n");
220 (void) printf("\n%s:\n", filename
);
223 if ((strtab
= (unsigned char *)
224 get_scndata(l_scns
->p_sd
, §ion_size
)) == NULL
) {
228 while (section_size
!= 0) {
230 temp
= (unsigned long *)strtab
;
233 path
= strtab
+ (topath
*sizeof (long));
234 (void) strncpy((char *)buf
, (char *)path
,
235 (total
- topath
)*sizeof (long));
236 (void) fprintf(stdout
, "%s\n", buf
);
237 strtab
+= total
*sizeof (long);
238 section_size
-= (total
*sizeof (long));
243 * Print raw data in hexidecimal. Input is the section data to
244 * be printed out and the size of the data. Output is relative
245 * to a table lookup in dumpmap.h.
248 print_rawdata(unsigned char *p_sec
, size_t size
)
256 for (j
= size
/sizeof (short); j
!= 0; --j
, ++count
) {
257 (void) printf("%.2x %.2x ", p_sec
[0], p_sec
[1]);
260 (void) printf("\n\t");
266 * take care of last byte if odd byte section
268 if ((size
& 0x1L
) == 1L)
269 (void) printf("%.2x", *p_sec
);
276 * Print relocation data of type SHT_RELA
277 * If d_flag, print data corresponding only to
278 * the section or range of sections specified.
279 * If n_flag, print data corresponding only to
283 print_rela(Elf
*elf_file
, SCNTAB
*p_scns
, Elf_Data
*rdata
, Elf_Data
*sym_data
,
284 GElf_Ehdr
* p_ehdr
, size_t reloc_size
, size_t sym_size
, char *filename
,
285 SCNTAB
*reloc_symtab
)
293 static int n_title
= 0;
298 if (gelf_getclass(elf_file
) == ELFCLASS64
)
301 rel_entsize
= p_scns
->p_shdr
.sh_entsize
;
302 if ((rel_entsize
== 0) ||
303 (rel_entsize
> p_scns
->p_shdr
.sh_size
)) {
304 rel_entsize
= gelf_fsize(elf_file
, ELF_T_RELA
, 1,
307 no_entries
= reloc_size
/ rel_entsize
;
309 no_syms
= sym_size
/ gelf_fsize(elf_file
, ELF_T_SYM
, 1, EV_CURRENT
);
310 while (no_entries
--) {
311 (void) gelf_getrela(rdata
, ndx
, &rela
);
313 type
= (int)GELF_R_TYPE(rela
.r_info
);
315 symid
= (int)GELF_R_SYM(rela
.r_info
);
317 if ((symid
> (no_syms
- 1)) || (symid
< 0)) {
318 (void) fprintf(stderr
, "%s: %s: invalid symbol table "
319 "offset - %d - in %s\n", prog_name
, filename
,
320 symid
, p_scns
->scn_name
);
324 (void) gelf_getsym(sym_data
, symid
, &sym
);
325 sym_name
= (char *)elf_strptr(elf_file
,
326 reloc_symtab
->p_shdr
.sh_link
, sym
.st_name
);
327 if (sym_name
== NULL
)
328 sym_name
= (char *)UNKNOWN
;
329 if (r_flag
&& rn_flag
) {
330 if (strcmp(name
, p_scns
->scn_name
) != 0) {
335 (void) printf("\n%s:\n", p_scns
->scn_name
);
336 (void) printf("%-*s%-*s%-*s%s\n\n",
337 12 + adj
, "Offset", 22, "Symndx",
338 16, "Type", "Addend");
345 if ((symid
< d_low
) || (symid
> d_hi
)) {
351 (void) printf("%-#*llx", 12 + adj
, EC_XWORD(rela
.r_offset
));
353 (void) printf("%-22d%-18d", symid
, type
);
355 Conv_inv_buf_t inv_buf
;
357 if (strlen(sym_name
)) {
358 size_t len
= strlen(sym_name
) + 1;
361 (void) sprintf(tmpstr
, "%%-%ds",
364 /*LINTED: E_SEC_PRINTF_VAR_FMT*/
365 (void) printf(tmpstr
, sym_name
);
367 (void) printf("%-22s", sym_name
);
369 (void) printf("%-22d", symid
);
371 (void) printf("%-20s",
372 conv_reloc_type(p_ehdr
->e_machine
,
373 type
, DUMP_CONVFMT
, &inv_buf
));
375 (void) printf("%lld\n", EC_SXWORD(rela
.r_addend
));
381 * Print relocation data of type SHT_REL.
382 * If d_flag, print data corresponding only to
383 * the section or range of sections specified.
384 * If n_flag, print data corresponding only to
388 print_rel(Elf
*elf_file
, SCNTAB
*p_scns
, Elf_Data
*rdata
, Elf_Data
*sym_data
,
389 GElf_Ehdr
*p_ehdr
, size_t reloc_size
, size_t sym_size
, char *filename
,
390 SCNTAB
*reloc_symtab
)
398 static int n_title
= 0;
403 if (gelf_getclass(elf_file
) == ELFCLASS64
)
406 rel_entsize
= p_scns
->p_shdr
.sh_entsize
;
407 if ((rel_entsize
== 0) ||
408 (rel_entsize
> p_scns
->p_shdr
.sh_size
)) {
409 rel_entsize
= gelf_fsize(elf_file
, ELF_T_REL
, 1,
412 no_entries
= reloc_size
/ rel_entsize
;
414 no_syms
= sym_size
/ gelf_fsize(elf_file
, ELF_T_SYM
, 1, EV_CURRENT
);
415 while (no_entries
--) {
416 (void) gelf_getrel(rdata
, ndx
, &rel
);
418 type
= (int)GELF_R_TYPE(rel
.r_info
);
420 symid
= (int)GELF_R_SYM(rel
.r_info
);
422 if ((symid
> (no_syms
- 1)) || (symid
< 0)) {
423 (void) fprintf(stderr
, "%s: %s: invalid symbol table "
424 "offset - %d - in %s\n", prog_name
, filename
,
425 symid
, p_scns
->scn_name
);
429 (void) gelf_getsym(sym_data
, symid
, &sym
);
430 sym_name
= (char *)elf_strptr(elf_file
,
431 reloc_symtab
->p_shdr
.sh_link
, sym
.st_name
);
432 if (sym_name
== NULL
)
433 sym_name
= (char *)UNKNOWN
;
434 if (r_flag
&& rn_flag
) {
435 if (strcmp(name
, p_scns
->scn_name
) != 0) {
440 (void) printf("\n%s:\n", p_scns
->scn_name
);
441 (void) printf("%-*s%-*s%s\n\n",
442 12 + adj
, "Offset", 20, "Symndx", "Type");
449 if ((symid
< d_low
) || (symid
> d_hi
)) {
455 (void) printf("%-#*llx", 12 + adj
, EC_ADDR(rel
.r_offset
));
457 (void) printf("%-20d%-18d", symid
, type
);
459 Conv_inv_buf_t inv_buf
;
461 if (strlen(sym_name
))
462 (void) printf("%-20s", sym_name
);
464 (void) printf("%-20d", sym
.st_name
);
466 (void) printf("%-20s",
467 conv_reloc_type(p_ehdr
->e_machine
,
468 type
, DUMP_CONVFMT
, &inv_buf
));
475 /* demangle C++ names */
477 demangled_name(char *s
)
479 static char *buf
= NULL
;
483 dn
= conv_demangle_name(s
);
486 * If not demangled, just return the symbol name
488 if (strcmp(s
, dn
) == 0)
492 * Demangled. Format it
496 len
= strlen(dn
) + strlen(s
) + 4;
497 if ((buf
= malloc(len
)) == NULL
)
500 (void) snprintf(buf
, len
, "%s\t[%s]", dn
, s
);
505 * Print the symbol table. Input is an ELF file descriptor, a
506 * pointer to the symbol table SCNTAB structure,
507 * the number of symbols, a range of symbols to print,
508 * an index which is the number of the
509 * section in the file, and the filename. The number of sections,
510 * the range, and the index are set in
511 * dump_symbol_table, depending on whether -n or -T were set.
514 print_symtab(Elf
*elf_file
, SCNTAB
*p_symtab
, Elf_Data
*sym_data
,
515 long range
, int index
)
518 int adj
= 0; /* field adjustment for elf64 */
519 Elf32_Word
*symshndx
= 0;
520 unsigned int nosymshndx
= 0;
521 Conv_inv_buf_t inv_buf
;
524 if (gelf_getclass(elf_file
) == ELFCLASS64
)
528 char *sym_name
= NULL
;
533 (void) gelf_getsym(sym_data
, index
, &sym
);
534 type
= (int)GELF_ST_TYPE(sym
.st_info
);
535 bind
= (int)GELF_ST_BIND(sym
.st_info
);
537 if ((sym
.st_shndx
== SHN_XINDEX
) &&
538 (symshndx
== 0) && (nosymshndx
== 0)) {
543 symscnndx
= elf_ndxscn(p_symtab
->p_sd
);
545 while ((_scn
= elf_nextscn(elf_file
, _scn
)) != 0) {
546 if (gelf_getshdr(_scn
, &_shdr
) == 0)
548 if ((_shdr
.sh_type
== SHT_SYMTAB_SHNDX
) &&
550 (_shdr
.sh_link
== (GElf_Word
)symscnndx
)) {
553 if ((_data
= elf_getdata(_scn
, 0)) == 0)
556 symshndx
= (Elf32_Word
*)_data
->d_buf
;
564 if ((symshndx
) && (sym
.st_shndx
== SHN_XINDEX
)) {
565 shndx
= symshndx
[index
];
568 shndx
= sym
.st_shndx
;
569 if ((sym
.st_shndx
== SHN_UNDEF
) ||
570 (sym
.st_shndx
>= SHN_LORESERVE
))
577 (void) printf("[%d]\t ", index
++);
579 if (v_flag
&& (type
== STT_SPARC_REGISTER
)) {
581 * The strings "REG_G1" through "REG_G7" are intended
582 * to be consistent with output from elfdump(1).
584 (void) printf("%-*s", 12 + adj
,
585 conv_sym_SPARC_value(sym
.st_value
,
586 DUMP_CONVFMT
, &inv_buf
));
588 (void) printf("0x%-*llx", 10 + adj
,
589 EC_ADDR(sym
.st_value
));
592 (void) printf("%-*lld", 9 + adj
, EC_XWORD(sym
.st_size
));
595 (void) printf("%d\t\t%d\t%d\t%#x\t",
596 type
, bind
, (int)sym
.st_other
, (int)shndx
);
599 (void) gelf_getehdr(elf_file
, &p_ehdr
);
600 (void) printf("%s\t",
601 conv_sym_info_type(p_ehdr
.e_machine
, type
,
602 DUMP_CONVFMT
, &inv_buf
));
604 conv_sym_info_bind(bind
, DUMP_CONVFMT
, &inv_buf
));
605 (void) printf("\t %d\t", EC_WORD(sym
.st_other
));
609 conv_sym_shndx(p_ehdr
.e_ident
[EI_OSABI
],
610 p_ehdr
.e_machine
, shndx
,
611 CONV_FMT_DECIMAL
, &inv_buf
));
613 (void) printf("%d", EC_WORD(shndx
));
617 /* support machines where NULL-deref causes core dump */
618 if (sym
.st_name
== 0)
619 sym_name
= (char *)UNKNOWN
;
622 sym_name
= demangled_name(
623 (char *)elf_strptr(elf_file
,
624 p_symtab
->p_shdr
.sh_link
,
627 sym_name
= (char *)elf_strptr(elf_file
,
628 p_symtab
->p_shdr
.sh_link
, sym
.st_name
);
629 if (sym_name
== NULL
)
630 sym_name
= (char *)UNKNOWN
;
631 (void) printf("%s\n", sym_name
);
638 * Print the section header table. Input is the SCNTAB structure,
639 * the number of sections, an index which is the number of the
640 * section in the file, and the filename. The values of the SCNTAB
641 * structure, the number of sections, and the index are set in
642 * dump_shdr depending on whether the -n or -d modifiers were set.
645 print_shdr(Elf
*elf_file
, SCNTAB
*s
, int num_scns
, int index
)
652 if (gelf_getclass(elf_file
) == ELFCLASS64
)
658 (void) gelf_getehdr(elf_file
, &p_ehdr
);
660 for (num
= 0; num
< num_scns
; num
++, p
++) {
661 (void) printf("[%d]\t", index
++);
663 (void) printf("%u\t%llu\t",
664 EC_WORD(p
->p_shdr
.sh_type
),
665 EC_XWORD(p
->p_shdr
.sh_flags
));
667 Conv_inv_buf_t inv_buf
;
669 /*LINTED: E_SEC_PRINTF_VAR_FMT*/
670 (void) printf(conv_sec_type(
671 p_ehdr
.e_ident
[EI_OSABI
], p_ehdr
.e_machine
,
672 p
->p_shdr
.sh_type
, DUMP_CONVFMT
, &inv_buf
));
675 if (p
->p_shdr
.sh_flags
& SHF_WRITE
)
679 if (p
->p_shdr
.sh_flags
& SHF_ALLOC
)
683 if (p
->p_shdr
.sh_flags
& SHF_EXECINSTR
)
688 if (p
->p_shdr
.sh_flags
& SHF_ORDERED
)
690 if (p
->p_shdr
.sh_flags
& SHF_EXCLUDE
)
696 (void) printf("%-#*llx%-#*llx%-#*llx%s%s\n",
697 field
, EC_ADDR(p
->p_shdr
.sh_addr
),
698 field
, EC_OFF(p
->p_shdr
.sh_offset
),
699 field
, EC_XWORD(p
->p_shdr
.sh_size
),
700 /* compatibility: tab for elf32 */
701 (field
== 13) ? "\t" : " ", p
->scn_name
);
703 (void) printf("\t%u\t%u\t%-#*llx%-#*llx\n\n",
704 EC_WORD(p
->p_shdr
.sh_link
),
705 EC_WORD(p
->p_shdr
.sh_info
),
706 field
, EC_XWORD(p
->p_shdr
.sh_addralign
),
707 field
, EC_XWORD(p
->p_shdr
.sh_entsize
));
712 * Check that a range of numbers is valid. Input is
713 * a lower bound, an upper bound, a boundary condition,
714 * and the filename. Negative numbers and numbers greater
715 * than the bound are invalid. low must be smaller than hi.
716 * The returned integer is the number of items in the
717 * range if it is valid and -1 otherwise.
720 check_range(int low
, int hi
, size_t bound
, char *filename
)
722 if (((size_t)low
> bound
) || (low
<= 0)) {
723 (void) fprintf(stderr
,
724 "%s: %s: number out of range, %d\n",
725 prog_name
, filename
, low
);
728 if (((size_t)hi
> bound
) || (hi
< 0)) {
729 (void) fprintf(stderr
,
730 "%s: %s: number out of range, %d\n",
731 prog_name
, filename
, hi
);
735 if (hi
&& (low
> hi
)) {
736 (void) fprintf(stderr
,
737 "%s: %s: invalid range, %d,%d\n",
738 prog_name
, filename
, low
, hi
);
742 return (hi
- low
+ 1);
748 * Print relocation information. Since this information is
749 * machine dependent, new sections must be added for each machine
750 * that is supported. Input is an ELF file descriptor, the ELF header,
751 * the SCNTAB structure, the number of sections, and a filename.
752 * Set up necessary information to print relocation information
753 * and call the appropriate print function depending on the
754 * type of relocation information. If the symbol table is
755 * absent, no relocation data is processed. Input is an
756 * ELF file descriptor, the ELF header, the SCNTAB structure,
757 * and the filename. Set range of d_flag and name if n_flag.
760 dump_reloc_table(Elf
*elf_file
, GElf_Ehdr
*p_ehdr
,
761 SCNTAB
*p_scns
, int num_scns
, char *filename
)
767 SCNTAB
*reloc_symtab
;
773 if (gelf_getclass(elf_file
) == ELFCLASS64
)
776 if ((!p_flag
) && (!r_title
)) {
777 (void) printf("\n **** RELOCATION INFORMATION ****\n");
781 while (num_scns
-- > 0) {
782 if ((p_scns
->p_shdr
.sh_type
!= SHT_RELA
) &&
783 (p_scns
->p_shdr
.sh_type
!= SHT_REL
)) {
788 head_scns
= p_head_scns
;
790 if (elf_getshdrnum(elf_file
, &shnum
) == -1) {
791 (void) fprintf(stderr
,
792 "%s: %s: elf_getshdrnum failed: %s\n",
793 prog_name
, filename
, elf_errmsg(-1));
797 if ((p_scns
->p_shdr
.sh_link
== 0) ||
799 (p_scns
->p_shdr
.sh_link
>= (GElf_Word
)shnum
)) {
800 (void) fprintf(stderr
, "%s: %s: invalid sh_link field: "
801 "section #: %d sh_link: %d\n",
803 prog_name
, filename
, (int)elf_ndxscn(p_scns
->p_sd
),
804 (int)p_scns
->p_shdr
.sh_link
);
807 head_scns
+= (p_scns
->p_shdr
.sh_link
-1);
809 if (head_scns
->p_shdr
.sh_type
== SHT_SYMTAB
) {
810 reloc_symtab
= p_symtab
;
811 } else if (head_scns
->p_shdr
.sh_type
== SHT_DYNSYM
) {
812 reloc_symtab
= p_dynsym
;
814 (void) fprintf(stderr
,
815 "%s: %s: could not get symbol table\n", prog_name
, filename
);
823 if ((sym_data
= elf_getdata(reloc_symtab
->p_sd
, NULL
)) == NULL
) {
824 (void) fprintf(stderr
,
825 "%s: %s: no symbol table data\n", prog_name
, filename
);
828 sym_size
= sym_data
->d_size
;
830 if (p_scns
== NULL
) {
831 (void) fprintf(stderr
,
832 "%s: %s: no section table data\n", prog_name
, filename
);
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
);
848 reloc_size
= rel_data
->d_size
;
852 print_rela(elf_file
, p_scns
, rel_data
, sym_data
, p_ehdr
,
853 reloc_size
, sym_size
, filename
, reloc_symtab
);
857 print_rela(elf_file
, p_scns
, rel_data
, sym_data
, p_ehdr
,
858 reloc_size
, sym_size
, filename
, reloc_symtab
);
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
);
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");
871 if ((rel_data
= elf_getdata(p_scns
->p_sd
, NULL
))
873 (void) fprintf(stderr
,
874 "%s: %s: no relocation information\n", prog_name
, filename
);
877 reloc_size
= rel_data
->d_size
;
880 print_rel(elf_file
, p_scns
, rel_data
, sym_data
,
881 p_ehdr
, reloc_size
, sym_size
,
882 filename
, reloc_symtab
);
886 print_rel(elf_file
, p_scns
, rel_data
, sym_data
,
887 p_ehdr
, reloc_size
, sym_size
,
888 filename
, reloc_symtab
);
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
);
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.
907 dump_string_table(SCNTAB
*s
, int num_scns
)
910 unsigned char *strtab
;
917 (void) printf("\n **** STRING TABLE INFORMATION ****\n");
920 for (i
= 0; i
< num_scns
; i
++, s
++) {
921 if (s
->p_shdr
.sh_type
!= SHT_STRTAB
)
927 (void) printf("\n%s:\n", s
->scn_name
);
928 (void) printf(" <offset> \tName\n");
931 if ((strtab
= (unsigned char *)
932 get_scndata(s
->p_sd
, §ion_size
)) == NULL
) {
936 if (section_size
!= 0) {
937 (void) printf(" <%d> \t", str_off
);
939 while (section_size
--) {
940 unsigned char c
= *strtab
++;
943 (void) printf(" <%d> \t", str_off
);
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.
973 dump_symbol_table(Elf
*elf_file
, SCNTAB
*p_symtab
, char *filename
)
976 GElf_Sym T_range
, n_range
; /* for use with -T and -n */
982 int adj
= 0; /* field adjustment for elf64 */
984 if (gelf_getclass(elf_file
) == ELFCLASS64
)
987 if (p_symtab
== NULL
) {
988 (void) fprintf(stderr
,
989 "%s: %s: could not get symbol table\n", prog_name
, filename
);
993 /* get symbol table 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");
1002 sym_size
= sym_data
->d_size
;
1004 count
= sym_size
/ p_symtab
->p_shdr
.sh_entsize
;
1006 if (n_flag
&& t_flag
&& !T_flag
) {
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) {
1019 "\n ***** SYMBOL TABLE INFORMATION *****\n");
1021 "[Index] %-*s%-*sType\tBind\tOther\tShndx\tName",
1022 12 + adj
, "Value", 9 + adj
, "Size");
1024 (void) printf("\n%s:\n", p_symtab
->scn_name
);
1025 print_symtab(elf_file
, p_symtab
, sym_data
,
1030 (void) fprintf(stderr
, "%s: %s: %s not found\n",
1031 prog_name
, filename
, name
);
1033 } else if (T_flag
) {
1034 T_num
= check_range(T_low
, T_hi
, count
, filename
);
1038 (void) gelf_getsym(sym_data
, T_low
-1, &T_range
);
1043 "\n ***** SYMBOL TABLE INFORMATION *****\n");
1045 "[Index] %-*s%-*sType\tBind\tOther\tShndx\tName",
1046 12 + adj
, "Value", 9 + adj
, "Size");
1048 (void) printf("\n%s:\n", p_symtab
->scn_name
);
1049 print_symtab(elf_file
, p_symtab
, sym_data
, T_num
, index
);
1053 "\n ***** SYMBOL TABLE INFORMATION *****\n");
1055 "[Index] %-*s%-*sType\tBind\tOther\tShndx\tName",
1056 12 + adj
, "Value", 9 + adj
, "Size");
1058 (void) printf("\n%s:\n", p_symtab
->scn_name
);
1059 print_symtab(elf_file
, p_symtab
, sym_data
, count
-1, 1);
1065 * Print dynamic linking information. Input is an ELF
1066 * file descriptor, the SCNTAB structure, the number of
1067 * sections, and the filename.
1070 dump_dynamic(Elf
*elf_file
, SCNTAB
*p_scns
, int num_scns
, char *filename
)
1072 #define pdyn_Fmtptr "%#llx"
1079 int lib_scns
= num_scns
;
1080 SCNTAB
*l_scns
= p_scns
;
1084 (void) gelf_getehdr(elf_file
, &p_ehdr
);
1087 (void) printf("\n **** DYNAMIC SECTION INFORMATION ****\n");
1089 for (; num_scns
> 0; num_scns
--, p_scns
++) {
1094 if (p_scns
->p_shdr
.sh_type
!= SHT_DYNAMIC
)
1098 (void) printf("%s:\n", p_scns
->scn_name
);
1099 (void) printf("[INDEX]\tTag Value\n");
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
,
1109 link
= p_scns
->p_shdr
.sh_link
;
1112 (void) gelf_getdyn(dyn_data
, ii
++, &p_dyn
);
1113 while (p_dyn
.d_tag
!= DT_NULL
) {
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
;
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
));
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.
1132 switch (p_dyn
.d_tag
) {
1134 * Items with an address value
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
:
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
:
1169 (void) printf(pdyn_Fmtptr
,
1170 EC_ADDR(p_dyn
.d_un
.d_ptr
));
1174 * Items with a string value
1180 case DT_SUNW_AUXILIARY
:
1181 case DT_SUNW_FILTER
:
1188 if (v_flag
) { /* Look up the string */
1189 str
= (char *)elf_strptr(elf_file
, link
,
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
));
1201 * Items with a literal value
1219 case DT_SPARC_REGISTER
:
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
:
1228 (void) printf(pdyn_Fmtptr
,
1229 EC_XWORD(p_dyn
.d_un
.d_val
));
1233 * Integer items that are bitmasks, or which
1234 * can be otherwise formatted in symbolic form.
1240 case DT_SUNW_LDMACH
:
1243 switch (p_dyn
.d_tag
) {
1245 str
= conv_dyn_flag(
1248 &conv_buf
.dyn_flag
);
1251 str
= conv_dyn_feature1(
1254 &conv_buf
.dyn_feature1
);
1257 str
= conv_dyn_posflag1(
1260 &conv_buf
.dyn_posflag1
);
1263 str
= conv_dyn_flag1(
1264 p_dyn
.d_un
.d_val
, 0,
1265 &conv_buf
.dyn_flag1
);
1267 case DT_SUNW_LDMACH
:
1268 str
= conv_ehdr_mach(
1269 p_dyn
.d_un
.d_val
, 0,
1274 if (str
) { /* Show as string */
1275 (void) printf("%s", str
);
1276 } else { /* Numeric form */
1277 (void) printf(pdyn_Fmtptr
,
1278 EC_ADDR(p_dyn
.d_un
.d_ptr
));
1283 * Depreciated items with a literal value
1285 case DT_DEPRECATED_SPARC_REGISTER
:
1286 (void) printf(pdyn_Fmtptr
1287 " (deprecated value)",
1288 EC_XWORD(p_dyn
.d_un
.d_val
));
1293 (void) printf("(ignored)");
1296 (void) printf("\n");
1297 (void) gelf_getdyn(dyn_data
, ii
++, &p_dyn
);
1302 * Check for existence of static shared library information.
1304 while (header_num
< p_ehdr
.e_phnum
) {
1305 (void) gelf_getphdr(elf_file
, header_num
, &p_phdr
);
1306 if (p_phdr
.p_type
== PT_SHLIB
) {
1307 while (--lib_scns
> 0) {
1308 if (strcmp(l_scns
->scn_name
, ".lib") == 0) {
1309 print_static(l_scns
, filename
);
1320 * Print the ELF header. Input is an ELF file descriptor
1321 * and the filename. If f_flag is set, the ELF header is
1322 * printed to stdout, otherwise the function returns after
1323 * setting the pointer to the ELF header. Any values which
1324 * are not known are printed in decimal. Fields must be updated
1325 * as new values are added.
1328 dump_elf_header(Elf
*elf_file
, char *filename
, GElf_Ehdr
* elf_head_p
)
1333 if (gelf_getehdr(elf_file
, elf_head_p
) == NULL
) {
1334 (void) fprintf(stderr
, "%s: %s: %s\n", prog_name
, filename
,
1339 class = (int)elf_head_p
->e_ident
[4];
1341 if (class == ELFCLASS64
)
1347 return (elf_head_p
);
1350 (void) printf("\n **** ELF HEADER ****\n");
1351 (void) printf("%-*s%-11s%-*sMachine Version\n",
1352 field
, "Class", "Data", field
, "Type");
1353 (void) printf("%-*s%-11s%-*sFlags Ehsize\n",
1354 field
, "Entry", "Phoff", field
, "Shoff");
1355 (void) printf("%-*s%-11s%-*sShnum Shstrndx\n\n",
1356 field
, "Phentsize", "Phnum", field
, "Shentsz");
1360 (void) printf("%-*d%-11d%-*d%-12d%d\n",
1361 field
, elf_head_p
->e_ident
[4], elf_head_p
->e_ident
[5],
1362 field
, (int)elf_head_p
->e_type
, (int)elf_head_p
->e_machine
,
1363 elf_head_p
->e_version
);
1365 Conv_inv_buf_t inv_buf
;
1367 (void) printf("%-*s", field
,
1368 conv_ehdr_class(class, DUMP_CONVFMT
, &inv_buf
));
1369 (void) printf("%-11s",
1370 conv_ehdr_data(elf_head_p
->e_ident
[5], DUMP_CONVFMT
,
1372 (void) printf("%-*s", field
,
1373 conv_ehdr_type(elf_head_p
->e_ident
[EI_OSABI
],
1374 elf_head_p
->e_type
, DUMP_CONVFMT
, &inv_buf
));
1375 (void) printf("%-12s",
1376 conv_ehdr_mach(elf_head_p
->e_machine
, DUMP_CONVFMT
,
1378 (void) printf("%s\n",
1379 conv_ehdr_vers(elf_head_p
->e_version
, DUMP_CONVFMT
,
1382 (void) printf("%-#*llx%-#11llx%-#*llx%-#12x%#x\n",
1383 field
, EC_ADDR(elf_head_p
->e_entry
), EC_OFF(elf_head_p
->e_phoff
),
1384 field
, EC_OFF(elf_head_p
->e_shoff
), EC_WORD(elf_head_p
->e_flags
),
1385 EC_WORD(elf_head_p
->e_ehsize
));
1386 if (!v_flag
|| (elf_head_p
->e_shstrndx
!= SHN_XINDEX
)) {
1387 (void) printf("%-#*x%-11u%-#*x%-12u%u\n",
1388 field
, EC_WORD(elf_head_p
->e_phentsize
),
1389 EC_WORD(elf_head_p
->e_phnum
),
1390 field
, EC_WORD(elf_head_p
->e_shentsize
),
1391 EC_WORD(elf_head_p
->e_shnum
),
1392 EC_WORD(elf_head_p
->e_shstrndx
));
1394 (void) printf("%-#*x%-11u%-#*x%-12uXINDEX\n",
1395 field
, EC_WORD(elf_head_p
->e_phentsize
),
1396 EC_WORD(elf_head_p
->e_phnum
),
1397 field
, EC_WORD(elf_head_p
->e_shentsize
),
1398 EC_WORD(elf_head_p
->e_shnum
));
1400 if ((elf_head_p
->e_shnum
== 0) && (elf_head_p
->e_shoff
> 0)) {
1405 if (gelf_getclass(elf_file
) == ELFCLASS64
)
1410 (void) printf("\n **** SECTION HEADER[0] "
1411 "{Elf Extensions} ****\n");
1413 "[No]\tType\tFlags\t%-*s %-*s%-*s%sName\n",
1414 field
, "Addr", field
, "Offset", field
,
1416 /* compatibility: tab for elf32 */
1417 (field
== 13) ? "\t" : " ");
1418 (void) printf("\tLn(strndx) Info\t%-*s Entsize\n",
1421 if ((scn
= elf_getscn(elf_file
, 0)) == NULL
) {
1422 (void) fprintf(stderr
,
1423 "%s: %s: elf_getscn failed: %s\n",
1424 prog_name
, filename
, elf_errmsg(-1));
1427 if (gelf_getshdr(scn
, &shdr0
) == 0) {
1428 (void) fprintf(stderr
,
1429 "%s: %s: gelf_getshdr: %s\n",
1430 prog_name
, filename
, elf_errmsg(-1));
1433 (void) printf("[0]\t%u\t%llu\t", EC_WORD(shdr0
.sh_type
),
1434 EC_XWORD(shdr0
.sh_flags
));
1436 (void) printf("%-#*llx %-#*llx%-*llu%s%-*u\n",
1437 field
, EC_ADDR(shdr0
.sh_addr
),
1438 field
, EC_OFF(shdr0
.sh_offset
),
1439 field
, EC_XWORD(shdr0
.sh_size
),
1440 /* compatibility: tab for elf32 */
1441 ((field
== 13) ? "\t" : " "),
1442 field
, EC_WORD(shdr0
.sh_name
));
1444 (void) printf("\t%u\t%u\t%-#*llx %-#*llx\n",
1445 EC_WORD(shdr0
.sh_link
),
1446 EC_WORD(shdr0
.sh_info
),
1447 field
, EC_XWORD(shdr0
.sh_addralign
),
1448 field
, EC_XWORD(shdr0
.sh_entsize
));
1450 (void) printf("\n");
1452 return (elf_head_p
);
1456 * Print section contents. Input is an ELF file descriptor,
1457 * the ELF header, the SCNTAB structure,
1458 * the number of symbols, and the filename.
1459 * The number of sections,
1460 * and the offset into the SCNTAB structure will be
1461 * set in dump_section if d_flag or n_flag are set.
1462 * If v_flag is set, sections which can be interpreted will
1463 * be interpreted, otherwise raw data will be output in hexidecimal.
1466 print_section(Elf
*elf_file
,
1467 GElf_Ehdr
*p_ehdr
, SCNTAB
*p
, int num_scns
, char *filename
)
1469 unsigned char *p_sec
;
1473 for (i
= 0; i
< num_scns
; i
++, p
++) {
1477 if (s_flag
&& !v_flag
)
1478 p_sec
= (unsigned char *)get_rawscn(p
->p_sd
, &size
);
1480 p_sec
= (unsigned char *)get_scndata(p
->p_sd
, &size
);
1482 if ((gelf_getshdr(p
->p_sd
, &shdr
) != NULL
) &&
1483 (shdr
.sh_type
== SHT_NOBITS
)) {
1486 if (s_flag
&& !v_flag
) {
1487 (void) printf("\n%s:\n", p
->scn_name
);
1488 print_rawdata(p_sec
, size
);
1491 if (shdr
.sh_type
== SHT_SYMTAB
) {
1492 dump_symbol_table(elf_file
, p
, filename
);
1495 if (shdr
.sh_type
== SHT_DYNSYM
) {
1496 dump_symbol_table(elf_file
, p
, filename
);
1499 if (shdr
.sh_type
== SHT_STRTAB
) {
1500 dump_string_table(p
, 1);
1503 if (shdr
.sh_type
== SHT_RELA
) {
1504 dump_reloc_table(elf_file
, p_ehdr
, p
, 1, filename
);
1507 if (shdr
.sh_type
== SHT_REL
) {
1508 dump_reloc_table(elf_file
, p_ehdr
, p
, 1, filename
);
1511 if (shdr
.sh_type
== SHT_DYNAMIC
) {
1512 dump_dynamic(elf_file
, p
, 1, filename
);
1516 (void) printf("\n%s:\n", p
->scn_name
);
1517 print_rawdata(p_sec
, size
);
1519 (void) printf("\n");
1523 * Print section contents. This function does not print the contents
1524 * of the sections but sets up the parameters and then calls
1525 * print_section to print the contents. Calling another function to print
1526 * the contents allows both -d and -n to work correctly
1527 * simultaneously. Input is an ELF file descriptor, the ELF header,
1528 * the SCNTAB structure, the number of sections, and the filename.
1529 * Set the range of sections if d_flag, and set section name if
1533 dump_section(Elf
*elf_file
,
1534 GElf_Ehdr
*p_ehdr
, SCNTAB
*s
, int num_scns
, char *filename
)
1536 SCNTAB
*n_range
, *d_range
; /* for use with -n and -d modifiers */
1538 int found_it
= 0; /* for use with -n section_name */
1543 for (i
= 0; i
< num_scns
; i
++, n_range
++) {
1544 if ((strcmp(name
, n_range
->scn_name
)) != 0)
1548 print_section(elf_file
, p_ehdr
,
1549 n_range
, 1, filename
);
1554 (void) fprintf(stderr
, "%s: %s: %s not found\n",
1555 prog_name
, filename
, name
);
1561 d_num
= check_range(d_low
, d_hi
, num_scns
, filename
);
1564 d_range
+= d_low
- 1;
1566 print_section(elf_file
, p_ehdr
, d_range
, d_num
, filename
);
1569 if (!n_flag
&& !d_flag
)
1570 print_section(elf_file
, p_ehdr
, s
, num_scns
, filename
);
1574 * Print the section header table. This function does not print the contents
1575 * of the section headers but sets up the parameters and then calls
1576 * print_shdr to print the contents. Calling another function to print
1577 * the contents allows both -d and -n to work correctly
1578 * simultaneously. Input is the SCNTAB structure,
1579 * the number of sections from the ELF header, and the filename.
1580 * Set the range of section headers to print if d_flag, and set
1581 * name of section header to print if n_flag.
1584 dump_shdr(Elf
*elf_file
, SCNTAB
*s
, int num_scns
, char *filename
)
1587 SCNTAB
*n_range
, *d_range
; /* for use with -n and -d modifiers */
1590 int found_it
= 0; /* for use with -n section_name */
1592 if (gelf_getclass(elf_file
) == ELFCLASS64
)
1598 (void) printf("\n **** SECTION HEADER TABLE ****\n");
1599 (void) printf("[No]\tType\tFlags\t%-*s %-*s %-*s%sName\n",
1600 field
, "Addr", field
, "Offset", field
, "Size",
1601 /* compatibility: tab for elf32 */
1602 (field
== 13) ? "\t" : " ");
1603 (void) printf("\tLink\tInfo\t%-*s Entsize\n\n",
1610 for (i
= 1; i
<= num_scns
; i
++, n_range
++) {
1611 if ((strcmp(name
, n_range
->scn_name
)) != 0)
1615 print_shdr(elf_file
, n_range
, 1, i
);
1620 (void) fprintf(stderr
, "%s: %s: %s not found\n",
1621 prog_name
, filename
, name
);
1627 d_num
= check_range(d_low
, d_hi
, num_scns
, filename
);
1630 d_range
+= d_low
- 1;
1632 print_shdr(elf_file
, d_range
, d_num
, d_low
);
1635 if (!n_flag
&& !d_flag
)
1636 print_shdr(elf_file
, s
, num_scns
, 1);
1640 * Process all of the command line options (except
1641 * for -a, -g, -f, and -o). All of the options processed
1642 * by this function require the presence of the section
1643 * header table and will not be processed if it is not present.
1644 * Set up a buffer containing section name, section header,
1645 * and section descriptor for each section in the file. This
1646 * structure is used to avoid duplicate calls to libelf functions.
1647 * Structure members for the symbol table, the debugging information,
1648 * and the line number information are global. All of the
1652 dump_section_table(Elf
*elf_file
, GElf_Ehdr
*elf_head_p
, char *filename
)
1655 static SCNTAB
*buffer
, *p_scns
;
1657 char *s_name
= NULL
;
1659 unsigned int num_scns
;
1664 if (elf_getshdrnum(elf_file
, &shnum
) == -1) {
1665 (void) fprintf(stderr
,
1666 "%s: %s: elf_getshdrnum failed: %s\n",
1667 prog_name
, filename
, elf_errmsg(-1));
1670 if (elf_getshdrstrndx(elf_file
, &shstrndx
) == -1) {
1671 (void) fprintf(stderr
,
1672 "%s: %s: elf_getshdrstrndx failed: %s\n",
1673 prog_name
, filename
, elf_errmsg(-1));
1677 if ((buffer
= calloc(shnum
, sizeof (SCNTAB
))) == NULL
) {
1678 (void) fprintf(stderr
, "%s: %s: cannot calloc space\n",
1679 prog_name
, filename
);
1683 num_scns
= (int)shnum
- 1;
1685 p_symtab
= (SCNTAB
*)0;
1686 p_dynsym
= (SCNTAB
*)0;
1688 p_head_scns
= buffer
;
1690 while ((scn
= elf_nextscn(elf_file
, scn
)) != 0) {
1691 if ((gelf_getshdr(scn
, &buffer
->p_shdr
)) == 0) {
1692 (void) fprintf(stderr
,
1693 "%s: %s: %s\n", prog_name
, filename
,
1698 elf_strptr(elf_file
, shstrndx
, buffer
->p_shdr
.sh_name
);
1699 buffer
->scn_name
= s_name
? s_name
: (char *)UNKNOWN
;
1702 if (buffer
->p_shdr
.sh_type
== SHT_SYMTAB
) {
1706 if (buffer
->p_shdr
.sh_type
== SHT_DYNSYM
)
1712 * These functions depend upon the presence of the section header table
1713 * and will not be invoked in its absence
1716 dump_shdr(elf_file
, p_scns
, num_scns
, filename
);
1718 if (p_symtab
&& (t_flag
|| T_flag
)) {
1719 dump_symbol_table(elf_file
, p_symtab
, filename
);
1722 dump_string_table(p_scns
, num_scns
);
1725 dump_reloc_table(elf_file
, elf_head_p
,
1726 p_scns
, num_scns
, filename
);
1729 dump_dynamic(elf_file
, p_scns
, num_scns
, filename
);
1732 dump_section(elf_file
, elf_head_p
, p_scns
,
1733 num_scns
, filename
);
1738 * Load the archive string table(s) (for extended-length strings)
1739 * into an in-core table/list
1741 static struct stab_list_s
*
1742 load_arstring_table(struct stab_list_s
*STabList
,
1743 int fd
, Elf
*elf_file
, Elf_Arhdr
*p_ar
, char *filename
)
1746 struct stab_list_s
*STL_entry
, *STL_next
;
1749 STL_entry
= malloc(sizeof (struct stab_list_s
));
1750 STL_entry
->next
= 0;
1751 STL_entry
->strings
= 0;
1752 STL_entry
->size
= 0;
1755 STabList
= STL_entry
;
1757 STL_next
= STabList
;
1758 while (STL_next
->next
!= NULL
)
1759 STL_next
= STL_next
->next
;
1760 STL_next
->next
= STL_entry
;
1763 STL_entry
->size
= p_ar
->ar_size
;
1764 STL_entry
->strings
= malloc(p_ar
->ar_size
);
1765 here
= elf_getbase(elf_file
);
1766 if ((lseek(fd
, here
, 0)) != here
) {
1767 (void) fprintf(stderr
,
1768 "%s: %s: could not lseek\n", prog_name
, filename
);
1771 if ((read(fd
, STL_entry
->strings
, p_ar
->ar_size
)) == -1) {
1772 (void) fprintf(stderr
,
1773 "%s: %s: could not read\n", prog_name
, filename
);
1780 * Print the archive header for each member of an archive.
1781 * Also call ar_sym_read to print the symbols in the
1782 * archive symbol table if g_flag. Input is a file descriptor,
1783 * an ELF file descriptor, and the filename. Putting the call
1784 * to dump the archive symbol table in this function is more
1785 * efficient since it is necessary to examine the archive member
1786 * name in the archive header to determine which member is the
1790 dump_ar_hdr(int fd
, Elf
*elf_file
, char *filename
)
1792 extern int v_flag
, g_flag
, a_flag
, p_flag
;
1802 while ((arf
= elf_begin(fd
, cmd
, elf_file
)) != 0) {
1803 p_ar
= elf_getarhdr(arf
);
1805 (void) fprintf(stderr
,
1806 "%s: %s: %s\n", prog_name
, filename
,
1810 if ((strcmp(p_ar
->ar_name
, "/") == 0) ||
1811 (strcmp(p_ar
->ar_name
, "/SYM64/") == 0)) {
1813 ar_sym_read(elf_file
, filename
);
1814 } else if (strcmp(p_ar
->ar_name
, "//") == 0) {
1815 StringTableList
= load_arstring_table(
1816 StringTableList
, fd
, arf
, p_ar
, filename
);
1817 cmd
= elf_next(arf
);
1818 (void) elf_end(arf
);
1822 (void) printf("%s[%s]:\n", filename
,
1824 if (!p_flag
&& title
== 0) {
1827 "\n\n\t\t\t***ARCHIVE HEADER***"
1828 "\n Date Uid Gid Mode Size Member Name\n\n");
1831 "\n\n\t\t\t***ARCHIVE HEADER***"
1832 "\n Date Uid Gid Mode Size Member Name\n\n");
1837 "\t0x%.8lx %6d %6d 0%.6ho 0x%.8lx %-s\n\n",
1838 p_ar
->ar_date
, (int)p_ar
->ar_uid
,
1841 p_ar
->ar_size
, p_ar
->ar_name
);
1843 if ((strftime(buf
, DATESIZE
,
1844 "%b %d %H:%M:%S %Y",
1846 &(p_ar
->ar_date
)))) == 0) {
1847 (void) fprintf(stderr
,
1848 "%s: %s: don't have enough space to store the date\n", prog_name
, filename
);
1852 "\t%s %6d %6d 0%.6ho 0x%.8lx %-s\n\n",
1853 buf
, (int)p_ar
->ar_uid
,
1856 p_ar
->ar_size
, p_ar
->ar_name
);
1860 cmd
= elf_next(arf
);
1861 (void) elf_end(arf
);
1866 (void) fprintf(stderr
,
1867 "%s: %s: %s\n", prog_name
, filename
, elf_errmsg(err
));
1872 * Process member files of an archive. This function provides
1873 * a loop through an archive equivalent the processing of
1874 * each_file for individual object files.
1877 dump_ar_files(int fd
, Elf
*elf_file
, char *filename
)
1887 while ((arf
= elf_begin(fd
, cmd
, elf_file
)) != 0) {
1890 p_ar
= elf_getarhdr(arf
);
1892 (void) fprintf(stderr
, "%s: %s: %s\n",
1893 prog_name
, filename
, elf_errmsg(-1));
1896 if (p_ar
->ar_name
[0] == '/') {
1897 cmd
= elf_next(arf
);
1898 (void) elf_end(arf
);
1902 len
= strlen(filename
) + strlen(p_ar
->ar_name
) + 3;
1903 if ((fullname
= malloc(len
)) == NULL
)
1905 (void) snprintf(fullname
, len
, "%s[%s]", filename
,
1907 (void) printf("\n%s:\n", fullname
);
1908 file_type
= elf_kind(arf
);
1909 if (file_type
== ELF_K_ELF
) {
1910 if (dump_elf_header(arf
, fullname
, &elf_head
) == NULL
)
1913 dump_exec_header(arf
,
1914 (unsigned)elf_head
.e_phnum
, fullname
);
1916 dump_section_table(arf
, &elf_head
, fullname
);
1918 (void) fprintf(stderr
, "%s: %s: invalid file type\n",
1919 prog_name
, fullname
);
1920 cmd
= elf_next(arf
);
1921 (void) elf_end(arf
);
1925 cmd
= elf_next(arf
);
1926 (void) elf_end(arf
);
1931 * Takes a filename as input. Test first for a valid version
1932 * of libelf.a and exit on error. Process each valid file
1933 * or archive given as input on the command line. Check
1934 * for file type. If it is an archive, process the archive-
1935 * specific options first, then files within the archive.
1936 * If it is an ELF object file, process it; otherwise
1937 * warn that it is an invalid file type.
1938 * All options except the archive-specific and program
1939 * execution header are processed in the function, dump_section_table.
1942 each_file(char *filename
)
1954 if (stat(filename
, &buf
) == -1) {
1956 (void) fprintf(stderr
, "%s: %s: %s", prog_name
, filename
,
1961 if ((fd
= open((filename
), O_RDONLY
)) == -1) {
1962 (void) fprintf(stderr
, "%s: %s: cannot read\n", prog_name
,
1967 if ((elf_file
= elf_begin(fd
, cmd
, (Elf
*)0)) == NULL
) {
1968 (void) fprintf(stderr
, "%s: %s: %s\n", prog_name
, filename
,
1973 file_type
= elf_kind(elf_file
);
1974 if (file_type
== ELF_K_AR
) {
1975 if (a_flag
|| g_flag
) {
1976 dump_ar_hdr(fd
, elf_file
, filename
);
1977 elf_file
= elf_begin(fd
, cmd
, (Elf
*)0);
1980 dump_ar_files(fd
, elf_file
, filename
);
1982 if (file_type
== ELF_K_ELF
) {
1983 (void) printf("\n%s:\n", filename
);
1984 if (dump_elf_header(elf_file
, filename
, &elf_head
)) {
1986 dump_exec_header(elf_file
,
1987 (unsigned)elf_head
.e_phnum
,
1990 dump_section_table(elf_file
,
1991 &elf_head
, filename
);
1994 (void) fprintf(stderr
, "%s: %s: invalid file type\n",
1995 prog_name
, filename
);
1998 (void) elf_end(elf_file
);
2003 * Sets up flags for command line options given and then
2004 * calls each_file() to process each file.
2007 main(int argc
, char *argv
[], char *envp
[])
2009 char *optstr
= OPTSTR
; /* option string used by getopt() */
2013 * Check for a binary that better fits this architecture.
2015 (void) conv_check_native(argv
, envp
);
2017 prog_name
= argv
[0];
2019 (void) setlocale(LC_ALL
, "");
2020 while ((optchar
= getopt(argc
, argv
, optstr
)) != -1) {
2058 set_range(optarg
, &d_low
, &d_hi
);
2086 set_range(optarg
, &T_low
, &T_hi
);
2100 (void) fprintf(stderr
, "dump: %s %s\n",
2101 (const char *)SGU_PKG
,
2102 (const char *)SGU_REL
);
2112 if (errflag
|| (optind
>= argc
) || (!z_flag
&& !x_flag
)) {
2113 if (!(V_flag
&& (argc
== 2))) {
2119 if (elf_version(EV_CURRENT
) == EV_NONE
) {
2120 (void) fprintf(stderr
, "%s: libelf is out of date\n",
2125 while (optind
< argc
) {
2126 each_file(argv
[optind
]);