8030 libmvect: uninitialized variable
[unleashed.git] / usr / src / lib / libtnfctl / sym.c
blob82730e9f519a5d0caf77a920f5310bd3e7cc6ee2
1 /*
2 * CDDL HEADER START
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
7 * with the License.
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]
20 * CDDL HEADER END
23 * Copyright (c) 1994, by Sun Microsytems, Inc.
27 * Routines that
28 * - return an address for a symbol name
29 * - return a symbol name for an address
32 #ifndef DEBUG
33 #define NDEBUG 1
34 #endif
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <string.h>
39 #include <errno.h>
40 #include <sys/procfs.h>
41 #include <sys/stat.h>
42 #include <assert.h>
44 #include "tnfctl_int.h"
45 #include "dbg.h"
49 * Typedefs
52 typedef struct sym_args {
53 char *sa_name;
54 uintptr_t sa_addr;
55 } sym_args_t;
58 * Declarations
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,
68 void *sym_entry,
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.
80 tnfctl_errcode_t
81 _tnfctl_sym_find_in_obj(int objfd, uintptr_t baseaddr, const char *symname,
82 uintptr_t *symaddr)
84 tnfctl_errcode_t prexstat = TNFCTL_ERR_NONE;
85 sym_args_t symargs;
86 tnfctl_elf_search_t search_info;
88 DBG_TNF_PROBE_1(_tnfctl_sym_find_in_obj_1, "libtnfctl",
89 "sunw%verbosity 3",
90 tnf_string, searching_for, symname);
92 symargs.sa_name = (char *) symname;
93 /* clear output argument in advance */
94 symargs.sa_addr = 0;
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);
101 if (prexstat)
102 return (prexstat);
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
116 * in the process.
118 tnfctl_errcode_t
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;
123 objlist_t *obj;
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)
141 /* symbol found */
142 break;
143 else if (prexstat != TNFCTL_ERR_BADARG)
144 /* error condition */
145 break;
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");
155 return (prexstat);
159 * _tnfctl_sym_obj_find() - determines the virtual address of the supplied
160 * symbol in the object specified by base name
162 tnfctl_errcode_t
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;
168 const char *str_ptr;
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);
177 found_obj = NULL;
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)
184 continue;
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;
190 } else {
191 str_ptr++; /* bump up past '/' */
194 /* XXX - use strcoll ? */
195 if (strcmp(str_ptr, lib_base_name) == 0) {
196 found_obj = obj;
197 break;
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");
210 return (prexstat);
214 * _tnfctl_sym_findname() - determines the name of a function from its address.
216 tnfctl_errcode_t
217 _tnfctl_sym_findname(tnfctl_handle_t *hndl, uintptr_t symaddr,
218 char **symname)
220 boolean_t release_lock;
221 tnfctl_errcode_t prexstat = TNFCTL_ERR_NONE;
222 objlist_t *obj;
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)
239 /* symbol found */
240 break;
241 else if (prexstat != TNFCTL_ERR_BADARG)
242 /* error condition */
243 break;
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");
253 return (prexstat);
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,
267 char **symname)
269 tnfctl_errcode_t prexstat = TNFCTL_ERR_NONE;
270 sym_args_t symargs;
271 tnfctl_elf_search_t search_info;
273 DBG_TNF_PROBE_1(sym_findname_in_obj_1, "libtnfctl",
274 "sunw%verbosity 3",
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);
286 if (prexstat)
287 return (prexstat);
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;
308 #if 0
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);
312 else
313 printf("symargs_p->sa_name = 0\n");
314 if (name != 0)
315 printf("(name) = %s\n", name);
316 else
317 printf("name = 0\n");
318 #endif
320 #ifdef VERYVERBOSE
321 (void) fprintf(stderr, "sym_match: checking \"%s\"\n", name);
322 #endif
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;
334 #if 0
335 printf("leaving sym_match\n");
336 #endif
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;
352 #ifdef VERYVERBOSE
353 (void) fprintf(stderr, "sym_matchname: checking \"%s\"\n", name);
354 #endif
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);