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