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