1/* 2 * Copyright (c) 2004 David Xu <davidxu@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h>
| 1/* 2 * Copyright (c) 2004 David Xu <davidxu@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h>
|
28__FBSDID("$FreeBSD: head/lib/libthread_db/libpthread_db.c 181059 2008-07-31 16:26:58Z marcel $");
| 28__FBSDID("$FreeBSD: head/lib/libthread_db/libpthread_db.c 181341 2008-08-06 03:14:18Z marcel $");
|
29 30#include <stddef.h> 31#include <stdlib.h> 32#include <string.h> 33#include <unistd.h> 34#include <pthread.h> 35#include <sys/types.h> 36#include <sys/linker_set.h> 37#include <sys/ptrace.h> 38#include <proc_service.h> 39#include <thread_db.h> 40 41#include "libpthread_db.h" 42#include "kse.h" 43 44#define P2T(c) ps2td(c) 45 46static void pt_unmap_lwp(const td_thragent_t *ta, lwpid_t lwp); 47static int pt_validate(const td_thrhandle_t *th); 48 49static int 50ps2td(int c) 51{ 52 switch (c) { 53 case PS_OK: 54 return TD_OK; 55 case PS_ERR: 56 return TD_ERR; 57 case PS_BADPID: 58 return TD_BADPH; 59 case PS_BADLID: 60 return TD_NOLWP; 61 case PS_BADADDR: 62 return TD_ERR; 63 case PS_NOSYM: 64 return TD_NOLIBTHREAD; 65 case PS_NOFREGS: 66 return TD_NOFPREGS; 67 default: 68 return TD_ERR; 69 } 70} 71 72static long 73pt_map_thread(const td_thragent_t *const_ta, psaddr_t pt, enum pt_type type) 74{ 75 td_thragent_t *ta = __DECONST(td_thragent_t *, const_ta); 76 struct pt_map *new; 77 int i, first = -1; 78 79 /* leave zero out */ 80 for (i = 1; i < ta->map_len; ++i) { 81 if (ta->map[i].type == PT_NONE) { 82 if (first == -1) 83 first = i; 84 } else if (ta->map[i].type == type && ta->map[i].thr == pt) { 85 return (i); 86 } 87 } 88 89 if (first == -1) { 90 if (ta->map_len == 0) { 91 ta->map = calloc(20, sizeof(struct pt_map)); 92 if (ta->map == NULL) 93 return (-1); 94 ta->map_len = 20; 95 first = 1; 96 } else { 97 new = realloc(ta->map, 98 sizeof(struct pt_map) * ta->map_len * 2); 99 if (new == NULL) 100 return (-1); 101 memset(new + ta->map_len, '\0', sizeof(struct pt_map) * 102 ta->map_len); 103 first = ta->map_len; 104 ta->map = new; 105 ta->map_len *= 2; 106 } 107 } 108 109 ta->map[first].type = type; 110 ta->map[first].thr = pt; 111 return (first); 112} 113 114static td_err_e 115pt_init(void) 116{ 117 pt_md_init(); 118 return (0); 119} 120 121static td_err_e 122pt_ta_new(struct ps_prochandle *ph, td_thragent_t **pta) 123{ 124#define LOOKUP_SYM(proc, sym, addr) \ 125 ret = ps_pglobal_lookup(proc, NULL, sym, addr); \ 126 if (ret != 0) { \ 127 TDBG("can not find symbol: %s\n", sym); \ 128 ret = TD_NOLIBTHREAD; \ 129 goto error; \ 130 } 131 132#define LOOKUP_VAL(proc, sym, val) \ 133 ret = ps_pglobal_lookup(proc, NULL, sym, &vaddr);\ 134 if (ret != 0) { \ 135 TDBG("can not find symbol: %s\n", sym); \ 136 ret = TD_NOLIBTHREAD; \ 137 goto error; \ 138 } \ 139 ret = ps_pread(proc, vaddr, val, sizeof(int)); \ 140 if (ret != 0) { \ 141 TDBG("can not read value of %s\n", sym);\ 142 ret = TD_NOLIBTHREAD; \ 143 goto error; \ 144 } 145 146 td_thragent_t *ta; 147 psaddr_t vaddr; 148 int dbg; 149 int ret; 150 151 TDBG_FUNC(); 152 153 ta = malloc(sizeof(td_thragent_t)); 154 if (ta == NULL) 155 return (TD_MALLOC); 156 157 ta->ph = ph; 158 ta->thread_activated = 0; 159 ta->map = NULL; 160 ta->map_len = 0; 161 162 LOOKUP_SYM(ph, "_libkse_debug", &ta->libkse_debug_addr); 163 LOOKUP_SYM(ph, "_thread_list", &ta->thread_list_addr); 164 LOOKUP_SYM(ph, "_thread_activated", &ta->thread_activated_addr); 165 LOOKUP_SYM(ph, "_thread_active_threads",&ta->thread_active_threads_addr); 166 LOOKUP_SYM(ph, "_thread_keytable", &ta->thread_keytable_addr); 167 LOOKUP_VAL(ph, "_thread_off_dtv", &ta->thread_off_dtv); 168 LOOKUP_VAL(ph, "_thread_off_kse_locklevel", &ta->thread_off_kse_locklevel); 169 LOOKUP_VAL(ph, "_thread_off_kse", &ta->thread_off_kse); 170 LOOKUP_VAL(ph, "_thread_off_tlsindex", &ta->thread_off_tlsindex); 171 LOOKUP_VAL(ph, "_thread_off_attr_flags", &ta->thread_off_attr_flags); 172 LOOKUP_VAL(ph, "_thread_size_key", &ta->thread_size_key); 173 LOOKUP_VAL(ph, "_thread_off_tcb", &ta->thread_off_tcb); 174 LOOKUP_VAL(ph, "_thread_off_linkmap", &ta->thread_off_linkmap); 175 LOOKUP_VAL(ph, "_thread_off_tmbx", &ta->thread_off_tmbx); 176 LOOKUP_VAL(ph, "_thread_off_thr_locklevel", &ta->thread_off_thr_locklevel); 177 LOOKUP_VAL(ph, "_thread_off_next", &ta->thread_off_next); 178 LOOKUP_VAL(ph, "_thread_off_state", &ta->thread_off_state); 179 LOOKUP_VAL(ph, "_thread_max_keys", &ta->thread_max_keys); 180 LOOKUP_VAL(ph, "_thread_off_key_allocated", &ta->thread_off_key_allocated); 181 LOOKUP_VAL(ph, "_thread_off_key_destructor", &ta->thread_off_key_destructor); 182 LOOKUP_VAL(ph, "_thread_state_running", &ta->thread_state_running); 183 LOOKUP_VAL(ph, "_thread_state_zoombie", &ta->thread_state_zoombie); 184 LOOKUP_VAL(ph, "_thread_off_sigmask", &ta->thread_off_sigmask); 185 LOOKUP_VAL(ph, "_thread_off_sigpend", &ta->thread_off_sigpend); 186 dbg = getpid(); 187 /* 188 * If this fails it probably means we're debugging a core file and 189 * can't write to it. 190 */ 191 ps_pwrite(ph, ta->libkse_debug_addr, &dbg, sizeof(int)); 192 *pta = ta; 193 return (0); 194 195error: 196 free(ta); 197 return (ret); 198} 199 200static td_err_e 201pt_ta_delete(td_thragent_t *ta) 202{ 203 int dbg; 204 205 TDBG_FUNC(); 206 207 dbg = 0; 208 /* 209 * Error returns from this write are not really a problem; 210 * the process doesn't exist any more. 211 */ 212 ps_pwrite(ta->ph, ta->libkse_debug_addr, &dbg, sizeof(int)); 213 if (ta->map) 214 free(ta->map); 215 free(ta); 216 return (TD_OK); 217} 218 219static td_err_e 220pt_ta_map_id2thr(const td_thragent_t *ta, thread_t id, td_thrhandle_t *th) 221{ 222 prgregset_t gregs; 223 TAILQ_HEAD(, pthread) thread_list; 224 psaddr_t pt, tcb_addr; 225 lwpid_t lwp; 226 int ret; 227 228 TDBG_FUNC(); 229 230 if (id < 0 || id >= ta->map_len || ta->map[id].type == PT_NONE) 231 return (TD_NOTHR); 232 ret = ps_pread(ta->ph, ta->thread_list_addr, &thread_list, 233 sizeof(thread_list)); 234 if (ret != 0) 235 return (P2T(ret)); 236 pt = (psaddr_t)thread_list.tqh_first; 237 if (ta->map[id].type == PT_LWP) { 238 /* 239 * if we are referencing a lwp, make sure it was not already 240 * mapped to user thread. 241 */ 242 while (pt != 0) { 243 ret = ps_pread(ta->ph, pt + ta->thread_off_tcb, 244 &tcb_addr, sizeof(tcb_addr)); 245 if (ret != 0) 246 return (P2T(ret)); 247 ret = ps_pread(ta->ph, 248 tcb_addr + ta->thread_off_tmbx + 249 offsetof(struct kse_thr_mailbox, tm_lwp), 250 &lwp, sizeof(lwp)); 251 if (ret != 0) 252 return (P2T(ret)); 253 /* 254 * If the lwp was already mapped to userland thread, 255 * we shouldn't reference it directly in future. 256 */ 257 if (lwp == ta->map[id].lwp) { 258 ta->map[id].type = PT_NONE; 259 return (TD_NOTHR); 260 } 261 /* get next thread */ 262 ret = ps_pread(ta->ph, 263 pt + ta->thread_off_next, 264 &pt, sizeof(pt)); 265 if (ret != 0) 266 return (P2T(ret)); 267 } 268 /* check lwp */ 269 ret = ps_lgetregs(ta->ph, ta->map[id].lwp, gregs); 270 if (ret != PS_OK) { 271 /* no longer exists */ 272 ta->map[id].type = PT_NONE; 273 return (TD_NOTHR); 274 } 275 } else { 276 while (pt != 0 && ta->map[id].thr != pt) { 277 ret = ps_pread(ta->ph, 278 pt + ta->thread_off_tcb, 279 &tcb_addr, sizeof(tcb_addr)); 280 if (ret != 0) 281 return (P2T(ret)); 282 /* get next thread */ 283 ret = ps_pread(ta->ph, 284 pt + ta->thread_off_next, 285 &pt, sizeof(pt)); 286 if (ret != 0) 287 return (P2T(ret)); 288 } 289 290 if (pt == 0) { 291 /* no longer exists */ 292 ta->map[id].type = PT_NONE; 293 return (TD_NOTHR); 294 } 295 } 296 th->th_ta = ta; 297 th->th_tid = id; 298 th->th_thread = pt; 299 return (TD_OK); 300} 301 302static td_err_e 303pt_ta_map_lwp2thr(const td_thragent_t *ta, lwpid_t lwp, td_thrhandle_t *th) 304{ 305 TAILQ_HEAD(, pthread) thread_list; 306 psaddr_t pt, ptr; 307 lwpid_t tmp_lwp; 308 int ret; 309 310 TDBG_FUNC(); 311 312 ret = ps_pread(ta->ph, ta->thread_list_addr, &thread_list, 313 sizeof(thread_list)); 314 if (ret != 0) 315 return (P2T(ret)); 316 pt = (psaddr_t)thread_list.tqh_first; 317 while (pt != 0) { 318 ret = ps_pread(ta->ph, pt + ta->thread_off_tcb, 319 &ptr, sizeof(ptr)); 320 if (ret != 0) 321 return (P2T(ret)); 322 ptr += ta->thread_off_tmbx + 323 offsetof(struct kse_thr_mailbox, tm_lwp); 324 ret = ps_pread(ta->ph, ptr, &tmp_lwp, sizeof(lwpid_t)); 325 if (ret != 0) 326 return (P2T(ret)); 327 if (tmp_lwp == lwp) { 328 th->th_ta = ta; 329 th->th_tid = pt_map_thread(ta, pt, PT_USER); 330 if (th->th_tid == -1) 331 return (TD_MALLOC); 332 pt_unmap_lwp(ta, lwp); 333 th->th_thread = pt; 334 return (TD_OK); 335 } 336 337 /* get next thread */ 338 ret = ps_pread(ta->ph, 339 pt + ta->thread_off_next, 340 &pt, sizeof(pt)); 341 if (ret != 0) 342 return (P2T(ret)); 343 } 344 345 return (TD_NOTHR); 346} 347 348static td_err_e
| 29 30#include <stddef.h> 31#include <stdlib.h> 32#include <string.h> 33#include <unistd.h> 34#include <pthread.h> 35#include <sys/types.h> 36#include <sys/linker_set.h> 37#include <sys/ptrace.h> 38#include <proc_service.h> 39#include <thread_db.h> 40 41#include "libpthread_db.h" 42#include "kse.h" 43 44#define P2T(c) ps2td(c) 45 46static void pt_unmap_lwp(const td_thragent_t *ta, lwpid_t lwp); 47static int pt_validate(const td_thrhandle_t *th); 48 49static int 50ps2td(int c) 51{ 52 switch (c) { 53 case PS_OK: 54 return TD_OK; 55 case PS_ERR: 56 return TD_ERR; 57 case PS_BADPID: 58 return TD_BADPH; 59 case PS_BADLID: 60 return TD_NOLWP; 61 case PS_BADADDR: 62 return TD_ERR; 63 case PS_NOSYM: 64 return TD_NOLIBTHREAD; 65 case PS_NOFREGS: 66 return TD_NOFPREGS; 67 default: 68 return TD_ERR; 69 } 70} 71 72static long 73pt_map_thread(const td_thragent_t *const_ta, psaddr_t pt, enum pt_type type) 74{ 75 td_thragent_t *ta = __DECONST(td_thragent_t *, const_ta); 76 struct pt_map *new; 77 int i, first = -1; 78 79 /* leave zero out */ 80 for (i = 1; i < ta->map_len; ++i) { 81 if (ta->map[i].type == PT_NONE) { 82 if (first == -1) 83 first = i; 84 } else if (ta->map[i].type == type && ta->map[i].thr == pt) { 85 return (i); 86 } 87 } 88 89 if (first == -1) { 90 if (ta->map_len == 0) { 91 ta->map = calloc(20, sizeof(struct pt_map)); 92 if (ta->map == NULL) 93 return (-1); 94 ta->map_len = 20; 95 first = 1; 96 } else { 97 new = realloc(ta->map, 98 sizeof(struct pt_map) * ta->map_len * 2); 99 if (new == NULL) 100 return (-1); 101 memset(new + ta->map_len, '\0', sizeof(struct pt_map) * 102 ta->map_len); 103 first = ta->map_len; 104 ta->map = new; 105 ta->map_len *= 2; 106 } 107 } 108 109 ta->map[first].type = type; 110 ta->map[first].thr = pt; 111 return (first); 112} 113 114static td_err_e 115pt_init(void) 116{ 117 pt_md_init(); 118 return (0); 119} 120 121static td_err_e 122pt_ta_new(struct ps_prochandle *ph, td_thragent_t **pta) 123{ 124#define LOOKUP_SYM(proc, sym, addr) \ 125 ret = ps_pglobal_lookup(proc, NULL, sym, addr); \ 126 if (ret != 0) { \ 127 TDBG("can not find symbol: %s\n", sym); \ 128 ret = TD_NOLIBTHREAD; \ 129 goto error; \ 130 } 131 132#define LOOKUP_VAL(proc, sym, val) \ 133 ret = ps_pglobal_lookup(proc, NULL, sym, &vaddr);\ 134 if (ret != 0) { \ 135 TDBG("can not find symbol: %s\n", sym); \ 136 ret = TD_NOLIBTHREAD; \ 137 goto error; \ 138 } \ 139 ret = ps_pread(proc, vaddr, val, sizeof(int)); \ 140 if (ret != 0) { \ 141 TDBG("can not read value of %s\n", sym);\ 142 ret = TD_NOLIBTHREAD; \ 143 goto error; \ 144 } 145 146 td_thragent_t *ta; 147 psaddr_t vaddr; 148 int dbg; 149 int ret; 150 151 TDBG_FUNC(); 152 153 ta = malloc(sizeof(td_thragent_t)); 154 if (ta == NULL) 155 return (TD_MALLOC); 156 157 ta->ph = ph; 158 ta->thread_activated = 0; 159 ta->map = NULL; 160 ta->map_len = 0; 161 162 LOOKUP_SYM(ph, "_libkse_debug", &ta->libkse_debug_addr); 163 LOOKUP_SYM(ph, "_thread_list", &ta->thread_list_addr); 164 LOOKUP_SYM(ph, "_thread_activated", &ta->thread_activated_addr); 165 LOOKUP_SYM(ph, "_thread_active_threads",&ta->thread_active_threads_addr); 166 LOOKUP_SYM(ph, "_thread_keytable", &ta->thread_keytable_addr); 167 LOOKUP_VAL(ph, "_thread_off_dtv", &ta->thread_off_dtv); 168 LOOKUP_VAL(ph, "_thread_off_kse_locklevel", &ta->thread_off_kse_locklevel); 169 LOOKUP_VAL(ph, "_thread_off_kse", &ta->thread_off_kse); 170 LOOKUP_VAL(ph, "_thread_off_tlsindex", &ta->thread_off_tlsindex); 171 LOOKUP_VAL(ph, "_thread_off_attr_flags", &ta->thread_off_attr_flags); 172 LOOKUP_VAL(ph, "_thread_size_key", &ta->thread_size_key); 173 LOOKUP_VAL(ph, "_thread_off_tcb", &ta->thread_off_tcb); 174 LOOKUP_VAL(ph, "_thread_off_linkmap", &ta->thread_off_linkmap); 175 LOOKUP_VAL(ph, "_thread_off_tmbx", &ta->thread_off_tmbx); 176 LOOKUP_VAL(ph, "_thread_off_thr_locklevel", &ta->thread_off_thr_locklevel); 177 LOOKUP_VAL(ph, "_thread_off_next", &ta->thread_off_next); 178 LOOKUP_VAL(ph, "_thread_off_state", &ta->thread_off_state); 179 LOOKUP_VAL(ph, "_thread_max_keys", &ta->thread_max_keys); 180 LOOKUP_VAL(ph, "_thread_off_key_allocated", &ta->thread_off_key_allocated); 181 LOOKUP_VAL(ph, "_thread_off_key_destructor", &ta->thread_off_key_destructor); 182 LOOKUP_VAL(ph, "_thread_state_running", &ta->thread_state_running); 183 LOOKUP_VAL(ph, "_thread_state_zoombie", &ta->thread_state_zoombie); 184 LOOKUP_VAL(ph, "_thread_off_sigmask", &ta->thread_off_sigmask); 185 LOOKUP_VAL(ph, "_thread_off_sigpend", &ta->thread_off_sigpend); 186 dbg = getpid(); 187 /* 188 * If this fails it probably means we're debugging a core file and 189 * can't write to it. 190 */ 191 ps_pwrite(ph, ta->libkse_debug_addr, &dbg, sizeof(int)); 192 *pta = ta; 193 return (0); 194 195error: 196 free(ta); 197 return (ret); 198} 199 200static td_err_e 201pt_ta_delete(td_thragent_t *ta) 202{ 203 int dbg; 204 205 TDBG_FUNC(); 206 207 dbg = 0; 208 /* 209 * Error returns from this write are not really a problem; 210 * the process doesn't exist any more. 211 */ 212 ps_pwrite(ta->ph, ta->libkse_debug_addr, &dbg, sizeof(int)); 213 if (ta->map) 214 free(ta->map); 215 free(ta); 216 return (TD_OK); 217} 218 219static td_err_e 220pt_ta_map_id2thr(const td_thragent_t *ta, thread_t id, td_thrhandle_t *th) 221{ 222 prgregset_t gregs; 223 TAILQ_HEAD(, pthread) thread_list; 224 psaddr_t pt, tcb_addr; 225 lwpid_t lwp; 226 int ret; 227 228 TDBG_FUNC(); 229 230 if (id < 0 || id >= ta->map_len || ta->map[id].type == PT_NONE) 231 return (TD_NOTHR); 232 ret = ps_pread(ta->ph, ta->thread_list_addr, &thread_list, 233 sizeof(thread_list)); 234 if (ret != 0) 235 return (P2T(ret)); 236 pt = (psaddr_t)thread_list.tqh_first; 237 if (ta->map[id].type == PT_LWP) { 238 /* 239 * if we are referencing a lwp, make sure it was not already 240 * mapped to user thread. 241 */ 242 while (pt != 0) { 243 ret = ps_pread(ta->ph, pt + ta->thread_off_tcb, 244 &tcb_addr, sizeof(tcb_addr)); 245 if (ret != 0) 246 return (P2T(ret)); 247 ret = ps_pread(ta->ph, 248 tcb_addr + ta->thread_off_tmbx + 249 offsetof(struct kse_thr_mailbox, tm_lwp), 250 &lwp, sizeof(lwp)); 251 if (ret != 0) 252 return (P2T(ret)); 253 /* 254 * If the lwp was already mapped to userland thread, 255 * we shouldn't reference it directly in future. 256 */ 257 if (lwp == ta->map[id].lwp) { 258 ta->map[id].type = PT_NONE; 259 return (TD_NOTHR); 260 } 261 /* get next thread */ 262 ret = ps_pread(ta->ph, 263 pt + ta->thread_off_next, 264 &pt, sizeof(pt)); 265 if (ret != 0) 266 return (P2T(ret)); 267 } 268 /* check lwp */ 269 ret = ps_lgetregs(ta->ph, ta->map[id].lwp, gregs); 270 if (ret != PS_OK) { 271 /* no longer exists */ 272 ta->map[id].type = PT_NONE; 273 return (TD_NOTHR); 274 } 275 } else { 276 while (pt != 0 && ta->map[id].thr != pt) { 277 ret = ps_pread(ta->ph, 278 pt + ta->thread_off_tcb, 279 &tcb_addr, sizeof(tcb_addr)); 280 if (ret != 0) 281 return (P2T(ret)); 282 /* get next thread */ 283 ret = ps_pread(ta->ph, 284 pt + ta->thread_off_next, 285 &pt, sizeof(pt)); 286 if (ret != 0) 287 return (P2T(ret)); 288 } 289 290 if (pt == 0) { 291 /* no longer exists */ 292 ta->map[id].type = PT_NONE; 293 return (TD_NOTHR); 294 } 295 } 296 th->th_ta = ta; 297 th->th_tid = id; 298 th->th_thread = pt; 299 return (TD_OK); 300} 301 302static td_err_e 303pt_ta_map_lwp2thr(const td_thragent_t *ta, lwpid_t lwp, td_thrhandle_t *th) 304{ 305 TAILQ_HEAD(, pthread) thread_list; 306 psaddr_t pt, ptr; 307 lwpid_t tmp_lwp; 308 int ret; 309 310 TDBG_FUNC(); 311 312 ret = ps_pread(ta->ph, ta->thread_list_addr, &thread_list, 313 sizeof(thread_list)); 314 if (ret != 0) 315 return (P2T(ret)); 316 pt = (psaddr_t)thread_list.tqh_first; 317 while (pt != 0) { 318 ret = ps_pread(ta->ph, pt + ta->thread_off_tcb, 319 &ptr, sizeof(ptr)); 320 if (ret != 0) 321 return (P2T(ret)); 322 ptr += ta->thread_off_tmbx + 323 offsetof(struct kse_thr_mailbox, tm_lwp); 324 ret = ps_pread(ta->ph, ptr, &tmp_lwp, sizeof(lwpid_t)); 325 if (ret != 0) 326 return (P2T(ret)); 327 if (tmp_lwp == lwp) { 328 th->th_ta = ta; 329 th->th_tid = pt_map_thread(ta, pt, PT_USER); 330 if (th->th_tid == -1) 331 return (TD_MALLOC); 332 pt_unmap_lwp(ta, lwp); 333 th->th_thread = pt; 334 return (TD_OK); 335 } 336 337 /* get next thread */ 338 ret = ps_pread(ta->ph, 339 pt + ta->thread_off_next, 340 &pt, sizeof(pt)); 341 if (ret != 0) 342 return (P2T(ret)); 343 } 344 345 return (TD_NOTHR); 346} 347 348static td_err_e
|
349pt_ta_thr_iter(const td_thragent_t *ta, 350 td_thr_iter_f *callback, void *cbdata_p, 351 td_thr_state_e state, int ti_pri, 352 sigset_t *ti_sigmask_p, 353 unsigned int ti_user_flags)
| 349pt_ta_thr_iter(const td_thragent_t *ta, td_thr_iter_f *callback, 350 void *cbdata_p, td_thr_state_e state __unused, int ti_pri __unused, 351 sigset_t *ti_sigmask_p __unused, unsigned int ti_user_flags __unused)
|
354{ 355 TAILQ_HEAD(, pthread) thread_list; 356 td_thrhandle_t th; 357 psaddr_t pt; 358 ps_err_e pserr; 359 int activated; 360 361 TDBG_FUNC(); 362 363 pserr = ps_pread(ta->ph, ta->thread_activated_addr, &activated, 364 sizeof(int)); 365 if (pserr != PS_OK) 366 return (P2T(pserr)); 367 if (!activated) 368 return (TD_OK); 369 370 pserr = ps_pread(ta->ph, ta->thread_list_addr, &thread_list, 371 sizeof(thread_list)); 372 if (pserr != 0) 373 return (P2T(pserr)); 374 pt = (psaddr_t)thread_list.tqh_first; 375 while (pt != 0) { 376 th.th_ta = ta; 377 th.th_tid = pt_map_thread(ta, pt, PT_USER); 378 th.th_thread = pt; 379 /* should we unmap lwp here ? */ 380 if (th.th_tid == -1) 381 return (TD_MALLOC); 382 if ((*callback)(&th, cbdata_p)) 383 return (TD_DBERR); 384 /* get next thread */ 385 pserr = ps_pread(ta->ph, 386 pt + ta->thread_off_next, &pt, 387 sizeof(pt)); 388 if (pserr != PS_OK) 389 return (P2T(pserr)); 390 } 391 return (TD_OK); 392} 393 394static td_err_e 395pt_ta_tsd_iter(const td_thragent_t *ta, td_key_iter_f *ki, void *arg) 396{
| 352{ 353 TAILQ_HEAD(, pthread) thread_list; 354 td_thrhandle_t th; 355 psaddr_t pt; 356 ps_err_e pserr; 357 int activated; 358 359 TDBG_FUNC(); 360 361 pserr = ps_pread(ta->ph, ta->thread_activated_addr, &activated, 362 sizeof(int)); 363 if (pserr != PS_OK) 364 return (P2T(pserr)); 365 if (!activated) 366 return (TD_OK); 367 368 pserr = ps_pread(ta->ph, ta->thread_list_addr, &thread_list, 369 sizeof(thread_list)); 370 if (pserr != 0) 371 return (P2T(pserr)); 372 pt = (psaddr_t)thread_list.tqh_first; 373 while (pt != 0) { 374 th.th_ta = ta; 375 th.th_tid = pt_map_thread(ta, pt, PT_USER); 376 th.th_thread = pt; 377 /* should we unmap lwp here ? */ 378 if (th.th_tid == -1) 379 return (TD_MALLOC); 380 if ((*callback)(&th, cbdata_p)) 381 return (TD_DBERR); 382 /* get next thread */ 383 pserr = ps_pread(ta->ph, 384 pt + ta->thread_off_next, &pt, 385 sizeof(pt)); 386 if (pserr != PS_OK) 387 return (P2T(pserr)); 388 } 389 return (TD_OK); 390} 391 392static td_err_e 393pt_ta_tsd_iter(const td_thragent_t *ta, td_key_iter_f *ki, void *arg) 394{
|
397 char *keytable;
| 395 void *keytable;
|
398 void *destructor; 399 int i, ret, allocated; 400 401 TDBG_FUNC(); 402 403 keytable = malloc(ta->thread_max_keys * ta->thread_size_key); 404 if (keytable == NULL) 405 return (TD_MALLOC); 406 ret = ps_pread(ta->ph, (psaddr_t)ta->thread_keytable_addr, keytable, 407 ta->thread_max_keys * ta->thread_size_key); 408 if (ret != 0) { 409 free(keytable); 410 return (P2T(ret)); 411 } 412 for (i = 0; i < ta->thread_max_keys; i++) {
| 396 void *destructor; 397 int i, ret, allocated; 398 399 TDBG_FUNC(); 400 401 keytable = malloc(ta->thread_max_keys * ta->thread_size_key); 402 if (keytable == NULL) 403 return (TD_MALLOC); 404 ret = ps_pread(ta->ph, (psaddr_t)ta->thread_keytable_addr, keytable, 405 ta->thread_max_keys * ta->thread_size_key); 406 if (ret != 0) { 407 free(keytable); 408 return (P2T(ret)); 409 } 410 for (i = 0; i < ta->thread_max_keys; i++) {
|
413 allocated = *(int *)(keytable + i * ta->thread_size_key + 414 ta->thread_off_key_allocated); 415 destructor = *(void **)(keytable + i * ta->thread_size_key + 416 ta->thread_off_key_destructor);
| 411 allocated = *(int *)(void *)((uintptr_t)keytable + 412 i * ta->thread_size_key + ta->thread_off_key_allocated); 413 destructor = *(void **)(void *)((uintptr_t)keytable + 414 i * ta->thread_size_key + ta->thread_off_key_destructor);
|
417 if (allocated) { 418 ret = (ki)(i, destructor, arg); 419 if (ret != 0) { 420 free(keytable); 421 return (TD_DBERR); 422 } 423 } 424 } 425 free(keytable); 426 return (TD_OK); 427} 428 429static td_err_e
| 415 if (allocated) { 416 ret = (ki)(i, destructor, arg); 417 if (ret != 0) { 418 free(keytable); 419 return (TD_DBERR); 420 } 421 } 422 } 423 free(keytable); 424 return (TD_OK); 425} 426 427static td_err_e
|
430pt_ta_event_addr(const td_thragent_t *ta, td_event_e event, td_notify_t *ptr)
| 428pt_ta_event_addr(const td_thragent_t *ta __unused, td_event_e event __unused, 429 td_notify_t *ptr __unused)
|
431{ 432 TDBG_FUNC(); 433 return (TD_ERR); 434} 435 436static td_err_e
| 430{ 431 TDBG_FUNC(); 432 return (TD_ERR); 433} 434 435static td_err_e
|
437pt_ta_set_event(const td_thragent_t *ta, td_thr_events_t *events)
| 436pt_ta_set_event(const td_thragent_t *ta __unused, 437 td_thr_events_t *events __unused)
|
438{ 439 TDBG_FUNC(); 440 return (0); 441} 442 443static td_err_e
| 438{ 439 TDBG_FUNC(); 440 return (0); 441} 442 443static td_err_e
|
444pt_ta_clear_event(const td_thragent_t *ta, td_thr_events_t *events)
| 444pt_ta_clear_event(const td_thragent_t *ta __unused, 445 td_thr_events_t *events __unused)
|
445{ 446 TDBG_FUNC(); 447 return (0); 448} 449 450static td_err_e
| 446{ 447 TDBG_FUNC(); 448 return (0); 449} 450 451static td_err_e
|
451pt_ta_event_getmsg(const td_thragent_t *ta, td_event_msg_t *msg)
| 452pt_ta_event_getmsg(const td_thragent_t *ta __unused, 453 td_event_msg_t *msg __unused)
|
452{ 453 TDBG_FUNC(); 454 return (TD_NOMSG); 455} 456 457static td_err_e 458pt_dbsuspend(const td_thrhandle_t *th, int suspend) 459{
| 454{ 455 TDBG_FUNC(); 456 return (TD_NOMSG); 457} 458 459static td_err_e 460pt_dbsuspend(const td_thrhandle_t *th, int suspend) 461{
|
460 td_thragent_t *ta = (td_thragent_t *)th->th_ta;
| 462 const td_thragent_t *ta = th->th_ta;
|
461 psaddr_t tcb_addr, tmbx_addr, ptr; 462 lwpid_t lwp; 463 uint32_t dflags; 464 int attrflags, locklevel, ret; 465 466 TDBG_FUNC(); 467 468 ret = pt_validate(th); 469 if (ret) 470 return (ret); 471 472 if (ta->map[th->th_tid].type == PT_LWP) { 473 if (suspend) 474 ret = ps_lstop(ta->ph, ta->map[th->th_tid].lwp); 475 else 476 ret = ps_lcontinue(ta->ph, ta->map[th->th_tid].lwp); 477 return (P2T(ret)); 478 } 479 480 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 481 ta->thread_off_attr_flags, 482 &attrflags, sizeof(attrflags)); 483 if (ret != 0) 484 return (P2T(ret)); 485 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 486 ta->thread_off_tcb, 487 &tcb_addr, sizeof(tcb_addr)); 488 if (ret != 0) 489 return (P2T(ret)); 490 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 491 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 492 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 493 if (ret != 0) 494 return (P2T(ret)); 495 496 if (lwp != 0) { 497 /* don't suspend signal thread */ 498 if (attrflags & 0x200) 499 return (0); 500 if (attrflags & PTHREAD_SCOPE_SYSTEM) { 501 /* 502 * don't suspend system scope thread if it is holding 503 * some low level locks 504 */ 505 ptr = ta->map[th->th_tid].thr + ta->thread_off_kse; 506 ret = ps_pread(ta->ph, ptr, &ptr, sizeof(ptr)); 507 if (ret != 0) 508 return (P2T(ret)); 509 ret = ps_pread(ta->ph, ptr + ta->thread_off_kse_locklevel, 510 &locklevel, sizeof(int)); 511 if (ret != 0) 512 return (P2T(ret)); 513 if (locklevel <= 0) { 514 ptr = ta->map[th->th_tid].thr + 515 ta->thread_off_thr_locklevel; 516 ret = ps_pread(ta->ph, ptr, &locklevel, 517 sizeof(int)); 518 if (ret != 0) 519 return (P2T(ret)); 520 } 521 if (suspend) { 522 if (locklevel <= 0) 523 ret = ps_lstop(ta->ph, lwp); 524 } else { 525 ret = ps_lcontinue(ta->ph, lwp); 526 } 527 if (ret != 0) 528 return (P2T(ret)); 529 /* FALLTHROUGH */ 530 } else { 531 struct ptrace_lwpinfo pl; 532 533 if (ps_linfo(ta->ph, lwp, (caddr_t)&pl)) 534 return (TD_ERR); 535 if (suspend) { 536 if (!(pl.pl_flags & PL_FLAG_BOUND)) 537 ret = ps_lstop(ta->ph, lwp); 538 } else { 539 ret = ps_lcontinue(ta->ph, lwp); 540 } 541 if (ret != 0) 542 return (P2T(ret)); 543 /* FALLTHROUGH */ 544 } 545 } 546 /* read tm_dflags */ 547 ret = ps_pread(ta->ph, 548 tmbx_addr + offsetof(struct kse_thr_mailbox, tm_dflags), 549 &dflags, sizeof(dflags)); 550 if (ret != 0) 551 return (P2T(ret)); 552 if (suspend) 553 dflags |= TMDF_SUSPEND; 554 else 555 dflags &= ~TMDF_SUSPEND; 556 ret = ps_pwrite(ta->ph, 557 tmbx_addr + offsetof(struct kse_thr_mailbox, tm_dflags), 558 &dflags, sizeof(dflags)); 559 return (P2T(ret)); 560} 561 562static td_err_e 563pt_thr_dbresume(const td_thrhandle_t *th) 564{ 565 TDBG_FUNC(); 566 567 return pt_dbsuspend(th, 0); 568} 569 570static td_err_e 571pt_thr_dbsuspend(const td_thrhandle_t *th) 572{ 573 TDBG_FUNC(); 574 575 return pt_dbsuspend(th, 1); 576} 577 578static td_err_e 579pt_thr_validate(const td_thrhandle_t *th) 580{ 581 td_thrhandle_t temp; 582 int ret; 583 584 TDBG_FUNC(); 585 586 ret = pt_ta_map_id2thr(th->th_ta, th->th_tid, 587 &temp); 588 return (ret); 589} 590 591static td_err_e 592pt_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info) 593{ 594 const td_thragent_t *ta = th->th_ta; 595 struct ptrace_lwpinfo linfo; 596 psaddr_t tcb_addr; 597 uint32_t dflags; 598 lwpid_t lwp; 599 int state; 600 int ret; 601 int attrflags; 602 603 TDBG_FUNC(); 604 605 bzero(info, sizeof(*info)); 606 ret = pt_validate(th); 607 if (ret) 608 return (ret); 609 610 memset(info, 0, sizeof(*info)); 611 if (ta->map[th->th_tid].type == PT_LWP) { 612 info->ti_type = TD_THR_SYSTEM; 613 info->ti_lid = ta->map[th->th_tid].lwp; 614 info->ti_tid = th->th_tid; 615 info->ti_state = TD_THR_RUN; 616 info->ti_type = TD_THR_SYSTEM; 617 return (TD_OK); 618 } 619 620 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 621 ta->thread_off_attr_flags, 622 &attrflags, sizeof(attrflags)); 623 if (ret != 0) 624 return (P2T(ret)); 625 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_tcb, 626 &tcb_addr, sizeof(tcb_addr)); 627 if (ret != 0) 628 return (P2T(ret)); 629 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_state, 630 &state, sizeof(state)); 631 ret = ps_pread(ta->ph, 632 tcb_addr + ta->thread_off_tmbx + 633 offsetof(struct kse_thr_mailbox, tm_lwp), 634 &info->ti_lid, sizeof(lwpid_t)); 635 if (ret != 0) 636 return (P2T(ret)); 637 ret = ps_pread(ta->ph, 638 tcb_addr + ta->thread_off_tmbx + 639 offsetof(struct kse_thr_mailbox, tm_dflags), 640 &dflags, sizeof(dflags)); 641 if (ret != 0) 642 return (P2T(ret)); 643 ret = ps_pread(ta->ph, tcb_addr + ta->thread_off_tmbx + 644 offsetof(struct kse_thr_mailbox, tm_lwp), &lwp, sizeof(lwpid_t)); 645 if (ret != 0) 646 return (P2T(ret)); 647 info->ti_ta_p = th->th_ta; 648 info->ti_tid = th->th_tid; 649 650 if (attrflags & PTHREAD_SCOPE_SYSTEM) { 651 ret = ps_linfo(ta->ph, lwp, &linfo); 652 if (ret == PS_OK) { 653 info->ti_sigmask = linfo.pl_sigmask; 654 info->ti_pending = linfo.pl_siglist; 655 } else 656 return (ret); 657 } else { 658 ret = ps_pread(ta->ph, 659 ta->map[th->th_tid].thr + ta->thread_off_sigmask, 660 &info->ti_sigmask, sizeof(sigset_t)); 661 if (ret) 662 return (ret); 663 ret = ps_pread(ta->ph, 664 ta->map[th->th_tid].thr + ta->thread_off_sigpend, 665 &info->ti_pending, sizeof(sigset_t)); 666 if (ret) 667 return (ret); 668 } 669 670 if (state == ta->thread_state_running) 671 info->ti_state = TD_THR_RUN; 672 else if (state == ta->thread_state_zoombie) 673 info->ti_state = TD_THR_ZOMBIE; 674 else 675 info->ti_state = TD_THR_SLEEP; 676 info->ti_db_suspended = ((dflags & TMDF_SUSPEND) != 0); 677 info->ti_type = TD_THR_USER; 678 return (0); 679} 680 681#ifdef __i386__ 682static td_err_e 683pt_thr_getxmmregs(const td_thrhandle_t *th, char *fxsave) 684{ 685 const td_thragent_t *ta = th->th_ta; 686 struct kse_thr_mailbox tmbx; 687 psaddr_t tcb_addr, tmbx_addr, ptr; 688 lwpid_t lwp; 689 int ret; 690 691 return TD_ERR; 692 693 TDBG_FUNC(); 694 695 ret = pt_validate(th); 696 if (ret) 697 return (ret); 698 699 if (ta->map[th->th_tid].type == PT_LWP) { 700 ret = ps_lgetxmmregs(ta->ph, ta->map[th->th_tid].lwp, fxsave); 701 return (P2T(ret)); 702 } 703 704 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_tcb, 705 &tcb_addr, sizeof(tcb_addr)); 706 if (ret != 0) 707 return (P2T(ret)); 708 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 709 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 710 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 711 if (ret != 0) 712 return (P2T(ret)); 713 if (lwp != 0) { 714 ret = ps_lgetxmmregs(ta->ph, lwp, fxsave); 715 return (P2T(ret)); 716 } 717 718 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 719 if (ret != 0) 720 return (P2T(ret)); 721 pt_ucontext_to_fxsave(&tmbx.tm_context, fxsave); 722 return (0); 723} 724#endif 725 726static td_err_e 727pt_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregs) 728{ 729 const td_thragent_t *ta = th->th_ta; 730 struct kse_thr_mailbox tmbx; 731 psaddr_t tcb_addr, tmbx_addr, ptr; 732 lwpid_t lwp; 733 int ret; 734 735 TDBG_FUNC(); 736 737 ret = pt_validate(th); 738 if (ret) 739 return (ret); 740 741 if (ta->map[th->th_tid].type == PT_LWP) { 742 ret = ps_lgetfpregs(ta->ph, ta->map[th->th_tid].lwp, fpregs); 743 return (P2T(ret)); 744 } 745 746 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_tcb, 747 &tcb_addr, sizeof(tcb_addr)); 748 if (ret != 0) 749 return (P2T(ret)); 750 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 751 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 752 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 753 if (ret != 0) 754 return (P2T(ret)); 755 if (lwp != 0) { 756 ret = ps_lgetfpregs(ta->ph, lwp, fpregs); 757 return (P2T(ret)); 758 } 759 760 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 761 if (ret != 0) 762 return (P2T(ret)); 763 pt_ucontext_to_fpreg(&tmbx.tm_context, fpregs); 764 return (0); 765} 766 767static td_err_e 768pt_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs) 769{ 770 const td_thragent_t *ta = th->th_ta; 771 struct kse_thr_mailbox tmbx; 772 psaddr_t tcb_addr, tmbx_addr, ptr; 773 lwpid_t lwp; 774 int ret; 775 776 TDBG_FUNC(); 777 778 ret = pt_validate(th); 779 if (ret) 780 return (ret); 781 782 if (ta->map[th->th_tid].type == PT_LWP) { 783 ret = ps_lgetregs(ta->ph, 784 ta->map[th->th_tid].lwp, gregs); 785 return (P2T(ret)); 786 } 787 788 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_tcb, 789 &tcb_addr, sizeof(tcb_addr)); 790 if (ret != 0) 791 return (P2T(ret)); 792 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 793 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 794 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 795 if (ret != 0) 796 return (P2T(ret)); 797 if (lwp != 0) { 798 ret = ps_lgetregs(ta->ph, lwp, gregs); 799 return (P2T(ret)); 800 } 801 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 802 if (ret != 0) 803 return (P2T(ret)); 804 pt_ucontext_to_reg(&tmbx.tm_context, gregs); 805 return (0); 806} 807 808#ifdef __i386__ 809static td_err_e 810pt_thr_setxmmregs(const td_thrhandle_t *th, const char *fxsave) 811{ 812 const td_thragent_t *ta = th->th_ta; 813 struct kse_thr_mailbox tmbx; 814 psaddr_t tcb_addr, tmbx_addr, ptr; 815 lwpid_t lwp; 816 int ret; 817 818 return TD_ERR; 819 820 TDBG_FUNC(); 821 822 ret = pt_validate(th); 823 if (ret) 824 return (ret); 825 826 if (ta->map[th->th_tid].type == PT_LWP) { 827 ret = ps_lsetxmmregs(ta->ph, ta->map[th->th_tid].lwp, fxsave); 828 return (P2T(ret)); 829 } 830 831 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 832 ta->thread_off_tcb, 833 &tcb_addr, sizeof(tcb_addr)); 834 if (ret != 0) 835 return (P2T(ret)); 836 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 837 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 838 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 839 if (ret != 0) 840 return (P2T(ret)); 841 if (lwp != 0) { 842 ret = ps_lsetxmmregs(ta->ph, lwp, fxsave); 843 return (P2T(ret)); 844 } 845 /* 846 * Read a copy of context, this makes sure that registers 847 * not covered by structure reg won't be clobbered 848 */ 849 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 850 if (ret != 0) 851 return (P2T(ret)); 852 853 pt_fxsave_to_ucontext(fxsave, &tmbx.tm_context); 854 ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 855 return (P2T(ret)); 856} 857#endif 858 859static td_err_e 860pt_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs) 861{ 862 const td_thragent_t *ta = th->th_ta; 863 struct kse_thr_mailbox tmbx; 864 psaddr_t tcb_addr, tmbx_addr, ptr; 865 lwpid_t lwp; 866 int ret; 867 868 TDBG_FUNC(); 869 870 ret = pt_validate(th); 871 if (ret) 872 return (ret); 873 874 if (ta->map[th->th_tid].type == PT_LWP) { 875 ret = ps_lsetfpregs(ta->ph, ta->map[th->th_tid].lwp, fpregs); 876 return (P2T(ret)); 877 } 878 879 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 880 ta->thread_off_tcb, 881 &tcb_addr, sizeof(tcb_addr)); 882 if (ret != 0) 883 return (P2T(ret)); 884 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 885 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 886 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 887 if (ret != 0) 888 return (P2T(ret)); 889 if (lwp != 0) { 890 ret = ps_lsetfpregs(ta->ph, lwp, fpregs); 891 return (P2T(ret)); 892 } 893 /* 894 * Read a copy of context, this makes sure that registers 895 * not covered by structure reg won't be clobbered 896 */ 897 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 898 if (ret != 0) 899 return (P2T(ret)); 900 901 pt_fpreg_to_ucontext(fpregs, &tmbx.tm_context); 902 ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 903 return (P2T(ret)); 904} 905 906static td_err_e 907pt_thr_setgregs(const td_thrhandle_t *th, const prgregset_t gregs) 908{ 909 const td_thragent_t *ta = th->th_ta; 910 struct kse_thr_mailbox tmbx; 911 psaddr_t tcb_addr, tmbx_addr, ptr; 912 lwpid_t lwp; 913 int ret; 914 915 TDBG_FUNC(); 916 917 ret = pt_validate(th); 918 if (ret) 919 return (ret); 920 921 if (ta->map[th->th_tid].type == PT_LWP) { 922 ret = ps_lsetregs(ta->ph, ta->map[th->th_tid].lwp, gregs); 923 return (P2T(ret)); 924 } 925 926 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 927 ta->thread_off_tcb, 928 &tcb_addr, sizeof(tcb_addr)); 929 if (ret != 0) 930 return (P2T(ret)); 931 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 932 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 933 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 934 if (ret != 0) 935 return (P2T(ret)); 936 if (lwp != 0) { 937 ret = ps_lsetregs(ta->ph, lwp, gregs); 938 return (P2T(ret)); 939 } 940 941 /* 942 * Read a copy of context, make sure that registers 943 * not covered by structure reg won't be clobbered 944 */ 945 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 946 if (ret != 0) 947 return (P2T(ret)); 948 pt_reg_to_ucontext(gregs, &tmbx.tm_context); 949 ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 950 return (P2T(ret)); 951} 952 953static td_err_e
| 463 psaddr_t tcb_addr, tmbx_addr, ptr; 464 lwpid_t lwp; 465 uint32_t dflags; 466 int attrflags, locklevel, ret; 467 468 TDBG_FUNC(); 469 470 ret = pt_validate(th); 471 if (ret) 472 return (ret); 473 474 if (ta->map[th->th_tid].type == PT_LWP) { 475 if (suspend) 476 ret = ps_lstop(ta->ph, ta->map[th->th_tid].lwp); 477 else 478 ret = ps_lcontinue(ta->ph, ta->map[th->th_tid].lwp); 479 return (P2T(ret)); 480 } 481 482 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 483 ta->thread_off_attr_flags, 484 &attrflags, sizeof(attrflags)); 485 if (ret != 0) 486 return (P2T(ret)); 487 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 488 ta->thread_off_tcb, 489 &tcb_addr, sizeof(tcb_addr)); 490 if (ret != 0) 491 return (P2T(ret)); 492 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 493 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 494 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 495 if (ret != 0) 496 return (P2T(ret)); 497 498 if (lwp != 0) { 499 /* don't suspend signal thread */ 500 if (attrflags & 0x200) 501 return (0); 502 if (attrflags & PTHREAD_SCOPE_SYSTEM) { 503 /* 504 * don't suspend system scope thread if it is holding 505 * some low level locks 506 */ 507 ptr = ta->map[th->th_tid].thr + ta->thread_off_kse; 508 ret = ps_pread(ta->ph, ptr, &ptr, sizeof(ptr)); 509 if (ret != 0) 510 return (P2T(ret)); 511 ret = ps_pread(ta->ph, ptr + ta->thread_off_kse_locklevel, 512 &locklevel, sizeof(int)); 513 if (ret != 0) 514 return (P2T(ret)); 515 if (locklevel <= 0) { 516 ptr = ta->map[th->th_tid].thr + 517 ta->thread_off_thr_locklevel; 518 ret = ps_pread(ta->ph, ptr, &locklevel, 519 sizeof(int)); 520 if (ret != 0) 521 return (P2T(ret)); 522 } 523 if (suspend) { 524 if (locklevel <= 0) 525 ret = ps_lstop(ta->ph, lwp); 526 } else { 527 ret = ps_lcontinue(ta->ph, lwp); 528 } 529 if (ret != 0) 530 return (P2T(ret)); 531 /* FALLTHROUGH */ 532 } else { 533 struct ptrace_lwpinfo pl; 534 535 if (ps_linfo(ta->ph, lwp, (caddr_t)&pl)) 536 return (TD_ERR); 537 if (suspend) { 538 if (!(pl.pl_flags & PL_FLAG_BOUND)) 539 ret = ps_lstop(ta->ph, lwp); 540 } else { 541 ret = ps_lcontinue(ta->ph, lwp); 542 } 543 if (ret != 0) 544 return (P2T(ret)); 545 /* FALLTHROUGH */ 546 } 547 } 548 /* read tm_dflags */ 549 ret = ps_pread(ta->ph, 550 tmbx_addr + offsetof(struct kse_thr_mailbox, tm_dflags), 551 &dflags, sizeof(dflags)); 552 if (ret != 0) 553 return (P2T(ret)); 554 if (suspend) 555 dflags |= TMDF_SUSPEND; 556 else 557 dflags &= ~TMDF_SUSPEND; 558 ret = ps_pwrite(ta->ph, 559 tmbx_addr + offsetof(struct kse_thr_mailbox, tm_dflags), 560 &dflags, sizeof(dflags)); 561 return (P2T(ret)); 562} 563 564static td_err_e 565pt_thr_dbresume(const td_thrhandle_t *th) 566{ 567 TDBG_FUNC(); 568 569 return pt_dbsuspend(th, 0); 570} 571 572static td_err_e 573pt_thr_dbsuspend(const td_thrhandle_t *th) 574{ 575 TDBG_FUNC(); 576 577 return pt_dbsuspend(th, 1); 578} 579 580static td_err_e 581pt_thr_validate(const td_thrhandle_t *th) 582{ 583 td_thrhandle_t temp; 584 int ret; 585 586 TDBG_FUNC(); 587 588 ret = pt_ta_map_id2thr(th->th_ta, th->th_tid, 589 &temp); 590 return (ret); 591} 592 593static td_err_e 594pt_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info) 595{ 596 const td_thragent_t *ta = th->th_ta; 597 struct ptrace_lwpinfo linfo; 598 psaddr_t tcb_addr; 599 uint32_t dflags; 600 lwpid_t lwp; 601 int state; 602 int ret; 603 int attrflags; 604 605 TDBG_FUNC(); 606 607 bzero(info, sizeof(*info)); 608 ret = pt_validate(th); 609 if (ret) 610 return (ret); 611 612 memset(info, 0, sizeof(*info)); 613 if (ta->map[th->th_tid].type == PT_LWP) { 614 info->ti_type = TD_THR_SYSTEM; 615 info->ti_lid = ta->map[th->th_tid].lwp; 616 info->ti_tid = th->th_tid; 617 info->ti_state = TD_THR_RUN; 618 info->ti_type = TD_THR_SYSTEM; 619 return (TD_OK); 620 } 621 622 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 623 ta->thread_off_attr_flags, 624 &attrflags, sizeof(attrflags)); 625 if (ret != 0) 626 return (P2T(ret)); 627 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_tcb, 628 &tcb_addr, sizeof(tcb_addr)); 629 if (ret != 0) 630 return (P2T(ret)); 631 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_state, 632 &state, sizeof(state)); 633 ret = ps_pread(ta->ph, 634 tcb_addr + ta->thread_off_tmbx + 635 offsetof(struct kse_thr_mailbox, tm_lwp), 636 &info->ti_lid, sizeof(lwpid_t)); 637 if (ret != 0) 638 return (P2T(ret)); 639 ret = ps_pread(ta->ph, 640 tcb_addr + ta->thread_off_tmbx + 641 offsetof(struct kse_thr_mailbox, tm_dflags), 642 &dflags, sizeof(dflags)); 643 if (ret != 0) 644 return (P2T(ret)); 645 ret = ps_pread(ta->ph, tcb_addr + ta->thread_off_tmbx + 646 offsetof(struct kse_thr_mailbox, tm_lwp), &lwp, sizeof(lwpid_t)); 647 if (ret != 0) 648 return (P2T(ret)); 649 info->ti_ta_p = th->th_ta; 650 info->ti_tid = th->th_tid; 651 652 if (attrflags & PTHREAD_SCOPE_SYSTEM) { 653 ret = ps_linfo(ta->ph, lwp, &linfo); 654 if (ret == PS_OK) { 655 info->ti_sigmask = linfo.pl_sigmask; 656 info->ti_pending = linfo.pl_siglist; 657 } else 658 return (ret); 659 } else { 660 ret = ps_pread(ta->ph, 661 ta->map[th->th_tid].thr + ta->thread_off_sigmask, 662 &info->ti_sigmask, sizeof(sigset_t)); 663 if (ret) 664 return (ret); 665 ret = ps_pread(ta->ph, 666 ta->map[th->th_tid].thr + ta->thread_off_sigpend, 667 &info->ti_pending, sizeof(sigset_t)); 668 if (ret) 669 return (ret); 670 } 671 672 if (state == ta->thread_state_running) 673 info->ti_state = TD_THR_RUN; 674 else if (state == ta->thread_state_zoombie) 675 info->ti_state = TD_THR_ZOMBIE; 676 else 677 info->ti_state = TD_THR_SLEEP; 678 info->ti_db_suspended = ((dflags & TMDF_SUSPEND) != 0); 679 info->ti_type = TD_THR_USER; 680 return (0); 681} 682 683#ifdef __i386__ 684static td_err_e 685pt_thr_getxmmregs(const td_thrhandle_t *th, char *fxsave) 686{ 687 const td_thragent_t *ta = th->th_ta; 688 struct kse_thr_mailbox tmbx; 689 psaddr_t tcb_addr, tmbx_addr, ptr; 690 lwpid_t lwp; 691 int ret; 692 693 return TD_ERR; 694 695 TDBG_FUNC(); 696 697 ret = pt_validate(th); 698 if (ret) 699 return (ret); 700 701 if (ta->map[th->th_tid].type == PT_LWP) { 702 ret = ps_lgetxmmregs(ta->ph, ta->map[th->th_tid].lwp, fxsave); 703 return (P2T(ret)); 704 } 705 706 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_tcb, 707 &tcb_addr, sizeof(tcb_addr)); 708 if (ret != 0) 709 return (P2T(ret)); 710 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 711 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 712 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 713 if (ret != 0) 714 return (P2T(ret)); 715 if (lwp != 0) { 716 ret = ps_lgetxmmregs(ta->ph, lwp, fxsave); 717 return (P2T(ret)); 718 } 719 720 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 721 if (ret != 0) 722 return (P2T(ret)); 723 pt_ucontext_to_fxsave(&tmbx.tm_context, fxsave); 724 return (0); 725} 726#endif 727 728static td_err_e 729pt_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregs) 730{ 731 const td_thragent_t *ta = th->th_ta; 732 struct kse_thr_mailbox tmbx; 733 psaddr_t tcb_addr, tmbx_addr, ptr; 734 lwpid_t lwp; 735 int ret; 736 737 TDBG_FUNC(); 738 739 ret = pt_validate(th); 740 if (ret) 741 return (ret); 742 743 if (ta->map[th->th_tid].type == PT_LWP) { 744 ret = ps_lgetfpregs(ta->ph, ta->map[th->th_tid].lwp, fpregs); 745 return (P2T(ret)); 746 } 747 748 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_tcb, 749 &tcb_addr, sizeof(tcb_addr)); 750 if (ret != 0) 751 return (P2T(ret)); 752 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 753 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 754 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 755 if (ret != 0) 756 return (P2T(ret)); 757 if (lwp != 0) { 758 ret = ps_lgetfpregs(ta->ph, lwp, fpregs); 759 return (P2T(ret)); 760 } 761 762 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 763 if (ret != 0) 764 return (P2T(ret)); 765 pt_ucontext_to_fpreg(&tmbx.tm_context, fpregs); 766 return (0); 767} 768 769static td_err_e 770pt_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs) 771{ 772 const td_thragent_t *ta = th->th_ta; 773 struct kse_thr_mailbox tmbx; 774 psaddr_t tcb_addr, tmbx_addr, ptr; 775 lwpid_t lwp; 776 int ret; 777 778 TDBG_FUNC(); 779 780 ret = pt_validate(th); 781 if (ret) 782 return (ret); 783 784 if (ta->map[th->th_tid].type == PT_LWP) { 785 ret = ps_lgetregs(ta->ph, 786 ta->map[th->th_tid].lwp, gregs); 787 return (P2T(ret)); 788 } 789 790 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_tcb, 791 &tcb_addr, sizeof(tcb_addr)); 792 if (ret != 0) 793 return (P2T(ret)); 794 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 795 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 796 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 797 if (ret != 0) 798 return (P2T(ret)); 799 if (lwp != 0) { 800 ret = ps_lgetregs(ta->ph, lwp, gregs); 801 return (P2T(ret)); 802 } 803 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 804 if (ret != 0) 805 return (P2T(ret)); 806 pt_ucontext_to_reg(&tmbx.tm_context, gregs); 807 return (0); 808} 809 810#ifdef __i386__ 811static td_err_e 812pt_thr_setxmmregs(const td_thrhandle_t *th, const char *fxsave) 813{ 814 const td_thragent_t *ta = th->th_ta; 815 struct kse_thr_mailbox tmbx; 816 psaddr_t tcb_addr, tmbx_addr, ptr; 817 lwpid_t lwp; 818 int ret; 819 820 return TD_ERR; 821 822 TDBG_FUNC(); 823 824 ret = pt_validate(th); 825 if (ret) 826 return (ret); 827 828 if (ta->map[th->th_tid].type == PT_LWP) { 829 ret = ps_lsetxmmregs(ta->ph, ta->map[th->th_tid].lwp, fxsave); 830 return (P2T(ret)); 831 } 832 833 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 834 ta->thread_off_tcb, 835 &tcb_addr, sizeof(tcb_addr)); 836 if (ret != 0) 837 return (P2T(ret)); 838 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 839 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 840 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 841 if (ret != 0) 842 return (P2T(ret)); 843 if (lwp != 0) { 844 ret = ps_lsetxmmregs(ta->ph, lwp, fxsave); 845 return (P2T(ret)); 846 } 847 /* 848 * Read a copy of context, this makes sure that registers 849 * not covered by structure reg won't be clobbered 850 */ 851 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 852 if (ret != 0) 853 return (P2T(ret)); 854 855 pt_fxsave_to_ucontext(fxsave, &tmbx.tm_context); 856 ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 857 return (P2T(ret)); 858} 859#endif 860 861static td_err_e 862pt_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs) 863{ 864 const td_thragent_t *ta = th->th_ta; 865 struct kse_thr_mailbox tmbx; 866 psaddr_t tcb_addr, tmbx_addr, ptr; 867 lwpid_t lwp; 868 int ret; 869 870 TDBG_FUNC(); 871 872 ret = pt_validate(th); 873 if (ret) 874 return (ret); 875 876 if (ta->map[th->th_tid].type == PT_LWP) { 877 ret = ps_lsetfpregs(ta->ph, ta->map[th->th_tid].lwp, fpregs); 878 return (P2T(ret)); 879 } 880 881 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 882 ta->thread_off_tcb, 883 &tcb_addr, sizeof(tcb_addr)); 884 if (ret != 0) 885 return (P2T(ret)); 886 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 887 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 888 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 889 if (ret != 0) 890 return (P2T(ret)); 891 if (lwp != 0) { 892 ret = ps_lsetfpregs(ta->ph, lwp, fpregs); 893 return (P2T(ret)); 894 } 895 /* 896 * Read a copy of context, this makes sure that registers 897 * not covered by structure reg won't be clobbered 898 */ 899 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 900 if (ret != 0) 901 return (P2T(ret)); 902 903 pt_fpreg_to_ucontext(fpregs, &tmbx.tm_context); 904 ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 905 return (P2T(ret)); 906} 907 908static td_err_e 909pt_thr_setgregs(const td_thrhandle_t *th, const prgregset_t gregs) 910{ 911 const td_thragent_t *ta = th->th_ta; 912 struct kse_thr_mailbox tmbx; 913 psaddr_t tcb_addr, tmbx_addr, ptr; 914 lwpid_t lwp; 915 int ret; 916 917 TDBG_FUNC(); 918 919 ret = pt_validate(th); 920 if (ret) 921 return (ret); 922 923 if (ta->map[th->th_tid].type == PT_LWP) { 924 ret = ps_lsetregs(ta->ph, ta->map[th->th_tid].lwp, gregs); 925 return (P2T(ret)); 926 } 927 928 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 929 ta->thread_off_tcb, 930 &tcb_addr, sizeof(tcb_addr)); 931 if (ret != 0) 932 return (P2T(ret)); 933 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 934 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 935 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 936 if (ret != 0) 937 return (P2T(ret)); 938 if (lwp != 0) { 939 ret = ps_lsetregs(ta->ph, lwp, gregs); 940 return (P2T(ret)); 941 } 942 943 /* 944 * Read a copy of context, make sure that registers 945 * not covered by structure reg won't be clobbered 946 */ 947 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 948 if (ret != 0) 949 return (P2T(ret)); 950 pt_reg_to_ucontext(gregs, &tmbx.tm_context); 951 ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 952 return (P2T(ret)); 953} 954 955static td_err_e
|
954pt_thr_event_enable(const td_thrhandle_t *th, int en)
| 956pt_thr_event_enable(const td_thrhandle_t *th __unused, int en __unused)
|
955{ 956 TDBG_FUNC(); 957 return (0); 958} 959 960static td_err_e
| 957{ 958 TDBG_FUNC(); 959 return (0); 960} 961 962static td_err_e
|
961pt_thr_set_event(const td_thrhandle_t *th, td_thr_events_t *setp)
| 963pt_thr_set_event(const td_thrhandle_t *th __unused, 964 td_thr_events_t *setp __unused)
|
962{ 963 TDBG_FUNC(); 964 return (0); 965} 966 967static td_err_e
| 965{ 966 TDBG_FUNC(); 967 return (0); 968} 969 970static td_err_e
|
968pt_thr_clear_event(const td_thrhandle_t *th, td_thr_events_t *setp)
| 971pt_thr_clear_event(const td_thrhandle_t *th __unused, 972 td_thr_events_t *setp __unused)
|
969{ 970 TDBG_FUNC(); 971 return (0); 972} 973 974static td_err_e
| 973{ 974 TDBG_FUNC(); 975 return (0); 976} 977 978static td_err_e
|
975pt_thr_event_getmsg(const td_thrhandle_t *th, td_event_msg_t *msg)
| 979pt_thr_event_getmsg(const td_thrhandle_t *th __unused, 980 td_event_msg_t *msg __unused)
|
976{ 977 TDBG_FUNC(); 978 return (TD_NOMSG); 979} 980 981static td_err_e 982pt_thr_sstep(const td_thrhandle_t *th, int step) 983{ 984 const td_thragent_t *ta = th->th_ta; 985 struct kse_thr_mailbox tmbx; 986 struct reg regs; 987 psaddr_t tcb_addr, tmbx_addr; 988 uint32_t dflags; 989 lwpid_t lwp; 990 int ret; 991 992 TDBG_FUNC(); 993 994 ret = pt_validate(th); 995 if (ret) 996 return (ret); 997 998 if (ta->map[th->th_tid].type == PT_LWP) 999 return (TD_BADTH); 1000 1001 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 1002 ta->thread_off_tcb, 1003 &tcb_addr, sizeof(tcb_addr)); 1004 if (ret != 0) 1005 return (P2T(ret)); 1006 1007 /* Clear or set single step flag in thread mailbox */ 1008 ret = ps_pread(ta->ph, 1009 tcb_addr + ta->thread_off_tmbx + 1010 offsetof(struct kse_thr_mailbox, tm_dflags), 1011 &dflags, sizeof(uint32_t)); 1012 if (ret != 0) 1013 return (P2T(ret)); 1014 if (step != 0) 1015 dflags |= TMDF_SSTEP; 1016 else 1017 dflags &= ~TMDF_SSTEP; 1018 ret = ps_pwrite(ta->ph, 1019 tcb_addr + ta->thread_off_tmbx + 1020 offsetof(struct kse_thr_mailbox, tm_dflags), 1021 &dflags, sizeof(uint32_t)); 1022 if (ret != 0) 1023 return (P2T(ret)); 1024 /* Get lwp */ 1025 ret = ps_pread(ta->ph, 1026 tcb_addr + ta->thread_off_tmbx + 1027 offsetof(struct kse_thr_mailbox, tm_lwp), 1028 &lwp, sizeof(lwpid_t)); 1029 if (ret != 0) 1030 return (P2T(ret)); 1031 if (lwp != 0) 1032 return (0); 1033 1034 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 1035 /* 1036 * context is in userland, some architectures store 1037 * single step status in registers, we should change 1038 * these registers. 1039 */ 1040 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 1041 if (ret == 0) { 1042 pt_ucontext_to_reg(&tmbx.tm_context, ®s); 1043 /* only write out if it is really changed. */ 1044 if (pt_reg_sstep(®s, step) != 0) { 1045 pt_reg_to_ucontext(®s, &tmbx.tm_context); 1046 ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, 1047 sizeof(tmbx)); 1048 } 1049 } 1050 return (P2T(ret)); 1051} 1052 1053static void 1054pt_unmap_lwp(const td_thragent_t *ta, lwpid_t lwp) 1055{ 1056 int i; 1057 1058 for (i = 0; i < ta->map_len; ++i) { 1059 if (ta->map[i].type == PT_LWP && ta->map[i].lwp == lwp) { 1060 ta->map[i].type = PT_NONE; 1061 return; 1062 } 1063 } 1064} 1065 1066static int 1067pt_validate(const td_thrhandle_t *th) 1068{ 1069 1070 if (th->th_tid < 0 || th->th_tid >= th->th_ta->map_len || 1071 th->th_ta->map[th->th_tid].type == PT_NONE) 1072 return (TD_NOTHR); 1073 return (TD_OK); 1074} 1075 1076static td_err_e 1077pt_thr_tls_get_addr(const td_thrhandle_t *th, psaddr_t _linkmap, size_t offset, 1078 psaddr_t *address) 1079{ 1080 const td_thragent_t *ta = th->th_ta; 1081 psaddr_t dtv_addr, obj_entry, tcb_addr; 1082 int tls_index, ret; 1083 1084 /* linkmap is a member of Obj_Entry */ 1085 obj_entry = _linkmap - ta->thread_off_linkmap; 1086 1087 /* get tlsindex of the object file */ 1088 ret = ps_pread(ta->ph, 1089 obj_entry + ta->thread_off_tlsindex, 1090 &tls_index, sizeof(tls_index)); 1091 if (ret != 0) 1092 return (P2T(ret)); 1093 1094 /* get thread tcb */ 1095 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 1096 ta->thread_off_tcb, 1097 &tcb_addr, sizeof(tcb_addr)); 1098 if (ret != 0) 1099 return (P2T(ret)); 1100 1101 /* get dtv array address */ 1102 ret = ps_pread(ta->ph, tcb_addr + ta->thread_off_dtv, 1103 &dtv_addr, sizeof(dtv_addr)); 1104 if (ret != 0) 1105 return (P2T(ret)); 1106 /* now get the object's tls block base address */ 1107 ret = ps_pread(ta->ph, dtv_addr + sizeof(void *) * (tls_index + 1), 1108 address, sizeof(*address)); 1109 if (ret != 0) 1110 return (P2T(ret)); 1111 1112 *address += offset; 1113 return (TD_OK); 1114} 1115 1116struct ta_ops libpthread_db_ops = { 1117 .to_init = pt_init, 1118 .to_ta_clear_event = pt_ta_clear_event, 1119 .to_ta_delete = pt_ta_delete, 1120 .to_ta_event_addr = pt_ta_event_addr, 1121 .to_ta_event_getmsg = pt_ta_event_getmsg, 1122 .to_ta_map_id2thr = pt_ta_map_id2thr, 1123 .to_ta_map_lwp2thr = pt_ta_map_lwp2thr, 1124 .to_ta_new = pt_ta_new, 1125 .to_ta_set_event = pt_ta_set_event, 1126 .to_ta_thr_iter = pt_ta_thr_iter, 1127 .to_ta_tsd_iter = pt_ta_tsd_iter, 1128 .to_thr_clear_event = pt_thr_clear_event, 1129 .to_thr_dbresume = pt_thr_dbresume, 1130 .to_thr_dbsuspend = pt_thr_dbsuspend, 1131 .to_thr_event_enable = pt_thr_event_enable, 1132 .to_thr_event_getmsg = pt_thr_event_getmsg, 1133 .to_thr_get_info = pt_thr_get_info, 1134 .to_thr_getfpregs = pt_thr_getfpregs, 1135 .to_thr_getgregs = pt_thr_getgregs, 1136 .to_thr_set_event = pt_thr_set_event, 1137 .to_thr_setfpregs = pt_thr_setfpregs, 1138 .to_thr_setgregs = pt_thr_setgregs, 1139 .to_thr_validate = pt_thr_validate, 1140 .to_thr_tls_get_addr = pt_thr_tls_get_addr, 1141 1142 /* FreeBSD specific extensions. */ 1143 .to_thr_sstep = pt_thr_sstep, 1144#ifdef __i386__ 1145 .to_thr_getxmmregs = pt_thr_getxmmregs, 1146 .to_thr_setxmmregs = pt_thr_setxmmregs, 1147#endif 1148}; 1149 1150DATA_SET(__ta_ops, libpthread_db_ops);
| 981{ 982 TDBG_FUNC(); 983 return (TD_NOMSG); 984} 985 986static td_err_e 987pt_thr_sstep(const td_thrhandle_t *th, int step) 988{ 989 const td_thragent_t *ta = th->th_ta; 990 struct kse_thr_mailbox tmbx; 991 struct reg regs; 992 psaddr_t tcb_addr, tmbx_addr; 993 uint32_t dflags; 994 lwpid_t lwp; 995 int ret; 996 997 TDBG_FUNC(); 998 999 ret = pt_validate(th); 1000 if (ret) 1001 return (ret); 1002 1003 if (ta->map[th->th_tid].type == PT_LWP) 1004 return (TD_BADTH); 1005 1006 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 1007 ta->thread_off_tcb, 1008 &tcb_addr, sizeof(tcb_addr)); 1009 if (ret != 0) 1010 return (P2T(ret)); 1011 1012 /* Clear or set single step flag in thread mailbox */ 1013 ret = ps_pread(ta->ph, 1014 tcb_addr + ta->thread_off_tmbx + 1015 offsetof(struct kse_thr_mailbox, tm_dflags), 1016 &dflags, sizeof(uint32_t)); 1017 if (ret != 0) 1018 return (P2T(ret)); 1019 if (step != 0) 1020 dflags |= TMDF_SSTEP; 1021 else 1022 dflags &= ~TMDF_SSTEP; 1023 ret = ps_pwrite(ta->ph, 1024 tcb_addr + ta->thread_off_tmbx + 1025 offsetof(struct kse_thr_mailbox, tm_dflags), 1026 &dflags, sizeof(uint32_t)); 1027 if (ret != 0) 1028 return (P2T(ret)); 1029 /* Get lwp */ 1030 ret = ps_pread(ta->ph, 1031 tcb_addr + ta->thread_off_tmbx + 1032 offsetof(struct kse_thr_mailbox, tm_lwp), 1033 &lwp, sizeof(lwpid_t)); 1034 if (ret != 0) 1035 return (P2T(ret)); 1036 if (lwp != 0) 1037 return (0); 1038 1039 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 1040 /* 1041 * context is in userland, some architectures store 1042 * single step status in registers, we should change 1043 * these registers. 1044 */ 1045 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 1046 if (ret == 0) { 1047 pt_ucontext_to_reg(&tmbx.tm_context, ®s); 1048 /* only write out if it is really changed. */ 1049 if (pt_reg_sstep(®s, step) != 0) { 1050 pt_reg_to_ucontext(®s, &tmbx.tm_context); 1051 ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, 1052 sizeof(tmbx)); 1053 } 1054 } 1055 return (P2T(ret)); 1056} 1057 1058static void 1059pt_unmap_lwp(const td_thragent_t *ta, lwpid_t lwp) 1060{ 1061 int i; 1062 1063 for (i = 0; i < ta->map_len; ++i) { 1064 if (ta->map[i].type == PT_LWP && ta->map[i].lwp == lwp) { 1065 ta->map[i].type = PT_NONE; 1066 return; 1067 } 1068 } 1069} 1070 1071static int 1072pt_validate(const td_thrhandle_t *th) 1073{ 1074 1075 if (th->th_tid < 0 || th->th_tid >= th->th_ta->map_len || 1076 th->th_ta->map[th->th_tid].type == PT_NONE) 1077 return (TD_NOTHR); 1078 return (TD_OK); 1079} 1080 1081static td_err_e 1082pt_thr_tls_get_addr(const td_thrhandle_t *th, psaddr_t _linkmap, size_t offset, 1083 psaddr_t *address) 1084{ 1085 const td_thragent_t *ta = th->th_ta; 1086 psaddr_t dtv_addr, obj_entry, tcb_addr; 1087 int tls_index, ret; 1088 1089 /* linkmap is a member of Obj_Entry */ 1090 obj_entry = _linkmap - ta->thread_off_linkmap; 1091 1092 /* get tlsindex of the object file */ 1093 ret = ps_pread(ta->ph, 1094 obj_entry + ta->thread_off_tlsindex, 1095 &tls_index, sizeof(tls_index)); 1096 if (ret != 0) 1097 return (P2T(ret)); 1098 1099 /* get thread tcb */ 1100 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 1101 ta->thread_off_tcb, 1102 &tcb_addr, sizeof(tcb_addr)); 1103 if (ret != 0) 1104 return (P2T(ret)); 1105 1106 /* get dtv array address */ 1107 ret = ps_pread(ta->ph, tcb_addr + ta->thread_off_dtv, 1108 &dtv_addr, sizeof(dtv_addr)); 1109 if (ret != 0) 1110 return (P2T(ret)); 1111 /* now get the object's tls block base address */ 1112 ret = ps_pread(ta->ph, dtv_addr + sizeof(void *) * (tls_index + 1), 1113 address, sizeof(*address)); 1114 if (ret != 0) 1115 return (P2T(ret)); 1116 1117 *address += offset; 1118 return (TD_OK); 1119} 1120 1121struct ta_ops libpthread_db_ops = { 1122 .to_init = pt_init, 1123 .to_ta_clear_event = pt_ta_clear_event, 1124 .to_ta_delete = pt_ta_delete, 1125 .to_ta_event_addr = pt_ta_event_addr, 1126 .to_ta_event_getmsg = pt_ta_event_getmsg, 1127 .to_ta_map_id2thr = pt_ta_map_id2thr, 1128 .to_ta_map_lwp2thr = pt_ta_map_lwp2thr, 1129 .to_ta_new = pt_ta_new, 1130 .to_ta_set_event = pt_ta_set_event, 1131 .to_ta_thr_iter = pt_ta_thr_iter, 1132 .to_ta_tsd_iter = pt_ta_tsd_iter, 1133 .to_thr_clear_event = pt_thr_clear_event, 1134 .to_thr_dbresume = pt_thr_dbresume, 1135 .to_thr_dbsuspend = pt_thr_dbsuspend, 1136 .to_thr_event_enable = pt_thr_event_enable, 1137 .to_thr_event_getmsg = pt_thr_event_getmsg, 1138 .to_thr_get_info = pt_thr_get_info, 1139 .to_thr_getfpregs = pt_thr_getfpregs, 1140 .to_thr_getgregs = pt_thr_getgregs, 1141 .to_thr_set_event = pt_thr_set_event, 1142 .to_thr_setfpregs = pt_thr_setfpregs, 1143 .to_thr_setgregs = pt_thr_setgregs, 1144 .to_thr_validate = pt_thr_validate, 1145 .to_thr_tls_get_addr = pt_thr_tls_get_addr, 1146 1147 /* FreeBSD specific extensions. */ 1148 .to_thr_sstep = pt_thr_sstep, 1149#ifdef __i386__ 1150 .to_thr_getxmmregs = pt_thr_getxmmregs, 1151 .to_thr_setxmmregs = pt_thr_setxmmregs, 1152#endif 1153}; 1154 1155DATA_SET(__ta_ops, libpthread_db_ops);
|