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$"); 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 46 static void pt_unmap_lwp(const td_thragent_t *ta, lwpid_t lwp); 47 static int pt_validate(const td_thrhandle_t *th); 48 49 static int 50 ps2td(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 72 static long 73 pt_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 114 static td_err_e 115 pt_init(void) 116 { 117 pt_md_init(); 118 return (0); 119 } 120 121 static td_err_e 122 pt_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 195 error: 196 free(ta); 197 return (ret); 198 } 199 200 static td_err_e 201 pt_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 219 static td_err_e 220 pt_ta_map_id2thr(const td_thragent_t *ta, thread_t id, td_thrhandle_t *th) 221 { 222 prgregset_t gregs; 223 psaddr_t pt, tcb_addr; 224 lwpid_t lwp; 225 int ret; 226 227 TDBG_FUNC(); 228 229 if (id < 0 || id >= ta->map_len || ta->map[id].type == PT_NONE) 230 return (TD_NOTHR); 231 232 ret = thr_pread_ptr(ta, ta->thread_list_addr, &pt); 233 if (ret != 0) 234 return (TD_ERR); 235 if (ta->map[id].type == PT_LWP) { 236 /* 237 * if we are referencing a lwp, make sure it was not already 238 * mapped to user thread. 239 */ 240 while (pt != 0) { 241 ret = thr_pread_ptr(ta, pt + ta->thread_off_tcb, 242 &tcb_addr); 243 if (ret != 0) 244 return (TD_ERR); 245 ret = thr_pread_int(ta, tcb_addr + ta->thread_off_tmbx + 246 offsetof(struct kse_thr_mailbox, tm_lwp), &lwp); 247 if (ret != 0) 248 return (TD_ERR); 249 /* 250 * If the lwp was already mapped to userland thread, 251 * we shouldn't reference it directly in future. 252 */ 253 if (lwp == ta->map[id].lwp) { 254 ta->map[id].type = PT_NONE; 255 return (TD_NOTHR); 256 } 257 /* get next thread */ 258 ret = thr_pread_ptr(ta, pt + ta->thread_off_next, &pt); 259 if (ret != 0) 260 return (TD_ERR); 261 } 262 /* check lwp */ 263 ret = ps_lgetregs(ta->ph, ta->map[id].lwp, gregs); 264 if (ret != PS_OK) { 265 /* no longer exists */ 266 ta->map[id].type = PT_NONE; 267 return (TD_NOTHR); 268 } 269 } else { 270 while (pt != 0 && ta->map[id].thr != pt) { 271 ret = thr_pread_ptr(ta, pt + ta->thread_off_tcb, 272 &tcb_addr); 273 if (ret != 0) 274 return (TD_ERR); 275 /* get next thread */ 276 ret = thr_pread_ptr(ta, pt + ta->thread_off_next, &pt); 277 if (ret != 0) 278 return (TD_ERR); 279 } 280 281 if (pt == 0) { 282 /* no longer exists */ 283 ta->map[id].type = PT_NONE; 284 return (TD_NOTHR); 285 } 286 } 287 th->th_ta = ta; 288 th->th_tid = id; 289 th->th_thread = pt; 290 return (TD_OK); 291 } 292 293 static td_err_e 294 pt_ta_map_lwp2thr(const td_thragent_t *ta, lwpid_t lwp, td_thrhandle_t *th) 295 { 296 psaddr_t pt, tcb_addr; 297 lwpid_t lwp1; 298 int ret; 299 300 TDBG_FUNC(); 301 302 ret = thr_pread_ptr(ta, ta->thread_list_addr, &pt); 303 if (ret != 0) 304 return (TD_ERR); 305 while (pt != 0) { 306 ret = thr_pread_ptr(ta, pt + ta->thread_off_tcb, &tcb_addr); 307 if (ret != 0) 308 return (TD_ERR); 309 ret = thr_pread_int(ta, tcb_addr + ta->thread_off_tmbx + 310 offsetof(struct kse_thr_mailbox, tm_lwp), &lwp1); 311 if (ret != 0) 312 return (TD_ERR); 313 if (lwp1 == lwp) { 314 th->th_ta = ta; 315 th->th_tid = pt_map_thread(ta, pt, PT_USER); 316 if (th->th_tid == -1) 317 return (TD_MALLOC); 318 pt_unmap_lwp(ta, lwp); 319 th->th_thread = pt; 320 return (TD_OK); 321 } 322 323 /* get next thread */ 324 ret = thr_pread_ptr(ta, pt + ta->thread_off_next, &pt); 325 if (ret != 0) 326 return (TD_ERR); 327 } 328 329 return (TD_NOTHR); 330 } 331 332 static td_err_e 333 pt_ta_thr_iter(const td_thragent_t *ta, td_thr_iter_f *callback, 334 void *cbdata_p, td_thr_state_e state __unused, int ti_pri __unused, 335 sigset_t *ti_sigmask_p __unused, unsigned int ti_user_flags __unused) 336 { 337 td_thrhandle_t th; 338 psaddr_t pt; 339 ps_err_e pserr; 340 int activated, ret; 341 342 TDBG_FUNC(); 343 344 pserr = ps_pread(ta->ph, ta->thread_activated_addr, &activated, 345 sizeof(int)); 346 if (pserr != PS_OK) 347 return (P2T(pserr)); 348 if (!activated) 349 return (TD_OK); 350 351 ret = thr_pread_ptr(ta, ta->thread_list_addr, &pt); 352 if (ret != 0) 353 return (TD_ERR); 354 while (pt != 0) { 355 th.th_ta = ta; 356 th.th_tid = pt_map_thread(ta, pt, PT_USER); 357 th.th_thread = pt; 358 /* should we unmap lwp here ? */ 359 if (th.th_tid == -1) 360 return (TD_MALLOC); 361 if ((*callback)(&th, cbdata_p)) 362 return (TD_DBERR); 363 /* get next thread */ 364 ret = thr_pread_ptr(ta, pt + ta->thread_off_next, &pt); 365 if (ret != 0) 366 return (TD_ERR); 367 } 368 return (TD_OK); 369 } 370 371 static td_err_e 372 pt_ta_tsd_iter(const td_thragent_t *ta, td_key_iter_f *ki, void *arg) 373 { 374 void *keytable; 375 void *destructor; 376 int i, ret, allocated; 377 378 TDBG_FUNC(); 379 380 keytable = malloc(ta->thread_max_keys * ta->thread_size_key); 381 if (keytable == NULL) 382 return (TD_MALLOC); 383 ret = ps_pread(ta->ph, (psaddr_t)ta->thread_keytable_addr, keytable, 384 ta->thread_max_keys * ta->thread_size_key); 385 if (ret != 0) { 386 free(keytable); 387 return (P2T(ret)); 388 } 389 for (i = 0; i < ta->thread_max_keys; i++) { 390 allocated = *(int *)(void *)((uintptr_t)keytable + 391 i * ta->thread_size_key + ta->thread_off_key_allocated); 392 destructor = *(void **)(void *)((uintptr_t)keytable + 393 i * ta->thread_size_key + ta->thread_off_key_destructor); 394 if (allocated) { 395 ret = (ki)(i, destructor, arg); 396 if (ret != 0) { 397 free(keytable); 398 return (TD_DBERR); 399 } 400 } 401 } 402 free(keytable); 403 return (TD_OK); 404 } 405 406 static td_err_e 407 pt_ta_event_addr(const td_thragent_t *ta __unused, td_event_e event __unused, 408 td_notify_t *ptr __unused) 409 { 410 TDBG_FUNC(); 411 return (TD_ERR); 412 } 413 414 static td_err_e 415 pt_ta_set_event(const td_thragent_t *ta __unused, 416 td_thr_events_t *events __unused) 417 { 418 TDBG_FUNC(); 419 return (0); 420 } 421 422 static td_err_e 423 pt_ta_clear_event(const td_thragent_t *ta __unused, 424 td_thr_events_t *events __unused) 425 { 426 TDBG_FUNC(); 427 return (0); 428 } 429 430 static td_err_e 431 pt_ta_event_getmsg(const td_thragent_t *ta __unused, 432 td_event_msg_t *msg __unused) 433 { 434 TDBG_FUNC(); 435 return (TD_NOMSG); 436 } 437 438 static td_err_e 439 pt_dbsuspend(const td_thrhandle_t *th, int suspend) 440 { 441 const td_thragent_t *ta = th->th_ta; 442 psaddr_t tcb_addr, tmbx_addr, ptr; 443 lwpid_t lwp; 444 uint32_t dflags; 445 int attrflags, locklevel, ret; 446 447 TDBG_FUNC(); 448 449 ret = pt_validate(th); 450 if (ret) 451 return (ret); 452 453 if (ta->map[th->th_tid].type == PT_LWP) { 454 if (suspend) 455 ret = ps_lstop(ta->ph, ta->map[th->th_tid].lwp); 456 else 457 ret = ps_lcontinue(ta->ph, ta->map[th->th_tid].lwp); 458 return (P2T(ret)); 459 } 460 461 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 462 ta->thread_off_attr_flags, 463 &attrflags, sizeof(attrflags)); 464 if (ret != 0) 465 return (P2T(ret)); 466 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 467 ta->thread_off_tcb, 468 &tcb_addr, sizeof(tcb_addr)); 469 if (ret != 0) 470 return (P2T(ret)); 471 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 472 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 473 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 474 if (ret != 0) 475 return (P2T(ret)); 476 477 if (lwp != 0) { 478 /* don't suspend signal thread */ 479 if (attrflags & 0x200) 480 return (0); 481 if (attrflags & PTHREAD_SCOPE_SYSTEM) { 482 /* 483 * don't suspend system scope thread if it is holding 484 * some low level locks 485 */ 486 ptr = ta->map[th->th_tid].thr + ta->thread_off_kse; 487 ret = ps_pread(ta->ph, ptr, &ptr, sizeof(ptr)); 488 if (ret != 0) 489 return (P2T(ret)); 490 ret = ps_pread(ta->ph, ptr + ta->thread_off_kse_locklevel, 491 &locklevel, sizeof(int)); 492 if (ret != 0) 493 return (P2T(ret)); 494 if (locklevel <= 0) { 495 ptr = ta->map[th->th_tid].thr + 496 ta->thread_off_thr_locklevel; 497 ret = ps_pread(ta->ph, ptr, &locklevel, 498 sizeof(int)); 499 if (ret != 0) 500 return (P2T(ret)); 501 } 502 if (suspend) { 503 if (locklevel <= 0) 504 ret = ps_lstop(ta->ph, lwp); 505 } else { 506 ret = ps_lcontinue(ta->ph, lwp); 507 } 508 if (ret != 0) 509 return (P2T(ret)); 510 /* FALLTHROUGH */ 511 } else { 512 struct ptrace_lwpinfo pl; 513 514 if (ps_linfo(ta->ph, lwp, (caddr_t)&pl)) 515 return (TD_ERR); 516 if (suspend) { 517 if (!(pl.pl_flags & PL_FLAG_BOUND)) 518 ret = ps_lstop(ta->ph, lwp); 519 } else { 520 ret = ps_lcontinue(ta->ph, lwp); 521 } 522 if (ret != 0) 523 return (P2T(ret)); 524 /* FALLTHROUGH */ 525 } 526 } 527 /* read tm_dflags */ 528 ret = ps_pread(ta->ph, 529 tmbx_addr + offsetof(struct kse_thr_mailbox, tm_dflags), 530 &dflags, sizeof(dflags)); 531 if (ret != 0) 532 return (P2T(ret)); 533 if (suspend) 534 dflags |= TMDF_SUSPEND; 535 else 536 dflags &= ~TMDF_SUSPEND; 537 ret = ps_pwrite(ta->ph, 538 tmbx_addr + offsetof(struct kse_thr_mailbox, tm_dflags), 539 &dflags, sizeof(dflags)); 540 return (P2T(ret)); 541 } 542 543 static td_err_e 544 pt_thr_dbresume(const td_thrhandle_t *th) 545 { 546 TDBG_FUNC(); 547 548 return pt_dbsuspend(th, 0); 549 } 550 551 static td_err_e 552 pt_thr_dbsuspend(const td_thrhandle_t *th) 553 { 554 TDBG_FUNC(); 555 556 return pt_dbsuspend(th, 1); 557 } 558 559 static td_err_e 560 pt_thr_validate(const td_thrhandle_t *th) 561 { 562 td_thrhandle_t temp; 563 int ret; 564 565 TDBG_FUNC(); 566 567 ret = pt_ta_map_id2thr(th->th_ta, th->th_tid, 568 &temp); 569 return (ret); 570 } 571 572 static td_err_e 573 pt_thr_old_get_info(const td_thrhandle_t *th, td_old_thrinfo_t *info) 574 { 575 const td_thragent_t *ta = th->th_ta; 576 struct ptrace_lwpinfo linfo; 577 psaddr_t tcb_addr; 578 uint32_t dflags; 579 lwpid_t lwp; 580 int state; 581 int ret; 582 int attrflags; 583 584 TDBG_FUNC(); 585 586 bzero(info, sizeof(*info)); 587 ret = pt_validate(th); 588 if (ret) 589 return (ret); 590 591 memset(info, 0, sizeof(*info)); 592 if (ta->map[th->th_tid].type == PT_LWP) { 593 info->ti_type = TD_THR_SYSTEM; 594 info->ti_lid = ta->map[th->th_tid].lwp; 595 info->ti_tid = th->th_tid; 596 info->ti_state = TD_THR_RUN; 597 info->ti_type = TD_THR_SYSTEM; 598 return (TD_OK); 599 } 600 601 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 602 ta->thread_off_attr_flags, 603 &attrflags, sizeof(attrflags)); 604 if (ret != 0) 605 return (P2T(ret)); 606 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_tcb, 607 &tcb_addr, sizeof(tcb_addr)); 608 if (ret != 0) 609 return (P2T(ret)); 610 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_state, 611 &state, sizeof(state)); 612 ret = ps_pread(ta->ph, 613 tcb_addr + ta->thread_off_tmbx + 614 offsetof(struct kse_thr_mailbox, tm_lwp), 615 &info->ti_lid, sizeof(lwpid_t)); 616 if (ret != 0) 617 return (P2T(ret)); 618 ret = ps_pread(ta->ph, 619 tcb_addr + ta->thread_off_tmbx + 620 offsetof(struct kse_thr_mailbox, tm_dflags), 621 &dflags, sizeof(dflags)); 622 if (ret != 0) 623 return (P2T(ret)); 624 ret = ps_pread(ta->ph, tcb_addr + ta->thread_off_tmbx + 625 offsetof(struct kse_thr_mailbox, tm_lwp), &lwp, sizeof(lwpid_t)); 626 if (ret != 0) 627 return (P2T(ret)); 628 info->ti_ta_p = th->th_ta; 629 info->ti_tid = th->th_tid; 630 631 if (attrflags & PTHREAD_SCOPE_SYSTEM) { 632 ret = ps_linfo(ta->ph, lwp, &linfo); 633 if (ret == PS_OK) { 634 info->ti_sigmask = linfo.pl_sigmask; 635 info->ti_pending = linfo.pl_siglist; 636 } else 637 return (ret); 638 } else { 639 ret = ps_pread(ta->ph, 640 ta->map[th->th_tid].thr + ta->thread_off_sigmask, 641 &info->ti_sigmask, sizeof(sigset_t)); 642 if (ret) 643 return (ret); 644 ret = ps_pread(ta->ph, 645 ta->map[th->th_tid].thr + ta->thread_off_sigpend, 646 &info->ti_pending, sizeof(sigset_t)); 647 if (ret) 648 return (ret); 649 } 650 651 if (state == ta->thread_state_running) 652 info->ti_state = TD_THR_RUN; 653 else if (state == ta->thread_state_zoombie) 654 info->ti_state = TD_THR_ZOMBIE; 655 else 656 info->ti_state = TD_THR_SLEEP; 657 info->ti_db_suspended = ((dflags & TMDF_SUSPEND) != 0); 658 info->ti_type = TD_THR_USER; 659 return (0); 660 } 661 662 static td_err_e 663 pt_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info) 664 { 665 td_err_e e; 666 667 e = pt_thr_old_get_info(th, (td_old_thrinfo_t *)info); 668 bzero(&info->ti_siginfo, sizeof(info->ti_siginfo)); 669 return (e); 670 } 671 672 #ifdef __i386__ 673 static td_err_e 674 pt_thr_getxmmregs(const td_thrhandle_t *th, char *fxsave) 675 { 676 const td_thragent_t *ta = th->th_ta; 677 struct kse_thr_mailbox tmbx; 678 psaddr_t tcb_addr, tmbx_addr, ptr; 679 lwpid_t lwp; 680 int ret; 681 682 return TD_ERR; 683 684 TDBG_FUNC(); 685 686 ret = pt_validate(th); 687 if (ret) 688 return (ret); 689 690 if (ta->map[th->th_tid].type == PT_LWP) { 691 ret = ps_lgetxmmregs(ta->ph, ta->map[th->th_tid].lwp, fxsave); 692 return (P2T(ret)); 693 } 694 695 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_tcb, 696 &tcb_addr, sizeof(tcb_addr)); 697 if (ret != 0) 698 return (P2T(ret)); 699 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 700 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 701 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 702 if (ret != 0) 703 return (P2T(ret)); 704 if (lwp != 0) { 705 ret = ps_lgetxmmregs(ta->ph, lwp, fxsave); 706 return (P2T(ret)); 707 } 708 709 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 710 if (ret != 0) 711 return (P2T(ret)); 712 pt_ucontext_to_fxsave(&tmbx.tm_context, fxsave); 713 return (0); 714 } 715 #endif 716 717 static td_err_e 718 pt_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregs) 719 { 720 const td_thragent_t *ta = th->th_ta; 721 struct kse_thr_mailbox tmbx; 722 psaddr_t tcb_addr, tmbx_addr, ptr; 723 lwpid_t lwp; 724 int ret; 725 726 TDBG_FUNC(); 727 728 ret = pt_validate(th); 729 if (ret) 730 return (ret); 731 732 if (ta->map[th->th_tid].type == PT_LWP) { 733 ret = ps_lgetfpregs(ta->ph, ta->map[th->th_tid].lwp, fpregs); 734 return (P2T(ret)); 735 } 736 737 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_tcb, 738 &tcb_addr, sizeof(tcb_addr)); 739 if (ret != 0) 740 return (P2T(ret)); 741 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 742 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 743 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 744 if (ret != 0) 745 return (P2T(ret)); 746 if (lwp != 0) { 747 ret = ps_lgetfpregs(ta->ph, lwp, fpregs); 748 return (P2T(ret)); 749 } 750 751 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 752 if (ret != 0) 753 return (P2T(ret)); 754 pt_ucontext_to_fpreg(&tmbx.tm_context, fpregs); 755 return (0); 756 } 757 758 static td_err_e 759 pt_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs) 760 { 761 const td_thragent_t *ta = th->th_ta; 762 struct kse_thr_mailbox tmbx; 763 psaddr_t tcb_addr, tmbx_addr, ptr; 764 lwpid_t lwp; 765 int ret; 766 767 TDBG_FUNC(); 768 769 ret = pt_validate(th); 770 if (ret) 771 return (ret); 772 773 if (ta->map[th->th_tid].type == PT_LWP) { 774 ret = ps_lgetregs(ta->ph, 775 ta->map[th->th_tid].lwp, gregs); 776 return (P2T(ret)); 777 } 778 779 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_tcb, 780 &tcb_addr, sizeof(tcb_addr)); 781 if (ret != 0) 782 return (P2T(ret)); 783 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 784 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 785 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 786 if (ret != 0) 787 return (P2T(ret)); 788 if (lwp != 0) { 789 ret = ps_lgetregs(ta->ph, lwp, gregs); 790 return (P2T(ret)); 791 } 792 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 793 if (ret != 0) 794 return (P2T(ret)); 795 pt_ucontext_to_reg(&tmbx.tm_context, gregs); 796 return (0); 797 } 798 799 #ifdef __i386__ 800 static td_err_e 801 pt_thr_setxmmregs(const td_thrhandle_t *th, const char *fxsave) 802 { 803 const td_thragent_t *ta = th->th_ta; 804 struct kse_thr_mailbox tmbx; 805 psaddr_t tcb_addr, tmbx_addr, ptr; 806 lwpid_t lwp; 807 int ret; 808 809 return TD_ERR; 810 811 TDBG_FUNC(); 812 813 ret = pt_validate(th); 814 if (ret) 815 return (ret); 816 817 if (ta->map[th->th_tid].type == PT_LWP) { 818 ret = ps_lsetxmmregs(ta->ph, ta->map[th->th_tid].lwp, fxsave); 819 return (P2T(ret)); 820 } 821 822 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 823 ta->thread_off_tcb, 824 &tcb_addr, sizeof(tcb_addr)); 825 if (ret != 0) 826 return (P2T(ret)); 827 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 828 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 829 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 830 if (ret != 0) 831 return (P2T(ret)); 832 if (lwp != 0) { 833 ret = ps_lsetxmmregs(ta->ph, lwp, fxsave); 834 return (P2T(ret)); 835 } 836 /* 837 * Read a copy of context, this makes sure that registers 838 * not covered by structure reg won't be clobbered 839 */ 840 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 841 if (ret != 0) 842 return (P2T(ret)); 843 844 pt_fxsave_to_ucontext(fxsave, &tmbx.tm_context); 845 ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 846 return (P2T(ret)); 847 } 848 #endif 849 850 static td_err_e 851 pt_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs) 852 { 853 const td_thragent_t *ta = th->th_ta; 854 struct kse_thr_mailbox tmbx; 855 psaddr_t tcb_addr, tmbx_addr, ptr; 856 lwpid_t lwp; 857 int ret; 858 859 TDBG_FUNC(); 860 861 ret = pt_validate(th); 862 if (ret) 863 return (ret); 864 865 if (ta->map[th->th_tid].type == PT_LWP) { 866 ret = ps_lsetfpregs(ta->ph, ta->map[th->th_tid].lwp, fpregs); 867 return (P2T(ret)); 868 } 869 870 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 871 ta->thread_off_tcb, 872 &tcb_addr, sizeof(tcb_addr)); 873 if (ret != 0) 874 return (P2T(ret)); 875 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 876 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 877 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 878 if (ret != 0) 879 return (P2T(ret)); 880 if (lwp != 0) { 881 ret = ps_lsetfpregs(ta->ph, lwp, fpregs); 882 return (P2T(ret)); 883 } 884 /* 885 * Read a copy of context, this makes sure that registers 886 * not covered by structure reg won't be clobbered 887 */ 888 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 889 if (ret != 0) 890 return (P2T(ret)); 891 892 pt_fpreg_to_ucontext(fpregs, &tmbx.tm_context); 893 ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 894 return (P2T(ret)); 895 } 896 897 static td_err_e 898 pt_thr_setgregs(const td_thrhandle_t *th, const prgregset_t gregs) 899 { 900 const td_thragent_t *ta = th->th_ta; 901 struct kse_thr_mailbox tmbx; 902 psaddr_t tcb_addr, tmbx_addr, ptr; 903 lwpid_t lwp; 904 int ret; 905 906 TDBG_FUNC(); 907 908 ret = pt_validate(th); 909 if (ret) 910 return (ret); 911 912 if (ta->map[th->th_tid].type == PT_LWP) { 913 ret = ps_lsetregs(ta->ph, ta->map[th->th_tid].lwp, gregs); 914 return (P2T(ret)); 915 } 916 917 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 918 ta->thread_off_tcb, 919 &tcb_addr, sizeof(tcb_addr)); 920 if (ret != 0) 921 return (P2T(ret)); 922 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 923 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 924 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 925 if (ret != 0) 926 return (P2T(ret)); 927 if (lwp != 0) { 928 ret = ps_lsetregs(ta->ph, lwp, gregs); 929 return (P2T(ret)); 930 } 931 932 /* 933 * Read a copy of context, make sure that registers 934 * not covered by structure reg won't be clobbered 935 */ 936 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 937 if (ret != 0) 938 return (P2T(ret)); 939 pt_reg_to_ucontext(gregs, &tmbx.tm_context); 940 ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 941 return (P2T(ret)); 942 } 943 944 static td_err_e 945 pt_thr_event_enable(const td_thrhandle_t *th __unused, int en __unused) 946 { 947 TDBG_FUNC(); 948 return (0); 949 } 950 951 static td_err_e 952 pt_thr_set_event(const td_thrhandle_t *th __unused, 953 td_thr_events_t *setp __unused) 954 { 955 TDBG_FUNC(); 956 return (0); 957 } 958 959 static td_err_e 960 pt_thr_clear_event(const td_thrhandle_t *th __unused, 961 td_thr_events_t *setp __unused) 962 { 963 TDBG_FUNC(); 964 return (0); 965 } 966 967 static td_err_e 968 pt_thr_event_getmsg(const td_thrhandle_t *th __unused, 969 td_event_msg_t *msg __unused) 970 { 971 TDBG_FUNC(); 972 return (TD_NOMSG); 973 } 974 975 static td_err_e 976 pt_thr_sstep(const td_thrhandle_t *th, int step) 977 { 978 const td_thragent_t *ta = th->th_ta; 979 struct kse_thr_mailbox tmbx; 980 struct reg regs; 981 psaddr_t tcb_addr, tmbx_addr; 982 uint32_t dflags; 983 lwpid_t lwp; 984 int ret; 985 986 TDBG_FUNC(); 987 988 ret = pt_validate(th); 989 if (ret) 990 return (ret); 991 992 if (ta->map[th->th_tid].type == PT_LWP) 993 return (TD_BADTH); 994 995 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 996 ta->thread_off_tcb, 997 &tcb_addr, sizeof(tcb_addr)); 998 if (ret != 0) 999 return (P2T(ret)); 1000 1001 /* Clear or set single step flag in thread mailbox */ 1002 ret = ps_pread(ta->ph, 1003 tcb_addr + ta->thread_off_tmbx + 1004 offsetof(struct kse_thr_mailbox, tm_dflags), 1005 &dflags, sizeof(uint32_t)); 1006 if (ret != 0) 1007 return (P2T(ret)); 1008 if (step != 0) 1009 dflags |= TMDF_SSTEP; 1010 else 1011 dflags &= ~TMDF_SSTEP; 1012 ret = ps_pwrite(ta->ph, 1013 tcb_addr + ta->thread_off_tmbx + 1014 offsetof(struct kse_thr_mailbox, tm_dflags), 1015 &dflags, sizeof(uint32_t)); 1016 if (ret != 0) 1017 return (P2T(ret)); 1018 /* Get lwp */ 1019 ret = ps_pread(ta->ph, 1020 tcb_addr + ta->thread_off_tmbx + 1021 offsetof(struct kse_thr_mailbox, tm_lwp), 1022 &lwp, sizeof(lwpid_t)); 1023 if (ret != 0) 1024 return (P2T(ret)); 1025 if (lwp != 0) 1026 return (0); 1027 1028 tmbx_addr = tcb_addr + ta->thread_off_tmbx; 1029 /* 1030 * context is in userland, some architectures store 1031 * single step status in registers, we should change 1032 * these registers. 1033 */ 1034 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 1035 if (ret == 0) { 1036 pt_ucontext_to_reg(&tmbx.tm_context, ®s); 1037 /* only write out if it is really changed. */ 1038 if (pt_reg_sstep(®s, step) != 0) { 1039 pt_reg_to_ucontext(®s, &tmbx.tm_context); 1040 ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, 1041 sizeof(tmbx)); 1042 } 1043 } 1044 return (P2T(ret)); 1045 } 1046 1047 static void 1048 pt_unmap_lwp(const td_thragent_t *ta, lwpid_t lwp) 1049 { 1050 int i; 1051 1052 for (i = 0; i < ta->map_len; ++i) { 1053 if (ta->map[i].type == PT_LWP && ta->map[i].lwp == lwp) { 1054 ta->map[i].type = PT_NONE; 1055 return; 1056 } 1057 } 1058 } 1059 1060 static int 1061 pt_validate(const td_thrhandle_t *th) 1062 { 1063 1064 if (th->th_tid < 0 || th->th_tid >= th->th_ta->map_len || 1065 th->th_ta->map[th->th_tid].type == PT_NONE) 1066 return (TD_NOTHR); 1067 return (TD_OK); 1068 } 1069 1070 static td_err_e 1071 pt_thr_tls_get_addr(const td_thrhandle_t *th, psaddr_t _linkmap, size_t offset, 1072 psaddr_t *address) 1073 { 1074 const td_thragent_t *ta = th->th_ta; 1075 psaddr_t dtv_addr, obj_entry, tcb_addr; 1076 int tls_index, ret; 1077 1078 /* linkmap is a member of Obj_Entry */ 1079 obj_entry = _linkmap - ta->thread_off_linkmap; 1080 1081 /* get tlsindex of the object file */ 1082 ret = ps_pread(ta->ph, 1083 obj_entry + ta->thread_off_tlsindex, 1084 &tls_index, sizeof(tls_index)); 1085 if (ret != 0) 1086 return (P2T(ret)); 1087 1088 /* get thread tcb */ 1089 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 1090 ta->thread_off_tcb, 1091 &tcb_addr, sizeof(tcb_addr)); 1092 if (ret != 0) 1093 return (P2T(ret)); 1094 1095 /* get dtv array address */ 1096 ret = ps_pread(ta->ph, tcb_addr + ta->thread_off_dtv, 1097 &dtv_addr, sizeof(dtv_addr)); 1098 if (ret != 0) 1099 return (P2T(ret)); 1100 /* now get the object's tls block base address */ 1101 ret = ps_pread(ta->ph, dtv_addr + sizeof(void *) * (tls_index + 1), 1102 address, sizeof(*address)); 1103 if (ret != 0) 1104 return (P2T(ret)); 1105 1106 *address += offset; 1107 return (TD_OK); 1108 } 1109 1110 static struct ta_ops libpthread_db_ops = { 1111 .to_init = pt_init, 1112 .to_ta_clear_event = pt_ta_clear_event, 1113 .to_ta_delete = pt_ta_delete, 1114 .to_ta_event_addr = pt_ta_event_addr, 1115 .to_ta_event_getmsg = pt_ta_event_getmsg, 1116 .to_ta_map_id2thr = pt_ta_map_id2thr, 1117 .to_ta_map_lwp2thr = pt_ta_map_lwp2thr, 1118 .to_ta_new = pt_ta_new, 1119 .to_ta_set_event = pt_ta_set_event, 1120 .to_ta_thr_iter = pt_ta_thr_iter, 1121 .to_ta_tsd_iter = pt_ta_tsd_iter, 1122 .to_thr_clear_event = pt_thr_clear_event, 1123 .to_thr_dbresume = pt_thr_dbresume, 1124 .to_thr_dbsuspend = pt_thr_dbsuspend, 1125 .to_thr_event_enable = pt_thr_event_enable, 1126 .to_thr_event_getmsg = pt_thr_event_getmsg, 1127 .to_thr_old_get_info = pt_thr_old_get_info, 1128 .to_thr_get_info = pt_thr_get_info, 1129 .to_thr_getfpregs = pt_thr_getfpregs, 1130 .to_thr_getgregs = pt_thr_getgregs, 1131 .to_thr_set_event = pt_thr_set_event, 1132 .to_thr_setfpregs = pt_thr_setfpregs, 1133 .to_thr_setgregs = pt_thr_setgregs, 1134 .to_thr_validate = pt_thr_validate, 1135 .to_thr_tls_get_addr = pt_thr_tls_get_addr, 1136 1137 /* FreeBSD specific extensions. */ 1138 .to_thr_sstep = pt_thr_sstep, 1139 #ifdef __i386__ 1140 .to_thr_getxmmregs = pt_thr_getxmmregs, 1141 .to_thr_setxmmregs = pt_thr_setxmmregs, 1142 #endif 1143 }; 1144 1145 DATA_SET(__ta_ops, libpthread_db_ops); 1146