* Step now accepts pid+tid
* Fix attach in w32 debugger - use dpa and get first thread by default * Mark with asterisks the selected pid/thread (dp/dpt) * Fix reg_write in w32
This commit is contained in:
parent
8df7b217eb
commit
0aafe05b45
|
@ -192,6 +192,7 @@ int main(int argc, char **argv) {
|
|||
if (debug) {
|
||||
r_core_cmd (&r, "e io.ffio=true", 0);
|
||||
r_core_cmd (&r, "dh native", 0);
|
||||
r_core_cmdf (&r, "dpa %d", r.file->fd);
|
||||
r_core_cmdf (&r, "dp=%d", r.file->fd);
|
||||
r_core_cmd (&r, ".dr*", 0);
|
||||
r_core_cmd (&r, "sr pc", 0);
|
||||
|
|
|
@ -3766,12 +3766,10 @@ static void cmd_debug_pid(RCore *core, const char *input) {
|
|||
case 'a':
|
||||
r_debug_attach (core->dbg,
|
||||
(int) r_num_math (core->num, input+2));
|
||||
r_debug_select (core->dbg,
|
||||
(int) r_num_math (core->num, input+2),
|
||||
(int) r_num_math (core->num, input+2));
|
||||
r_debug_select (core->dbg, core->dbg->pid, core->dbg->tid);
|
||||
break;
|
||||
case 'f':
|
||||
r_debug_select (core->dbg, core->file->fd, core->file->fd);
|
||||
r_debug_select (core->dbg, core->file->fd, core->dbg->tid);
|
||||
break;
|
||||
case '=':
|
||||
r_debug_select (core->dbg,
|
||||
|
@ -3921,11 +3919,13 @@ static int cmd_debug(void *data, const char *input) {
|
|||
if (ptr) {
|
||||
bypassbp (core);
|
||||
int old_pid = core->dbg->pid;
|
||||
int old_tid = core->dbg->tid;
|
||||
int pid = atoi (ptr+1);
|
||||
int tid = pid; // XXX
|
||||
*ptr = 0;
|
||||
r_debug_select (core->dbg, pid, pid);
|
||||
r_debug_select (core->dbg, pid, tid);
|
||||
r_debug_continue_kill (core->dbg, atoi (input+2));
|
||||
r_debug_select (core->dbg, old_pid, old_pid);
|
||||
r_debug_select (core->dbg, old_pid, old_tid);
|
||||
} else r_debug_continue_kill (core->dbg, atoi (input+2));
|
||||
checkbpcallback (core);
|
||||
break;
|
||||
|
@ -3955,9 +3955,9 @@ static int cmd_debug(void *data, const char *input) {
|
|||
int pid = atoi (input+2);
|
||||
bypassbp (core);
|
||||
r_reg_arena_swap (core->dbg->reg, R_TRUE);
|
||||
r_debug_select (core->dbg, pid, pid);
|
||||
r_debug_select (core->dbg, pid, core->dbg->tid);
|
||||
r_debug_continue (core->dbg);
|
||||
r_debug_select (core->dbg, old_pid, old_pid);
|
||||
r_debug_select (core->dbg, old_pid, core->dbg->tid);
|
||||
checkbpcallback (core);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -63,13 +63,15 @@ R_API int r_debug_attach(struct r_debug_t *dbg, int pid) {
|
|||
int ret = R_FALSE;
|
||||
if (dbg && dbg->h && dbg->h->attach) {
|
||||
ret = dbg->h->attach (pid);
|
||||
if (ret) {
|
||||
if (ret != -1) {
|
||||
eprintf ("pid = %d tid = %d\n", pid, ret);
|
||||
// TODO: get arch and set io pid
|
||||
//int arch = dbg->h->arch;
|
||||
//r_reg_set(dbg->reg->nregs, arch); //R_DBG_ARCH_X86);
|
||||
// dbg->bp->iob->system("pid %d", pid);
|
||||
dbg->pid = pid;
|
||||
dbg->tid = pid;
|
||||
//dbg->pid = pid;
|
||||
//dbg->tid = ret;
|
||||
r_debug_select (dbg, pid, ret); //dbg->pid, dbg->tid);
|
||||
} else eprintf ("Cannot attach to this pid\n");
|
||||
} else eprintf ("dbg->attach = NULL\n");
|
||||
return ret;
|
||||
|
@ -198,7 +200,7 @@ R_API int r_debug_step_soft(RDebug *dbg) {
|
|||
}
|
||||
|
||||
R_API int r_debug_step_hard(RDebug *dbg) {
|
||||
if (!dbg->h->step (dbg, dbg->pid))
|
||||
if (!dbg->h->step (dbg))
|
||||
return R_FALSE;
|
||||
return r_debug_wait (dbg);
|
||||
}
|
||||
|
@ -245,7 +247,7 @@ R_API int r_debug_continue_kill(RDebug *dbg, int sig) {
|
|||
int ret = R_FALSE;
|
||||
if (dbg && dbg->h && dbg->h->cont) {
|
||||
r_bp_restore (dbg->bp, R_FALSE); // set sw breakpoints
|
||||
ret = dbg->h->cont (dbg->pid, sig);
|
||||
ret = dbg->h->cont (dbg->pid, dbg->tid, sig);
|
||||
if (dbg->h->wait)
|
||||
ret = dbg->h->wait (dbg->pid);
|
||||
r_bp_restore (dbg->bp, R_TRUE); // unset sw breakpoints
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <r_lib.h>
|
||||
#include <signal.h>
|
||||
|
||||
static int r_debug_native_continue(int pid, int sig);
|
||||
static int r_debug_native_continue(int pid, int tid, int sig);
|
||||
static int r_debug_native_reg_read(RDebug *dbg, int type, ut8 *buf, int size);
|
||||
static int r_debug_native_reg_write(int pid, int tid, int type, const ut8* buf, int size);
|
||||
|
||||
|
@ -148,21 +148,18 @@ static inline void debug_arch_x86_trap_set(RDebug *dbg, int foo) {
|
|||
}
|
||||
#endif // __APPLE__
|
||||
|
||||
static int r_debug_native_step(RDebug *dbg, int pid) {
|
||||
static int r_debug_native_step(RDebug *dbg) {
|
||||
int ret = R_FALSE;
|
||||
int pid = dbg->pid;
|
||||
#if __WINDOWS__
|
||||
CONTEXT regs;
|
||||
//R_DEBUG_REG_T regs;
|
||||
|
||||
regs.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
|
||||
// GetTheadContext (tid2hnd
|
||||
// XXX TODO CONTINUE h
|
||||
/* up TRAP flag */
|
||||
CONTEXT regs __attribute__((aligned (16)));
|
||||
/* set TRAP flag */
|
||||
/*
|
||||
r_debug_native_reg_read (dbg, R_REG_TYPE_GPR, ®s, sizeof (regs));
|
||||
regs.EFlags |= 0x100;
|
||||
r_debug_native_reg_write (dbg->pid, dbg->tid, R_REG_TYPE_GPR, ®s, sizeof (regs));
|
||||
//single_step = pid;
|
||||
r_debug_native_continue (pid, -1);
|
||||
r_debug_native_reg_write (pid, dbg->tid, R_REG_TYPE_GPR, ®s, sizeof (regs));
|
||||
*/
|
||||
r_debug_native_continue (pid, dbg->tid, -1);
|
||||
#elif __APPLE__
|
||||
debug_arch_x86_trap_set (dbg, 1);
|
||||
// TODO: not supported in all platforms. need dbg.swstep=
|
||||
|
@ -193,21 +190,25 @@ static int r_debug_native_step(RDebug *dbg, int pid) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
// return thread id
|
||||
static int r_debug_native_attach(int pid) {
|
||||
int ret = -1;
|
||||
#if __WINDOWS__
|
||||
HANDLE hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
|
||||
if (hProcess != (HANDLE)NULL && DebugActiveProcess (pid)) {
|
||||
w32_dbg_threads (pid);
|
||||
ret = 0;
|
||||
ret = w32_first_thread (pid);
|
||||
} else ret = -1;
|
||||
ret = w32_first_thread (pid);
|
||||
#elif __APPLE__
|
||||
ret = ptrace (PT_ATTACH, pid, 0, 0);
|
||||
if (ret!=-1)
|
||||
ret = pid;
|
||||
#else
|
||||
ret = ptrace (PTRACE_ATTACH, pid, 0, 0);
|
||||
eprintf ("attach=%d\n", ret);
|
||||
if (ret!=-1)
|
||||
ret = pid;
|
||||
#endif
|
||||
return (ret != -1)?R_TRUE:R_FALSE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int r_debug_native_detach(int pid) {
|
||||
|
@ -234,12 +235,13 @@ static int r_debug_native_continue_syscall(int pid, int num) {
|
|||
|
||||
/* TODO: specify thread? */
|
||||
/* TODO: must return true/false */
|
||||
static int r_debug_native_continue(int pid, int sig) {
|
||||
static int r_debug_native_continue(int pid, int tid, int sig) {
|
||||
void *data = NULL;
|
||||
if (sig != -1)
|
||||
data = (void*)(size_t)sig;
|
||||
#if __WINDOWS__
|
||||
if (ContinueDebugEvent (pid, pid, DBG_CONTINUE) == 0) {
|
||||
if (ContinueDebugEvent (pid, tid, DBG_CONTINUE) == 0) {
|
||||
print_lasterr ((char *)__FUNCTION__);
|
||||
eprintf ("debug_contp: error\n");
|
||||
return -1;
|
||||
}
|
||||
|
@ -940,9 +942,11 @@ static int r_debug_native_reg_write(int pid, int tid, int type, const ut8* buf,
|
|||
} else
|
||||
if (type == R_REG_TYPE_GPR) {
|
||||
#if __WINDOWS__
|
||||
CONTEXT ctx;
|
||||
CONTEXT ctx __attribute__((aligned(16)));
|
||||
memcpy (&ctx, buf, sizeof (CONTEXT));
|
||||
ctx.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
|
||||
return SetThreadContext (tid2handler (pid, tid), &ctx)? 0: -1;
|
||||
// eprintf ("EFLAGS =%x\n", ctx.EFlags);
|
||||
return SetThreadContext (tid2handler (pid, tid), &ctx)? R_TRUE: R_FALSE;
|
||||
#elif __linux__ || __sun || __NetBSD__ || __FreeBSD__ || __OpenBSD__
|
||||
int ret = ptrace (PTRACE_SETREGS, pid, 0, buf);
|
||||
if (sizeof (R_DEBUG_REG_T) < size)
|
||||
|
|
|
@ -113,7 +113,7 @@ static void print_lasterr(const char *str) {
|
|||
0, // ignored
|
||||
0, // ignored
|
||||
(LPTSTR)&buffer,
|
||||
size,
|
||||
size-1,
|
||||
(va_list*)pArgs)) {
|
||||
eprintf ("(%s): Format message failed with 0x%x\n",
|
||||
r_str_get (str), GetLastError());
|
||||
|
@ -194,47 +194,43 @@ static inline int w32_h2p(HANDLE h) {
|
|||
}
|
||||
|
||||
// TODO: not yet used !!!
|
||||
static int w32_dbg_threads(int pid) {
|
||||
#if 0
|
||||
HANDLE th;
|
||||
THREADENTRY32 te32;
|
||||
TH_INFO *th_i;
|
||||
int ret = -1;
|
||||
te32.dwSize = sizeof (THREADENTRY32);
|
||||
static int w32_first_thread(int pid) {
|
||||
HANDLE th;
|
||||
HANDLE thid;
|
||||
THREADENTRY32 te32;
|
||||
int ret = -1;
|
||||
|
||||
th = CreateToolhelp32Snapshot (TH32CS_SNAPTHREAD, ps.pid);
|
||||
if (th == INVALID_HANDLE_VALUE || !Thread32First(th, &te32))
|
||||
goto err_load_th;
|
||||
te32.dwSize = sizeof(THREADENTRY32);
|
||||
|
||||
//free_th ();
|
||||
do {
|
||||
/* get all threads of process */
|
||||
if (te32.th32OwnerProcessID == pid) {
|
||||
const char *path = "unk";
|
||||
RDebugPid *pid = r_debug_pid_new (
|
||||
path, te32.th32ThreadID, 's', 0); // TODO: add pc
|
||||
eprintf ("THREAD: id=0x%08x flags=0x%08x\n",
|
||||
te32.th32ThreadID, te32.dwFlags);
|
||||
eprintf ("HANDLER: 0x%p\n", w32_openthread (
|
||||
THREAD_ALL_ACCESS, 0, te32.th32ThreadID));
|
||||
/* open a new handler */
|
||||
//th_i->ht = w32_openthread(THREAD_ALL_ACCESS, 0,
|
||||
// te32.th32ThreadID);
|
||||
ret = te32.th32ThreadID;
|
||||
//r_list_append (list, thread);
|
||||
}
|
||||
} while (Thread32Next (th, &te32));
|
||||
|
||||
err_load_th:
|
||||
if (ret == -1)
|
||||
if (w32_openthread == NULL) {
|
||||
eprintf("w32_thread_list: no w32_openthread?\n");
|
||||
return -1;
|
||||
//print_lasterr((char *)__FUNCTION__);
|
||||
|
||||
if (th != INVALID_HANDLE_VALUE)
|
||||
ClosePlugin (th);
|
||||
return ret;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
th = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, pid);
|
||||
if (th == INVALID_HANDLE_VALUE) {
|
||||
eprintf ("w32_thread_list: invalid handle\n");
|
||||
return -1;
|
||||
}
|
||||
if (!Thread32First (th, &te32)) {
|
||||
CloseHandle (th);
|
||||
eprintf ("w32_thread_list: no thread first\n");
|
||||
return -1;
|
||||
}
|
||||
do {
|
||||
/* get all threads of process */
|
||||
if (te32.th32OwnerProcessID == pid) {
|
||||
thid = w32_openthread (THREAD_ALL_ACCESS, 0, te32.th32ThreadID);
|
||||
if (thid == NULL)
|
||||
goto err_load_th;
|
||||
CloseHandle (th);
|
||||
return te32.th32ThreadID;
|
||||
}
|
||||
} while (Thread32Next (th, &te32));
|
||||
err_load_th:
|
||||
if (ret == -1)
|
||||
print_lasterr ((char *)__FUNCTION__);
|
||||
eprintf ("w32thread: Oops\n");
|
||||
return pid; // -1 ?
|
||||
}
|
||||
|
||||
static int debug_exception_event (unsigned long code) {
|
||||
|
@ -290,7 +286,7 @@ static int w32_dbg_wait(int pid) {
|
|||
pid, w32_h2t (de.u.CreateProcessInfo.
|
||||
hProcess),
|
||||
de.u.CreateProcessInfo.lpStartAddress);
|
||||
r_debug_native_continue (pid, -1);
|
||||
r_debug_native_continue (pid, tid, -1);
|
||||
next_event = 1;
|
||||
ret = R_DBG_REASON_NEW_PID;
|
||||
break;
|
||||
|
@ -303,45 +299,44 @@ static int w32_dbg_wait(int pid) {
|
|||
case CREATE_THREAD_DEBUG_EVENT:
|
||||
eprintf ("(%d) created thread (0x%x)\n",
|
||||
pid, de.u.CreateThread.lpStartAddress);
|
||||
r_debug_native_continue (pid, -1);
|
||||
r_debug_native_continue (pid, tid, -1);
|
||||
ret = R_DBG_REASON_NEW_TID;
|
||||
next_event = 1;
|
||||
break;
|
||||
case EXIT_THREAD_DEBUG_EVENT:
|
||||
eprintf("EXIT_THREAD\n");
|
||||
r_debug_native_continue (pid, -1);
|
||||
r_debug_native_continue (pid, tid, -1);
|
||||
next_event = 1;
|
||||
ret = R_DBG_REASON_EXIT_TID;
|
||||
break;
|
||||
case LOAD_DLL_DEBUG_EVENT:
|
||||
eprintf("(%d) Loading %s library at 0x%x\n",
|
||||
pid, "", de.u.LoadDll.lpBaseOfDll);
|
||||
r_debug_native_continue (pid, -1);
|
||||
r_debug_native_continue (pid, tid, -1);
|
||||
next_event = 1;
|
||||
ret = R_DBG_REASON_NEW_LIB;
|
||||
break;
|
||||
case UNLOAD_DLL_DEBUG_EVENT:
|
||||
eprintf ("UNLOAD_DLL\n");
|
||||
r_debug_native_continue (pid, -1);
|
||||
r_debug_native_continue (pid, tid, -1);
|
||||
next_event = 1;
|
||||
ret = R_DBG_REASON_EXIT_LIB;
|
||||
break;
|
||||
case OUTPUT_DEBUG_STRING_EVENT:
|
||||
eprintf("OUTPUT_DBUG_STING\n");
|
||||
r_debug_native_continue (pid, -1);
|
||||
r_debug_native_continue (pid, tid, -1);
|
||||
next_event = 1;
|
||||
break;
|
||||
case RIP_EVENT:
|
||||
eprintf("RIP_EVENT\n");
|
||||
r_debug_native_continue (pid, -1);
|
||||
r_debug_native_continue (pid, tid, -1);
|
||||
next_event = 1;
|
||||
// XXX unknown ret = R_DBG_REASON_TRAP;
|
||||
break;
|
||||
case EXCEPTION_DEBUG_EVENT:
|
||||
next_event = debug_exception_event (
|
||||
de.u.Exception.ExceptionRecord.ExceptionCode);
|
||||
ret = R_DBG_REASON_TRAP;
|
||||
break;
|
||||
return R_DBG_REASON_TRAP;
|
||||
default:
|
||||
eprintf ("Unknown event: %d\n", code);
|
||||
return -1;
|
||||
|
|
|
@ -28,7 +28,9 @@ R_API int r_debug_pid_list(struct r_debug_t *dbg, int pid) {
|
|||
iter = r_list_iterator (list);
|
||||
while (r_list_iter_next (iter)) {
|
||||
RDebugPid *p = r_list_iter_get (iter);
|
||||
eprintf (" %d %c %s\n", p->pid, p->status, p->path);
|
||||
eprintf (" %c %d %c %s\n",
|
||||
dbg->pid==p->pid?'*':'-',
|
||||
p->pid, p->status, p->path);
|
||||
}
|
||||
r_list_free (list);
|
||||
}
|
||||
|
@ -45,7 +47,9 @@ R_API int r_debug_thread_list(struct r_debug_t *dbg, int pid) {
|
|||
iter = r_list_iterator (list);
|
||||
while (r_list_iter_next (iter)) {
|
||||
RDebugPid *p = r_list_iter_get (iter);
|
||||
eprintf (" %d %c %s\n", p->pid, p->status, p->path);
|
||||
eprintf (" %c %d %c %s\n",
|
||||
dbg->tid==p->pid?'*':'-',
|
||||
p->pid, p->status, p->path);
|
||||
}
|
||||
r_list_free (list);
|
||||
}
|
||||
|
|
|
@ -135,8 +135,8 @@ typedef struct r_debug_plugin_t {
|
|||
RList *(*pids)(int pid);
|
||||
RFList (*backtrace)(int count);
|
||||
/* flow */
|
||||
int (*step)(RDebug *dbg, int pid); // if step() is NULL; reimplement it with traps
|
||||
int (*cont)(int pid, int sig);
|
||||
int (*step)(RDebug *dbg);
|
||||
int (*cont)(int pid, int tid, int sig);
|
||||
int (*wait)(int pid);
|
||||
int (*kill)(RDebug *dbg, boolt thread, int sig);
|
||||
int (*contsc)(int pid, int sc);
|
||||
|
|
Loading…
Reference in New Issue