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