4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1997-1999 by Sun Microsystems, Inc.
24 * All rights reserved.
37 #include <sys/types.h>
43 #include <sys/machelf.h>
46 #include <sys/cpuvar.h>
48 typedef struct syment
{
54 static syment_t
*symbol_table
;
55 static int nsyms
, maxsyms
;
56 static char maxsymname
[64];
59 #define elf_getshdr elf64_getshdr
61 #define elf_getshdr elf32_getshdr
65 add_symbol(char *name
, uintptr_t addr
, size_t size
)
69 if (nsyms
>= maxsyms
) {
71 symbol_table
= realloc(symbol_table
, maxsyms
* sizeof (*sep
));
72 if (symbol_table
== NULL
) {
73 (void) fprintf(stderr
, "can't allocate symbol table\n");
77 sep
= &symbol_table
[nsyms
++];
85 remove_symbol(uintptr_t addr
)
88 syment_t
*sep
= symbol_table
;
90 for (i
= 0; i
< nsyms
; i
++, sep
++)
91 if (sep
->addr
== addr
)
96 fake_up_certain_popular_kernel_symbols(void)
102 if ((kc
= kstat_open()) == NULL
)
105 for (ksp
= kc
->kc_chain
; ksp
; ksp
= ksp
->ks_next
) {
106 if (strcmp(ksp
->ks_module
, "cpu_info") == 0) {
107 if ((name
= malloc(20)) == NULL
)
110 * For consistency, keep cpu[0] and toss cpu0
111 * or any other such symbols.
113 if (ksp
->ks_instance
== 0)
114 remove_symbol((uintptr_t)ksp
->ks_private
);
115 (void) sprintf(name
, "cpu[%d]", ksp
->ks_instance
);
116 add_symbol(name
, (uintptr_t)ksp
->ks_private
,
117 sizeof (struct cpu
));
120 (void) kstat_close(kc
);
124 symcmp(const void *p1
, const void *p2
)
126 uintptr_t a1
= ((syment_t
*)p1
)->addr
;
127 uintptr_t a2
= ((syment_t
*)p2
)->addr
;
141 Sym
*symtab
, *symp
, *lastsym
;
148 if ((fd
= open("/dev/ksyms", O_RDONLY
)) == -1)
151 (void) elf_version(EV_CURRENT
);
153 elf
= elf_begin(fd
, ELF_C_READ
, NULL
);
155 for (cnt
= 1; (scn
= elf_nextscn(elf
, scn
)) != NULL
; cnt
++) {
156 Shdr
*shdr
= elf_getshdr(scn
);
157 if (shdr
->sh_type
== SHT_SYMTAB
) {
158 symtab
= (Sym
*)elf_getdata(scn
, NULL
)->d_buf
;
159 nsyms
= shdr
->sh_size
/ shdr
->sh_entsize
;
160 strindex
= shdr
->sh_link
;
164 for (cnt
= 1; (scn
= elf_nextscn(elf
, scn
)) != NULL
; cnt
++) {
166 strtab
= (char *)elf_getdata(scn
, NULL
)->d_buf
;
169 lastsym
= symtab
+ nsyms
;
171 for (symp
= symtab
; symp
< lastsym
; symp
++)
172 if ((uint_t
)ELF32_ST_TYPE(symp
->st_info
) <= STT_FUNC
&&
174 add_symbol(symp
->st_name
+ strtab
,
175 (uintptr_t)symp
->st_value
, (size_t)symp
->st_size
);
177 fake_up_certain_popular_kernel_symbols();
178 (void) sprintf(maxsymname
, "0x%lx", ULONG_MAX
);
179 add_symbol(maxsymname
, ULONG_MAX
, 1);
181 qsort(symbol_table
, nsyms
, sizeof (syment_t
), symcmp
);
184 * Destroy all duplicate symbols, then sort it again.
186 for (i
= 0; i
< nsyms
- 1; i
++)
187 if (symbol_table
[i
].addr
== symbol_table
[i
+ 1].addr
)
188 symbol_table
[i
].addr
= 0;
190 qsort(symbol_table
, nsyms
, sizeof (syment_t
), symcmp
);
192 while (symbol_table
[1].addr
== 0) {
196 symbol_table
[0].name
= "(usermode)";
197 symbol_table
[0].addr
= 0;
198 symbol_table
[0].size
= 1;
204 addr_to_sym(uintptr_t addr
, uintptr_t *offset
, size_t *sizep
)
211 while (hi
- lo
> 1) {
213 if (addr
>= symbol_table
[mid
].addr
) {
219 sep
= &symbol_table
[lo
];
220 *offset
= addr
- sep
->addr
;
226 sym_to_addr(char *name
)
229 syment_t
*sep
= symbol_table
;
231 for (i
= 0; i
< nsyms
; i
++) {
232 if (strcmp(name
, sep
->name
) == 0)
243 syment_t
*sep
= symbol_table
;
245 for (i
= 0; i
< nsyms
; i
++) {
246 if (strcmp(name
, sep
->name
) == 0)