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