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