summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormidipix <writeonce@midipix.org>2019-09-22 06:11:36 +0000
committermidipix <writeonce@midipix.org>2019-09-22 06:11:36 +0000
commit896cb3d36665afbb113b410325a61f8e95ec300c (patch)
tree7d953ff0c8544f194c82625b013e1342dcab512c
parent4548310fcd708bf74ab29c5dc3de40a6c57f0865 (diff)
downloadchainport-896cb3d36665afbb113b410325a61f8e95ec300c.tar.bz2
chainport-896cb3d36665afbb113b410325a61f8e95ec300c.tar.xz
mgdb: winnt_exception_filters[]: initial implementation and integration.
-rw-r--r--overlay/mgdb/gdb/winnt-nat.c126
-rw-r--r--overlay/mgdb/gdb/winnt-nat.h10
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; module<module_cap; module++) {
+ if ((uctx = (struct pe_unit_ctx *)module->module_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 *);