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