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
= (void *)0;
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
497 len
= strlen(dn
) + strlen(s
) + 4;
498 if ((buf
= malloc(len
)) == NULL
)
501 (void) snprintf(buf
, len
, "%s\t[%s]", dn
, s
);
506 * Print the symbol table. Input is an ELF file descriptor, a
507 * pointer to the symbol table SCNTAB structure,
508 * the number of symbols, a range of symbols to print,
509 * an index which is the number of the
510 * section in the file, and the filename. The number of sections,
511 * the range, and the index are set in
512 * dump_symbol_table, depending on whether -n or -T were set.
515 print_symtab(Elf
*elf_file
, SCNTAB
*p_symtab
, Elf_Data
*sym_data
,
516 long range
, int index
)
519 int adj
= 0; /* field adjustment for elf64 */
520 Elf32_Word
*symshndx
= 0;
521 unsigned int nosymshndx
= 0;
522 Conv_inv_buf_t inv_buf
;
525 if (gelf_getclass(elf_file
) == ELFCLASS64
)
529 char *sym_name
= (char *)0;
534 (void) gelf_getsym(sym_data
, index
, &sym
);
535 type
= (int)GELF_ST_TYPE(sym
.st_info
);
536 bind
= (int)GELF_ST_BIND(sym
.st_info
);
538 if ((sym
.st_shndx
== SHN_XINDEX
) &&
539 (symshndx
== 0) && (nosymshndx
== 0)) {
544 symscnndx
= elf_ndxscn(p_symtab
->p_sd
);
546 while ((_scn
= elf_nextscn(elf_file
, _scn
)) != 0) {
547 if (gelf_getshdr(_scn
, &_shdr
) == 0)
549 if ((_shdr
.sh_type
== SHT_SYMTAB_SHNDX
) &&
551 (_shdr
.sh_link
== (GElf_Word
)symscnndx
)) {
554 if ((_data
= elf_getdata(_scn
, 0)) == 0)
557 symshndx
= (Elf32_Word
*)_data
->d_buf
;
565 if ((symshndx
) && (sym
.st_shndx
== SHN_XINDEX
)) {
566 shndx
= symshndx
[index
];
569 shndx
= sym
.st_shndx
;
570 if ((sym
.st_shndx
== SHN_UNDEF
) ||
571 (sym
.st_shndx
>= SHN_LORESERVE
))
578 (void) printf("[%d]\t ", index
++);
580 if (v_flag
&& (type
== STT_SPARC_REGISTER
)) {
582 * The strings "REG_G1" through "REG_G7" are intended
583 * to be consistent with output from elfdump(1).
585 (void) printf("%-*s", 12 + adj
,
586 conv_sym_SPARC_value(sym
.st_value
,
587 DUMP_CONVFMT
, &inv_buf
));
589 (void) printf("0x%-*llx", 10 + adj
,
590 EC_ADDR(sym
.st_value
));
593 (void) printf("%-*lld", 9 + adj
, EC_XWORD(sym
.st_size
));
596 (void) printf("%d\t\t%d\t%d\t%#x\t",
597 type
, bind
, (int)sym
.st_other
, (int)shndx
);
600 (void) gelf_getehdr(elf_file
, &p_ehdr
);
601 (void) printf("%s\t",
602 conv_sym_info_type(p_ehdr
.e_machine
, type
,
603 DUMP_CONVFMT
, &inv_buf
));
605 conv_sym_info_bind(bind
, DUMP_CONVFMT
, &inv_buf
));
606 (void) printf("\t %d\t", EC_WORD(sym
.st_other
));
610 conv_sym_shndx(p_ehdr
.e_ident
[EI_OSABI
],
611 p_ehdr
.e_machine
, shndx
,
612 CONV_FMT_DECIMAL
, &inv_buf
));
614 (void) printf("%d", EC_WORD(shndx
));
618 /* support machines where NULL-deref causes core dump */
619 if (sym
.st_name
== 0)
620 sym_name
= (char *)UNKNOWN
;
623 sym_name
= demangled_name(
624 (char *)elf_strptr(elf_file
,
625 p_symtab
->p_shdr
.sh_link
,
628 sym_name
= (char *)elf_strptr(elf_file
,
629 p_symtab
->p_shdr
.sh_link
, sym
.st_name
);
630 if (sym_name
== NULL
)
631 sym_name
= (char *)UNKNOWN
;
632 (void) printf("%s\n", sym_name
);
639 * Print the section header table. Input is the SCNTAB structure,
640 * the number of sections, an index which is the number of the
641 * section in the file, and the filename. The values of the SCNTAB
642 * structure, the number of sections, and the index are set in
643 * dump_shdr depending on whether the -n or -d modifiers were set.
646 print_shdr(Elf
*elf_file
, SCNTAB
*s
, int num_scns
, int index
)
653 if (gelf_getclass(elf_file
) == ELFCLASS64
)
659 (void) gelf_getehdr(elf_file
, &p_ehdr
);
661 for (num
= 0; num
< num_scns
; num
++, p
++) {
662 (void) printf("[%d]\t", index
++);
664 (void) printf("%u\t%llu\t",
665 EC_WORD(p
->p_shdr
.sh_type
),
666 EC_XWORD(p
->p_shdr
.sh_flags
));
668 Conv_inv_buf_t inv_buf
;
670 /*LINTED: E_SEC_PRINTF_VAR_FMT*/
671 (void) printf(conv_sec_type(
672 p_ehdr
.e_ident
[EI_OSABI
], p_ehdr
.e_machine
,
673 p
->p_shdr
.sh_type
, DUMP_CONVFMT
, &inv_buf
));
676 if (p
->p_shdr
.sh_flags
& SHF_WRITE
)
680 if (p
->p_shdr
.sh_flags
& SHF_ALLOC
)
684 if (p
->p_shdr
.sh_flags
& SHF_EXECINSTR
)
689 if (p
->p_shdr
.sh_flags
& SHF_ORDERED
)
691 if (p
->p_shdr
.sh_flags
& SHF_EXCLUDE
)
697 (void) printf("%-#*llx%-#*llx%-#*llx%s%s\n",
698 field
, EC_ADDR(p
->p_shdr
.sh_addr
),
699 field
, EC_OFF(p
->p_shdr
.sh_offset
),
700 field
, EC_XWORD(p
->p_shdr
.sh_size
),
701 /* compatibility: tab for elf32 */
702 (field
== 13) ? "\t" : " ", p
->scn_name
);
704 (void) printf("\t%u\t%u\t%-#*llx%-#*llx\n\n",
705 EC_WORD(p
->p_shdr
.sh_link
),
706 EC_WORD(p
->p_shdr
.sh_info
),
707 field
, EC_XWORD(p
->p_shdr
.sh_addralign
),
708 field
, EC_XWORD(p
->p_shdr
.sh_entsize
));
713 * Check that a range of numbers is valid. Input is
714 * a lower bound, an upper bound, a boundary condition,
715 * and the filename. Negative numbers and numbers greater
716 * than the bound are invalid. low must be smaller than hi.
717 * The returned integer is the number of items in the
718 * range if it is valid and -1 otherwise.
721 check_range(int low
, int hi
, size_t bound
, char *filename
)
723 if (((size_t)low
> bound
) || (low
<= 0)) {
724 (void) fprintf(stderr
,
725 "%s: %s: number out of range, %d\n",
726 prog_name
, filename
, low
);
729 if (((size_t)hi
> bound
) || (hi
< 0)) {
730 (void) fprintf(stderr
,
731 "%s: %s: number out of range, %d\n",
732 prog_name
, filename
, hi
);
736 if (hi
&& (low
> hi
)) {
737 (void) fprintf(stderr
,
738 "%s: %s: invalid range, %d,%d\n",
739 prog_name
, filename
, low
, hi
);
743 return (hi
- low
+ 1);
749 * Print relocation information. Since this information is
750 * machine dependent, new sections must be added for each machine
751 * that is supported. Input is an ELF file descriptor, the ELF header,
752 * the SCNTAB structure, the number of sections, and a filename.
753 * Set up necessary information to print relocation information
754 * and call the appropriate print function depending on the
755 * type of relocation information. If the symbol table is
756 * absent, no relocation data is processed. Input is an
757 * ELF file descriptor, the ELF header, the SCNTAB structure,
758 * and the filename. Set range of d_flag and name if n_flag.
761 dump_reloc_table(Elf
*elf_file
, GElf_Ehdr
*p_ehdr
,
762 SCNTAB
*p_scns
, int num_scns
, char *filename
)
768 SCNTAB
*reloc_symtab
;
774 if (gelf_getclass(elf_file
) == ELFCLASS64
)
777 if ((!p_flag
) && (!r_title
)) {
778 (void) printf("\n **** RELOCATION INFORMATION ****\n");
782 while (num_scns
-- > 0) {
783 if ((p_scns
->p_shdr
.sh_type
!= SHT_RELA
) &&
784 (p_scns
->p_shdr
.sh_type
!= SHT_REL
)) {
789 head_scns
= p_head_scns
;
791 if (elf_getshdrnum(elf_file
, &shnum
) == -1) {
792 (void) fprintf(stderr
,
793 "%s: %s: elf_getshdrnum failed: %s\n",
794 prog_name
, filename
, elf_errmsg(-1));
798 if ((p_scns
->p_shdr
.sh_link
== 0) ||
800 (p_scns
->p_shdr
.sh_link
>= (GElf_Word
)shnum
)) {
801 (void) fprintf(stderr
, "%s: %s: invalid sh_link field: "
802 "section #: %d sh_link: %d\n",
804 prog_name
, filename
, (int)elf_ndxscn(p_scns
->p_sd
),
805 (int)p_scns
->p_shdr
.sh_link
);
808 head_scns
+= (p_scns
->p_shdr
.sh_link
-1);
810 if (head_scns
->p_shdr
.sh_type
== SHT_SYMTAB
) {
811 reloc_symtab
= p_symtab
;
812 } else if (head_scns
->p_shdr
.sh_type
== SHT_DYNSYM
) {
813 reloc_symtab
= p_dynsym
;
815 (void) fprintf(stderr
,
816 "%s: %s: could not get symbol table\n", prog_name
, filename
);
824 if ((sym_data
= elf_getdata(reloc_symtab
->p_sd
, NULL
)) == NULL
) {
825 (void) fprintf(stderr
,
826 "%s: %s: no symbol table data\n", prog_name
, filename
);
829 sym_size
= sym_data
->d_size
;
831 if (p_scns
== NULL
) {
832 (void) fprintf(stderr
,
833 "%s: %s: no section table data\n", prog_name
, filename
);
837 if (p_scns
->p_shdr
.sh_type
== SHT_RELA
) {
838 if (!n_flag
&& r_flag
)
839 (void) printf("\n%s:\n", p_scns
->scn_name
);
840 if (!p_flag
&& (!n_flag
&& r_flag
))
841 (void) printf("%-*s%-*s%-*s%s\n\n",
842 12 + adj
, "Offset", 22, "Symndx",
843 18, "Type", "Addend");
844 if ((rel_data
= elf_getdata(p_scns
->p_sd
, NULL
)) == NULL
) {
845 (void) fprintf(stderr
,
846 "%s: %s: no relocation information\n", prog_name
, filename
);
849 reloc_size
= rel_data
->d_size
;
853 print_rela(elf_file
, p_scns
, rel_data
, sym_data
, p_ehdr
,
854 reloc_size
, sym_size
, filename
, reloc_symtab
);
858 print_rela(elf_file
, p_scns
, rel_data
, sym_data
, p_ehdr
,
859 reloc_size
, sym_size
, filename
, reloc_symtab
);
861 if (!n_flag
&& !d_flag
)
862 print_rela(elf_file
, p_scns
, rel_data
, sym_data
, p_ehdr
,
863 reloc_size
, sym_size
, filename
, reloc_symtab
);
865 if (p_scns
->p_shdr
.sh_type
== SHT_REL
) {
866 if (!n_flag
&& r_flag
)
867 (void) printf("\n%s:\n", p_scns
->scn_name
);
868 if (!p_flag
&& (!n_flag
&& r_flag
)) {
869 (void) printf("%-*s%-*s%s\n\n",
870 12 + adj
, "Offset", 20, "Symndx", "Type");
872 if ((rel_data
= elf_getdata(p_scns
->p_sd
, NULL
))
874 (void) fprintf(stderr
,
875 "%s: %s: no relocation information\n", prog_name
, filename
);
878 reloc_size
= rel_data
->d_size
;
881 print_rel(elf_file
, p_scns
, rel_data
, sym_data
,
882 p_ehdr
, reloc_size
, sym_size
,
883 filename
, reloc_symtab
);
887 print_rel(elf_file
, p_scns
, rel_data
, sym_data
,
888 p_ehdr
, reloc_size
, sym_size
,
889 filename
, reloc_symtab
);
891 if (!n_flag
&& !d_flag
)
892 print_rel(elf_file
, p_scns
, rel_data
, sym_data
,
893 p_ehdr
, reloc_size
, sym_size
,
894 filename
, reloc_symtab
);
902 * Print out the string tables. Input is an opened ELF file,
903 * the SCNTAB structure, the number of sections, and the filename.
904 * Since there can be more than one string table, all sections are
905 * examined and any with the correct type are printed out.
908 dump_string_table(SCNTAB
*s
, int num_scns
)
911 unsigned char *strtab
;
918 (void) printf("\n **** STRING TABLE INFORMATION ****\n");
921 for (i
= 0; i
< num_scns
; i
++, s
++) {
922 if (s
->p_shdr
.sh_type
!= SHT_STRTAB
)
928 (void) printf("\n%s:\n", s
->scn_name
);
929 (void) printf(" <offset> \tName\n");
932 if ((strtab
= (unsigned char *)
933 get_scndata(s
->p_sd
, §ion_size
)) == NULL
) {
937 if (section_size
!= 0) {
938 (void) printf(" <%d> \t", str_off
);
940 while (section_size
--) {
941 unsigned char c
= *strtab
++;
944 (void) printf(" <%d> \t", str_off
);
964 * Print the symbol table. This function does not print the contents
965 * of the symbol table but sets up the parameters and then calls
966 * print_symtab to print the symbols. Calling another function to print
967 * the symbols allows both -T and -n to work correctly
968 * simultaneously. Input is an opened ELF file, a pointer to the
969 * symbol table SCNTAB structure, and the filename.
970 * Set the range of symbols to print if T_flag, and set
971 * name of symbol to print if n_flag.
974 dump_symbol_table(Elf
*elf_file
, SCNTAB
*p_symtab
, char *filename
)
977 GElf_Sym T_range
, n_range
; /* for use with -T and -n */
983 int adj
= 0; /* field adjustment for elf64 */
985 if (gelf_getclass(elf_file
) == ELFCLASS64
)
988 if (p_symtab
== NULL
) {
989 (void) fprintf(stderr
,
990 "%s: %s: could not get symbol table\n", prog_name
, filename
);
994 /* get symbol table data */
998 elf_getdata(p_symtab
->p_sd
, NULL
)) == NULL
) {
999 (void) printf("\n%s:\n", p_symtab
->scn_name
);
1000 (void) printf("No symbol table data\n");
1003 sym_size
= sym_data
->d_size
;
1005 count
= sym_size
/ p_symtab
->p_shdr
.sh_entsize
;
1007 if (n_flag
&& t_flag
&& !T_flag
) {
1009 for (i
= 1; i
< count
; i
++) {
1010 (void) gelf_getsym(sym_data
, i
, &n_range
);
1011 if (strcmp(name
, (char *)
1012 elf_strptr(elf_file
,
1013 p_symtab
->p_shdr
.sh_link
,
1014 n_range
.st_name
)) != 0) {
1020 "\n ***** SYMBOL TABLE INFORMATION *****\n");
1022 "[Index] %-*s%-*sType\tBind\tOther\tShndx\tName",
1023 12 + adj
, "Value", 9 + adj
, "Size");
1025 (void) printf("\n%s:\n", p_symtab
->scn_name
);
1026 print_symtab(elf_file
, p_symtab
, sym_data
,
1031 (void) fprintf(stderr
, "%s: %s: %s not found\n",
1032 prog_name
, filename
, name
);
1034 } else if (T_flag
) {
1035 T_num
= check_range(T_low
, T_hi
, count
, filename
);
1039 (void) gelf_getsym(sym_data
, T_low
-1, &T_range
);
1044 "\n ***** SYMBOL TABLE INFORMATION *****\n");
1046 "[Index] %-*s%-*sType\tBind\tOther\tShndx\tName",
1047 12 + adj
, "Value", 9 + adj
, "Size");
1049 (void) printf("\n%s:\n", p_symtab
->scn_name
);
1050 print_symtab(elf_file
, p_symtab
, sym_data
, T_num
, index
);
1054 "\n ***** SYMBOL TABLE INFORMATION *****\n");
1056 "[Index] %-*s%-*sType\tBind\tOther\tShndx\tName",
1057 12 + adj
, "Value", 9 + adj
, "Size");
1059 (void) printf("\n%s:\n", p_symtab
->scn_name
);
1060 print_symtab(elf_file
, p_symtab
, sym_data
, count
-1, 1);
1066 * Print dynamic linking information. Input is an ELF
1067 * file descriptor, the SCNTAB structure, the number of
1068 * sections, and the filename.
1071 dump_dynamic(Elf
*elf_file
, SCNTAB
*p_scns
, int num_scns
, char *filename
)
1073 #define pdyn_Fmtptr "%#llx"
1080 int lib_scns
= num_scns
;
1081 SCNTAB
*l_scns
= p_scns
;
1085 (void) gelf_getehdr(elf_file
, &p_ehdr
);
1088 (void) printf("\n **** DYNAMIC SECTION INFORMATION ****\n");
1090 for (; num_scns
> 0; num_scns
--, p_scns
++) {
1095 if (p_scns
->p_shdr
.sh_type
!= SHT_DYNAMIC
)
1099 (void) printf("%s:\n", p_scns
->scn_name
);
1100 (void) printf("[INDEX]\tTag Value\n");
1103 if ((dyn_data
= elf_getdata(p_scns
->p_sd
, NULL
)) == 0) {
1104 (void) fprintf(stderr
, "%s: %s: no data in "
1105 "%s section\n", prog_name
, filename
,
1110 link
= p_scns
->p_shdr
.sh_link
;
1113 (void) gelf_getdyn(dyn_data
, ii
++, &p_dyn
);
1114 while (p_dyn
.d_tag
!= DT_NULL
) {
1117 Conv_dyn_flag_buf_t dyn_flag
;
1118 Conv_dyn_flag1_buf_t dyn_flag1
;
1119 Conv_dyn_feature1_buf_t dyn_feature1
;
1120 Conv_dyn_posflag1_buf_t dyn_posflag1
;
1123 (void) printf("[%d]\t%-15.15s ", index
++,
1124 conv_dyn_tag(p_dyn
.d_tag
,
1125 p_ehdr
.e_ident
[EI_OSABI
], p_ehdr
.e_machine
,
1126 DUMP_CONVFMT
, &conv_buf
.inv
));
1129 * It would be nice to use a table driven loop
1130 * here, but the address space is too sparse
1131 * and irregular. A switch is simple and robust.
1133 switch (p_dyn
.d_tag
) {
1135 * Items with an address value
1150 case DT_INIT_ARRAYSZ
:
1151 case DT_FINI_ARRAYSZ
:
1152 case DT_PREINIT_ARRAY
:
1153 case DT_PREINIT_ARRAYSZ
:
1154 case DT_SUNW_RTLDINF
:
1156 case DT_SUNW_CAPINFO
:
1157 case DT_SUNW_CAPCHAIN
:
1158 case DT_SUNW_SYMTAB
:
1159 case DT_SUNW_SYMSORT
:
1160 case DT_SUNW_TLSSORT
:
1170 (void) printf(pdyn_Fmtptr
,
1171 EC_ADDR(p_dyn
.d_un
.d_ptr
));
1175 * Items with a string value
1181 case DT_SUNW_AUXILIARY
:
1182 case DT_SUNW_FILTER
:
1189 if (v_flag
) { /* Look up the string */
1190 str
= (char *)elf_strptr(elf_file
, link
,
1193 str
= (char *)UNKNOWN
;
1194 (void) printf("%s", str
);
1195 } else { /* Show the address */
1196 (void) printf(pdyn_Fmtptr
,
1197 EC_ADDR(p_dyn
.d_un
.d_ptr
));
1202 * Items with a literal value
1220 case DT_SPARC_REGISTER
:
1222 case DT_SUNW_SORTENT
:
1223 case DT_SUNW_SYMSORTSZ
:
1224 case DT_SUNW_TLSSORTSZ
:
1225 case DT_SUNW_STRPAD
:
1226 case DT_SUNW_CAPCHAINENT
:
1227 case DT_SUNW_CAPCHAINSZ
:
1229 (void) printf(pdyn_Fmtptr
,
1230 EC_XWORD(p_dyn
.d_un
.d_val
));
1234 * Integer items that are bitmasks, or which
1235 * can be otherwise formatted in symbolic form.
1241 case DT_SUNW_LDMACH
:
1244 switch (p_dyn
.d_tag
) {
1246 str
= conv_dyn_flag(
1249 &conv_buf
.dyn_flag
);
1252 str
= conv_dyn_feature1(
1255 &conv_buf
.dyn_feature1
);
1258 str
= conv_dyn_posflag1(
1261 &conv_buf
.dyn_posflag1
);
1264 str
= conv_dyn_flag1(
1265 p_dyn
.d_un
.d_val
, 0,
1266 &conv_buf
.dyn_flag1
);
1268 case DT_SUNW_LDMACH
:
1269 str
= conv_ehdr_mach(
1270 p_dyn
.d_un
.d_val
, 0,
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
));
1284 * Depreciated items with a literal value
1286 case DT_DEPRECATED_SPARC_REGISTER
:
1287 (void) printf(pdyn_Fmtptr
1288 " (deprecated value)",
1289 EC_XWORD(p_dyn
.d_un
.d_val
));
1294 (void) printf("(ignored)");
1297 (void) printf("\n");
1298 (void) gelf_getdyn(dyn_data
, ii
++, &p_dyn
);
1303 * Check for existence of static shared library information.
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
);
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.
1329 dump_elf_header(Elf
*elf_file
, char *filename
, GElf_Ehdr
* elf_head_p
)
1334 if (gelf_getehdr(elf_file
, elf_head_p
) == NULL
) {
1335 (void) fprintf(stderr
, "%s: %s: %s\n", prog_name
, filename
,
1340 class = (int)elf_head_p
->e_ident
[4];
1342 if (class == ELFCLASS64
)
1348 return (elf_head_p
);
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");
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
);
1366 Conv_inv_buf_t inv_buf
;
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
,
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
,
1379 (void) printf("%s\n",
1380 conv_ehdr_vers(elf_head_p
->e_version
, DUMP_CONVFMT
,
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
));
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
));
1401 if ((elf_head_p
->e_shnum
== 0) && (elf_head_p
->e_shoff
> 0)) {
1406 if (gelf_getclass(elf_file
) == ELFCLASS64
)
1411 (void) printf("\n **** SECTION HEADER[0] "
1412 "{Elf Extensions} ****\n");
1414 "[No]\tType\tFlags\t%-*s %-*s%-*s%sName\n",
1415 field
, "Addr", field
, "Offset", field
,
1417 /* compatibility: tab for elf32 */
1418 (field
== 13) ? "\t" : " ");
1419 (void) printf("\tLn(strndx) Info\t%-*s Entsize\n",
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));
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));
1434 (void) printf("[0]\t%u\t%llu\t", EC_WORD(shdr0
.sh_type
),
1435 EC_XWORD(shdr0
.sh_flags
));
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
));
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
));
1451 (void) printf("\n");
1453 return (elf_head_p
);
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.
1467 print_section(Elf
*elf_file
,
1468 GElf_Ehdr
*p_ehdr
, SCNTAB
*p
, int num_scns
, char *filename
)
1470 unsigned char *p_sec
;
1474 for (i
= 0; i
< num_scns
; i
++, p
++) {
1478 if (s_flag
&& !v_flag
)
1479 p_sec
= (unsigned char *)get_rawscn(p
->p_sd
, &size
);
1481 p_sec
= (unsigned char *)get_scndata(p
->p_sd
, &size
);
1483 if ((gelf_getshdr(p
->p_sd
, &shdr
) != NULL
) &&
1484 (shdr
.sh_type
== SHT_NOBITS
)) {
1487 if (s_flag
&& !v_flag
) {
1488 (void) printf("\n%s:\n", p
->scn_name
);
1489 print_rawdata(p_sec
, size
);
1492 if (shdr
.sh_type
== SHT_SYMTAB
) {
1493 dump_symbol_table(elf_file
, p
, filename
);
1496 if (shdr
.sh_type
== SHT_DYNSYM
) {
1497 dump_symbol_table(elf_file
, p
, filename
);
1500 if (shdr
.sh_type
== SHT_STRTAB
) {
1501 dump_string_table(p
, 1);
1504 if (shdr
.sh_type
== SHT_RELA
) {
1505 dump_reloc_table(elf_file
, p_ehdr
, p
, 1, filename
);
1508 if (shdr
.sh_type
== SHT_REL
) {
1509 dump_reloc_table(elf_file
, p_ehdr
, p
, 1, filename
);
1512 if (shdr
.sh_type
== SHT_DYNAMIC
) {
1513 dump_dynamic(elf_file
, p
, 1, filename
);
1517 (void) printf("\n%s:\n", p
->scn_name
);
1518 print_rawdata(p_sec
, size
);
1520 (void) printf("\n");
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
1534 dump_section(Elf
*elf_file
,
1535 GElf_Ehdr
*p_ehdr
, SCNTAB
*s
, int num_scns
, char *filename
)
1537 SCNTAB
*n_range
, *d_range
; /* for use with -n and -d modifiers */
1539 int found_it
= 0; /* for use with -n section_name */
1544 for (i
= 0; i
< num_scns
; i
++, n_range
++) {
1545 if ((strcmp(name
, n_range
->scn_name
)) != 0)
1549 print_section(elf_file
, p_ehdr
,
1550 n_range
, 1, filename
);
1555 (void) fprintf(stderr
, "%s: %s: %s not found\n",
1556 prog_name
, filename
, name
);
1562 d_num
= check_range(d_low
, d_hi
, num_scns
, filename
);
1565 d_range
+= d_low
- 1;
1567 print_section(elf_file
, p_ehdr
, d_range
, d_num
, filename
);
1570 if (!n_flag
&& !d_flag
)
1571 print_section(elf_file
, p_ehdr
, s
, num_scns
, filename
);
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.
1585 dump_shdr(Elf
*elf_file
, SCNTAB
*s
, int num_scns
, char *filename
)
1588 SCNTAB
*n_range
, *d_range
; /* for use with -n and -d modifiers */
1591 int found_it
= 0; /* for use with -n section_name */
1593 if (gelf_getclass(elf_file
) == ELFCLASS64
)
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",
1611 for (i
= 1; i
<= num_scns
; i
++, n_range
++) {
1612 if ((strcmp(name
, n_range
->scn_name
)) != 0)
1616 print_shdr(elf_file
, n_range
, 1, i
);
1621 (void) fprintf(stderr
, "%s: %s: %s not found\n",
1622 prog_name
, filename
, name
);
1628 d_num
= check_range(d_low
, d_hi
, num_scns
, filename
);
1631 d_range
+= d_low
- 1;
1633 print_shdr(elf_file
, d_range
, d_num
, d_low
);
1636 if (!n_flag
&& !d_flag
)
1637 print_shdr(elf_file
, s
, num_scns
, 1);
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
1653 dump_section_table(Elf
*elf_file
, GElf_Ehdr
*elf_head_p
, char *filename
)
1656 static SCNTAB
*buffer
, *p_scns
;
1658 char *s_name
= NULL
;
1660 unsigned int num_scns
;
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));
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));
1678 if ((buffer
= calloc(shnum
, sizeof (SCNTAB
))) == NULL
) {
1679 (void) fprintf(stderr
, "%s: %s: cannot calloc space\n",
1680 prog_name
, filename
);
1684 num_scns
= (int)shnum
- 1;
1686 p_symtab
= (SCNTAB
*)0;
1687 p_dynsym
= (SCNTAB
*)0;
1689 p_head_scns
= buffer
;
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
,
1699 elf_strptr(elf_file
, shstrndx
, buffer
->p_shdr
.sh_name
);
1700 buffer
->scn_name
= s_name
? s_name
: (char *)UNKNOWN
;
1703 if (buffer
->p_shdr
.sh_type
== SHT_SYMTAB
) {
1707 if (buffer
->p_shdr
.sh_type
== SHT_DYNSYM
)
1713 * These functions depend upon the presence of the section header table
1714 * and will not be invoked in its absence
1717 dump_shdr(elf_file
, p_scns
, num_scns
, filename
);
1719 if (p_symtab
&& (t_flag
|| T_flag
)) {
1720 dump_symbol_table(elf_file
, p_symtab
, filename
);
1723 dump_string_table(p_scns
, num_scns
);
1726 dump_reloc_table(elf_file
, elf_head_p
,
1727 p_scns
, num_scns
, filename
);
1730 dump_dynamic(elf_file
, p_scns
, num_scns
, filename
);
1733 dump_section(elf_file
, elf_head_p
, p_scns
,
1734 num_scns
, filename
);
1739 * Load the archive string table(s) (for extended-length strings)
1740 * into an in-core table/list
1742 static struct stab_list_s
*
1743 load_arstring_table(struct stab_list_s
*STabList
,
1744 int fd
, Elf
*elf_file
, Elf_Arhdr
*p_ar
, char *filename
)
1747 struct stab_list_s
*STL_entry
, *STL_next
;
1750 STL_entry
= malloc(sizeof (struct stab_list_s
));
1751 STL_entry
->next
= 0;
1752 STL_entry
->strings
= 0;
1753 STL_entry
->size
= 0;
1756 STabList
= STL_entry
;
1758 STL_next
= STabList
;
1759 while (STL_next
->next
!= (void *)0)
1760 STL_next
= STL_next
->next
;
1761 STL_next
->next
= STL_entry
;
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
);
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
);
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
1791 dump_ar_hdr(int fd
, Elf
*elf_file
, char *filename
)
1793 extern int v_flag
, g_flag
, a_flag
, p_flag
;
1803 while ((arf
= elf_begin(fd
, cmd
, elf_file
)) != 0) {
1804 p_ar
= elf_getarhdr(arf
);
1806 (void) fprintf(stderr
,
1807 "%s: %s: %s\n", prog_name
, filename
,
1811 if ((strcmp(p_ar
->ar_name
, "/") == 0) ||
1812 (strcmp(p_ar
->ar_name
, "/SYM64/") == 0)) {
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
);
1823 (void) printf("%s[%s]:\n", filename
,
1825 if (!p_flag
&& title
== 0) {
1828 "\n\n\t\t\t***ARCHIVE HEADER***"
1829 "\n Date Uid Gid Mode Size Member Name\n\n");
1832 "\n\n\t\t\t***ARCHIVE HEADER***"
1833 "\n Date Uid Gid Mode Size Member Name\n\n");
1838 "\t0x%.8lx %6d %6d 0%.6ho 0x%.8lx %-s\n\n",
1839 p_ar
->ar_date
, (int)p_ar
->ar_uid
,
1842 p_ar
->ar_size
, p_ar
->ar_name
);
1844 if ((strftime(buf
, DATESIZE
,
1845 "%b %d %H:%M:%S %Y",
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
);
1853 "\t%s %6d %6d 0%.6ho 0x%.8lx %-s\n\n",
1854 buf
, (int)p_ar
->ar_uid
,
1857 p_ar
->ar_size
, p_ar
->ar_name
);
1861 cmd
= elf_next(arf
);
1862 (void) elf_end(arf
);
1867 (void) fprintf(stderr
,
1868 "%s: %s: %s\n", prog_name
, filename
, elf_errmsg(err
));
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.
1878 dump_ar_files(int fd
, Elf
*elf_file
, char *filename
)
1888 while ((arf
= elf_begin(fd
, cmd
, elf_file
)) != 0) {
1891 p_ar
= elf_getarhdr(arf
);
1893 (void) fprintf(stderr
, "%s: %s: %s\n",
1894 prog_name
, filename
, elf_errmsg(-1));
1897 if (p_ar
->ar_name
[0] == '/') {
1898 cmd
= elf_next(arf
);
1899 (void) elf_end(arf
);
1903 len
= strlen(filename
) + strlen(p_ar
->ar_name
) + 3;
1904 if ((fullname
= malloc(len
)) == NULL
)
1906 (void) snprintf(fullname
, len
, "%s[%s]", filename
,
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
)
1914 dump_exec_header(arf
,
1915 (unsigned)elf_head
.e_phnum
, fullname
);
1917 dump_section_table(arf
, &elf_head
, fullname
);
1919 (void) fprintf(stderr
, "%s: %s: invalid file type\n",
1920 prog_name
, fullname
);
1921 cmd
= elf_next(arf
);
1922 (void) elf_end(arf
);
1926 cmd
= elf_next(arf
);
1927 (void) elf_end(arf
);
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.
1943 each_file(char *filename
)
1955 if (stat(filename
, &buf
) == -1) {
1957 (void) fprintf(stderr
, "%s: %s: %s", prog_name
, filename
,
1962 if ((fd
= open((filename
), O_RDONLY
)) == -1) {
1963 (void) fprintf(stderr
, "%s: %s: cannot read\n", prog_name
,
1968 if ((elf_file
= elf_begin(fd
, cmd
, (Elf
*)0)) == NULL
) {
1969 (void) fprintf(stderr
, "%s: %s: %s\n", prog_name
, filename
,
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);
1981 dump_ar_files(fd
, elf_file
, filename
);
1983 if (file_type
== ELF_K_ELF
) {
1984 (void) printf("\n%s:\n", filename
);
1985 if (dump_elf_header(elf_file
, filename
, &elf_head
)) {
1987 dump_exec_header(elf_file
,
1988 (unsigned)elf_head
.e_phnum
,
1991 dump_section_table(elf_file
,
1992 &elf_head
, filename
);
1995 (void) fprintf(stderr
, "%s: %s: invalid file type\n",
1996 prog_name
, filename
);
1999 (void) elf_end(elf_file
);
2004 * Sets up flags for command line options given and then
2005 * calls each_file() to process each file.
2008 main(int argc
, char *argv
[], char *envp
[])
2010 char *optstr
= OPTSTR
; /* option string used by getopt() */
2014 * Check for a binary that better fits this architecture.
2016 (void) conv_check_native(argv
, envp
);
2018 prog_name
= argv
[0];
2020 (void) setlocale(LC_ALL
, "");
2021 while ((optchar
= getopt(argc
, argv
, optstr
)) != -1) {
2059 set_range(optarg
, &d_low
, &d_hi
);
2087 set_range(optarg
, &T_low
, &T_hi
);
2101 (void) fprintf(stderr
, "dump: %s %s\n",
2102 (const char *)SGU_PKG
,
2103 (const char *)SGU_REL
);
2113 if (errflag
|| (optind
>= argc
) || (!z_flag
&& !x_flag
)) {
2114 if (!(V_flag
&& (argc
== 2))) {
2120 if (elf_version(EV_CURRENT
) == EV_NONE
) {
2121 (void) fprintf(stderr
, "%s: libelf is out of date\n",
2126 while (optind
< argc
) {
2127 each_file(argv
[optind
]);