DWORD PAL_DeleteExecWatchpoint( HANDLE hThread, PVOID pvInstruction ) { PERF_ENTRY(PAL_DeleteExecWatchpoint); ENTRY("PAL_DeleteExecWatchpoint (hThread=%p, pvInstruction=%p)\n", hThread, pvInstruction); DWORD dwError = ERROR_NOT_SUPPORTED; #if HAVE_PRWATCH_T CPalThread *pThread = NULL; CPalThread *pTargetThread = NULL; IPalObject *pobjThread = NULL; int fd = -1; char ctlPath[50]; struct { long ctlCode; prwatch_t prwatch; } ctlStruct; pThread = InternalGetCurrentThread(); dwError = InternalGetThreadDataFromHandle( pThread, hThread, 0, // THREAD_SET_CONTEXT &pTargetThread, &pobjThread ); if (NO_ERROR != dwError) { goto PAL_DeleteExecWatchpointExit; } snprintf(ctlPath, sizeof(ctlPath), "/proc/%u/lwp/%u/lwpctl", getpid(), pTargetThread->GetLwpId()); fd = InternalOpen(pThread, ctlPath, O_WRONLY); if (-1 == fd) { ERROR("Failed to open %s\n", ctlPath); dwError = ERROR_INVALID_ACCESS; goto PAL_DeleteExecWatchpointExit; } ctlStruct.ctlCode = PCWATCH; ctlStruct.prwatch.pr_vaddr = (uintptr_t) pvInstruction; ctlStruct.prwatch.pr_size = sizeof(DWORD); ctlStruct.prwatch.pr_wflags = 0; if (write(fd, (void*) &ctlStruct, sizeof(ctlStruct)) != sizeof(ctlStruct)) { ERROR("Failure writing control structure (errno = %u)\n", errno); dwError = ERROR_INTERNAL_ERROR; goto PAL_DeleteExecWatchpointExit; } dwError = ERROR_SUCCESS; PAL_DeleteExecWatchpointExit: if (NULL != pobjThread) { pobjThread->ReleaseReference(pThread); } if (-1 != fd) { close(fd); } #endif // HAVE_PRWATCH_T LOGEXIT("PAL_DeleteExecWatchpoint returns ret:%d\n", dwError); PERF_EXIT(PAL_DeleteExecWatchpoint); return dwError; }
DWORD PAL_CreateExecWatchpoint( HANDLE hThread, PVOID pvInstruction ) { PERF_ENTRY(PAL_CreateExecWatchpoint); ENTRY("PAL_CreateExecWatchpoint (hThread=%p, pvInstruction=%p)\n", hThread, pvInstruction); DWORD dwError = ERROR_NOT_SUPPORTED; #if HAVE_PRWATCH_T CPalThread *pThread = NULL; CPalThread *pTargetThread = NULL; IPalObject *pobjThread = NULL; int fd = -1; char ctlPath[50]; struct { long ctlCode; prwatch_t prwatch; } ctlStruct; // // We must never set a watchpoint on an instruction that enters a syscall; // if such a request comes in we succeed it w/o actually creating the // watchpoint. This mirrors the behavior of setting the single-step flag // in a thread context when the thread is w/in a system service -- the // flag is ignored and will not be present when the thread returns // to user mode. // #if defined(_SPARC_) if (*(DWORD*)pvInstruction == 0x91d02008) // ta 8 { TRACE("Watchpoint requested on sysenter instruction -- ignoring"); dwError = ERROR_SUCCESS; goto PAL_CreateExecWatchpointExit; } #else #error Need syscall instruction for this platform #endif // _SPARC_ pThread = InternalGetCurrentThread(); dwError = InternalGetThreadDataFromHandle( pThread, hThread, 0, // THREAD_SET_CONTEXT &pTargetThread, &pobjThread ); if (NO_ERROR != dwError) { goto PAL_CreateExecWatchpointExit; } snprintf(ctlPath, sizeof(ctlPath), "/proc/%u/lwp/%u/lwpctl", getpid(), pTargetThread->GetLwpId()); fd = InternalOpen(pThread, ctlPath, O_WRONLY); if (-1 == fd) { ERROR("Failed to open %s\n", ctlPath); dwError = ERROR_INVALID_ACCESS; goto PAL_CreateExecWatchpointExit; } ctlStruct.ctlCode = PCWATCH; ctlStruct.prwatch.pr_vaddr = (uintptr_t) pvInstruction; ctlStruct.prwatch.pr_size = sizeof(DWORD); ctlStruct.prwatch.pr_wflags = WA_EXEC | WA_TRAPAFTER; if (write(fd, (void*) &ctlStruct, sizeof(ctlStruct)) != sizeof(ctlStruct)) { ERROR("Failure writing control structure (errno = %u)\n", errno); dwError = ERROR_INTERNAL_ERROR; goto PAL_CreateExecWatchpointExit; } dwError = ERROR_SUCCESS; PAL_CreateExecWatchpointExit: if (NULL != pobjThread) { pobjThread->ReleaseReference(pThread); } if (-1 != fd) { close(fd); } #endif // HAVE_PRWATCH_T LOGEXIT("PAL_CreateExecWatchpoint returns ret:%d\n", dwError); PERF_EXIT(PAL_CreateExecWatchpoint); return dwError; }