+some other %fs access instructions emulation
authorshort <>
Tue, 8 Apr 2003 18:11:45 +0000 (18:11 +0000)
committershort <>
Tue, 8 Apr 2003 18:11:45 +0000 (18:11 +0000)
+"sti" instruction emulation

src/libcaptive/ps/signal.c

index faa3cb6..8ea73c6 100644 (file)
@@ -55,6 +55,8 @@ int _abnormal_termination(void)
 }
 
 
+#if 0
+
 /**
  * RtlpDispatchException:
  * @ExceptionRecord: Ignored by libcaptive.
@@ -71,12 +73,18 @@ ULONG RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,IN PCONTEXT Con
        g_return_val_if_reached(0);
 }
 
+#endif
+
 
 /* =='KeGetCurrentKPCR()->ExceptionList';
  * libcaptive has reduced KPCR (named 'captive_KPCR') which
  * does not contain this field
  */
-static greg_t fs_KPCR_ExceptionList=(greg_t)-1;
+greg_t fs_KPCR_ExceptionList=(greg_t)-1;
+
+/* FIXME */
+static greg_t fs_KPCR_Unknown638=0;
+
 
 static gboolean instr_mov_greg_to_fsmem(int greg,const void *fsmem,struct ucontext *ucontext)
 {
@@ -88,6 +96,15 @@ static gboolean instr_mov_greg_to_fsmem(int greg,const void *fsmem,struct uconte
        g_return_val_if_reached(FALSE);
 }
 
+static gboolean instr_mov_immed_to_fsmem(greg_t immed,const void *fsmem,struct ucontext *ucontext)
+{
+       if (fsmem==(const void *)0x00000000) {  /* exception stack top pointer */
+               fs_KPCR_ExceptionList=immed;
+               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==(const void *)0x00000000) {  /* exception stack top pointer */
@@ -108,6 +125,35 @@ static gboolean instr_mov_fsmem_to_greg(const void *fsmem,int greg,struct uconte
        g_return_val_if_reached(FALSE);
 }
 
+static gboolean instr_push_fsmem(const void *fsmem,struct ucontext *ucontext)
+{
+       if (fsmem==(const void *)0x00000000) {  /* exception stack top pointer */
+               ucontext->uc_mcontext.gregs[REG_ESP]-=4;
+               *(greg_t *)ucontext->uc_mcontext.gregs[REG_ESP]=fs_KPCR_ExceptionList;
+               return TRUE;
+               }
+       g_return_val_if_reached(FALSE);
+}
+
+static gboolean instr_pop_fsmem(const void *fsmem,struct ucontext *ucontext)
+{
+       if (fsmem==(const void *)0x00000000) {  /* exception stack top pointer */
+               fs_KPCR_ExceptionList=*(greg_t *)ucontext->uc_mcontext.gregs[REG_ESP];
+               ucontext->uc_mcontext.gregs[REG_ESP]+=4;
+               return TRUE;
+               }
+       g_return_val_if_reached(FALSE);
+}
+
+static gboolean instr_incl_fsmem(const void *fsmem,struct ucontext *ucontext)
+{
+       if (fsmem==(const void *)0x00000638) {  /* Unknown638 */
+               fs_KPCR_Unknown638++;
+               return TRUE;
+               }
+       g_return_val_if_reached(FALSE);
+}
+
 static int op_regcode_to_greg(guint8 regcode)
 {
        switch (regcode) {
@@ -191,7 +237,7 @@ const void *reg_eip_aligned;
                        }
                if (*reg_eip==0x8B) {   /* prefix 0x8B */
                        reg_eip++;
-                       if ((*reg_eip & ~0x38)==0x05) { /* 'mov %fs:{reg_eip[1..4]},%{op_regcode_to_greg(*reg_eip[b3..b5])} */
+                       if ((*reg_eip & ~0x38)==0x05) { /* 'mov %fs:{reg_eip[1..4]},%{op_regcode_to_greg(*reg_eip[b3..b5])}' */
                                reg_eip++;
                                if (instr_mov_fsmem_to_greg(*(const void **)reg_eip,op_regcode_to_greg(reg_eip[-1]>>3U),ucontext)) {
                                        reg_eip+=4;
@@ -201,6 +247,67 @@ const void *reg_eip_aligned;
                                }
                        g_assert_not_reached();
                        }
+               if (*reg_eip==0xFF) {   /* prefix 0xFF */
+                       reg_eip++;
+                       if (*reg_eip==0x05) {   /* 'incl %fs:{reg_eip[1..4]}' */
+                               reg_eip++;
+                               if (instr_incl_fsmem(*(const void **)reg_eip,ucontext)) {
+                                       reg_eip+=4;
+                                       goto ok;
+                                       }
+                               g_assert_not_reached();
+                               }
+                       if (*reg_eip==0x35) {   /* 'pushl %fs:{reg_eip[1..4]}' */
+                               reg_eip++;
+                               if (instr_push_fsmem(*(const void **)reg_eip,ucontext)) {
+                                       reg_eip+=4;
+                                       goto ok;
+                                       }
+                               g_assert_not_reached();
+                               }
+                       g_assert_not_reached();
+                       }
+               if (*reg_eip==0x8F) {   /* prefix 0x0F */
+                       reg_eip++;
+                       if (*reg_eip==0x05) {   /* 'popl %fs:{reg_eip[1..4]}' */
+                               reg_eip++;
+                               if (instr_pop_fsmem(*(const void **)reg_eip,ucontext)) {
+                                       reg_eip+=4;
+                                       goto ok;
+                                       }
+                               g_assert_not_reached();
+                               }
+                       g_assert_not_reached();
+                       }
+               if (*reg_eip==0xC7) {   /* prefix 0xC7 */
+                       reg_eip++;
+                       if (*reg_eip==0x05) {   /* 'movl ${reg_eip[5..8]},%fs:{reg_eip[1..4]}' */
+                               reg_eip++;
+                               if (instr_mov_immed_to_fsmem(((greg_t *)reg_eip)[1],*(const void **)reg_eip,ucontext)) {
+                                       reg_eip+=4+4;
+                                       goto ok;
+                                       }
+                               g_assert_not_reached();
+                               }
+                       g_assert_not_reached();
+                       }
+               g_assert_not_reached();
+               }
+
+       /* all instruction notation comments are written in AT&T 'instr src,dest' syntax! */
+       if (*reg_eip==0x66) {   /* prefix '%fs:' */
+               reg_eip++;
+               /* TODO:thread; %fs: is CPU-dependent */
+               if (*reg_eip==0x8E) {   /* two-byte opcode */
+                       reg_eip++;
+                       if (*reg_eip==0xE3) {   /* 'mov %bx,%fs' */
+                               reg_eip++;
+                               g_assert(0x30==(0xFFFF&ucontext->uc_mcontext.gregs[REG_EBX]));
+                               /* 'reload' of %fs can be ignored */
+                               goto ok;
+                               }
+                       g_assert_not_reached();
+                       }
                g_assert_not_reached();
                }
 
@@ -248,6 +355,12 @@ const gchar *funcname_disabled;
                goto ok;
                }
 
+       if (*reg_eip==0xFB) {   /* sti */
+               g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: reg_eip=%p; STI neutralized",G_STRLOC,reg_eip);
+               *reg_eip=0x90;  /* nop */
+               goto ok;
+               }
+
        g_assert_not_reached();
 
 ok: