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]
23 * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
32 * Given a symbol index, look up the corresponding symbol from the
35 * This function allows the caller to treat the symbol table as a single
36 * logical entity even though there may be 2 actual ELF symbol tables
37 * involved. See the comments in Pcontrol.h for details.
40 symtab_getsym(sym_tbl_t
*symtab
, int ndx
, GElf_Sym
*dst
)
42 /* If index is in range of primary symtab, look it up there */
43 if (ndx
>= symtab
->st_symn_aux
) {
44 return (gelf_getsym(symtab
->st_syms_pri
,
45 ndx
- symtab
->st_symn_aux
, dst
));
48 /* Not in primary: Look it up in the auxiliary symtab */
49 return (gelf_getsym(symtab
->st_syms_aux
, ndx
, dst
));
53 str_map_sym(const char *symname
, map_info_t
*mp
, GElf_Sym
*symptr
, char **str
)
59 if (mp
->mi_symtab
.st_syms_pri
)
60 symp
= &(mp
->mi_symtab
);
61 else if (mp
->mi_dynsym
.st_syms_pri
)
62 symp
= &(mp
->mi_dynsym
);
68 for (i
= 0; i
< (int)symp
->st_symn
; i
++) {
71 if (symtab_getsym(symp
, i
, &sym
) == NULL
) {
72 (void) printf("symtab_getsym(): %s\n", elf_errmsg(-1));
78 if ((sym
.st_shndx
== SHN_UNDEF
) ||
79 (strcmp(strs
+ sym
.st_name
, symname
) != 0))
83 *str
= (char *)strs
+ symptr
->st_name
;
84 if ((mp
->mi_flags
& FLG_MI_EXEC
) == 0)
85 symptr
->st_value
+= (GElf_Addr
)(mp
->mi_addr
);
93 * If two syms are of equal value this routine will
94 * favor one over the other based off of it's symbol
98 sym_swap(GElf_Sym
* s1
, GElf_Sym
* s2
)
100 int t1
= GELF_ST_TYPE(s1
->st_info
);
101 int t2
= GELF_ST_TYPE(s2
->st_info
);
103 if ((t1
== STT_FUNC
) || (t2
== STT_FUNC
)) {
109 if ((t1
== STT_OBJECT
) || (t2
== STT_OBJECT
)) {
110 if (t1
== STT_OBJECT
)
115 if ((t1
== STT_OBJECT
) || (t2
== STT_OBJECT
)) {
116 if (t1
== STT_OBJECT
)
124 addr_map_sym(map_info_t
*mp
, ulong_t addr
, GElf_Sym
*symptr
, char **str
)
128 GElf_Sym
*symr
= NULL
;
129 GElf_Sym
*lsymr
= NULL
;
132 ulong_t baseaddr
= 0;
135 if ((mp
->mi_flags
& FLG_MI_EXEC
) == 0)
136 baseaddr
= (ulong_t
)mp
->mi_addr
;
138 if (mp
->mi_symtab
.st_syms_pri
)
139 symp
= &(mp
->mi_symtab
);
140 else if (mp
->mi_dynsym
.st_syms_pri
)
141 symp
= &(mp
->mi_dynsym
);
149 for (i
= 0; i
< (int)symp
->st_symn
; i
++) {
152 if (symtab_getsym(symp
, i
, &sym
) == NULL
) {
153 (void) printf("symtab_getsym(): %s\n", elf_errmsg(-1));
156 if ((sym
.st_name
== 0) || (sym
.st_shndx
== SHN_UNDEF
))
159 svalue
= (ulong_t
)sym
.st_value
;
161 if (svalue
<= addr
) {
163 * track both the best local and best
164 * global fit for this address. Later
165 * we will favor the global over the local
167 if ((GELF_ST_BIND(sym
.st_info
) == STB_LOCAL
) &&
169 (svalue
>= (ulong_t
)lsymr
->st_value
))) {
170 if (lsymr
&& (lsymr
->st_value
== svalue
))
171 *lsymr
= sym_swap(lsymr
, &sym
);
176 } else if ((symr
== NULL
) ||
177 (svalue
>= (ulong_t
)symr
->st_value
)) {
178 if (symr
&& (symr
->st_value
== svalue
))
179 *symr
= sym_swap(symr
, &sym
);
187 if ((symr
== NULL
) && (lsymr
== NULL
))
192 * If a possible local symbol was found should
195 if (symr
&& (lsymr
->st_value
> symr
->st_value
))
197 else if (symr
== NULL
)
202 *str
= (char *)(symp
->st_strs
+ symptr
->st_name
);
203 symptr
->st_value
+= baseaddr
;
208 addr_to_sym(struct ps_prochandle
*ph
, ulong_t addr
,
209 GElf_Sym
*symp
, char **str
)
213 if ((mip
= addr_to_map(ph
, addr
)) == NULL
)
216 return (addr_map_sym(mip
, addr
, symp
, str
));
220 str_to_sym(struct ps_prochandle
*ph
, const char *name
, GElf_Sym
*symp
)
224 if (ph
->pp_lmaplist
.ml_head
== NULL
) {
225 if (str_map_sym(name
, &(ph
->pp_ldsomap
), symp
, NULL
) == RET_OK
)
228 return (str_map_sym(name
, &(ph
->pp_execmap
), symp
, NULL
));
231 for (mip
= ph
->pp_lmaplist
.ml_head
; mip
; mip
= mip
->mi_next
)
232 if (str_map_sym(name
, mip
, symp
, NULL
) == RET_OK
)