Add support for Windows on ARM (#1502)
* Support building for Windows on ARM * Fix usage of reserved function name on ARM * Fix architecture dependent `CONTEXT` fields access * Fixes for debugging on Windows on ARM * Fix breakpoint behavior on windows on ARM * Fix register profile when debugging * Remove `drx` error message if not supported * Add support for hardware breakpoints * Disable support for hardware single-stepping * Fix Windows Message breakpoints on ARM * Fix software single-stepping on return instruction on ARM * Consider link register as destination for return instructions * Fix setting debug bits to 16 * Rename `r12` to `ip` for windows arm register profile * Remove debug bits hardcoding on windows * Add 32bit registers to Windows ARM64 register profile * Fix software step breakpoint alignment when entering thumb mode * Define `RZ_TEST_ARCH` for `arm` and `arm64` * Use `StackWalk64` API for backtracing on Windows * Fix software single-stepping ARM in thumb mode * Sync `asm.bits` with debugger * Cleanup windows_debug.c * Add SPDX for cross-arm64-windows.txt * Add floating point control register flags * Fix Windows Arm register profile alignment * Keep `drx` warning
This commit is contained in:
parent
73fa2b30a5
commit
53a7694631
21 changed files with 816 additions and 283 deletions
|
|
@ -22,6 +22,10 @@
|
||||||
#define RZ_TEST_ARCH "x86"
|
#define RZ_TEST_ARCH "x86"
|
||||||
#elif __x86_64__
|
#elif __x86_64__
|
||||||
#define RZ_TEST_ARCH "x64"
|
#define RZ_TEST_ARCH "x64"
|
||||||
|
#elif __arm__
|
||||||
|
#define RZ_TEST_ARCH "arm"
|
||||||
|
#elif __arm64__
|
||||||
|
#define RZ_TEST_ARCH "arm64"
|
||||||
#else
|
#else
|
||||||
#define RZ_TEST_ARCH "unknown"
|
#define RZ_TEST_ARCH "unknown"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -696,14 +696,6 @@ static bool cb_asmbits(void *user, void *data) {
|
||||||
bool load_from_debug = rz_config_get_b(core->config, "cfg.debug");
|
bool load_from_debug = rz_config_get_b(core->config, "cfg.debug");
|
||||||
if (load_from_debug) {
|
if (load_from_debug) {
|
||||||
if (core->dbg->cur && core->dbg->cur->reg_profile) {
|
if (core->dbg->cur && core->dbg->cur->reg_profile) {
|
||||||
// XXX. that should depend on the plugin, not the host os
|
|
||||||
#if __WINDOWS__
|
|
||||||
#if !defined(_WIN64)
|
|
||||||
core->dbg->bits = RZ_SYS_BITS_32;
|
|
||||||
#else
|
|
||||||
core->dbg->bits = RZ_SYS_BITS_64;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
char *rp = core->dbg->cur->reg_profile(core->dbg);
|
char *rp = core->dbg->cur->reg_profile(core->dbg);
|
||||||
rz_reg_set_profile_string(core->dbg->reg, rp);
|
rz_reg_set_profile_string(core->dbg->reg, rp);
|
||||||
rz_reg_set_profile_string(core->analysis->reg, rp);
|
rz_reg_set_profile_string(core->analysis->reg, rp);
|
||||||
|
|
@ -3383,7 +3375,11 @@ RZ_API int rz_core_config_init(RzCore *core) {
|
||||||
|
|
||||||
SETCB("dbg.bpinmaps", "true", &cb_dbg_bpinmaps, "Activate breakpoints only if they are inside a valid map");
|
SETCB("dbg.bpinmaps", "true", &cb_dbg_bpinmaps, "Activate breakpoints only if they are inside a valid map");
|
||||||
SETCB("dbg.forks", "false", &cb_dbg_forks, "Stop execution if fork() is done (see dbg.threads)");
|
SETCB("dbg.forks", "false", &cb_dbg_forks, "Stop execution if fork() is done (see dbg.threads)");
|
||||||
|
#if __WINDOWS__
|
||||||
|
n = NODECB("dbg.btalgo", "default", &cb_dbg_btalgo);
|
||||||
|
#else
|
||||||
n = NODECB("dbg.btalgo", "fuzzy", &cb_dbg_btalgo);
|
n = NODECB("dbg.btalgo", "fuzzy", &cb_dbg_btalgo);
|
||||||
|
#endif
|
||||||
SETDESC(n, "Select backtrace algorithm");
|
SETDESC(n, "Select backtrace algorithm");
|
||||||
SETOPTIONS(n, "default", "fuzzy", "analysis", "trace", NULL);
|
SETOPTIONS(n, "default", "fuzzy", "analysis", "trace", NULL);
|
||||||
SETCB("dbg.threads", "false", &cb_stopthreads, "Stop all threads when debugger breaks (see dbg.forks)");
|
SETCB("dbg.threads", "false", &cb_stopthreads, "Stop all threads when debugger breaks (see dbg.forks)");
|
||||||
|
|
|
||||||
|
|
@ -585,6 +585,25 @@ RZ_API void rz_core_debug_ri(RzCore *core, RzReg *reg, int mode) {
|
||||||
ht_up_free(db);
|
ht_up_free(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RZ_IPI void rz_core_debug_sync_bits(RzCore *core) {
|
||||||
|
if (rz_config_get_b(core->config, "cfg.debug")) {
|
||||||
|
switch (core->dbg->bits) {
|
||||||
|
case RZ_SYS_BITS_8:
|
||||||
|
rz_config_set_i(core->config, "asm.bits", 8);
|
||||||
|
break;
|
||||||
|
case RZ_SYS_BITS_16:
|
||||||
|
rz_config_set_i(core->config, "asm.bits", 16);
|
||||||
|
break;
|
||||||
|
case RZ_SYS_BITS_32:
|
||||||
|
rz_config_set_i(core->config, "asm.bits", 32);
|
||||||
|
break;
|
||||||
|
case RZ_SYS_BITS_64:
|
||||||
|
rz_config_set_i(core->config, "asm.bits", 64);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RZ_IPI void rz_core_debug_single_step_in(RzCore *core) {
|
RZ_IPI void rz_core_debug_single_step_in(RzCore *core) {
|
||||||
if (rz_config_get_b(core->config, "cfg.debug")) {
|
if (rz_config_get_b(core->config, "cfg.debug")) {
|
||||||
if (core->print->cur_enabled) {
|
if (core->print->cur_enabled) {
|
||||||
|
|
|
||||||
|
|
@ -703,6 +703,7 @@ RZ_IPI void rz_core_dbg_follow_seek_register(RzCore *core) {
|
||||||
if ((pc < core->offset) || (pc > (core->offset + follow))) {
|
if ((pc < core->offset) || (pc > (core->offset + follow))) {
|
||||||
rz_core_seek_to_register(core, "PC", false);
|
rz_core_seek_to_register(core, "PC", false);
|
||||||
}
|
}
|
||||||
|
rz_core_debug_sync_bits(core);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,7 @@ RZ_IPI bool rz_core_debug_reg_set(RzCore *core, const char *regname, ut64 val, c
|
||||||
RZ_IPI bool rz_core_debug_reg_list(RzCore *core, int type, int size, bool skip_covered, PJ *pj, int rad, const char *use_color);
|
RZ_IPI bool rz_core_debug_reg_list(RzCore *core, int type, int size, bool skip_covered, PJ *pj, int rad, const char *use_color);
|
||||||
RZ_IPI void rz_core_debug_regs2flags(RzCore *core);
|
RZ_IPI void rz_core_debug_regs2flags(RzCore *core);
|
||||||
RZ_IPI void rz_core_regs2flags(RzCore *core);
|
RZ_IPI void rz_core_regs2flags(RzCore *core);
|
||||||
|
RZ_IPI void rz_core_debug_sync_bits(RzCore *core);
|
||||||
RZ_IPI void rz_core_debug_single_step_in(RzCore *core);
|
RZ_IPI void rz_core_debug_single_step_in(RzCore *core);
|
||||||
RZ_IPI void rz_core_debug_single_step_over(RzCore *core);
|
RZ_IPI void rz_core_debug_single_step_over(RzCore *core);
|
||||||
RZ_IPI void rz_core_debug_breakpoint_toggle(RzCore *core, ut64 addr);
|
RZ_IPI void rz_core_debug_breakpoint_toggle(RzCore *core, ut64 addr);
|
||||||
|
|
|
||||||
|
|
@ -3363,6 +3363,7 @@ RZ_API void rz_core_visual_title(RzCore *core, int color) {
|
||||||
} else if (follow < 0) {
|
} else if (follow < 0) {
|
||||||
rz_core_seek(core, curpc + follow, true);
|
rz_core_seek(core, curpc + follow, true);
|
||||||
}
|
}
|
||||||
|
rz_core_debug_sync_bits(core);
|
||||||
oldpc = curpc;
|
oldpc = curpc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -461,6 +461,11 @@ RZ_API int rz_debug_stop(RzDebug *dbg) {
|
||||||
RZ_API bool rz_debug_set_arch(RzDebug *dbg, const char *arch, int bits) {
|
RZ_API bool rz_debug_set_arch(RzDebug *dbg, const char *arch, int bits) {
|
||||||
if (arch && dbg && dbg->cur) {
|
if (arch && dbg && dbg->cur) {
|
||||||
switch (bits) {
|
switch (bits) {
|
||||||
|
case 16:
|
||||||
|
if (dbg->cur->bits & RZ_SYS_BITS_16) {
|
||||||
|
dbg->bits = RZ_SYS_BITS_16;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 27:
|
case 27:
|
||||||
if (dbg->cur->bits == 27) {
|
if (dbg->cur->bits == 27) {
|
||||||
dbg->bits = 27;
|
dbg->bits = 27;
|
||||||
|
|
@ -798,6 +803,9 @@ RZ_API int rz_debug_step_soft(RzDebug *dbg) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool has_lr_reg = rz_reg_get_name(dbg->reg, RZ_REG_NAME_LR);
|
||||||
|
const bool arch_ret_is_pop = !strcmp(dbg->arch, "arm") && dbg->bits <= RZ_SYS_BITS_32;
|
||||||
|
|
||||||
pc = rz_debug_reg_get(dbg, dbg->reg->name[RZ_REG_NAME_PC]);
|
pc = rz_debug_reg_get(dbg, dbg->reg->name[RZ_REG_NAME_PC]);
|
||||||
sp = rz_debug_reg_get(dbg, dbg->reg->name[RZ_REG_NAME_SP]);
|
sp = rz_debug_reg_get(dbg, dbg->reg->name[RZ_REG_NAME_SP]);
|
||||||
|
|
||||||
|
|
@ -815,8 +823,15 @@ RZ_API int rz_debug_step_soft(RzDebug *dbg) {
|
||||||
}
|
}
|
||||||
switch (op.type) {
|
switch (op.type) {
|
||||||
case RZ_ANALYSIS_OP_TYPE_RET:
|
case RZ_ANALYSIS_OP_TYPE_RET:
|
||||||
dbg->iob.read_at(dbg->iob.io, sp, (ut8 *)&sp_top, 8);
|
if (arch_ret_is_pop && op.stackop == RZ_ANALYSIS_STACK_INC) {
|
||||||
next[0] = (dbg->bits == RZ_SYS_BITS_32) ? sp_top.r32[0] : sp_top.r64;
|
dbg->iob.read_at(dbg->iob.io, sp - op.stackptr - 4, (ut8 *)&sp_top, 4);
|
||||||
|
next[0] = sp_top.r32[0];
|
||||||
|
} else if (has_lr_reg) {
|
||||||
|
next[0] = rz_debug_reg_get(dbg, dbg->reg->name[RZ_REG_NAME_LR]);
|
||||||
|
} else {
|
||||||
|
dbg->iob.read_at(dbg->iob.io, sp, (ut8 *)&sp_top, 8);
|
||||||
|
next[0] = (dbg->bits <= RZ_SYS_BITS_32) ? sp_top.r32[0] : sp_top.r64;
|
||||||
|
}
|
||||||
br = 1;
|
br = 1;
|
||||||
break;
|
break;
|
||||||
case RZ_ANALYSIS_OP_TYPE_CJMP:
|
case RZ_ANALYSIS_OP_TYPE_CJMP:
|
||||||
|
|
@ -842,7 +857,7 @@ RZ_API int rz_debug_step_soft(RzDebug *dbg) {
|
||||||
if (!dbg->iob.read_at(dbg->iob.io, r, (ut8 *)&memval, 8)) {
|
if (!dbg->iob.read_at(dbg->iob.io, r, (ut8 *)&memval, 8)) {
|
||||||
next[0] = op.addr + op.size;
|
next[0] = op.addr + op.size;
|
||||||
} else {
|
} else {
|
||||||
next[0] = (dbg->bits == RZ_SYS_BITS_32) ? memval.r32[0] : memval.r64;
|
next[0] = (dbg->bits <= RZ_SYS_BITS_32) ? memval.r32[0] : memval.r64;
|
||||||
}
|
}
|
||||||
br = 1;
|
br = 1;
|
||||||
break;
|
break;
|
||||||
|
|
@ -857,7 +872,7 @@ RZ_API int rz_debug_step_soft(RzDebug *dbg) {
|
||||||
if (!dbg->iob.read_at(dbg->iob.io, r * op.scale + op.disp, (ut8 *)&memval, 8)) {
|
if (!dbg->iob.read_at(dbg->iob.io, r * op.scale + op.disp, (ut8 *)&memval, 8)) {
|
||||||
next[0] = op.addr + op.size;
|
next[0] = op.addr + op.size;
|
||||||
} else {
|
} else {
|
||||||
next[0] = (dbg->bits == RZ_SYS_BITS_32) ? memval.r32[0] : memval.r64;
|
next[0] = (dbg->bits <= RZ_SYS_BITS_32) ? memval.r32[0] : memval.r64;
|
||||||
}
|
}
|
||||||
br = 1;
|
br = 1;
|
||||||
break;
|
break;
|
||||||
|
|
@ -867,7 +882,11 @@ RZ_API int rz_debug_step_soft(RzDebug *dbg) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int align = rz_analysis_archinfo(dbg->analysis, RZ_ANALYSIS_ARCHINFO_ALIGN);
|
||||||
for (i = 0; i < br; i++) {
|
for (i = 0; i < br; i++) {
|
||||||
|
if (align > 1) {
|
||||||
|
next[i] = next[i] - (next[i] % align);
|
||||||
|
}
|
||||||
RzBreakpointItem *bpi = rz_bp_add_sw(dbg->bp, next[i], dbg->bpsize, RZ_BP_PROT_EXEC);
|
RzBreakpointItem *bpi = rz_bp_add_sw(dbg->bp, next[i], dbg->bpsize, RZ_BP_PROT_EXEC);
|
||||||
if (bpi) {
|
if (bpi) {
|
||||||
bpi->swstep = true;
|
bpi->swstep = true;
|
||||||
|
|
|
||||||
|
|
@ -129,9 +129,10 @@ static int rz_debug_native_step(RzDebug *dbg) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
#else // linux
|
#elif __linux__
|
||||||
return linux_step(dbg);
|
return linux_step(dbg);
|
||||||
#endif
|
#endif
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return thread id
|
// return thread id
|
||||||
|
|
@ -1305,7 +1306,7 @@ static int rz_debug_native_drx(RzDebug *dbg, int n, ut64 addr, int sz, int rwx,
|
||||||
#else
|
#else
|
||||||
eprintf("drx: Unsupported platform\n");
|
eprintf("drx: Unsupported platform\n");
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if __linux__
|
#if __linux__
|
||||||
|
|
@ -1434,6 +1435,10 @@ static int rz_debug_native_bp(RzBreakpoint *bp, RzBreakpointItem *b, bool set) {
|
||||||
return set
|
return set
|
||||||
? arm64_hwbp_add(dbg, bp, b)
|
? arm64_hwbp_add(dbg, bp, b)
|
||||||
: arm64_hwbp_del(dbg, bp, b);
|
: arm64_hwbp_del(dbg, bp, b);
|
||||||
|
#elif __WINDOWS__
|
||||||
|
return set
|
||||||
|
? w32_hwbp_arm_add(dbg, bp, b)
|
||||||
|
: w32_hwbp_arm_del(dbg, bp, b);
|
||||||
#elif __arm__ && __linux__
|
#elif __arm__ && __linux__
|
||||||
return set
|
return set
|
||||||
? arm32_hwbp_add(dbg, bp, b)
|
? arm32_hwbp_add(dbg, bp, b)
|
||||||
|
|
@ -1602,7 +1607,11 @@ RzDebugPlugin rz_debug_plugin_native = {
|
||||||
#elif __aarch64__ || __arm64__
|
#elif __aarch64__ || __arm64__
|
||||||
.bits = RZ_SYS_BITS_16 | RZ_SYS_BITS_32 | RZ_SYS_BITS_64,
|
.bits = RZ_SYS_BITS_16 | RZ_SYS_BITS_32 | RZ_SYS_BITS_64,
|
||||||
.arch = "arm",
|
.arch = "arm",
|
||||||
|
#if __WINDOWS__
|
||||||
|
.canstep = 0,
|
||||||
|
#else
|
||||||
.canstep = 1,
|
.canstep = 1,
|
||||||
|
#endif
|
||||||
#elif __arm__
|
#elif __arm__
|
||||||
.bits = RZ_SYS_BITS_16 | RZ_SYS_BITS_32 | RZ_SYS_BITS_64,
|
.bits = RZ_SYS_BITS_16 | RZ_SYS_BITS_32 | RZ_SYS_BITS_64,
|
||||||
.arch = "arm",
|
.arch = "arm",
|
||||||
|
|
@ -1656,7 +1665,9 @@ RzDebugPlugin rz_debug_plugin_native = {
|
||||||
.modules_get = rz_debug_native_modules_get,
|
.modules_get = rz_debug_native_modules_get,
|
||||||
.map_protect = rz_debug_native_map_protect,
|
.map_protect = rz_debug_native_map_protect,
|
||||||
.breakpoint = rz_debug_native_bp,
|
.breakpoint = rz_debug_native_bp,
|
||||||
|
#if __i386__ || __x86_64__
|
||||||
.drx = rz_debug_native_drx,
|
.drx = rz_debug_native_drx,
|
||||||
|
#endif
|
||||||
.gcore = rz_debug_gcore,
|
.gcore = rz_debug_gcore,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ typedef struct { // Keep in sync with io_windbg.c
|
||||||
PDEBUG_ADVANCED3 dbgAdvanced;
|
PDEBUG_ADVANCED3 dbgAdvanced;
|
||||||
} DbgEngContext;
|
} DbgEngContext;
|
||||||
|
|
||||||
static bool __is_target_kernel(DbgEngContext *idbg) {
|
static bool is_target_kernel(DbgEngContext *idbg) {
|
||||||
ULONG Class, Qualifier;
|
ULONG Class, Qualifier;
|
||||||
if (SUCCEEDED(ITHISCALL(dbgCtrl, GetDebuggeeType, &Class, &Qualifier))) {
|
if (SUCCEEDED(ITHISCALL(dbgCtrl, GetDebuggeeType, &Class, &Qualifier))) {
|
||||||
if (Class == DEBUG_CLASS_KERNEL) {
|
if (Class == DEBUG_CLASS_KERNEL) {
|
||||||
|
|
@ -81,7 +81,7 @@ static int windbg_select(RzDebug *dbg, int pid, int tid) {
|
||||||
rz_return_val_if_fail(idbg && idbg->initialized, 0);
|
rz_return_val_if_fail(idbg && idbg->initialized, 0);
|
||||||
ULONG process_id = pid;
|
ULONG process_id = pid;
|
||||||
ULONG thread_id = tid;
|
ULONG thread_id = tid;
|
||||||
if (!__is_target_kernel(idbg)) {
|
if (!is_target_kernel(idbg)) {
|
||||||
ITHISCALL(dbgSysObj, GetProcessIdBySystemId, pid, &process_id);
|
ITHISCALL(dbgSysObj, GetProcessIdBySystemId, pid, &process_id);
|
||||||
ITHISCALL(dbgSysObj, GetThreadIdBySystemId, tid, &thread_id);
|
ITHISCALL(dbgSysObj, GetThreadIdBySystemId, tid, &thread_id);
|
||||||
}
|
}
|
||||||
|
|
@ -136,10 +136,10 @@ static int windbg_stop(RzDebug *dbg) {
|
||||||
|
|
||||||
static bool do_break = false;
|
static bool do_break = false;
|
||||||
|
|
||||||
static void __break(void *user) {
|
static void break_debugger(void *user) {
|
||||||
RzDebug *dbg = (RzDebug *)user;
|
RzDebug *dbg = (RzDebug *)user;
|
||||||
DbgEngContext *idbg = dbg->plugin_data;
|
DbgEngContext *idbg = dbg->plugin_data;
|
||||||
if (__is_target_kernel(idbg)) {
|
if (is_target_kernel(idbg)) {
|
||||||
windbg_stop(dbg);
|
windbg_stop(dbg);
|
||||||
}
|
}
|
||||||
do_break = true;
|
do_break = true;
|
||||||
|
|
@ -149,8 +149,8 @@ static int windbg_wait(RzDebug *dbg, int pid) {
|
||||||
DbgEngContext *idbg = dbg->plugin_data;
|
DbgEngContext *idbg = dbg->plugin_data;
|
||||||
rz_return_val_if_fail(idbg && idbg->initialized, 0);
|
rz_return_val_if_fail(idbg && idbg->initialized, 0);
|
||||||
ULONG Type, ProcessId, ThreadId;
|
ULONG Type, ProcessId, ThreadId;
|
||||||
rz_cons_break_push(__break, dbg);
|
rz_cons_break_push(break_debugger, dbg);
|
||||||
const ULONG timeout = __is_target_kernel(idbg) ? INFINITE : TIMEOUT;
|
const ULONG timeout = is_target_kernel(idbg) ? INFINITE : TIMEOUT;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
while ((hr = ITHISCALL(dbgCtrl, WaitForEvent, DEBUG_WAIT_DEFAULT, timeout)) == S_FALSE) {
|
while ((hr = ITHISCALL(dbgCtrl, WaitForEvent, DEBUG_WAIT_DEFAULT, timeout)) == S_FALSE) {
|
||||||
if (do_break) {
|
if (do_break) {
|
||||||
|
|
@ -165,7 +165,7 @@ static int windbg_wait(RzDebug *dbg, int pid) {
|
||||||
return RZ_DEBUG_REASON_DEAD;
|
return RZ_DEBUG_REASON_DEAD;
|
||||||
}
|
}
|
||||||
ITHISCALL(dbgCtrl, GetLastEventInformation, &Type, &ProcessId, &ThreadId, NULL, 0, NULL, NULL, 0, NULL);
|
ITHISCALL(dbgCtrl, GetLastEventInformation, &Type, &ProcessId, &ThreadId, NULL, 0, NULL, NULL, 0, NULL);
|
||||||
if (!__is_target_kernel(idbg)) {
|
if (!is_target_kernel(idbg)) {
|
||||||
ITHISCALL(dbgSysObj, GetCurrentProcessSystemId, (PULONG)&dbg->pid);
|
ITHISCALL(dbgSysObj, GetCurrentProcessSystemId, (PULONG)&dbg->pid);
|
||||||
ITHISCALL(dbgSysObj, GetCurrentThreadSystemId, (PULONG)&dbg->tid);
|
ITHISCALL(dbgSysObj, GetCurrentThreadSystemId, (PULONG)&dbg->tid);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,9 @@
|
||||||
|
|
||||||
#include <rz_analysis.h>
|
#include <rz_analysis.h>
|
||||||
|
|
||||||
|
#if __WINDOWS__
|
||||||
|
#include "bt/windows-all.c"
|
||||||
|
#endif
|
||||||
#include "bt/generic-x86.c"
|
#include "bt/generic-x86.c"
|
||||||
#include "bt/generic-x64.c"
|
#include "bt/generic-x64.c"
|
||||||
#include "bt/fuzzy-all.c"
|
#include "bt/fuzzy-all.c"
|
||||||
|
|
@ -46,19 +49,28 @@ static RzList *rz_debug_native_frames(RzDebug *dbg, ut64 at) {
|
||||||
if (!strcmp(dbg->btalgo, "fuzzy")) {
|
if (!strcmp(dbg->btalgo, "fuzzy")) {
|
||||||
cb = backtrace_fuzzy;
|
cb = backtrace_fuzzy;
|
||||||
} else if (!strcmp(dbg->btalgo, "analysis")) {
|
} else if (!strcmp(dbg->btalgo, "analysis")) {
|
||||||
if (dbg->bits == RZ_SYS_BITS_64) {
|
if (!strcmp(dbg->arch, "x86")) {
|
||||||
cb = backtrace_x86_64_analysis;
|
if (dbg->bits == RZ_SYS_BITS_64) {
|
||||||
|
cb = backtrace_x86_64_analysis;
|
||||||
|
} else {
|
||||||
|
cb = backtrace_x86_32_analysis;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
cb = backtrace_x86_32_analysis;
|
eprintf("Analysis backtrace not available for current architecture (%s)\n", dbg->arch);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!cb) {
|
if (!cb) {
|
||||||
|
#if __WINDOWS__
|
||||||
|
cb = backtrace_windows;
|
||||||
|
#else
|
||||||
if (dbg->bits == RZ_SYS_BITS_64) {
|
if (dbg->bits == RZ_SYS_BITS_64) {
|
||||||
cb = backtrace_x86_64;
|
cb = backtrace_x86_64;
|
||||||
} else {
|
} else {
|
||||||
cb = backtrace_x86_32;
|
cb = backtrace_x86_32;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
RzList *list;
|
RzList *list;
|
||||||
|
|
|
||||||
120
librz/debug/p/native/bt/windows-all.c
Normal file
120
librz/debug/p/native/bt/windows-all.c
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
// SPDX-FileCopyrightText: 2021 GustavoLCR <gugulcr@gmail.com>
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-only
|
||||||
|
|
||||||
|
#include <DbgHelp.h>
|
||||||
|
#include <w32dbg_wrap.h>
|
||||||
|
|
||||||
|
#define DEF_PROC(proc) proc##_t *w32_##proc
|
||||||
|
#define GET_PROC(proc) \
|
||||||
|
w32_##proc = (proc##_t *)GetProcAddress(dbghelp, #proc); \
|
||||||
|
if (!w32_##proc) { \
|
||||||
|
return false; \
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef BOOL __stdcall SymInitialize_t(
|
||||||
|
_In_ HANDLE hProcess,
|
||||||
|
_In_opt_ PCSTR UserSearchPath,
|
||||||
|
_In_ BOOL fInvadeProcess);
|
||||||
|
|
||||||
|
typedef BOOL __stdcall SymCleanup_t(
|
||||||
|
_In_ HANDLE hProcess);
|
||||||
|
|
||||||
|
typedef PVOID __stdcall SymFunctionTableAccess64_t(
|
||||||
|
_In_ HANDLE hProcess,
|
||||||
|
_In_ DWORD64 AddrBase);
|
||||||
|
|
||||||
|
typedef DWORD64 __stdcall SymGetModuleBase64_t(
|
||||||
|
_In_ HANDLE hProcess,
|
||||||
|
_In_ DWORD64 qwAddr);
|
||||||
|
|
||||||
|
typedef BOOL __stdcall StackWalk64_t(
|
||||||
|
_In_ DWORD MachineType,
|
||||||
|
_In_ HANDLE hProcess,
|
||||||
|
_In_ HANDLE hThread,
|
||||||
|
_Inout_ LPSTACKFRAME64 StackFrame,
|
||||||
|
_Inout_ PVOID ContextRecord,
|
||||||
|
_In_opt_ PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
|
||||||
|
_In_opt_ PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
|
||||||
|
_In_opt_ PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
|
||||||
|
_In_opt_ PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
|
||||||
|
|
||||||
|
DEF_PROC(SymInitialize);
|
||||||
|
DEF_PROC(SymCleanup);
|
||||||
|
DEF_PROC(SymFunctionTableAccess64);
|
||||||
|
DEF_PROC(SymGetModuleBase64);
|
||||||
|
DEF_PROC(StackWalk64);
|
||||||
|
|
||||||
|
static inline bool initialize_sym_api(void) {
|
||||||
|
static bool initialized = false;
|
||||||
|
if (initialized) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
HMODULE dbghelp = LoadLibrary(TEXT("DbgHelp"));
|
||||||
|
if (!dbghelp) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
GET_PROC(SymInitialize);
|
||||||
|
GET_PROC(SymCleanup);
|
||||||
|
GET_PROC(SymFunctionTableAccess64);
|
||||||
|
GET_PROC(SymGetModuleBase64);
|
||||||
|
GET_PROC(StackWalk64);
|
||||||
|
initialized = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static RzList *backtrace_windows(RzDebug *dbg, ut64 at) {
|
||||||
|
initialize_sym_api();
|
||||||
|
static RzThreadLock *lock = NULL;
|
||||||
|
if (!lock) {
|
||||||
|
lock = rz_th_lock_new(false);
|
||||||
|
if (!lock) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
W32DbgWInst *wrap = dbg->plugin_data;
|
||||||
|
#if __arm64__
|
||||||
|
DWORD machine_type = IMAGE_FILE_MACHINE_ARM64;
|
||||||
|
#elif __arm__
|
||||||
|
DWORD machine_type = IMAGE_FILE_MACHINE_ARMNT;
|
||||||
|
#elif __x86_64__
|
||||||
|
DWORD machine_type = IMAGE_FILE_MACHINE_AMD64;
|
||||||
|
#else
|
||||||
|
DWORD machine_type = IMAGE_FILE_MACHINE_I386;
|
||||||
|
#endif
|
||||||
|
STACKFRAME64 stack = { 0 };
|
||||||
|
stack.AddrFrame.Mode = AddrModeFlat;
|
||||||
|
stack.AddrFrame.Offset = rz_reg_getv(dbg->reg, rz_reg_get_name(dbg->reg, RZ_REG_NAME_BP));
|
||||||
|
stack.AddrStack.Mode = AddrModeFlat;
|
||||||
|
stack.AddrStack.Offset = rz_reg_getv(dbg->reg, rz_reg_get_name(dbg->reg, RZ_REG_NAME_SP));
|
||||||
|
stack.AddrPC.Mode = AddrModeFlat;
|
||||||
|
stack.AddrPC.Offset = rz_reg_getv(dbg->reg, rz_reg_get_name(dbg->reg, RZ_REG_NAME_PC));
|
||||||
|
|
||||||
|
RzList *list = rz_list_newf(free);
|
||||||
|
if (!list) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
CONTEXT *ctx = (CONTEXT *)rz_reg_arena_peek(dbg->reg);
|
||||||
|
rz_th_lock_enter(lock);
|
||||||
|
w32_SymInitialize(wrap->pi.hProcess, NULL, TRUE);
|
||||||
|
while (w32_StackWalk64(machine_type, wrap->pi.hProcess, wrap->pi.hThread, &stack, ctx, NULL, w32_SymFunctionTableAccess64, w32_SymGetModuleBase64, NULL)) {
|
||||||
|
RzDebugFrame *frame = RZ_NEW0(RzDebugFrame);
|
||||||
|
if (!frame) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
frame->addr = stack.AddrPC.Offset;
|
||||||
|
frame->bp = stack.AddrFrame.Offset;
|
||||||
|
frame->sp = stack.AddrStack.Offset;
|
||||||
|
frame->size = frame->bp - frame->sp;
|
||||||
|
if (!rz_list_append(list, frame)) {
|
||||||
|
free(frame);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w32_SymCleanup(wrap->pi.hProcess);
|
||||||
|
rz_th_lock_leave(lock);
|
||||||
|
free(ctx);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef DEF_PROC
|
||||||
|
#undef GET_PROC
|
||||||
|
|
@ -6,6 +6,7 @@ return strdup(
|
||||||
"=PC pc\n"
|
"=PC pc\n"
|
||||||
"=BP x29\n"
|
"=BP x29\n"
|
||||||
"=SP sp\n"
|
"=SP sp\n"
|
||||||
|
"=LR x30\n"
|
||||||
"=SN x8\n"
|
"=SN x8\n"
|
||||||
"=A0 x0\n"
|
"=A0 x0\n"
|
||||||
"=A1 x1\n"
|
"=A1 x1\n"
|
||||||
|
|
|
||||||
|
|
@ -6,17 +6,21 @@
|
||||||
|
|
||||||
static char *rz_debug_native_reg_profile(RzDebug *dbg) {
|
static char *rz_debug_native_reg_profile(RzDebug *dbg) {
|
||||||
#if __WINDOWS__
|
#if __WINDOWS__
|
||||||
/*_______
|
/*_______
|
||||||
| | |
|
| | |
|
||||||
|___|___|
|
|___|___|
|
||||||
| | |
|
| | |
|
||||||
|___|___|
|
|___|___|
|
||||||
*/
|
*/
|
||||||
if (dbg->bits & RZ_SYS_BITS_64) {
|
#if defined(__arm64__)
|
||||||
|
#include "reg/windows-arm64.h"
|
||||||
|
#elif defined(__arm__)
|
||||||
|
#include "reg/windows-arm.h"
|
||||||
|
#elif defined(__x86_64__)
|
||||||
#include "reg/windows-x64.h"
|
#include "reg/windows-x64.h"
|
||||||
} else {
|
#elif defined(__i386__)
|
||||||
#include "reg/windows-x86.h"
|
#include "reg/windows-x86.h"
|
||||||
}
|
#endif
|
||||||
#elif (__OpenBSD__ || __NetBSD__)
|
#elif (__OpenBSD__ || __NetBSD__)
|
||||||
/* __.--..__
|
/* __.--..__
|
||||||
\-/-/-/ _ __ _.--' _.--'
|
\-/-/-/ _ __ _.--' _.--'
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ return strdup(
|
||||||
"=PC pc\n"
|
"=PC pc\n"
|
||||||
"=SP sp\n"
|
"=SP sp\n"
|
||||||
"=BP fp\n"
|
"=BP fp\n"
|
||||||
|
"=LR lr\n"
|
||||||
"=A0 r0\n"
|
"=A0 r0\n"
|
||||||
"=A1 r1\n"
|
"=A1 r1\n"
|
||||||
"=A2 r2\n"
|
"=A2 r2\n"
|
||||||
|
|
@ -25,7 +26,7 @@ return strdup(
|
||||||
"gpr r9 .32 40 0\n"
|
"gpr r9 .32 40 0\n"
|
||||||
"gpr r10 .32 44 0\n"
|
"gpr r10 .32 44 0\n"
|
||||||
"gpr r11 .32 48 0\n"
|
"gpr r11 .32 48 0\n"
|
||||||
"gpr r12 .32 52 0\n"
|
"gpr ip .32 52 0\n"
|
||||||
"gpr sp .32 56 0\n"
|
"gpr sp .32 56 0\n"
|
||||||
"gpr lr .32 60 0\n"
|
"gpr lr .32 60 0\n"
|
||||||
"gpr pc .32 64 0\n"
|
"gpr pc .32 64 0\n"
|
||||||
|
|
@ -34,40 +35,44 @@ return strdup(
|
||||||
"flg cf .1 68.29 0 carry\n"
|
"flg cf .1 68.29 0 carry\n"
|
||||||
"flg zf .1 68.30 0 zero\n"
|
"flg zf .1 68.30 0 zero\n"
|
||||||
"flg nf .1 68.31 0 sign\n"
|
"flg nf .1 68.31 0 sign\n"
|
||||||
"gpr fpsr .32 72 0\n"
|
"flg fpscr .32 72 0\n"
|
||||||
"fpu q0 .128 76 0\n"
|
"flg fvf .1 72.28 0 overflow\n"
|
||||||
"fpu q1 .128 92 0\n"
|
"flg fcf .1 72.29 0 carry\n"
|
||||||
"fpu q2 .128 108 0\n"
|
"flg fzf .1 72.30 0 zero\n"
|
||||||
"fpu q3 .128 124 0\n"
|
"flg fnf .1 72.31 0 sign\n"
|
||||||
"fpu q4 .128 140 0\n"
|
"fpu q0 .128 80 0\n"
|
||||||
"fpu q5 .128 156 0\n"
|
"fpu q1 .128 96 0\n"
|
||||||
"fpu q6 .128 172 0\n"
|
"fpu q2 .128 112 0\n"
|
||||||
"fpu q7 .128 188 0\n"
|
"fpu q3 .128 128 0\n"
|
||||||
"fpu q8 .128 204 0\n"
|
"fpu q4 .128 144 0\n"
|
||||||
"fpu q9 .128 220 0\n"
|
"fpu q5 .128 160 0\n"
|
||||||
"fpu q10 .128 236 0\n"
|
"fpu q6 .128 176 0\n"
|
||||||
"fpu q11 .128 252 0\n"
|
"fpu q7 .128 192 0\n"
|
||||||
"fpu q12 .128 268 0\n"
|
"fpu q8 .128 208 0\n"
|
||||||
"fpu q13 .128 284 0\n"
|
"fpu q9 .128 224 0\n"
|
||||||
"fpu q14 .128 300 0\n"
|
"fpu q10 .128 240 0\n"
|
||||||
"fpu q15 .128 316 0\n"
|
"fpu q11 .128 256 0\n"
|
||||||
"drx bcr0 .32 332 0\n"
|
"fpu q12 .128 272 0\n"
|
||||||
"drx bcr1 .32 336 0\n"
|
"fpu q13 .128 288 0\n"
|
||||||
"drx bcr2 .32 340 0\n"
|
"fpu q14 .128 304 0\n"
|
||||||
"drx bcr3 .32 344 0\n"
|
"fpu q15 .128 320 0\n"
|
||||||
"drx bcr4 .32 348 0\n"
|
"drx bcr0 .32 336 0\n"
|
||||||
"drx bcr5 .32 352 0\n"
|
"drx bcr1 .32 340 0\n"
|
||||||
"drx bcr6 .32 356 0\n"
|
"drx bcr2 .32 344 0\n"
|
||||||
"drx bcr7 .32 360 0\n"
|
"drx bcr3 .32 348 0\n"
|
||||||
"drx bvr0 .32 364 0\n"
|
"drx bcr4 .32 352 0\n"
|
||||||
"drx bvr1 .32 368 0\n"
|
"drx bcr5 .32 356 0\n"
|
||||||
"drx bvr2 .32 372 0\n"
|
"drx bcr6 .32 360 0\n"
|
||||||
"drx bvr3 .32 376 0\n"
|
"drx bcr7 .32 364 0\n"
|
||||||
"drx bvr4 .32 380 0\n"
|
"drx bvr0 .32 368 0\n"
|
||||||
"drx bvr5 .32 384 0\n"
|
"drx bvr1 .32 372 0\n"
|
||||||
"drx bvr6 .32 388 0\n"
|
"drx bvr2 .32 376 0\n"
|
||||||
"drx bvr7 .32 392 0\n"
|
"drx bvr3 .32 380 0\n"
|
||||||
"drx wcr0 .32 396 0\n"
|
"drx bvr4 .32 384 0\n"
|
||||||
"drx wcr1 .32 400 0\n"
|
"drx bvr5 .32 388 0\n"
|
||||||
"drx wvr0 .32 404 0\n"
|
"drx bvr6 .32 392 0\n"
|
||||||
"drx wvr1 .32 408 0\n");
|
"drx bvr7 .32 396 0\n"
|
||||||
|
"drx wcr0 .32 400 0\n"
|
||||||
|
"drx wcr1 .32 404 0\n"
|
||||||
|
"drx wvr0 .32 408 0\n"
|
||||||
|
"drx wvr1 .32 412 0\n");
|
||||||
|
|
|
||||||
|
|
@ -1,108 +1,233 @@
|
||||||
// SPDX-FileCopyrightText: 2020 GustavoLCR <gugulcr@gmail.com>
|
// SPDX-FileCopyrightText: 2020 GustavoLCR <gugulcr@gmail.com>
|
||||||
// SPDX-License-Identifier: LGPL-3.0-only
|
// SPDX-License-Identifier: LGPL-3.0-only
|
||||||
|
|
||||||
return strdup(
|
if (dbg->bits == RZ_SYS_BITS_64) {
|
||||||
"=PC pc\n"
|
return strdup(
|
||||||
"=SP sp\n"
|
"=PC pc\n"
|
||||||
"=BP fp\n"
|
"=SP sp\n"
|
||||||
"=A0 x0\n"
|
"=BP fp\n"
|
||||||
"=A1 x1\n"
|
"=LR lr\n"
|
||||||
"=A2 x2\n"
|
"=A0 x0\n"
|
||||||
"=A3 x3\n"
|
"=A1 x1\n"
|
||||||
"=ZF zf\n"
|
"=A2 x2\n"
|
||||||
"=SF nf\n"
|
"=A3 x3\n"
|
||||||
"=OF vf\n"
|
"=ZF zf\n"
|
||||||
"=CF cf\n"
|
"=SF nf\n"
|
||||||
"=SN x16\n"
|
"=OF vf\n"
|
||||||
"flg cpsr .32 4 0 _____tfiae_____________j__qvczn\n"
|
"=CF cf\n"
|
||||||
"flg vf .1 4.28 0 overflow\n"
|
"=SN x16\n"
|
||||||
"flg cf .1 4.29 0 carry\n"
|
"flg cpsr .32 4 0 _____tfiae_____________j__qvczn\n"
|
||||||
"flg zf .1 4.30 0 zero\n"
|
"flg vf .1 4.28 0 overflow\n"
|
||||||
"flg nf .1 4.31 0 sign\n"
|
"flg cf .1 4.29 0 carry\n"
|
||||||
"gpr x0 .64 8 0\n"
|
"flg zf .1 4.30 0 zero\n"
|
||||||
"gpr x1 .64 16 0\n"
|
"flg nf .1 4.31 0 sign\n"
|
||||||
"gpr x2 .64 24 0\n"
|
"gpr x0 .64 8 0\n"
|
||||||
"gpr x3 .64 32 0\n"
|
"gpr x1 .64 16 0\n"
|
||||||
"gpr x4 .64 40 0\n"
|
"gpr x2 .64 24 0\n"
|
||||||
"gpr x5 .64 48 0\n"
|
"gpr x3 .64 32 0\n"
|
||||||
"gpr x6 .64 56 0\n"
|
"gpr x4 .64 40 0\n"
|
||||||
"gpr x7 .64 64 0\n"
|
"gpr x5 .64 48 0\n"
|
||||||
"gpr x8 .64 72 0\n"
|
"gpr x6 .64 56 0\n"
|
||||||
"gpr x9 .64 80 0\n"
|
"gpr x7 .64 64 0\n"
|
||||||
"gpr x10 .64 88 0\n"
|
"gpr x8 .64 72 0\n"
|
||||||
"gpr x11 .64 96 0\n"
|
"gpr x9 .64 80 0\n"
|
||||||
"gpr x12 .64 104 0\n"
|
"gpr x10 .64 88 0\n"
|
||||||
"gpr x13 .64 112 0\n"
|
"gpr x11 .64 96 0\n"
|
||||||
"gpr x14 .64 120 0\n"
|
"gpr x12 .64 104 0\n"
|
||||||
"gpr x15 .64 128 0\n"
|
"gpr x13 .64 112 0\n"
|
||||||
"gpr x16 .64 136 0\n"
|
"gpr x14 .64 120 0\n"
|
||||||
"gpr x17 .64 144 0\n"
|
"gpr x15 .64 128 0\n"
|
||||||
"gpr x18 .64 152 0\n"
|
"gpr x16 .64 136 0\n"
|
||||||
"gpr x19 .64 160 0\n"
|
"gpr x17 .64 144 0\n"
|
||||||
"gpr x20 .64 168 0\n"
|
"gpr x18 .64 152 0\n"
|
||||||
"gpr x21 .64 176 0\n"
|
"gpr x19 .64 160 0\n"
|
||||||
"gpr x22 .64 184 0\n"
|
"gpr x20 .64 168 0\n"
|
||||||
"gpr x23 .64 192 0\n"
|
"gpr x21 .64 176 0\n"
|
||||||
"gpr x24 .64 200 0\n"
|
"gpr x22 .64 184 0\n"
|
||||||
"gpr x25 .64 208 0\n"
|
"gpr x23 .64 192 0\n"
|
||||||
"gpr x26 .64 216 0\n"
|
"gpr x24 .64 200 0\n"
|
||||||
"gpr x27 .64 224 0\n"
|
"gpr x25 .64 208 0\n"
|
||||||
"gpr x28 .64 232 0\n"
|
"gpr x26 .64 216 0\n"
|
||||||
"gpr fp .64 240 0\n"
|
"gpr x27 .64 224 0\n"
|
||||||
"gpr lr .64 248 0\n"
|
"gpr x28 .64 232 0\n"
|
||||||
"gpr sp .64 256 0\n"
|
"gpr w0 .32 8 0\n"
|
||||||
"gpr pc .64 264 0\n"
|
"gpr w1 .32 16 0\n"
|
||||||
"fpu v0 .128 272 0\n"
|
"gpr w2 .32 24 0\n"
|
||||||
"fpu v1 .128 288 0\n"
|
"gpr w3 .32 32 0\n"
|
||||||
"fpu v2 .128 304 0\n"
|
"gpr w4 .32 40 0\n"
|
||||||
"fpu v3 .128 320 0\n"
|
"gpr w5 .32 48 0\n"
|
||||||
"fpu v4 .128 336 0\n"
|
"gpr w6 .32 56 0\n"
|
||||||
"fpu v5 .128 352 0\n"
|
"gpr w7 .32 64 0\n"
|
||||||
"fpu v6 .128 368 0\n"
|
"gpr w8 .32 72 0\n"
|
||||||
"fpu v7 .128 384 0\n"
|
"gpr w9 .32 80 0\n"
|
||||||
"fpu v8 .128 400 0\n"
|
"gpr w10 .32 88 0\n"
|
||||||
"fpu v9 .128 416 0\n"
|
"gpr w11 .32 96 0\n"
|
||||||
"fpu v10 .128 432 0\n"
|
"gpr w12 .32 104 0\n"
|
||||||
"fpu v11 .128 448 0\n"
|
"gpr w13 .32 112 0\n"
|
||||||
"fpu v12 .128 464 0\n"
|
"gpr w14 .32 120 0\n"
|
||||||
"fpu v13 .128 480 0\n"
|
"gpr w15 .32 128 0\n"
|
||||||
"fpu v14 .128 496 0\n"
|
"gpr w16 .32 136 0\n"
|
||||||
"fpu v15 .128 512 0\n"
|
"gpr w17 .32 144 0\n"
|
||||||
"fpu v16 .128 528 0\n"
|
"gpr w18 .32 152 0\n"
|
||||||
"fpu v17 .128 544 0\n"
|
"gpr w19 .32 160 0\n"
|
||||||
"fpu v18 .128 560 0\n"
|
"gpr w20 .32 168 0\n"
|
||||||
"fpu v19 .128 576 0\n"
|
"gpr w21 .32 176 0\n"
|
||||||
"fpu v20 .128 592 0\n"
|
"gpr w22 .32 184 0\n"
|
||||||
"fpu v21 .128 608 0\n"
|
"gpr w23 .32 192 0\n"
|
||||||
"fpu v22 .128 624 0\n"
|
"gpr w24 .32 200 0\n"
|
||||||
"fpu v23 .128 640 0\n"
|
"gpr w25 .32 208 0\n"
|
||||||
"fpu v24 .128 656 0\n"
|
"gpr w26 .32 216 0\n"
|
||||||
"fpu v25 .128 672 0\n"
|
"gpr w27 .32 224 0\n"
|
||||||
"fpu v26 .128 688 0\n"
|
"gpr w28 .32 232 0\n"
|
||||||
"fpu v27 .128 704 0\n"
|
"gpr fp .64 240 0\n"
|
||||||
"fpu v28 .128 720 0\n"
|
"gpr lr .64 248 0\n"
|
||||||
"fpu v29 .128 736 0\n"
|
"gpr sp .64 256 0\n"
|
||||||
"fpu v30 .128 752 0\n"
|
"gpr pc .64 264 0\n"
|
||||||
"fpu v31 .128 768 0\n"
|
"fpu v0 .128 272 0\n"
|
||||||
"gpr fpcr .32 784 0\n"
|
"fpu v1 .128 288 0\n"
|
||||||
"gpr fpsr .32 788 0\n"
|
"fpu v2 .128 304 0\n"
|
||||||
"drx bcr0 .32 792 0\n"
|
"fpu v3 .128 320 0\n"
|
||||||
"drx bcr1 .32 796 0\n"
|
"fpu v4 .128 336 0\n"
|
||||||
"drx bcr2 .32 800 0\n"
|
"fpu v5 .128 352 0\n"
|
||||||
"drx bcr3 .32 804 0\n"
|
"fpu v6 .128 368 0\n"
|
||||||
"drx bcr4 .32 808 0\n"
|
"fpu v7 .128 384 0\n"
|
||||||
"drx bcr5 .32 812 0\n"
|
"fpu v8 .128 400 0\n"
|
||||||
"drx bcr6 .32 816 0\n"
|
"fpu v9 .128 416 0\n"
|
||||||
"drx bcr7 .32 820 0\n"
|
"fpu v10 .128 432 0\n"
|
||||||
"drx bvr0 .64 824 0\n"
|
"fpu v11 .128 448 0\n"
|
||||||
"drx bvr1 .64 832 0\n"
|
"fpu v12 .128 464 0\n"
|
||||||
"drx bvr2 .64 840 0\n"
|
"fpu v13 .128 480 0\n"
|
||||||
"drx bvr3 .64 848 0\n"
|
"fpu v14 .128 496 0\n"
|
||||||
"drx bvr4 .64 856 0\n"
|
"fpu v15 .128 512 0\n"
|
||||||
"drx bvr5 .64 864 0\n"
|
"fpu v16 .128 528 0\n"
|
||||||
"drx bvr6 .64 872 0\n"
|
"fpu v17 .128 544 0\n"
|
||||||
"drx bvr7 .64 880 0\n"
|
"fpu v18 .128 560 0\n"
|
||||||
"drx wcr0 .32 888 0\n"
|
"fpu v19 .128 576 0\n"
|
||||||
"drx wcr1 .32 892 0\n"
|
"fpu v20 .128 592 0\n"
|
||||||
"drx wvr0 .64 896 0\n"
|
"fpu v21 .128 608 0\n"
|
||||||
"drx wvr1 .64 904 0\n");
|
"fpu v22 .128 624 0\n"
|
||||||
|
"fpu v23 .128 640 0\n"
|
||||||
|
"fpu v24 .128 656 0\n"
|
||||||
|
"fpu v25 .128 672 0\n"
|
||||||
|
"fpu v26 .128 688 0\n"
|
||||||
|
"fpu v27 .128 704 0\n"
|
||||||
|
"fpu v28 .128 720 0\n"
|
||||||
|
"fpu v29 .128 736 0\n"
|
||||||
|
"fpu v30 .128 752 0\n"
|
||||||
|
"fpu v31 .128 768 0\n"
|
||||||
|
"flg fpcr .32 784 0\n"
|
||||||
|
"flg fpsr .32 788 0\n"
|
||||||
|
"flg fvf .1 788.28 0 overflow\n"
|
||||||
|
"flg fcf .1 788.29 0 carry\n"
|
||||||
|
"flg fzf .1 788.30 0 zero\n"
|
||||||
|
"flg fnf .1 788.31 0 sign\n"
|
||||||
|
"drx bcr0 .32 792 0\n"
|
||||||
|
"drx bcr1 .32 796 0\n"
|
||||||
|
"drx bcr2 .32 800 0\n"
|
||||||
|
"drx bcr3 .32 804 0\n"
|
||||||
|
"drx bcr4 .32 808 0\n"
|
||||||
|
"drx bcr5 .32 812 0\n"
|
||||||
|
"drx bcr6 .32 816 0\n"
|
||||||
|
"drx bcr7 .32 820 0\n"
|
||||||
|
"drx bvr0 .64 824 0\n"
|
||||||
|
"drx bvr1 .64 832 0\n"
|
||||||
|
"drx bvr2 .64 840 0\n"
|
||||||
|
"drx bvr3 .64 848 0\n"
|
||||||
|
"drx bvr4 .64 856 0\n"
|
||||||
|
"drx bvr5 .64 864 0\n"
|
||||||
|
"drx bvr6 .64 872 0\n"
|
||||||
|
"drx bvr7 .64 880 0\n"
|
||||||
|
"drx wcr0 .32 888 0\n"
|
||||||
|
"drx wcr1 .32 892 0\n"
|
||||||
|
"drx wvr0 .64 896 0\n"
|
||||||
|
"drx wvr1 .64 904 0\n");
|
||||||
|
} else {
|
||||||
|
return strdup(
|
||||||
|
"=PC pc\n"
|
||||||
|
"=SP sp\n"
|
||||||
|
"=BP fp\n"
|
||||||
|
"=LR lr\n"
|
||||||
|
"=A0 r0\n"
|
||||||
|
"=A1 r1\n"
|
||||||
|
"=A2 r2\n"
|
||||||
|
"=A3 r3\n"
|
||||||
|
"=ZF zf\n"
|
||||||
|
"=SF nf\n"
|
||||||
|
"=OF vf\n"
|
||||||
|
"=CF cf\n"
|
||||||
|
"flg cpsr .32 4 0 _____tfiae_____________j__qvczn\n"
|
||||||
|
"flg vf .1 4.28 0 overflow\n"
|
||||||
|
"flg cf .1 4.29 0 carry\n"
|
||||||
|
"flg zf .1 4.30 0 zero\n"
|
||||||
|
"flg nf .1 4.31 0 sign\n"
|
||||||
|
"gpr r0 .32 8 0\n"
|
||||||
|
"gpr r1 .32 16 0\n"
|
||||||
|
"gpr r2 .32 24 0\n"
|
||||||
|
"gpr r3 .32 32 0\n"
|
||||||
|
"gpr r4 .32 40 0\n"
|
||||||
|
"gpr r5 .32 48 0\n"
|
||||||
|
"gpr r6 .32 56 0\n"
|
||||||
|
"gpr r7 .32 64 0\n"
|
||||||
|
"gpr r8 .32 72 0\n"
|
||||||
|
"gpr r9 .32 80 0\n"
|
||||||
|
"gpr r10 .32 88 0\n"
|
||||||
|
"gpr fp .32 96 0\n"
|
||||||
|
"gpr ip .32 104 0\n"
|
||||||
|
"gpr sp .32 112 0\n"
|
||||||
|
"gpr lr .32 120 0\n"
|
||||||
|
"gpr pc .64 264 0\n"
|
||||||
|
"fpu v0 .128 272 0\n"
|
||||||
|
"fpu v1 .128 288 0\n"
|
||||||
|
"fpu v2 .128 304 0\n"
|
||||||
|
"fpu v3 .128 320 0\n"
|
||||||
|
"fpu v4 .128 336 0\n"
|
||||||
|
"fpu v5 .128 352 0\n"
|
||||||
|
"fpu v6 .128 368 0\n"
|
||||||
|
"fpu v7 .128 384 0\n"
|
||||||
|
"fpu v8 .128 400 0\n"
|
||||||
|
"fpu v9 .128 416 0\n"
|
||||||
|
"fpu v10 .128 432 0\n"
|
||||||
|
"fpu v11 .128 448 0\n"
|
||||||
|
"fpu v12 .128 464 0\n"
|
||||||
|
"fpu v13 .128 480 0\n"
|
||||||
|
"fpu v14 .128 496 0\n"
|
||||||
|
"fpu v15 .128 512 0\n"
|
||||||
|
"fpu v16 .128 528 0\n"
|
||||||
|
"fpu v17 .128 544 0\n"
|
||||||
|
"fpu v18 .128 560 0\n"
|
||||||
|
"fpu v19 .128 576 0\n"
|
||||||
|
"fpu v20 .128 592 0\n"
|
||||||
|
"fpu v21 .128 608 0\n"
|
||||||
|
"fpu v22 .128 624 0\n"
|
||||||
|
"fpu v23 .128 640 0\n"
|
||||||
|
"fpu v24 .128 656 0\n"
|
||||||
|
"fpu v25 .128 672 0\n"
|
||||||
|
"fpu v26 .128 688 0\n"
|
||||||
|
"fpu v27 .128 704 0\n"
|
||||||
|
"fpu v28 .128 720 0\n"
|
||||||
|
"fpu v29 .128 736 0\n"
|
||||||
|
"fpu v30 .128 752 0\n"
|
||||||
|
"fpu v31 .128 768 0\n"
|
||||||
|
"gpr fpcr .32 784 0\n"
|
||||||
|
"gpr fpsr .32 788 0\n"
|
||||||
|
"drx bcr0 .32 792 0\n"
|
||||||
|
"drx bcr1 .32 796 0\n"
|
||||||
|
"drx bcr2 .32 800 0\n"
|
||||||
|
"drx bcr3 .32 804 0\n"
|
||||||
|
"drx bcr4 .32 808 0\n"
|
||||||
|
"drx bcr5 .32 812 0\n"
|
||||||
|
"drx bcr6 .32 816 0\n"
|
||||||
|
"drx bcr7 .32 820 0\n"
|
||||||
|
"drx bvr0 .64 824 0\n"
|
||||||
|
"drx bvr1 .64 832 0\n"
|
||||||
|
"drx bvr2 .64 840 0\n"
|
||||||
|
"drx bvr3 .64 848 0\n"
|
||||||
|
"drx bvr4 .64 856 0\n"
|
||||||
|
"drx bvr5 .64 864 0\n"
|
||||||
|
"drx bvr6 .64 872 0\n"
|
||||||
|
"drx bvr7 .64 880 0\n"
|
||||||
|
"drx wcr0 .32 888 0\n"
|
||||||
|
"drx wcr1 .32 892 0\n"
|
||||||
|
"drx wvr0 .64 896 0\n"
|
||||||
|
"drx wvr1 .64 904 0\n");
|
||||||
|
}
|
||||||
|
|
@ -183,38 +183,26 @@ static PTHREAD_ITEM add_thread(RzDebug *dbg, DWORD pid, DWORD tid, HANDLE hThrea
|
||||||
return pthread;
|
return pthread;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int suspend_thread(HANDLE th, int bits) {
|
static inline int suspend_thread(HANDLE th) {
|
||||||
int ret;
|
int ret;
|
||||||
//if (bits == RZ_SYS_BITS_32) {
|
|
||||||
if ((ret = SuspendThread(th)) == -1) {
|
if ((ret = SuspendThread(th)) == -1) {
|
||||||
rz_sys_perror("SuspendThread");
|
rz_sys_perror("SuspendThread");
|
||||||
}
|
}
|
||||||
/*} else {
|
|
||||||
if ((ret = Wow64SuspendThread (th)) == -1) {
|
|
||||||
rz_sys_perror ("Wow64SuspendThread");
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int resume_thread(HANDLE th, int bits) {
|
static int resume_thread(HANDLE th) {
|
||||||
int ret;
|
int ret;
|
||||||
//if (bits == RZ_SYS_BITS_32) {
|
|
||||||
if ((ret = ResumeThread(th)) == -1) {
|
if ((ret = ResumeThread(th)) == -1) {
|
||||||
rz_sys_perror("ResumeThread");
|
rz_sys_perror("ResumeThread");
|
||||||
}
|
}
|
||||||
/*} else {
|
|
||||||
if ((ret = ResumeThread (th)) == -1) {
|
|
||||||
rz_sys_perror ("Wow64ResumeThread");
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void continue_thread(HANDLE th, int bits) {
|
static inline void continue_thread(HANDLE th) {
|
||||||
int ret;
|
int ret;
|
||||||
do {
|
do {
|
||||||
ret = resume_thread(th, bits);
|
ret = resume_thread(th);
|
||||||
} while (ret > 0);
|
} while (ret > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -244,7 +232,7 @@ static bool is_process_alive(HANDLE ph) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_thread_context(HANDLE th, const ut8 *buf, int size, int bits) {
|
static int set_thread_context(HANDLE th, const ut8 *buf, int size) {
|
||||||
bool ret;
|
bool ret;
|
||||||
CONTEXT ctx = { 0 };
|
CONTEXT ctx = { 0 };
|
||||||
size = RZ_MIN(size, sizeof(ctx));
|
size = RZ_MIN(size, sizeof(ctx));
|
||||||
|
|
@ -255,11 +243,11 @@ static int set_thread_context(HANDLE th, const ut8 *buf, int size, int bits) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_thread_context(HANDLE th, ut8 *buf, int size, int bits) {
|
static int get_thread_context(HANDLE th, ut8 *buf, int size, DWORD context_flags) {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
CONTEXT ctx = { 0 };
|
CONTEXT ctx = { 0 };
|
||||||
// TODO: support various types?
|
// TODO: support various types?
|
||||||
ctx.ContextFlags = CONTEXT_ALL;
|
ctx.ContextFlags = context_flags;
|
||||||
if (GetThreadContext(th, &ctx)) {
|
if (GetThreadContext(th, &ctx)) {
|
||||||
if (size > sizeof(ctx)) {
|
if (size > sizeof(ctx)) {
|
||||||
size = sizeof(ctx);
|
size = sizeof(ctx);
|
||||||
|
|
@ -274,6 +262,21 @@ static int get_thread_context(HANDLE th, ut8 *buf, int size, int bits) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if __i386__ || __x86_64__
|
||||||
|
|
||||||
|
int w32_step(RzDebug *dbg) {
|
||||||
|
/* set TRAP flag */
|
||||||
|
CONTEXT ctx;
|
||||||
|
if (!w32_reg_read(dbg, RZ_REG_TYPE_GPR, (ut8 *)&ctx, sizeof(ctx))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ctx.EFlags |= 0x100;
|
||||||
|
if (!w32_reg_write(dbg, RZ_REG_TYPE_GPR, (ut8 *)&ctx, sizeof(ctx))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return w32_continue(dbg, dbg->pid, dbg->tid, dbg->reason.signum);
|
||||||
|
}
|
||||||
|
|
||||||
static int get_avx(HANDLE th, ut128 xmm[16], ut128 ymm[16]) {
|
static int get_avx(HANDLE th, ut128 xmm[16], ut128 ymm[16]) {
|
||||||
int nregs = 0, index = 0;
|
int nregs = 0, index = 0;
|
||||||
DWORD ctxsize = 0;
|
DWORD ctxsize = 0;
|
||||||
|
|
@ -416,6 +419,160 @@ static void print_fpu_context(HANDLE th, CONTEXT *ctx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void transfer_drx(RzDebug *dbg, const ut8 *buf) {
|
||||||
|
CONTEXT cur_ctx;
|
||||||
|
if (w32_reg_read(dbg, RZ_REG_TYPE_ANY, (ut8 *)&cur_ctx, sizeof(CONTEXT))) {
|
||||||
|
CONTEXT *new_ctx = (CONTEXT *)buf;
|
||||||
|
size_t drx_size = offsetof(CONTEXT, Dr7) - offsetof(CONTEXT, Dr0) + sizeof(new_ctx->Dr7);
|
||||||
|
memcpy(&cur_ctx.Dr0, &new_ctx->Dr0, drx_size);
|
||||||
|
*new_ctx = cur_ctx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static void transfer_drx(RzDebug *dbg, const ut8 *buf) {
|
||||||
|
// Do nothing (not supported)
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_fpu_context(HANDLE th, CONTEXT *buf) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
int w32_step(RzDebug *dbg) {
|
||||||
|
// Do nothing (not supported)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void get_arm_hwbp_values(ut64 address, ut32 *control, ut64 *value) {
|
||||||
|
const ut32 type = 0b0100 << 20; // match
|
||||||
|
const ut32 bas = 0xF << 5; // match a64 and a32
|
||||||
|
const ut32 priv = 1 << 2;
|
||||||
|
const ut32 enable = 1;
|
||||||
|
*control = type | bas | priv | enable;
|
||||||
|
*value = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void get_arm64_hwwp_values(ut64 address, int size, int rw, ut32 *control, ut64 *value) {
|
||||||
|
const unsigned int offset = address % 8;
|
||||||
|
const ut32 byte_mask = ((1 << size) - 1) << offset;
|
||||||
|
const ut32 priv = 1 << 2;
|
||||||
|
const ut32 enable = 1;
|
||||||
|
ut32 load_store = 0;
|
||||||
|
switch (rw) {
|
||||||
|
case RZ_BP_PROT_READ:
|
||||||
|
load_store = 1;
|
||||||
|
break;
|
||||||
|
case RZ_BP_PROT_WRITE:
|
||||||
|
load_store = 2;
|
||||||
|
break;
|
||||||
|
case RZ_BP_PROT_ACCESS:
|
||||||
|
load_store = 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*control = byte_mask << 5 | load_store << 3 | priv | enable;
|
||||||
|
*value = address - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool is_watchpoint(RzBreakpointItem *b) {
|
||||||
|
return b->perm & (RZ_BP_PROT_ACCESS | RZ_BP_PROT_READ | RZ_BP_PROT_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool is_breakpoint(RzBreakpointItem *b) {
|
||||||
|
return b->perm & RZ_BP_PROT_EXEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
int w32_hwbp_arm_add(RzDebug *dbg, RzBreakpoint *bp, RzBreakpointItem *b) {
|
||||||
|
rz_return_val_if_fail(dbg && bp && b, 0);
|
||||||
|
W32DbgWInst *wrap = dbg->plugin_data;
|
||||||
|
CONTEXT ctx;
|
||||||
|
const bool alive = is_thread_alive(dbg, wrap->pi.dwThreadId);
|
||||||
|
if (alive && suspend_thread(wrap->pi.hThread) == -1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
get_thread_context(wrap->pi.hThread, (ut8 *)&ctx, sizeof(CONTEXT), CONTEXT_DEBUG_REGISTERS);
|
||||||
|
ut32 control;
|
||||||
|
ut64 value;
|
||||||
|
int i;
|
||||||
|
if (is_watchpoint(b)) {
|
||||||
|
get_arm64_hwwp_values(b->addr, b->size, b->perm, &control, &value);
|
||||||
|
for (i = 0; i < ARM64_MAX_WATCHPOINTS; i++) {
|
||||||
|
if (!ctx.Wvr[i] || ctx.Wvr[i] == value) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i < ARM64_MAX_WATCHPOINTS) {
|
||||||
|
ctx.Wcr[i] = control;
|
||||||
|
ctx.Wvr[i] = value;
|
||||||
|
} else {
|
||||||
|
eprintf("Too many hardware watchpoints\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (is_breakpoint(b)) {
|
||||||
|
get_arm_hwbp_values(b->addr, &control, &value);
|
||||||
|
for (i = 0; i < ARM64_MAX_BREAKPOINTS; i++) {
|
||||||
|
if (!ctx.Bvr[i] || ctx.Bvr[i] == value) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i < ARM64_MAX_BREAKPOINTS) {
|
||||||
|
ctx.Bcr[i] = control;
|
||||||
|
ctx.Bvr[i] = value;
|
||||||
|
} else {
|
||||||
|
eprintf("Too many hardware breakpoints\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set_thread_context(wrap->pi.hThread, (ut8 *)&ctx, sizeof(CONTEXT));
|
||||||
|
if (alive && resume_thread(wrap->pi.hThread) == -1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int w32_hwbp_arm_del(RzDebug *dbg, RzBreakpoint *bp, RzBreakpointItem *b) {
|
||||||
|
W32DbgWInst *wrap = dbg->plugin_data;
|
||||||
|
CONTEXT ctx;
|
||||||
|
const bool alive = is_thread_alive(dbg, wrap->pi.dwThreadId);
|
||||||
|
if (alive && suspend_thread(wrap->pi.hThread) == -1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
get_thread_context(wrap->pi.hThread, (ut8 *)&ctx, sizeof(CONTEXT), CONTEXT_DEBUG_REGISTERS);
|
||||||
|
ut32 control;
|
||||||
|
ut64 value;
|
||||||
|
int i;
|
||||||
|
if (is_watchpoint(b)) {
|
||||||
|
get_arm64_hwwp_values(b->addr, b->size, b->perm, &control, &value);
|
||||||
|
for (i = 0; i < ARM64_MAX_WATCHPOINTS; i++) {
|
||||||
|
if (ctx.Wcr[i] == control && ctx.Wvr[i] == value) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i < ARM64_MAX_WATCHPOINTS) {
|
||||||
|
ctx.Wcr[i] = 0;
|
||||||
|
ctx.Wvr[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (is_breakpoint(b)) {
|
||||||
|
get_arm_hwbp_values(b->addr, &control, &value);
|
||||||
|
for (i = 0; i < ARM64_MAX_BREAKPOINTS; i++) {
|
||||||
|
if (ctx.Bvr[i] == value) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i < ARM64_MAX_BREAKPOINTS) {
|
||||||
|
ctx.Bcr[i] = 0;
|
||||||
|
ctx.Bvr[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set_thread_context(wrap->pi.hThread, (ut8 *)&ctx, sizeof(CONTEXT));
|
||||||
|
if (alive && resume_thread(wrap->pi.hThread, dbg->bits) == -1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static HANDLE get_thread_handle_from_tid(RzDebug *dbg, int tid) {
|
static HANDLE get_thread_handle_from_tid(RzDebug *dbg, int tid) {
|
||||||
rz_return_val_if_fail(dbg, NULL);
|
rz_return_val_if_fail(dbg, NULL);
|
||||||
W32DbgWInst *wrap = dbg->plugin_data;
|
W32DbgWInst *wrap = dbg->plugin_data;
|
||||||
|
|
@ -443,30 +600,20 @@ int w32_reg_read(RzDebug *dbg, int type, ut8 *buf, int size) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// Always suspend
|
// Always suspend
|
||||||
if (alive && suspend_thread(th, dbg->bits) == -1) {
|
if (alive && suspend_thread(th) == -1) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
size = get_thread_context(th, buf, size, dbg->bits);
|
size = get_thread_context(th, buf, size, CONTEXT_ALL);
|
||||||
if (showfpu) {
|
if (showfpu) {
|
||||||
print_fpu_context(th, (CONTEXT *)buf);
|
print_fpu_context(th, (CONTEXT *)buf);
|
||||||
}
|
}
|
||||||
// Always resume
|
// Always resume
|
||||||
if (alive && resume_thread(th, dbg->bits) == -1) {
|
if (alive && resume_thread(th) == -1) {
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void transfer_drx(RzDebug *dbg, const ut8 *buf) {
|
|
||||||
CONTEXT cur_ctx;
|
|
||||||
if (w32_reg_read(dbg, RZ_REG_TYPE_ANY, (ut8 *)&cur_ctx, sizeof(CONTEXT))) {
|
|
||||||
CONTEXT *new_ctx = (CONTEXT *)buf;
|
|
||||||
size_t drx_size = offsetof(CONTEXT, Dr7) - offsetof(CONTEXT, Dr0) + sizeof(new_ctx->Dr7);
|
|
||||||
memcpy(&cur_ctx.Dr0, &new_ctx->Dr0, drx_size);
|
|
||||||
*new_ctx = cur_ctx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int w32_reg_write(RzDebug *dbg, int type, const ut8 *buf, int size) {
|
int w32_reg_write(RzDebug *dbg, int type, const ut8 *buf, int size) {
|
||||||
bool alive = is_thread_alive(dbg, dbg->tid);
|
bool alive = is_thread_alive(dbg, dbg->tid);
|
||||||
if (!alive) {
|
if (!alive) {
|
||||||
|
|
@ -477,15 +624,15 @@ int w32_reg_write(RzDebug *dbg, int type, const ut8 *buf, int size) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// Always suspend
|
// Always suspend
|
||||||
if (suspend_thread(th, dbg->bits) == -1) {
|
if (suspend_thread(th) == -1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (type == RZ_REG_TYPE_DRX) {
|
if (type == RZ_REG_TYPE_DRX) {
|
||||||
transfer_drx(dbg, buf);
|
transfer_drx(dbg, buf);
|
||||||
}
|
}
|
||||||
bool ret = set_thread_context(th, buf, size, dbg->bits);
|
bool ret = set_thread_context(th, buf, size);
|
||||||
// Always resume
|
// Always resume
|
||||||
if (resume_thread(th, dbg->bits) == -1) {
|
if (resume_thread(th) == -1) {
|
||||||
ret = false;
|
ret = false;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -529,7 +676,7 @@ int w32_detach(RzDebug *dbg, int pid) {
|
||||||
PTHREAD_ITEM th;
|
PTHREAD_ITEM th;
|
||||||
rz_list_foreach (dbg->threads, it, th) {
|
rz_list_foreach (dbg->threads, it, th) {
|
||||||
if (th->bSuspended && !th->bFinished) {
|
if (th->bSuspended && !th->bFinished) {
|
||||||
resume_thread(th->hThread, dbg->bits);
|
resume_thread(th->hThread);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rz_list_purge(dbg->threads);
|
rz_list_purge(dbg->threads);
|
||||||
|
|
@ -778,7 +925,7 @@ int w32_select(RzDebug *dbg, int pid, int tid) {
|
||||||
// Suspend all other threads
|
// Suspend all other threads
|
||||||
rz_list_foreach (dbg->threads, it, th) {
|
rz_list_foreach (dbg->threads, it, th) {
|
||||||
if (!th->bFinished && !th->bSuspended && th->tid != selected) {
|
if (!th->bFinished && !th->bSuspended && th->tid != selected) {
|
||||||
suspend_thread(th->hThread, dbg->bits);
|
suspend_thread(th->hThread);
|
||||||
th->bSuspended = true;
|
th->bSuspended = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1022,7 +1169,6 @@ int w32_dbg_wait(RzDebug *dbg, int pid) {
|
||||||
case UNLOAD_DLL_DEBUG_EVENT: {
|
case UNLOAD_DLL_DEBUG_EVENT: {
|
||||||
PLIB_ITEM lib = (PLIB_ITEM)find_library(de.u.UnloadDll.lpBaseOfDll);
|
PLIB_ITEM lib = (PLIB_ITEM)find_library(de.u.UnloadDll.lpBaseOfDll);
|
||||||
if (lib) {
|
if (lib) {
|
||||||
CloseHandle(lib->hFile);
|
|
||||||
remove_library(lib);
|
remove_library(lib);
|
||||||
}
|
}
|
||||||
ret = RZ_DEBUG_REASON_EXIT_LIB;
|
ret = RZ_DEBUG_REASON_EXIT_LIB;
|
||||||
|
|
@ -1073,6 +1219,11 @@ int w32_dbg_wait(RzDebug *dbg, int pid) {
|
||||||
next_event = 0;
|
next_event = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
if (rz_bp_get_at(dbg->bp, (size_t)de.u.Exception.ExceptionRecord.ExceptionAddress)) {
|
||||||
|
ret = RZ_DEBUG_REASON_BREAKPOINT;
|
||||||
|
next_event = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
print_exception_event(&de);
|
print_exception_event(&de);
|
||||||
if (is_exception_fatal(de.u.Exception.ExceptionRecord.ExceptionCode)) {
|
if (is_exception_fatal(de.u.Exception.ExceptionRecord.ExceptionCode)) {
|
||||||
next_event = 0;
|
next_event = 0;
|
||||||
|
|
@ -1093,7 +1244,7 @@ int w32_dbg_wait(RzDebug *dbg, int pid) {
|
||||||
eprintf("(%d) unknown event: %lu\n", pid, de.dwDebugEventCode);
|
eprintf("(%d) unknown event: %lu\n", pid, de.dwDebugEventCode);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
goto end;
|
next_event = 0;
|
||||||
}
|
}
|
||||||
} while (next_event);
|
} while (next_event);
|
||||||
|
|
||||||
|
|
@ -1105,7 +1256,23 @@ int w32_dbg_wait(RzDebug *dbg, int pid) {
|
||||||
rz_warn_if_reached();
|
rz_warn_if_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if __arm__ || __arm64__
|
||||||
|
if (ret != RZ_DEBUG_REASON_EXIT_TID) {
|
||||||
|
CONTEXT ctx;
|
||||||
|
suspend_thread(wrap->pi.hThread);
|
||||||
|
get_thread_context(wrap->pi.hThread, (ut8 *)&ctx, sizeof(ctx), CONTEXT_CONTROL);
|
||||||
|
resume_thread(wrap->pi.hThread);
|
||||||
|
if (ctx.Cpsr & 0x20) {
|
||||||
|
dbg->bits = RZ_SYS_BITS_16;
|
||||||
|
} else {
|
||||||
|
#if __arm__
|
||||||
|
dbg->bits = RZ_SYS_BITS_32;
|
||||||
|
#else
|
||||||
|
dbg->bits = RZ_SYS_BITS_64;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
end:
|
end:
|
||||||
if (ret == RZ_DEBUG_REASON_DEAD) {
|
if (ret == RZ_DEBUG_REASON_DEAD) {
|
||||||
w32_detach(dbg, dbg->pid);
|
w32_detach(dbg, dbg->pid);
|
||||||
|
|
@ -1116,20 +1283,6 @@ end:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int w32_step(RzDebug *dbg) {
|
|
||||||
/* set TRAP flag */
|
|
||||||
CONTEXT ctx;
|
|
||||||
if (!w32_reg_read(dbg, RZ_REG_TYPE_GPR, (ut8 *)&ctx, sizeof(ctx))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ctx.EFlags |= 0x100;
|
|
||||||
if (!w32_reg_write(dbg, RZ_REG_TYPE_GPR, (ut8 *)&ctx, sizeof(ctx))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return w32_continue(dbg, dbg->pid, dbg->tid, dbg->reason.signum);
|
|
||||||
// (void)rz_debug_handle_signals (dbg);
|
|
||||||
}
|
|
||||||
|
|
||||||
int w32_continue(RzDebug *dbg, int pid, int tid, int sig) {
|
int w32_continue(RzDebug *dbg, int pid, int tid, int sig) {
|
||||||
if (tid != dbg->tid) {
|
if (tid != dbg->tid) {
|
||||||
dbg->tid = w32_select(dbg, pid, tid);
|
dbg->tid = w32_select(dbg, pid, tid);
|
||||||
|
|
@ -1146,7 +1299,7 @@ int w32_continue(RzDebug *dbg, int pid, int tid, int sig) {
|
||||||
|
|
||||||
PTHREAD_ITEM th = find_thread(dbg, tid);
|
PTHREAD_ITEM th = find_thread(dbg, tid);
|
||||||
if (th && th->hThread != INVALID_HANDLE_VALUE && th->bSuspended) {
|
if (th && th->hThread != INVALID_HANDLE_VALUE && th->bSuspended) {
|
||||||
continue_thread(th->hThread, dbg->bits);
|
continue_thread(th->hThread);
|
||||||
th->bSuspended = false;
|
th->bSuspended = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1222,6 +1375,19 @@ int w32_map_protect(RzDebug *dbg, ut64 addr, int size, int perms) {
|
||||||
size, io_perms_to_prot(perms), &old);
|
size, io_perms_to_prot(perms), &old);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline ut64 pc_from_context(CONTEXT *ctx) {
|
||||||
|
#if __x86_64__
|
||||||
|
return ctx->Rip;
|
||||||
|
#elif __arm__ || __arm64__
|
||||||
|
return ctx->Pc;
|
||||||
|
#elif __i386__
|
||||||
|
return ctx->Eip;
|
||||||
|
#else
|
||||||
|
#pragma warning("platform not supported")
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
RzList *w32_thread_list(RzDebug *dbg, int pid, RzList *list) {
|
RzList *w32_thread_list(RzDebug *dbg, int pid, RzList *list) {
|
||||||
// pid is not respected for TH32CS_SNAPTHREAD flag
|
// pid is not respected for TH32CS_SNAPTHREAD flag
|
||||||
HANDLE th = w32_CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
HANDLE th = w32_CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
||||||
|
|
@ -1257,11 +1423,7 @@ RzList *w32_thread_list(RzDebug *dbg, int pid, RzList *list) {
|
||||||
dbg->tid = te.th32ThreadID;
|
dbg->tid = te.th32ThreadID;
|
||||||
w32_reg_read(dbg, RZ_REG_TYPE_GPR, (ut8 *)&ctx, sizeof(ctx));
|
w32_reg_read(dbg, RZ_REG_TYPE_GPR, (ut8 *)&ctx, sizeof(ctx));
|
||||||
// TODO: is needed check context for x32 and x64??
|
// TODO: is needed check context for x32 and x64??
|
||||||
#if _WIN64
|
pc = pc_from_context(&ctx);
|
||||||
pc = ctx.Rip;
|
|
||||||
#else
|
|
||||||
pc = ctx.Eip;
|
|
||||||
#endif
|
|
||||||
PTHREAD_ITEM pthread = find_thread(dbg, te.th32ThreadID);
|
PTHREAD_ITEM pthread = find_thread(dbg, te.th32ThreadID);
|
||||||
if (pthread) {
|
if (pthread) {
|
||||||
if (pthread->bFinished) {
|
if (pthread->bFinished) {
|
||||||
|
|
@ -1404,6 +1566,7 @@ static RzDebugPid *build_debug_pid(int pid, int ppid, HANDLE ph, const TCHAR *na
|
||||||
}
|
}
|
||||||
|
|
||||||
RzList *w32_pid_list(RzDebug *dbg, int pid, RzList *list) {
|
RzList *w32_pid_list(RzDebug *dbg, int pid, RzList *list) {
|
||||||
|
W32DbgWInst *wrap = dbg->plugin_data;
|
||||||
HANDLE sh = w32_CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, pid);
|
HANDLE sh = w32_CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, pid);
|
||||||
if (sh == INVALID_HANDLE_VALUE) {
|
if (sh == INVALID_HANDLE_VALUE) {
|
||||||
rz_sys_perror("CreateToolhelp32Snapshot");
|
rz_sys_perror("CreateToolhelp32Snapshot");
|
||||||
|
|
@ -1412,7 +1575,6 @@ RzList *w32_pid_list(RzDebug *dbg, int pid, RzList *list) {
|
||||||
PROCESSENTRY32 pe;
|
PROCESSENTRY32 pe;
|
||||||
pe.dwSize = sizeof(pe);
|
pe.dwSize = sizeof(pe);
|
||||||
if (Process32First(sh, &pe)) {
|
if (Process32First(sh, &pe)) {
|
||||||
W32DbgWInst *wrap = dbg->plugin_data;
|
|
||||||
bool all = pid == 0;
|
bool all = pid == 0;
|
||||||
do {
|
do {
|
||||||
if (all || pe.th32ProcessID == pid || pe.th32ParentProcessID == pid) {
|
if (all || pe.th32ProcessID == pid || pe.th32ParentProcessID == pid) {
|
||||||
|
|
|
||||||
|
|
@ -190,4 +190,10 @@ RzDebugInfo *w32_info(RzDebug *dbg, const char *arg);
|
||||||
RzList *w32_pid_list(RzDebug *dbg, int pid, RzList *list);
|
RzList *w32_pid_list(RzDebug *dbg, int pid, RzList *list);
|
||||||
|
|
||||||
RzList *w32_desc_list(int pid);
|
RzList *w32_desc_list(int pid);
|
||||||
|
|
||||||
|
#if __arm64__
|
||||||
|
int w32_hwbp_arm_add(RzDebug *dbg, RzBreakpoint *bp, RzBreakpointItem *b);
|
||||||
|
int w32_hwbp_arm_del(RzDebug *dbg, RzBreakpoint *bp, RzBreakpointItem *b);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -247,13 +247,21 @@ static char *msg_types_arr[] = {
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
void __free_window(void *ptr) {
|
typedef struct _window {
|
||||||
|
DWORD pid;
|
||||||
|
DWORD tid;
|
||||||
|
HWND h;
|
||||||
|
char *name;
|
||||||
|
ut64 proc;
|
||||||
|
} window;
|
||||||
|
|
||||||
|
void free_window(void *ptr) {
|
||||||
window *win = ptr;
|
window *win = ptr;
|
||||||
free(win->name);
|
free(win->name);
|
||||||
free(win);
|
free(win);
|
||||||
}
|
}
|
||||||
|
|
||||||
static window *__window_from_handle(HANDLE hwnd) {
|
static window *window_from_handle(HANDLE hwnd) {
|
||||||
rz_return_val_if_fail(hwnd, NULL);
|
rz_return_val_if_fail(hwnd, NULL);
|
||||||
window *win = RZ_NEW0(window);
|
window *win = RZ_NEW0(window);
|
||||||
if (!win) {
|
if (!win) {
|
||||||
|
|
@ -277,7 +285,7 @@ static window *__window_from_handle(HANDLE hwnd) {
|
||||||
return win;
|
return win;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RzTable *__create_window_table(void) {
|
static RzTable *create_window_table(void) {
|
||||||
RzTable *tbl = rz_table_new();
|
RzTable *tbl = rz_table_new();
|
||||||
if (!tbl) {
|
if (!tbl) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -289,7 +297,7 @@ static RzTable *__create_window_table(void) {
|
||||||
return tbl;
|
return tbl;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __add_window_to_table(RzTable *tbl, window *win) {
|
static void add_window_to_table(RzTable *tbl, window *win) {
|
||||||
rz_return_if_fail(tbl && win);
|
rz_return_if_fail(tbl && win);
|
||||||
char *handle = rz_str_newf("0x%08" PFMT64x "", (ut64)win->h);
|
char *handle = rz_str_newf("0x%08" PFMT64x "", (ut64)win->h);
|
||||||
char *pid = rz_str_newf("%lu", win->pid);
|
char *pid = rz_str_newf("%lu", win->pid);
|
||||||
|
|
@ -301,18 +309,20 @@ static void __add_window_to_table(RzTable *tbl, window *win) {
|
||||||
}
|
}
|
||||||
|
|
||||||
RZ_API void rz_w32_identify_window(void) {
|
RZ_API void rz_w32_identify_window(void) {
|
||||||
while (!rz_cons_yesno('y', "Move cursor to the window to be identified. Ready?"))
|
while (!rz_cons_yesno('y', "Move cursor to the window to be identified. Ready? (Y/n)"))
|
||||||
;
|
;
|
||||||
POINT p;
|
POINT p;
|
||||||
GetCursorPos(&p);
|
if (!GetCursorPos(&p)) {
|
||||||
HANDLE hwnd = WindowFromPoint(p);
|
rz_sys_perror("GetCursorPos");
|
||||||
|
}
|
||||||
|
HWND hwnd = WindowFromPoint(p);
|
||||||
window *win = NULL;
|
window *win = NULL;
|
||||||
if (hwnd) {
|
if (hwnd) {
|
||||||
if (rz_cons_yesno('y', "Try to get the child?")) {
|
if (rz_cons_yesno('y', "Try to get the child? (Y/n)")) {
|
||||||
HANDLE child = ChildWindowFromPoint(hwnd, p);
|
HWND child = ChildWindowFromPoint(hwnd, p);
|
||||||
hwnd = child ? child : hwnd;
|
hwnd = child ? child : hwnd;
|
||||||
}
|
}
|
||||||
win = __window_from_handle(hwnd);
|
win = window_from_handle(hwnd);
|
||||||
} else {
|
} else {
|
||||||
eprintf("No window found\n");
|
eprintf("No window found\n");
|
||||||
return;
|
return;
|
||||||
|
|
@ -321,22 +331,22 @@ RZ_API void rz_w32_identify_window(void) {
|
||||||
eprintf("Error trying to get information from 0x%08" PFMT64x "\n", (ut64)hwnd);
|
eprintf("Error trying to get information from 0x%08" PFMT64x "\n", (ut64)hwnd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RzTable *tbl = __create_window_table();
|
RzTable *tbl = create_window_table();
|
||||||
if (!tbl) {
|
if (!tbl) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
__add_window_to_table(tbl, win);
|
add_window_to_table(tbl, win);
|
||||||
char *tbl_str = rz_table_tofancystring(tbl);
|
char *tbl_str = rz_table_tofancystring(tbl);
|
||||||
rz_cons_print(tbl_str);
|
rz_cons_print(tbl_str);
|
||||||
free(tbl_str);
|
free(tbl_str);
|
||||||
rz_table_free(tbl);
|
rz_table_free(tbl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL CALLBACK __enum_childs(
|
static BOOL CALLBACK enum_childs(
|
||||||
_In_ HWND hwnd,
|
_In_ HWND hwnd,
|
||||||
_In_ LPARAM lParam) {
|
_In_ LPARAM lParam) {
|
||||||
RzList *windows = (RzList *)lParam;
|
RzList *windows = (RzList *)lParam;
|
||||||
window *win = __window_from_handle(hwnd);
|
window *win = window_from_handle(hwnd);
|
||||||
if (!win) {
|
if (!win) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -344,16 +354,16 @@ static BOOL CALLBACK __enum_childs(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RzList *__get_windows(RzDebug *dbg) {
|
static RzList *get_windows(RzDebug *dbg) {
|
||||||
RzList *windows = rz_list_newf((RzListFree)__free_window);
|
RzList *windows = rz_list_newf((RzListFree)free_window);
|
||||||
HWND hCurWnd = NULL;
|
HWND hCurWnd = NULL;
|
||||||
do {
|
do {
|
||||||
hCurWnd = FindWindowEx(NULL, hCurWnd, NULL, NULL);
|
hCurWnd = FindWindowEx(NULL, hCurWnd, NULL, NULL);
|
||||||
DWORD dwProcessID = 0;
|
DWORD dwProcessID = 0;
|
||||||
GetWindowThreadProcessId(hCurWnd, &dwProcessID);
|
GetWindowThreadProcessId(hCurWnd, &dwProcessID);
|
||||||
if (dbg->pid == dwProcessID) {
|
if (dbg->pid == dwProcessID) {
|
||||||
EnumChildWindows(hCurWnd, __enum_childs, (LPARAM)windows);
|
EnumChildWindows(hCurWnd, enum_childs, (LPARAM)windows);
|
||||||
window *win = __window_from_handle(hCurWnd);
|
window *win = window_from_handle(hCurWnd);
|
||||||
if (!win) {
|
if (!win) {
|
||||||
rz_list_free(windows);
|
rz_list_free(windows);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -364,7 +374,7 @@ static RzList *__get_windows(RzDebug *dbg) {
|
||||||
return windows;
|
return windows;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ut64 __get_dispatchmessage_offset(RzDebug *dbg) {
|
static ut64 get_dispatchmessage_offset(RzDebug *dbg) {
|
||||||
RzList *modlist = rz_debug_modules_list(dbg);
|
RzList *modlist = rz_debug_modules_list(dbg);
|
||||||
RzListIter *it;
|
RzListIter *it;
|
||||||
RzDebugMap *mod;
|
RzDebugMap *mod;
|
||||||
|
|
@ -397,7 +407,7 @@ static ut64 __get_dispatchmessage_offset(RzDebug *dbg) {
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init_msg_types(Sdb **msg_types) {
|
static void init_msg_types(Sdb **msg_types) {
|
||||||
*msg_types = sdb_new0();
|
*msg_types = sdb_new0();
|
||||||
int i;
|
int i;
|
||||||
char *cur_type;
|
char *cur_type;
|
||||||
|
|
@ -406,44 +416,44 @@ static void __init_msg_types(Sdb **msg_types) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD __get_msg_type(char *name) {
|
static DWORD get_msg_type(char *name) {
|
||||||
static Sdb *msg_types = NULL;
|
static Sdb *msg_types = NULL;
|
||||||
if (!msg_types) {
|
if (!msg_types) {
|
||||||
__init_msg_types(&msg_types);
|
init_msg_types(&msg_types);
|
||||||
}
|
}
|
||||||
ut32 found;
|
ut32 found;
|
||||||
const char *type_str = sdb_const_get(msg_types, name, &found);
|
const char *type_str = sdb_const_get(msg_types, name, &found);
|
||||||
if (found) {
|
if (found) {
|
||||||
int type = rz_num_math(NULL, type_str);
|
int type = rz_num_get(NULL, type_str);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __print_windows(RzDebug *dbg, RzList *windows) {
|
static void print_windows(RzDebug *dbg, RzList *windows) {
|
||||||
RzTable *tbl = __create_window_table();
|
RzTable *tbl = create_window_table();
|
||||||
if (!tbl) {
|
if (!tbl) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RzListIter *it;
|
RzListIter *it;
|
||||||
window *win;
|
window *win;
|
||||||
rz_list_foreach (windows, it, win) {
|
rz_list_foreach (windows, it, win) {
|
||||||
__add_window_to_table(tbl, win);
|
add_window_to_table(tbl, win);
|
||||||
}
|
}
|
||||||
char *t = rz_table_tofancystring(tbl);
|
char *t = rz_table_tostring(tbl);
|
||||||
dbg->cb_printf(t);
|
dbg->cb_printf(t);
|
||||||
free(t);
|
free(t);
|
||||||
rz_table_free(tbl);
|
rz_table_free(tbl);
|
||||||
}
|
}
|
||||||
|
|
||||||
RZ_API void rz_w32_print_windows(RzDebug *dbg) {
|
RZ_API void rz_w32_print_windows(RzDebug *dbg) {
|
||||||
RzList *windows = __get_windows(dbg);
|
RzList *windows = get_windows(dbg);
|
||||||
if (windows) {
|
if (windows) {
|
||||||
if (!windows->length) {
|
if (!windows->length) {
|
||||||
dbg->cb_printf("No windows for this process.\n");
|
dbg->cb_printf("No windows for this process.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
__print_windows(dbg, windows);
|
print_windows(dbg, windows);
|
||||||
}
|
}
|
||||||
rz_list_free(windows);
|
rz_list_free(windows);
|
||||||
}
|
}
|
||||||
|
|
@ -453,14 +463,14 @@ RZ_API bool rz_w32_add_winmsg_breakpoint(RzDebug *dbg, const char *msg_name, con
|
||||||
char *name = strdup(msg_name);
|
char *name = strdup(msg_name);
|
||||||
rz_str_trim(name);
|
rz_str_trim(name);
|
||||||
|
|
||||||
DWORD type = __get_msg_type(name);
|
DWORD type = get_msg_type(name);
|
||||||
if (!type) {
|
if (!type) {
|
||||||
free(name);
|
free(name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ut64 offset = 0;
|
ut64 offset = 0;
|
||||||
if (window_id) {
|
if (window_id) {
|
||||||
RzList *windows = __get_windows(dbg);
|
RzList *windows = get_windows(dbg);
|
||||||
if (windows && !windows->length) {
|
if (windows && !windows->length) {
|
||||||
dbg->cb_printf("No windows for this process.\n");
|
dbg->cb_printf("No windows for this process.\n");
|
||||||
}
|
}
|
||||||
|
|
@ -475,30 +485,51 @@ RZ_API bool rz_w32_add_winmsg_breakpoint(RzDebug *dbg, const char *msg_name, con
|
||||||
}
|
}
|
||||||
if (!offset) {
|
if (!offset) {
|
||||||
dbg->cb_printf("Window not found, try these:\n");
|
dbg->cb_printf("Window not found, try these:\n");
|
||||||
__print_windows(dbg, windows);
|
print_windows(dbg, windows);
|
||||||
}
|
}
|
||||||
rz_list_free(windows);
|
rz_list_free(windows);
|
||||||
} else {
|
} else {
|
||||||
offset = __get_dispatchmessage_offset(dbg);
|
offset = get_dispatchmessage_offset(dbg);
|
||||||
}
|
}
|
||||||
if (!offset) {
|
if (!offset) {
|
||||||
free(name);
|
free(name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
rz_debug_bp_add(dbg, offset, 0, 0, 0, NULL, 0);
|
RzBreakpointItem *b = rz_debug_bp_add(dbg, offset, 0, 0, 0, NULL, 0);
|
||||||
|
if (!b) {
|
||||||
|
free(name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
char *cond;
|
char *cond;
|
||||||
if (window_id) {
|
if (window_id) {
|
||||||
cond = rz_str_newf("?= `ae %lu,edx,-`", type);
|
char *reg;
|
||||||
|
if (!strcmp(dbg->arch, "arm")) {
|
||||||
|
if (dbg->bits == RZ_SYS_BITS_64) {
|
||||||
|
reg = "x1";
|
||||||
|
} else {
|
||||||
|
reg = "r1";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reg = "edx";
|
||||||
|
}
|
||||||
|
b->cond = rz_str_newf("?q `ae %s,%d,-`", reg, type);
|
||||||
} else {
|
} else {
|
||||||
char *reg;
|
char *reg;
|
||||||
if (dbg->bits == RZ_SYS_BITS_64) {
|
if (!strcmp(dbg->arch, "arm")) {
|
||||||
reg = "rcx";
|
if (dbg->bits == RZ_SYS_BITS_64) {
|
||||||
|
reg = "x0";
|
||||||
|
} else {
|
||||||
|
reg = "r0";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
reg = "ecx";
|
if (dbg->bits == RZ_SYS_BITS_64) {
|
||||||
|
reg = "rcx";
|
||||||
|
} else {
|
||||||
|
reg = "ecx";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cond = rz_str_newf("?= `ae %lu,%s,%d,+,[4],-`", type, reg, dbg->bits);
|
b->cond = rz_str_newf("?q `ae %lu,%s,%d,+,[4],-`", type, reg, dbg->bits);
|
||||||
}
|
}
|
||||||
dbg->corebind.cmdf(dbg->corebind.core, "\"dbC %s @ 0x%" PFMT64x "\"", cond, offset);
|
|
||||||
free(name);
|
free(name);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,6 @@
|
||||||
|
|
||||||
#include <rz_types.h>
|
#include <rz_types.h>
|
||||||
|
|
||||||
typedef struct _window {
|
|
||||||
DWORD pid;
|
|
||||||
DWORD tid;
|
|
||||||
HANDLE h;
|
|
||||||
char *name;
|
|
||||||
ut64 proc;
|
|
||||||
} window;
|
|
||||||
|
|
||||||
RZ_API bool rz_w32_add_winmsg_breakpoint(RzDebug *dbg, const char *msg_name, const char *window_id);
|
RZ_API bool rz_w32_add_winmsg_breakpoint(RzDebug *dbg, const char *msg_name, const char *window_id);
|
||||||
RZ_API void rz_w32_identify_window(void);
|
RZ_API void rz_w32_identify_window(void);
|
||||||
RZ_API void rz_w32_print_windows(RzDebug *dbg);
|
RZ_API void rz_w32_print_windows(RzDebug *dbg);
|
||||||
|
|
|
||||||
|
|
@ -497,16 +497,26 @@ static inline void *rz_new_copy(int size, void *data) {
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#ifdef _WIN64
|
#if defined(_M_X64) || defined(_M_AMD64)
|
||||||
#define RZ_SYS_ARCH "x86"
|
#define RZ_SYS_ARCH "x86"
|
||||||
#define RZ_SYS_BITS (RZ_SYS_BITS_32 | RZ_SYS_BITS_64)
|
#define RZ_SYS_BITS (RZ_SYS_BITS_32 | RZ_SYS_BITS_64)
|
||||||
#define RZ_SYS_ENDIAN 0
|
#define RZ_SYS_ENDIAN 0
|
||||||
#define __x86_64__ 1
|
#define __x86_64__ 1
|
||||||
#else
|
#elif defined(_M_IX86)
|
||||||
#define RZ_SYS_ARCH "x86"
|
#define RZ_SYS_ARCH "x86"
|
||||||
#define RZ_SYS_BITS (RZ_SYS_BITS_32)
|
#define RZ_SYS_BITS (RZ_SYS_BITS_32)
|
||||||
#define __i386__ 1
|
|
||||||
#define RZ_SYS_ENDIAN 0
|
#define RZ_SYS_ENDIAN 0
|
||||||
|
#define __i386__ 1
|
||||||
|
#elif defined(_M_ARM64)
|
||||||
|
#define RZ_SYS_ARCH "arm"
|
||||||
|
#define RZ_SYS_BITS (RZ_SYS_BITS_32 | RZ_SYS_BITS_64)
|
||||||
|
#define RZ_SYS_ENDIAN 0
|
||||||
|
#define __arm64__ 1
|
||||||
|
#elif defined(_M_ARM)
|
||||||
|
#define RZ_SYS_ARCH "arm"
|
||||||
|
#define RZ_SYS_BITS RZ_SYS_BITS_32
|
||||||
|
#define RZ_SYS_ENDIAN 0
|
||||||
|
#define __arm__ 1
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#define RZ_SYS_ARCH "unknown"
|
#define RZ_SYS_ARCH "unknown"
|
||||||
|
|
|
||||||
13
sys/cross-arm64-windows.txt
Normal file
13
sys/cross-arm64-windows.txt
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
# SPDX-FileCopyrightText: 2021 GustavoLCR <gugulcr@gmail.com>
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only
|
||||||
|
[binaries]
|
||||||
|
c = 'cl'
|
||||||
|
cpp = 'cl'
|
||||||
|
ar = 'lib'
|
||||||
|
windres = 'rc'
|
||||||
|
|
||||||
|
[host_machine]
|
||||||
|
system = 'windows'
|
||||||
|
cpu_family = 'aarch64'
|
||||||
|
cpu = 'armv8'
|
||||||
|
endian = 'little'
|
||||||
Loading…
Reference in a new issue