// SetPC sets the RIP register to the value specified by `pc`. func (r *Regs) SetPC(thread *Thread, pc uint64) error { var context C.CONTEXT context.ContextFlags = C.CONTEXT_ALL res := C.GetThreadContext(C.HANDLE(thread.os.hThread), &context) if res == C.FALSE { return fmt.Errorf("could not GetThreadContext") } context.Rip = C.DWORD64(pc) res = C.SetThreadContext(C.HANDLE(thread.os.hThread), &context) if res == C.FALSE { return fmt.Errorf("could not SetThreadContext") } return nil }
func (t *Thread) singleStep() error { var context C.CONTEXT context.ContextFlags = C.CONTEXT_ALL // Set the processor TRAP flag res := C.GetThreadContext(C.HANDLE(t.os.hThread), &context) if res == C.FALSE { return fmt.Errorf("could not GetThreadContext") } context.EFlags |= 0x100 res = C.SetThreadContext(C.HANDLE(t.os.hThread), &context) if res == C.FALSE { return fmt.Errorf("could not SetThreadContext") } // Suspend all threads except this one for _, thread := range t.dbp.Threads { if thread.ID == t.ID { continue } res := C.SuspendThread(C.HANDLE(thread.os.hThread)) if res == C.DWORD(0xFFFFFFFF) { return fmt.Errorf("could not suspend thread: %d", thread.ID) } } // Continue and wait for the step to complete t.dbp.execPtraceFunc(func() { res = C.ContinueDebugEvent(C.DWORD(t.dbp.Pid), C.DWORD(t.ID), C.DBG_CONTINUE) }) if res == C.FALSE { return fmt.Errorf("could not ContinueDebugEvent.") } _, err := t.dbp.trapWait(0) if err != nil { return err } // Resume all threads except this one for _, thread := range t.dbp.Threads { if thread.ID == t.ID { continue } res := C.ResumeThread(C.HANDLE(thread.os.hThread)) if res == C.DWORD(0xFFFFFFFF) { return fmt.Errorf("ould not resume thread: %d", thread.ID) } } // Unset the processor TRAP flag res = C.GetThreadContext(C.HANDLE(t.os.hThread), &context) if res == C.FALSE { return fmt.Errorf("could not GetThreadContext") } context.EFlags &= ^C.DWORD(0x100) res = C.SetThreadContext(C.HANDLE(t.os.hThread), &context) if res == C.FALSE { return fmt.Errorf("could not SetThreadContext") } return nil }