9 _In_ REFIID InterfaceId,
13 _In_ PCWSTR RemoteOptions,
14 _In_ REFIID InterfaceId,
20 #define WINDBGURI "windbg://"
26 DWORD lastExecutionStatus;
27 PDEBUG_CLIENT5 dbgClient;
28 PDEBUG_CONTROL4 dbgCtrl;
29 PDEBUG_DATA_SPACES4 dbgData;
30 PDEBUG_REGISTERS2 dbgReg;
31 PDEBUG_SYSTEM_OBJECTS4 dbgSysObj;
32 PDEBUG_SYMBOLS3 dbgSymbols;
33 PDEBUG_ADVANCED3 dbgAdvanced;
36 #define THISCALL(dbginterface, function, ...) dbginterface->lpVtbl->function(dbginterface, __VA_ARGS__)
37 #define ITHISCALL(dbginterface, function, ...) THISCALL(idbg->dbginterface, function, __VA_ARGS__)
39 #define DECLARE_CALLBACKS_IMPL(Type, IFace) \
40 typedef struct IFace##_impl { \
42 DbgEngContext *m_idbg; \
44 } Type##_IMPL, *P##Type##_IMPL;
46 #define INIT_IUNKNOWN_CALLBACKS(IFace, lpVtbl) \
47 lpVtbl->QueryInterface = IFace##_QueryInterface_impl; \
48 lpVtbl->AddRef = IFace##_AddRef_impl; \
49 lpVtbl->Release = IFace##_Release_impl
51 #define DECLARE_NEW(IFace, IVtbl) \
52 static P##IFace IFace##_impl_new( \
53 DbgEngContext *idbg) { \
57 P##IFace##_IMPL callbacks = RZ_NEW(IFace##_IMPL); \
61 callbacks->lpVtbl = RZ_NEW(IVtbl); \
62 if (!callbacks->lpVtbl) { \
66 IFace##_vtbl_init((P##IFace)callbacks); \
67 callbacks->m_idbg = idbg; \
68 callbacks->m_ref = 1; \
69 return (P##IFace)callbacks; \
72 #define DECLARE_QUERYINTERFACE(IFace, IFaceIID) \
73 static STDMETHODIMP IFace##_QueryInterface_impl( \
75 _In_ REFIID InterfaceId, \
76 _Out_ PVOID *Interface) { \
78 if (IsEqualIID(InterfaceId, &IID_IUnknown) || \
79 IsEqualIID(InterfaceId, &IFaceIID)) { \
81 THISCALL(This, AddRef); \
84 return E_NOINTERFACE; \
88 #define DECLARE_ADDREF(IFace) \
89 static STDMETHODIMP_(ULONG) IFace##_AddRef_impl( \
91 P##IFace##_IMPL impl = (P##IFace##_IMPL)This; \
92 return InterlockedIncrement(&impl->m_ref); \
95 #define DECLARE_RELEASE(IFace) \
96 static STDMETHODIMP_(ULONG) IFace##_Release_impl( \
98 P##IFace##_IMPL impl = (P##IFace##_IMPL)This; \
99 LONG ret = InterlockedDecrement(&impl->m_ref); \
101 free(This->lpVtbl); \
112 *Mask = DEBUG_EVENT_BREAKPOINT | DEBUG_EVENT_CREATE_PROCESS;
113 *Mask |= DEBUG_EVENT_EXCEPTION | DEBUG_EVENT_SYSTEM_ERROR;
114 *Mask |= DEBUG_EVENT_EXIT_PROCESS;
119 PDEBUG_EVENT_CALLBACKS This,
120 ULONG64 ImageFileHandle,
128 ULONG64 InitialThreadHandle,
129 ULONG64 ThreadDataOffset,
130 ULONG64 StartOffset) {
131 PDEBUG_EVENT_CALLBACKS_IMPL impl = (PDEBUG_EVENT_CALLBACKS_IMPL)This;
132 impl->m_idbg->processBase = BaseOffset;
133 return DEBUG_STATUS_BREAK;
136 static STDMETHODIMP
__breakpoint_cb(PDEBUG_EVENT_CALLBACKS This, PDEBUG_BREAKPOINT Bp) {
137 return DEBUG_STATUS_BREAK;
140 static STDMETHODIMP
__exception_cb(PDEBUG_EVENT_CALLBACKS This, PEXCEPTION_RECORD64 Exception,
ULONG FirstChance) {
141 return DEBUG_STATUS_BREAK;
145 return DEBUG_STATUS_BREAK;
149 return DEBUG_STATUS_BREAK;
154 PDEBUG_INPUT_CALLBACKS_IMPL impl = (PDEBUG_INPUT_CALLBACKS_IMPL)This;
206 DECLARE_NEW(DEBUG_EVENT_CALLBACKS, IDebugEventCallbacksVtbl)
207 DECLARE_NEW(DEBUG_INPUT_CALLBACKS, IDebugInputCallbacksVtbl)
208 DECLARE_NEW(DEBUG_OUTPUT_CALLBACKS, IDebugOutputCallbacksVtbl)
213 ITHISCALL(I, Release); \
230 THISCALL(I, Release);
235 PDEBUG_EVENT_CALLBACKS event_callbacks = DEBUG_EVENT_CALLBACKS_impl_new(idbg);
236 PDEBUG_INPUT_CALLBACKS input_callbacks = DEBUG_INPUT_CALLBACKS_impl_new(idbg);
237 PDEBUG_OUTPUT_CALLBACKS output_callbacks = DEBUG_OUTPUT_CALLBACKS_impl_new(idbg);
239 if (!event_callbacks || !output_callbacks || !event_callbacks) {
246 if (FAILED(
ITHISCALL(dbgClient, SetEventCallbacks, event_callbacks)) ||
247 FAILED(
ITHISCALL(dbgClient, SetInputCallbacks, input_callbacks)) ||
248 FAILED(
ITHISCALL(dbgClient, SetOutputCallbacks, output_callbacks))) {
348 char *ext_path =
rz_sys_getenv(
"_NT_DEBUGGER_EXTENSION_PATH");
351 char *
s = strtok(ext_path,
";");
353 PWCHAR dir = rz_utf8_to_utf16(
s);
354 SetDllDirectoryW(dir);
356 h = LoadLibrary(TEXT(
"dbgeng.dll"));
357 }
while (!
h && (
s = strtok(
NULL,
";")));
358 SetDllDirectoryW(
NULL);
362 h = LoadLibrary(TEXT(
"dbgeng.dll"));
413 args += strlen(
"-remote") + 1;
421 args += strlen(
"-premote") + 1;
432 ITHISCALL(dbgCtrl, AddEngineOptions, DEBUG_ENGOPT_INITIAL_BREAK);
433 ITHISCALL(dbgCtrl, AddEngineOptions, DEBUG_ENGOPT_FINAL_BREAK);
434 ITHISCALL(dbgCtrl, AddEngineOptions, DEBUG_ENGOPT_ALLOW_READ_ONLY_BREAKPOINTS);
435 ITHISCALL(dbgCtrl, SetCodeLevel, DEBUG_LEVEL_ASSEMBLY);
438 const size_t argv_sz =
sizeof(
char *) * ((
size_t)argc + 2);
446 memmove(
argv + 1,
argv, argv_sz -
sizeof(
char *));
450 bool image_path_set =
false, symbol_path_set =
false;
452 DWORD spawn_options = DEBUG_ONLY_THIS_PROCESS | CREATE_NEW_CONSOLE;
453 DWORD attach_options = DEBUG_ATTACH_DEFAULT;
464 ITHISCALL(dbgCtrl, AddEngineOptions, DEBUG_ENGOPT_INITIAL_MODULE_BREAK);
467 ITHISCALL(dbgCtrl, RemoveEngineOptions, DEBUG_ENGOPT_INITIAL_BREAK);
470 ITHISCALL(dbgCtrl, RemoveEngineOptions, DEBUG_ENGOPT_FINAL_BREAK);
473 if (strcmp(opt.
arg,
"d")) {
474 spawn_options |= DEBUG_CREATE_PROCESS_NO_DEBUG_HEAP;
479 image_path_set =
true;
482 if (strcmp(opt.
arg,
"l")) {
484 }
else if (strcmp(opt.
arg,
"qm")) {
485 ITHISCALL(dbgCtrl, AddEngineOptions, DEBUG_ENGOPT_KD_QUIET_MODE);
492 spawn_options &= ~DEBUG_ONLY_THIS_PROCESS;
493 spawn_options |= DEBUG_PROCESS;
500 if (strcmp(opt.
arg,
"b")) {
501 attach_options |= DEBUG_ATTACH_INVASIVE_NO_INITIAL_BREAK;
502 }
else if (strcmp(opt.
arg,
"e")) {
503 attach_options |= DEBUG_ATTACH_EXISTING;
504 }
else if (strcmp(opt.
arg,
"v")) {
505 attach_options |= DEBUG_ATTACH_NONINVASIVE;
510 symbol_path_set =
true;
521 if (!symbol_path_set) {
526 char *sympath =
rz_str_newf(
"cache*;srv*%s*%s", store,
s);
527 ITHISCALL(dbgSymbols, SetSymbolPath, sympath);
531 if (!image_path_set) {
540 hr =
ITHISCALL(dbgClient, CreateProcess, 0ULL,
cmd, spawn_options);
543 eprintf(
"Missing argument for local spawn\n");
547 hr =
ITHISCALL(dbgClient, AttachProcess, 0ULL,
pid, attach_options);
550 if (
ITHISCALL(dbgClient, IsKernelDebuggerEnabled) == S_FALSE) {
551 eprintf(
"Live Kernel debug not available. Set the /debug boot switch to enable it\n");
553 hr =
ITHISCALL(dbgClient, AttachKernel, DEBUG_ATTACH_LOCAL_KERNEL,
args);
560 hr =
ITHISCALL(dbgClient, AttachKernel, DEBUG_ATTACH_KERNEL_CONNECTION,
args);
568 ITHISCALL(dbgCtrl, WaitForEvent, DEBUG_WAIT_DEFAULT, INFINITE);
570 ITHISCALL(dbgCtrl, Execute, DEBUG_OUTCTL_ALL_CLIENTS,
command, DEBUG_EXECUTE_DEFAULT);
588 RzCore *core =
fd->io->corebind.core;
590 ITHISCALL(dbgClient, EndSession, DEBUG_END_DISCONNECT);
594 ITHISCALL(dbgClient, EndSession, DEBUG_END_ACTIVE_DETACH);
620 ULONG bytesRead = 0ULL;
624 if (SUCCEEDED(
ITHISCALL(dbgData, GetValidRegionVirtual, io->
off,
count, &ValidBase, &ValidSize))) {
625 if (ValidSize && ValidBase < io->
off +
count) {
626 const ULONG64 skipped = ValidBase - io->
off;
628 ITHISCALL(dbgData, ReadVirtual, ValidBase, (
PVOID)(
buf + skipped), toRead, &bytesRead);
629 bytesRead += skipped;
638 ULONG bytesWritten = 0ULL;
645 ULONG Id = 0, Class, Qualifier;
646 if (SUCCEEDED(
ITHISCALL(dbgCtrl, GetDebuggeeType, &Class, &Qualifier))) {
647 if (Class == DEBUG_CLASS_KERNEL) {
648 ITHISCALL(dbgSysObj, GetCurrentProcessId, &Id);
650 ITHISCALL(dbgSysObj, GetCurrentProcessSystemId, &Id);
658 ULONG Id = 0, Class, Qualifier;
659 if (SUCCEEDED(
ITHISCALL(dbgCtrl, GetDebuggeeType, &Class, &Qualifier))) {
660 if (Class == DEBUG_CLASS_KERNEL) {
661 ITHISCALL(dbgSysObj, GetCurrentThreadId, &Id);
663 ITHISCALL(dbgSysObj, GetCurrentThreadSystemId, &Id);
680 ITHISCALL(dbgCtrl, Execute, DEBUG_OUTCTL_ALL_CLIENTS,
cmd, DEBUG_EXECUTE_DEFAULT);
686 .desc =
"WinDBG (DbgEng.dll) based io plugin for Windows",
703 #ifndef RZ_PLUGIN_INCORE
struct java_interface_t Interface
static static fork const void static count static fd const char const char static newpath const char static path const char path
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags cmd
RZ_API const char * rz_line_readline(void)
RZ_API void Ht_() free(HtName_(Ht) *ht)
#define DECLARE_ADDREF(IFace)
static bool cur_dbg_plugin_is_windbg(RzDebug *dbg)
static DebugCreate_t w32_DebugCreate
static int windbg_read(RzIO *io, RzIODesc *fd, ut8 *buf, int count)
static ut64 windbg_lseek(RzIO *io, RzIODesc *fd, ut64 offset, int whence)
#define INIT_IUNKNOWN_CALLBACKS(IFace, lpVtbl)
static DbgEngContext * create_context(void)
static int windbg_gettid(RzIODesc *fd)
static void DEBUG_EVENT_CALLBACKS_vtbl_init(PDEBUG_EVENT_CALLBACKS callbacks)
#define ITHISCALL(dbginterface, function,...)
#define DECLARE_NEW(IFace, IVtbl)
static void DEBUG_OUTPUT_CALLBACKS_vtbl_init(PDEBUG_OUTPUT_CALLBACKS callbacks)
RZ_API RzLibStruct rizin_plugin
static STDMETHODIMP __breakpoint_cb(PDEBUG_EVENT_CALLBACKS This, PDEBUG_BREAKPOINT Bp)
static STDMETHODIMP __exception_cb(PDEBUG_EVENT_CALLBACKS This, PEXCEPTION_RECORD64 Exception, ULONG FirstChance)
static STDMETHODIMP __output_cb(PDEBUG_OUTPUT_CALLBACKS This, ULONG Mask, PCSTR Text)
#define DECLARE_RELEASE(IFace)
static bool init_callbacks(DbgEngContext *idbg)
static DebugConnectWide_t w32_DebugConnectWide
static int windbg_write(RzIO *io, RzIODesc *fd, const ut8 *buf, int count)
static STDMETHODIMP __interest_mask(PDEBUG_EVENT_CALLBACKS This, PULONG Mask)
static STDMETHODIMP __input_cb(PDEBUG_INPUT_CALLBACKS This, ULONG BufferSize)
#define DECLARE_CALLBACKS_IMPL(Type, IFace)
RzIOPlugin rz_io_plugin_windbg
static RzIODesc * windbg_open(RzIO *io, const char *uri, int perm, int mode)
static int windbg_close(RzIODesc *fd)
static int windbg_init(void)
HRESULT(__stdcall * DebugConnectWide_t)(_In_ PCWSTR RemoteOptions, _In_ REFIID InterfaceId, _Out_ PVOID *Interface)
static bool windbg_getbase(RzIODesc *fd, ut64 *base)
static bool windbg_check(RzIO *io, const char *uri, bool many)
static void __free_context(DbgEngContext *idbg)
#define DECLARE_QUERYINTERFACE(IFace, IFaceIID)
static STDMETHODIMP __system_error_cb(PDEBUG_EVENT_CALLBACKS This, ULONG Error, ULONG Level)
static STDMETHODIMP __input_end_cb(PDEBUG_INPUT_CALLBACKS This)
static void DEBUG_INPUT_CALLBACKS_vtbl_init(PDEBUG_INPUT_CALLBACKS callbacks)
static STDMETHODIMP __createprocess_cb(PDEBUG_EVENT_CALLBACKS This, ULONG64 ImageFileHandle, ULONG64 Handle, ULONG64 BaseOffset, ULONG ModuleSize, PCSTR ModuleName, PCSTR ImageName, ULONG CheckSum, ULONG TimeDateStamp, ULONG64 InitialThreadHandle, ULONG64 ThreadDataOffset, ULONG64 StartOffset)
static int windbg_getpid(RzIODesc *fd)
static STDMETHODIMP __exit_process_cb(PDEBUG_EVENT_CALLBACKS This, ULONG ExitCode)
static char * windbg_system(RzIO *io, RzIODesc *fd, const char *cmd)
static DbgEngContext * create_remote_context(const char *opts)
HRESULT(__stdcall * DebugCreate_t)(_In_ REFIID InterfaceId, _Out_ PVOID *Interface)
void * realloc(void *ptr, size_t size)
RZ_API void rz_line_set_prompt(const char *prompt)
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc pid
static static fork const void static count static fd const char const char static newpath char char argv
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\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" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
RZ_API void rz_getopt_init(RzGetopt *go, int argc, const char **argv, const char *ostr)
RZ_API int rz_getopt_next(RzGetopt *opt)
RZ_API RzIODesc * rz_io_desc_new(RzIO *io, RzIOPlugin *plugin, const char *uri, int flags, int mode, void *data)
#define RZ_STR_ISNOTEMPTY(x)
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API char * rz_str_ndup(RZ_NULLABLE const char *ptr, int len)
Create new copy of string ptr limited to size len.
RZ_API char * rz_str_format_msvc_argv(size_t argc, const char **argv)
#define RZ_STR_ISEMPTY(x)
RZ_API bool rz_str_isnumber(const char *str)
RZ_API int rz_str_replace_ch(char *s, char a, char b, bool g)
RZ_API char ** rz_str_argv(const char *str, int *_argc)
RZ_API bool rz_str_startswith(RZ_NONNULL const char *str, RZ_NONNULL const char *needle)
Checks if a string starts with a specifc sequence of characters (case sensitive)
RZ_API void rz_str_argv_free(char **argv)
RZ_API char * rz_sys_getenv(const char *key)
Get the value of an environment variable named key or NULL if none exists.
PDEBUG_SYSTEM_OBJECTS4 dbgSysObj
PDEBUG_SYMBOLS3 dbgSymbols
PDEBUG_DATA_SPACES4 dbgData
PDEBUG_ADVANCED3 dbgAdvanced
struct rz_debug_plugin_t * cur
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static const z80_opcode fd[]