1 /*
2  * CDDL HEADER START
3  *
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.
8  *
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.
13  *
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]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  *      Copyright (c) 1994, by Sun Microsytems, Inc.
24  */
25 
26 #ifndef _TNFCTL_INT_H
27 #define	_TNFCTL_INT_H
28 
29 /*
30  * Interfaces private to libtnfctl
31  *	layout of tnfctl handle structure
32  *	layout of probe handle structure
33  *	other misc. interfaces used across source files
34  */
35 
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
39 
40 #include "tnfctl.h"
41 #include <sys/types.h>
42 #include <gelf.h>
43 #include <libelf.h>
44 #include "prb_proc.h"
45 #include <thread.h>
46 #include <synch.h>
47 
48 /*
49  * global variables used for INTERNAL_MODE synchronization with
50  * dlopen's and dlclose's on another thread.
51  */
52 extern mutex_t		_tnfctl_lmap_lock;
53 extern boolean_t	_tnfctl_libs_changed;
54 
55 /* Project private interface - function name in target */
56 #define	TRACE_END_FUNC		"tnf_trace_end"
57 
58 /* All tnfctl handles are in one of the following 4 modes */
59 enum proc_mode {
60 	KERNEL_MODE,		/* kernel tracing */
61 	DIRECT_MODE,		/* tracing another process (exec or attach) */
62 	INDIRECT_MODE,		/* client provides /proc functions */
63 	INTERNAL_MODE		/* tracing probes in the same process */
64 };
65 
66 typedef struct prbctlref prbctlref_t;
67 typedef struct objlist objlist_t;
68 
69 /* per probe state - transient - freed on dlclose() */
70 struct prbctlref {
71 	uintptr_t		addr;		/* probe address in target */
72 	objlist_t		*obj;		/* obj that this probe is in */
73 	ulong_t			probe_id;	/* assigned id */
74 	char			*attr_string;
75 	tnf_probe_control_t 	wrkprbctl;	/* probe struct from target */
76 	tnfctl_probe_t		*probe_handle;	/* handle visible to client */
77 };
78 
79 /* per object state */
80 struct objlist {
81 	boolean_t	new_probe;	/* relative to last library change */
82 	boolean_t	new;		/* relative to last sync with linker */
83 	boolean_t	old;		/* relative to last sync with linker */
84 	char *		objname;
85 	uintptr_t	baseaddr;
86 	int		objfd;
87 	uint_t		min_probe_num;	/* first probe id in object */
88 	uint_t		probecnt;	/* number of probes in object */
89 	prbctlref_t	*probes;	/* pointer to an array of probes */
90 	objlist_t	*next;
91 };
92 
93 /* per probe state that is freed only on tnfctl_close() */
94 struct tnfctl_probe_handle {
95 	boolean_t	valid;
96 	prbctlref_t	*probe_p;
97 	void		*client_registered_data;
98 	struct tnfctl_probe_handle *next;
99 };
100 
101 /*
102  * state saved per tnfctl handle
103  */
104 struct tnfctl_handle {
105 	void		*proc_p;	/* proc handle */
106 	int		kfd;		/* kernel handle */
107 	pid_t		targ_pid;	/* pid of target */
108 	enum proc_mode	mode;		/* mode of handle */
109 	/* tracing info */
110 	const char 	*trace_file_name;
111 	int		trace_buf_size;
112 	int		trace_min_size;
113 	tnfctl_bufstate_t	trace_buf_state;
114 	boolean_t	trace_state;
115 	boolean_t	kpidfilter_state;
116 	boolean_t	called_exit;
117 	/* addresses of functions in target */
118 	uintptr_t	testfunc;
119 	uintptr_t	allocfunc;
120 	uintptr_t	commitfunc;
121 	uintptr_t	endfunc;
122 	uintptr_t	rollbackfunc;
123 	uintptr_t	probelist_head;
124 	uintptr_t	probelist_valid;
125 	uintptr_t	trace_error;
126 	uintptr_t	memseg_p;
127 	uintptr_t	nonthread_test;
128 	uintptr_t	thread_test;
129 	uintptr_t	thread_sync;
130 	boolean_t	mt_target;
131 	uint_t		num_probes;	/* number of probes in target */
132 	tnfctl_probe_t	*probe_handle_list_head;
133 	/* object info */
134 	boolean_t	in_objlist;	/* _tnfctl_lmap_lock reentrancy check */
135 	objlist_t	*objlist;
136 	/* combination info */
137 	void		*buildroot;	/* root of built combinations */
138 	void		*decoderoot;	/* root of decoded combinations */
139 	/* per probe create/destroy functions */
140 	void *(*create_func)(tnfctl_handle_t *, tnfctl_probe_t *);
141 	void (*destroy_func)(void *);
142 	/* functions to inspect target process */
143 	int (*p_read)(void *prochandle, uintptr_t addr, void *buf, size_t size);
144 	int (*p_write)(void *prochandle, uintptr_t addr,
145 			void *buf, size_t size);
146 	int (*p_obj_iter)(void *prochandle, tnfctl_ind_obj_f *func,
147 						void *client_data);
148 	pid_t (*p_getpid)(void *prochandle);
149 };
150 
151 typedef enum comb_op {
152 	PRB_COMB_CHAIN = 0,	/* call the down, then the next */
153 	PRB_COMB_COUNT = 1	/* how many? */
154 } comb_op_t;
155 
156 enum event_op_t {
157 	EVT_NONE,
158 	EVT_OPEN,
159 	EVT_CLOSE
160 };
161 
162 
163 /*
164  * interfaces to search for symbols or to search for relocations
165  * in an elf file
166  */
167 typedef struct tnfctl_elf_search tnfctl_elf_search_t;
168 
169 /* prototype for callback for traversing an elf section */
170 typedef tnfctl_errcode_t
171 (*tnfctl_traverse_section_func_t) (Elf * elf, char *strs, Elf_Scn * scn,
172 	GElf_Shdr * shdr, Elf_Data * data, uintptr_t baseaddr,
173 	tnfctl_elf_search_t * search_info);
174 
175 /* prototype for callback for traversing records in an elf section */
176 typedef tnfctl_errcode_t
177 (*tnfctl_record_func_t) (char *name, uintptr_t addr, void *entry,
178 	tnfctl_elf_search_t * search_info);
179 
180 struct tnfctl_elf_search {
181 	tnfctl_traverse_section_func_t	section_func;
182 	void				*section_data;
183 	tnfctl_record_func_t		record_func;
184 	void				*record_data;
185 };
186 
187 /* traverse all the sections in an object */
188 tnfctl_errcode_t _tnfctl_traverse_object(int objfd, uintptr_t addr,
189 			tnfctl_elf_search_t *search_info_p);
190 /* search a .rela section */
191 tnfctl_errcode_t _tnfctl_traverse_rela(Elf * elf, char *strs, Elf_Scn * rel_scn,
192 	GElf_Shdr * rel_shdr, Elf_Data * rel_data, uintptr_t baseaddr,
193 	tnfctl_elf_search_t * search_info_p);
194 /* search a .dynsym section */
195 tnfctl_errcode_t _tnfctl_traverse_dynsym(Elf * elf, char *elfstrs,
196 	Elf_Scn * scn, GElf_Shdr * shdr, Elf_Data * data, uintptr_t baseaddr,
197 	tnfctl_elf_search_t * search_info_p);
198 
199 /* prototype of callback for internal probe traversal function */
200 typedef tnfctl_errcode_t
201 (*_tnfctl_traverse_probe_func_t)(tnfctl_handle_t *, prbctlref_t *, void *);
202 
203 /* sync up list of objects with that of the linker */
204 tnfctl_errcode_t _tnfctl_lmap_update(tnfctl_handle_t *hndl, boolean_t *lmap_ok,
205 					enum event_op_t *evt);
206 
207 /* sync up list of objects and probes */
208 tnfctl_errcode_t _tnfctl_refresh_process(tnfctl_handle_t *, boolean_t *,
209 				enum event_op_t *);
210 
211 tnfctl_errcode_t _tnfctl_set_state(tnfctl_handle_t *hndl);
212 tnfctl_errcode_t _tnfctl_create_tracefile(tnfctl_handle_t *hndl,
213 		const char *trace_file_name, uint_t trace_file_size);
214 
215 /* probe interfaces */
216 tnfctl_errcode_t _tnfctl_find_all_probes(tnfctl_handle_t *hndl);
217 tnfctl_errcode_t _tnfctl_probes_traverse(tnfctl_handle_t *hndl,
218 	_tnfctl_traverse_probe_func_t func_p, void *calldata_p);
219 tnfctl_errcode_t _tnfctl_flush_a_probe(tnfctl_handle_t *hndl,
220 	prbctlref_t *ref_p, size_t offset, size_t size);
221 
222 /* combination interfaces */
223 tnfctl_errcode_t _tnfctl_comb_build(tnfctl_handle_t *hndl, comb_op_t op,
224 	uintptr_t down, uintptr_t next, uintptr_t *comb_p);
225 tnfctl_errcode_t _tnfctl_comb_decode(tnfctl_handle_t *hndl, uintptr_t addr,
226 	char ***func_names, uintptr_t **func_addrs);
227 
228 /* allocate memory in target process */
229 tnfctl_errcode_t _tnfctl_targmem_alloc(tnfctl_handle_t *hndl, size_t size,
230 			uintptr_t *addr_p);
231 
232 /* inprocess "plug ins" for functions in tnfctl_handle_t structure */
233 int _tnfctl_read_targ(void *proc_p, uintptr_t addr, void *buf, size_t size);
234 int _tnfctl_write_targ(void *proc_p, uintptr_t addr, void *buf, size_t size);
235 int _tnfctl_loadobj_iter(void *proc_p, tnfctl_ind_obj_f *func,
236 			void *client_data);
237 pid_t _tnfctl_pid_get(void *proc_p);
238 
239 /* read a string from the target process */
240 tnfctl_errcode_t _tnfctl_readstr_targ(tnfctl_handle_t *hndl, uintptr_t addr,
241 				char **outstr_pp);
242 
243 /* symbol searching interfaces */
244 tnfctl_errcode_t _tnfctl_sym_find_in_obj(int objfd, uintptr_t baseaddr,
245 		const char *symname, uintptr_t *symaddr);
246 tnfctl_errcode_t _tnfctl_sym_obj_find(tnfctl_handle_t *hndl,
247 	const char *lib_base_name, const char *symname, uintptr_t *symaddr);
248 tnfctl_errcode_t _tnfctl_sym_find(tnfctl_handle_t *hndl, const char *symname,
249 			uintptr_t *symaddr);
250 tnfctl_errcode_t _tnfctl_sym_findname(tnfctl_handle_t *hndl, uintptr_t symaddr,
251 	char **symname);
252 tnfctl_errcode_t _tnfctl_elf_dbgent(tnfctl_handle_t *hndl,
253 				uintptr_t * entaddr_p);
254 
255 /* free objs and probes */
256 void _tnfctl_free_objs_and_probes(tnfctl_handle_t *);
257 
258 /* locking interfaces */
259 tnfctl_errcode_t _tnfctl_lock_libs(tnfctl_handle_t *hndl,
260 	boolean_t *release_lock);
261 void _tnfctl_unlock_libs(tnfctl_handle_t *hndl, boolean_t release_lock);
262 tnfctl_errcode_t _tnfctl_sync_lib_list(tnfctl_handle_t *hndl);
263 
264 /*
265  * BugID 1253419
266  * The flags that indicate if in/external trace control is active.
267  * Used to prevent simultaneous internal and external probe control.
268  * For external control keep pid of traced process to handle case
269  * where process forks. (child is not under external control)
270  */
271 #define	TNFCTL_INTERNAL_TRACEFLAG	"_tnfctl_internal_tracing_flag"
272 #define	TNFCTL_EXTERNAL_TRACEDPID	"_tnfctl_externally_traced_pid"
273 extern boolean_t _tnfctl_internal_tracing_flag;
274 extern pid_t _tnfctl_externally_traced_pid;
275 tnfctl_errcode_t _tnfctl_internal_getlock(void);
276 tnfctl_errcode_t _tnfctl_external_getlock(tnfctl_handle_t *hndl);
277 tnfctl_errcode_t _tnfctl_internal_releaselock(void);
278 tnfctl_errcode_t _tnfctl_external_releaselock(tnfctl_handle_t *hndl);
279 
280 /* error mapping functions */
281 tnfctl_errcode_t _tnfctl_map_to_errcode(prb_status_t prbstat);
282 tnfctl_errcode_t tnfctl_status_map(int);
283 
284 
285 /*
286  * LOCK is the macro to lock down the library list so that a dlopen or
287  * dlclose by another thread will block waiting for the lock to be released.
288  *
289  * LOCK_SYNC does the same as LOCK + it syncs up libtnfctl's cache of
290  * libraries in target process with that of what the run time linker maintains.
291  *
292  * These macros do conditional locking because they are needed only by
293  * INTERNAL_MODE clients.  There are 2 versions of these macros so that
294  * lock_lint won't have to see the conditional locking.
295  * CAUTION: Be aware that these macros have a return() embedded in them.
296  */
297 #define	LOCK(hndl, stat, release)					\
298 	if (hndl->mode == INTERNAL_MODE) {				\
299 		stat = _tnfctl_lock_libs(hndl, &release);		\
300 		if (stat)						\
301 			return (stat);					\
302 	}								\
303 	else
304 
305 #define	LOCK_SYNC(hndl, stat, release)					\
306 	if (hndl->mode == INTERNAL_MODE) {				\
307 		stat = _tnfctl_lock_libs(hndl, &release);		\
308 		if (stat)						\
309 			return (stat);					\
310 		stat = _tnfctl_sync_lib_list(hndl);			\
311 		if (stat) {						\
312 			_tnfctl_unlock_libs(hndl, release);		\
313 			return (stat);					\
314 		}							\
315 	}								\
316 	else
317 
318 #define	UNLOCK(hndl, release)						\
319 	if (hndl->mode == INTERNAL_MODE)				\
320 		_tnfctl_unlock_libs(hndl, release_lock);		\
321 	else
322 
323 #ifdef __cplusplus
324 }
325 #endif
326 
327 #endif /* _TNFCTL_INT_H */
328