From 896cb3d36665afbb113b410325a61f8e95ec300c Mon Sep 17 00:00:00 2001 From: midipix Date: Sun, 22 Sep 2019 06:11:36 +0000 Subject: mgdb: winnt_exception_filters[]: initial implementation and integration. --- overlay/mgdb/gdb/winnt-nat.c | 126 ++++++++++++++++++++++++++++++++++++++++++- overlay/mgdb/gdb/winnt-nat.h | 10 ++++ 2 files changed, 134 insertions(+), 2 deletions(-) diff --git a/overlay/mgdb/gdb/winnt-nat.c b/overlay/mgdb/gdb/winnt-nat.c index 7c456d6..4a27c40 100644 --- a/overlay/mgdb/gdb/winnt-nat.c +++ b/overlay/mgdb/gdb/winnt-nat.c @@ -38,11 +38,19 @@ #define winnt_perror(msg,pid) \ error("%s(): %s (pid %d).",__FUNCTION__,msg,pid) +#define WINNT_W32_EXCEPTION_MASK ((0xe << 28) | ('m' << 16) | ('s' << 8) | ('c' << 0)) + static size_t pcnt; static winnt_process * plist; static char * outbuf; static struct pe_driver_ctx * pe_dctx; +static struct winnt_exception_filter winnt_exception_filters[] = { + {WINNT_W32_EXCEPTION_MASK, WINNT_EXCEPTION_FIRST_CHANCE, 0}, + {0, WINNT_EXCEPTION_FIRST_CHANCE, "sysfer.dll"}, + {0, 0, 0}, +}; + static winnt_process * winnt_plist_expand (void) { struct winnt_process * pnew; @@ -775,6 +783,104 @@ static void winnt_detach (struct target_ops * t, const char * args, int from_tty exec_file_clear(from_tty); } +static int winnt_exception_filter_match_code( + struct __dbg_event * event, + struct winnt_exception_filter * filter) +{ + if (!filter->exception_code) + return 1; + + if (!event->exception_record) + return 0; + + if (filter->exception_code != event->exception_record->exception_code) + return 0; + + if (filter->exception_flags & WINNT_EXCEPTION_FIRST_CHANCE) + if (event->exception_priority) + return 1; + + if (filter->exception_flags & WINNT_EXCEPTION_SECOND_CHANCE) + if (!event->exception_priority) + return 1; + + return 0; +} + +static int winnt_exception_filter_match_module( + struct __dbg_event * event, + struct winnt_exception_filter * filter, + struct winnt_process* pidinfo) +{ + struct __dbg_module_info * module; + struct __dbg_module_info * module_cap; + struct winnt_thread * thread; + struct pe_unit_ctx * uctx; + struct pe_meta_sec_hdr * sechdr; + int secidx; + char * addr; + char * mark; + char * text; + char * text_cap; + + thread = winnt_get_thread(pidinfo,event->systid); + addr = (char *)thread->regctx.uc_rip; + module_cap = &pidinfo->modules[pidinfo->nmodules]; + + for (module=pidinfo->modules; modulemodule_ctx)) { + secidx = pe_get_named_section_index( + uctx->meta,".text"); + + if (secidx >= 0) { + mark = 0; + sechdr = &uctx->meta->m_sectbl[secidx]; + text = (char *)module->module_base; + text += sechdr->sh_virtual_addr; + text_cap = text + sechdr->sh_virtual_size; + + if ((addr >= text) && (addr < text_cap)) + mark = strrchr(module->module_name,'/'); + + if (mark && !filter->exception_module) + return 1; + + if (mark && filter->exception_module) + if (!(strcmp(++mark,filter->exception_module))) + return 1; + } + } + } + + return 0; +} + +static int winnt_exception_filter_match(struct __dbg_event * event) +{ + struct winnt_process * pidinfo; + struct winnt_exception_filter * filter = winnt_exception_filters; + + switch (event->evttype) { + case __DBG_STATE_EXCEPTION: + case __DBG_STATE_BREAKPOINT: + case __DBG_STATE_SINGLE_STEP: + break; + + default: + return 0; + } + + if (!(pidinfo = winnt_process_record(event->syspid))) + return 0; + + for (; filter->exception_flags; filter++) + if (winnt_exception_filter_match_code(event,filter)) + if (winnt_exception_filter_match_module(event,filter,pidinfo)) + return 1; + + return 0; +} + static struct __dbg_event * winnt_wait_event(ptid_t ptid) { struct __dbg_event event; @@ -850,11 +956,27 @@ static ptid_t winnt_wait( int pfd; struct __dbg_event * event; struct winnt_process * process; + int fskip; + int eresponse; target_terminal_ours(); - if (!(event = winnt_wait_event(ptid))) - return null_ptid; + do { + if (!(event = winnt_wait_event(ptid))) + return null_ptid; + + if ((fskip = winnt_exception_filter_match(event))) { + if (!(process = winnt_process_record(event->syspid))) + return null_ptid; + + if (event->exception_priority) + eresponse = __DBG_RESPONSE_EXCEPTION_NOT_HANDLED; + else + eresponse = __DBG_RESPONSE_CONTINUE; + + winnt_respond(process->pfd,event,eresponse); + } + } while (fskip); if (!(process = winnt_process_record(event->syspid))) return null_ptid; diff --git a/overlay/mgdb/gdb/winnt-nat.h b/overlay/mgdb/gdb/winnt-nat.h index 473c2a9..593a140 100644 --- a/overlay/mgdb/gdb/winnt-nat.h +++ b/overlay/mgdb/gdb/winnt-nat.h @@ -18,6 +18,10 @@ #define WINNT_THREAD_CONTEXT_READY (0X0) #define WINNT_THREAD_CONTEXT_DIRTY (0Xffffffff) +#define WINNT_EXCEPTION_FIRST_CHANCE 0x01 +#define WINNT_EXCEPTION_SECOND_CHANCE 0x02 +#define WINNT_EXCEPTION_ALL 0xffffffff + struct regcache; struct winnt_process; @@ -46,6 +50,12 @@ struct winnt_thread { mcontext_t regctx; }; +struct winnt_exception_filter { + uint32_t exception_code; + uint32_t exception_flags; + const char * exception_module; +}; + void amd64_winnt_fetch_registers( struct regcache *, int regnum, struct winnt_thread *); -- cgit v1.2.3