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