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 (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <unistd.h> 29 #include <sys/uio.h> 30 #include <fcntl.h> 31 #include <string.h> 32 #include <errno.h> 33 #include <sys/types.h> 34 #include <sys/signal.h> 35 #include <sys/fault.h> 36 #include <sys/syscall.h> 37 #include <procfs.h> 38 #include <sys/auxv.h> 39 #include <libelf.h> 40 #include <sys/param.h> 41 #include <sys/machelf.h> 42 #include <stdarg.h> 43 44 #include "rdb.h" 45 46 static const char *fault_strings[] = { 47 "<null string>", 48 "illegal instruction", 49 "privileged instruction", 50 "breakpoint instruction", 51 "trace trap (single-step)", 52 "Memory access (e.g., alignment)", 53 "Memory bounds (invalid address)", 54 "Integer overflow", 55 "Integer zero divide" 56 "Floating-point exception", 57 "Irrecoverable stack faul", 58 "Recoverable page fault (no associated sig)" 59 }; 60 61 #define MAXFAULT FLTPAGE 62 63 retc_t 64 set_breakpoint(struct ps_prochandle *ph, ulong_t addr, unsigned flags) 65 { 66 bptlist_t *new, *cur, *prev; 67 68 for (cur = ph->pp_breakpoints, prev = NULL; 69 (cur && (cur->bl_addr < addr)); 70 prev = cur, cur = cur->bl_next) 71 ; 72 if (cur && (cur->bl_addr == addr)) { 73 /* 74 * already have break point set here. 75 */ 76 cur->bl_flags |= flags; 77 return (RET_OK); 78 } 79 80 new = malloc(sizeof (bptlist_t)); 81 new->bl_addr = addr; 82 new->bl_flags = flags; 83 if (prev == NULL) { 84 /* 85 * insert at head 86 */ 87 new->bl_next = ph->pp_breakpoints; 88 ph->pp_breakpoints = new; 89 return (RET_OK); 90 } 91 92 prev->bl_next = new; 93 new->bl_next = cur; 94 return (RET_OK); 95 } 96 97 static bptlist_t * 98 find_bp(struct ps_prochandle *ph, ulong_t addr) 99 { 100 bptlist_t *cur; 101 102 for (cur = ph->pp_breakpoints; 103 (cur && (cur->bl_addr != addr)); 104 cur = cur->bl_next) 105 ; 106 107 if ((cur == NULL) || (cur->bl_addr != addr)) 108 return ((bptlist_t *)-1); 109 return (cur); 110 } 111 112 static retc_t 113 delete_bp(struct ps_prochandle *ph, ulong_t addr) 114 { 115 bptlist_t *cur, *prev; 116 117 for (cur = ph->pp_breakpoints, prev = NULL; 118 (cur && (cur->bl_addr < addr)); 119 prev = cur, cur = cur->bl_next) 120 ; 121 if ((cur == NULL) || (cur->bl_addr != addr)) 122 return (RET_FAILED); 123 124 if (prev == NULL) 125 ph->pp_breakpoints = cur->bl_next; 126 else 127 prev->bl_next = cur->bl_next; 128 129 free(cur); 130 return (RET_OK); 131 } 132 133 void 134 list_breakpoints(struct ps_prochandle *ph) 135 { 136 bptlist_t *cur; 137 138 if (ph->pp_breakpoints == NULL) { 139 (void) printf("no active breakpoints.\n"); 140 return; 141 } 142 143 (void) printf("active breakpoints:\n"); 144 for (cur = ph->pp_breakpoints; cur; cur = cur->bl_next) { 145 (void) printf("\t0x%08lx:0x%04x - %s\n", cur->bl_addr, 146 cur->bl_flags, print_address_ps(ph, cur->bl_addr, 147 FLG_PAP_SONAME)); 148 } 149 } 150 151 static void 152 set_breaks(struct ps_prochandle *ph) 153 { 154 bptlist_t *cur; 155 bptinstr_t bpt_instr = BPINSTR; 156 157 for (cur = ph->pp_breakpoints; cur; cur = cur->bl_next) { 158 bptinstr_t old_inst = 0; 159 160 if (ps_pread(ph, cur->bl_addr, (char *)&old_inst, 161 sizeof (bptinstr_t)) != PS_OK) 162 perr("sb: error setting breakpoint"); 163 164 cur->bl_instr = old_inst; 165 166 if (ps_pwrite(ph, cur->bl_addr, (char *)&bpt_instr, 167 sizeof (bptinstr_t)) != PS_OK) 168 perr("sb1: error setting breakpoint\n"); 169 } 170 171 } 172 173 static void 174 clear_breaks(struct ps_prochandle *ph) 175 { 176 bptlist_t *cur; 177 178 /* 179 * Restore all the original instructions 180 */ 181 for (cur = ph->pp_breakpoints; cur; cur = cur->bl_next) 182 if (ps_pwrite(ph, cur->bl_addr, (char *)&(cur->bl_instr), 183 sizeof (bptinstr_t)) != PS_OK) 184 perr("cb: error clearing breakpoint"); 185 } 186 187 retc_t 188 delete_all_breakpoints(struct ps_prochandle *ph) 189 { 190 bptlist_t *cur, *prev; 191 192 if (ph->pp_breakpoints == NULL) 193 return (RET_OK); 194 195 for (prev = NULL, cur = ph->pp_breakpoints; 196 cur; prev = cur, cur = cur->bl_next) 197 if (prev) 198 free(prev); 199 if (prev) 200 free(prev); 201 202 ph->pp_breakpoints = NULL; 203 return (RET_OK); 204 } 205 206 retc_t 207 delete_breakpoint(struct ps_prochandle *ph, ulong_t addr, unsigned flags) 208 { 209 bptlist_t *bpt; 210 211 if (((bpt = find_bp(ph, addr)) == (bptlist_t *)-1) || 212 ((bpt->bl_flags & flags) == 0)) 213 return (RET_FAILED); 214 215 bpt->bl_flags &= ~flags; 216 if (bpt->bl_flags) 217 return (RET_OK); 218 219 return (delete_bp(ph, addr)); 220 } 221 222 static void 223 handle_sp_break(struct ps_prochandle *ph) 224 { 225 rd_event_msg_t emt; 226 227 if (rd_event_getmsg(ph->pp_rap, &emt) != RD_OK) { 228 (void) fprintf(stderr, "hsb: failed rd_event_getmsg()\n"); 229 return; 230 } 231 232 if (emt.type == RD_DLACTIVITY) { 233 if (emt.u.state == RD_CONSISTENT) 234 ph->pp_flags |= FLG_PP_LMAPS; 235 else 236 ph->pp_flags &= ~FLG_PP_LMAPS; 237 if ((rdb_flags & RDB_FL_EVENTS) == 0) 238 return; 239 240 (void) printf("dlactivity: state changed to: "); 241 switch (emt.u.state) { 242 case RD_CONSISTENT: 243 (void) printf("RD_CONSISTENT\n"); 244 break; 245 case RD_ADD: 246 (void) printf("RD_ADD\n"); 247 break; 248 case RD_DELETE: 249 (void) printf("RD_DELETE\n"); 250 break; 251 default: 252 (void) printf("unknown: 0x%x\n", emt.u.state); 253 } 254 return; 255 } 256 257 if ((rdb_flags & RDB_FL_EVENTS) == 0) 258 return; 259 260 if (emt.type == RD_PREINIT) { 261 (void) printf("preinit reached\n"); 262 return; 263 } 264 265 if (emt.type == RD_POSTINIT) 266 (void) printf("postinit reached\n"); 267 } 268 269 unsigned 270 continue_to_break(struct ps_prochandle *ph) 271 { 272 bptlist_t *bpt; 273 pstatus_t pstatus; 274 struct iovec piov[5]; 275 long oper1, oper2, oper3, pflags = 0; 276 fltset_t faults; 277 278 /* 279 * We step by the first instruction incase their was 280 * a break-point there. 281 */ 282 (void) step_n(ph, 1, FLG_SN_NONE); 283 284 premptyset(&faults); 285 praddset(&faults, FLTBPT); 286 praddset(&faults, FLTILL); 287 praddset(&faults, FLTPRIV); 288 praddset(&faults, FLTACCESS); 289 praddset(&faults, FLTBOUNDS); 290 praddset(&faults, FLTIZDIV); 291 praddset(&faults, FLTSTACK); 292 praddset(&faults, FLTTRACE); 293 294 295 /* LINTED CONSTANT */ 296 while (1) { 297 set_breaks(ph); 298 oper1 = PCSFAULT; 299 piov[0].iov_base = (caddr_t)(&oper1); 300 piov[0].iov_len = sizeof (oper1); 301 302 piov[1].iov_base = (caddr_t)(&faults); 303 piov[1].iov_len = sizeof (faults); 304 305 oper2 = PCRUN; 306 piov[2].iov_base = (caddr_t)(&oper2); 307 piov[2].iov_len = sizeof (oper2); 308 pflags = PRCFAULT; 309 piov[3].iov_base = (caddr_t)(&pflags); 310 piov[3].iov_len = sizeof (pflags); 311 312 oper3 = PCWSTOP; 313 piov[4].iov_base = (caddr_t)(&oper3); 314 piov[4].iov_len = sizeof (oper3); 315 316 if (writev(ph->pp_ctlfd, piov, 5) == -1) { 317 if (errno == ENOENT) { 318 ph->pp_flags &= ~FLG_PP_PACT; 319 320 (void) ps_close(ph); 321 (void) printf("process terminated.\n"); 322 return (0); 323 } 324 perr("ctb: PCWSTOP"); 325 } 326 327 if (pread(ph->pp_statusfd, &pstatus, sizeof (pstatus), 0) == -1) 328 perr("ctb: reading status"); 329 330 331 if ((pstatus.pr_lwp.pr_why != PR_FAULTED) || 332 (pstatus.pr_lwp.pr_what != FLTBPT)) { 333 const char *fltmsg; 334 335 if ((pstatus.pr_lwp.pr_what <= MAXFAULT) && 336 (pstatus.pr_lwp.pr_why == PR_FAULTED)) 337 fltmsg = fault_strings[pstatus.pr_lwp.pr_what]; 338 else 339 fltmsg = "<unknown error>"; 340 341 (void) fprintf(stderr, "ctb: bad stop - stopped " 342 "on why: 0x%x what: %s(0x%x)\n", 343 pstatus.pr_lwp.pr_why, fltmsg, 344 pstatus.pr_lwp.pr_what); 345 return (0); 346 } 347 348 oper1 = PCCFAULT; 349 if (writev(ph->pp_ctlfd, piov, 1) == -1) 350 perr("ctb: PCCFAULT"); 351 352 if ((bpt = find_bp(ph, pstatus.pr_lwp.pr_reg[R_PC])) == 353 (bptlist_t *)-1) { 354 (void) fprintf(stderr, 355 "stopped at unregistered breakpoint! " 356 "addr: 0x%x\n", 357 EC_WORD(pstatus.pr_lwp.pr_reg[R_PC])); 358 break; 359 } 360 clear_breaks(ph); 361 362 /* 363 * If this was a BP at which we should stop 364 */ 365 if (bpt->bl_flags & MASK_BP_STOP) 366 break; 367 368 (void) step_n(ph, 1, FLG_SN_NONE); 369 } 370 371 if (bpt->bl_flags & FLG_BP_USERDEF) 372 (void) printf("break point reached at addr: 0x%x\n", 373 EC_WORD(pstatus.pr_lwp.pr_reg[R_PC])); 374 375 if (bpt->bl_flags & MASK_BP_SPECIAL) 376 handle_sp_break(ph); 377 378 if (ph->pp_flags & FLG_PP_LMAPS) { 379 if (get_linkmaps(ph) != PS_OK) 380 (void) fprintf(stderr, "problem loading linkmaps\n"); 381 } 382 383 return (bpt->bl_flags); 384 } 385 386 ulong_t 387 is_plt(struct ps_prochandle *ph, ulong_t pc) 388 { 389 map_info_t *mip; 390 ulong_t pltbase; 391 392 if ((mip = addr_to_map(ph, pc)) == (map_info_t *)0) 393 return ((ulong_t)0); 394 395 pltbase = mip->mi_pltbase; 396 if ((mip->mi_flags & FLG_MI_EXEC) == 0) 397 pltbase += mip->mi_addr; 398 399 if ((pc >= pltbase) && (pc <= (pltbase + mip->mi_pltsize))) 400 return (pltbase); 401 402 return ((ulong_t)0); 403 } 404 405 retc_t 406 step_n(struct ps_prochandle *ph, size_t count, sn_flags_e flgs) 407 { 408 pstatus_t pstatus; 409 fltset_t faults; 410 int i; 411 long oper; 412 long flags; 413 struct iovec piov[2]; 414 415 if (pread(ph->pp_statusfd, &pstatus, sizeof (pstatus), 0) == -1) 416 perr("stn: reading status"); 417 418 piov[0].iov_base = (caddr_t)(&oper); 419 piov[0].iov_len = sizeof (oper); 420 421 premptyset(&faults); 422 praddset(&faults, FLTTRACE); 423 424 flags = PRSTEP | PRCFAULT; 425 426 for (i = 0; i < count; i++) { 427 bptlist_t *bpt; 428 uintptr_t pc, pltbase; 429 430 pc = pstatus.pr_lwp.pr_reg[R_PC]; 431 432 if ((bpt = find_bp(ph, pc)) != (bptlist_t *)-1) { 433 if (bpt->bl_flags & MASK_BP_SPECIAL) 434 handle_sp_break(ph); 435 } 436 437 if (flgs & FLG_SN_VERBOSE) 438 disasm(ph, 1); 439 440 oper = PCSFAULT; 441 piov[1].iov_base = (caddr_t)(&faults); 442 piov[1].iov_len = sizeof (faults); 443 444 if (writev(ph->pp_ctlfd, piov, 2) == -1) 445 perr("stn: PCSFAULT"); 446 447 oper = PCRUN; 448 piov[1].iov_base = (caddr_t)(&flags); 449 piov[1].iov_len = sizeof (flags); 450 if (writev(ph->pp_ctlfd, piov, 2) == -1) 451 perr("stn: PCRUN(PRSETP)"); 452 453 oper = PCWSTOP; 454 if (writev(ph->pp_ctlfd, piov, 1) == -1) 455 perr("stn: PCWSTOP stepping"); 456 457 if (pread(ph->pp_statusfd, &pstatus, sizeof (pstatus), 0) == -1) 458 perr("stn1: reading status"); 459 pc = pstatus.pr_lwp.pr_reg[R_PC]; 460 461 462 if ((pstatus.pr_lwp.pr_why != PR_FAULTED) || 463 (pstatus.pr_lwp.pr_what != FLTTRACE)) { 464 (void) fprintf(stderr, "sn: bad stop - stopped on " 465 "why: 0x%x what: 0x%x\n", pstatus.pr_lwp.pr_why, 466 pstatus.pr_lwp.pr_what); 467 return (RET_FAILED); 468 } 469 470 if ((flgs & FLG_SN_PLTSKIP) && 471 ((pltbase = is_plt(ph, pc)) != (ulong_t)0)) { 472 rd_plt_info_t rp; 473 if (rd_plt_resolution(ph->pp_rap, pc, 474 pstatus.pr_lwp.pr_lwpid, pltbase, &rp) != RD_OK) { 475 (void) fprintf(stderr, 476 "sn: rd_plt_resolution failed\n"); 477 return (RET_FAILED); 478 } 479 if (rp.pi_skip_method == RD_RESOLVE_TARGET_STEP) { 480 unsigned bpflags; 481 482 (void) set_breakpoint(ph, rp.pi_target, 483 FLG_BP_PLTRES); 484 bpflags = continue_to_break(ph); 485 486 (void) delete_breakpoint(ph, rp.pi_target, 487 FLG_BP_PLTRES); 488 489 if (bpflags & FLG_BP_PLTRES) 490 (void) step_n(ph, rp.pi_nstep, 491 FLG_SN_NONE); 492 } else if (rp.pi_skip_method == RD_RESOLVE_STEP) 493 (void) step_n(ph, rp.pi_nstep, FLG_SN_NONE); 494 } 495 } 496 497 oper = PRCFAULT; 498 if (writev(ph->pp_ctlfd, piov, 1) == -1) 499 perr("stn: PRCFAULT"); 500 501 if ((flgs & FLG_SN_VERBOSE) && (ph->pp_flags & FLG_PP_LMAPS)) { 502 if (get_linkmaps(ph) != PS_OK) 503 (void) fprintf(stderr, "problem loading linkmaps\n"); 504 } 505 506 return (RET_OK); 507 } 508 509 void 510 step_to_addr(struct ps_prochandle *ph, ulong_t addr) 511 { 512 pstatus_t pstat; 513 int count = 0; 514 ulong_t caddr; 515 516 if (read(ph->pp_statusfd, &pstat, sizeof (pstat)) == -1) 517 perr("sta: reading status"); 518 519 caddr = pstat.pr_lwp.pr_reg[R_PC]; 520 521 while ((caddr > addr) || ((caddr + 0xff) < addr)) { 522 (void) step_n(ph, 1, FLG_SN_NONE); 523 if (read(ph->pp_statusfd, &pstat, sizeof (pstat)) == -1) 524 perr("sta1: reading status"); 525 caddr = pstat.pr_lwp.pr_reg[R_PC]; 526 if ((count % 10000) == 0) { 527 (void) printf("%d: ", count); 528 disasm(ph, 1); 529 } 530 531 count++; 532 } 533 534 (void) printf("address found %d instructions in: pc: 0x%lx addr: " 535 "0x%lx\n", count, caddr, addr); 536 } 537