#include "captive/mm.h" /* for captive_mmap_map_get() */
#include <sys/mman.h>
#include "reactos/internal/mm.h" /* for PAGE_SIZE */
-
-
-static greg_t val_exceptionstack_top=0;
-
+#include "captive/ldr.h" /* for captive_ModuleList_patchpoint_find() */
+#include "captive/ldr_exports.h" /* for struct captive_ModuleList_patchpoint */
/**
*
* Returns whether some exception occured (FIXME: in what scope?).
* Exception handlers are registered from W32 binary in stack frames stored in "fs:[0x00000000]"
- * value which gets mapped by libcaptive/ps/signal.c to #val_exceptionstack_top
+ * value which gets mapped by libcaptive/ps/signal.c to #fs_KPCR_ExceptionList
* variable.
*
* libcaptive currently does not raise any exceptions therefore this call always returns value %0.
}
+/* =='KeGetCurrentKPCR()->ExceptionList';
+ * libcaptive has reduced KPCR (named 'captive_KPCR') which
+ * does not contain this field
+ */
+static greg_t fs_KPCR_ExceptionList=(greg_t)-1;
+
static gboolean instr_mov_greg_to_fsmem(int greg,const void *fsmem,struct ucontext *ucontext)
{
- if (fsmem==0x00000000) { /* exception stack top pointer */
+ if (fsmem==(const void *)0x00000000) { /* exception stack top pointer */
/* moving from %esp is required to pass! */
- val_exceptionstack_top=ucontext->uc_mcontext.gregs[greg];
+ fs_KPCR_ExceptionList=ucontext->uc_mcontext.gregs[greg];
return TRUE;
}
g_return_val_if_reached(FALSE);
static gboolean instr_mov_fsmem_to_greg(const void *fsmem,int greg,struct ucontext *ucontext)
{
- if (fsmem==0x00000000) { /* exception stack top pointer */
+ if (fsmem==(const void *)0x00000000) { /* exception stack top pointer */
/* moving to %esp is required to pass! */
- ucontext->uc_mcontext.gregs[greg]=val_exceptionstack_top;
+ ucontext->uc_mcontext.gregs[greg]=fs_KPCR_ExceptionList;
+ return TRUE;
+ }
+ if (fsmem==(const void *)0x00000124) { /* =='KeGetCurrentKPCR()->CurrentThread' */
+ g_return_val_if_fail(greg!=REG_ESP,FALSE);
+ ucontext->uc_mcontext.gregs[greg]=(greg_t)captive_KeGetCurrentKPCR()->CurrentThread;
return TRUE;
}
g_return_val_if_reached(FALSE);
static void sigaction_SIGSEGV(int signo,siginfo_t *siginfo,struct ucontext *ucontext)
{
-const guint8 *reg_eip;
+guint8 *reg_eip;
const void *reg_eip_aligned;
g_return_if_fail(signo==SIGSEGV);
}
g_assert_not_reached();
}
+
+ if (*reg_eip==0xF4) { /* hlt; from captive_ModuleList_patch() */
+struct captive_ModuleList_patchpoint *patchpoint;
+const gchar *funcname_disabled;
+
+ g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: reg_eip=%p; 0xF4 hit",G_STRLOC,reg_eip);
+
+ if ((funcname_disabled=captive_ModuleList_function_disable_find(
+ reg_eip))) { /* ExportAddress */
+ g_error("%s: Reached disabled W32 function: %s",G_STRLOC,funcname_disabled);
+ g_assert_not_reached();
+ }
+ patchpoint=captive_ModuleList_patchpoint_find(
+ reg_eip); /* ExportAddress */
+ g_assert(patchpoint!=NULL);
+ if (reg_eip==patchpoint->orig_w32_func) {
+ g_assert(0xF4 /* hlt */ ==*patchpoint->orig_w32_func);
+ g_assert(patchpoint->orig_w32_2ndinstr_byte ==*patchpoint->orig_w32_2ndinstr);
+ if (patchpoint->through_w32_func) {
+ *patchpoint->orig_w32_func=patchpoint->orig_w32_func_byte;
+ *patchpoint->orig_w32_2ndinstr=0xF4; /* hlt */
+ }
+ else { /* !patchpoint->through_w32_func */
+ reg_eip=(guint8 *)patchpoint->wrap_wrap_func;
+ }
+ goto ok;
+ }
+ if (reg_eip==patchpoint->orig_w32_2ndinstr) {
+ g_assert(patchpoint->orig_w32_func_byte ==*patchpoint->orig_w32_func);
+ g_assert(0xF4 /* hlt */ ==*patchpoint->orig_w32_2ndinstr);
+ g_assert(patchpoint->through_w32_func==TRUE);
+ *patchpoint->orig_w32_func=0xF4; /* hlt */
+ *patchpoint->orig_w32_2ndinstr=patchpoint->orig_w32_2ndinstr_byte;
+ patchpoint->through_w32_func=FALSE;
+ goto ok;
+ }
+ g_assert_not_reached();
+ }
+
+ if (*reg_eip==0xFA) { /* cli */
+ g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: reg_eip=%p; CLI neutralized",G_STRLOC,reg_eip);
+ *reg_eip=0x90; /* nop */
+ goto ok;
+ }
+
g_assert_not_reached();
ok: