1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <stddef.h> 32 #include <unistd.h> 33 #include <thr_uberdata.h> 34 #include <thread_db.h> 35 #include <libc_int.h> 36 37 /* 38 * Private structures. 39 */ 40 41 typedef union { 42 mutex_t lock; 43 rwlock_t rwlock; 44 sema_t semaphore; 45 cond_t condition; 46 } td_so_un_t; 47 48 struct td_thragent { 49 rwlock_t rwlock; 50 struct ps_prochandle *ph_p; 51 int initialized; 52 int sync_tracking; 53 int model; 54 int primary_map; 55 psaddr_t bootstrap_addr; 56 psaddr_t uberdata_addr; 57 psaddr_t tdb_eventmask_addr; 58 psaddr_t tdb_register_sync_addr; 59 psaddr_t tdb_events[TD_MAX_EVENT_NUM - TD_MIN_EVENT_NUM + 1]; 60 psaddr_t hash_table_addr; 61 int hash_size; 62 lwpid_t single_lwpid; 63 psaddr_t single_ulwp_addr; 64 }; 65 66 /* 67 * This is the name of the variable in libc that contains 68 * the uberdata address that we will need. 69 */ 70 #define TD_BOOTSTRAP_NAME "_tdb_bootstrap" 71 /* 72 * This is the actual name of uberdata, used in the event 73 * that tdb_bootstrap has not yet been initialized. 74 */ 75 #define TD_UBERDATA_NAME "_uberdata" 76 /* 77 * The library name should end with ".so.1", but older versions of 78 * dbx expect the unadorned name and malfunction if ".1" is specified. 79 * Unfortunately, if ".1" is not specified, mdb malfunctions when it 80 * is applied to another instance of itself (due to the presence of 81 * /usr/lib/mdb/proc/libc.so). So we try it both ways. 82 */ 83 #define TD_LIBRARY_NAME "libc.so" 84 #define TD_LIBRARY_NAME_1 "libc.so.1" 85 86 td_err_e __td_thr_get_info(td_thrhandle_t *th_p, td_thrinfo_t *ti_p); 87 88 td_err_e __td_ta_thr_iter(td_thragent_t *ta_p, td_thr_iter_f *cb, 89 void *cbdata_p, td_thr_state_e state, int ti_pri, 90 sigset_t *ti_sigmask_p, unsigned ti_user_flags); 91 92 /* 93 * Initialize threads debugging interface. 94 */ 95 #pragma weak td_init = __td_init 96 td_err_e 97 __td_init() 98 { 99 return (TD_OK); 100 } 101 102 /* 103 * This function does nothing, and never did. 104 * But the symbol is in the ABI, so we can't delete it. 105 */ 106 #pragma weak td_log = __td_log 107 void 108 __td_log() 109 { 110 } 111 112 /* 113 * Short-cut to read just the hash table size from the process, 114 * to avoid repeatedly reading the full uberdata structure when 115 * dealing with a single-threaded process. 116 */ 117 static uint_t 118 td_read_hash_size(td_thragent_t *ta_p) 119 { 120 psaddr_t addr; 121 uint_t hash_size; 122 123 switch (ta_p->initialized) { 124 default: /* uninitialized */ 125 return (0); 126 case 1: /* partially initialized */ 127 break; 128 case 2: /* fully initialized */ 129 return (ta_p->hash_size); 130 } 131 132 if (ta_p->model == PR_MODEL_NATIVE) { 133 addr = ta_p->uberdata_addr + offsetof(uberdata_t, hash_size); 134 } else { 135 #if defined(_LP64) && defined(_SYSCALL32) 136 addr = ta_p->uberdata_addr + offsetof(uberdata32_t, hash_size); 137 #else 138 addr = 0; 139 #endif 140 } 141 if (ps_pdread(ta_p->ph_p, addr, &hash_size, sizeof (hash_size)) 142 != PS_OK) 143 return (0); 144 return (hash_size); 145 } 146 147 static td_err_e 148 td_read_uberdata(td_thragent_t *ta_p) 149 { 150 struct ps_prochandle *ph_p = ta_p->ph_p; 151 152 if (ta_p->model == PR_MODEL_NATIVE) { 153 uberdata_t uberdata; 154 155 if (ps_pdread(ph_p, ta_p->uberdata_addr, 156 &uberdata, sizeof (uberdata)) != PS_OK) 157 return (TD_DBERR); 158 ta_p->primary_map = uberdata.primary_map; 159 ta_p->tdb_eventmask_addr = ta_p->uberdata_addr + 160 offsetof(uberdata_t, tdb.tdb_ev_global_mask); 161 ta_p->tdb_register_sync_addr = ta_p->uberdata_addr + 162 offsetof(uberdata_t, uberflags.uf_tdb_register_sync); 163 ta_p->hash_table_addr = (psaddr_t)uberdata.thr_hash_table; 164 ta_p->hash_size = uberdata.hash_size; 165 if (ps_pdread(ph_p, (psaddr_t)uberdata.tdb.tdb_events, 166 ta_p->tdb_events, sizeof (ta_p->tdb_events)) != PS_OK) 167 return (TD_DBERR); 168 169 } else { 170 #if defined(_LP64) && defined(_SYSCALL32) 171 uberdata32_t uberdata; 172 caddr32_t tdb_events[TD_MAX_EVENT_NUM - TD_MIN_EVENT_NUM + 1]; 173 int i; 174 175 if (ps_pdread(ph_p, ta_p->uberdata_addr, 176 &uberdata, sizeof (uberdata)) != PS_OK) 177 return (TD_DBERR); 178 ta_p->primary_map = uberdata.primary_map; 179 ta_p->tdb_eventmask_addr = ta_p->uberdata_addr + 180 offsetof(uberdata32_t, tdb.tdb_ev_global_mask); 181 ta_p->tdb_register_sync_addr = ta_p->uberdata_addr + 182 offsetof(uberdata32_t, uberflags.uf_tdb_register_sync); 183 ta_p->hash_table_addr = (psaddr_t)uberdata.thr_hash_table; 184 ta_p->hash_size = uberdata.hash_size; 185 if (ps_pdread(ph_p, (psaddr_t)uberdata.tdb.tdb_events, 186 tdb_events, sizeof (tdb_events)) != PS_OK) 187 return (TD_DBERR); 188 for (i = 0; i < TD_MAX_EVENT_NUM - TD_MIN_EVENT_NUM + 1; i++) 189 ta_p->tdb_events[i] = tdb_events[i]; 190 #else 191 return (TD_DBERR); 192 #endif 193 } 194 if (ta_p->hash_size != 1) { /* multi-threaded */ 195 ta_p->initialized = 2; 196 ta_p->single_lwpid = 0; 197 ta_p->single_ulwp_addr = NULL; 198 } else { /* single-threaded */ 199 ta_p->initialized = 1; 200 /* 201 * Get the address and lwpid of the single thread/LWP. 202 * It may not be ulwp_one if this is a child of fork1(). 203 */ 204 if (ta_p->model == PR_MODEL_NATIVE) { 205 thr_hash_table_t head; 206 lwpid_t lwpid = 0; 207 208 if (ps_pdread(ph_p, ta_p->hash_table_addr, 209 &head, sizeof (head)) != PS_OK) 210 return (TD_DBERR); 211 if ((psaddr_t)head.hash_bucket == NULL) 212 ta_p->initialized = 0; 213 else if (ps_pdread(ph_p, (psaddr_t)head.hash_bucket + 214 offsetof(ulwp_t, ul_lwpid), 215 &lwpid, sizeof (lwpid)) != PS_OK) 216 return (TD_DBERR); 217 ta_p->single_lwpid = lwpid; 218 ta_p->single_ulwp_addr = (psaddr_t)head.hash_bucket; 219 } else { 220 #if defined(_LP64) && defined(_SYSCALL32) 221 thr_hash_table32_t head; 222 lwpid_t lwpid = 0; 223 224 if (ps_pdread(ph_p, ta_p->hash_table_addr, 225 &head, sizeof (head)) != PS_OK) 226 return (TD_DBERR); 227 if ((psaddr_t)head.hash_bucket == NULL) 228 ta_p->initialized = 0; 229 else if (ps_pdread(ph_p, (psaddr_t)head.hash_bucket + 230 offsetof(ulwp32_t, ul_lwpid), 231 &lwpid, sizeof (lwpid)) != PS_OK) 232 return (TD_DBERR); 233 ta_p->single_lwpid = lwpid; 234 ta_p->single_ulwp_addr = (psaddr_t)head.hash_bucket; 235 #else 236 return (TD_DBERR); 237 #endif 238 } 239 } 240 if (!ta_p->primary_map) 241 ta_p->initialized = 0; 242 return (TD_OK); 243 } 244 245 static td_err_e 246 td_read_bootstrap_data(td_thragent_t *ta_p) 247 { 248 struct ps_prochandle *ph_p = ta_p->ph_p; 249 psaddr_t bootstrap_addr; 250 psaddr_t uberdata_addr; 251 ps_err_e db_return; 252 td_err_e return_val; 253 int do_1; 254 255 switch (ta_p->initialized) { 256 case 2: /* fully initialized */ 257 return (TD_OK); 258 case 1: /* partially initialized */ 259 if (td_read_hash_size(ta_p) == 1) 260 return (TD_OK); 261 return (td_read_uberdata(ta_p)); 262 } 263 264 /* 265 * Uninitialized -- do the startup work. 266 * We set ta_p->initialized to -1 to cut off recursive calls 267 * into libc_db by code in the provider of ps_pglobal_lookup(). 268 */ 269 do_1 = 0; 270 ta_p->initialized = -1; 271 db_return = ps_pglobal_lookup(ph_p, TD_LIBRARY_NAME, 272 TD_BOOTSTRAP_NAME, &bootstrap_addr); 273 if (db_return == PS_NOSYM) { 274 do_1 = 1; 275 db_return = ps_pglobal_lookup(ph_p, TD_LIBRARY_NAME_1, 276 TD_BOOTSTRAP_NAME, &bootstrap_addr); 277 } 278 if (db_return == PS_NOSYM) /* libc is not linked yet */ 279 return (TD_NOLIBTHREAD); 280 if (db_return != PS_OK) 281 return (TD_ERR); 282 db_return = ps_pglobal_lookup(ph_p, 283 do_1? TD_LIBRARY_NAME_1 : TD_LIBRARY_NAME, 284 TD_UBERDATA_NAME, &uberdata_addr); 285 if (db_return == PS_NOSYM) /* libc is not linked yet */ 286 return (TD_NOLIBTHREAD); 287 if (db_return != PS_OK) 288 return (TD_ERR); 289 290 /* 291 * Read the uberdata address into the thread agent structure. 292 */ 293 if (ta_p->model == PR_MODEL_NATIVE) { 294 psaddr_t psaddr; 295 if (ps_pdread(ph_p, bootstrap_addr, 296 &psaddr, sizeof (psaddr)) != PS_OK) 297 return (TD_DBERR); 298 if ((ta_p->bootstrap_addr = psaddr) == NULL) 299 psaddr = uberdata_addr; 300 else if (ps_pdread(ph_p, psaddr, 301 &psaddr, sizeof (psaddr)) != PS_OK) 302 return (TD_DBERR); 303 ta_p->uberdata_addr = psaddr; 304 } else { 305 #if defined(_LP64) && defined(_SYSCALL32) 306 caddr32_t psaddr; 307 if (ps_pdread(ph_p, bootstrap_addr, 308 &psaddr, sizeof (psaddr)) != PS_OK) 309 return (TD_DBERR); 310 if ((ta_p->bootstrap_addr = (psaddr_t)psaddr) == NULL) 311 psaddr = (caddr32_t)uberdata_addr; 312 else if (ps_pdread(ph_p, (psaddr_t)psaddr, 313 &psaddr, sizeof (psaddr)) != PS_OK) 314 return (TD_DBERR); 315 ta_p->uberdata_addr = (psaddr_t)psaddr; 316 #else 317 return (TD_DBERR); 318 #endif /* _SYSCALL32 */ 319 } 320 321 if ((return_val = td_read_uberdata(ta_p)) != TD_OK) 322 return (return_val); 323 if (ta_p->bootstrap_addr == NULL) 324 ta_p->initialized = 0; 325 return (TD_OK); 326 } 327 328 #pragma weak ps_kill 329 #pragma weak ps_lrolltoaddr 330 331 /* 332 * Allocate a new agent process handle ("thread agent"). 333 */ 334 #pragma weak td_ta_new = __td_ta_new 335 td_err_e 336 __td_ta_new(struct ps_prochandle *ph_p, td_thragent_t **ta_pp) 337 { 338 td_thragent_t *ta_p; 339 int model; 340 td_err_e return_val = TD_OK; 341 342 if (ph_p == NULL) 343 return (TD_BADPH); 344 if (ta_pp == NULL) 345 return (TD_ERR); 346 *ta_pp = NULL; 347 if (ps_pstop(ph_p) != PS_OK) 348 return (TD_DBERR); 349 /* 350 * ps_pdmodel might not be defined if this is an older client. 351 * Make it a weak symbol and test if it exists before calling. 352 */ 353 #pragma weak ps_pdmodel 354 if (ps_pdmodel == NULL) { 355 model = PR_MODEL_NATIVE; 356 } else if (ps_pdmodel(ph_p, &model) != PS_OK) { 357 (void) ps_pcontinue(ph_p); 358 return (TD_ERR); 359 } 360 if ((ta_p = malloc(sizeof (*ta_p))) == NULL) { 361 (void) ps_pcontinue(ph_p); 362 return (TD_MALLOC); 363 } 364 365 /* 366 * Initialize the agent process handle. 367 * Pick up the symbol value we need from the target process. 368 */ 369 (void) memset(ta_p, 0, sizeof (*ta_p)); 370 ta_p->ph_p = ph_p; 371 (void) rwlock_init(&ta_p->rwlock, USYNC_THREAD, NULL); 372 ta_p->model = model; 373 return_val = td_read_bootstrap_data(ta_p); 374 375 /* 376 * Because the old libthread_db enabled lock tracking by default, 377 * we must also do it. However, we do it only if the application 378 * provides the ps_kill() and ps_lrolltoaddr() interfaces. 379 * (dbx provides the ps_kill() and ps_lrolltoaddr() interfaces.) 380 */ 381 if (return_val == TD_OK && ps_kill != NULL && ps_lrolltoaddr != NULL) { 382 register_sync_t oldenable; 383 register_sync_t enable = REGISTER_SYNC_ENABLE; 384 psaddr_t psaddr = ta_p->tdb_register_sync_addr; 385 386 if (ps_pdread(ph_p, psaddr, 387 &oldenable, sizeof (oldenable)) != PS_OK) 388 return_val = TD_DBERR; 389 else if (oldenable != REGISTER_SYNC_OFF || 390 ps_pdwrite(ph_p, psaddr, 391 &enable, sizeof (enable)) != PS_OK) { 392 /* 393 * Lock tracking was already enabled or we 394 * failed to enable it, probably because we 395 * are examining a core file. In either case 396 * set the sync_tracking flag non-zero to 397 * indicate that we should not attempt to 398 * disable lock tracking when we delete the 399 * agent process handle in td_ta_delete(). 400 */ 401 ta_p->sync_tracking = 1; 402 } 403 } 404 405 if (return_val == TD_OK) 406 *ta_pp = ta_p; 407 else 408 free(ta_p); 409 410 (void) ps_pcontinue(ph_p); 411 return (return_val); 412 } 413 414 /* 415 * Utility function to grab the readers lock and return the prochandle, 416 * given an agent process handle. Performs standard error checking. 417 * Returns non-NULL with the lock held, or NULL with the lock not held. 418 */ 419 static struct ps_prochandle * 420 ph_lock_ta(td_thragent_t *ta_p, td_err_e *err) 421 { 422 struct ps_prochandle *ph_p = NULL; 423 td_err_e error; 424 425 if (ta_p == NULL || ta_p->initialized == -1) { 426 *err = TD_BADTA; 427 } else if (rw_rdlock(&ta_p->rwlock) != 0) { /* can't happen? */ 428 *err = TD_BADTA; 429 } else if ((ph_p = ta_p->ph_p) == NULL) { 430 (void) rw_unlock(&ta_p->rwlock); 431 *err = TD_BADPH; 432 } else if (ta_p->initialized != 2 && 433 (error = td_read_bootstrap_data(ta_p)) != TD_OK) { 434 (void) rw_unlock(&ta_p->rwlock); 435 ph_p = NULL; 436 *err = error; 437 } else { 438 *err = TD_OK; 439 } 440 441 return (ph_p); 442 } 443 444 /* 445 * Utility function to grab the readers lock and return the prochandle, 446 * given an agent thread handle. Performs standard error checking. 447 * Returns non-NULL with the lock held, or NULL with the lock not held. 448 */ 449 static struct ps_prochandle * 450 ph_lock_th(const td_thrhandle_t *th_p, td_err_e *err) 451 { 452 if (th_p == NULL || th_p->th_unique == NULL) { 453 *err = TD_BADTH; 454 return (NULL); 455 } 456 return (ph_lock_ta(th_p->th_ta_p, err)); 457 } 458 459 /* 460 * Utility function to grab the readers lock and return the prochandle, 461 * given a synchronization object handle. Performs standard error checking. 462 * Returns non-NULL with the lock held, or NULL with the lock not held. 463 */ 464 static struct ps_prochandle * 465 ph_lock_sh(const td_synchandle_t *sh_p, td_err_e *err) 466 { 467 if (sh_p == NULL || sh_p->sh_unique == NULL) { 468 *err = TD_BADSH; 469 return (NULL); 470 } 471 return (ph_lock_ta(sh_p->sh_ta_p, err)); 472 } 473 474 /* 475 * Unlock the agent process handle obtained from ph_lock_*(). 476 */ 477 static void 478 ph_unlock(td_thragent_t *ta_p) 479 { 480 (void) rw_unlock(&ta_p->rwlock); 481 } 482 483 /* 484 * De-allocate an agent process handle, 485 * releasing all related resources. 486 * 487 * XXX -- This is hopelessly broken --- 488 * Storage for thread agent is not deallocated. The prochandle 489 * in the thread agent is set to NULL so that future uses of 490 * the thread agent can be detected and an error value returned. 491 * All functions in the external user interface that make 492 * use of the thread agent are expected 493 * to check for a NULL prochandle in the thread agent. 494 * All such functions are also expected to obtain a 495 * reader lock on the thread agent while it is using it. 496 */ 497 #pragma weak td_ta_delete = __td_ta_delete 498 td_err_e 499 __td_ta_delete(td_thragent_t *ta_p) 500 { 501 struct ps_prochandle *ph_p; 502 503 /* 504 * This is the only place we grab the writer lock. 505 * We are going to NULL out the prochandle. 506 */ 507 if (ta_p == NULL || rw_wrlock(&ta_p->rwlock) != 0) 508 return (TD_BADTA); 509 if ((ph_p = ta_p->ph_p) == NULL) { 510 (void) rw_unlock(&ta_p->rwlock); 511 return (TD_BADPH); 512 } 513 /* 514 * If synch. tracking was disabled when td_ta_new() was called and 515 * if td_ta_sync_tracking_enable() was never called, then disable 516 * synch. tracking (it was enabled by default in td_ta_new()). 517 */ 518 if (ta_p->sync_tracking == 0 && 519 ps_kill != NULL && ps_lrolltoaddr != NULL) { 520 register_sync_t enable = REGISTER_SYNC_DISABLE; 521 522 (void) ps_pdwrite(ph_p, ta_p->tdb_register_sync_addr, 523 &enable, sizeof (enable)); 524 } 525 ta_p->ph_p = NULL; 526 (void) rw_unlock(&ta_p->rwlock); 527 return (TD_OK); 528 } 529 530 /* 531 * Map an agent process handle to a client prochandle. 532 * Currently unused by dbx. 533 */ 534 #pragma weak td_ta_get_ph = __td_ta_get_ph 535 td_err_e 536 __td_ta_get_ph(td_thragent_t *ta_p, struct ps_prochandle **ph_pp) 537 { 538 td_err_e return_val; 539 540 if (ph_pp != NULL) /* protect stupid callers */ 541 *ph_pp = NULL; 542 if (ph_pp == NULL) 543 return (TD_ERR); 544 if ((*ph_pp = ph_lock_ta(ta_p, &return_val)) == NULL) 545 return (return_val); 546 ph_unlock(ta_p); 547 return (TD_OK); 548 } 549 550 /* 551 * Set the process's suggested concurrency level. 552 * This is a no-op in a one-level model. 553 * Currently unused by dbx. 554 */ 555 #pragma weak td_ta_setconcurrency = __td_ta_setconcurrency 556 /* ARGSUSED1 */ 557 td_err_e 558 __td_ta_setconcurrency(const td_thragent_t *ta_p, int level) 559 { 560 if (ta_p == NULL) 561 return (TD_BADTA); 562 if (ta_p->ph_p == NULL) 563 return (TD_BADPH); 564 return (TD_OK); 565 } 566 567 /* 568 * Get the number of threads in the process. 569 */ 570 #pragma weak td_ta_get_nthreads = __td_ta_get_nthreads 571 td_err_e 572 __td_ta_get_nthreads(td_thragent_t *ta_p, int *nthread_p) 573 { 574 struct ps_prochandle *ph_p; 575 td_err_e return_val; 576 int nthreads; 577 int nzombies; 578 psaddr_t nthreads_addr; 579 psaddr_t nzombies_addr; 580 581 if (ta_p->model == PR_MODEL_NATIVE) { 582 nthreads_addr = ta_p->uberdata_addr + 583 offsetof(uberdata_t, nthreads); 584 nzombies_addr = ta_p->uberdata_addr + 585 offsetof(uberdata_t, nzombies); 586 } else { 587 #if defined(_LP64) && defined(_SYSCALL32) 588 nthreads_addr = ta_p->uberdata_addr + 589 offsetof(uberdata32_t, nthreads); 590 nzombies_addr = ta_p->uberdata_addr + 591 offsetof(uberdata32_t, nzombies); 592 #else 593 nthreads_addr = 0; 594 nzombies_addr = 0; 595 #endif /* _SYSCALL32 */ 596 } 597 598 if (nthread_p == NULL) 599 return (TD_ERR); 600 if ((ph_p = ph_lock_ta(ta_p, &return_val)) == NULL) 601 return (return_val); 602 if (ps_pdread(ph_p, nthreads_addr, &nthreads, sizeof (int)) != PS_OK) 603 return_val = TD_DBERR; 604 if (ps_pdread(ph_p, nzombies_addr, &nzombies, sizeof (int)) != PS_OK) 605 return_val = TD_DBERR; 606 ph_unlock(ta_p); 607 if (return_val == TD_OK) 608 *nthread_p = nthreads + nzombies; 609 return (return_val); 610 } 611 612 typedef struct { 613 thread_t tid; 614 int found; 615 td_thrhandle_t th; 616 } td_mapper_param_t; 617 618 /* 619 * Check the value in data against the thread id. 620 * If it matches, return 1 to terminate iterations. 621 * This function is used by td_ta_map_id2thr() to map a tid to a thread handle. 622 */ 623 static int 624 td_mapper_id2thr(td_thrhandle_t *th_p, td_mapper_param_t *data) 625 { 626 td_thrinfo_t ti; 627 628 if (__td_thr_get_info(th_p, &ti) == TD_OK && 629 data->tid == ti.ti_tid) { 630 data->found = 1; 631 data->th = *th_p; 632 return (1); 633 } 634 return (0); 635 } 636 637 /* 638 * Given a thread identifier, return the corresponding thread handle. 639 */ 640 #pragma weak td_ta_map_id2thr = __td_ta_map_id2thr 641 td_err_e 642 __td_ta_map_id2thr(td_thragent_t *ta_p, thread_t tid, 643 td_thrhandle_t *th_p) 644 { 645 td_err_e return_val; 646 td_mapper_param_t data; 647 648 if (th_p != NULL && /* optimize for a single thread */ 649 ta_p != NULL && 650 ta_p->initialized == 1 && 651 (td_read_hash_size(ta_p) == 1 || 652 td_read_uberdata(ta_p) == TD_OK) && 653 ta_p->initialized == 1 && 654 ta_p->single_lwpid == tid) { 655 th_p->th_ta_p = ta_p; 656 if ((th_p->th_unique = ta_p->single_ulwp_addr) == 0) 657 return (TD_NOTHR); 658 return (TD_OK); 659 } 660 661 /* 662 * LOCKING EXCEPTION - Locking is not required here because 663 * the locking and checking will be done in __td_ta_thr_iter. 664 */ 665 666 if (ta_p == NULL) 667 return (TD_BADTA); 668 if (th_p == NULL) 669 return (TD_BADTH); 670 if (tid == 0) 671 return (TD_NOTHR); 672 673 data.tid = tid; 674 data.found = 0; 675 return_val = __td_ta_thr_iter(ta_p, 676 (td_thr_iter_f *)td_mapper_id2thr, (void *)&data, 677 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, 678 TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); 679 if (return_val == TD_OK) { 680 if (data.found == 0) 681 return_val = TD_NOTHR; 682 else 683 *th_p = data.th; 684 } 685 686 return (return_val); 687 } 688 689 /* 690 * Map the address of a synchronization object to a sync. object handle. 691 */ 692 #pragma weak td_ta_map_addr2sync = __td_ta_map_addr2sync 693 td_err_e 694 __td_ta_map_addr2sync(td_thragent_t *ta_p, psaddr_t addr, td_synchandle_t *sh_p) 695 { 696 struct ps_prochandle *ph_p; 697 td_err_e return_val; 698 uint16_t sync_magic; 699 700 if (sh_p == NULL) 701 return (TD_BADSH); 702 if (addr == NULL) 703 return (TD_ERR); 704 if ((ph_p = ph_lock_ta(ta_p, &return_val)) == NULL) 705 return (return_val); 706 /* 707 * Check the magic number of the sync. object to make sure it's valid. 708 * The magic number is at the same offset for all sync. objects. 709 */ 710 if (ps_pdread(ph_p, (psaddr_t)&((mutex_t *)addr)->mutex_magic, 711 &sync_magic, sizeof (sync_magic)) != PS_OK) { 712 ph_unlock(ta_p); 713 return (TD_BADSH); 714 } 715 ph_unlock(ta_p); 716 if (sync_magic != MUTEX_MAGIC && sync_magic != COND_MAGIC && 717 sync_magic != SEMA_MAGIC && sync_magic != RWL_MAGIC) 718 return (TD_BADSH); 719 /* 720 * Just fill in the appropriate fields of the sync. handle. 721 */ 722 sh_p->sh_ta_p = (td_thragent_t *)ta_p; 723 sh_p->sh_unique = addr; 724 return (TD_OK); 725 } 726 727 /* 728 * Iterate over the set of global TSD keys. 729 * The call back function is called with three arguments, 730 * a key, a pointer to the destructor function, and the cbdata pointer. 731 * Currently unused by dbx. 732 */ 733 #pragma weak td_ta_tsd_iter = __td_ta_tsd_iter 734 td_err_e 735 __td_ta_tsd_iter(td_thragent_t *ta_p, td_key_iter_f *cb, void *cbdata_p) 736 { 737 struct ps_prochandle *ph_p; 738 td_err_e return_val; 739 int key; 740 int numkeys; 741 psaddr_t dest_addr; 742 psaddr_t *destructors = NULL; 743 PFrV destructor; 744 745 if (cb == NULL) 746 return (TD_ERR); 747 if ((ph_p = ph_lock_ta(ta_p, &return_val)) == NULL) 748 return (return_val); 749 if (ps_pstop(ph_p) != PS_OK) { 750 ph_unlock(ta_p); 751 return (TD_DBERR); 752 } 753 754 if (ta_p->model == PR_MODEL_NATIVE) { 755 tsd_metadata_t tsdm; 756 757 if (ps_pdread(ph_p, 758 ta_p->uberdata_addr + offsetof(uberdata_t, tsd_metadata), 759 &tsdm, sizeof (tsdm)) != PS_OK) 760 return_val = TD_DBERR; 761 else { 762 numkeys = tsdm.tsdm_nused; 763 dest_addr = (psaddr_t)tsdm.tsdm_destro; 764 if (numkeys > 0) 765 destructors = 766 malloc(numkeys * sizeof (psaddr_t)); 767 } 768 } else { 769 #if defined(_LP64) && defined(_SYSCALL32) 770 tsd_metadata32_t tsdm; 771 772 if (ps_pdread(ph_p, 773 ta_p->uberdata_addr + offsetof(uberdata32_t, tsd_metadata), 774 &tsdm, sizeof (tsdm)) != PS_OK) 775 return_val = TD_DBERR; 776 else { 777 numkeys = tsdm.tsdm_nused; 778 dest_addr = (psaddr_t)tsdm.tsdm_destro; 779 if (numkeys > 0) 780 destructors = 781 malloc(numkeys * sizeof (caddr32_t)); 782 } 783 #else 784 return_val = TD_DBERR; 785 #endif /* _SYSCALL32 */ 786 } 787 788 if (return_val != TD_OK || numkeys <= 0) { 789 (void) ps_pcontinue(ph_p); 790 ph_unlock(ta_p); 791 return (return_val); 792 } 793 794 if (destructors == NULL) 795 return_val = TD_MALLOC; 796 else if (ta_p->model == PR_MODEL_NATIVE) { 797 if (ps_pdread(ph_p, dest_addr, 798 destructors, numkeys * sizeof (psaddr_t)) != PS_OK) 799 return_val = TD_DBERR; 800 else { 801 for (key = 1; key < numkeys; key++) { 802 destructor = (PFrV)destructors[key]; 803 if (destructor != TSD_UNALLOCATED && 804 (*cb)(key, destructor, cbdata_p)) 805 break; 806 } 807 } 808 #if defined(_LP64) && defined(_SYSCALL32) 809 } else { 810 caddr32_t *destructors32 = (caddr32_t *)destructors; 811 caddr32_t destruct32; 812 813 if (ps_pdread(ph_p, dest_addr, 814 destructors32, numkeys * sizeof (caddr32_t)) != PS_OK) 815 return_val = TD_DBERR; 816 else { 817 for (key = 1; key < numkeys; key++) { 818 destruct32 = destructors32[key]; 819 if (destruct32 != (caddr32_t)TSD_UNALLOCATED && 820 (*cb)(key, (PFrV)(uintptr_t)destruct32, 821 cbdata_p)) 822 break; 823 } 824 } 825 #endif /* _SYSCALL32 */ 826 } 827 828 if (destructors) 829 free(destructors); 830 (void) ps_pcontinue(ph_p); 831 ph_unlock(ta_p); 832 return (return_val); 833 } 834 835 int 836 sigequalset(const sigset_t *s1, const sigset_t *s2) 837 { 838 return ( 839 s1->__sigbits[0] == s2->__sigbits[0] && 840 s1->__sigbits[1] == s2->__sigbits[1] && 841 s1->__sigbits[2] == s2->__sigbits[2] && 842 s1->__sigbits[3] == s2->__sigbits[3]); 843 } 844 845 /* 846 * Description: 847 * Iterate over all threads. For each thread call 848 * the function pointed to by "cb" with a pointer 849 * to a thread handle, and a pointer to data which 850 * can be NULL. Only call td_thr_iter_f() on threads 851 * which match the properties of state, ti_pri, 852 * ti_sigmask_p, and ti_user_flags. If cb returns 853 * a non-zero value, terminate iterations. 854 * 855 * Input: 856 * *ta_p - thread agent 857 * *cb - call back function defined by user. 858 * td_thr_iter_f() takes a thread handle and 859 * cbdata_p as a parameter. 860 * cbdata_p - parameter for td_thr_iter_f(). 861 * 862 * state - state of threads of interest. A value of 863 * TD_THR_ANY_STATE from enum td_thr_state_e 864 * does not restrict iterations by state. 865 * ti_pri - lower bound of priorities of threads of 866 * interest. A value of TD_THR_LOWEST_PRIORITY 867 * defined in thread_db.h does not restrict 868 * iterations by priority. A thread with priority 869 * less than ti_pri will NOT be passed to the callback 870 * function. 871 * ti_sigmask_p - signal mask of threads of interest. 872 * A value of TD_SIGNO_MASK defined in thread_db.h 873 * does not restrict iterations by signal mask. 874 * ti_user_flags - user flags of threads of interest. A 875 * value of TD_THR_ANY_USER_FLAGS defined in thread_db.h 876 * does not restrict iterations by user flags. 877 */ 878 #pragma weak td_ta_thr_iter = __td_ta_thr_iter 879 td_err_e 880 __td_ta_thr_iter(td_thragent_t *ta_p, td_thr_iter_f *cb, 881 void *cbdata_p, td_thr_state_e state, int ti_pri, 882 sigset_t *ti_sigmask_p, unsigned ti_user_flags) 883 { 884 struct ps_prochandle *ph_p; 885 psaddr_t first_lwp_addr; 886 psaddr_t first_zombie_addr; 887 psaddr_t curr_lwp_addr; 888 psaddr_t next_lwp_addr; 889 td_thrhandle_t th; 890 ps_err_e db_return; 891 ps_err_e db_return2; 892 td_err_e return_val; 893 894 if (cb == NULL) 895 return (TD_ERR); 896 /* 897 * If state is not within bound, short circuit. 898 */ 899 if (state < TD_THR_ANY_STATE || state > TD_THR_STOPPED_ASLEEP) 900 return (TD_OK); 901 902 if ((ph_p = ph_lock_ta(ta_p, &return_val)) == NULL) 903 return (return_val); 904 if (ps_pstop(ph_p) != PS_OK) { 905 ph_unlock(ta_p); 906 return (TD_DBERR); 907 } 908 909 /* 910 * For each ulwp_t in the circular linked lists pointed 911 * to by "all_lwps" and "all_zombies": 912 * (1) Filter each thread. 913 * (2) Create the thread_object for each thread that passes. 914 * (3) Call the call back function on each thread. 915 */ 916 917 if (ta_p->model == PR_MODEL_NATIVE) { 918 db_return = ps_pdread(ph_p, 919 ta_p->uberdata_addr + offsetof(uberdata_t, all_lwps), 920 &first_lwp_addr, sizeof (first_lwp_addr)); 921 db_return2 = ps_pdread(ph_p, 922 ta_p->uberdata_addr + offsetof(uberdata_t, all_zombies), 923 &first_zombie_addr, sizeof (first_zombie_addr)); 924 } else { 925 #if defined(_LP64) && defined(_SYSCALL32) 926 caddr32_t addr32; 927 928 db_return = ps_pdread(ph_p, 929 ta_p->uberdata_addr + offsetof(uberdata32_t, all_lwps), 930 &addr32, sizeof (addr32)); 931 first_lwp_addr = addr32; 932 db_return2 = ps_pdread(ph_p, 933 ta_p->uberdata_addr + offsetof(uberdata32_t, all_zombies), 934 &addr32, sizeof (addr32)); 935 first_zombie_addr = addr32; 936 #else /* _SYSCALL32 */ 937 db_return = PS_ERR; 938 db_return2 = PS_ERR; 939 #endif /* _SYSCALL32 */ 940 } 941 if (db_return == PS_OK) 942 db_return = db_return2; 943 944 /* 945 * If first_lwp_addr and first_zombie_addr are both NULL, 946 * libc must not yet be initialized or all threads have 947 * exited. Return TD_NOTHR and all will be well. 948 */ 949 if (db_return == PS_OK && 950 first_lwp_addr == NULL && first_zombie_addr == NULL) { 951 (void) ps_pcontinue(ph_p); 952 ph_unlock(ta_p); 953 return (TD_NOTHR); 954 } 955 if (db_return != PS_OK) { 956 (void) ps_pcontinue(ph_p); 957 ph_unlock(ta_p); 958 return (TD_DBERR); 959 } 960 961 /* 962 * Run down the lists of all living and dead lwps. 963 */ 964 if (first_lwp_addr == NULL) 965 first_lwp_addr = first_zombie_addr; 966 curr_lwp_addr = first_lwp_addr; 967 for (;;) { 968 td_thr_state_e ts_state; 969 int userpri; 970 unsigned userflags; 971 sigset_t mask; 972 973 /* 974 * Read the ulwp struct. 975 */ 976 if (ta_p->model == PR_MODEL_NATIVE) { 977 ulwp_t ulwp; 978 979 if (ps_pdread(ph_p, curr_lwp_addr, 980 &ulwp, sizeof (ulwp)) != PS_OK && 981 ((void) memset(&ulwp, 0, sizeof (ulwp)), 982 ps_pdread(ph_p, curr_lwp_addr, 983 &ulwp, REPLACEMENT_SIZE)) != PS_OK) { 984 return_val = TD_DBERR; 985 break; 986 } 987 next_lwp_addr = (psaddr_t)ulwp.ul_forw; 988 989 ts_state = ulwp.ul_dead? TD_THR_ZOMBIE : 990 ulwp.ul_stop? TD_THR_STOPPED : 991 ulwp.ul_wchan? TD_THR_SLEEP : 992 TD_THR_ACTIVE; 993 userpri = ulwp.ul_pri; 994 userflags = ulwp.ul_usropts; 995 if (ulwp.ul_dead) 996 (void) sigemptyset(&mask); 997 else 998 mask = *(sigset_t *)&ulwp.ul_sigmask; 999 } else { 1000 #if defined(_LP64) && defined(_SYSCALL32) 1001 ulwp32_t ulwp; 1002 1003 if (ps_pdread(ph_p, curr_lwp_addr, 1004 &ulwp, sizeof (ulwp)) != PS_OK && 1005 ((void) memset(&ulwp, 0, sizeof (ulwp)), 1006 ps_pdread(ph_p, curr_lwp_addr, 1007 &ulwp, REPLACEMENT_SIZE32)) != PS_OK) { 1008 return_val = TD_DBERR; 1009 break; 1010 } 1011 next_lwp_addr = (psaddr_t)ulwp.ul_forw; 1012 1013 ts_state = ulwp.ul_dead? TD_THR_ZOMBIE : 1014 ulwp.ul_stop? TD_THR_STOPPED : 1015 ulwp.ul_wchan? TD_THR_SLEEP : 1016 TD_THR_ACTIVE; 1017 userpri = ulwp.ul_pri; 1018 userflags = ulwp.ul_usropts; 1019 if (ulwp.ul_dead) 1020 (void) sigemptyset(&mask); 1021 else 1022 mask = *(sigset_t *)&ulwp.ul_sigmask; 1023 #else /* _SYSCALL32 */ 1024 return_val = TD_ERR; 1025 break; 1026 #endif /* _SYSCALL32 */ 1027 } 1028 1029 /* 1030 * Filter on state, priority, sigmask, and user flags. 1031 */ 1032 1033 if ((state != ts_state) && 1034 (state != TD_THR_ANY_STATE)) 1035 goto advance; 1036 1037 if (ti_pri > userpri) 1038 goto advance; 1039 1040 if (ti_sigmask_p != TD_SIGNO_MASK && 1041 !sigequalset(ti_sigmask_p, &mask)) 1042 goto advance; 1043 1044 if (ti_user_flags != userflags && 1045 ti_user_flags != (unsigned)TD_THR_ANY_USER_FLAGS) 1046 goto advance; 1047 1048 /* 1049 * Call back - break if the return 1050 * from the call back is non-zero. 1051 */ 1052 th.th_ta_p = (td_thragent_t *)ta_p; 1053 th.th_unique = curr_lwp_addr; 1054 if ((*cb)(&th, cbdata_p)) 1055 break; 1056 1057 advance: 1058 if ((curr_lwp_addr = next_lwp_addr) == first_lwp_addr) { 1059 /* 1060 * Switch to the zombie list, unless it is NULL 1061 * or we have already been doing the zombie list, 1062 * in which case terminate the loop. 1063 */ 1064 if (first_zombie_addr == NULL || 1065 first_lwp_addr == first_zombie_addr) 1066 break; 1067 curr_lwp_addr = first_lwp_addr = first_zombie_addr; 1068 } 1069 } 1070 1071 (void) ps_pcontinue(ph_p); 1072 ph_unlock(ta_p); 1073 return (return_val); 1074 } 1075 1076 /* 1077 * Enable or disable process synchronization object tracking. 1078 * Currently unused by dbx. 1079 */ 1080 #pragma weak td_ta_sync_tracking_enable = __td_ta_sync_tracking_enable 1081 td_err_e 1082 __td_ta_sync_tracking_enable(td_thragent_t *ta_p, int onoff) 1083 { 1084 struct ps_prochandle *ph_p; 1085 td_err_e return_val; 1086 register_sync_t enable; 1087 1088 if ((ph_p = ph_lock_ta(ta_p, &return_val)) == NULL) 1089 return (return_val); 1090 /* 1091 * Values of tdb_register_sync in the victim process: 1092 * REGISTER_SYNC_ENABLE enables registration of synch objects 1093 * REGISTER_SYNC_DISABLE disables registration of synch objects 1094 * These cause the table to be cleared and tdb_register_sync set to: 1095 * REGISTER_SYNC_ON registration in effect 1096 * REGISTER_SYNC_OFF registration not in effect 1097 */ 1098 enable = onoff? REGISTER_SYNC_ENABLE : REGISTER_SYNC_DISABLE; 1099 if (ps_pdwrite(ph_p, ta_p->tdb_register_sync_addr, 1100 &enable, sizeof (enable)) != PS_OK) 1101 return_val = TD_DBERR; 1102 /* 1103 * Remember that this interface was called (see td_ta_delete()). 1104 */ 1105 ta_p->sync_tracking = 1; 1106 ph_unlock(ta_p); 1107 return (return_val); 1108 } 1109 1110 /* 1111 * Iterate over all known synchronization variables. 1112 * It is very possible that the list generated is incomplete, 1113 * because the iterator can only find synchronization variables 1114 * that have been registered by the process since synchronization 1115 * object registration was enabled. 1116 * The call back function cb is called for each synchronization 1117 * variable with two arguments: a pointer to the synchronization 1118 * handle and the passed-in argument cbdata. 1119 * If cb returns a non-zero value, iterations are terminated. 1120 */ 1121 #pragma weak td_ta_sync_iter = __td_ta_sync_iter 1122 td_err_e 1123 __td_ta_sync_iter(td_thragent_t *ta_p, td_sync_iter_f *cb, void *cbdata) 1124 { 1125 struct ps_prochandle *ph_p; 1126 td_err_e return_val; 1127 int i; 1128 register_sync_t enable; 1129 psaddr_t next_desc; 1130 tdb_sync_stats_t sync_stats; 1131 td_synchandle_t synchandle; 1132 psaddr_t psaddr; 1133 void *vaddr; 1134 uint64_t *sync_addr_hash = NULL; 1135 1136 if (cb == NULL) 1137 return (TD_ERR); 1138 if ((ph_p = ph_lock_ta(ta_p, &return_val)) == NULL) 1139 return (return_val); 1140 if (ps_pstop(ph_p) != PS_OK) { 1141 ph_unlock(ta_p); 1142 return (TD_DBERR); 1143 } 1144 if (ps_pdread(ph_p, ta_p->tdb_register_sync_addr, 1145 &enable, sizeof (enable)) != PS_OK) { 1146 return_val = TD_DBERR; 1147 goto out; 1148 } 1149 if (enable != REGISTER_SYNC_ON) 1150 goto out; 1151 1152 /* 1153 * First read the hash table. 1154 * The hash table is large; allocate with mmap(). 1155 */ 1156 if ((vaddr = mmap(NULL, TDB_HASH_SIZE * sizeof (uint64_t), 1157 PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, (off_t)0)) 1158 == MAP_FAILED) { 1159 return_val = TD_MALLOC; 1160 goto out; 1161 } 1162 sync_addr_hash = vaddr; 1163 1164 if (ta_p->model == PR_MODEL_NATIVE) { 1165 if (ps_pdread(ph_p, ta_p->uberdata_addr + 1166 offsetof(uberdata_t, tdb.tdb_sync_addr_hash), 1167 &psaddr, sizeof (&psaddr)) != PS_OK) { 1168 return_val = TD_DBERR; 1169 goto out; 1170 } 1171 } else { 1172 #ifdef _SYSCALL32 1173 caddr32_t addr; 1174 1175 if (ps_pdread(ph_p, ta_p->uberdata_addr + 1176 offsetof(uberdata32_t, tdb.tdb_sync_addr_hash), 1177 &addr, sizeof (addr)) != PS_OK) { 1178 return_val = TD_DBERR; 1179 goto out; 1180 } 1181 psaddr = addr; 1182 #else 1183 return_val = TD_ERR; 1184 goto out; 1185 #endif /* _SYSCALL32 */ 1186 } 1187 1188 if (psaddr == NULL) 1189 goto out; 1190 if (ps_pdread(ph_p, psaddr, sync_addr_hash, 1191 TDB_HASH_SIZE * sizeof (uint64_t)) != PS_OK) { 1192 return_val = TD_DBERR; 1193 goto out; 1194 } 1195 1196 /* 1197 * Now scan the hash table. 1198 */ 1199 for (i = 0; i < TDB_HASH_SIZE; i++) { 1200 for (next_desc = (psaddr_t)sync_addr_hash[i]; 1201 next_desc != NULL; 1202 next_desc = (psaddr_t)sync_stats.next) { 1203 if (ps_pdread(ph_p, next_desc, 1204 &sync_stats, sizeof (sync_stats)) != PS_OK) { 1205 return_val = TD_DBERR; 1206 goto out; 1207 } 1208 if (sync_stats.un.type == TDB_NONE) { 1209 /* not registered since registration enabled */ 1210 continue; 1211 } 1212 synchandle.sh_ta_p = ta_p; 1213 synchandle.sh_unique = (psaddr_t)sync_stats.sync_addr; 1214 if ((*cb)(&synchandle, cbdata) != 0) 1215 goto out; 1216 } 1217 } 1218 1219 out: 1220 if (sync_addr_hash != NULL) 1221 (void) munmap((void *)sync_addr_hash, 1222 TDB_HASH_SIZE * sizeof (uint64_t)); 1223 (void) ps_pcontinue(ph_p); 1224 ph_unlock(ta_p); 1225 return (return_val); 1226 } 1227 1228 /* 1229 * Enable process statistics collection. 1230 */ 1231 #pragma weak td_ta_enable_stats = __td_ta_enable_stats 1232 /* ARGSUSED */ 1233 td_err_e 1234 __td_ta_enable_stats(const td_thragent_t *ta_p, int onoff) 1235 { 1236 return (TD_NOCAPAB); 1237 } 1238 1239 /* 1240 * Reset process statistics. 1241 */ 1242 #pragma weak td_ta_reset_stats = __td_ta_reset_stats 1243 /* ARGSUSED */ 1244 td_err_e 1245 __td_ta_reset_stats(const td_thragent_t *ta_p) 1246 { 1247 return (TD_NOCAPAB); 1248 } 1249 1250 /* 1251 * Read process statistics. 1252 */ 1253 #pragma weak td_ta_get_stats = __td_ta_get_stats 1254 /* ARGSUSED */ 1255 td_err_e 1256 __td_ta_get_stats(const td_thragent_t *ta_p, td_ta_stats_t *tstats) 1257 { 1258 return (TD_NOCAPAB); 1259 } 1260 1261 /* 1262 * Transfer information from lwp struct to thread information struct. 1263 * XXX -- lots of this needs cleaning up. 1264 */ 1265 static void 1266 td_thr2to(td_thragent_t *ta_p, psaddr_t ts_addr, 1267 ulwp_t *ulwp, td_thrinfo_t *ti_p) 1268 { 1269 lwpid_t lwpid; 1270 1271 if ((lwpid = ulwp->ul_lwpid) == 0) 1272 lwpid = 1; 1273 (void) memset(ti_p, 0, sizeof (*ti_p)); 1274 ti_p->ti_ta_p = ta_p; 1275 ti_p->ti_user_flags = ulwp->ul_usropts; 1276 ti_p->ti_tid = lwpid; 1277 ti_p->ti_exitval = ulwp->ul_rval; 1278 ti_p->ti_startfunc = (psaddr_t)ulwp->ul_startpc; 1279 if (!ulwp->ul_dead) { 1280 /* 1281 * The bloody fools got this backwards! 1282 */ 1283 ti_p->ti_stkbase = (psaddr_t)ulwp->ul_stktop; 1284 ti_p->ti_stksize = ulwp->ul_stksiz; 1285 } 1286 ti_p->ti_ro_area = ts_addr; 1287 ti_p->ti_ro_size = ulwp->ul_replace? 1288 REPLACEMENT_SIZE : sizeof (ulwp_t); 1289 ti_p->ti_state = ulwp->ul_dead? TD_THR_ZOMBIE : 1290 ulwp->ul_stop? TD_THR_STOPPED : 1291 ulwp->ul_wchan? TD_THR_SLEEP : 1292 TD_THR_ACTIVE; 1293 ti_p->ti_db_suspended = 0; 1294 ti_p->ti_type = TD_THR_USER; 1295 ti_p->ti_sp = ulwp->ul_sp; 1296 ti_p->ti_flags = 0; 1297 ti_p->ti_pri = ulwp->ul_pri; 1298 ti_p->ti_lid = lwpid; 1299 if (!ulwp->ul_dead) 1300 ti_p->ti_sigmask = ulwp->ul_sigmask; 1301 ti_p->ti_traceme = 0; 1302 ti_p->ti_preemptflag = 0; 1303 ti_p->ti_pirecflag = 0; 1304 (void) sigemptyset(&ti_p->ti_pending); 1305 ti_p->ti_events = ulwp->ul_td_evbuf.eventmask; 1306 } 1307 1308 #if defined(_LP64) && defined(_SYSCALL32) 1309 static void 1310 td_thr2to32(td_thragent_t *ta_p, psaddr_t ts_addr, 1311 ulwp32_t *ulwp, td_thrinfo_t *ti_p) 1312 { 1313 lwpid_t lwpid; 1314 1315 if ((lwpid = ulwp->ul_lwpid) == 0) 1316 lwpid = 1; 1317 (void) memset(ti_p, 0, sizeof (*ti_p)); 1318 ti_p->ti_ta_p = ta_p; 1319 ti_p->ti_user_flags = ulwp->ul_usropts; 1320 ti_p->ti_tid = lwpid; 1321 ti_p->ti_exitval = (void *)(uintptr_t)ulwp->ul_rval; 1322 ti_p->ti_startfunc = (psaddr_t)ulwp->ul_startpc; 1323 if (!ulwp->ul_dead) { 1324 /* 1325 * The bloody fools got this backwards! 1326 */ 1327 ti_p->ti_stkbase = (psaddr_t)ulwp->ul_stktop; 1328 ti_p->ti_stksize = ulwp->ul_stksiz; 1329 } 1330 ti_p->ti_ro_area = ts_addr; 1331 ti_p->ti_ro_size = ulwp->ul_replace? 1332 REPLACEMENT_SIZE32 : sizeof (ulwp32_t); 1333 ti_p->ti_state = ulwp->ul_dead? TD_THR_ZOMBIE : 1334 ulwp->ul_stop? TD_THR_STOPPED : 1335 ulwp->ul_wchan? TD_THR_SLEEP : 1336 TD_THR_ACTIVE; 1337 ti_p->ti_db_suspended = 0; 1338 ti_p->ti_type = TD_THR_USER; 1339 ti_p->ti_sp = (uint32_t)ulwp->ul_sp; 1340 ti_p->ti_flags = 0; 1341 ti_p->ti_pri = ulwp->ul_pri; 1342 ti_p->ti_lid = lwpid; 1343 if (!ulwp->ul_dead) 1344 ti_p->ti_sigmask = *(sigset_t *)&ulwp->ul_sigmask; 1345 ti_p->ti_traceme = 0; 1346 ti_p->ti_preemptflag = 0; 1347 ti_p->ti_pirecflag = 0; 1348 (void) sigemptyset(&ti_p->ti_pending); 1349 ti_p->ti_events = ulwp->ul_td_evbuf.eventmask; 1350 } 1351 #endif /* _SYSCALL32 */ 1352 1353 /* 1354 * Get thread information. 1355 */ 1356 #pragma weak td_thr_get_info = __td_thr_get_info 1357 td_err_e 1358 __td_thr_get_info(td_thrhandle_t *th_p, td_thrinfo_t *ti_p) 1359 { 1360 struct ps_prochandle *ph_p; 1361 td_thragent_t *ta_p; 1362 td_err_e return_val; 1363 psaddr_t psaddr; 1364 1365 if (ti_p == NULL) 1366 return (TD_ERR); 1367 (void) memset(ti_p, NULL, sizeof (*ti_p)); 1368 1369 if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL) 1370 return (return_val); 1371 ta_p = th_p->th_ta_p; 1372 if (ps_pstop(ph_p) != PS_OK) { 1373 ph_unlock(ta_p); 1374 return (TD_DBERR); 1375 } 1376 1377 /* 1378 * Read the ulwp struct from the process. 1379 * Transfer the ulwp struct to the thread information struct. 1380 */ 1381 psaddr = th_p->th_unique; 1382 if (ta_p->model == PR_MODEL_NATIVE) { 1383 ulwp_t ulwp; 1384 1385 if (ps_pdread(ph_p, psaddr, &ulwp, sizeof (ulwp)) != PS_OK && 1386 ((void) memset(&ulwp, 0, sizeof (ulwp)), 1387 ps_pdread(ph_p, psaddr, &ulwp, REPLACEMENT_SIZE)) != PS_OK) 1388 return_val = TD_DBERR; 1389 else 1390 td_thr2to(ta_p, psaddr, &ulwp, ti_p); 1391 } else { 1392 #if defined(_LP64) && defined(_SYSCALL32) 1393 ulwp32_t ulwp; 1394 1395 if (ps_pdread(ph_p, psaddr, &ulwp, sizeof (ulwp)) != PS_OK && 1396 ((void) memset(&ulwp, 0, sizeof (ulwp)), 1397 ps_pdread(ph_p, psaddr, &ulwp, REPLACEMENT_SIZE32)) != 1398 PS_OK) 1399 return_val = TD_DBERR; 1400 else 1401 td_thr2to32(ta_p, psaddr, &ulwp, ti_p); 1402 #else 1403 return_val = TD_ERR; 1404 #endif /* _SYSCALL32 */ 1405 } 1406 1407 (void) ps_pcontinue(ph_p); 1408 ph_unlock(ta_p); 1409 return (return_val); 1410 } 1411 1412 /* 1413 * Given a process and an event number, return information about 1414 * an address in the process or at which a breakpoint can be set 1415 * to monitor the event. 1416 */ 1417 #pragma weak td_ta_event_addr = __td_ta_event_addr 1418 td_err_e 1419 __td_ta_event_addr(td_thragent_t *ta_p, td_event_e event, td_notify_t *notify_p) 1420 { 1421 if (ta_p == NULL) 1422 return (TD_BADTA); 1423 if (event < TD_MIN_EVENT_NUM || event > TD_MAX_EVENT_NUM) 1424 return (TD_NOEVENT); 1425 if (notify_p == NULL) 1426 return (TD_ERR); 1427 1428 notify_p->type = NOTIFY_BPT; 1429 notify_p->u.bptaddr = ta_p->tdb_events[event - TD_MIN_EVENT_NUM]; 1430 1431 return (TD_OK); 1432 } 1433 1434 /* 1435 * Add the events in eventset 2 to eventset 1. 1436 */ 1437 static void 1438 eventsetaddset(td_thr_events_t *event1_p, td_thr_events_t *event2_p) 1439 { 1440 int i; 1441 1442 for (i = 0; i < TD_EVENTSIZE; i++) 1443 event1_p->event_bits[i] |= event2_p->event_bits[i]; 1444 } 1445 1446 /* 1447 * Delete the events in eventset 2 from eventset 1. 1448 */ 1449 static void 1450 eventsetdelset(td_thr_events_t *event1_p, td_thr_events_t *event2_p) 1451 { 1452 int i; 1453 1454 for (i = 0; i < TD_EVENTSIZE; i++) 1455 event1_p->event_bits[i] &= ~event2_p->event_bits[i]; 1456 } 1457 1458 /* 1459 * Either add or delete the given event set from a thread's event mask. 1460 */ 1461 static td_err_e 1462 mod_eventset(td_thrhandle_t *th_p, td_thr_events_t *events, int onoff) 1463 { 1464 struct ps_prochandle *ph_p; 1465 td_err_e return_val = TD_OK; 1466 char enable; 1467 td_thr_events_t evset; 1468 psaddr_t psaddr_evset; 1469 psaddr_t psaddr_enab; 1470 1471 if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL) 1472 return (return_val); 1473 if (th_p->th_ta_p->model == PR_MODEL_NATIVE) { 1474 ulwp_t *ulwp = (ulwp_t *)th_p->th_unique; 1475 psaddr_evset = (psaddr_t)&ulwp->ul_td_evbuf.eventmask; 1476 psaddr_enab = (psaddr_t)&ulwp->ul_td_events_enable; 1477 } else { 1478 #if defined(_LP64) && defined(_SYSCALL32) 1479 ulwp32_t *ulwp = (ulwp32_t *)th_p->th_unique; 1480 psaddr_evset = (psaddr_t)&ulwp->ul_td_evbuf.eventmask; 1481 psaddr_enab = (psaddr_t)&ulwp->ul_td_events_enable; 1482 #else 1483 ph_unlock(th_p->th_ta_p); 1484 return (TD_ERR); 1485 #endif /* _SYSCALL32 */ 1486 } 1487 if (ps_pstop(ph_p) != PS_OK) { 1488 ph_unlock(th_p->th_ta_p); 1489 return (TD_DBERR); 1490 } 1491 1492 if (ps_pdread(ph_p, psaddr_evset, &evset, sizeof (evset)) != PS_OK) 1493 return_val = TD_DBERR; 1494 else { 1495 if (onoff) 1496 eventsetaddset(&evset, events); 1497 else 1498 eventsetdelset(&evset, events); 1499 if (ps_pdwrite(ph_p, psaddr_evset, &evset, sizeof (evset)) 1500 != PS_OK) 1501 return_val = TD_DBERR; 1502 else { 1503 enable = 0; 1504 if (td_eventismember(&evset, TD_EVENTS_ENABLE)) 1505 enable = 1; 1506 if (ps_pdwrite(ph_p, psaddr_enab, 1507 &enable, sizeof (enable)) != PS_OK) 1508 return_val = TD_DBERR; 1509 } 1510 } 1511 1512 (void) ps_pcontinue(ph_p); 1513 ph_unlock(th_p->th_ta_p); 1514 return (return_val); 1515 } 1516 1517 /* 1518 * Enable or disable tracing for a given thread. Tracing 1519 * is filtered based on the event mask of each thread. Tracing 1520 * can be turned on/off for the thread without changing thread 1521 * event mask. 1522 * Currently unused by dbx. 1523 */ 1524 #pragma weak td_thr_event_enable = __td_thr_event_enable 1525 td_err_e 1526 __td_thr_event_enable(td_thrhandle_t *th_p, int onoff) 1527 { 1528 td_thr_events_t evset; 1529 1530 td_event_emptyset(&evset); 1531 td_event_addset(&evset, TD_EVENTS_ENABLE); 1532 return (mod_eventset(th_p, &evset, onoff)); 1533 } 1534 1535 /* 1536 * Set event mask to enable event. event is turned on in 1537 * event mask for thread. If a thread encounters an event 1538 * for which its event mask is on, notification will be sent 1539 * to the debugger. 1540 * Addresses for each event are provided to the 1541 * debugger. It is assumed that a breakpoint of some type will 1542 * be placed at that address. If the event mask for the thread 1543 * is on, the instruction at the address will be executed. 1544 * Otherwise, the instruction will be skipped. 1545 */ 1546 #pragma weak td_thr_set_event = __td_thr_set_event 1547 td_err_e 1548 __td_thr_set_event(td_thrhandle_t *th_p, td_thr_events_t *events) 1549 { 1550 return (mod_eventset(th_p, events, 1)); 1551 } 1552 1553 /* 1554 * Enable or disable a set of events in the process-global event mask, 1555 * depending on the value of onoff. 1556 */ 1557 static td_err_e 1558 td_ta_mod_event(td_thragent_t *ta_p, td_thr_events_t *events, int onoff) 1559 { 1560 struct ps_prochandle *ph_p; 1561 td_thr_events_t targ_eventset; 1562 td_err_e return_val; 1563 1564 if ((ph_p = ph_lock_ta(ta_p, &return_val)) == NULL) 1565 return (return_val); 1566 if (ps_pstop(ph_p) != PS_OK) { 1567 ph_unlock(ta_p); 1568 return (TD_DBERR); 1569 } 1570 if (ps_pdread(ph_p, ta_p->tdb_eventmask_addr, 1571 &targ_eventset, sizeof (targ_eventset)) != PS_OK) 1572 return_val = TD_DBERR; 1573 else { 1574 if (onoff) 1575 eventsetaddset(&targ_eventset, events); 1576 else 1577 eventsetdelset(&targ_eventset, events); 1578 if (ps_pdwrite(ph_p, ta_p->tdb_eventmask_addr, 1579 &targ_eventset, sizeof (targ_eventset)) != PS_OK) 1580 return_val = TD_DBERR; 1581 } 1582 (void) ps_pcontinue(ph_p); 1583 ph_unlock(ta_p); 1584 return (return_val); 1585 } 1586 1587 /* 1588 * Enable a set of events in the process-global event mask. 1589 */ 1590 #pragma weak td_ta_set_event = __td_ta_set_event 1591 td_err_e 1592 __td_ta_set_event(td_thragent_t *ta_p, td_thr_events_t *events) 1593 { 1594 return (td_ta_mod_event(ta_p, events, 1)); 1595 } 1596 1597 /* 1598 * Set event mask to disable the given event set; these events are cleared 1599 * from the event mask of the thread. Events that occur for a thread 1600 * with the event masked off will not cause notification to be 1601 * sent to the debugger (see td_thr_set_event for fuller description). 1602 */ 1603 #pragma weak td_thr_clear_event = __td_thr_clear_event 1604 td_err_e 1605 __td_thr_clear_event(td_thrhandle_t *th_p, td_thr_events_t *events) 1606 { 1607 return (mod_eventset(th_p, events, 0)); 1608 } 1609 1610 /* 1611 * Disable a set of events in the process-global event mask. 1612 */ 1613 #pragma weak td_ta_clear_event = __td_ta_clear_event 1614 td_err_e 1615 __td_ta_clear_event(td_thragent_t *ta_p, td_thr_events_t *events) 1616 { 1617 return (td_ta_mod_event(ta_p, events, 0)); 1618 } 1619 1620 /* 1621 * This function returns the most recent event message, if any, 1622 * associated with a thread. Given a thread handle, return the message 1623 * corresponding to the event encountered by the thread. Only one 1624 * message per thread is saved. Messages from earlier events are lost 1625 * when later events occur. 1626 */ 1627 #pragma weak td_thr_event_getmsg = __td_thr_event_getmsg 1628 td_err_e 1629 __td_thr_event_getmsg(td_thrhandle_t *th_p, td_event_msg_t *msg) 1630 { 1631 struct ps_prochandle *ph_p; 1632 td_err_e return_val = TD_OK; 1633 psaddr_t psaddr; 1634 1635 if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL) 1636 return (return_val); 1637 if (ps_pstop(ph_p) != PS_OK) { 1638 ph_unlock(th_p->th_ta_p); 1639 return (TD_BADTA); 1640 } 1641 if (th_p->th_ta_p->model == PR_MODEL_NATIVE) { 1642 ulwp_t *ulwp = (ulwp_t *)th_p->th_unique; 1643 td_evbuf_t evbuf; 1644 1645 psaddr = (psaddr_t)&ulwp->ul_td_evbuf; 1646 if (ps_pdread(ph_p, psaddr, &evbuf, sizeof (evbuf)) != PS_OK) { 1647 return_val = TD_DBERR; 1648 } else if (evbuf.eventnum == TD_EVENT_NONE) { 1649 return_val = TD_NOEVENT; 1650 } else { 1651 msg->event = evbuf.eventnum; 1652 msg->th_p = (td_thrhandle_t *)th_p; 1653 msg->msg.data = (uintptr_t)evbuf.eventdata; 1654 /* "Consume" the message */ 1655 evbuf.eventnum = TD_EVENT_NONE; 1656 evbuf.eventdata = NULL; 1657 if (ps_pdwrite(ph_p, psaddr, &evbuf, sizeof (evbuf)) 1658 != PS_OK) 1659 return_val = TD_DBERR; 1660 } 1661 } else { 1662 #if defined(_LP64) && defined(_SYSCALL32) 1663 ulwp32_t *ulwp = (ulwp32_t *)th_p->th_unique; 1664 td_evbuf32_t evbuf; 1665 1666 psaddr = (psaddr_t)&ulwp->ul_td_evbuf; 1667 if (ps_pdread(ph_p, psaddr, &evbuf, sizeof (evbuf)) != PS_OK) { 1668 return_val = TD_DBERR; 1669 } else if (evbuf.eventnum == TD_EVENT_NONE) { 1670 return_val = TD_NOEVENT; 1671 } else { 1672 msg->event = evbuf.eventnum; 1673 msg->th_p = (td_thrhandle_t *)th_p; 1674 msg->msg.data = (uintptr_t)evbuf.eventdata; 1675 /* "Consume" the message */ 1676 evbuf.eventnum = TD_EVENT_NONE; 1677 evbuf.eventdata = NULL; 1678 if (ps_pdwrite(ph_p, psaddr, &evbuf, sizeof (evbuf)) 1679 != PS_OK) 1680 return_val = TD_DBERR; 1681 } 1682 #else 1683 return_val = TD_ERR; 1684 #endif /* _SYSCALL32 */ 1685 } 1686 1687 (void) ps_pcontinue(ph_p); 1688 ph_unlock(th_p->th_ta_p); 1689 return (return_val); 1690 } 1691 1692 /* 1693 * The callback function td_ta_event_getmsg uses when looking for 1694 * a thread with an event. A thin wrapper around td_thr_event_getmsg. 1695 */ 1696 static int 1697 event_msg_cb(const td_thrhandle_t *th_p, void *arg) 1698 { 1699 static td_thrhandle_t th; 1700 td_event_msg_t *msg = arg; 1701 1702 if (__td_thr_event_getmsg((td_thrhandle_t *)th_p, msg) == TD_OK) { 1703 /* 1704 * Got an event, stop iterating. 1705 * 1706 * Because of past mistakes in interface definition, 1707 * we are forced to pass back a static local variable 1708 * for the thread handle because th_p is a pointer 1709 * to a local variable in __td_ta_thr_iter(). 1710 * Grr... 1711 */ 1712 th = *th_p; 1713 msg->th_p = &th; 1714 return (1); 1715 } 1716 return (0); 1717 } 1718 1719 /* 1720 * This function is just like td_thr_event_getmsg, except that it is 1721 * passed a process handle rather than a thread handle, and returns 1722 * an event message for some thread in the process that has an event 1723 * message pending. If no thread has an event message pending, this 1724 * routine returns TD_NOEVENT. Thus, all pending event messages may 1725 * be collected from a process by repeatedly calling this routine 1726 * until it returns TD_NOEVENT. 1727 */ 1728 #pragma weak td_ta_event_getmsg = __td_ta_event_getmsg 1729 td_err_e 1730 __td_ta_event_getmsg(td_thragent_t *ta_p, td_event_msg_t *msg) 1731 { 1732 td_err_e return_val; 1733 1734 if (ta_p == NULL) 1735 return (TD_BADTA); 1736 if (ta_p->ph_p == NULL) 1737 return (TD_BADPH); 1738 if (msg == NULL) 1739 return (TD_ERR); 1740 msg->event = TD_EVENT_NONE; 1741 if ((return_val = __td_ta_thr_iter(ta_p, event_msg_cb, msg, 1742 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, TD_SIGNO_MASK, 1743 TD_THR_ANY_USER_FLAGS)) != TD_OK) 1744 return (return_val); 1745 if (msg->event == TD_EVENT_NONE) 1746 return (TD_NOEVENT); 1747 return (TD_OK); 1748 } 1749 1750 static lwpid_t 1751 thr_to_lwpid(const td_thrhandle_t *th_p) 1752 { 1753 struct ps_prochandle *ph_p = th_p->th_ta_p->ph_p; 1754 lwpid_t lwpid; 1755 1756 /* 1757 * The caller holds the prochandle lock 1758 * and has already verfied everything. 1759 */ 1760 if (th_p->th_ta_p->model == PR_MODEL_NATIVE) { 1761 ulwp_t *ulwp = (ulwp_t *)th_p->th_unique; 1762 1763 if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_lwpid, 1764 &lwpid, sizeof (lwpid)) != PS_OK) 1765 lwpid = 0; 1766 else if (lwpid == 0) 1767 lwpid = 1; 1768 } else { 1769 #if defined(_LP64) && defined(_SYSCALL32) 1770 ulwp32_t *ulwp = (ulwp32_t *)th_p->th_unique; 1771 1772 if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_lwpid, 1773 &lwpid, sizeof (lwpid)) != PS_OK) 1774 lwpid = 0; 1775 else if (lwpid == 0) 1776 lwpid = 1; 1777 #else 1778 lwpid = 0; 1779 #endif /* _SYSCALL32 */ 1780 } 1781 1782 return (lwpid); 1783 } 1784 1785 /* 1786 * Suspend a thread. 1787 * XXX: What does this mean in a one-level model? 1788 */ 1789 #pragma weak td_thr_dbsuspend = __td_thr_dbsuspend 1790 td_err_e 1791 __td_thr_dbsuspend(const td_thrhandle_t *th_p) 1792 { 1793 struct ps_prochandle *ph_p; 1794 td_err_e return_val; 1795 1796 if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL) 1797 return (return_val); 1798 if (ps_lstop(ph_p, thr_to_lwpid(th_p)) != PS_OK) 1799 return_val = TD_DBERR; 1800 ph_unlock(th_p->th_ta_p); 1801 return (return_val); 1802 } 1803 1804 /* 1805 * Resume a suspended thread. 1806 * XXX: What does this mean in a one-level model? 1807 */ 1808 #pragma weak td_thr_dbresume = __td_thr_dbresume 1809 td_err_e 1810 __td_thr_dbresume(const td_thrhandle_t *th_p) 1811 { 1812 struct ps_prochandle *ph_p; 1813 td_err_e return_val; 1814 1815 if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL) 1816 return (return_val); 1817 if (ps_lcontinue(ph_p, thr_to_lwpid(th_p)) != PS_OK) 1818 return_val = TD_DBERR; 1819 ph_unlock(th_p->th_ta_p); 1820 return (return_val); 1821 } 1822 1823 /* 1824 * Set a thread's signal mask. 1825 * Currently unused by dbx. 1826 */ 1827 #pragma weak td_thr_sigsetmask = __td_thr_sigsetmask 1828 /* ARGSUSED */ 1829 td_err_e 1830 __td_thr_sigsetmask(const td_thrhandle_t *th_p, const sigset_t ti_sigmask) 1831 { 1832 return (TD_NOCAPAB); 1833 } 1834 1835 /* 1836 * Set a thread's "signals-pending" set. 1837 * Currently unused by dbx. 1838 */ 1839 #pragma weak td_thr_setsigpending = __td_thr_setsigpending 1840 /* ARGSUSED */ 1841 td_err_e 1842 __td_thr_setsigpending(const td_thrhandle_t *th_p, 1843 uchar_t ti_pending_flag, const sigset_t ti_pending) 1844 { 1845 return (TD_NOCAPAB); 1846 } 1847 1848 /* 1849 * Get a thread's general register set. 1850 */ 1851 #pragma weak td_thr_getgregs = __td_thr_getgregs 1852 td_err_e 1853 __td_thr_getgregs(td_thrhandle_t *th_p, prgregset_t regset) 1854 { 1855 struct ps_prochandle *ph_p; 1856 td_err_e return_val; 1857 1858 if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL) 1859 return (return_val); 1860 if (ps_pstop(ph_p) != PS_OK) { 1861 ph_unlock(th_p->th_ta_p); 1862 return (TD_DBERR); 1863 } 1864 1865 if (ps_lgetregs(ph_p, thr_to_lwpid(th_p), regset) != PS_OK) 1866 return_val = TD_DBERR; 1867 1868 (void) ps_pcontinue(ph_p); 1869 ph_unlock(th_p->th_ta_p); 1870 return (return_val); 1871 } 1872 1873 /* 1874 * Set a thread's general register set. 1875 */ 1876 #pragma weak td_thr_setgregs = __td_thr_setgregs 1877 td_err_e 1878 __td_thr_setgregs(td_thrhandle_t *th_p, const prgregset_t regset) 1879 { 1880 struct ps_prochandle *ph_p; 1881 td_err_e return_val; 1882 1883 if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL) 1884 return (return_val); 1885 if (ps_pstop(ph_p) != PS_OK) { 1886 ph_unlock(th_p->th_ta_p); 1887 return (TD_DBERR); 1888 } 1889 1890 if (ps_lsetregs(ph_p, thr_to_lwpid(th_p), regset) != PS_OK) 1891 return_val = TD_DBERR; 1892 1893 (void) ps_pcontinue(ph_p); 1894 ph_unlock(th_p->th_ta_p); 1895 return (return_val); 1896 } 1897 1898 /* 1899 * Get a thread's floating-point register set. 1900 */ 1901 #pragma weak td_thr_getfpregs = __td_thr_getfpregs 1902 td_err_e 1903 __td_thr_getfpregs(td_thrhandle_t *th_p, prfpregset_t *fpregset) 1904 { 1905 struct ps_prochandle *ph_p; 1906 td_err_e return_val; 1907 1908 if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL) 1909 return (return_val); 1910 if (ps_pstop(ph_p) != PS_OK) { 1911 ph_unlock(th_p->th_ta_p); 1912 return (TD_DBERR); 1913 } 1914 1915 if (ps_lgetfpregs(ph_p, thr_to_lwpid(th_p), fpregset) != PS_OK) 1916 return_val = TD_DBERR; 1917 1918 (void) ps_pcontinue(ph_p); 1919 ph_unlock(th_p->th_ta_p); 1920 return (return_val); 1921 } 1922 1923 /* 1924 * Set a thread's floating-point register set. 1925 */ 1926 #pragma weak td_thr_setfpregs = __td_thr_setfpregs 1927 td_err_e 1928 __td_thr_setfpregs(td_thrhandle_t *th_p, const prfpregset_t *fpregset) 1929 { 1930 struct ps_prochandle *ph_p; 1931 td_err_e return_val; 1932 1933 if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL) 1934 return (return_val); 1935 if (ps_pstop(ph_p) != PS_OK) { 1936 ph_unlock(th_p->th_ta_p); 1937 return (TD_DBERR); 1938 } 1939 1940 if (ps_lsetfpregs(ph_p, thr_to_lwpid(th_p), fpregset) != PS_OK) 1941 return_val = TD_DBERR; 1942 1943 (void) ps_pcontinue(ph_p); 1944 ph_unlock(th_p->th_ta_p); 1945 return (return_val); 1946 } 1947 1948 /* 1949 * Get the size of the extra state register set for this architecture. 1950 * Currently unused by dbx. 1951 */ 1952 #pragma weak td_thr_getxregsize = __td_thr_getxregsize 1953 /* ARGSUSED */ 1954 td_err_e 1955 __td_thr_getxregsize(td_thrhandle_t *th_p, int *xregsize) 1956 { 1957 #if defined(__sparc) 1958 struct ps_prochandle *ph_p; 1959 td_err_e return_val; 1960 1961 if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL) 1962 return (return_val); 1963 if (ps_pstop(ph_p) != PS_OK) { 1964 ph_unlock(th_p->th_ta_p); 1965 return (TD_DBERR); 1966 } 1967 1968 if (ps_lgetxregsize(ph_p, thr_to_lwpid(th_p), xregsize) != PS_OK) 1969 return_val = TD_DBERR; 1970 1971 (void) ps_pcontinue(ph_p); 1972 ph_unlock(th_p->th_ta_p); 1973 return (return_val); 1974 #else /* __sparc */ 1975 return (TD_NOXREGS); 1976 #endif /* __sparc */ 1977 } 1978 1979 /* 1980 * Get a thread's extra state register set. 1981 */ 1982 #pragma weak td_thr_getxregs = __td_thr_getxregs 1983 /* ARGSUSED */ 1984 td_err_e 1985 __td_thr_getxregs(td_thrhandle_t *th_p, void *xregset) 1986 { 1987 #if defined(__sparc) 1988 struct ps_prochandle *ph_p; 1989 td_err_e return_val; 1990 1991 if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL) 1992 return (return_val); 1993 if (ps_pstop(ph_p) != PS_OK) { 1994 ph_unlock(th_p->th_ta_p); 1995 return (TD_DBERR); 1996 } 1997 1998 if (ps_lgetxregs(ph_p, thr_to_lwpid(th_p), (caddr_t)xregset) != PS_OK) 1999 return_val = TD_DBERR; 2000 2001 (void) ps_pcontinue(ph_p); 2002 ph_unlock(th_p->th_ta_p); 2003 return (return_val); 2004 #else /* __sparc */ 2005 return (TD_NOXREGS); 2006 #endif /* __sparc */ 2007 } 2008 2009 /* 2010 * Set a thread's extra state register set. 2011 */ 2012 #pragma weak td_thr_setxregs = __td_thr_setxregs 2013 /* ARGSUSED */ 2014 td_err_e 2015 __td_thr_setxregs(td_thrhandle_t *th_p, const void *xregset) 2016 { 2017 #if defined(__sparc) 2018 struct ps_prochandle *ph_p; 2019 td_err_e return_val; 2020 2021 if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL) 2022 return (return_val); 2023 if (ps_pstop(ph_p) != PS_OK) { 2024 ph_unlock(th_p->th_ta_p); 2025 return (TD_DBERR); 2026 } 2027 2028 if (ps_lsetxregs(ph_p, thr_to_lwpid(th_p), (caddr_t)xregset) != PS_OK) 2029 return_val = TD_DBERR; 2030 2031 (void) ps_pcontinue(ph_p); 2032 ph_unlock(th_p->th_ta_p); 2033 return (return_val); 2034 #else /* __sparc */ 2035 return (TD_NOXREGS); 2036 #endif /* __sparc */ 2037 } 2038 2039 struct searcher { 2040 psaddr_t addr; 2041 int status; 2042 }; 2043 2044 /* 2045 * Check the struct thread address in *th_p again first 2046 * value in "data". If value in data is found, set second value 2047 * in "data" to 1 and return 1 to terminate iterations. 2048 * This function is used by td_thr_validate() to verify that 2049 * a thread handle is valid. 2050 */ 2051 static int 2052 td_searcher(const td_thrhandle_t *th_p, void *data) 2053 { 2054 struct searcher *searcher_data = (struct searcher *)data; 2055 2056 if (searcher_data->addr == th_p->th_unique) { 2057 searcher_data->status = 1; 2058 return (1); 2059 } 2060 return (0); 2061 } 2062 2063 /* 2064 * Validate the thread handle. Check that 2065 * a thread exists in the thread agent/process that 2066 * corresponds to thread with handle *th_p. 2067 * Currently unused by dbx. 2068 */ 2069 #pragma weak td_thr_validate = __td_thr_validate 2070 td_err_e 2071 __td_thr_validate(const td_thrhandle_t *th_p) 2072 { 2073 td_err_e return_val; 2074 struct searcher searcher_data = {0, 0}; 2075 2076 if (th_p == NULL) 2077 return (TD_BADTH); 2078 if (th_p->th_unique == NULL || th_p->th_ta_p == NULL) 2079 return (TD_BADTH); 2080 2081 /* 2082 * LOCKING EXCEPTION - Locking is not required 2083 * here because no use of the thread agent is made (other 2084 * than the sanity check) and checking of the thread 2085 * agent will be done in __td_ta_thr_iter. 2086 */ 2087 2088 searcher_data.addr = th_p->th_unique; 2089 return_val = __td_ta_thr_iter(th_p->th_ta_p, 2090 td_searcher, &searcher_data, 2091 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, 2092 TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); 2093 2094 if (return_val == TD_OK && searcher_data.status == 0) 2095 return_val = TD_NOTHR; 2096 2097 return (return_val); 2098 } 2099 2100 /* 2101 * Get a thread's private binding to a given thread specific 2102 * data(TSD) key(see thr_getspecific(3T). If the thread doesn't 2103 * have a binding for a particular key, then NULL is returned. 2104 */ 2105 #pragma weak td_thr_tsd = __td_thr_tsd 2106 td_err_e 2107 __td_thr_tsd(td_thrhandle_t *th_p, thread_key_t key, void **data_pp) 2108 { 2109 struct ps_prochandle *ph_p; 2110 td_thragent_t *ta_p; 2111 td_err_e return_val; 2112 int maxkey; 2113 int nkey; 2114 psaddr_t tsd_paddr; 2115 2116 if (data_pp == NULL) 2117 return (TD_ERR); 2118 *data_pp = NULL; 2119 if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL) 2120 return (return_val); 2121 ta_p = th_p->th_ta_p; 2122 if (ps_pstop(ph_p) != PS_OK) { 2123 ph_unlock(ta_p); 2124 return (TD_DBERR); 2125 } 2126 2127 if (ta_p->model == PR_MODEL_NATIVE) { 2128 ulwp_t *ulwp = (ulwp_t *)th_p->th_unique; 2129 tsd_metadata_t tsdm; 2130 tsd_t stsd; 2131 2132 if (ps_pdread(ph_p, 2133 ta_p->uberdata_addr + offsetof(uberdata_t, tsd_metadata), 2134 &tsdm, sizeof (tsdm)) != PS_OK) 2135 return_val = TD_DBERR; 2136 else if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_stsd, 2137 &tsd_paddr, sizeof (tsd_paddr)) != PS_OK) 2138 return_val = TD_DBERR; 2139 else if (tsd_paddr != NULL && 2140 ps_pdread(ph_p, tsd_paddr, &stsd, sizeof (stsd)) != PS_OK) 2141 return_val = TD_DBERR; 2142 else { 2143 maxkey = tsdm.tsdm_nused; 2144 nkey = tsd_paddr == NULL ? TSD_NFAST : stsd.tsd_nalloc; 2145 2146 if (key < TSD_NFAST) 2147 tsd_paddr = (psaddr_t)&ulwp->ul_ftsd[0]; 2148 } 2149 } else { 2150 #if defined(_LP64) && defined(_SYSCALL32) 2151 ulwp32_t *ulwp = (ulwp32_t *)th_p->th_unique; 2152 tsd_metadata32_t tsdm; 2153 tsd32_t stsd; 2154 caddr32_t addr; 2155 2156 if (ps_pdread(ph_p, 2157 ta_p->uberdata_addr + offsetof(uberdata32_t, tsd_metadata), 2158 &tsdm, sizeof (tsdm)) != PS_OK) 2159 return_val = TD_DBERR; 2160 else if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_stsd, 2161 &addr, sizeof (addr)) != PS_OK) 2162 return_val = TD_DBERR; 2163 else if (addr != NULL && 2164 ps_pdread(ph_p, addr, &stsd, sizeof (stsd)) != PS_OK) 2165 return_val = TD_DBERR; 2166 else { 2167 maxkey = tsdm.tsdm_nused; 2168 nkey = addr == NULL ? TSD_NFAST : stsd.tsd_nalloc; 2169 2170 if (key < TSD_NFAST) { 2171 tsd_paddr = (psaddr_t)&ulwp->ul_ftsd[0]; 2172 } else { 2173 tsd_paddr = addr; 2174 } 2175 } 2176 #else 2177 return_val = TD_ERR; 2178 #endif /* _SYSCALL32 */ 2179 } 2180 2181 if (return_val == TD_OK && (key < 1 || key >= maxkey)) 2182 return_val = TD_NOTSD; 2183 if (return_val != TD_OK || key >= nkey) { 2184 /* NULL has already been stored in data_pp */ 2185 (void) ps_pcontinue(ph_p); 2186 ph_unlock(ta_p); 2187 return (return_val); 2188 } 2189 2190 /* 2191 * Read the value from the thread's tsd array. 2192 */ 2193 if (ta_p->model == PR_MODEL_NATIVE) { 2194 void *value; 2195 2196 if (ps_pdread(ph_p, tsd_paddr + key * sizeof (void *), 2197 &value, sizeof (value)) != PS_OK) 2198 return_val = TD_DBERR; 2199 else 2200 *data_pp = value; 2201 #if defined(_LP64) && defined(_SYSCALL32) 2202 } else { 2203 caddr32_t value32; 2204 2205 if (ps_pdread(ph_p, tsd_paddr + key * sizeof (caddr32_t), 2206 &value32, sizeof (value32)) != PS_OK) 2207 return_val = TD_DBERR; 2208 else 2209 *data_pp = (void *)(uintptr_t)value32; 2210 #endif /* _SYSCALL32 */ 2211 } 2212 2213 (void) ps_pcontinue(ph_p); 2214 ph_unlock(ta_p); 2215 return (return_val); 2216 } 2217 2218 /* 2219 * Get the base address of a thread's thread local storage (TLS) block 2220 * for the module (executable or shared object) identified by 'moduleid'. 2221 */ 2222 #pragma weak td_thr_tlsbase = __td_thr_tlsbase 2223 td_err_e 2224 __td_thr_tlsbase(td_thrhandle_t *th_p, ulong_t moduleid, psaddr_t *base) 2225 { 2226 struct ps_prochandle *ph_p; 2227 td_thragent_t *ta_p; 2228 td_err_e return_val; 2229 2230 if (base == NULL) 2231 return (TD_ERR); 2232 *base = NULL; 2233 if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL) 2234 return (return_val); 2235 ta_p = th_p->th_ta_p; 2236 if (ps_pstop(ph_p) != PS_OK) { 2237 ph_unlock(ta_p); 2238 return (TD_DBERR); 2239 } 2240 2241 if (ta_p->model == PR_MODEL_NATIVE) { 2242 ulwp_t *ulwp = (ulwp_t *)th_p->th_unique; 2243 tls_metadata_t tls_metadata; 2244 TLS_modinfo tlsmod; 2245 tls_t tls; 2246 2247 if (ps_pdread(ph_p, 2248 ta_p->uberdata_addr + offsetof(uberdata_t, tls_metadata), 2249 &tls_metadata, sizeof (tls_metadata)) != PS_OK) 2250 return_val = TD_DBERR; 2251 else if (moduleid >= tls_metadata.tls_modinfo.tls_size) 2252 return_val = TD_NOTLS; 2253 else if (ps_pdread(ph_p, 2254 (psaddr_t)((TLS_modinfo *) 2255 tls_metadata.tls_modinfo.tls_data + moduleid), 2256 &tlsmod, sizeof (tlsmod)) != PS_OK) 2257 return_val = TD_DBERR; 2258 else if (tlsmod.tm_memsz == 0) 2259 return_val = TD_NOTLS; 2260 else if (tlsmod.tm_flags & TM_FLG_STATICTLS) 2261 *base = (psaddr_t)ulwp - tlsmod.tm_stattlsoffset; 2262 else if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_tls, 2263 &tls, sizeof (tls)) != PS_OK) 2264 return_val = TD_DBERR; 2265 else if (moduleid >= tls.tls_size) 2266 return_val = TD_TLSDEFER; 2267 else if (ps_pdread(ph_p, 2268 (psaddr_t)((tls_t *)tls.tls_data + moduleid), 2269 &tls, sizeof (tls)) != PS_OK) 2270 return_val = TD_DBERR; 2271 else if (tls.tls_size == 0) 2272 return_val = TD_TLSDEFER; 2273 else 2274 *base = (psaddr_t)tls.tls_data; 2275 } else { 2276 #if defined(_LP64) && defined(_SYSCALL32) 2277 ulwp32_t *ulwp = (ulwp32_t *)th_p->th_unique; 2278 tls_metadata32_t tls_metadata; 2279 TLS_modinfo32 tlsmod; 2280 tls32_t tls; 2281 2282 if (ps_pdread(ph_p, 2283 ta_p->uberdata_addr + offsetof(uberdata32_t, tls_metadata), 2284 &tls_metadata, sizeof (tls_metadata)) != PS_OK) 2285 return_val = TD_DBERR; 2286 else if (moduleid >= tls_metadata.tls_modinfo.tls_size) 2287 return_val = TD_NOTLS; 2288 else if (ps_pdread(ph_p, 2289 (psaddr_t)((TLS_modinfo32 *) 2290 (uintptr_t)tls_metadata.tls_modinfo.tls_data + moduleid), 2291 &tlsmod, sizeof (tlsmod)) != PS_OK) 2292 return_val = TD_DBERR; 2293 else if (tlsmod.tm_memsz == 0) 2294 return_val = TD_NOTLS; 2295 else if (tlsmod.tm_flags & TM_FLG_STATICTLS) 2296 *base = (psaddr_t)ulwp - tlsmod.tm_stattlsoffset; 2297 else if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_tls, 2298 &tls, sizeof (tls)) != PS_OK) 2299 return_val = TD_DBERR; 2300 else if (moduleid >= tls.tls_size) 2301 return_val = TD_TLSDEFER; 2302 else if (ps_pdread(ph_p, 2303 (psaddr_t)((tls32_t *)(uintptr_t)tls.tls_data + moduleid), 2304 &tls, sizeof (tls)) != PS_OK) 2305 return_val = TD_DBERR; 2306 else if (tls.tls_size == 0) 2307 return_val = TD_TLSDEFER; 2308 else 2309 *base = (psaddr_t)tls.tls_data; 2310 #else 2311 return_val = TD_ERR; 2312 #endif /* _SYSCALL32 */ 2313 } 2314 2315 (void) ps_pcontinue(ph_p); 2316 ph_unlock(ta_p); 2317 return (return_val); 2318 } 2319 2320 /* 2321 * Change a thread's priority to the value specified by ti_pri. 2322 * Currently unused by dbx. 2323 */ 2324 #pragma weak td_thr_setprio = __td_thr_setprio 2325 /* ARGSUSED */ 2326 td_err_e 2327 __td_thr_setprio(td_thrhandle_t *th_p, int ti_pri) 2328 { 2329 return (TD_NOCAPAB); 2330 } 2331 2332 /* 2333 * This structure links td_thr_lockowner and the lowner_cb callback function. 2334 */ 2335 typedef struct { 2336 td_sync_iter_f *owner_cb; 2337 void *owner_cb_arg; 2338 td_thrhandle_t *th_p; 2339 } lowner_cb_ctl_t; 2340 2341 static int 2342 lowner_cb(const td_synchandle_t *sh_p, void *arg) 2343 { 2344 lowner_cb_ctl_t *ocb = arg; 2345 int trunc = 0; 2346 union { 2347 rwlock_t rwl; 2348 mutex_t mx; 2349 } rw_m; 2350 2351 if (ps_pdread(sh_p->sh_ta_p->ph_p, sh_p->sh_unique, 2352 &rw_m, sizeof (rw_m)) != PS_OK) { 2353 trunc = 1; 2354 if (ps_pdread(sh_p->sh_ta_p->ph_p, sh_p->sh_unique, 2355 &rw_m.mx, sizeof (rw_m.mx)) != PS_OK) 2356 return (0); 2357 } 2358 if (rw_m.mx.mutex_magic == MUTEX_MAGIC && 2359 rw_m.mx.mutex_owner == ocb->th_p->th_unique) 2360 return ((ocb->owner_cb)(sh_p, ocb->owner_cb_arg)); 2361 if (!trunc && rw_m.rwl.magic == RWL_MAGIC) { 2362 mutex_t *rwlock = &rw_m.rwl.mutex; 2363 if (rwlock->mutex_owner == ocb->th_p->th_unique) 2364 return ((ocb->owner_cb)(sh_p, ocb->owner_cb_arg)); 2365 } 2366 return (0); 2367 } 2368 2369 /* 2370 * Iterate over the set of locks owned by a specified thread. 2371 * If cb returns a non-zero value, terminate iterations. 2372 */ 2373 #pragma weak td_thr_lockowner = __td_thr_lockowner 2374 td_err_e 2375 __td_thr_lockowner(const td_thrhandle_t *th_p, td_sync_iter_f *cb, 2376 void *cb_data) 2377 { 2378 td_thragent_t *ta_p; 2379 td_err_e return_val; 2380 lowner_cb_ctl_t lcb; 2381 2382 /* 2383 * Just sanity checks. 2384 */ 2385 if (ph_lock_th((td_thrhandle_t *)th_p, &return_val) == NULL) 2386 return (return_val); 2387 ta_p = th_p->th_ta_p; 2388 ph_unlock(ta_p); 2389 2390 lcb.owner_cb = cb; 2391 lcb.owner_cb_arg = cb_data; 2392 lcb.th_p = (td_thrhandle_t *)th_p; 2393 return (__td_ta_sync_iter(ta_p, lowner_cb, &lcb)); 2394 } 2395 2396 /* 2397 * If a thread is asleep on a synchronization variable, 2398 * then get the synchronization handle. 2399 */ 2400 #pragma weak td_thr_sleepinfo = __td_thr_sleepinfo 2401 td_err_e 2402 __td_thr_sleepinfo(const td_thrhandle_t *th_p, td_synchandle_t *sh_p) 2403 { 2404 struct ps_prochandle *ph_p; 2405 td_err_e return_val = TD_OK; 2406 uintptr_t wchan; 2407 2408 if (sh_p == NULL) 2409 return (TD_ERR); 2410 if ((ph_p = ph_lock_th((td_thrhandle_t *)th_p, &return_val)) == NULL) 2411 return (return_val); 2412 2413 /* 2414 * No need to stop the process for a simple read. 2415 */ 2416 if (th_p->th_ta_p->model == PR_MODEL_NATIVE) { 2417 ulwp_t *ulwp = (ulwp_t *)th_p->th_unique; 2418 2419 if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_wchan, 2420 &wchan, sizeof (wchan)) != PS_OK) 2421 return_val = TD_DBERR; 2422 } else { 2423 #if defined(_LP64) && defined(_SYSCALL32) 2424 ulwp32_t *ulwp = (ulwp32_t *)th_p->th_unique; 2425 caddr32_t wchan32; 2426 2427 if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_wchan, 2428 &wchan32, sizeof (wchan32)) != PS_OK) 2429 return_val = TD_DBERR; 2430 wchan = wchan32; 2431 #else 2432 return_val = TD_ERR; 2433 #endif /* _SYSCALL32 */ 2434 } 2435 2436 if (return_val != TD_OK || wchan == NULL) { 2437 sh_p->sh_ta_p = NULL; 2438 sh_p->sh_unique = NULL; 2439 if (return_val == TD_OK) 2440 return_val = TD_ERR; 2441 } else { 2442 sh_p->sh_ta_p = th_p->th_ta_p; 2443 sh_p->sh_unique = (psaddr_t)wchan; 2444 } 2445 2446 ph_unlock(th_p->th_ta_p); 2447 return (return_val); 2448 } 2449 2450 /* 2451 * Which thread is running on an lwp? 2452 */ 2453 #pragma weak td_ta_map_lwp2thr = __td_ta_map_lwp2thr 2454 td_err_e 2455 __td_ta_map_lwp2thr(td_thragent_t *ta_p, lwpid_t lwpid, 2456 td_thrhandle_t *th_p) 2457 { 2458 return (__td_ta_map_id2thr(ta_p, lwpid, th_p)); 2459 } 2460 2461 /* 2462 * Common code for td_sync_get_info() and td_sync_get_stats() 2463 */ 2464 static td_err_e 2465 sync_get_info_common(const td_synchandle_t *sh_p, struct ps_prochandle *ph_p, 2466 td_syncinfo_t *si_p) 2467 { 2468 int trunc = 0; 2469 td_so_un_t generic_so; 2470 2471 /* 2472 * Determine the sync. object type; a little type fudgery here. 2473 * First attempt to read the whole union. If that fails, attempt 2474 * to read just the condvar. A condvar is the smallest sync. object. 2475 */ 2476 if (ps_pdread(ph_p, sh_p->sh_unique, 2477 &generic_so, sizeof (generic_so)) != PS_OK) { 2478 trunc = 1; 2479 if (ps_pdread(ph_p, sh_p->sh_unique, &generic_so.condition, 2480 sizeof (generic_so.condition)) != PS_OK) 2481 return (TD_DBERR); 2482 } 2483 2484 switch (generic_so.condition.cond_magic) { 2485 case MUTEX_MAGIC: 2486 if (trunc && ps_pdread(ph_p, sh_p->sh_unique, 2487 &generic_so.lock, sizeof (generic_so.lock)) != PS_OK) 2488 return (TD_DBERR); 2489 si_p->si_type = TD_SYNC_MUTEX; 2490 si_p->si_shared_type = 2491 (generic_so.lock.mutex_type & USYNC_PROCESS); 2492 (void) memcpy(si_p->si_flags, &generic_so.lock.mutex_flag, 2493 sizeof (generic_so.lock.mutex_flag)); 2494 si_p->si_state.mutex_locked = 2495 (generic_so.lock.mutex_lockw != 0); 2496 si_p->si_size = sizeof (generic_so.lock); 2497 si_p->si_has_waiters = generic_so.lock.mutex_waiters; 2498 si_p->si_rcount = generic_so.lock.mutex_rcount; 2499 si_p->si_prioceiling = generic_so.lock.mutex_ceiling; 2500 if (si_p->si_state.mutex_locked) { 2501 if (si_p->si_shared_type & USYNC_PROCESS) 2502 si_p->si_ownerpid = 2503 generic_so.lock.mutex_ownerpid; 2504 si_p->si_owner.th_ta_p = sh_p->sh_ta_p; 2505 si_p->si_owner.th_unique = generic_so.lock.mutex_owner; 2506 } 2507 break; 2508 case COND_MAGIC: 2509 si_p->si_type = TD_SYNC_COND; 2510 si_p->si_shared_type = 2511 (generic_so.condition.cond_type & USYNC_PROCESS); 2512 (void) memcpy(si_p->si_flags, generic_so.condition.flags.flag, 2513 sizeof (generic_so.condition.flags.flag)); 2514 si_p->si_size = sizeof (generic_so.condition); 2515 si_p->si_has_waiters = 2516 (generic_so.condition.cond_waiters_user | 2517 generic_so.condition.cond_waiters_kernel)? 1 : 0; 2518 break; 2519 case SEMA_MAGIC: 2520 if (trunc && ps_pdread(ph_p, sh_p->sh_unique, 2521 &generic_so.semaphore, sizeof (generic_so.semaphore)) 2522 != PS_OK) 2523 return (TD_DBERR); 2524 si_p->si_type = TD_SYNC_SEMA; 2525 si_p->si_shared_type = 2526 (generic_so.semaphore.type & USYNC_PROCESS); 2527 si_p->si_state.sem_count = generic_so.semaphore.count; 2528 si_p->si_size = sizeof (generic_so.semaphore); 2529 si_p->si_has_waiters = 2530 ((lwp_sema_t *)&generic_so.semaphore)->flags[7]; 2531 /* this is useless but the old interface provided it */ 2532 si_p->si_data = (psaddr_t)generic_so.semaphore.count; 2533 break; 2534 case RWL_MAGIC: 2535 { 2536 uint32_t rwstate; 2537 2538 if (trunc && ps_pdread(ph_p, sh_p->sh_unique, 2539 &generic_so.rwlock, sizeof (generic_so.rwlock)) != PS_OK) 2540 return (TD_DBERR); 2541 si_p->si_type = TD_SYNC_RWLOCK; 2542 si_p->si_shared_type = 2543 (generic_so.rwlock.rwlock_type & USYNC_PROCESS); 2544 si_p->si_size = sizeof (generic_so.rwlock); 2545 2546 rwstate = (uint32_t)generic_so.rwlock.rwlock_readers; 2547 if (rwstate & URW_WRITE_LOCKED) { 2548 si_p->si_state.nreaders = -1; 2549 si_p->si_is_wlock = 1; 2550 si_p->si_owner.th_ta_p = sh_p->sh_ta_p; 2551 si_p->si_owner.th_unique = 2552 generic_so.rwlock.rwlock_owner; 2553 if (si_p->si_shared_type & USYNC_PROCESS) 2554 si_p->si_ownerpid = 2555 generic_so.rwlock.rwlock_ownerpid; 2556 } else { 2557 si_p->si_state.nreaders = (rwstate & URW_READERS_MASK); 2558 } 2559 si_p->si_has_waiters = ((rwstate & URW_HAS_WAITERS) != 0); 2560 2561 /* this is useless but the old interface provided it */ 2562 si_p->si_data = (psaddr_t)generic_so.rwlock.readers; 2563 break; 2564 } 2565 default: 2566 return (TD_BADSH); 2567 } 2568 2569 si_p->si_ta_p = sh_p->sh_ta_p; 2570 si_p->si_sv_addr = sh_p->sh_unique; 2571 return (TD_OK); 2572 } 2573 2574 /* 2575 * Given a synchronization handle, fill in the 2576 * information for the synchronization variable into *si_p. 2577 */ 2578 #pragma weak td_sync_get_info = __td_sync_get_info 2579 td_err_e 2580 __td_sync_get_info(const td_synchandle_t *sh_p, td_syncinfo_t *si_p) 2581 { 2582 struct ps_prochandle *ph_p; 2583 td_err_e return_val; 2584 2585 if (si_p == NULL) 2586 return (TD_ERR); 2587 (void) memset(si_p, 0, sizeof (*si_p)); 2588 if ((ph_p = ph_lock_sh(sh_p, &return_val)) == NULL) 2589 return (return_val); 2590 if (ps_pstop(ph_p) != PS_OK) { 2591 ph_unlock(sh_p->sh_ta_p); 2592 return (TD_DBERR); 2593 } 2594 2595 return_val = sync_get_info_common(sh_p, ph_p, si_p); 2596 2597 (void) ps_pcontinue(ph_p); 2598 ph_unlock(sh_p->sh_ta_p); 2599 return (return_val); 2600 } 2601 2602 static uint_t 2603 tdb_addr_hash64(uint64_t addr) 2604 { 2605 uint64_t value60 = (addr >> 4); 2606 uint32_t value30 = (value60 >> 30) ^ (value60 & 0x3fffffff); 2607 return ((value30 >> 15) ^ (value30 & 0x7fff)); 2608 } 2609 2610 static uint_t 2611 tdb_addr_hash32(uint64_t addr) 2612 { 2613 uint32_t value30 = (addr >> 2); /* 30 bits */ 2614 return ((value30 >> 15) ^ (value30 & 0x7fff)); 2615 } 2616 2617 static td_err_e 2618 read_sync_stats(td_thragent_t *ta_p, psaddr_t hash_table, 2619 psaddr_t sync_obj_addr, tdb_sync_stats_t *sync_stats) 2620 { 2621 psaddr_t next_desc; 2622 uint64_t first; 2623 uint_t ix; 2624 2625 /* 2626 * Compute the hash table index from the synch object's address. 2627 */ 2628 if (ta_p->model == PR_MODEL_LP64) 2629 ix = tdb_addr_hash64(sync_obj_addr); 2630 else 2631 ix = tdb_addr_hash32(sync_obj_addr); 2632 2633 /* 2634 * Get the address of the first element in the linked list. 2635 */ 2636 if (ps_pdread(ta_p->ph_p, hash_table + ix * sizeof (uint64_t), 2637 &first, sizeof (first)) != PS_OK) 2638 return (TD_DBERR); 2639 2640 /* 2641 * Search the linked list for an entry for the synch object.. 2642 */ 2643 for (next_desc = (psaddr_t)first; next_desc != NULL; 2644 next_desc = (psaddr_t)sync_stats->next) { 2645 if (ps_pdread(ta_p->ph_p, next_desc, 2646 sync_stats, sizeof (*sync_stats)) != PS_OK) 2647 return (TD_DBERR); 2648 if (sync_stats->sync_addr == sync_obj_addr) 2649 return (TD_OK); 2650 } 2651 2652 (void) memset(sync_stats, 0, sizeof (*sync_stats)); 2653 return (TD_OK); 2654 } 2655 2656 /* 2657 * Given a synchronization handle, fill in the 2658 * statistics for the synchronization variable into *ss_p. 2659 */ 2660 #pragma weak td_sync_get_stats = __td_sync_get_stats 2661 td_err_e 2662 __td_sync_get_stats(const td_synchandle_t *sh_p, td_syncstats_t *ss_p) 2663 { 2664 struct ps_prochandle *ph_p; 2665 td_thragent_t *ta_p; 2666 td_err_e return_val; 2667 register_sync_t enable; 2668 psaddr_t hashaddr; 2669 tdb_sync_stats_t sync_stats; 2670 size_t ix; 2671 2672 if (ss_p == NULL) 2673 return (TD_ERR); 2674 (void) memset(ss_p, 0, sizeof (*ss_p)); 2675 if ((ph_p = ph_lock_sh(sh_p, &return_val)) == NULL) 2676 return (return_val); 2677 ta_p = sh_p->sh_ta_p; 2678 if (ps_pstop(ph_p) != PS_OK) { 2679 ph_unlock(ta_p); 2680 return (TD_DBERR); 2681 } 2682 2683 if ((return_val = sync_get_info_common(sh_p, ph_p, &ss_p->ss_info)) 2684 != TD_OK) { 2685 if (return_val != TD_BADSH) 2686 goto out; 2687 /* we can correct TD_BADSH */ 2688 (void) memset(&ss_p->ss_info, 0, sizeof (ss_p->ss_info)); 2689 ss_p->ss_info.si_ta_p = sh_p->sh_ta_p; 2690 ss_p->ss_info.si_sv_addr = sh_p->sh_unique; 2691 /* we correct si_type and si_size below */ 2692 return_val = TD_OK; 2693 } 2694 if (ps_pdread(ph_p, ta_p->tdb_register_sync_addr, 2695 &enable, sizeof (enable)) != PS_OK) { 2696 return_val = TD_DBERR; 2697 goto out; 2698 } 2699 if (enable != REGISTER_SYNC_ON) 2700 goto out; 2701 2702 /* 2703 * Get the address of the hash table in the target process. 2704 */ 2705 if (ta_p->model == PR_MODEL_NATIVE) { 2706 if (ps_pdread(ph_p, ta_p->uberdata_addr + 2707 offsetof(uberdata_t, tdb.tdb_sync_addr_hash), 2708 &hashaddr, sizeof (&hashaddr)) != PS_OK) { 2709 return_val = TD_DBERR; 2710 goto out; 2711 } 2712 } else { 2713 #if defined(_LP64) && defined(_SYSCALL32) 2714 caddr32_t addr; 2715 2716 if (ps_pdread(ph_p, ta_p->uberdata_addr + 2717 offsetof(uberdata32_t, tdb.tdb_sync_addr_hash), 2718 &addr, sizeof (addr)) != PS_OK) { 2719 return_val = TD_DBERR; 2720 goto out; 2721 } 2722 hashaddr = addr; 2723 #else 2724 return_val = TD_ERR; 2725 goto out; 2726 #endif /* _SYSCALL32 */ 2727 } 2728 2729 if (hashaddr == 0) 2730 return_val = TD_BADSH; 2731 else 2732 return_val = read_sync_stats(ta_p, hashaddr, 2733 sh_p->sh_unique, &sync_stats); 2734 if (return_val != TD_OK) 2735 goto out; 2736 2737 /* 2738 * We have the hash table entry. Transfer the data to 2739 * the td_syncstats_t structure provided by the caller. 2740 */ 2741 switch (sync_stats.un.type) { 2742 case TDB_MUTEX: 2743 { 2744 td_mutex_stats_t *msp = &ss_p->ss_un.mutex; 2745 2746 ss_p->ss_info.si_type = TD_SYNC_MUTEX; 2747 ss_p->ss_info.si_size = sizeof (mutex_t); 2748 msp->mutex_lock = 2749 sync_stats.un.mutex.mutex_lock; 2750 msp->mutex_sleep = 2751 sync_stats.un.mutex.mutex_sleep; 2752 msp->mutex_sleep_time = 2753 sync_stats.un.mutex.mutex_sleep_time; 2754 msp->mutex_hold_time = 2755 sync_stats.un.mutex.mutex_hold_time; 2756 msp->mutex_try = 2757 sync_stats.un.mutex.mutex_try; 2758 msp->mutex_try_fail = 2759 sync_stats.un.mutex.mutex_try_fail; 2760 if (sync_stats.sync_addr >= ta_p->hash_table_addr && 2761 (ix = sync_stats.sync_addr - ta_p->hash_table_addr) 2762 < ta_p->hash_size * sizeof (thr_hash_table_t)) 2763 msp->mutex_internal = 2764 ix / sizeof (thr_hash_table_t) + 1; 2765 break; 2766 } 2767 case TDB_COND: 2768 { 2769 td_cond_stats_t *csp = &ss_p->ss_un.cond; 2770 2771 ss_p->ss_info.si_type = TD_SYNC_COND; 2772 ss_p->ss_info.si_size = sizeof (cond_t); 2773 csp->cond_wait = 2774 sync_stats.un.cond.cond_wait; 2775 csp->cond_timedwait = 2776 sync_stats.un.cond.cond_timedwait; 2777 csp->cond_wait_sleep_time = 2778 sync_stats.un.cond.cond_wait_sleep_time; 2779 csp->cond_timedwait_sleep_time = 2780 sync_stats.un.cond.cond_timedwait_sleep_time; 2781 csp->cond_timedwait_timeout = 2782 sync_stats.un.cond.cond_timedwait_timeout; 2783 csp->cond_signal = 2784 sync_stats.un.cond.cond_signal; 2785 csp->cond_broadcast = 2786 sync_stats.un.cond.cond_broadcast; 2787 if (sync_stats.sync_addr >= ta_p->hash_table_addr && 2788 (ix = sync_stats.sync_addr - ta_p->hash_table_addr) 2789 < ta_p->hash_size * sizeof (thr_hash_table_t)) 2790 csp->cond_internal = 2791 ix / sizeof (thr_hash_table_t) + 1; 2792 break; 2793 } 2794 case TDB_RWLOCK: 2795 { 2796 td_rwlock_stats_t *rwsp = &ss_p->ss_un.rwlock; 2797 2798 ss_p->ss_info.si_type = TD_SYNC_RWLOCK; 2799 ss_p->ss_info.si_size = sizeof (rwlock_t); 2800 rwsp->rw_rdlock = 2801 sync_stats.un.rwlock.rw_rdlock; 2802 rwsp->rw_rdlock_try = 2803 sync_stats.un.rwlock.rw_rdlock_try; 2804 rwsp->rw_rdlock_try_fail = 2805 sync_stats.un.rwlock.rw_rdlock_try_fail; 2806 rwsp->rw_wrlock = 2807 sync_stats.un.rwlock.rw_wrlock; 2808 rwsp->rw_wrlock_hold_time = 2809 sync_stats.un.rwlock.rw_wrlock_hold_time; 2810 rwsp->rw_wrlock_try = 2811 sync_stats.un.rwlock.rw_wrlock_try; 2812 rwsp->rw_wrlock_try_fail = 2813 sync_stats.un.rwlock.rw_wrlock_try_fail; 2814 break; 2815 } 2816 case TDB_SEMA: 2817 { 2818 td_sema_stats_t *ssp = &ss_p->ss_un.sema; 2819 2820 ss_p->ss_info.si_type = TD_SYNC_SEMA; 2821 ss_p->ss_info.si_size = sizeof (sema_t); 2822 ssp->sema_wait = 2823 sync_stats.un.sema.sema_wait; 2824 ssp->sema_wait_sleep = 2825 sync_stats.un.sema.sema_wait_sleep; 2826 ssp->sema_wait_sleep_time = 2827 sync_stats.un.sema.sema_wait_sleep_time; 2828 ssp->sema_trywait = 2829 sync_stats.un.sema.sema_trywait; 2830 ssp->sema_trywait_fail = 2831 sync_stats.un.sema.sema_trywait_fail; 2832 ssp->sema_post = 2833 sync_stats.un.sema.sema_post; 2834 ssp->sema_max_count = 2835 sync_stats.un.sema.sema_max_count; 2836 ssp->sema_min_count = 2837 sync_stats.un.sema.sema_min_count; 2838 break; 2839 } 2840 default: 2841 return_val = TD_BADSH; 2842 break; 2843 } 2844 2845 out: 2846 (void) ps_pcontinue(ph_p); 2847 ph_unlock(ta_p); 2848 return (return_val); 2849 } 2850 2851 /* 2852 * Change the state of a synchronization variable. 2853 * 1) mutex lock state set to value 2854 * 2) semaphore's count set to value 2855 * 3) writer's lock set by value < 0 2856 * 4) reader's lock number of readers set to value >= 0 2857 * Currently unused by dbx. 2858 */ 2859 #pragma weak td_sync_setstate = __td_sync_setstate 2860 td_err_e 2861 __td_sync_setstate(const td_synchandle_t *sh_p, long lvalue) 2862 { 2863 struct ps_prochandle *ph_p; 2864 int trunc = 0; 2865 td_err_e return_val; 2866 td_so_un_t generic_so; 2867 uint32_t *rwstate; 2868 int value = (int)lvalue; 2869 2870 if ((ph_p = ph_lock_sh(sh_p, &return_val)) == NULL) 2871 return (return_val); 2872 if (ps_pstop(ph_p) != PS_OK) { 2873 ph_unlock(sh_p->sh_ta_p); 2874 return (TD_DBERR); 2875 } 2876 2877 /* 2878 * Read the synch. variable information. 2879 * First attempt to read the whole union and if that fails 2880 * fall back to reading only the smallest member, the condvar. 2881 */ 2882 if (ps_pdread(ph_p, sh_p->sh_unique, &generic_so, 2883 sizeof (generic_so)) != PS_OK) { 2884 trunc = 1; 2885 if (ps_pdread(ph_p, sh_p->sh_unique, &generic_so.condition, 2886 sizeof (generic_so.condition)) != PS_OK) { 2887 (void) ps_pcontinue(ph_p); 2888 ph_unlock(sh_p->sh_ta_p); 2889 return (TD_DBERR); 2890 } 2891 } 2892 2893 /* 2894 * Set the new value in the sync. variable, read the synch. variable 2895 * information. from the process, reset its value and write it back. 2896 */ 2897 switch (generic_so.condition.mutex_magic) { 2898 case MUTEX_MAGIC: 2899 if (trunc && ps_pdread(ph_p, sh_p->sh_unique, 2900 &generic_so.lock, sizeof (generic_so.lock)) != PS_OK) { 2901 return_val = TD_DBERR; 2902 break; 2903 } 2904 generic_so.lock.mutex_lockw = (uint8_t)value; 2905 if (ps_pdwrite(ph_p, sh_p->sh_unique, &generic_so.lock, 2906 sizeof (generic_so.lock)) != PS_OK) 2907 return_val = TD_DBERR; 2908 break; 2909 case SEMA_MAGIC: 2910 if (trunc && ps_pdread(ph_p, sh_p->sh_unique, 2911 &generic_so.semaphore, sizeof (generic_so.semaphore)) 2912 != PS_OK) { 2913 return_val = TD_DBERR; 2914 break; 2915 } 2916 generic_so.semaphore.count = value; 2917 if (ps_pdwrite(ph_p, sh_p->sh_unique, &generic_so.semaphore, 2918 sizeof (generic_so.semaphore)) != PS_OK) 2919 return_val = TD_DBERR; 2920 break; 2921 case COND_MAGIC: 2922 /* Operation not supported on a condition variable */ 2923 return_val = TD_ERR; 2924 break; 2925 case RWL_MAGIC: 2926 if (trunc && ps_pdread(ph_p, sh_p->sh_unique, 2927 &generic_so.rwlock, sizeof (generic_so.rwlock)) != PS_OK) { 2928 return_val = TD_DBERR; 2929 break; 2930 } 2931 rwstate = (uint32_t *)&generic_so.rwlock.readers; 2932 *rwstate &= URW_HAS_WAITERS; 2933 if (value < 0) 2934 *rwstate |= URW_WRITE_LOCKED; 2935 else 2936 *rwstate |= (value & URW_READERS_MASK); 2937 if (ps_pdwrite(ph_p, sh_p->sh_unique, &generic_so.rwlock, 2938 sizeof (generic_so.rwlock)) != PS_OK) 2939 return_val = TD_DBERR; 2940 break; 2941 default: 2942 /* Bad sync. object type */ 2943 return_val = TD_BADSH; 2944 break; 2945 } 2946 2947 (void) ps_pcontinue(ph_p); 2948 ph_unlock(sh_p->sh_ta_p); 2949 return (return_val); 2950 } 2951 2952 typedef struct { 2953 td_thr_iter_f *waiter_cb; 2954 psaddr_t sync_obj_addr; 2955 uint16_t sync_magic; 2956 void *waiter_cb_arg; 2957 td_err_e errcode; 2958 } waiter_cb_ctl_t; 2959 2960 static int 2961 waiters_cb(const td_thrhandle_t *th_p, void *arg) 2962 { 2963 td_thragent_t *ta_p = th_p->th_ta_p; 2964 struct ps_prochandle *ph_p = ta_p->ph_p; 2965 waiter_cb_ctl_t *wcb = arg; 2966 caddr_t wchan; 2967 2968 if (ta_p->model == PR_MODEL_NATIVE) { 2969 ulwp_t *ulwp = (ulwp_t *)th_p->th_unique; 2970 2971 if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_wchan, 2972 &wchan, sizeof (wchan)) != PS_OK) { 2973 wcb->errcode = TD_DBERR; 2974 return (1); 2975 } 2976 } else { 2977 #if defined(_LP64) && defined(_SYSCALL32) 2978 ulwp32_t *ulwp = (ulwp32_t *)th_p->th_unique; 2979 caddr32_t wchan32; 2980 2981 if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_wchan, 2982 &wchan32, sizeof (wchan32)) != PS_OK) { 2983 wcb->errcode = TD_DBERR; 2984 return (1); 2985 } 2986 wchan = (caddr_t)(uintptr_t)wchan32; 2987 #else 2988 wcb->errcode = TD_ERR; 2989 return (1); 2990 #endif /* _SYSCALL32 */ 2991 } 2992 2993 if (wchan == NULL) 2994 return (0); 2995 2996 if (wchan == (caddr_t)wcb->sync_obj_addr) 2997 return ((*wcb->waiter_cb)(th_p, wcb->waiter_cb_arg)); 2998 2999 return (0); 3000 } 3001 3002 /* 3003 * For a given synchronization variable, iterate over the 3004 * set of waiting threads. The call back function is passed 3005 * two parameters, a pointer to a thread handle and a pointer 3006 * to extra call back data. 3007 */ 3008 #pragma weak td_sync_waiters = __td_sync_waiters 3009 td_err_e 3010 __td_sync_waiters(const td_synchandle_t *sh_p, td_thr_iter_f *cb, void *cb_data) 3011 { 3012 struct ps_prochandle *ph_p; 3013 waiter_cb_ctl_t wcb; 3014 td_err_e return_val; 3015 3016 if ((ph_p = ph_lock_sh(sh_p, &return_val)) == NULL) 3017 return (return_val); 3018 if (ps_pdread(ph_p, 3019 (psaddr_t)&((mutex_t *)sh_p->sh_unique)->mutex_magic, 3020 (caddr_t)&wcb.sync_magic, sizeof (wcb.sync_magic)) != PS_OK) { 3021 ph_unlock(sh_p->sh_ta_p); 3022 return (TD_DBERR); 3023 } 3024 ph_unlock(sh_p->sh_ta_p); 3025 3026 switch (wcb.sync_magic) { 3027 case MUTEX_MAGIC: 3028 case COND_MAGIC: 3029 case SEMA_MAGIC: 3030 case RWL_MAGIC: 3031 break; 3032 default: 3033 return (TD_BADSH); 3034 } 3035 3036 wcb.waiter_cb = cb; 3037 wcb.sync_obj_addr = sh_p->sh_unique; 3038 wcb.waiter_cb_arg = cb_data; 3039 wcb.errcode = TD_OK; 3040 return_val = __td_ta_thr_iter(sh_p->sh_ta_p, waiters_cb, &wcb, 3041 TD_THR_SLEEP, TD_THR_LOWEST_PRIORITY, 3042 TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); 3043 3044 if (return_val != TD_OK) 3045 return (return_val); 3046 3047 return (wcb.errcode); 3048 } 3049