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) 1994, by Sun Microsytems, Inc.
28 * - return an address for a symbol name
29 * - return a symbol name for an address
40 #include <sys/procfs.h>
44 #include "tnfctl_int.h"
52 typedef struct sym_args
{
61 static tnfctl_errcode_t
sym_findname_in_obj(int objfd
, uintptr_t baseaddr
,
62 uintptr_t symaddr
, char **symname
);
64 static tnfctl_errcode_t
sym_match(char *name
, uintptr_t addr
, void *sym_entry
,
65 tnfctl_elf_search_t
*search_info_p
);
67 static tnfctl_errcode_t
sym_matchname(char *name
, uintptr_t addr
,
69 tnfctl_elf_search_t
*search_info_p
);
72 /* ---------------------------------------------------------------- */
73 /* ----------------------- Public Functions ----------------------- */
74 /* ---------------------------------------------------------------- */
77 * _tnfctl_sym_find_in_obj() - determines the virtual address of the supplied
78 * symbol in the object file specified by fd.
81 _tnfctl_sym_find_in_obj(int objfd
, uintptr_t baseaddr
, const char *symname
,
84 tnfctl_errcode_t prexstat
= TNFCTL_ERR_NONE
;
86 tnfctl_elf_search_t search_info
;
88 DBG_TNF_PROBE_1(_tnfctl_sym_find_in_obj_1
, "libtnfctl",
90 tnf_string
, searching_for
, symname
);
92 symargs
.sa_name
= (char *) symname
;
93 /* clear output argument in advance */
96 search_info
.section_func
= _tnfctl_traverse_dynsym
;
97 search_info
.record_func
= sym_match
;
98 search_info
.record_data
= &symargs
;
100 prexstat
= _tnfctl_traverse_object(objfd
, baseaddr
, &search_info
);
104 /* check if we found symbol address */
105 if (symargs
.sa_addr
== 0) {
106 return (TNFCTL_ERR_BADARG
);
109 *symaddr
= symargs
.sa_addr
;
110 return (TNFCTL_ERR_NONE
);
115 * _tnfctl_sym_find() - determines the virtual address of the supplied symbol
119 _tnfctl_sym_find(tnfctl_handle_t
*hndl
, const char *symname
, uintptr_t *symaddr
)
121 boolean_t release_lock
;
122 tnfctl_errcode_t prexstat
= TNFCTL_ERR_NONE
;
125 DBG_TNF_PROBE_1(_tnfctl_sym_find_start
, "libtnfctl",
126 "start _tnfctl_sym_find; sunw%verbosity 3",
127 tnf_string
, searching_for
, symname
);
129 /*LINTED statement has no consequent: else*/
130 LOCK(hndl
, prexstat
, release_lock
);
132 /* for every object in list, search for symbol */
133 for (obj
= hndl
->objlist
; obj
; obj
= obj
->next
) {
134 if (obj
->old
== B_TRUE
)
135 continue; /* don't examine dlclose'd libs */
137 /* return value of TNFCTL_ERR_BADARG means symbol not found */
138 prexstat
= _tnfctl_sym_find_in_obj(obj
->objfd
,
139 obj
->baseaddr
, symname
, symaddr
);
140 if (prexstat
== TNFCTL_ERR_NONE
)
143 else if (prexstat
!= TNFCTL_ERR_BADARG
)
144 /* error condition */
146 /* continue loop on TNFCTL_ERR_BADARG */
149 /*LINTED statement has no consequent: else*/
150 UNLOCK(hndl
, release_lock
);
152 DBG_TNF_PROBE_0(_tnfctl_sym_find_end
, "libtnfctl",
153 "end _tnfctl_sym_find; sunw%verbosity 3");
159 * _tnfctl_sym_obj_find() - determines the virtual address of the supplied
160 * symbol in the object specified by base name
163 _tnfctl_sym_obj_find(tnfctl_handle_t
*hndl
, const char *lib_base_name
,
164 const char *symname
, uintptr_t *symaddr
)
166 tnfctl_errcode_t prexstat
= TNFCTL_ERR_NONE
;
167 objlist_t
*obj
, *found_obj
;
170 assert((hndl
->mode
== INTERNAL_MODE
) ?
171 (MUTEX_HELD(&_tnfctl_lmap_lock
)) : 1);
173 DBG_TNF_PROBE_1(_tnfctl_sym_obj_find_start
, "libtnfctl",
174 "start _tnfctl_sym_obj_find; sunw%verbosity 3",
175 tnf_string
, searching_for
, symname
);
178 /* for every object in list ... */
179 for (obj
= hndl
->objlist
; obj
; obj
= obj
->next
) {
180 if (obj
->old
== B_TRUE
)
181 continue; /* don't examine dlclose'd libs */
183 if (obj
->objname
== NULL
)
186 /* find the last occurrence of / in the name */
187 str_ptr
= strrchr(obj
->objname
, '/');
188 if (str_ptr
== NULL
) {
189 str_ptr
= obj
->objname
;
191 str_ptr
++; /* bump up past '/' */
194 /* XXX - use strcoll ? */
195 if (strcmp(str_ptr
, lib_base_name
) == 0) {
200 /* return value of TNFCTL_ERR_BADARG means symbol not found */
201 if (found_obj
== NULL
)
202 return (TNFCTL_ERR_BADARG
);
204 prexstat
= _tnfctl_sym_find_in_obj(found_obj
->objfd
,
205 found_obj
->baseaddr
, symname
, symaddr
);
207 DBG_TNF_PROBE_0(_tnfctl_sym_obj_find_end
, "libtnfctl",
208 "end _tnfctl_sym_obj_find; sunw%verbosity 3");
214 * _tnfctl_sym_findname() - determines the name of a function from its address.
217 _tnfctl_sym_findname(tnfctl_handle_t
*hndl
, uintptr_t symaddr
,
220 boolean_t release_lock
;
221 tnfctl_errcode_t prexstat
= TNFCTL_ERR_NONE
;
224 DBG_TNF_PROBE_1(_tnfctl_sym_findname_start
, "libtnfctl",
225 "start _tnfctl_sym_findname; sunw%verbosity 3",
226 tnf_opaque
, searching_for
, symaddr
);
228 /*LINTED statement has no consequent: else*/
229 LOCK(hndl
, prexstat
, release_lock
);
231 /* for every object in list, search for name */
232 for (obj
= hndl
->objlist
; obj
; obj
= obj
->next
) {
233 if (obj
->old
== B_TRUE
)
234 continue; /* don't examine dlclose'd libs */
235 /* return value of TNFCTL_ERR_BADARG means symbol not found */
236 prexstat
= sym_findname_in_obj(obj
->objfd
,
237 obj
->baseaddr
, symaddr
, symname
);
238 if (prexstat
== TNFCTL_ERR_NONE
)
241 else if (prexstat
!= TNFCTL_ERR_BADARG
)
242 /* error condition */
244 /* continue loop on TNFCTL_ERR_BADARG */
247 /*LINTED statement has no consequent: else*/
248 UNLOCK(hndl
, release_lock
);
250 DBG_TNF_PROBE_0(_tnfctl_sym_findname_end
, "libtnfctl",
251 "end _tnfctl_sym_findname; sunw%verbosity 3");
257 /* ---------------------------------------------------------------- */
258 /* ----------------------- Private Functions ---------------------- */
259 /* ---------------------------------------------------------------- */
262 * sym_findname_in_obj() - determines the name of the supplied
263 * address in the specified object file.
265 static tnfctl_errcode_t
266 sym_findname_in_obj(int objfd
, uintptr_t baseaddr
, uintptr_t symaddr
,
269 tnfctl_errcode_t prexstat
= TNFCTL_ERR_NONE
;
271 tnfctl_elf_search_t search_info
;
273 DBG_TNF_PROBE_1(sym_findname_in_obj_1
, "libtnfctl",
275 tnf_opaque
, searching_for
, symaddr
);
277 /* clear output argument in advance */
278 symargs
.sa_name
= NULL
;
279 symargs
.sa_addr
= symaddr
;
281 search_info
.section_func
= _tnfctl_traverse_dynsym
;
282 search_info
.record_func
= sym_matchname
;
283 search_info
.record_data
= &symargs
;
285 prexstat
= _tnfctl_traverse_object(objfd
, baseaddr
, &search_info
);
289 /* check if we found symbol address */
290 if (symargs
.sa_name
== NULL
) {
291 return (TNFCTL_ERR_BADARG
);
294 *symname
= symargs
.sa_name
;
295 return (TNFCTL_ERR_NONE
);
299 * sym_match() - function to be called on each symbol in a dynsym section.
300 * Used to find the address of a symbol.
302 static tnfctl_errcode_t
303 sym_match(char *name
, uintptr_t addr
, void *sym_entry
,
304 tnfctl_elf_search_t
*search_info_p
)
306 sym_args_t
*symargs_p
= (sym_args_t
*) search_info_p
->record_data
;
307 Elf3264_Sym
*sym
= (Elf3264_Sym
*) sym_entry
;
309 printf("enter sym_match: \n");
310 if (symargs_p
->sa_name
!= 0)
311 printf("(symargs_p->sa_name) = %s\n", symargs_p
->sa_name
);
313 printf("symargs_p->sa_name = 0\n");
315 printf("(name) = %s\n", name
);
317 printf("name = 0\n");
321 (void) fprintf(stderr
, "sym_match: checking \"%s\"\n", name
);
324 if ((sym
->st_shndx
!= SHN_UNDEF
) &&
325 (strcmp(name
, symargs_p
->sa_name
) == 0)) {
327 DBG_TNF_PROBE_2(sym_match_1
, "libtnfctl",
328 "sunw%verbosity 2; sunw%debug '\tMatched Symbol'",
329 tnf_string
, symbol
, name
,
330 tnf_opaque
, address_found
, addr
);
332 symargs_p
->sa_addr
= addr
;
335 printf("leaving sym_match\n");
337 return (TNFCTL_ERR_NONE
);
342 * sym_matchname() - function to be called on each symbol in a dynsym
343 * section. Used to find the name of a symbol whose address is known.
345 static tnfctl_errcode_t
346 sym_matchname(char *name
, uintptr_t addr
, void *sym_entry
,
347 tnfctl_elf_search_t
* search_info_p
)
349 sym_args_t
*symargs_p
= (sym_args_t
*) search_info_p
->record_data
;
350 Elf3264_Sym
*sym
= (Elf3264_Sym
*) sym_entry
;
353 (void) fprintf(stderr
, "sym_matchname: checking \"%s\"\n", name
);
356 if ((sym
->st_shndx
!= SHN_UNDEF
) &&
357 symargs_p
->sa_addr
== addr
) {
359 DBG_TNF_PROBE_2(sym_matchname_1
, "libtnfctl",
360 "sunw%verbosity 2; sunw%debug '\tMatched Name'",
361 tnf_string
, symbol_found
, name
,
362 tnf_opaque
, address
, addr
);
364 symargs_p
->sa_name
= strdup(name
);
367 return (TNFCTL_ERR_NONE
);