/* * Wait for the specified process to hit a breakpoint at the specified symbol. */ static void verify_bkpt(struct proc_handle *phdl, GElf_Sym *sym, const char *symname, const char *mapname) { char mapbname[MAXPATHLEN], *name; GElf_Sym tsym; prmap_t *map; size_t namesz; u_long addr; int error, state; state = proc_wstatus(phdl); ATF_REQUIRE_EQ_MSG(state, PS_STOP, "process has state %d", state); /* Get the program counter and decrement it. */ error = proc_regget(phdl, REG_PC, &addr); ATF_REQUIRE_EQ_MSG(error, 0, "failed to obtain PC for '%s'", target_prog_file); proc_bkptregadj(&addr); /* * Make sure the PC matches the expected value obtained from the symbol * definition we looked up earlier. */ ATF_CHECK_EQ_MSG(addr, sym->st_value, "program counter 0x%lx doesn't match expected value 0x%jx", addr, (uintmax_t)sym->st_value); /* * Ensure we can look up the r_debug_state symbol using its starting * address and that the resulting symbol matches the one we found using * a name lookup. */ namesz = strlen(symname) + 1; name = malloc(namesz); ATF_REQUIRE(name != NULL); error = proc_addr2sym(phdl, addr, name, namesz, &tsym); ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up symbol at 0x%lx", addr); ATF_REQUIRE_EQ(memcmp(sym, &tsym, sizeof(*sym)), 0); ATF_REQUIRE_EQ_MSG(strcmp(symname, name), 0, "expected symbol name '%s' doesn't match '%s'", symname, name); free(name); map = proc_addr2map(phdl, addr); ATF_REQUIRE_MSG(map != NULL, "failed to look up map for address 0x%lx", addr); basename_r(map->pr_mapname, mapbname); ATF_REQUIRE_EQ_MSG(strcmp(mapname, mapbname), 0, "expected map name '%s' doesn't match '%s'", mapname, mapbname); }
/* * Step over the breakpoint. */ int proc_bkptexec(struct proc_handle *phdl, unsigned long saved) { unsigned long pc; unsigned long samesaved; int status; if (proc_regget(phdl, REG_PC, &pc) < 0) { warn("ERROR: couldn't get PC register"); return (-1); } proc_bkptregadj(&pc); if (proc_bkptdel(phdl, pc, saved) < 0) { warn("ERROR: couldn't delete breakpoint"); return (-1); } /* * Go back in time and step over the new instruction just * set up by proc_bkptdel(). */ proc_regset(phdl, REG_PC, pc); if (ptrace(PT_STEP, proc_getpid(phdl), (caddr_t)1, 0) < 0) { warn("ERROR: ptrace step failed"); return (-1); } proc_wstatus(phdl); status = proc_getwstat(phdl); if (!WIFSTOPPED(status)) { warn("ERROR: don't know why process stopped"); return (-1); } /* * Restore the breakpoint. The saved instruction should be * the same as the one that we were passed in. */ if (proc_bkptset(phdl, pc, &samesaved) < 0) { warn("ERROR: couldn't restore breakpoint"); return (-1); } assert(samesaved == saved); return (0); }
static void dt_proc_bpmatch(dtrace_hdl_t *dtp, dt_proc_t *dpr) { #ifdef illumos const lwpstatus_t *psp = &Pstatus(dpr->dpr_proc)->pr_lwp; #else unsigned long pc; #endif dt_bkpt_t *dbp; assert(DT_MUTEX_HELD(&dpr->dpr_lock)); #ifndef illumos proc_regget(dpr->dpr_proc, REG_PC, &pc); proc_bkptregadj(&pc); #endif for (dbp = dt_list_next(&dpr->dpr_bps); dbp != NULL; dbp = dt_list_next(dbp)) { #ifdef illumos if (psp->pr_reg[R_PC] == dbp->dbp_addr) break; #else if (pc == dbp->dbp_addr) break; #endif } if (dbp == NULL) { dt_dprintf("pid %d: spurious breakpoint wakeup for %lx\n", #ifdef illumos (int)dpr->dpr_pid, (ulong_t)psp->pr_reg[R_PC]); #else (int)dpr->dpr_pid, pc); #endif return; }