rizin/librz/debug/p/native/bt/windows-all.c
GustavoLCR 53a7694631
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
2021-11-24 20:13:42 +08:00

120 lines
3.3 KiB
C

// 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