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.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * Generic functions that know how to traverse elf sections in an object.
30 * Also functions that know how to traverse records in a section.
38 #include <sys/procfs.h>
41 #include "tnfctl_int.h"
46 * _tnfctl_traverse_object() - traverses all of the elf sections in an object,
47 * calling the supplied function on each.
50 _tnfctl_traverse_object(int objfd
, uintptr_t addr
,
51 tnfctl_elf_search_t
*search_info_p
)
54 GElf_Ehdr
*ehdr
, ehdr_obj
;
56 GElf_Shdr
*shdr
, shdr_obj
;
59 tnfctl_errcode_t prexstat
= TNFCTL_ERR_NONE
;
61 DBG_TNF_PROBE_1(_tnfctl_traverse_object_1
, "libtnfctl",
63 tnf_opaque
, obj_addr
, addr
);
65 if (elf_version(EV_CURRENT
) == EV_NONE
)
66 return (TNFCTL_ERR_INTERNAL
);
68 /* open elf descriptor on the fd */
69 elf
= elf_begin(objfd
, ELF_C_READ
, NULL
);
70 if (elf
== NULL
|| elf_kind(elf
) != ELF_K_ELF
) {
71 DBG_TNF_PROBE_0(_tnfctl_traverse_object_2
, "libtnfctl",
72 "sunw%verbosity 3; sunw%debug 'not elf object'");
73 return (TNFCTL_ERR_INTERNAL
);
75 /* get the elf header */
76 if ((ehdr
= gelf_getehdr(elf
, &ehdr_obj
)) == NULL
) {
77 DBG((void) fprintf(stderr
,
78 "_tnfctl_traverse_object: gelf_getehdr failed\n"));
80 return (TNFCTL_ERR_INTERNAL
);
82 if ((ehdr
->e_type
!= ET_EXEC
) && (ehdr
->e_type
!= ET_DYN
)) {
83 DBG((void) fprintf(stderr
,
84 "_tnfctl_traverse_object: not an "
85 "executable or a shared object\n"));
87 return (TNFCTL_ERR_INTERNAL
);
89 /* if an executable file, the base address is 0 */
90 if (ehdr
->e_type
== ET_EXEC
)
92 /* get a pointer to the elf header string table */
93 strs
= elf_strptr(elf
, ehdr
->e_shstrndx
, NULL
);
95 DBG_TNF_PROBE_1(_tnfctl_traverse_object_3
, "libtnfctl",
97 tnf_long
, num_sections_found
, ehdr
->e_shnum
);
99 for (idx
= 1; idx
< ehdr
->e_shnum
; idx
++) {
102 if ((scn
= elf_getscn(elf
, idx
)) == NULL
) {
103 DBG((void) fprintf(stderr
,
104 "_tnfctl_traverse_object: elf_getscn failed\n"));
105 prexstat
= TNFCTL_ERR_INTERNAL
;
108 if ((shdr
= gelf_getshdr(scn
, &shdr_obj
)) == NULL
) {
109 DBG((void) fprintf(stderr
,
110 "_tnfctl_traverse_obj:gelf_getshdr failed\n"));
111 prexstat
= TNFCTL_ERR_INTERNAL
;
115 if ((data
= elf_getdata(scn
, NULL
)) == NULL
) {
116 DBG((void) fprintf(stderr
,
117 "_tnfctl_traverse_obj:gelf_getdata failed\n"));
118 prexstat
= TNFCTL_ERR_INTERNAL
;
121 /* call the supplied function */
122 prexstat
= search_info_p
->section_func(elf
,
123 strs
, scn
, shdr
, data
, addr
, search_info_p
);
132 } /* end _tnfctl_traverse_object */
136 * _tnfctl_traverse_rela() - this function traverses a .rela section calling the
137 * supplied function on each relocation record.
141 _tnfctl_traverse_rela(Elf
* elf
, char *strs
, Elf_Scn
* rel_scn
,
142 GElf_Shdr
* rel_shdr
, Elf_Data
* rel_data
, uintptr_t baseaddr
,
143 tnfctl_elf_search_t
* search_info_p
)
146 GElf_Shdr
*sym_shdr
, sym_shdr_obj
;
148 Elf3264_Sym
*sym_table
;
150 GElf_Shdr
*str_shdr
, str_shdr_obj
;
159 DBG_TNF_PROBE_0(_tnfctl_traverse_rela_1
, "libtnfctl",
162 /* bail if this isn't a rela (or rel) section */
163 if (rel_shdr
->sh_type
== SHT_RELA
) {
165 } else if (rel_shdr
->sh_type
== SHT_REL
) {
168 return (TNFCTL_ERR_NONE
);
170 /* find the symbol table section associated with this rela section */
171 sym_scn
= elf_getscn(elf
, rel_shdr
->sh_link
);
172 if (sym_scn
== NULL
) {
173 DBG((void) fprintf(stderr
,
174 "_tnfctl_traverse_rela:elf_getscn (sym) failed\n"));
175 return (TNFCTL_ERR_INTERNAL
);
177 sym_shdr
= gelf_getshdr(sym_scn
, &sym_shdr_obj
);
178 if (sym_shdr
== NULL
) {
179 DBG((void) fprintf(stderr
,
180 "_tnfctl_traverse_rela:gelf_getshdr (sym) failed\n"));
181 return (TNFCTL_ERR_INTERNAL
);
183 sym_data
= elf_getdata(sym_scn
, NULL
);
184 if (sym_data
== NULL
) {
185 DBG((void) fprintf(stderr
,
186 "_tnfctl_traverse_rela:elf_getdata (sym) failed\n"));
187 return (TNFCTL_ERR_INTERNAL
);
189 sym_table
= (Elf3264_Sym
*) sym_data
->d_buf
;
191 /* find the string table associated with the symbol table */
192 str_scn
= elf_getscn(elf
, sym_shdr
->sh_link
);
193 if (str_scn
== NULL
) {
194 DBG((void) fprintf(stderr
,
195 "_tnfctl_traverse_rela:elf_getscn (str) failed\n"));
196 return (TNFCTL_ERR_INTERNAL
);
198 str_shdr
= gelf_getshdr(str_scn
, &str_shdr_obj
);
199 if (str_shdr
== NULL
) {
200 DBG((void) fprintf(stderr
,
201 "_tnfctl_traverse_rela:gelf_getshdr (str) failed\n"));
202 return (TNFCTL_ERR_INTERNAL
);
204 str_data
= elf_getdata(str_scn
, NULL
);
205 if (str_data
== NULL
) {
206 DBG((void) fprintf(stderr
,
207 "_tnfctl_traverse_rela: elf_getdata (str) failed\n"));
208 return (TNFCTL_ERR_INTERNAL
);
210 str_table
= (char *) str_data
->d_buf
;
212 /* loop over each relocation record */
213 nrels
= rel_shdr
->sh_size
/ rel_shdr
->sh_entsize
;
215 DBG_TNF_PROBE_1(_tnfctl_traverse_rela_2
, "libtnfctl",
217 tnf_long
, relocations_found
, nrels
);
219 ptr
= rel_data
->d_buf
;
220 rela_sz
= (isrela
) ? sizeof (Elf3264_Rela
) : sizeof (Elf3264_Rel
);
221 for (i
= 0; i
< nrels
; i
++, ptr
+= rela_sz
) {
222 Elf3264_Word syminfo
;
227 tnfctl_errcode_t prexstat
;
229 /* decode the r_info field of the relocation record */
231 Elf3264_Rela
*rela_p
;
233 /*LINTED pointer cast may result in improper alignment*/
234 rela_p
= (Elf3264_Rela
*) ptr
;
235 syminfo
= ELF3264_R_SYM(rela_p
->r_info
);
236 offset
= rela_p
->r_offset
;
240 /*LINTED pointer cast may result in improper alignment*/
241 rel_p
= (Elf3264_Rel
*) ptr
;
242 syminfo
= ELF3264_R_SYM(rel_p
->r_info
);
243 offset
= rel_p
->r_offset
;
246 /* find the associated symbol table entry */
249 sym
= sym_table
+ syminfo
;
251 /* find the associated string table entry */
254 name
= str_table
+ sym
->st_name
;
255 addr
= offset
+ baseaddr
;
257 prexstat
= search_info_p
->record_func(name
, addr
, ptr
,
263 return (TNFCTL_ERR_NONE
);
265 } /* end _tnfctl_traverse_rela */
269 * _tnfctl_traverse_dynsym() - this function traverses a dynsym section calling
270 * the supplied function on each symbol.
275 _tnfctl_traverse_dynsym(Elf
* elf
,
281 tnfctl_elf_search_t
* search_info_p
)
286 tnfctl_errcode_t prexstat
;
290 /* bail if this isn't a dynsym section */
291 if (shdr
->sh_type
!= SHT_DYNSYM
)
292 return (TNFCTL_ERR_NONE
);
294 printf("### entering _tnfctl_traverse_dynsym...\n");
297 nsyms
= shdr
->sh_size
/ shdr
->sh_entsize
;
298 strs
= elf_strptr(elf
, shdr
->sh_link
, 0);
300 DBG_TNF_PROBE_1(_tnfctl_traverse_dynsym_1
, "libtnfctl",
302 tnf_long
, symbols_found
, nsyms
);
304 for (i
= 0; i
< nsyms
; i
++) {
305 Elf3264_Sym
*sym
= &syms
[i
];
309 name
= strs
+ sym
->st_name
;
310 addr
= baseaddr
+ sym
->st_value
;
314 printf("_tnfctl_traverse_dynsym: name = %s\n", name
);
316 printf("_tnfctl_traverse_dynsym: name is 0\n");
318 prexstat
= search_info_p
->record_func(name
,
319 addr
, sym
, search_info_p
);
324 printf("### leaving _tnfctl_traverse_dynsym...\n");
328 } /* end _tnfctl_traverse_dynsym */