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