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:
GustavoLCR 2021-11-24 09:13:42 -03:00 committed by GitHub
parent 73fa2b30a5
commit 53a7694631
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 816 additions and 283 deletions

View file

@ -22,6 +22,10 @@
#define RZ_TEST_ARCH "x86"
#elif __x86_64__
#define RZ_TEST_ARCH "x64"
#elif __arm__
#define RZ_TEST_ARCH "arm"
#elif __arm64__
#define RZ_TEST_ARCH "arm64"
#else
#define RZ_TEST_ARCH "unknown"
#endif

View file

@ -696,14 +696,6 @@ static bool cb_asmbits(void *user, void *data) {
bool load_from_debug = rz_config_get_b(core->config, "cfg.debug");
if (load_from_debug) {
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);
rz_reg_set_profile_string(core->dbg->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.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);
#endif
SETDESC(n, "Select backtrace algorithm");
SETOPTIONS(n, "default", "fuzzy", "analysis", "trace", NULL);
SETCB("dbg.threads", "false", &cb_stopthreads, "Stop all threads when debugger breaks (see dbg.forks)");

View file

@ -585,6 +585,25 @@ RZ_API void rz_core_debug_ri(RzCore *core, RzReg *reg, int mode) {
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) {
if (rz_config_get_b(core->config, "cfg.debug")) {
if (core->print->cur_enabled) {

View file

@ -703,6 +703,7 @@ RZ_IPI void rz_core_dbg_follow_seek_register(RzCore *core) {
if ((pc < core->offset) || (pc > (core->offset + follow))) {
rz_core_seek_to_register(core, "PC", false);
}
rz_core_debug_sync_bits(core);
}
}

View file

@ -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 void rz_core_debug_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_over(RzCore *core);
RZ_IPI void rz_core_debug_breakpoint_toggle(RzCore *core, ut64 addr);

View file

@ -3363,6 +3363,7 @@ RZ_API void rz_core_visual_title(RzCore *core, int color) {
} else if (follow < 0) {
rz_core_seek(core, curpc + follow, true);
}
rz_core_debug_sync_bits(core);
oldpc = curpc;
}
}

View file

@ -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) {
if (arch && dbg && dbg->cur) {
switch (bits) {
case 16:
if (dbg->cur->bits & RZ_SYS_BITS_16) {
dbg->bits = RZ_SYS_BITS_16;
}
break;
case 27:
if (dbg->cur->bits == 27) {
dbg->bits = 27;
@ -798,6 +803,9 @@ RZ_API int rz_debug_step_soft(RzDebug *dbg) {
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]);
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) {
case RZ_ANALYSIS_OP_TYPE_RET:
if (arch_ret_is_pop && op.stackop == RZ_ANALYSIS_STACK_INC) {
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;
next[0] = (dbg->bits <= RZ_SYS_BITS_32) ? sp_top.r32[0] : sp_top.r64;
}
br = 1;
break;
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)) {
next[0] = op.addr + op.size;
} 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;
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)) {
next[0] = op.addr + op.size;
} 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;
break;
@ -867,7 +882,11 @@ RZ_API int rz_debug_step_soft(RzDebug *dbg) {
break;
}
const int align = rz_analysis_archinfo(dbg->analysis, RZ_ANALYSIS_ARCHINFO_ALIGN);
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);
if (bpi) {
bpi->swstep = true;

View file

@ -129,9 +129,10 @@ static int rz_debug_native_step(RzDebug *dbg) {
return false;
}
return true;
#else // linux
#elif __linux__
return linux_step(dbg);
#endif
return 0;
}
// return thread id
@ -1305,7 +1306,7 @@ static int rz_debug_native_drx(RzDebug *dbg, int n, ut64 addr, int sz, int rwx,
#else
eprintf("drx: Unsupported platform\n");
#endif
return false;
return -1;
}
#if __linux__
@ -1434,6 +1435,10 @@ static int rz_debug_native_bp(RzBreakpoint *bp, RzBreakpointItem *b, bool set) {
return set
? arm64_hwbp_add(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__
return set
? arm32_hwbp_add(dbg, bp, b)
@ -1602,7 +1607,11 @@ RzDebugPlugin rz_debug_plugin_native = {
#elif __aarch64__ || __arm64__
.bits = RZ_SYS_BITS_16 | RZ_SYS_BITS_32 | RZ_SYS_BITS_64,
.arch = "arm",
#if __WINDOWS__
.canstep = 0,
#else
.canstep = 1,
#endif
#elif __arm__
.bits = RZ_SYS_BITS_16 | RZ_SYS_BITS_32 | RZ_SYS_BITS_64,
.arch = "arm",
@ -1656,7 +1665,9 @@ RzDebugPlugin rz_debug_plugin_native = {
.modules_get = rz_debug_native_modules_get,
.map_protect = rz_debug_native_map_protect,
.breakpoint = rz_debug_native_bp,
#if __i386__ || __x86_64__
.drx = rz_debug_native_drx,
#endif
.gcore = rz_debug_gcore,
};

View file

@ -44,7 +44,7 @@ typedef struct { // Keep in sync with io_windbg.c
PDEBUG_ADVANCED3 dbgAdvanced;
} DbgEngContext;
static bool __is_target_kernel(DbgEngContext *idbg) {
static bool is_target_kernel(DbgEngContext *idbg) {
ULONG Class, Qualifier;
if (SUCCEEDED(ITHISCALL(dbgCtrl, GetDebuggeeType, &Class, &Qualifier))) {
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);
ULONG process_id = pid;
ULONG thread_id = tid;
if (!__is_target_kernel(idbg)) {
if (!is_target_kernel(idbg)) {
ITHISCALL(dbgSysObj, GetProcessIdBySystemId, pid, &process_id);
ITHISCALL(dbgSysObj, GetThreadIdBySystemId, tid, &thread_id);
}
@ -136,10 +136,10 @@ static int windbg_stop(RzDebug *dbg) {
static bool do_break = false;
static void __break(void *user) {
static void break_debugger(void *user) {
RzDebug *dbg = (RzDebug *)user;
DbgEngContext *idbg = dbg->plugin_data;
if (__is_target_kernel(idbg)) {
if (is_target_kernel(idbg)) {
windbg_stop(dbg);
}
do_break = true;
@ -149,8 +149,8 @@ static int windbg_wait(RzDebug *dbg, int pid) {
DbgEngContext *idbg = dbg->plugin_data;
rz_return_val_if_fail(idbg && idbg->initialized, 0);
ULONG Type, ProcessId, ThreadId;
rz_cons_break_push(__break, dbg);
const ULONG timeout = __is_target_kernel(idbg) ? INFINITE : TIMEOUT;
rz_cons_break_push(break_debugger, dbg);
const ULONG timeout = is_target_kernel(idbg) ? INFINITE : TIMEOUT;
HRESULT hr;
while ((hr = ITHISCALL(dbgCtrl, WaitForEvent, DEBUG_WAIT_DEFAULT, timeout)) == S_FALSE) {
if (do_break) {
@ -165,7 +165,7 @@ static int windbg_wait(RzDebug *dbg, int pid) {
return RZ_DEBUG_REASON_DEAD;
}
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, GetCurrentThreadSystemId, (PULONG)&dbg->tid);
} else {

View file

@ -3,6 +3,9 @@
#include <rz_analysis.h>
#if __WINDOWS__
#include "bt/windows-all.c"
#endif
#include "bt/generic-x86.c"
#include "bt/generic-x64.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")) {
cb = backtrace_fuzzy;
} else if (!strcmp(dbg->btalgo, "analysis")) {
if (!strcmp(dbg->arch, "x86")) {
if (dbg->bits == RZ_SYS_BITS_64) {
cb = backtrace_x86_64_analysis;
} else {
cb = backtrace_x86_32_analysis;
}
} else {
eprintf("Analysis backtrace not available for current architecture (%s)\n", dbg->arch);
return NULL;
}
}
}
if (!cb) {
#if __WINDOWS__
cb = backtrace_windows;
#else
if (dbg->bits == RZ_SYS_BITS_64) {
cb = backtrace_x86_64;
} else {
cb = backtrace_x86_32;
}
#endif
}
RzList *list;

View 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

View file

@ -6,6 +6,7 @@ return strdup(
"=PC pc\n"
"=BP x29\n"
"=SP sp\n"
"=LR x30\n"
"=SN x8\n"
"=A0 x0\n"
"=A1 x1\n"

View file

@ -6,17 +6,21 @@
static char *rz_debug_native_reg_profile(RzDebug *dbg) {
#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"
} else {
#elif defined(__i386__)
#include "reg/windows-x86.h"
}
#endif
#elif (__OpenBSD__ || __NetBSD__)
/* __.--..__
\-/-/-/ _ __ _.--' _.--'

View file

@ -5,6 +5,7 @@ return strdup(
"=PC pc\n"
"=SP sp\n"
"=BP fp\n"
"=LR lr\n"
"=A0 r0\n"
"=A1 r1\n"
"=A2 r2\n"
@ -25,7 +26,7 @@ return strdup(
"gpr r9 .32 40 0\n"
"gpr r10 .32 44 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 lr .32 60 0\n"
"gpr pc .32 64 0\n"
@ -34,40 +35,44 @@ return strdup(
"flg cf .1 68.29 0 carry\n"
"flg zf .1 68.30 0 zero\n"
"flg nf .1 68.31 0 sign\n"
"gpr fpsr .32 72 0\n"
"fpu q0 .128 76 0\n"
"fpu q1 .128 92 0\n"
"fpu q2 .128 108 0\n"
"fpu q3 .128 124 0\n"
"fpu q4 .128 140 0\n"
"fpu q5 .128 156 0\n"
"fpu q6 .128 172 0\n"
"fpu q7 .128 188 0\n"
"fpu q8 .128 204 0\n"
"fpu q9 .128 220 0\n"
"fpu q10 .128 236 0\n"
"fpu q11 .128 252 0\n"
"fpu q12 .128 268 0\n"
"fpu q13 .128 284 0\n"
"fpu q14 .128 300 0\n"
"fpu q15 .128 316 0\n"
"drx bcr0 .32 332 0\n"
"drx bcr1 .32 336 0\n"
"drx bcr2 .32 340 0\n"
"drx bcr3 .32 344 0\n"
"drx bcr4 .32 348 0\n"
"drx bcr5 .32 352 0\n"
"drx bcr6 .32 356 0\n"
"drx bcr7 .32 360 0\n"
"drx bvr0 .32 364 0\n"
"drx bvr1 .32 368 0\n"
"drx bvr2 .32 372 0\n"
"drx bvr3 .32 376 0\n"
"drx bvr4 .32 380 0\n"
"drx bvr5 .32 384 0\n"
"drx bvr6 .32 388 0\n"
"drx bvr7 .32 392 0\n"
"drx wcr0 .32 396 0\n"
"drx wcr1 .32 400 0\n"
"drx wvr0 .32 404 0\n"
"drx wvr1 .32 408 0\n");
"flg fpscr .32 72 0\n"
"flg fvf .1 72.28 0 overflow\n"
"flg fcf .1 72.29 0 carry\n"
"flg fzf .1 72.30 0 zero\n"
"flg fnf .1 72.31 0 sign\n"
"fpu q0 .128 80 0\n"
"fpu q1 .128 96 0\n"
"fpu q2 .128 112 0\n"
"fpu q3 .128 128 0\n"
"fpu q4 .128 144 0\n"
"fpu q5 .128 160 0\n"
"fpu q6 .128 176 0\n"
"fpu q7 .128 192 0\n"
"fpu q8 .128 208 0\n"
"fpu q9 .128 224 0\n"
"fpu q10 .128 240 0\n"
"fpu q11 .128 256 0\n"
"fpu q12 .128 272 0\n"
"fpu q13 .128 288 0\n"
"fpu q14 .128 304 0\n"
"fpu q15 .128 320 0\n"
"drx bcr0 .32 336 0\n"
"drx bcr1 .32 340 0\n"
"drx bcr2 .32 344 0\n"
"drx bcr3 .32 348 0\n"
"drx bcr4 .32 352 0\n"
"drx bcr5 .32 356 0\n"
"drx bcr6 .32 360 0\n"
"drx bcr7 .32 364 0\n"
"drx bvr0 .32 368 0\n"
"drx bvr1 .32 372 0\n"
"drx bvr2 .32 376 0\n"
"drx bvr3 .32 380 0\n"
"drx bvr4 .32 384 0\n"
"drx bvr5 .32 388 0\n"
"drx bvr6 .32 392 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");

View file

@ -1,10 +1,12 @@
// SPDX-FileCopyrightText: 2020 GustavoLCR <gugulcr@gmail.com>
// SPDX-License-Identifier: LGPL-3.0-only
return strdup(
if (dbg->bits == RZ_SYS_BITS_64) {
return strdup(
"=PC pc\n"
"=SP sp\n"
"=BP fp\n"
"=LR lr\n"
"=A0 x0\n"
"=A1 x1\n"
"=A2 x2\n"
@ -48,6 +50,35 @@ return strdup(
"gpr x26 .64 216 0\n"
"gpr x27 .64 224 0\n"
"gpr x28 .64 232 0\n"
"gpr w0 .32 8 0\n"
"gpr w1 .32 16 0\n"
"gpr w2 .32 24 0\n"
"gpr w3 .32 32 0\n"
"gpr w4 .32 40 0\n"
"gpr w5 .32 48 0\n"
"gpr w6 .32 56 0\n"
"gpr w7 .32 64 0\n"
"gpr w8 .32 72 0\n"
"gpr w9 .32 80 0\n"
"gpr w10 .32 88 0\n"
"gpr w11 .32 96 0\n"
"gpr w12 .32 104 0\n"
"gpr w13 .32 112 0\n"
"gpr w14 .32 120 0\n"
"gpr w15 .32 128 0\n"
"gpr w16 .32 136 0\n"
"gpr w17 .32 144 0\n"
"gpr w18 .32 152 0\n"
"gpr w19 .32 160 0\n"
"gpr w20 .32 168 0\n"
"gpr w21 .32 176 0\n"
"gpr w22 .32 184 0\n"
"gpr w23 .32 192 0\n"
"gpr w24 .32 200 0\n"
"gpr w25 .32 208 0\n"
"gpr w26 .32 216 0\n"
"gpr w27 .32 224 0\n"
"gpr w28 .32 232 0\n"
"gpr fp .64 240 0\n"
"gpr lr .64 248 0\n"
"gpr sp .64 256 0\n"
@ -84,6 +115,99 @@ return strdup(
"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"
@ -106,3 +230,4 @@ return strdup(
"drx wcr1 .32 892 0\n"
"drx wvr0 .64 896 0\n"
"drx wvr1 .64 904 0\n");
}

View file

@ -183,38 +183,26 @@ static PTHREAD_ITEM add_thread(RzDebug *dbg, DWORD pid, DWORD tid, HANDLE hThrea
return pthread;
}
static int suspend_thread(HANDLE th, int bits) {
static inline int suspend_thread(HANDLE th) {
int ret;
//if (bits == RZ_SYS_BITS_32) {
if ((ret = SuspendThread(th)) == -1) {
rz_sys_perror("SuspendThread");
}
/*} else {
if ((ret = Wow64SuspendThread (th)) == -1) {
rz_sys_perror ("Wow64SuspendThread");
}
}*/
return ret;
}
static int resume_thread(HANDLE th, int bits) {
static int resume_thread(HANDLE th) {
int ret;
//if (bits == RZ_SYS_BITS_32) {
if ((ret = ResumeThread(th)) == -1) {
rz_sys_perror("ResumeThread");
}
/*} else {
if ((ret = ResumeThread (th)) == -1) {
rz_sys_perror ("Wow64ResumeThread");
}
}*/
return ret;
}
static inline void continue_thread(HANDLE th, int bits) {
static inline void continue_thread(HANDLE th) {
int ret;
do {
ret = resume_thread(th, bits);
ret = resume_thread(th);
} while (ret > 0);
}
@ -244,7 +232,7 @@ static bool is_process_alive(HANDLE ph) {
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;
CONTEXT ctx = { 0 };
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;
}
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;
CONTEXT ctx = { 0 };
// TODO: support various types?
ctx.ContextFlags = CONTEXT_ALL;
ctx.ContextFlags = context_flags;
if (GetThreadContext(th, &ctx)) {
if (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;
}
#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]) {
int nregs = 0, index = 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) {
rz_return_val_if_fail(dbg, NULL);
W32DbgWInst *wrap = dbg->plugin_data;
@ -443,30 +600,20 @@ int w32_reg_read(RzDebug *dbg, int type, ut8 *buf, int size) {
return 0;
}
// Always suspend
if (alive && suspend_thread(th, dbg->bits) == -1) {
if (alive && suspend_thread(th) == -1) {
return 0;
}
size = get_thread_context(th, buf, size, dbg->bits);
size = get_thread_context(th, buf, size, CONTEXT_ALL);
if (showfpu) {
print_fpu_context(th, (CONTEXT *)buf);
}
// Always resume
if (alive && resume_thread(th, dbg->bits) == -1) {
if (alive && resume_thread(th) == -1) {
size = 0;
}
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) {
bool alive = is_thread_alive(dbg, dbg->tid);
if (!alive) {
@ -477,15 +624,15 @@ int w32_reg_write(RzDebug *dbg, int type, const ut8 *buf, int size) {
return 0;
}
// Always suspend
if (suspend_thread(th, dbg->bits) == -1) {
if (suspend_thread(th) == -1) {
return false;
}
if (type == RZ_REG_TYPE_DRX) {
transfer_drx(dbg, buf);
}
bool ret = set_thread_context(th, buf, size, dbg->bits);
bool ret = set_thread_context(th, buf, size);
// Always resume
if (resume_thread(th, dbg->bits) == -1) {
if (resume_thread(th) == -1) {
ret = false;
}
return ret;
@ -529,7 +676,7 @@ int w32_detach(RzDebug *dbg, int pid) {
PTHREAD_ITEM th;
rz_list_foreach (dbg->threads, it, th) {
if (th->bSuspended && !th->bFinished) {
resume_thread(th->hThread, dbg->bits);
resume_thread(th->hThread);
}
}
rz_list_purge(dbg->threads);
@ -778,7 +925,7 @@ int w32_select(RzDebug *dbg, int pid, int tid) {
// Suspend all other threads
rz_list_foreach (dbg->threads, it, th) {
if (!th->bFinished && !th->bSuspended && th->tid != selected) {
suspend_thread(th->hThread, dbg->bits);
suspend_thread(th->hThread);
th->bSuspended = true;
}
}
@ -1022,7 +1169,6 @@ int w32_dbg_wait(RzDebug *dbg, int pid) {
case UNLOAD_DLL_DEBUG_EVENT: {
PLIB_ITEM lib = (PLIB_ITEM)find_library(de.u.UnloadDll.lpBaseOfDll);
if (lib) {
CloseHandle(lib->hFile);
remove_library(lib);
}
ret = RZ_DEBUG_REASON_EXIT_LIB;
@ -1073,6 +1219,11 @@ int w32_dbg_wait(RzDebug *dbg, int pid) {
next_event = 0;
break;
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);
if (is_exception_fatal(de.u.Exception.ExceptionRecord.ExceptionCode)) {
next_event = 0;
@ -1093,7 +1244,7 @@ int w32_dbg_wait(RzDebug *dbg, int pid) {
eprintf("(%d) unknown event: %lu\n", pid, de.dwDebugEventCode);
ret = -1;
}
goto end;
next_event = 0;
}
} while (next_event);
@ -1105,7 +1256,23 @@ int w32_dbg_wait(RzDebug *dbg, int pid) {
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:
if (ret == RZ_DEBUG_REASON_DEAD) {
w32_detach(dbg, dbg->pid);
@ -1116,20 +1283,6 @@ end:
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) {
if (tid != dbg->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);
if (th && th->hThread != INVALID_HANDLE_VALUE && th->bSuspended) {
continue_thread(th->hThread, dbg->bits);
continue_thread(th->hThread);
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);
}
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) {
// pid is not respected for TH32CS_SNAPTHREAD flag
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;
w32_reg_read(dbg, RZ_REG_TYPE_GPR, (ut8 *)&ctx, sizeof(ctx));
// TODO: is needed check context for x32 and x64??
#if _WIN64
pc = ctx.Rip;
#else
pc = ctx.Eip;
#endif
pc = pc_from_context(&ctx);
PTHREAD_ITEM pthread = find_thread(dbg, te.th32ThreadID);
if (pthread) {
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) {
W32DbgWInst *wrap = dbg->plugin_data;
HANDLE sh = w32_CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, pid);
if (sh == INVALID_HANDLE_VALUE) {
rz_sys_perror("CreateToolhelp32Snapshot");
@ -1412,7 +1575,6 @@ RzList *w32_pid_list(RzDebug *dbg, int pid, RzList *list) {
PROCESSENTRY32 pe;
pe.dwSize = sizeof(pe);
if (Process32First(sh, &pe)) {
W32DbgWInst *wrap = dbg->plugin_data;
bool all = pid == 0;
do {
if (all || pe.th32ProcessID == pid || pe.th32ParentProcessID == pid) {

View file

@ -190,4 +190,10 @@ RzDebugInfo *w32_info(RzDebug *dbg, const char *arg);
RzList *w32_pid_list(RzDebug *dbg, int pid, RzList *list);
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

View file

@ -247,13 +247,21 @@ static char *msg_types_arr[] = {
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;
free(win->name);
free(win);
}
static window *__window_from_handle(HANDLE hwnd) {
static window *window_from_handle(HANDLE hwnd) {
rz_return_val_if_fail(hwnd, NULL);
window *win = RZ_NEW0(window);
if (!win) {
@ -277,7 +285,7 @@ static window *__window_from_handle(HANDLE hwnd) {
return win;
}
static RzTable *__create_window_table(void) {
static RzTable *create_window_table(void) {
RzTable *tbl = rz_table_new();
if (!tbl) {
return NULL;
@ -289,7 +297,7 @@ static RzTable *__create_window_table(void) {
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);
char *handle = rz_str_newf("0x%08" PFMT64x "", (ut64)win->h);
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) {
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;
GetCursorPos(&p);
HANDLE hwnd = WindowFromPoint(p);
if (!GetCursorPos(&p)) {
rz_sys_perror("GetCursorPos");
}
HWND hwnd = WindowFromPoint(p);
window *win = NULL;
if (hwnd) {
if (rz_cons_yesno('y', "Try to get the child?")) {
HANDLE child = ChildWindowFromPoint(hwnd, p);
if (rz_cons_yesno('y', "Try to get the child? (Y/n)")) {
HWND child = ChildWindowFromPoint(hwnd, p);
hwnd = child ? child : hwnd;
}
win = __window_from_handle(hwnd);
win = window_from_handle(hwnd);
} else {
eprintf("No window found\n");
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);
return;
}
RzTable *tbl = __create_window_table();
RzTable *tbl = create_window_table();
if (!tbl) {
return;
}
__add_window_to_table(tbl, win);
add_window_to_table(tbl, win);
char *tbl_str = rz_table_tofancystring(tbl);
rz_cons_print(tbl_str);
free(tbl_str);
rz_table_free(tbl);
}
static BOOL CALLBACK __enum_childs(
static BOOL CALLBACK enum_childs(
_In_ HWND hwnd,
_In_ LPARAM lParam) {
RzList *windows = (RzList *)lParam;
window *win = __window_from_handle(hwnd);
window *win = window_from_handle(hwnd);
if (!win) {
return false;
}
@ -344,16 +354,16 @@ static BOOL CALLBACK __enum_childs(
return true;
}
static RzList *__get_windows(RzDebug *dbg) {
RzList *windows = rz_list_newf((RzListFree)__free_window);
static RzList *get_windows(RzDebug *dbg) {
RzList *windows = rz_list_newf((RzListFree)free_window);
HWND hCurWnd = NULL;
do {
hCurWnd = FindWindowEx(NULL, hCurWnd, NULL, NULL);
DWORD dwProcessID = 0;
GetWindowThreadProcessId(hCurWnd, &dwProcessID);
if (dbg->pid == dwProcessID) {
EnumChildWindows(hCurWnd, __enum_childs, (LPARAM)windows);
window *win = __window_from_handle(hCurWnd);
EnumChildWindows(hCurWnd, enum_childs, (LPARAM)windows);
window *win = window_from_handle(hCurWnd);
if (!win) {
rz_list_free(windows);
return NULL;
@ -364,7 +374,7 @@ static RzList *__get_windows(RzDebug *dbg) {
return windows;
}
static ut64 __get_dispatchmessage_offset(RzDebug *dbg) {
static ut64 get_dispatchmessage_offset(RzDebug *dbg) {
RzList *modlist = rz_debug_modules_list(dbg);
RzListIter *it;
RzDebugMap *mod;
@ -397,7 +407,7 @@ static ut64 __get_dispatchmessage_offset(RzDebug *dbg) {
return offset;
}
static void __init_msg_types(Sdb **msg_types) {
static void init_msg_types(Sdb **msg_types) {
*msg_types = sdb_new0();
int i;
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;
if (!msg_types) {
__init_msg_types(&msg_types);
init_msg_types(&msg_types);
}
ut32 found;
const char *type_str = sdb_const_get(msg_types, name, &found);
if (found) {
int type = rz_num_math(NULL, type_str);
int type = rz_num_get(NULL, type_str);
return type;
}
return 0;
}
static void __print_windows(RzDebug *dbg, RzList *windows) {
RzTable *tbl = __create_window_table();
static void print_windows(RzDebug *dbg, RzList *windows) {
RzTable *tbl = create_window_table();
if (!tbl) {
return;
}
RzListIter *it;
window *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);
free(t);
rz_table_free(tbl);
}
RZ_API void rz_w32_print_windows(RzDebug *dbg) {
RzList *windows = __get_windows(dbg);
RzList *windows = get_windows(dbg);
if (windows) {
if (!windows->length) {
dbg->cb_printf("No windows for this process.\n");
return;
}
__print_windows(dbg, windows);
print_windows(dbg, 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);
rz_str_trim(name);
DWORD type = __get_msg_type(name);
DWORD type = get_msg_type(name);
if (!type) {
free(name);
return false;
}
ut64 offset = 0;
if (window_id) {
RzList *windows = __get_windows(dbg);
RzList *windows = get_windows(dbg);
if (windows && !windows->length) {
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) {
dbg->cb_printf("Window not found, try these:\n");
__print_windows(dbg, windows);
print_windows(dbg, windows);
}
rz_list_free(windows);
} else {
offset = __get_dispatchmessage_offset(dbg);
offset = get_dispatchmessage_offset(dbg);
}
if (!offset) {
free(name);
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;
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 {
char *reg;
if (!strcmp(dbg->arch, "arm")) {
if (dbg->bits == RZ_SYS_BITS_64) {
reg = "x0";
} else {
reg = "r0";
}
} else {
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);
}
dbg->corebind.cmdf(dbg->corebind.core, "\"dbC %s @ 0x%" PFMT64x "\"", cond, offset);
b->cond = rz_str_newf("?q `ae %lu,%s,%d,+,[4],-`", type, reg, dbg->bits);
}
free(name);
return true;
}

View file

@ -3,14 +3,6 @@
#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 void rz_w32_identify_window(void);
RZ_API void rz_w32_print_windows(RzDebug *dbg);

View file

@ -497,16 +497,26 @@ static inline void *rz_new_copy(int size, void *data) {
#endif
#else
#ifdef _MSC_VER
#ifdef _WIN64
#if defined(_M_X64) || defined(_M_AMD64)
#define RZ_SYS_ARCH "x86"
#define RZ_SYS_BITS (RZ_SYS_BITS_32 | RZ_SYS_BITS_64)
#define RZ_SYS_ENDIAN 0
#define __x86_64__ 1
#else
#elif defined(_M_IX86)
#define RZ_SYS_ARCH "x86"
#define RZ_SYS_BITS (RZ_SYS_BITS_32)
#define __i386__ 1
#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
#else
#define RZ_SYS_ARCH "unknown"

View 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'