1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 2192 raf * Common Development and Distribution License (the "License"). 6 2192 raf * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 2192 raf 22 0 stevel /* 23 7330 Roger * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 0 stevel * Use is subject to license terms. 25 0 stevel */ 26 0 stevel 27 0 stevel #define _SYSCALL32 28 0 stevel 29 0 stevel #include <stdio.h> 30 0 stevel #include <stdlib.h> 31 0 stevel #include <unistd.h> 32 0 stevel #include <ctype.h> 33 0 stevel #include <string.h> 34 0 stevel #include <memory.h> 35 0 stevel #include <errno.h> 36 0 stevel #include <sys/types.h> 37 0 stevel #include <sys/stack.h> 38 0 stevel #include <signal.h> 39 0 stevel #include <limits.h> 40 0 stevel #include <sys/isa_defs.h> 41 0 stevel #include <proc_service.h> 42 0 stevel #include <dlfcn.h> 43 0 stevel #include <fnmatch.h> 44 0 stevel #include <libproc.h> 45 0 stevel #include "ramdata.h" 46 0 stevel #include "systable.h" 47 0 stevel #include "print.h" 48 0 stevel #include "proto.h" 49 0 stevel #include "htbl.h" 50 0 stevel 51 0 stevel /* 52 0 stevel * Functions supporting library function call tracing. 53 0 stevel */ 54 0 stevel 55 0 stevel typedef struct { 56 0 stevel prmap_t *pmap; 57 0 stevel int nmap; 58 0 stevel } ph_map_t; 59 0 stevel 60 0 stevel /* 61 0 stevel * static functions in this file. 62 0 stevel */ 63 0 stevel void function_entry(private_t *, struct bkpt *, struct callstack *); 64 0 stevel void function_return(private_t *, struct callstack *); 65 0 stevel int object_iter(void *, const prmap_t *, const char *); 66 2192 raf int object_present(void *, const prmap_t *, const char *); 67 0 stevel int symbol_iter(void *, const GElf_Sym *, const char *); 68 0 stevel uintptr_t get_return_address(uintptr_t *); 69 0 stevel int get_arguments(long *argp); 70 0 stevel uintptr_t previous_fp(uintptr_t, uintptr_t *); 71 0 stevel int lwp_stack_traps(void *cd, const lwpstatus_t *Lsp); 72 0 stevel int thr_stack_traps(const td_thrhandle_t *Thp, void *cd); 73 0 stevel struct bkpt *create_bkpt(uintptr_t, int, int); 74 0 stevel void set_deferred_breakpoints(void); 75 0 stevel 76 0 stevel #define DEF_MAXCALL 16 /* initial value of Stk->maxcall */ 77 0 stevel 78 0 stevel #define FAULT_ADDR ((uintptr_t)(0-8)) 79 0 stevel 80 0 stevel #define HASHSZ 2048 81 0 stevel #define bpt_hash(addr) ((((addr) >> 13) ^ ((addr) >> 2)) & 0x7ff) 82 0 stevel 83 0 stevel static void 84 0 stevel setup_thread_agent(void) 85 0 stevel { 86 0 stevel struct bkpt *Bp; 87 0 stevel td_notify_t notify; 88 0 stevel td_thr_events_t events; 89 0 stevel 90 0 stevel if (Thr_agent != NULL) /* only once */ 91 0 stevel return; 92 0 stevel if (td_init() != TD_OK || td_ta_new(Proc, &Thr_agent) != TD_OK) 93 0 stevel Thr_agent = NULL; 94 0 stevel else { 95 0 stevel td_event_emptyset(&events); 96 0 stevel td_event_addset(&events, TD_CREATE); 97 0 stevel if (td_ta_event_addr(Thr_agent, TD_CREATE, ¬ify) == TD_OK && 98 0 stevel notify.type == NOTIFY_BPT && 99 0 stevel td_ta_set_event(Thr_agent, &events) == TD_OK && 100 0 stevel (Bp = create_bkpt(notify.u.bptaddr, 0, 1)) != NULL) 101 0 stevel Bp->flags |= BPT_TD_CREATE; 102 2192 raf } 103 2192 raf } 104 2192 raf 105 2192 raf /* 106 2192 raf * Delete all breakpoints in the range [base .. base+size) 107 2192 raf * from the breakpoint hash table. 108 2192 raf */ 109 2192 raf static void 110 2192 raf delete_breakpoints(uintptr_t base, size_t size) 111 2192 raf { 112 2192 raf struct bkpt **Bpp; 113 2192 raf struct bkpt *Bp; 114 2192 raf int i; 115 2192 raf 116 2192 raf if (bpt_hashtable == NULL) 117 2192 raf return; 118 2192 raf for (i = 0; i < HASHSZ; i++) { 119 2192 raf Bpp = &bpt_hashtable[i]; 120 2192 raf while ((Bp = *Bpp) != NULL) { 121 2192 raf if (Bp->addr < base || Bp->addr >= base + size) { 122 2192 raf Bpp = &Bp->next; 123 2192 raf continue; 124 2192 raf } 125 2192 raf *Bpp = Bp->next; 126 2192 raf if (Bp->sym_name) 127 2192 raf free(Bp->sym_name); 128 2192 raf free(Bp); 129 2192 raf } 130 0 stevel } 131 0 stevel } 132 0 stevel 133 0 stevel /* 134 0 stevel * Establishment of breakpoints on traced library functions. 135 0 stevel */ 136 0 stevel void 137 0 stevel establish_breakpoints(void) 138 0 stevel { 139 0 stevel if (Dynpat == NULL) 140 0 stevel return; 141 0 stevel 142 0 stevel /* allocate the breakpoint hash table */ 143 0 stevel if (bpt_hashtable == NULL) { 144 0 stevel bpt_hashtable = my_malloc(HASHSZ * sizeof (struct bkpt *), 145 7330 Roger NULL); 146 0 stevel (void) memset(bpt_hashtable, 0, 147 7330 Roger HASHSZ * sizeof (struct bkpt *)); 148 0 stevel } 149 0 stevel 150 0 stevel /* 151 0 stevel * Set special rtld_db event breakpoints, first time only. 152 0 stevel */ 153 0 stevel if (Rdb_agent == NULL && 154 0 stevel (Rdb_agent = Prd_agent(Proc)) != NULL) { 155 0 stevel rd_notify_t notify; 156 0 stevel struct bkpt *Bp; 157 0 stevel 158 0 stevel (void) rd_event_enable(Rdb_agent, 1); 159 0 stevel if (rd_event_addr(Rdb_agent, RD_PREINIT, ¬ify) == RD_OK && 160 0 stevel (Bp = create_bkpt(notify.u.bptaddr, 0, 1)) != NULL) 161 0 stevel Bp->flags |= BPT_PREINIT; 162 0 stevel if (rd_event_addr(Rdb_agent, RD_POSTINIT, ¬ify) == RD_OK && 163 0 stevel (Bp = create_bkpt(notify.u.bptaddr, 0, 1)) != NULL) 164 0 stevel Bp->flags |= BPT_POSTINIT; 165 0 stevel if (rd_event_addr(Rdb_agent, RD_DLACTIVITY, ¬ify) == RD_OK && 166 0 stevel (Bp = create_bkpt(notify.u.bptaddr, 0, 1)) != NULL) 167 0 stevel Bp->flags |= BPT_DLACTIVITY; 168 0 stevel } 169 0 stevel 170 0 stevel /* 171 0 stevel * Set special thread event breakpoint, first time libc is seen. 172 0 stevel */ 173 0 stevel if (Thr_agent == NULL) 174 0 stevel setup_thread_agent(); 175 0 stevel 176 0 stevel /* 177 0 stevel * Tell libproc to update its mappings. 178 0 stevel */ 179 0 stevel Pupdate_maps(Proc); 180 2192 raf 181 2192 raf /* 182 2192 raf * If rtld_db told us a library was being deleted, 183 2192 raf * first mark all of the dynlibs as not present, then 184 2192 raf * iterate over the shared objects, marking only those 185 2192 raf * present that really are present, and finally delete 186 2192 raf * all of the not-present dynlibs. 187 2192 raf */ 188 2192 raf if (delete_library) { 189 2192 raf struct dynlib **Dpp; 190 2192 raf struct dynlib *Dp; 191 2192 raf 192 7675 Edward for (Dp = Dynlib; Dp != NULL; Dp = Dp->next) 193 2192 raf Dp->present = FALSE; 194 2192 raf (void) Pobject_iter(Proc, object_present, NULL); 195 7675 Edward Dpp = &Dynlib; 196 2192 raf while ((Dp = *Dpp) != NULL) { 197 2192 raf if (Dp->present) { 198 2192 raf Dpp = &Dp->next; 199 2192 raf continue; 200 2192 raf } 201 2192 raf delete_breakpoints(Dp->base, Dp->size); 202 2192 raf *Dpp = Dp->next; 203 2192 raf free(Dp->lib_name); 204 2192 raf free(Dp->match_name); 205 2192 raf free(Dp->prt_name); 206 2192 raf free(Dp); 207 2192 raf } 208 2192 raf delete_library = FALSE; 209 2192 raf } 210 0 stevel 211 0 stevel /* 212 0 stevel * Iterate over the shared objects, creating breakpoints. 213 0 stevel */ 214 0 stevel (void) Pobject_iter(Proc, object_iter, NULL); 215 0 stevel 216 0 stevel /* 217 0 stevel * Now actually set all the breakpoints we just created. 218 0 stevel */ 219 0 stevel set_deferred_breakpoints(); 220 0 stevel } 221 0 stevel 222 0 stevel /* 223 0 stevel * Initial establishment of stacks in a newly-grabbed process. 224 0 stevel * establish_breakpoints() has already been called. 225 0 stevel */ 226 0 stevel void 227 0 stevel establish_stacks(void) 228 0 stevel { 229 0 stevel const pstatus_t *Psp = Pstatus(Proc); 230 0 stevel char mapfile[64]; 231 0 stevel int mapfd; 232 0 stevel struct stat statb; 233 0 stevel prmap_t *Pmap = NULL; 234 0 stevel int nmap = 0; 235 0 stevel ph_map_t ph_map; 236 0 stevel 237 0 stevel (void) sprintf(mapfile, "/proc/%d/rmap", (int)Psp->pr_pid); 238 0 stevel if ((mapfd = open(mapfile, O_RDONLY)) < 0 || 239 0 stevel fstat(mapfd, &statb) != 0 || 240 0 stevel statb.st_size < sizeof (prmap_t) || 241 0 stevel (Pmap = my_malloc(statb.st_size, NULL)) == NULL || 242 0 stevel (nmap = pread(mapfd, Pmap, statb.st_size, 0L)) <= 0 || 243 0 stevel (nmap /= sizeof (prmap_t)) == 0) { 244 0 stevel if (Pmap != NULL) 245 0 stevel free(Pmap); 246 0 stevel Pmap = NULL; 247 0 stevel nmap = 0; 248 0 stevel } 249 0 stevel if (mapfd >= 0) 250 0 stevel (void) close(mapfd); 251 0 stevel 252 0 stevel /* 253 0 stevel * Iterate over lwps, establishing stacks. 254 0 stevel */ 255 0 stevel ph_map.pmap = Pmap; 256 0 stevel ph_map.nmap = nmap; 257 0 stevel (void) Plwp_iter(Proc, lwp_stack_traps, &ph_map); 258 0 stevel if (Pmap != NULL) 259 0 stevel free(Pmap); 260 0 stevel 261 0 stevel if (Thr_agent == NULL) 262 0 stevel return; 263 0 stevel 264 0 stevel /* 265 0 stevel * Iterate over unbound threads, establishing stacks. 266 0 stevel */ 267 0 stevel (void) td_ta_thr_iter(Thr_agent, thr_stack_traps, NULL, 268 7330 Roger TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, 269 7330 Roger TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); 270 0 stevel } 271 0 stevel 272 0 stevel void 273 0 stevel do_symbol_iter(const char *object_name, struct dynpat *Dyp) 274 0 stevel { 275 0 stevel if (*Dyp->Dp->prt_name == '\0') 276 0 stevel object_name = PR_OBJ_EXEC; 277 0 stevel 278 0 stevel /* 279 0 stevel * Always search the dynamic symbol table. 280 0 stevel */ 281 0 stevel (void) Psymbol_iter(Proc, object_name, 282 7330 Roger PR_DYNSYM, BIND_WEAK|BIND_GLOBAL|TYPE_FUNC, 283 7330 Roger symbol_iter, Dyp); 284 0 stevel 285 0 stevel /* 286 0 stevel * Search the static symbol table if this is the 287 0 stevel * executable file or if we are being asked to 288 0 stevel * report internal calls within the library. 289 0 stevel */ 290 0 stevel if (object_name == PR_OBJ_EXEC || Dyp->internal) 291 0 stevel (void) Psymbol_iter(Proc, object_name, 292 7330 Roger PR_SYMTAB, BIND_ANY|TYPE_FUNC, 293 7330 Roger symbol_iter, Dyp); 294 0 stevel } 295 0 stevel 296 0 stevel /* ARGSUSED */ 297 0 stevel int 298 0 stevel object_iter(void *cd, const prmap_t *pmp, const char *object_name) 299 0 stevel { 300 0 stevel char name[100]; 301 0 stevel struct dynpat *Dyp; 302 0 stevel struct dynlib *Dp; 303 0 stevel const char *str; 304 0 stevel char *s; 305 0 stevel int i; 306 0 stevel 307 0 stevel if ((pmp->pr_mflags & MA_WRITE) || !(pmp->pr_mflags & MA_EXEC)) 308 0 stevel return (0); 309 0 stevel 310 0 stevel /* 311 0 stevel * Set special thread event breakpoint, first time libc is seen. 312 0 stevel */ 313 0 stevel if (Thr_agent == NULL && strstr(object_name, "/libc.so.") != NULL) 314 0 stevel setup_thread_agent(); 315 0 stevel 316 7675 Edward for (Dp = Dynlib; Dp != NULL; Dp = Dp->next) 317 0 stevel if (strcmp(object_name, Dp->lib_name) == 0 || 318 0 stevel (strcmp(Dp->lib_name, "a.out") == 0 && 319 0 stevel strcmp(pmp->pr_mapname, "a.out") == 0)) 320 0 stevel break; 321 0 stevel 322 0 stevel if (Dp == NULL) { 323 0 stevel Dp = my_malloc(sizeof (struct dynlib), NULL); 324 0 stevel (void) memset(Dp, 0, sizeof (struct dynlib)); 325 0 stevel if (strcmp(pmp->pr_mapname, "a.out") == 0) { 326 0 stevel Dp->lib_name = strdup(pmp->pr_mapname); 327 0 stevel Dp->match_name = strdup(pmp->pr_mapname); 328 0 stevel Dp->prt_name = strdup(""); 329 0 stevel } else { 330 0 stevel Dp->lib_name = strdup(object_name); 331 0 stevel if ((str = strrchr(object_name, '/')) != NULL) 332 0 stevel str++; 333 0 stevel else 334 0 stevel str = object_name; 335 0 stevel (void) strncpy(name, str, sizeof (name) - 2); 336 0 stevel name[sizeof (name) - 2] = '\0'; 337 0 stevel if ((s = strstr(name, ".so")) != NULL) 338 0 stevel *s = '\0'; 339 0 stevel Dp->match_name = strdup(name); 340 0 stevel (void) strcat(name, ":"); 341 0 stevel Dp->prt_name = strdup(name); 342 0 stevel } 343 7675 Edward Dp->next = Dynlib; 344 7675 Edward Dynlib = Dp; 345 0 stevel } 346 0 stevel 347 0 stevel if (Dp->built || 348 0 stevel (not_consist && strcmp(Dp->prt_name, "ld:") != 0)) /* kludge */ 349 0 stevel return (0); 350 0 stevel 351 0 stevel if (hflag && not_consist) 352 0 stevel (void) fprintf(stderr, "not_consist is TRUE, building %s\n", 353 7330 Roger Dp->lib_name); 354 0 stevel 355 0 stevel Dp->base = pmp->pr_vaddr; 356 0 stevel Dp->size = pmp->pr_size; 357 0 stevel 358 0 stevel /* 359 0 stevel * For every dynlib pattern that matches this library's name, 360 0 stevel * iterate through all of the library's symbols looking for 361 0 stevel * matching symbol name patterns. 362 0 stevel */ 363 0 stevel for (Dyp = Dynpat; Dyp != NULL; Dyp = Dyp->next) { 364 0 stevel if (interrupt|sigusr1) 365 0 stevel break; 366 0 stevel for (i = 0; i < Dyp->nlibpat; i++) { 367 0 stevel if (interrupt|sigusr1) 368 0 stevel break; 369 0 stevel if (fnmatch(Dyp->libpat[i], Dp->match_name, 0) != 0) 370 0 stevel continue; /* no match */ 371 0 stevel 372 0 stevel /* 373 0 stevel * Require an exact match for the executable (a.out) 374 0 stevel * and for the dynamic linker (ld.so.1). 375 0 stevel */ 376 0 stevel if ((strcmp(Dp->match_name, "a.out") == 0 || 377 0 stevel strcmp(Dp->match_name, "ld") == 0) && 378 0 stevel strcmp(Dyp->libpat[i], Dp->match_name) != 0) 379 0 stevel continue; 380 0 stevel 381 0 stevel /* 382 0 stevel * Set Dyp->Dp to Dp so symbol_iter() can use it. 383 0 stevel */ 384 0 stevel Dyp->Dp = Dp; 385 0 stevel do_symbol_iter(object_name, Dyp); 386 0 stevel Dyp->Dp = NULL; 387 0 stevel } 388 0 stevel } 389 0 stevel 390 0 stevel Dp->built = TRUE; 391 0 stevel return (interrupt | sigusr1); 392 2192 raf } 393 2192 raf 394 2192 raf /* ARGSUSED */ 395 2192 raf int 396 2192 raf object_present(void *cd, const prmap_t *pmp, const char *object_name) 397 2192 raf { 398 2192 raf struct dynlib *Dp; 399 2192 raf 400 7675 Edward for (Dp = Dynlib; Dp != NULL; Dp = Dp->next) { 401 2192 raf if (Dp->base == pmp->pr_vaddr) 402 2192 raf Dp->present = TRUE; 403 2192 raf } 404 2192 raf 405 2192 raf return (0); 406 0 stevel } 407 0 stevel 408 0 stevel /* 409 0 stevel * Search for an existing breakpoint at the 'pc' location. 410 0 stevel */ 411 0 stevel struct bkpt * 412 0 stevel get_bkpt(uintptr_t pc) 413 0 stevel { 414 0 stevel struct bkpt *Bp; 415 0 stevel 416 0 stevel for (Bp = bpt_hashtable[bpt_hash(pc)]; Bp != NULL; Bp = Bp->next) 417 0 stevel if (pc == Bp->addr) 418 0 stevel break; 419 0 stevel 420 0 stevel return (Bp); 421 0 stevel } 422 0 stevel 423 0 stevel /* 424 0 stevel * Create a breakpoint at 'pc', if one is not there already. 425 0 stevel * 'ret' is true when creating a function return breakpoint, in which case 426 0 stevel * fail and return NULL if the breakpoint would be created in writeable data. 427 0 stevel * If 'set' it true, set the breakpoint in the process now. 428 0 stevel */ 429 0 stevel struct bkpt * 430 0 stevel create_bkpt(uintptr_t pc, int ret, int set) 431 0 stevel { 432 0 stevel uint_t hix = bpt_hash(pc); 433 0 stevel struct bkpt *Bp; 434 0 stevel const prmap_t *pmp; 435 0 stevel 436 0 stevel for (Bp = bpt_hashtable[hix]; Bp != NULL; Bp = Bp->next) 437 0 stevel if (pc == Bp->addr) 438 0 stevel return (Bp); 439 0 stevel 440 0 stevel /* 441 0 stevel * Don't set return breakpoints on writeable data 442 0 stevel * or on any space other than executable text. 443 0 stevel * Don't set breakpoints in the child of a vfork() 444 0 stevel * because that would modify the parent's address space. 445 0 stevel */ 446 0 stevel if (is_vfork_child || 447 0 stevel (ret && 448 0 stevel ((pmp = Paddr_to_text_map(Proc, pc)) == NULL || 449 0 stevel !(pmp->pr_mflags & MA_EXEC) || 450 0 stevel (pmp->pr_mflags & MA_WRITE)))) 451 0 stevel return (NULL); 452 0 stevel 453 0 stevel /* create a new unnamed breakpoint */ 454 0 stevel Bp = my_malloc(sizeof (struct bkpt), NULL); 455 0 stevel Bp->sym_name = NULL; 456 0 stevel Bp->dyn = NULL; 457 0 stevel Bp->addr = pc; 458 0 stevel Bp->instr = 0; 459 0 stevel Bp->flags = 0; 460 0 stevel if (set && Psetbkpt(Proc, Bp->addr, &Bp->instr) == 0) 461 0 stevel Bp->flags |= BPT_ACTIVE; 462 0 stevel Bp->next = bpt_hashtable[hix]; 463 0 stevel bpt_hashtable[hix] = Bp; 464 0 stevel 465 0 stevel return (Bp); 466 0 stevel } 467 0 stevel 468 0 stevel /* 469 0 stevel * Set all breakpoints that haven't been set yet. 470 0 stevel * Deactivate all breakpoints from modules that are not present any more. 471 0 stevel */ 472 0 stevel void 473 0 stevel set_deferred_breakpoints(void) 474 0 stevel { 475 0 stevel struct bkpt *Bp; 476 0 stevel int i; 477 0 stevel 478 0 stevel if (is_vfork_child) 479 0 stevel return; 480 0 stevel 481 0 stevel for (i = 0; i < HASHSZ; i++) { 482 0 stevel for (Bp = bpt_hashtable[i]; Bp != NULL; Bp = Bp->next) { 483 0 stevel if (!(Bp->flags & BPT_ACTIVE)) { 484 0 stevel if (!(Bp->flags & BPT_EXCLUDE) && 485 0 stevel Psetbkpt(Proc, Bp->addr, &Bp->instr) == 0) 486 0 stevel Bp->flags |= BPT_ACTIVE; 487 0 stevel } else if (Paddr_to_text_map(Proc, Bp->addr) == NULL) { 488 0 stevel Bp->flags &= ~BPT_ACTIVE; 489 0 stevel } 490 0 stevel } 491 0 stevel } 492 0 stevel } 493 0 stevel 494 0 stevel int 495 0 stevel symbol_iter(void *cd, const GElf_Sym *sym, const char *sym_name) 496 0 stevel { 497 0 stevel struct dynpat *Dyp = cd; 498 0 stevel struct dynlib *Dp = Dyp->Dp; 499 0 stevel uintptr_t pc = sym->st_value; 500 0 stevel struct bkpt *Bp; 501 0 stevel int i; 502 0 stevel 503 0 stevel /* ignore any undefined symbols */ 504 0 stevel if (sym->st_shndx == SHN_UNDEF) 505 0 stevel return (0); 506 0 stevel 507 0 stevel /* 508 0 stevel * Arbitrarily omit "_start" from the executable. 509 0 stevel * (Avoid indentation before main().) 510 0 stevel */ 511 0 stevel if (*Dp->prt_name == '\0' && strcmp(sym_name, "_start") == 0) 512 0 stevel return (0); 513 0 stevel 514 0 stevel /* 515 0 stevel * Arbitrarily omit "_rt_boot" from the dynamic linker. 516 0 stevel * (Avoid indentation before main().) 517 0 stevel */ 518 0 stevel if (strcmp(Dp->match_name, "ld") == 0 && 519 0 stevel strcmp(sym_name, "_rt_boot") == 0) 520 0 stevel return (0); 521 0 stevel 522 0 stevel /* 523 0 stevel * Arbitrarily omit any symbols whose name starts with '.'. 524 0 stevel * Apparantly putting a breakpoint on .umul causes a 525 0 stevel * fatal error in libthread (%y is not restored correctly 526 0 stevel * when a single step is taken). Looks like a /proc bug. 527 0 stevel */ 528 0 stevel if (*sym_name == '.') 529 0 stevel return (0); 530 0 stevel 531 0 stevel /* 532 0 stevel * For each pattern in the array of symbol patterns, 533 0 stevel * if the pattern matches the symbol name, then 534 0 stevel * create a breakpoint at the function in question. 535 0 stevel */ 536 0 stevel for (i = 0; i < Dyp->nsympat; i++) { 537 0 stevel if (interrupt|sigusr1) 538 0 stevel break; 539 0 stevel if (fnmatch(Dyp->sympat[i], sym_name, 0) != 0) 540 0 stevel continue; 541 0 stevel 542 0 stevel if ((Bp = create_bkpt(pc, 0, 0)) == NULL) /* can't fail */ 543 0 stevel return (0); 544 0 stevel 545 0 stevel /* 546 0 stevel * New breakpoints receive a name now. 547 0 stevel * For existing breakpoints, prefer the subset name if possible, 548 0 stevel * else prefer the shorter name. 549 0 stevel */ 550 0 stevel if (Bp->sym_name == NULL) { 551 0 stevel Bp->sym_name = strdup(sym_name); 552 0 stevel } else if (strstr(Bp->sym_name, sym_name) != NULL || 553 0 stevel strlen(Bp->sym_name) > strlen(sym_name)) { 554 0 stevel free(Bp->sym_name); 555 0 stevel Bp->sym_name = strdup(sym_name); 556 0 stevel } 557 0 stevel Bp->dyn = Dp; 558 0 stevel Bp->flags |= Dyp->flag; 559 0 stevel if (Dyp->exclude) 560 0 stevel Bp->flags |= BPT_EXCLUDE; 561 0 stevel else if (Dyp->internal || *Dp->prt_name == '\0') 562 0 stevel Bp->flags |= BPT_INTERNAL; 563 0 stevel return (0); 564 0 stevel } 565 0 stevel 566 0 stevel return (interrupt | sigusr1); 567 0 stevel } 568 0 stevel 569 0 stevel /* For debugging only ---- */ 570 0 stevel void 571 0 stevel report_htable_stats(void) 572 0 stevel { 573 0 stevel const pstatus_t *Psp = Pstatus(Proc); 574 0 stevel struct callstack *Stk; 575 0 stevel struct bkpt *Bp; 576 0 stevel uint_t Min = 1000000; 577 0 stevel uint_t Max = 0; 578 0 stevel uint_t Avg = 0; 579 0 stevel uint_t Total = 0; 580 0 stevel uint_t i, j; 581 0 stevel uint_t bucket[HASHSZ]; 582 0 stevel 583 0 stevel if (Dynpat == NULL || !hflag) 584 0 stevel return; 585 0 stevel 586 0 stevel hflag = FALSE; 587 0 stevel (void) memset(bucket, 0, sizeof (bucket)); 588 0 stevel 589 0 stevel for (i = 0; i < HASHSZ; i++) { 590 0 stevel j = 0; 591 0 stevel for (Bp = bpt_hashtable[i]; Bp != NULL; Bp = Bp->next) 592 0 stevel j++; 593 0 stevel if (j < Min) 594 0 stevel Min = j; 595 0 stevel if (j > Max) 596 0 stevel Max = j; 597 0 stevel if (j < HASHSZ) 598 0 stevel bucket[j]++; 599 0 stevel Total += j; 600 0 stevel } 601 0 stevel Avg = (Total + HASHSZ / 2) / HASHSZ; 602 0 stevel (void) fprintf(stderr, "truss hash table statistics --------\n"); 603 0 stevel (void) fprintf(stderr, " Total = %u\n", Total); 604 0 stevel (void) fprintf(stderr, " Min = %u\n", Min); 605 0 stevel (void) fprintf(stderr, " Max = %u\n", Max); 606 0 stevel (void) fprintf(stderr, " Avg = %u\n", Avg); 607 0 stevel for (i = 0; i < HASHSZ; i++) 608 0 stevel if (bucket[i]) 609 0 stevel (void) fprintf(stderr, " %3u buckets of size %d\n", 610 7330 Roger bucket[i], i); 611 0 stevel 612 0 stevel (void) fprintf(stderr, "truss-detected stacks --------\n"); 613 0 stevel for (Stk = callstack; Stk != NULL; Stk = Stk->next) { 614 0 stevel (void) fprintf(stderr, 615 7330 Roger " base = 0x%.8lx end = 0x%.8lx size = %ld\n", 616 7330 Roger (ulong_t)Stk->stkbase, 617 7330 Roger (ulong_t)Stk->stkend, 618 7330 Roger (ulong_t)(Stk->stkend - Stk->stkbase)); 619 0 stevel } 620 0 stevel (void) fprintf(stderr, "primary unix stack --------\n"); 621 0 stevel (void) fprintf(stderr, 622 7330 Roger " base = 0x%.8lx end = 0x%.8lx size = %ld\n", 623 7330 Roger (ulong_t)Psp->pr_stkbase, 624 7330 Roger (ulong_t)(Psp->pr_stkbase + Psp->pr_stksize), 625 7330 Roger (ulong_t)Psp->pr_stksize); 626 0 stevel (void) fprintf(stderr, "nthr_create = %u\n", nthr_create); 627 0 stevel } 628 0 stevel 629 0 stevel void 630 0 stevel make_lwp_stack(const lwpstatus_t *Lsp, prmap_t *Pmap, int nmap) 631 0 stevel { 632 0 stevel const pstatus_t *Psp = Pstatus(Proc); 633 0 stevel uintptr_t sp = Lsp->pr_reg[R_SP]; 634 0 stevel id_t lwpid = Lsp->pr_lwpid; 635 0 stevel struct callstack *Stk; 636 0 stevel td_thrhandle_t th; 637 0 stevel td_thrinfo_t thrinfo; 638 0 stevel 639 0 stevel if (data_model != PR_MODEL_LP64) 640 0 stevel sp = (uint32_t)sp; 641 0 stevel 642 0 stevel /* check to see if we already have this stack */ 643 0 stevel if (sp == 0) 644 0 stevel return; 645 0 stevel for (Stk = callstack; Stk != NULL; Stk = Stk->next) 646 0 stevel if (sp >= Stk->stkbase && sp < Stk->stkend) 647 0 stevel return; 648 0 stevel 649 0 stevel Stk = my_malloc(sizeof (struct callstack), NULL); 650 0 stevel Stk->next = callstack; 651 0 stevel callstack = Stk; 652 0 stevel nstack++; 653 0 stevel Stk->tref = 0; 654 0 stevel Stk->tid = 0; 655 0 stevel Stk->nthr_create = 0; 656 0 stevel Stk->ncall = 0; 657 0 stevel Stk->maxcall = DEF_MAXCALL; 658 0 stevel Stk->stack = my_malloc(DEF_MAXCALL * sizeof (*Stk->stack), NULL); 659 0 stevel 660 0 stevel /* primary stack */ 661 0 stevel if (sp >= Psp->pr_stkbase && sp < Psp->pr_stkbase + Psp->pr_stksize) { 662 0 stevel Stk->stkbase = Psp->pr_stkbase; 663 0 stevel Stk->stkend = Stk->stkbase + Psp->pr_stksize; 664 0 stevel return; 665 0 stevel } 666 0 stevel 667 0 stevel /* alternate stack */ 668 0 stevel if ((Lsp->pr_altstack.ss_flags & SS_ONSTACK) && 669 0 stevel sp >= (uintptr_t)Lsp->pr_altstack.ss_sp && 670 0 stevel sp < (uintptr_t)Lsp->pr_altstack.ss_sp 671 0 stevel + Lsp->pr_altstack.ss_size) { 672 0 stevel Stk->stkbase = (uintptr_t)Lsp->pr_altstack.ss_sp; 673 0 stevel Stk->stkend = Stk->stkbase + Lsp->pr_altstack.ss_size; 674 0 stevel return; 675 0 stevel } 676 0 stevel 677 0 stevel /* thread stacks? */ 678 0 stevel if (Thr_agent != NULL && 679 0 stevel td_ta_map_lwp2thr(Thr_agent, lwpid, &th) == TD_OK && 680 0 stevel td_thr_get_info(&th, &thrinfo) == TD_OK && 681 0 stevel sp >= (uintptr_t)thrinfo.ti_stkbase - thrinfo.ti_stksize && 682 0 stevel sp < (uintptr_t)thrinfo.ti_stkbase) { 683 0 stevel /* The bloody fools got this backwards! */ 684 0 stevel Stk->stkend = (uintptr_t)thrinfo.ti_stkbase; 685 0 stevel Stk->stkbase = Stk->stkend - thrinfo.ti_stksize; 686 0 stevel return; 687 0 stevel } 688 0 stevel 689 0 stevel /* last chance -- try the raw memory map */ 690 0 stevel for (; nmap; nmap--, Pmap++) { 691 0 stevel if (sp >= Pmap->pr_vaddr && 692 0 stevel sp < Pmap->pr_vaddr + Pmap->pr_size) { 693 0 stevel Stk->stkbase = Pmap->pr_vaddr; 694 0 stevel Stk->stkend = Pmap->pr_vaddr + Pmap->pr_size; 695 0 stevel return; 696 0 stevel } 697 0 stevel } 698 0 stevel 699 0 stevel callstack = Stk->next; 700 0 stevel nstack--; 701 0 stevel free(Stk->stack); 702 0 stevel free(Stk); 703 0 stevel } 704 0 stevel 705 0 stevel void 706 0 stevel make_thr_stack(const td_thrhandle_t *Thp, prgregset_t reg) 707 0 stevel { 708 0 stevel const pstatus_t *Psp = Pstatus(Proc); 709 0 stevel td_thrinfo_t thrinfo; 710 0 stevel uintptr_t sp = reg[R_SP]; 711 0 stevel struct callstack *Stk; 712 0 stevel 713 0 stevel if (data_model != PR_MODEL_LP64) 714 0 stevel sp = (uint32_t)sp; 715 0 stevel 716 0 stevel /* check to see if we already have this stack */ 717 0 stevel if (sp == 0) 718 0 stevel return; 719 0 stevel for (Stk = callstack; Stk != NULL; Stk = Stk->next) 720 0 stevel if (sp >= Stk->stkbase && sp < Stk->stkend) 721 0 stevel return; 722 0 stevel 723 0 stevel Stk = my_malloc(sizeof (struct callstack), NULL); 724 0 stevel Stk->next = callstack; 725 0 stevel callstack = Stk; 726 0 stevel nstack++; 727 0 stevel Stk->tref = 0; 728 0 stevel Stk->tid = 0; 729 0 stevel Stk->nthr_create = 0; 730 0 stevel Stk->ncall = 0; 731 0 stevel Stk->maxcall = DEF_MAXCALL; 732 0 stevel Stk->stack = my_malloc(DEF_MAXCALL * sizeof (*Stk->stack), NULL); 733 0 stevel 734 0 stevel /* primary stack */ 735 0 stevel if (sp >= Psp->pr_stkbase && sp < Psp->pr_stkbase + Psp->pr_stksize) { 736 0 stevel Stk->stkbase = Psp->pr_stkbase; 737 0 stevel Stk->stkend = Stk->stkbase + Psp->pr_stksize; 738 0 stevel return; 739 0 stevel } 740 0 stevel 741 0 stevel if (td_thr_get_info(Thp, &thrinfo) == TD_OK && 742 0 stevel sp >= (uintptr_t)thrinfo.ti_stkbase - thrinfo.ti_stksize && 743 0 stevel sp < (uintptr_t)thrinfo.ti_stkbase) { 744 0 stevel /* The bloody fools got this backwards! */ 745 0 stevel Stk->stkend = (uintptr_t)thrinfo.ti_stkbase; 746 0 stevel Stk->stkbase = Stk->stkend - thrinfo.ti_stksize; 747 0 stevel return; 748 0 stevel } 749 0 stevel 750 0 stevel callstack = Stk->next; 751 0 stevel nstack--; 752 0 stevel free(Stk->stack); 753 0 stevel free(Stk); 754 0 stevel } 755 0 stevel 756 0 stevel struct callstack * 757 0 stevel find_lwp_stack(uintptr_t sp) 758 0 stevel { 759 0 stevel const pstatus_t *Psp = Pstatus(Proc); 760 0 stevel char mapfile[64]; 761 0 stevel int mapfd; 762 0 stevel struct stat statb; 763 0 stevel prmap_t *Pmap = NULL; 764 0 stevel prmap_t *pmap = NULL; 765 0 stevel int nmap = 0; 766 0 stevel struct callstack *Stk = NULL; 767 0 stevel 768 0 stevel /* 769 0 stevel * Get the address space map. 770 0 stevel */ 771 0 stevel (void) sprintf(mapfile, "/proc/%d/rmap", (int)Psp->pr_pid); 772 0 stevel if ((mapfd = open(mapfile, O_RDONLY)) < 0 || 773 0 stevel fstat(mapfd, &statb) != 0 || 774 0 stevel statb.st_size < sizeof (prmap_t) || 775 0 stevel (Pmap = my_malloc(statb.st_size, NULL)) == NULL || 776 0 stevel (nmap = pread(mapfd, Pmap, statb.st_size, 0L)) <= 0 || 777 0 stevel (nmap /= sizeof (prmap_t)) == 0) { 778 0 stevel if (Pmap != NULL) 779 0 stevel free(Pmap); 780 0 stevel if (mapfd >= 0) 781 0 stevel (void) close(mapfd); 782 0 stevel return (NULL); 783 0 stevel } 784 0 stevel (void) close(mapfd); 785 0 stevel 786 0 stevel for (pmap = Pmap; nmap--; pmap++) { 787 0 stevel if (sp >= pmap->pr_vaddr && 788 0 stevel sp < pmap->pr_vaddr + pmap->pr_size) { 789 0 stevel Stk = my_malloc(sizeof (struct callstack), NULL); 790 0 stevel Stk->next = callstack; 791 0 stevel callstack = Stk; 792 0 stevel nstack++; 793 0 stevel Stk->stkbase = pmap->pr_vaddr; 794 0 stevel Stk->stkend = pmap->pr_vaddr + pmap->pr_size; 795 0 stevel Stk->tref = 0; 796 0 stevel Stk->tid = 0; 797 0 stevel Stk->nthr_create = 0; 798 0 stevel Stk->ncall = 0; 799 0 stevel Stk->maxcall = DEF_MAXCALL; 800 0 stevel Stk->stack = my_malloc( 801 7330 Roger DEF_MAXCALL * sizeof (*Stk->stack), NULL); 802 0 stevel break; 803 0 stevel } 804 0 stevel } 805 0 stevel 806 0 stevel free(Pmap); 807 0 stevel return (Stk); 808 0 stevel } 809 0 stevel 810 0 stevel struct callstack * 811 0 stevel find_stack(uintptr_t sp) 812 0 stevel { 813 0 stevel const pstatus_t *Psp = Pstatus(Proc); 814 0 stevel private_t *pri = get_private(); 815 0 stevel const lwpstatus_t *Lsp = pri->lwpstat; 816 0 stevel id_t lwpid = Lsp->pr_lwpid; 817 0 stevel #if defined(__sparc) 818 0 stevel prgreg_t tref = Lsp->pr_reg[R_G7]; 819 0 stevel #elif defined(__amd64) 820 0 stevel prgreg_t tref = Lsp->pr_reg[REG_FS]; 821 0 stevel #elif defined(__i386) 822 0 stevel prgreg_t tref = Lsp->pr_reg[GS]; 823 0 stevel #endif 824 0 stevel struct callstack *Stk = NULL; 825 0 stevel td_thrhandle_t th; 826 0 stevel td_thrinfo_t thrinfo; 827 0 stevel td_err_e error; 828 0 stevel 829 0 stevel /* primary stack */ 830 0 stevel if (sp >= Psp->pr_stkbase && sp < Psp->pr_stkbase + Psp->pr_stksize) { 831 0 stevel Stk = my_malloc(sizeof (struct callstack), NULL); 832 0 stevel Stk->next = callstack; 833 0 stevel callstack = Stk; 834 0 stevel nstack++; 835 0 stevel Stk->stkbase = Psp->pr_stkbase; 836 0 stevel Stk->stkend = Stk->stkbase + Psp->pr_stksize; 837 0 stevel Stk->tref = 0; 838 0 stevel Stk->tid = 0; 839 0 stevel Stk->nthr_create = 0; 840 0 stevel Stk->ncall = 0; 841 0 stevel Stk->maxcall = DEF_MAXCALL; 842 0 stevel Stk->stack = my_malloc(DEF_MAXCALL * sizeof (*Stk->stack), 843 7330 Roger NULL); 844 0 stevel return (Stk); 845 0 stevel } 846 0 stevel 847 0 stevel /* alternate stack */ 848 0 stevel if ((Lsp->pr_altstack.ss_flags & SS_ONSTACK) && 849 0 stevel sp >= (uintptr_t)Lsp->pr_altstack.ss_sp && 850 0 stevel sp < (uintptr_t)Lsp->pr_altstack.ss_sp 851 0 stevel + Lsp->pr_altstack.ss_size) { 852 0 stevel Stk = my_malloc(sizeof (struct callstack), NULL); 853 0 stevel Stk->next = callstack; 854 0 stevel callstack = Stk; 855 0 stevel nstack++; 856 0 stevel Stk->stkbase = (uintptr_t)Lsp->pr_altstack.ss_sp; 857 0 stevel Stk->stkend = Stk->stkbase + Lsp->pr_altstack.ss_size; 858 0 stevel Stk->tref = 0; 859 0 stevel Stk->tid = 0; 860 0 stevel Stk->nthr_create = 0; 861 0 stevel Stk->ncall = 0; 862 0 stevel Stk->maxcall = DEF_MAXCALL; 863 0 stevel Stk->stack = my_malloc(DEF_MAXCALL * sizeof (*Stk->stack), 864 7330 Roger NULL); 865 0 stevel return (Stk); 866 0 stevel } 867 0 stevel 868 0 stevel if (Thr_agent == NULL) 869 0 stevel return (find_lwp_stack(sp)); 870 0 stevel 871 0 stevel /* thread stacks? */ 872 0 stevel if ((error = td_ta_map_lwp2thr(Thr_agent, lwpid, &th)) != TD_OK) { 873 0 stevel if (hflag) 874 0 stevel (void) fprintf(stderr, 875 7330 Roger "cannot get thread handle for " 876 7330 Roger "lwp#%d, error=%d, tref=0x%.8lx\n", 877 7330 Roger (int)lwpid, error, (long)tref); 878 0 stevel return (NULL); 879 0 stevel } 880 0 stevel 881 0 stevel if ((error = td_thr_get_info(&th, &thrinfo)) != TD_OK) { 882 0 stevel if (hflag) 883 0 stevel (void) fprintf(stderr, 884 7330 Roger "cannot get thread info for " 885 7330 Roger "lwp#%d, error=%d, tref=0x%.8lx\n", 886 7330 Roger (int)lwpid, error, (long)tref); 887 0 stevel return (NULL); 888 0 stevel } 889 0 stevel 890 0 stevel if (sp >= (uintptr_t)thrinfo.ti_stkbase - thrinfo.ti_stksize && 891 0 stevel sp < (uintptr_t)thrinfo.ti_stkbase) { 892 0 stevel Stk = my_malloc(sizeof (struct callstack), NULL); 893 0 stevel Stk->next = callstack; 894 0 stevel callstack = Stk; 895 0 stevel nstack++; 896 0 stevel /* The bloody fools got this backwards! */ 897 0 stevel Stk->stkend = (uintptr_t)thrinfo.ti_stkbase; 898 0 stevel Stk->stkbase = Stk->stkend - thrinfo.ti_stksize; 899 0 stevel Stk->tref = tref; 900 0 stevel Stk->tid = thrinfo.ti_tid; 901 0 stevel Stk->nthr_create = nthr_create; 902 0 stevel Stk->ncall = 0; 903 0 stevel Stk->maxcall = DEF_MAXCALL; 904 0 stevel Stk->stack = my_malloc(DEF_MAXCALL * sizeof (*Stk->stack), 905 7330 Roger NULL); 906 0 stevel return (Stk); 907 0 stevel } 908 0 stevel 909 0 stevel /* stack bounds failure -- complain bitterly */ 910 0 stevel if (hflag) { 911 0 stevel (void) fprintf(stderr, 912 7330 Roger "sp not within thread stack: " 913 7330 Roger "sp=0x%.8lx stkbase=0x%.8lx stkend=0x%.8lx\n", 914 7330 Roger (ulong_t)sp, 915 7330 Roger /* The bloody fools got this backwards! */ 916 7330 Roger (ulong_t)thrinfo.ti_stkbase - thrinfo.ti_stksize, 917 7330 Roger (ulong_t)thrinfo.ti_stkbase); 918 0 stevel } 919 0 stevel 920 0 stevel return (NULL); 921 0 stevel } 922 0 stevel 923 0 stevel void 924 0 stevel get_tid(struct callstack *Stk) 925 0 stevel { 926 0 stevel private_t *pri = get_private(); 927 0 stevel const lwpstatus_t *Lsp = pri->lwpstat; 928 0 stevel id_t lwpid = Lsp->pr_lwpid; 929 0 stevel #if defined(__sparc) 930 0 stevel prgreg_t tref = Lsp->pr_reg[R_G7]; 931 0 stevel #elif defined(__amd64) 932 0 stevel prgreg_t tref = (data_model == PR_MODEL_LP64) ? 933 0 stevel Lsp->pr_reg[REG_FS] : Lsp->pr_reg[REG_GS]; 934 0 stevel #elif defined(__i386) 935 0 stevel prgreg_t tref = Lsp->pr_reg[GS]; 936 0 stevel #endif 937 0 stevel td_thrhandle_t th; 938 0 stevel td_thrinfo_t thrinfo; 939 0 stevel td_err_e error; 940 0 stevel 941 0 stevel if (Thr_agent == NULL) { 942 0 stevel Stk->tref = 0; 943 0 stevel Stk->tid = 0; 944 0 stevel Stk->nthr_create = 0; 945 0 stevel return; 946 0 stevel } 947 0 stevel 948 0 stevel /* 949 0 stevel * Shortcut here -- 950 0 stevel * If we have a matching tref and no new threads have 951 0 stevel * been created since the last time we encountered this 952 0 stevel * stack, then we don't have to go through the overhead 953 0 stevel * of calling td_ta_map_lwp2thr() to get the thread-id. 954 0 stevel */ 955 0 stevel if (tref == Stk->tref && Stk->nthr_create == nthr_create) 956 0 stevel return; 957 0 stevel 958 0 stevel if ((error = td_ta_map_lwp2thr(Thr_agent, lwpid, &th)) != TD_OK) { 959 0 stevel if (hflag) 960 0 stevel (void) fprintf(stderr, 961 7330 Roger "cannot get thread handle for " 962 7330 Roger "lwp#%d, error=%d, tref=0x%.8lx\n", 963 7330 Roger (int)lwpid, error, (long)tref); 964 0 stevel Stk->tref = 0; 965 0 stevel Stk->tid = 0; 966 0 stevel Stk->nthr_create = 0; 967 0 stevel } else if ((error = td_thr_get_info(&th, &thrinfo)) != TD_OK) { 968 0 stevel if (hflag) 969 0 stevel (void) fprintf(stderr, 970 7330 Roger "cannot get thread info for " 971 7330 Roger "lwp#%d, error=%d, tref=0x%.8lx\n", 972 7330 Roger (int)lwpid, error, (long)tref); 973 0 stevel Stk->tref = 0; 974 0 stevel Stk->tid = 0; 975 0 stevel Stk->nthr_create = 0; 976 0 stevel } else { 977 0 stevel Stk->tref = tref; 978 0 stevel Stk->tid = thrinfo.ti_tid; 979 0 stevel Stk->nthr_create = nthr_create; 980 0 stevel } 981 0 stevel } 982 0 stevel 983 0 stevel struct callstack * 984 0 stevel callstack_info(uintptr_t sp, uintptr_t fp, int makeid) 985 0 stevel { 986 0 stevel struct callstack *Stk; 987 0 stevel uintptr_t trash; 988 0 stevel 989 0 stevel if (sp == 0 || 990 0 stevel Pread(Proc, &trash, sizeof (trash), sp) != sizeof (trash)) 991 0 stevel return (NULL); 992 0 stevel 993 0 stevel for (Stk = callstack; Stk != NULL; Stk = Stk->next) 994 0 stevel if (sp >= Stk->stkbase && sp < Stk->stkend) 995 0 stevel break; 996 0 stevel 997 0 stevel /* 998 0 stevel * If we didn't find the stack, do it the hard way. 999 0 stevel */ 1000 0 stevel if (Stk == NULL) { 1001 0 stevel uintptr_t stkbase = sp; 1002 0 stevel uintptr_t stkend; 1003 0 stevel uint_t minsize; 1004 0 stevel 1005 0 stevel #if defined(i386) || defined(__amd64) 1006 0 stevel #ifdef _LP64 1007 0 stevel if (data_model == PR_MODEL_LP64) 1008 0 stevel minsize = 2 * sizeof (uintptr_t); /* fp + pc */ 1009 0 stevel else 1010 0 stevel #endif 1011 0 stevel minsize = 2 * sizeof (uint32_t); 1012 0 stevel #else 1013 0 stevel #ifdef _LP64 1014 0 stevel if (data_model != PR_MODEL_LP64) 1015 0 stevel minsize = SA32(MINFRAME32); 1016 0 stevel else 1017 0 stevel minsize = SA64(MINFRAME64); 1018 0 stevel #else 1019 0 stevel minsize = SA(MINFRAME); 1020 0 stevel #endif 1021 0 stevel #endif /* i386 */ 1022 0 stevel stkend = sp + minsize; 1023 0 stevel 1024 0 stevel while (Stk == NULL && fp != 0 && fp >= sp) { 1025 0 stevel stkend = fp + minsize; 1026 0 stevel for (Stk = callstack; Stk != NULL; Stk = Stk->next) 1027 0 stevel if ((fp >= Stk->stkbase && fp < Stk->stkend) || 1028 0 stevel (stkend > Stk->stkbase && 1029 0 stevel stkend <= Stk->stkend)) 1030 0 stevel break; 1031 0 stevel if (Stk == NULL) 1032 0 stevel fp = previous_fp(fp, NULL); 1033 0 stevel } 1034 0 stevel 1035 0 stevel if (Stk != NULL) /* the stack grew */ 1036 0 stevel Stk->stkbase = stkbase; 1037 0 stevel } 1038 0 stevel 1039 0 stevel if (Stk == NULL && makeid) /* new stack */ 1040 0 stevel Stk = find_stack(sp); 1041 0 stevel 1042 0 stevel if (Stk == NULL) 1043 0 stevel return (NULL); 1044 0 stevel 1045 0 stevel /* 1046 0 stevel * Ensure that there is room for at least one more entry. 1047 0 stevel */ 1048 0 stevel if (Stk->ncall == Stk->maxcall) { 1049 0 stevel Stk->maxcall *= 2; 1050 0 stevel Stk->stack = my_realloc(Stk->stack, 1051 0 stevel Stk->maxcall * sizeof (*Stk->stack), NULL); 1052 0 stevel } 1053 0 stevel 1054 0 stevel if (makeid) 1055 0 stevel get_tid(Stk); 1056 0 stevel 1057 0 stevel return (Stk); 1058 0 stevel } 1059 0 stevel 1060 0 stevel /* 1061 0 stevel * Reset the breakpoint information (called on successful exec()). 1062 0 stevel */ 1063 0 stevel void 1064 0 stevel reset_breakpoints(void) 1065 0 stevel { 1066 0 stevel struct dynlib *Dp; 1067 0 stevel struct bkpt *Bp; 1068 0 stevel struct callstack *Stk; 1069 0 stevel int i; 1070 0 stevel 1071 0 stevel if (Dynpat == NULL) 1072 0 stevel return; 1073 0 stevel 1074 0 stevel /* destroy all previous dynamic library information */ 1075 7675 Edward while ((Dp = Dynlib) != NULL) { 1076 7675 Edward Dynlib = Dp->next; 1077 0 stevel free(Dp->lib_name); 1078 0 stevel free(Dp->match_name); 1079 0 stevel free(Dp->prt_name); 1080 0 stevel free(Dp); 1081 0 stevel } 1082 0 stevel 1083 0 stevel /* destroy all previous breakpoint trap information */ 1084 0 stevel if (bpt_hashtable != NULL) { 1085 0 stevel for (i = 0; i < HASHSZ; i++) { 1086 0 stevel while ((Bp = bpt_hashtable[i]) != NULL) { 1087 0 stevel bpt_hashtable[i] = Bp->next; 1088 0 stevel if (Bp->sym_name) 1089 0 stevel free(Bp->sym_name); 1090 0 stevel free(Bp); 1091 0 stevel } 1092 0 stevel } 1093 0 stevel } 1094 0 stevel 1095 0 stevel /* destroy all the callstack information */ 1096 0 stevel while ((Stk = callstack) != NULL) { 1097 0 stevel callstack = Stk->next; 1098 0 stevel free(Stk->stack); 1099 0 stevel free(Stk); 1100 0 stevel } 1101 0 stevel 1102 0 stevel /* we are not a multi-threaded process anymore */ 1103 0 stevel if (Thr_agent != NULL) 1104 0 stevel (void) td_ta_delete(Thr_agent); 1105 0 stevel Thr_agent = NULL; 1106 0 stevel 1107 0 stevel /* tell libproc to clear out its mapping information */ 1108 0 stevel Preset_maps(Proc); 1109 0 stevel Rdb_agent = NULL; 1110 0 stevel 1111 0 stevel /* Reestablish the symbols from the executable */ 1112 0 stevel (void) establish_breakpoints(); 1113 0 stevel } 1114 0 stevel 1115 0 stevel /* 1116 0 stevel * Clear breakpoints from the process (called before Prelease()). 1117 0 stevel * Don't actually destroy the breakpoint table; 1118 0 stevel * threads currently fielding breakpoints will need it. 1119 0 stevel */ 1120 0 stevel void 1121 0 stevel clear_breakpoints(void) 1122 0 stevel { 1123 0 stevel struct bkpt *Bp; 1124 0 stevel int i; 1125 0 stevel 1126 0 stevel if (Dynpat == NULL) 1127 0 stevel return; 1128 0 stevel 1129 0 stevel /* 1130 0 stevel * Change all breakpoint traps back to normal instructions. 1131 0 stevel * We attempt to remove a breakpoint from every address which 1132 0 stevel * may have ever contained a breakpoint to protect our victims. 1133 0 stevel */ 1134 0 stevel report_htable_stats(); /* report stats first */ 1135 0 stevel for (i = 0; i < HASHSZ; i++) { 1136 0 stevel for (Bp = bpt_hashtable[i]; Bp != NULL; Bp = Bp->next) { 1137 0 stevel if (Bp->flags & BPT_ACTIVE) 1138 0 stevel (void) Pdelbkpt(Proc, Bp->addr, Bp->instr); 1139 0 stevel Bp->flags &= ~BPT_ACTIVE; 1140 0 stevel } 1141 0 stevel } 1142 0 stevel 1143 0 stevel if (Thr_agent != NULL) { 1144 0 stevel td_thr_events_t events; 1145 0 stevel 1146 7330 Roger td_event_fillset(&events); 1147 7330 Roger (void) td_ta_clear_event(Thr_agent, &events); 1148 0 stevel (void) td_ta_delete(Thr_agent); 1149 0 stevel } 1150 0 stevel Thr_agent = NULL; 1151 0 stevel } 1152 0 stevel 1153 0 stevel /* 1154 0 stevel * Reestablish the breakpoint traps in the process. 1155 0 stevel * Called after resuming from a vfork() in the parent. 1156 0 stevel */ 1157 0 stevel void 1158 0 stevel reestablish_traps(void) 1159 0 stevel { 1160 0 stevel struct bkpt *Bp; 1161 0 stevel ulong_t instr; 1162 0 stevel int i; 1163 0 stevel 1164 0 stevel if (Dynpat == NULL || is_vfork_child) 1165 0 stevel return; 1166 0 stevel 1167 0 stevel for (i = 0; i < HASHSZ; i++) { 1168 0 stevel for (Bp = bpt_hashtable[i]; Bp != NULL; Bp = Bp->next) { 1169 0 stevel if ((Bp->flags & BPT_ACTIVE) && 1170 0 stevel Psetbkpt(Proc, Bp->addr, &instr) != 0) 1171 0 stevel Bp->flags &= ~BPT_ACTIVE; 1172 0 stevel } 1173 0 stevel } 1174 0 stevel } 1175 0 stevel 1176 0 stevel void 1177 0 stevel show_function_call(private_t *pri, 1178 0 stevel struct callstack *Stk, struct dynlib *Dp, struct bkpt *Bp) 1179 0 stevel { 1180 0 stevel long arg[8]; 1181 0 stevel int narg; 1182 0 stevel int i; 1183 0 stevel 1184 0 stevel narg = get_arguments(arg); 1185 0 stevel make_pname(pri, (Stk != NULL)? Stk->tid : 0); 1186 0 stevel putpname(pri); 1187 0 stevel timestamp(pri); 1188 0 stevel if (Stk != NULL) { 1189 0 stevel for (i = 1; i < Stk->ncall; i++) { 1190 0 stevel (void) fputc(' ', stdout); 1191 0 stevel (void) fputc(' ', stdout); 1192 0 stevel } 1193 0 stevel } 1194 0 stevel (void) printf("-> %s%s(", Dp->prt_name, Bp->sym_name); 1195 0 stevel for (i = 0; i < narg; i++) { 1196 0 stevel (void) printf("0x%lx", arg[i]); 1197 0 stevel if (i < narg-1) { 1198 0 stevel (void) fputc(',', stdout); 1199 0 stevel (void) fputc(' ', stdout); 1200 0 stevel } 1201 0 stevel } 1202 0 stevel (void) printf(")\n"); 1203 0 stevel Flush(); 1204 0 stevel } 1205 0 stevel 1206 0 stevel /* ARGSUSED */ 1207 0 stevel void 1208 0 stevel show_function_return(private_t *pri, long rval, int stret, 1209 0 stevel struct callstack *Stk, struct dynlib *Dp, struct bkpt *Bp) 1210 0 stevel { 1211 0 stevel int i; 1212 0 stevel 1213 0 stevel make_pname(pri, Stk->tid); 1214 0 stevel putpname(pri); 1215 0 stevel timestamp(pri); 1216 0 stevel for (i = 0; i < Stk->ncall; i++) { 1217 0 stevel (void) fputc(' ', stdout); 1218 0 stevel (void) fputc(' ', stdout); 1219 0 stevel } 1220 0 stevel (void) printf("<- %s%s() = ", Dp->prt_name, Bp->sym_name); 1221 0 stevel if (stret) { 1222 0 stevel (void) printf("struct return\n"); 1223 0 stevel } else if (data_model == PR_MODEL_LP64) { 1224 0 stevel if (rval >= (64 * 1024) || -rval >= (64 * 1024)) 1225 0 stevel (void) printf("0x%lx\n", rval); 1226 0 stevel else 1227 0 stevel (void) printf("%ld\n", rval); 1228 0 stevel } else { 1229 0 stevel int rval32 = (int)rval; 1230 0 stevel if (rval32 >= (64 * 1024) || -rval32 >= (64 * 1024)) 1231 0 stevel (void) printf("0x%x\n", rval32); 1232 0 stevel else 1233 0 stevel (void) printf("%d\n", rval32); 1234 0 stevel } 1235 0 stevel Flush(); 1236 0 stevel } 1237 0 stevel 1238 0 stevel /* 1239 0 stevel * Called to deal with function-call tracing. 1240 0 stevel * Return 0 on normal success, 1 to indicate a BPT_HANG success, 1241 0 stevel * and -1 on failure (not tracing functions or unknown breakpoint). 1242 0 stevel */ 1243 0 stevel int 1244 0 stevel function_trace(private_t *pri, int first, int clear, int dotrace) 1245 0 stevel { 1246 0 stevel struct ps_lwphandle *Lwp = pri->Lwp; 1247 0 stevel const lwpstatus_t *Lsp = pri->lwpstat; 1248 0 stevel uintptr_t pc = Lsp->pr_reg[R_PC]; 1249 0 stevel uintptr_t sp = Lsp->pr_reg[R_SP]; 1250 0 stevel uintptr_t fp = Lsp->pr_reg[R_FP]; 1251 0 stevel struct bkpt *Bp; 1252 0 stevel struct dynlib *Dp; 1253 0 stevel struct callstack *Stk; 1254 0 stevel ulong_t instr; 1255 0 stevel int active; 1256 0 stevel int rval = 0; 1257 0 stevel 1258 0 stevel if (Dynpat == NULL) 1259 0 stevel return (-1); 1260 0 stevel 1261 0 stevel if (data_model != PR_MODEL_LP64) { 1262 0 stevel pc = (uint32_t)pc; 1263 0 stevel sp = (uint32_t)sp; 1264 0 stevel fp = (uint32_t)fp; 1265 0 stevel } 1266 0 stevel 1267 0 stevel if ((Bp = get_bkpt(pc)) == NULL) { 1268 0 stevel if (hflag) 1269 0 stevel (void) fprintf(stderr, 1270 7330 Roger "function_trace(): " 1271 7330 Roger "cannot find breakpoint for pc: 0x%.8lx\n", 1272 7330 Roger (ulong_t)pc); 1273 0 stevel return (-1); 1274 0 stevel } 1275 0 stevel 1276 0 stevel if ((Bp->flags & (BPT_PREINIT|BPT_POSTINIT|BPT_DLACTIVITY)) && !clear) { 1277 0 stevel rd_event_msg_t event_msg; 1278 0 stevel 1279 0 stevel if (hflag) { 1280 0 stevel if (Bp->flags & BPT_PREINIT) 1281 0 stevel (void) fprintf(stderr, "function_trace(): " 1282 7330 Roger "RD_PREINIT breakpoint\n"); 1283 0 stevel if (Bp->flags & BPT_POSTINIT) 1284 0 stevel (void) fprintf(stderr, "function_trace(): " 1285 7330 Roger "RD_POSTINIT breakpoint\n"); 1286 0 stevel if (Bp->flags & BPT_DLACTIVITY) 1287 0 stevel (void) fprintf(stderr, "function_trace(): " 1288 7330 Roger "RD_DLACTIVITY breakpoint\n"); 1289 0 stevel } 1290 0 stevel if (rd_event_getmsg(Rdb_agent, &event_msg) == RD_OK) { 1291 0 stevel if (event_msg.type == RD_DLACTIVITY) { 1292 2192 raf switch (event_msg.u.state) { 1293 2192 raf case RD_CONSISTENT: 1294 0 stevel establish_breakpoints(); 1295 2192 raf break; 1296 2192 raf case RD_ADD: 1297 0 stevel not_consist = TRUE; /* kludge */ 1298 0 stevel establish_breakpoints(); 1299 0 stevel not_consist = FALSE; 1300 2192 raf break; 1301 2192 raf case RD_DELETE: 1302 2192 raf delete_library = TRUE; 1303 2192 raf break; 1304 2192 raf default: 1305 2192 raf break; 1306 0 stevel } 1307 0 stevel } 1308 0 stevel if (hflag) { 1309 0 stevel const char *et; 1310 0 stevel char buf[32]; 1311 0 stevel 1312 0 stevel switch (event_msg.type) { 1313 0 stevel case RD_NONE: 1314 0 stevel et = "RD_NONE"; 1315 0 stevel break; 1316 0 stevel case RD_PREINIT: 1317 0 stevel et = "RD_PREINIT"; 1318 0 stevel break; 1319 0 stevel case RD_POSTINIT: 1320 0 stevel et = "RD_POSTINIT"; 1321 0 stevel break; 1322 0 stevel case RD_DLACTIVITY: 1323 0 stevel et = "RD_DLACTIVITY"; 1324 0 stevel break; 1325 0 stevel default: 1326 0 stevel (void) sprintf(buf, "0x%x", 1327 7330 Roger event_msg.type); 1328 0 stevel et = buf; 1329 0 stevel break; 1330 0 stevel } 1331 0 stevel (void) fprintf(stderr, 1332 7330 Roger "event_msg.type = %s ", et); 1333 0 stevel switch (event_msg.u.state) { 1334 0 stevel case RD_NOSTATE: 1335 0 stevel et = "RD_NOSTATE"; 1336 0 stevel break; 1337 0 stevel case RD_CONSISTENT: 1338 0 stevel et = "RD_CONSISTENT"; 1339 0 stevel break; 1340 0 stevel case RD_ADD: 1341 0 stevel et = "RD_ADD"; 1342 0 stevel break; 1343 0 stevel case RD_DELETE: 1344 0 stevel et = "RD_DELETE"; 1345 0 stevel break; 1346 0 stevel default: 1347 0 stevel (void) sprintf(buf, "0x%x", 1348 7330 Roger event_msg.u.state); 1349 0 stevel et = buf; 1350 0 stevel break; 1351 0 stevel } 1352 0 stevel (void) fprintf(stderr, 1353 7330 Roger "event_msg.u.state = %s\n", et); 1354 0 stevel } 1355 0 stevel } 1356 0 stevel } 1357 0 stevel 1358 0 stevel if ((Bp->flags & BPT_TD_CREATE) && !clear) { 1359 0 stevel nthr_create++; 1360 0 stevel if (hflag) 1361 0 stevel (void) fprintf(stderr, "function_trace(): " 1362 7330 Roger "BPT_TD_CREATE breakpoint\n"); 1363 0 stevel /* we don't care about the event message */ 1364 0 stevel } 1365 0 stevel 1366 0 stevel Dp = Bp->dyn; 1367 0 stevel 1368 0 stevel if (dotrace) { 1369 0 stevel if ((Stk = callstack_info(sp, fp, 1)) == NULL) { 1370 0 stevel if (Dp != NULL && !clear) { 1371 0 stevel if (cflag) { 1372 0 stevel add_fcall(fcall_tbl, Dp->prt_name, 1373 0 stevel Bp->sym_name, (unsigned long)1); 1374 0 stevel } 1375 0 stevel else 1376 0 stevel show_function_call(pri, NULL, Dp, Bp); 1377 0 stevel if ((Bp->flags & BPT_HANG) && !first) 1378 0 stevel rval = 1; 1379 0 stevel } 1380 0 stevel } else if (!clear) { 1381 0 stevel if (Dp != NULL) { 1382 0 stevel function_entry(pri, Bp, Stk); 1383 0 stevel if ((Bp->flags & BPT_HANG) && !first) 1384 0 stevel rval = 1; 1385 0 stevel } else { 1386 0 stevel function_return(pri, Stk); 1387 0 stevel } 1388 0 stevel } 1389 0 stevel } 1390 0 stevel 1391 0 stevel /* 1392 0 stevel * Single-step the traced instruction. Since it's possible that 1393 0 stevel * another thread has deactivated this breakpoint, we indicate 1394 0 stevel * that we have reactivated it by virtue of executing it. 1395 0 stevel * 1396 0 stevel * To avoid a deadlock with some other thread in the process 1397 0 stevel * performing a fork() or a thr_suspend() operation, we must 1398 0 stevel * drop and later reacquire truss_lock. Some fancy dancing here. 1399 0 stevel */ 1400 0 stevel active = (Bp->flags & BPT_ACTIVE); 1401 0 stevel Bp->flags |= BPT_ACTIVE; 1402 0 stevel instr = Bp->instr; 1403 0 stevel (void) mutex_unlock(&truss_lock); 1404 0 stevel (void) Lxecbkpt(Lwp, instr); 1405 0 stevel (void) mutex_lock(&truss_lock); 1406 0 stevel 1407 0 stevel if (rval || clear) { /* leave process stopped and abandoned */ 1408 0 stevel #if defined(__i386) 1409 0 stevel /* 1410 0 stevel * Leave it stopped in a state that a stack trace is reasonable. 1411 0 stevel */ 1412 0 stevel /* XX64 needs to be updated for amd64 & gcc */ 1413 0 stevel if (rval && instr == 0x55) { /* pushl %ebp */ 1414 0 stevel /* step it over the movl %esp,%ebp */ 1415 0 stevel (void) mutex_unlock(&truss_lock); 1416 0 stevel (void) Lsetrun(Lwp, 0, PRCFAULT|PRSTEP); 1417 0 stevel /* we're wrapping up; wait one second at most */ 1418 0 stevel (void) Lwait(Lwp, MILLISEC); 1419 0 stevel (void) mutex_lock(&truss_lock); 1420 0 stevel } 1421 0 stevel #endif 1422 0 stevel if (get_bkpt(pc) != Bp) 1423 0 stevel abend("function_trace: lost breakpoint", NULL); 1424 0 stevel (void) Pdelbkpt(Proc, Bp->addr, Bp->instr); 1425 0 stevel Bp->flags &= ~BPT_ACTIVE; 1426 0 stevel (void) mutex_unlock(&truss_lock); 1427 0 stevel (void) Lsetrun(Lwp, 0, PRCFAULT|PRSTOP); 1428 0 stevel /* we're wrapping up; wait one second at most */ 1429 0 stevel (void) Lwait(Lwp, MILLISEC); 1430 0 stevel (void) mutex_lock(&truss_lock); 1431 0 stevel } else { 1432 0 stevel if (get_bkpt(pc) != Bp) 1433 0 stevel abend("function_trace: lost breakpoint", NULL); 1434 0 stevel if (!active || !(Bp->flags & BPT_ACTIVE)) { 1435 0 stevel (void) Pdelbkpt(Proc, Bp->addr, Bp->instr); 1436 0 stevel Bp->flags &= ~BPT_ACTIVE; 1437 0 stevel } 1438 0 stevel } 1439 0 stevel return (rval); 1440 0 stevel } 1441 0 stevel 1442 0 stevel void 1443 0 stevel function_entry(private_t *pri, struct bkpt *Bp, struct callstack *Stk) 1444 0 stevel { 1445 0 stevel const lwpstatus_t *Lsp = pri->lwpstat; 1446 0 stevel uintptr_t sp = Lsp->pr_reg[R_SP]; 1447 0 stevel uintptr_t rpc = get_return_address(&sp); 1448 0 stevel struct dynlib *Dp = Bp->dyn; 1449 0 stevel int oldframe = FALSE; 1450 0 stevel int i; 1451 0 stevel 1452 0 stevel #ifdef _LP64 1453 0 stevel if (data_model != PR_MODEL_LP64) { 1454 0 stevel sp = (uint32_t)sp; 1455 0 stevel rpc = (uint32_t)rpc; 1456 0 stevel } 1457 0 stevel #endif 1458 0 stevel 1459 0 stevel /* 1460 0 stevel * If the sp is not within the stack bounds, forget it. 1461 0 stevel * If the symbol's 'internal' flag is false, 1462 0 stevel * don't report internal calls within the library. 1463 0 stevel */ 1464 0 stevel if (!(sp >= Stk->stkbase && sp < Stk->stkend) || 1465 0 stevel (!(Bp->flags & BPT_INTERNAL) && 1466 0 stevel rpc >= Dp->base && rpc < Dp->base + Dp->size)) 1467 0 stevel return; 1468 0 stevel 1469 0 stevel for (i = 0; i < Stk->ncall; i++) { 1470 0 stevel if (sp >= Stk->stack[i].sp) { 1471 0 stevel Stk->ncall = i; 1472 0 stevel if (sp == Stk->stack[i].sp) 1473 0 stevel oldframe = TRUE; 1474 0 stevel break; 1475 0 stevel } 1476 0 stevel } 1477 0 stevel 1478 0 stevel /* 1479 0 stevel * Breakpoints for function returns are set here 1480 0 stevel * If we're counting function calls, there is no need to set 1481 0 stevel * a breakpoint upon return 1482 0 stevel */ 1483 0 stevel 1484 0 stevel if (!oldframe && !cflag) { 1485 0 stevel (void) create_bkpt(rpc, 1, 1); /* may or may not be set */ 1486 0 stevel Stk->stack[Stk->ncall].sp = sp; /* record it anyeay */ 1487 0 stevel Stk->stack[Stk->ncall].pc = rpc; 1488 0 stevel Stk->stack[Stk->ncall].fcn = Bp; 1489 0 stevel } 1490 0 stevel Stk->ncall++; 1491 0 stevel if (cflag) { 1492 0 stevel add_fcall(fcall_tbl, Dp->prt_name, Bp->sym_name, 1493 0 stevel (unsigned long)1); 1494 0 stevel } else { 1495 0 stevel show_function_call(pri, Stk, Dp, Bp); 1496 0 stevel } 1497 0 stevel } 1498 0 stevel 1499 0 stevel /* 1500 0 stevel * We are here because we hit an unnamed breakpoint. 1501 0 stevel * Attempt to match this up with a return pc on the stack 1502 0 stevel * and report the function return. 1503 0 stevel */ 1504 0 stevel void 1505 0 stevel function_return(private_t *pri, struct callstack *Stk) 1506 0 stevel { 1507 0 stevel const lwpstatus_t *Lsp = pri->lwpstat; 1508 0 stevel uintptr_t sp = Lsp->pr_reg[R_SP]; 1509 0 stevel uintptr_t fp = Lsp->pr_reg[R_FP]; 1510 0 stevel int i; 1511 0 stevel 1512 0 stevel #ifdef _LP64 1513 0 stevel if (data_model != PR_MODEL_LP64) { 1514 0 stevel sp = (uint32_t)sp; 1515 0 stevel fp = (uint32_t)fp; 1516 0 stevel } 1517 0 stevel #endif 1518 0 stevel 1519 0 stevel if (fp < sp + 8) 1520 0 stevel fp = sp + 8; 1521 0 stevel 1522 0 stevel for (i = Stk->ncall - 1; i >= 0; i--) { 1523 0 stevel if (sp <= Stk->stack[i].sp && fp > Stk->stack[i].sp) { 1524 0 stevel Stk->ncall = i; 1525 0 stevel break; 1526 0 stevel } 1527 0 stevel } 1528 0 stevel 1529 0 stevel #if defined(i386) || defined(__amd64) 1530 0 stevel if (i < 0) { 1531 0 stevel /* probably __mul64() or friends -- try harder */ 1532 0 stevel int j; 1533 0 stevel for (j = 0; i < 0 && j < 8; j++) { /* up to 8 args */ 1534 0 stevel sp -= 4; 1535 0 stevel for (i = Stk->ncall - 1; i >= 0; i--) { 1536 0 stevel if (sp <= Stk->stack[i].sp && 1537 0 stevel fp > Stk->stack[i].sp) { 1538 0 stevel Stk->ncall = i; 1539 0 stevel break; 1540 0 stevel } 1541 0 stevel } 1542 0 stevel } 1543 0 stevel } 1544 0 stevel #endif 1545 0 stevel 1546 0 stevel if ((i >= 0) && (!cflag)) { 1547 0 stevel show_function_return(pri, Lsp->pr_reg[R_R0], 0, 1548 7330 Roger Stk, Stk->stack[i].fcn->dyn, Stk->stack[i].fcn); 1549 0 stevel } 1550 0 stevel } 1551 0 stevel 1552 0 stevel #if defined(__sparc) 1553 0 stevel #define FPADJUST 0 1554 0 stevel #elif defined(__amd64) 1555 0 stevel #define FPADJUST 8 1556 0 stevel #elif defined(__i386) 1557 0 stevel #define FPADJUST 4 1558 0 stevel #endif 1559 0 stevel 1560 0 stevel void 1561 0 stevel trap_one_stack(prgregset_t reg) 1562 0 stevel { 1563 0 stevel struct dynlib *Dp; 1564 0 stevel struct bkpt *Bp; 1565 0 stevel struct callstack *Stk; 1566 0 stevel GElf_Sym sym; 1567 0 stevel char sym_name[32]; 1568 0 stevel uintptr_t sp = reg[R_SP]; 1569 0 stevel uintptr_t pc = reg[R_PC]; 1570 0 stevel uintptr_t fp; 1571 0 stevel uintptr_t rpc; 1572 0 stevel uint_t nframe = 0; 1573 0 stevel uint_t maxframe = 8; 1574 0 stevel struct { 1575 0 stevel uintptr_t sp; /* %sp within called function */ 1576 0 stevel uintptr_t pc; /* %pc within called function */ 1577 0 stevel uintptr_t rsp; /* the return sp */ 1578 0 stevel uintptr_t rpc; /* the return pc */ 1579 0 stevel } *frame = my_malloc(maxframe * sizeof (*frame), NULL); 1580 0 stevel 1581 0 stevel /* 1582 0 stevel * Gather stack frames bottom to top. 1583 0 stevel */ 1584 0 stevel while (sp != 0) { 1585 0 stevel fp = sp; /* remember higest non-null sp */ 1586 0 stevel frame[nframe].sp = sp; 1587 0 stevel frame[nframe].pc = pc; 1588 0 stevel sp = previous_fp(sp, &pc); 1589 0 stevel frame[nframe].rsp = sp; 1590 0 stevel frame[nframe].rpc = pc; 1591 0 stevel if (++nframe == maxframe) { 1592 0 stevel maxframe *= 2; 1593 0 stevel frame = my_realloc(frame, maxframe * sizeof (*frame), 1594 7330 Roger NULL); 1595 0 stevel } 1596 0 stevel } 1597 0 stevel 1598 0 stevel /* 1599 0 stevel * Scan for function return breakpoints top to bottom. 1600 0 stevel */ 1601 0 stevel while (nframe--) { 1602 0 stevel /* lookup the called function in the symbol tables */ 1603 0 stevel if (Plookup_by_addr(Proc, frame[nframe].pc, sym_name, 1604 0 stevel sizeof (sym_name), &sym) != 0) 1605 0 stevel continue; 1606 0 stevel 1607 0 stevel pc = sym.st_value; /* entry point of the function */ 1608 0 stevel rpc = frame[nframe].rpc; /* caller's return pc */ 1609 0 stevel 1610 0 stevel /* lookup the function in the breakpoint table */ 1611 0 stevel if ((Bp = get_bkpt(pc)) == NULL || (Dp = Bp->dyn) == NULL) 1612 0 stevel continue; 1613 0 stevel 1614 0 stevel if (!(Bp->flags & BPT_INTERNAL) && 1615 0 stevel rpc >= Dp->base && rpc < Dp->base + Dp->size) 1616 0 stevel continue; 1617 0 stevel 1618 0 stevel sp = frame[nframe].rsp + FPADJUST; /* %sp at time of call */ 1619 0 stevel if ((Stk = callstack_info(sp, fp, 0)) == NULL) 1620 0 stevel continue; /* can't happen? */ 1621 0 stevel 1622 0 stevel if (create_bkpt(rpc, 1, 1) != NULL) { 1623 0 stevel Stk->stack[Stk->ncall].sp = sp; 1624 0 stevel Stk->stack[Stk->ncall].pc = rpc; 1625 0 stevel Stk->stack[Stk->ncall].fcn = Bp; 1626 0 stevel Stk->ncall++; 1627 0 stevel } 1628 0 stevel } 1629 0 stevel 1630 0 stevel free(frame); 1631 0 stevel } 1632 0 stevel 1633 0 stevel int 1634 0 stevel lwp_stack_traps(void *cd, const lwpstatus_t *Lsp) 1635 0 stevel { 1636 0 stevel ph_map_t *ph_map = (ph_map_t *)cd; 1637 0 stevel prgregset_t reg; 1638 0 stevel 1639 0 stevel (void) memcpy(reg, Lsp->pr_reg, sizeof (prgregset_t)); 1640 0 stevel make_lwp_stack(Lsp, ph_map->pmap, ph_map->nmap); 1641 0 stevel trap_one_stack(reg); 1642 0 stevel 1643 0 stevel return (interrupt | sigusr1); 1644 0 stevel } 1645 0 stevel 1646 0 stevel /* ARGSUSED */ 1647 0 stevel int 1648 0 stevel thr_stack_traps(const td_thrhandle_t *Thp, void *cd) 1649 0 stevel { 1650 0 stevel prgregset_t reg; 1651 0 stevel 1652 0 stevel /* 1653 0 stevel * We have already dealt with all the lwps. 1654 0 stevel * We only care about unbound threads here (TD_PARTIALREG). 1655 0 stevel */ 1656 0 stevel if (td_thr_getgregs(Thp, reg) != TD_PARTIALREG) 1657 0 stevel return (0); 1658 0 stevel 1659 0 stevel make_thr_stack(Thp, reg); 1660 0 stevel trap_one_stack(reg); 1661 0 stevel 1662 0 stevel return (interrupt | sigusr1); 1663 0 stevel } 1664 0 stevel 1665 0 stevel #if defined(__sparc) 1666 0 stevel 1667 0 stevel uintptr_t 1668 0 stevel previous_fp(uintptr_t sp, uintptr_t *rpc) 1669 0 stevel { 1670 0 stevel uintptr_t fp = 0; 1671 0 stevel uintptr_t pc = 0; 1672 0 stevel 1673 0 stevel #ifdef _LP64 1674 0 stevel if (data_model == PR_MODEL_LP64) { 1675 0 stevel struct rwindow64 rwin; 1676 0 stevel if (Pread(Proc, &rwin, sizeof (rwin), sp + STACK_BIAS) 1677 0 stevel == sizeof (rwin)) { 1678 0 stevel fp = (uintptr_t)rwin.rw_fp; 1679 0 stevel pc = (uintptr_t)rwin.rw_rtn; 1680 0 stevel } 1681 0 stevel if (fp != 0 && 1682 0 stevel Pread(Proc, &rwin, sizeof (rwin), fp + STACK_BIAS) 1683 0 stevel != sizeof (rwin)) 1684 0 stevel fp = pc = 0; 1685 0 stevel } else { 1686 0 stevel struct rwindow32 rwin; 1687 0 stevel #else /* _LP64 */ 1688 0 stevel struct rwindow rwin; 1689 0 stevel #endif /* _LP64 */ 1690 0 stevel if (Pread(Proc, &rwin, sizeof (rwin), sp) == sizeof (rwin)) { 1691 0 stevel fp = (uint32_t)rwin.rw_fp; 1692 0 stevel pc = (uint32_t)rwin.rw_rtn; 1693 0 stevel } 1694 0 stevel if (fp != 0 && 1695 0 stevel Pread(Proc, &rwin, sizeof (rwin), fp) != sizeof (rwin)) 1696 0 stevel fp = pc = 0; 1697 0 stevel #ifdef _LP64 1698 0 stevel } 1699 0 stevel #endif 1700 0 stevel if (rpc) 1701 0 stevel *rpc = pc; 1702 0 stevel return (fp); 1703 0 stevel } 1704 0 stevel 1705 0 stevel /* ARGSUSED */ 1706 0 stevel uintptr_t 1707 0 stevel get_return_address(uintptr_t *psp) 1708 0 stevel { 1709 0 stevel instr_t inst; 1710 0 stevel private_t *pri = get_private(); 1711 0 stevel const lwpstatus_t *Lsp = pri->lwpstat; 1712 0 stevel uintptr_t rpc; 1713 0 stevel 1714 0 stevel rpc = (uintptr_t)Lsp->pr_reg[R_O7] + 8; 1715 0 stevel if (data_model != PR_MODEL_LP64) 1716 0 stevel rpc = (uint32_t)rpc; 1717 0 stevel 1718 0 stevel /* check for structure return (bletch!) */ 1719 0 stevel if (Pread(Proc, &inst, sizeof (inst), rpc) == sizeof (inst) && 1720 0 stevel inst < 0x1000) 1721 0 stevel rpc += sizeof (instr_t); 1722 0 stevel 1723 0 stevel return (rpc); 1724 0 stevel } 1725 0 stevel 1726 0 stevel int 1727 0 stevel get_arguments(long *argp) 1728 0 stevel { 1729 0 stevel private_t *pri = get_private(); 1730 0 stevel const lwpstatus_t *Lsp = pri->lwpstat; 1731 0 stevel int i; 1732 0 stevel 1733 0 stevel if (data_model != PR_MODEL_LP64) 1734 0 stevel for (i = 0; i < 4; i++) 1735 0 stevel argp[i] = (uint_t)Lsp->pr_reg[R_O0+i]; 1736 0 stevel else 1737 0 stevel for (i = 0; i < 4; i++) 1738 0 stevel argp[i] = (long)Lsp->pr_reg[R_O0+i]; 1739 0 stevel return (4); 1740 0 stevel } 1741 0 stevel 1742 0 stevel #endif /* __sparc */ 1743 0 stevel 1744 0 stevel #if defined(__i386) || defined(__amd64) 1745 0 stevel 1746 0 stevel uintptr_t 1747 0 stevel previous_fp(uintptr_t fp, uintptr_t *rpc) 1748 0 stevel { 1749 0 stevel uintptr_t frame[2]; 1750 0 stevel uintptr_t trash[2]; 1751 0 stevel 1752 0 stevel if (Pread(Proc, frame, sizeof (frame), fp) != sizeof (frame) || 1753 0 stevel (frame[0] != 0 && 1754 0 stevel Pread(Proc, trash, sizeof (trash), frame[0]) != sizeof (trash))) 1755 0 stevel frame[0] = frame[1] = 0; 1756 0 stevel 1757 0 stevel if (rpc) 1758 0 stevel *rpc = frame[1]; 1759 0 stevel return (frame[0]); 1760 0 stevel } 1761 0 stevel 1762 0 stevel #endif 1763 0 stevel 1764 0 stevel #if defined(__amd64) || defined(__i386) 1765 0 stevel 1766 0 stevel /* 1767 0 stevel * Examine the instruction at the return location of a function call 1768 0 stevel * and return the byte count by which the stack is adjusted on return. 1769 0 stevel * It the instruction at the return location is an addl, as expected, 1770 0 stevel * then adjust the return pc by the size of that instruction so that 1771 0 stevel * we will place the return breakpoint on the following instruction. 1772 0 stevel * This allows programs that interrogate their own stacks and record 1773 0 stevel * function calls and arguments to work correctly even while we interfere. 1774 0 stevel * Return the count on success, -1 on failure. 1775 0 stevel */ 1776 0 stevel int 1777 0 stevel return_count32(uint32_t *ppc) 1778 0 stevel { 1779 0 stevel uintptr_t pc = *ppc; 1780 0 stevel struct bkpt *Bp; 1781 0 stevel int count; 1782 0 stevel uchar_t instr[6]; /* instruction at pc */ 1783 0 stevel 1784 0 stevel if ((count = Pread(Proc, instr, sizeof (instr), pc)) < 0) 1785 0 stevel return (-1); 1786 0 stevel 1787 0 stevel /* find the replaced instruction at pc (if any) */ 1788 0 stevel if ((Bp = get_bkpt(pc)) != NULL && (Bp->flags & BPT_ACTIVE)) 1789 0 stevel instr[0] = (uchar_t)Bp->instr; 1790 0 stevel 1791 0 stevel if (count != sizeof (instr) && 1792 0 stevel (count < 3 || instr[0] != 0x83)) 1793 0 stevel return (-1); 1794 0 stevel 1795 0 stevel /* 1796 0 stevel * A bit of disassembly of the instruction is required here. 1797 0 stevel */ 1798 0 stevel if (instr[1] != 0xc4) { /* not an addl mumble,%esp inctruction */ 1799 0 stevel count = 0; 1800 0 stevel } else if (instr[0] == 0x81) { /* count is a longword */ 1801 0 stevel count = instr[2]+(instr[3]<<8)+(instr[4]<<16)+(instr[5]<<24); 1802 0 stevel *ppc += 6; 1803 0 stevel } else if (instr[0] == 0x83) { /* count is a byte */ 1804 0 stevel count = instr[2]; 1805 0 stevel *ppc += 3; 1806 0 stevel } else { /* not an addl inctruction */ 1807 0 stevel count = 0; 1808 0 stevel } 1809 0 stevel 1810 0 stevel return (count); 1811 0 stevel } 1812 0 stevel 1813 0 stevel uintptr_t 1814 0 stevel get_return_address32(uintptr_t *psp) 1815 0 stevel { 1816 0 stevel uint32_t sp = *psp; 1817 0 stevel uint32_t rpc; 1818 0 stevel int count; 1819 0 stevel 1820 0 stevel *psp += 4; /* account for popping the stack on return */ 1821 0 stevel if (Pread(Proc, &rpc, sizeof (rpc), sp) != sizeof (rpc)) 1822 0 stevel return (0); 1823 0 stevel if ((count = return_count32(&rpc)) < 0) 1824 0 stevel count = 0; 1825 0 stevel *psp += count; /* expected sp on return */ 1826 0 stevel return (rpc); 1827 0 stevel } 1828 0 stevel 1829 0 stevel uintptr_t 1830 0 stevel get_return_address(uintptr_t *psp) 1831 0 stevel { 1832 0 stevel #ifdef _LP64 1833 0 stevel uintptr_t rpc; 1834 0 stevel uintptr_t sp = *psp; 1835 0 stevel 1836 0 stevel if (data_model == PR_MODEL_LP64) { 1837 0 stevel if (Pread(Proc, &rpc, sizeof (rpc), sp) != sizeof (rpc)) 1838 0 stevel return (0); 1839 0 stevel /* 1840 0 stevel * Ignore arguments pushed on the stack. See comments in 1841 0 stevel * get_arguments(). 1842 0 stevel */ 1843 0 stevel return (rpc); 1844 0 stevel } else 1845 0 stevel #endif 1846 0 stevel return (get_return_address32(psp)); 1847 0 stevel } 1848 0 stevel 1849 0 stevel 1850 0 stevel int 1851 0 stevel get_arguments32(long *argp) 1852 0 stevel { 1853 0 stevel private_t *pri = get_private(); 1854 0 stevel const lwpstatus_t *Lsp = pri->lwpstat; 1855 0 stevel uint32_t frame[5]; /* return pc + 4 args */ 1856 0 stevel int narg; 1857 0 stevel int count; 1858 0 stevel int i; 1859 0 stevel 1860 0 stevel narg = Pread(Proc, frame, sizeof (frame), 1861 7330 Roger (uintptr_t)Lsp->pr_reg[R_SP]); 1862 0 stevel narg -= sizeof (greg32_t); 1863 0 stevel if (narg <= 0) 1864 0 stevel return (0); 1865 0 stevel narg /= sizeof (greg32_t); /* no more than 4 */ 1866 0 stevel 1867 0 stevel /* 1868 0 stevel * Given the return PC, determine the number of arguments. 1869 0 stevel */ 1870 0 stevel if ((count = return_count32(&frame[0])) < 0) 1871 0 stevel narg = 0; 1872 0 stevel else { 1873 0 stevel count /= sizeof (greg32_t); 1874 0 stevel if (narg > count) 1875 0 stevel narg = count; 1876 0 stevel } 1877 0 stevel 1878 0 stevel for (i = 0; i < narg; i++) 1879 0 stevel argp[i] = (long)frame[i+1]; 1880 0 stevel 1881 0 stevel return (narg); 1882 0 stevel } 1883 0 stevel 1884 0 stevel int 1885 0 stevel get_arguments(long *argp) 1886 0 stevel { 1887 0 stevel #ifdef _LP64 1888 0 stevel private_t *pri = get_private(); 1889 0 stevel const lwpstatus_t *Lsp = pri->lwpstat; 1890 0 stevel 1891 0 stevel if (data_model == PR_MODEL_LP64) { 1892 0 stevel /* 1893 0 stevel * On amd64, we do not know how many arguments are passed to 1894 0 stevel * each function. While it may be possible to detect if we 1895 0 stevel * have more than 6 arguments, it is of marginal value. 1896 0 stevel * Instead, assume that we always have 6 arguments, which are 1897 0 stevel * passed via registers. 1898 0 stevel */ 1899 0 stevel argp[0] = Lsp->pr_reg[REG_RDI]; 1900 0 stevel argp[1] = Lsp->pr_reg[REG_RSI]; 1901 0 stevel argp[2] = Lsp->pr_reg[REG_RDX]; 1902 0 stevel argp[3] = Lsp->pr_reg[REG_RCX]; 1903 0 stevel argp[4] = Lsp->pr_reg[REG_R8]; 1904 0 stevel argp[5] = Lsp->pr_reg[REG_R9]; 1905 0 stevel return (6); 1906 0 stevel } else 1907 0 stevel #endif 1908 0 stevel return (get_arguments32(argp)); 1909 0 stevel } 1910 0 stevel 1911 0 stevel #endif /* __amd64 || __i386 */ 1912