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.
27 #pragma ident "%Z%%M% %I% %E% SMI"
39 #include <sys/types.h>
45 #include <sys/machelf.h>
48 #include <sys/cpuvar.h>
50 typedef struct syment
{
56 static syment_t
*symbol_table
;
57 static int nsyms
, maxsyms
;
58 static char maxsymname
[64];
61 #define elf_getshdr elf64_getshdr
63 #define elf_getshdr elf32_getshdr
67 add_symbol(char *name
, uintptr_t addr
, size_t size
)
71 if (nsyms
>= maxsyms
) {
73 symbol_table
= realloc(symbol_table
, maxsyms
* sizeof (*sep
));
74 if (symbol_table
== NULL
) {
75 (void) fprintf(stderr
, "can't allocate symbol table\n");
79 sep
= &symbol_table
[nsyms
++];
87 remove_symbol(uintptr_t addr
)
90 syment_t
*sep
= symbol_table
;
92 for (i
= 0; i
< nsyms
; i
++, sep
++)
93 if (sep
->addr
== addr
)
98 fake_up_certain_popular_kernel_symbols(void)
104 if ((kc
= kstat_open()) == NULL
)
107 for (ksp
= kc
->kc_chain
; ksp
; ksp
= ksp
->ks_next
) {
108 if (strcmp(ksp
->ks_module
, "cpu_info") == 0) {
109 if ((name
= malloc(20)) == NULL
)
112 * For consistency, keep cpu[0] and toss cpu0
113 * or any other such symbols.
115 if (ksp
->ks_instance
== 0)
116 remove_symbol((uintptr_t)ksp
->ks_private
);
117 (void) sprintf(name
, "cpu[%d]", ksp
->ks_instance
);
118 add_symbol(name
, (uintptr_t)ksp
->ks_private
,
119 sizeof (struct cpu
));
122 (void) kstat_close(kc
);
126 symcmp(const void *p1
, const void *p2
)
128 uintptr_t a1
= ((syment_t
*)p1
)->addr
;
129 uintptr_t a2
= ((syment_t
*)p2
)->addr
;
143 Sym
*symtab
, *symp
, *lastsym
;
150 if ((fd
= open("/dev/ksyms", O_RDONLY
)) == -1)
153 (void) elf_version(EV_CURRENT
);
155 elf
= elf_begin(fd
, ELF_C_READ
, NULL
);
157 for (cnt
= 1; (scn
= elf_nextscn(elf
, scn
)) != NULL
; cnt
++) {
158 Shdr
*shdr
= elf_getshdr(scn
);
159 if (shdr
->sh_type
== SHT_SYMTAB
) {
160 symtab
= (Sym
*)elf_getdata(scn
, NULL
)->d_buf
;
161 nsyms
= shdr
->sh_size
/ shdr
->sh_entsize
;
162 strindex
= shdr
->sh_link
;
166 for (cnt
= 1; (scn
= elf_nextscn(elf
, scn
)) != NULL
; cnt
++) {
168 strtab
= (char *)elf_getdata(scn
, NULL
)->d_buf
;
171 lastsym
= symtab
+ nsyms
;
173 for (symp
= symtab
; symp
< lastsym
; symp
++)
174 if ((uint_t
)ELF32_ST_TYPE(symp
->st_info
) <= STT_FUNC
&&
176 add_symbol(symp
->st_name
+ strtab
,
177 (uintptr_t)symp
->st_value
, (size_t)symp
->st_size
);
179 fake_up_certain_popular_kernel_symbols();
180 (void) sprintf(maxsymname
, "0x%lx", ULONG_MAX
);
181 add_symbol(maxsymname
, ULONG_MAX
, 1);
183 qsort(symbol_table
, nsyms
, sizeof (syment_t
), symcmp
);
186 * Destroy all duplicate symbols, then sort it again.
188 for (i
= 0; i
< nsyms
- 1; i
++)
189 if (symbol_table
[i
].addr
== symbol_table
[i
+ 1].addr
)
190 symbol_table
[i
].addr
= 0;
192 qsort(symbol_table
, nsyms
, sizeof (syment_t
), symcmp
);
194 while (symbol_table
[1].addr
== 0) {
198 symbol_table
[0].name
= "(usermode)";
199 symbol_table
[0].addr
= 0;
200 symbol_table
[0].size
= 1;
206 addr_to_sym(uintptr_t addr
, uintptr_t *offset
, size_t *sizep
)
213 while (hi
- lo
> 1) {
215 if (addr
>= symbol_table
[mid
].addr
) {
221 sep
= &symbol_table
[lo
];
222 *offset
= addr
- sep
->addr
;
228 sym_to_addr(char *name
)
231 syment_t
*sep
= symbol_table
;
233 for (i
= 0; i
< nsyms
; i
++) {
234 if (strcmp(name
, sep
->name
) == 0)
245 syment_t
*sep
= symbol_table
;
247 for (i
= 0; i
< nsyms
; i
++) {
248 if (strcmp(name
, sep
->name
) == 0)