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