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