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 * Interfaces for searching for elf specific information
37 #include <sys/procfs.h>
39 #include "tnfctl_int.h"
47 static tnfctl_errcode_t
dynsec_num(tnfctl_handle_t
*hndl
, uintptr_t baseaddr
,
48 int objfd
, int *num_dyn
);
49 static tnfctl_errcode_t
elf_dynmatch(Elf
*elf
, char *strs
, Elf_Scn
*dyn_scn
,
50 GElf_Shdr
*dyn_shdr
, Elf_Data
*dyn_data
,
51 uintptr_t baseaddr
, tnfctl_elf_search_t
* search_info_p
);
52 static tnfctl_errcode_t
dyn_findtag(
53 Elf3264_Dyn
*start
, /* start of dynam table read in */
54 Elf3264_Sword tag
, /* tag to search for */
55 uintptr_t dynam_addr
, /* address of _DYNAMIC in target */
56 int limit
, /* number of entries in table */
57 uintptr_t *dentry_address
); /* return value */
60 /* ---------------------------------------------------------------- */
61 /* ----------------------- Public Functions ----------------------- */
62 /* ---------------------------------------------------------------- */
65 * _tnfctl_elf_dbgent() - this function finds the address of the
66 * debug struct (DT_DEBUG) in the target process. _DYNAMIC is a symbol
67 * present in every object. The one in the main executable references
68 * an array that is tagged with the kind of each member. We search
69 * for the tag of DT_DEBUG which is where the run time linker maintains
70 * a structure that references the shared object linked list.
72 * A side effect of searching for DT_DEBUG ensures that the executable is
73 * a dynamic executable - tracing only works on dynamic executables because
74 * static executables don't have relocation tables.
77 _tnfctl_elf_dbgent(tnfctl_handle_t
*hndl
, uintptr_t * entaddr_p
)
79 tnfctl_errcode_t prexstat
= TNFCTL_ERR_NONE
;
80 prb_status_t prbstat
= PRB_STATUS_OK
;
83 int num_dynentries
= 0;
84 uintptr_t dynamic_addr
;
86 uintptr_t dentry_addr
;
87 Elf3264_Dyn
*dynam_tab
= NULL
;
92 prbstat
= prb_mainobj_get(hndl
->proc_p
, &objfd
, &baseaddr
);
94 return (_tnfctl_map_to_errcode(prbstat
));
96 /* find the address of the symbol _DYNAMIC */
97 prexstat
= _tnfctl_sym_find_in_obj(objfd
, baseaddr
, "_DYNAMIC",
100 prexstat
= TNFCTL_ERR_NOTDYNAMIC
;
104 /* find the number of entries in the .dynamic section */
105 prexstat
= dynsec_num(hndl
, baseaddr
, objfd
, &num_dynentries
);
109 DBG_TNF_PROBE_2(_tnfctl_elf_dbgent_1
, "libtnfctl", "sunw%verbosity 2",
110 tnf_long
, num_of_dynentries
, num_dynentries
,
111 tnf_opaque
, DYNAMIC_address
, dynamic_addr
);
113 /* read in the dynamic table from the image of the process */
114 dynam_tab_size
= num_dynentries
* sizeof (Elf3264_Dyn
);
115 dynam_tab
= malloc(dynam_tab_size
);
118 return (TNFCTL_ERR_ALLOCFAIL
);
120 miscstat
= hndl
->p_read(hndl
->proc_p
, dynamic_addr
, dynam_tab
,
123 prexstat
= TNFCTL_ERR_INTERNAL
;
127 prexstat
= dyn_findtag(dynam_tab
, DT_DEBUG
, dynamic_addr
,
128 num_dynentries
, &dentry_addr
);
132 *entaddr_p
= dentry_addr
;
143 /* ---------------------------------------------------------------- */
144 /* ----------------------- Private Functions ---------------------- */
145 /* ---------------------------------------------------------------- */
148 * dyn_findtag() - searches tags in _DYNAMIC table
150 static tnfctl_errcode_t
151 dyn_findtag(Elf3264_Dyn
* start
, /* start of dynam table read in */
152 Elf3264_Sword tag
, /* tag to search for */
153 uintptr_t dynam_addr
, /* base address of _DYNAMIC in target */
154 int limit
, /* number of entries in table */
155 uintptr_t * dentry_address
)
159 for (dp
= start
; dp
->d_tag
!= DT_NULL
; dp
++) {
161 DBG_TNF_PROBE_1(dyn_findtag_1
, "libtnfctl",
162 "sunw%verbosity 3; sunw%debug 'in loop'",
163 tnf_long
, tag
, dp
->d_tag
);
165 if (dp
->d_tag
== tag
) {
166 *dentry_address
= dynam_addr
+
167 (dp
- start
) * sizeof (Elf3264_Dyn
);
168 return (TNFCTL_ERR_NONE
);
171 DBG((void) fprintf(stderr
,
172 "dyn_findtag: exceeded limit of table\n"));
173 return (TNFCTL_ERR_INTERNAL
);
177 DBG((void) fprintf(stderr
,
178 "dyn_findtag: couldn't find tag, last tag=%d\n",
180 return (TNFCTL_ERR_INTERNAL
);
185 * dynsec_num() - find the number of entries in the .dynamic section
188 static tnfctl_errcode_t
189 dynsec_num(tnfctl_handle_t
*hndl
, uintptr_t baseaddr
,
190 int objfd
, int *num_dyn
)
193 tnfctl_errcode_t prexstat
;
194 tnfctl_elf_search_t search_info
;
196 DBG_TNF_PROBE_0(dynsec_num_1
, "libtnfctl",
198 "sunw%debug 'counting number of entries in .dynamic section'");
200 search_info
.section_func
= elf_dynmatch
;
201 search_info
.section_data
= &num_ent
;
203 prexstat
= _tnfctl_traverse_object(objfd
, baseaddr
, &search_info
);
208 return (TNFCTL_ERR_NOTDYNAMIC
);
212 return (TNFCTL_ERR_NONE
);
217 * elf_dynmatch() - this function searches for the .dynamic section and
218 * returns the number of entries in it.
221 static tnfctl_errcode_t
222 elf_dynmatch(Elf
* elf
,
225 GElf_Shdr
* dyn_shdr
,
228 tnfctl_elf_search_t
*search_info_p
)
231 int *ret
= (int *) search_info_p
->section_data
;
233 /* bail if this isn't a .dynamic section */
234 scn_name
= strs
+ dyn_shdr
->sh_name
;
235 if (strcmp(scn_name
, ".dynamic") != 0)
236 return (TNFCTL_ERR_NONE
);
238 if (dyn_shdr
->sh_entsize
== 0) { /* no dynamic section */
241 *ret
= (int) (dyn_shdr
->sh_size
/ dyn_shdr
->sh_entsize
);
243 return (TNFCTL_ERR_NONE
);