diff --git a/binrz/rz-test/rz_test.h b/binrz/rz-test/rz_test.h index 6d087b3f839..747fb50acd4 100644 --- a/binrz/rz-test/rz_test.h +++ b/binrz/rz-test/rz_test.h @@ -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 diff --git a/librz/core/cconfig.c b/librz/core/cconfig.c index 91d3f45f877..fe546e9dff5 100644 --- a/librz/core/cconfig.c +++ b/librz/core/cconfig.c @@ -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)"); diff --git a/librz/core/cdebug.c b/librz/core/cdebug.c index 41cd7a7d3f6..bf9e810b8cb 100644 --- a/librz/core/cdebug.c +++ b/librz/core/cdebug.c @@ -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) { diff --git a/librz/core/cmd/cmd_debug.c b/librz/core/cmd/cmd_debug.c index 457a32583a2..44d3a5a49e7 100644 --- a/librz/core/cmd/cmd_debug.c +++ b/librz/core/cmd/cmd_debug.c @@ -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); } } diff --git a/librz/core/core_private.h b/librz/core/core_private.h index 623fe5d09d8..0fc526dc8a8 100644 --- a/librz/core/core_private.h +++ b/librz/core/core_private.h @@ -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); diff --git a/librz/core/tui/visual.c b/librz/core/tui/visual.c index f2e44bda6c1..7cd4944c2de 100644 --- a/librz/core/tui/visual.c +++ b/librz/core/tui/visual.c @@ -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; } } diff --git a/librz/debug/debug.c b/librz/debug/debug.c index 8d8fac95ca7..d2b4796af71 100644 --- a/librz/debug/debug.c +++ b/librz/debug/debug.c @@ -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: - 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; + 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; + } 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; diff --git a/librz/debug/p/debug_native.c b/librz/debug/p/debug_native.c index b1fd02e9b38..4a3c4cdd4a0 100644 --- a/librz/debug/p/debug_native.c +++ b/librz/debug/p/debug_native.c @@ -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, }; diff --git a/librz/debug/p/debug_windbg.c b/librz/debug/p/debug_windbg.c index 8cb228446e9..b2e998a47af 100644 --- a/librz/debug/p/debug_windbg.c +++ b/librz/debug/p/debug_windbg.c @@ -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 { diff --git a/librz/debug/p/native/bt.c b/librz/debug/p/native/bt.c index 555857675b4..b17dcb574bb 100644 --- a/librz/debug/p/native/bt.c +++ b/librz/debug/p/native/bt.c @@ -3,6 +3,9 @@ #include +#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 (dbg->bits == RZ_SYS_BITS_64) { - cb = backtrace_x86_64_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 { - cb = backtrace_x86_32_analysis; + 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; diff --git a/librz/debug/p/native/bt/windows-all.c b/librz/debug/p/native/bt/windows-all.c new file mode 100644 index 00000000000..d8e2e0502e1 --- /dev/null +++ b/librz/debug/p/native/bt/windows-all.c @@ -0,0 +1,120 @@ +// SPDX-FileCopyrightText: 2021 GustavoLCR +// SPDX-License-Identifier: LGPL-3.0-only + +#include +#include + +#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 diff --git a/librz/debug/p/native/linux/reg/linux-arm64.h b/librz/debug/p/native/linux/reg/linux-arm64.h index b3a064be9e4..3ab886612a6 100644 --- a/librz/debug/p/native/linux/reg/linux-arm64.h +++ b/librz/debug/p/native/linux/reg/linux-arm64.h @@ -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" diff --git a/librz/debug/p/native/reg.c b/librz/debug/p/native/reg.c index fb32374967a..99b468b464a 100644 --- a/librz/debug/p/native/reg.c +++ b/librz/debug/p/native/reg.c @@ -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__) /* __.--..__ \-/-/-/ _ __ _.--' _.--' diff --git a/librz/debug/p/native/reg/windows-arm.h b/librz/debug/p/native/reg/windows-arm.h index 324824de8c4..d0cdc09f798 100644 --- a/librz/debug/p/native/reg/windows-arm.h +++ b/librz/debug/p/native/reg/windows-arm.h @@ -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"); diff --git a/librz/debug/p/native/reg/windows-arm64.h b/librz/debug/p/native/reg/windows-arm64.h index ed7a61d5632..d95913099f5 100644 --- a/librz/debug/p/native/reg/windows-arm64.h +++ b/librz/debug/p/native/reg/windows-arm64.h @@ -1,108 +1,233 @@ // SPDX-FileCopyrightText: 2020 GustavoLCR // SPDX-License-Identifier: LGPL-3.0-only -return strdup( - "=PC pc\n" - "=SP sp\n" - "=BP fp\n" - "=A0 x0\n" - "=A1 x1\n" - "=A2 x2\n" - "=A3 x3\n" - "=ZF zf\n" - "=SF nf\n" - "=OF vf\n" - "=CF cf\n" - "=SN x16\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 x0 .64 8 0\n" - "gpr x1 .64 16 0\n" - "gpr x2 .64 24 0\n" - "gpr x3 .64 32 0\n" - "gpr x4 .64 40 0\n" - "gpr x5 .64 48 0\n" - "gpr x6 .64 56 0\n" - "gpr x7 .64 64 0\n" - "gpr x8 .64 72 0\n" - "gpr x9 .64 80 0\n" - "gpr x10 .64 88 0\n" - "gpr x11 .64 96 0\n" - "gpr x12 .64 104 0\n" - "gpr x13 .64 112 0\n" - "gpr x14 .64 120 0\n" - "gpr x15 .64 128 0\n" - "gpr x16 .64 136 0\n" - "gpr x17 .64 144 0\n" - "gpr x18 .64 152 0\n" - "gpr x19 .64 160 0\n" - "gpr x20 .64 168 0\n" - "gpr x21 .64 176 0\n" - "gpr x22 .64 184 0\n" - "gpr x23 .64 192 0\n" - "gpr x24 .64 200 0\n" - "gpr x25 .64 208 0\n" - "gpr x26 .64 216 0\n" - "gpr x27 .64 224 0\n" - "gpr x28 .64 232 0\n" - "gpr fp .64 240 0\n" - "gpr lr .64 248 0\n" - "gpr sp .64 256 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"); +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" + "=A3 x3\n" + "=ZF zf\n" + "=SF nf\n" + "=OF vf\n" + "=CF cf\n" + "=SN x16\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 x0 .64 8 0\n" + "gpr x1 .64 16 0\n" + "gpr x2 .64 24 0\n" + "gpr x3 .64 32 0\n" + "gpr x4 .64 40 0\n" + "gpr x5 .64 48 0\n" + "gpr x6 .64 56 0\n" + "gpr x7 .64 64 0\n" + "gpr x8 .64 72 0\n" + "gpr x9 .64 80 0\n" + "gpr x10 .64 88 0\n" + "gpr x11 .64 96 0\n" + "gpr x12 .64 104 0\n" + "gpr x13 .64 112 0\n" + "gpr x14 .64 120 0\n" + "gpr x15 .64 128 0\n" + "gpr x16 .64 136 0\n" + "gpr x17 .64 144 0\n" + "gpr x18 .64 152 0\n" + "gpr x19 .64 160 0\n" + "gpr x20 .64 168 0\n" + "gpr x21 .64 176 0\n" + "gpr x22 .64 184 0\n" + "gpr x23 .64 192 0\n" + "gpr x24 .64 200 0\n" + "gpr x25 .64 208 0\n" + "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" + "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" + "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"); +} \ No newline at end of file diff --git a/librz/debug/p/native/windows/windows_debug.c b/librz/debug/p/native/windows/windows_debug.c index 47d3a6d9fe7..a93db84cda5 100644 --- a/librz/debug/p/native/windows/windows_debug.c +++ b/librz/debug/p/native/windows/windows_debug.c @@ -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 @@ int w32_dbg_wait(RzDebug *dbg, int pid) { 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) { diff --git a/librz/debug/p/native/windows/windows_debug.h b/librz/debug/p/native/windows/windows_debug.h index 57b0ad9be07..427d153c351 100644 --- a/librz/debug/p/native/windows/windows_debug.h +++ b/librz/debug/p/native/windows/windows_debug.h @@ -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 \ No newline at end of file diff --git a/librz/debug/p/native/windows/windows_message.c b/librz/debug/p/native/windows/windows_message.c index 6519e78ff06..087dcd91a79 100644 --- a/librz/debug/p/native/windows/windows_message.c +++ b/librz/debug/p/native/windows/windows_message.c @@ -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 (dbg->bits == RZ_SYS_BITS_64) { - reg = "rcx"; + if (!strcmp(dbg->arch, "arm")) { + if (dbg->bits == RZ_SYS_BITS_64) { + reg = "x0"; + } else { + reg = "r0"; + } } 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); return true; } diff --git a/librz/debug/p/native/windows/windows_message.h b/librz/debug/p/native/windows/windows_message.h index bade61ac7db..bf1e321ea6c 100644 --- a/librz/debug/p/native/windows/windows_message.h +++ b/librz/debug/p/native/windows/windows_message.h @@ -3,14 +3,6 @@ #include -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); diff --git a/librz/include/rz_types.h b/librz/include/rz_types.h index 7197681ffd4..33038b61cd2 100644 --- a/librz/include/rz_types.h +++ b/librz/include/rz_types.h @@ -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 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" diff --git a/sys/cross-arm64-windows.txt b/sys/cross-arm64-windows.txt new file mode 100644 index 00000000000..debb39607ab --- /dev/null +++ b/sys/cross-arm64-windows.txt @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2021 GustavoLCR +# 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'