dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / sgs / libelf / demo / dispsyms.c
blob03f9ab5f624c00732a506fe5cbf05afb37c58482
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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.
39 #include <stdio.h>
40 #include <libelf.h>
41 #include <gelf.h>
42 #include <fcntl.h>
43 #include <unistd.h>
44 #include <stdlib.h>
45 #include <string.h>
47 static const char *symbind[STB_NUM] = {
48 /* STB_LOCL */ "LOCL",
49 /* STB_GLOBAL */ "GLOB",
50 /* STB_WEAK */ "WEAK"
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",
60 /* STT_TLS */ "TLS"
62 #if STT_NUM != (STT_TLS + 1)
63 #error "STT_NUM has grown. Update symtype[]."
64 #endif
66 #define INTSTRLEN 32
69 static void
70 print_symtab(Elf *elf, const char *file)
72 Elf_Scn *scn = NULL;
73 GElf_Shdr shdr;
74 GElf_Ehdr ehdr;
75 size_t shstrndx;
78 if (gelf_getehdr(elf, &ehdr) == NULL) {
79 (void) fprintf(stderr, "%s: elf_getehdr() failed: %s\n",
80 file, elf_errmsg(0));
81 return;
84 if (elf_getshdrstrndx(elf, &shstrndx) == -1) {
85 (void) fprintf(stderr, "%s: elf_getshdrstrndx() failed: %s\n",
86 file, elf_errmsg(0));
87 return;
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",
97 file, elf_errmsg(0));
98 return;
100 if ((shdr.sh_type != SHT_SYMTAB) &&
101 (shdr.sh_type != SHT_DYNSYM) &&
102 (shdr.sh_type != SHT_SUNW_LDYNSYM))
103 continue;
106 * Get the data associated with the Symbol
107 * section.
109 if ((symdata = elf_getdata(scn, NULL)) == NULL) {
110 (void) fprintf(stderr,
111 "%s: elf_getdata() failed: %s\n",
112 file, elf_errmsg(0));
113 return;
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.
128 shndxdata = 0;
129 nosymshndx = 0;
130 symcnt = shdr.sh_size / shdr.sh_entsize;
131 for (ndx = 0; ndx < symcnt; ndx++) {
132 GElf_Sym sym;
133 Elf32_Word shndx;
134 uint_t type, bind, specshndx;
135 char bindbuf[INTSTRLEN];
136 char typebuf[INTSTRLEN];
137 char shndxbuf[INTSTRLEN];
138 const char *bindstr, *typestr, *shndxstr;
141 * Get a symbol entry
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));
148 return;
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;
160 GElf_Shdr _shdr;
161 GElf_Word symscnndx;
163 specshndx = 0;
164 symscnndx = elf_ndxscn(scn);
166 while ((_scn =
167 elf_nextscn(elf, _scn)) != NULL) {
168 if (gelf_getshdr(_scn, &_shdr) == NULL)
169 break;
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
176 * table.
178 if ((_shdr.sh_type ==
179 SHT_SYMTAB_SHNDX) &&
180 (_shdr.sh_link == symscnndx) &&
181 ((shndxdata = elf_getdata(_scn,
182 NULL)) != NULL))
183 break;
186 * Get a symbol entry
188 if (shndxdata &&
189 (gelf_getsymshndx(symdata, shndxdata, ndx,
190 &sym, &shndx) == NULL)) {
191 (void) fprintf(stderr,
192 "%s: gelf_getsymshndx() "
193 "failed: %s\n",
194 file, elf_errmsg(0));
195 return;
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
203 * a bogus value.
205 if (shndxdata == 0)
206 nosymshndx = 1;
210 * Decode the type & binding information
212 type = GELF_ST_TYPE(sym.st_info);
213 bind = GELF_ST_BIND(sym.st_info);
215 if (type < STT_NUM)
216 typestr = symtype[type];
217 else {
218 (void) snprintf(typebuf, INTSTRLEN,
219 "%d", type);
220 typestr = typebuf;
223 if (bind < STB_NUM)
224 bindstr = symbind[bind];
225 else {
226 (void) snprintf(bindbuf, INTSTRLEN,
227 "%d", bind);
228 bindstr = bindbuf;
232 specshndx = 0;
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;
238 specshndx = 1;
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";
251 else {
252 (void) snprintf(shndxbuf, INTSTRLEN,
253 "%ld", shndx);
254 shndxstr = shndxbuf;
256 } else {
257 (void) snprintf(shndxbuf, INTSTRLEN,
258 "%ld", shndx);
259 shndxstr = shndxbuf;
263 * Display the symbol entry.
265 (void) printf("[%3d] 0x%08llx 0x%08llx %-4s "
266 "%-6s %2d %5s %s\n",
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));
275 static void
276 process_elf(Elf *elf, char *file, int fd, int member)
278 Elf_Cmd cmd;
279 Elf *_elf;
281 switch (elf_kind(elf)) {
282 case ELF_K_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);
288 break;
289 case ELF_K_AR:
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().
297 cmd = ELF_C_READ;
298 while ((_elf = elf_begin(fd, cmd, elf)) != NULL) {
299 Elf_Arhdr *arhdr;
300 char buffer[1024];
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);
318 break;
319 default:
320 if (!member)
321 (void) fprintf(stderr,
322 "%s: unexpected elf_kind(): 0x%x\n",
323 file, elf_kind(elf));
324 return;
329 main(int argc, char **argv)
331 int i;
333 if (argc < 2) {
334 (void) printf("usage: %s elf_file ...\n", argv[0]);
335 return (1);
339 * Initialize the elf library, must be called before elf_begin()
340 * can be called.
342 if (elf_version(EV_CURRENT) == EV_NONE) {
343 (void) fprintf(stderr,
344 "elf_version() failed: %s\n", elf_errmsg(0));
345 return (1);
348 for (i = 1; i < argc; i++) {
349 int fd;
350 Elf *elf;
351 char *elf_fname;
353 elf_fname = argv[i];
354 if ((fd = open(elf_fname, O_RDONLY)) == -1) {
355 perror("open");
356 continue;
360 * Attempt to open an Elf descriptor Read-Only
361 * for each file.
363 if ((elf = elf_begin(fd, ELF_C_READ, 0)) == NULL) {
364 (void) fprintf(stderr, "elf_begin() failed: %s\n",
365 elf_errmsg(0));
366 (void) close(fd);
367 continue;
371 * Process each elf descriptor.
373 process_elf(elf, elf_fname, fd, 0);
374 (void) elf_end(elf);
375 (void) close(fd);
378 return (0);