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]
22 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
26 * dispsyms: Display Symbols
28 * This program demonstrates the use of the libelf interface to
29 * read an ELF file. dispsyms will open an ELF file using
30 * elf_begin(ELF_C_READ) and examine search the ELF file
31 * for a symbol table (SHT_SYMTAB, SHT_DYNSYM, or SHT_SUNW_LDYNSYM).
32 * It will display the contents of any symbol tables it finds.
34 * Note: This program also understands about the use
35 * of 'Extended ELF Section indexes' and will
36 * decode a corresponding SHT_SYMTAB_SHNDX
37 * section if required.
47 static const char *symbind
[STB_NUM
] = {
48 /* STB_LOCL */ "LOCL",
49 /* STB_GLOBAL */ "GLOB",
53 static const char *symtype
[STT_NUM
] = {
54 /* STT_NOTYPE */ "NOTY",
55 /* STT_OBJECT */ "OBJT",
56 /* STT_FUNC */ "FUNC",
57 /* STT_SECTION */ "SECT",
58 /* STT_FILE */ "FILE",
59 /* STT_COMMON */ "COMM",
62 #if STT_NUM != (STT_TLS + 1)
63 #error "STT_NUM has grown. Update symtype[]."
70 print_symtab(Elf
*elf
, const char *file
)
78 if (gelf_getehdr(elf
, &ehdr
) == NULL
) {
79 (void) fprintf(stderr
, "%s: elf_getehdr() failed: %s\n",
84 if (elf_getshdrstrndx(elf
, &shstrndx
) == -1) {
85 (void) fprintf(stderr
, "%s: elf_getshdrstrndx() failed: %s\n",
90 while ((scn
= elf_nextscn(elf
, scn
)) != NULL
) {
91 uint_t symcnt
, ndx
, nosymshndx
;
92 Elf_Data
*symdata
, *shndxdata
;
94 if (gelf_getshdr(scn
, &shdr
) == NULL
) {
95 (void) fprintf(stderr
,
96 "%s: elf_getshdr() failed: %s\n",
100 if ((shdr
.sh_type
!= SHT_SYMTAB
) &&
101 (shdr
.sh_type
!= SHT_DYNSYM
) &&
102 (shdr
.sh_type
!= SHT_SUNW_LDYNSYM
))
106 * Get the data associated with the Symbol
109 if ((symdata
= elf_getdata(scn
, NULL
)) == NULL
) {
110 (void) fprintf(stderr
,
111 "%s: elf_getdata() failed: %s\n",
112 file
, elf_errmsg(0));
117 * Print symbol table title and header for symbol display
119 (void) printf("\nSymTab: %s:%s\n", file
,
120 elf_strptr(elf
, shstrndx
, shdr
.sh_name
));
121 (void) printf(" index value size type "
122 "bind oth shndx name\n");
125 * We now iterate over the full symbol table printing
126 * the symbols as we go.
130 symcnt
= shdr
.sh_size
/ shdr
.sh_entsize
;
131 for (ndx
= 0; ndx
< symcnt
; ndx
++) {
134 uint_t type
, bind
, specshndx
;
135 char bindbuf
[INTSTRLEN
];
136 char typebuf
[INTSTRLEN
];
137 char shndxbuf
[INTSTRLEN
];
138 const char *bindstr
, *typestr
, *shndxstr
;
143 if (gelf_getsymshndx(symdata
, shndxdata
, ndx
,
144 &sym
, &shndx
) == NULL
) {
145 (void) fprintf(stderr
,
146 "%s: gelf_getsymshndx() failed: %s\n",
147 file
, elf_errmsg(0));
151 * Check to see if this symbol's st_shndx is using
152 * the 'Extended SHNDX table' for a SYMTAB.
154 * If it is - and we haven't searched before, go
155 * find the associated SHT_SYMTAB_SHNDX section.
157 if ((sym
.st_shndx
== SHN_XINDEX
) &&
158 (shndxdata
== 0) && (nosymshndx
== 0)) {
159 Elf_Scn
*_scn
= NULL
;
164 symscnndx
= elf_ndxscn(scn
);
167 elf_nextscn(elf
, _scn
)) != NULL
) {
168 if (gelf_getshdr(_scn
, &_shdr
) == NULL
)
172 * We've found the Symtab SHNDX table
173 * if it's of type SHT_SYMTAB_SHNDX
174 * and it's shdr.sh_link points to the
175 * section index for the current symbol
178 if ((_shdr
.sh_type
==
180 (_shdr
.sh_link
== symscnndx
) &&
181 ((shndxdata
= elf_getdata(_scn
,
189 (gelf_getsymshndx(symdata
, shndxdata
, ndx
,
190 &sym
, &shndx
) == NULL
)) {
191 (void) fprintf(stderr
,
192 "%s: gelf_getsymshndx() "
194 file
, elf_errmsg(0));
198 * No Symtab SHNDX table was found. We could
199 * give a fatal error here - instead we'll
200 * just mark that fact and display as much of
201 * the symbol table as we can. Any symbol
202 * displayed with a XINDX section index has
210 * Decode the type & binding information
212 type
= GELF_ST_TYPE(sym
.st_info
);
213 bind
= GELF_ST_BIND(sym
.st_info
);
216 typestr
= symtype
[type
];
218 (void) snprintf(typebuf
, INTSTRLEN
,
224 bindstr
= symbind
[bind
];
226 (void) snprintf(bindbuf
, INTSTRLEN
,
233 if (sym
.st_shndx
< SHN_LORESERVE
)
234 shndx
= sym
.st_shndx
;
235 else if ((sym
.st_shndx
!= SHN_XINDEX
) ||
236 (shndxdata
== NULL
)) {
237 shndx
= sym
.st_shndx
;
241 if (shndx
== SHN_UNDEF
) {
242 shndxstr
= (const char *)"UNDEF";
244 } else if (specshndx
) {
245 if (shndx
== SHN_ABS
)
246 shndxstr
= (const char *)"ABS";
247 else if (shndx
== SHN_COMMON
)
248 shndxstr
= (const char *)"COMM";
249 else if (shndx
== SHN_XINDEX
)
250 shndxstr
= (const char *)"XIND";
252 (void) snprintf(shndxbuf
, INTSTRLEN
,
257 (void) snprintf(shndxbuf
, INTSTRLEN
,
263 * Display the symbol entry.
265 (void) printf("[%3d] 0x%08llx 0x%08llx %-4s "
267 ndx
, sym
.st_value
, sym
.st_size
,
268 typestr
, bindstr
, sym
.st_other
, shndxstr
,
269 elf_strptr(elf
, shdr
.sh_link
, sym
.st_name
));
276 process_elf(Elf
*elf
, char *file
, int fd
, int member
)
281 switch (elf_kind(elf
)) {
284 * This is an ELF file, now attempt to find it's
285 * .comment section and to display it.
287 print_symtab(elf
, file
);
291 * Archives contain multiple ELF files, which can each
292 * in turn be examined with libelf.
294 * The below loop will iterate over each member of the
295 * archive and recursively call process_elf().
298 while ((_elf
= elf_begin(fd
, cmd
, elf
)) != NULL
) {
302 arhdr
= elf_getarhdr(_elf
);
305 * Build up file names based off of
306 * 'archivename(membername)'.
308 (void) snprintf(buffer
, 1024, "%s(%s)",
309 file
, arhdr
->ar_name
);
312 * Recursively process the ELF members.
314 process_elf(_elf
, buffer
, fd
, 1);
315 cmd
= elf_next(_elf
);
316 (void) elf_end(_elf
);
321 (void) fprintf(stderr
,
322 "%s: unexpected elf_kind(): 0x%x\n",
323 file
, elf_kind(elf
));
329 main(int argc
, char **argv
)
334 (void) printf("usage: %s elf_file ...\n", argv
[0]);
339 * Initialize the elf library, must be called before elf_begin()
342 if (elf_version(EV_CURRENT
) == EV_NONE
) {
343 (void) fprintf(stderr
,
344 "elf_version() failed: %s\n", elf_errmsg(0));
348 for (i
= 1; i
< argc
; i
++) {
354 if ((fd
= open(elf_fname
, O_RDONLY
)) == -1) {
360 * Attempt to open an Elf descriptor Read-Only
363 if ((elf
= elf_begin(fd
, ELF_C_READ
, 0)) == NULL
) {
364 (void) fprintf(stderr
, "elf_begin() failed: %s\n",
371 * Process each elf descriptor.
373 process_elf(elf
, elf_fname
, fd
, 0);