mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
Added patch to implement emulation of GDT and LDT access in Win98 mode.
This commit is contained in:
parent
e22062154b
commit
bdf73385f7
@ -0,0 +1,90 @@
|
||||
From 3b1a8788726b7031baa66985329f4071fc0600a7 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Fri, 26 Feb 2016 23:14:25 +0100
|
||||
Subject: krnl386.exe16: Emulate 'mov Eb, Gb' instruction on x86 processor
|
||||
architecture.
|
||||
|
||||
Stolen from Sebastian Lackners ntorkrnl implementation.
|
||||
---
|
||||
dlls/krnl386.exe16/instr.c | 35 +++++++++++++++++++++++++++++------
|
||||
1 file changed, 29 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/dlls/krnl386.exe16/instr.c b/dlls/krnl386.exe16/instr.c
|
||||
index b44bd55..b0de30f 100644
|
||||
--- a/dlls/krnl386.exe16/instr.c
|
||||
+++ b/dlls/krnl386.exe16/instr.c
|
||||
@@ -113,7 +113,7 @@ static BOOL INSTR_ReplaceSelector( CONTEXT *context, WORD *sel )
|
||||
|
||||
|
||||
/* store an operand into a register */
|
||||
-static void store_reg( CONTEXT *context, BYTE regmodrm, const BYTE *addr, int long_op )
|
||||
+static void store_reg_word( CONTEXT *context, BYTE regmodrm, const BYTE *addr, int long_op )
|
||||
{
|
||||
switch((regmodrm >> 3) & 7)
|
||||
{
|
||||
@@ -152,6 +152,22 @@ static void store_reg( CONTEXT *context, BYTE regmodrm, const BYTE *addr, int lo
|
||||
}
|
||||
}
|
||||
|
||||
+/* store an operand into a byte register */
|
||||
+static void store_reg_byte( CONTEXT *context, BYTE regmodrm, const BYTE *addr )
|
||||
+{
|
||||
+ switch((regmodrm >> 3) & 7)
|
||||
+ {
|
||||
+ case 0: context->Eax = (context->Eax & 0xffffff00) | *addr; break;
|
||||
+ case 1: context->Ecx = (context->Ecx & 0xffffff00) | *addr; break;
|
||||
+ case 2: context->Edx = (context->Edx & 0xffffff00) | *addr; break;
|
||||
+ case 3: context->Ebx = (context->Ebx & 0xffffff00) | *addr; break;
|
||||
+ case 4: context->Eax = (context->Eax & 0xffff00ff) | (*addr << 8); break;
|
||||
+ case 5: context->Ecx = (context->Ecx & 0xffff00ff) | (*addr << 8); break;
|
||||
+ case 6: context->Edx = (context->Edx & 0xffff00ff) | (*addr << 8); break;
|
||||
+ case 7: context->Ebx = (context->Ebx & 0xffff00ff) | (*addr << 8); break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/***********************************************************************
|
||||
* INSTR_GetOperandAddr
|
||||
*
|
||||
@@ -333,7 +349,7 @@ static BOOL INSTR_EmulateLDS( CONTEXT *context, BYTE *instr, int long_op,
|
||||
|
||||
/* Now store the offset in the correct register */
|
||||
|
||||
- store_reg( context, *regmodrm, addr, long_op );
|
||||
+ store_reg_word( context, *regmodrm, addr, long_op );
|
||||
|
||||
/* Store the correct segment in the segment register */
|
||||
|
||||
@@ -689,19 +705,26 @@ DWORD __wine_emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context )
|
||||
}
|
||||
return ExceptionContinueExecution;
|
||||
|
||||
+ case 0x8a: /* mov Eb, Gb */
|
||||
case 0x8b: /* mov Ev, Gv */
|
||||
{
|
||||
- BYTE *addr = INSTR_GetOperandAddr(context, instr + 1, long_addr,
|
||||
+ BYTE *data = INSTR_GetOperandAddr(context, instr + 1, long_addr,
|
||||
segprefix, &len);
|
||||
+ unsigned int data_size = (*instr == 0x8b) ? (long_op ? 4 : 2) : 1;
|
||||
struct idtr idtr = get_idtr();
|
||||
- unsigned int offset = addr - idtr.base;
|
||||
+ unsigned int offset = data - idtr.base;
|
||||
|
||||
- if (offset <= idtr.limit + 1 - (long_op ? 4 : 2))
|
||||
+ if (offset <= idtr.limit + 1 - data_size)
|
||||
{
|
||||
idt[1].LimitLow = 0x100; /* FIXME */
|
||||
idt[2].LimitLow = 0x11E; /* FIXME */
|
||||
idt[3].LimitLow = 0x500; /* FIXME */
|
||||
- store_reg( context, instr[1], (BYTE *)idt + offset, long_op );
|
||||
+
|
||||
+ switch (*instr)
|
||||
+ {
|
||||
+ case 0x8a: store_reg_byte( context, instr[1], (BYTE *)idt + offset ); break;
|
||||
+ case 0x8b: store_reg_word( context, instr[1], (BYTE *)idt + offset, long_op ); break;
|
||||
+ }
|
||||
context->Eip += prefixlen + len + 1;
|
||||
return ExceptionContinueExecution;
|
||||
}
|
||||
--
|
||||
2.7.1
|
||||
|
@ -0,0 +1,117 @@
|
||||
From 1de2ab4f1d48391f112897c2c89d4c1d77d4ac3f Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Sat, 27 Feb 2016 00:04:10 +0100
|
||||
Subject: krnl386.exe16: Emulate GDT and LDT access.
|
||||
|
||||
---
|
||||
dlls/krnl386.exe16/instr.c | 64 +++++++++++++++++++++++++++++++++++++++-------
|
||||
1 file changed, 55 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/dlls/krnl386.exe16/instr.c b/dlls/krnl386.exe16/instr.c
|
||||
index b0de30f..865d944 100644
|
||||
--- a/dlls/krnl386.exe16/instr.c
|
||||
+++ b/dlls/krnl386.exe16/instr.c
|
||||
@@ -67,7 +67,7 @@ static inline void *get_stack( CONTEXT *context )
|
||||
}
|
||||
|
||||
#include "pshpack1.h"
|
||||
-struct idtr
|
||||
+struct dtr
|
||||
{
|
||||
WORD limit;
|
||||
BYTE *base;
|
||||
@@ -75,19 +75,41 @@ struct idtr
|
||||
#include "poppack.h"
|
||||
|
||||
static LDT_ENTRY idt[256];
|
||||
+static LDT_ENTRY gdt[8192];
|
||||
+static LDT_ENTRY ldt[8192];
|
||||
|
||||
-static inline struct idtr get_idtr(void)
|
||||
+static BOOL emulate_idtr( BYTE *data, unsigned int data_size, unsigned int *offset )
|
||||
{
|
||||
- struct idtr ret;
|
||||
#if defined(__i386__) && defined(__GNUC__)
|
||||
+ struct dtr ret;
|
||||
__asm__( "sidtl %0" : "=m" (ret) );
|
||||
+ *offset = data - ret.base;
|
||||
+ return (*offset <= ret.limit + 1 - data_size);
|
||||
#else
|
||||
- ret.base = (BYTE *)idt;
|
||||
- ret.limit = sizeof(idt) - 1;
|
||||
+ return FALSE;
|
||||
#endif
|
||||
- return ret;
|
||||
}
|
||||
|
||||
+static BOOL emulate_gdtr( BYTE *data, unsigned int data_size, unsigned int *offset )
|
||||
+{
|
||||
+#if defined(__i386__) && defined(__GNUC__)
|
||||
+ struct dtr ret;
|
||||
+ __asm__( "sgdtl %0" : "=m" (ret) );
|
||||
+ *offset = data - ret.base;
|
||||
+ return (*offset <= ret.limit + 1 - data_size);
|
||||
+#else
|
||||
+ return FALSE;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline WORD get_ldt(void)
|
||||
+{
|
||||
+ WORD seg = 1;
|
||||
+#if defined(__i386__) && defined(__GNUC__)
|
||||
+ __asm__( "sldt %0" : "=m" (seg) );
|
||||
+#endif
|
||||
+ return seg;
|
||||
+}
|
||||
|
||||
/***********************************************************************
|
||||
* INSTR_ReplaceSelector
|
||||
@@ -711,10 +733,9 @@ DWORD __wine_emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context )
|
||||
BYTE *data = INSTR_GetOperandAddr(context, instr + 1, long_addr,
|
||||
segprefix, &len);
|
||||
unsigned int data_size = (*instr == 0x8b) ? (long_op ? 4 : 2) : 1;
|
||||
- struct idtr idtr = get_idtr();
|
||||
- unsigned int offset = data - idtr.base;
|
||||
+ unsigned int offset;
|
||||
|
||||
- if (offset <= idtr.limit + 1 - data_size)
|
||||
+ if (emulate_idtr( data, data_size, &offset ))
|
||||
{
|
||||
idt[1].LimitLow = 0x100; /* FIXME */
|
||||
idt[2].LimitLow = 0x11E; /* FIXME */
|
||||
@@ -728,6 +749,31 @@ DWORD __wine_emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context )
|
||||
context->Eip += prefixlen + len + 1;
|
||||
return ExceptionContinueExecution;
|
||||
}
|
||||
+
|
||||
+ if (emulate_gdtr( data, data_size, &offset ))
|
||||
+ {
|
||||
+ static BOOL initialized;
|
||||
+
|
||||
+ if (!initialized)
|
||||
+ {
|
||||
+ WORD index = get_ldt() >> 3;
|
||||
+ gdt[index].BaseLow = ((DWORD_PTR)ldt & 0x0000FFFF);
|
||||
+ gdt[index].HighWord.Bytes.BaseMid = ((DWORD_PTR)ldt & 0x00FF0000) >> 16;
|
||||
+ gdt[index].HighWord.Bytes.BaseHi = ((DWORD_PTR)ldt & 0xFF000000) >> 24;
|
||||
+ gdt[index].LimitLow = 0xFFFF;
|
||||
+ gdt[index].HighWord.Bits.Pres = 1;
|
||||
+
|
||||
+ initialized = TRUE;
|
||||
+ }
|
||||
+
|
||||
+ switch (*instr)
|
||||
+ {
|
||||
+ case 0x8a: store_reg_byte( context, instr[1], (BYTE *)gdt + offset ); break;
|
||||
+ case 0x8b: store_reg_word( context, instr[1], (BYTE *)gdt + offset, long_op ); break;
|
||||
+ }
|
||||
+ context->Eip += prefixlen + len + 1;
|
||||
+ return ExceptionContinueExecution;
|
||||
+ }
|
||||
}
|
||||
break; /* Unable to emulate it */
|
||||
|
||||
--
|
||||
2.7.1
|
||||
|
1
patches/krnl386.exe16-GDT_LDT_Emulation/definition
Normal file
1
patches/krnl386.exe16-GDT_LDT_Emulation/definition
Normal file
@ -0,0 +1 @@
|
||||
Fixes: [30237] Implement emulation of GDT and LDT access in Win98 mode
|
@ -174,6 +174,7 @@ patch_enable_all ()
|
||||
enable_kernel32_SetFileInformationByHandle="$1"
|
||||
enable_kernel32_TimezoneInformation_Registry="$1"
|
||||
enable_kernel32_VerifyVersionInfo="$1"
|
||||
enable_krnl386_exe16_GDT_LDT_Emulation="$1"
|
||||
enable_krnl386_exe16_Invalid_Console_Handles="$1"
|
||||
enable_libs_Debug_Channel="$1"
|
||||
enable_libs_Unicode_Collation="$1"
|
||||
@ -667,6 +668,9 @@ patch_enable ()
|
||||
kernel32-VerifyVersionInfo)
|
||||
enable_kernel32_VerifyVersionInfo="$2"
|
||||
;;
|
||||
krnl386.exe16-GDT_LDT_Emulation)
|
||||
enable_krnl386_exe16_GDT_LDT_Emulation="$2"
|
||||
;;
|
||||
krnl386.exe16-Invalid_Console_Handles)
|
||||
enable_krnl386_exe16_Invalid_Console_Handles="$2"
|
||||
;;
|
||||
@ -4163,6 +4167,23 @@ if test "$enable_kernel32_VerifyVersionInfo" -eq 1; then
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset krnl386.exe16-GDT_LDT_Emulation
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#30237] Implement emulation of GDT and LDT access in Win98 mode
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/krnl386.exe16/instr.c
|
||||
# |
|
||||
if test "$enable_krnl386_exe16_GDT_LDT_Emulation" -eq 1; then
|
||||
patch_apply krnl386.exe16-GDT_LDT_Emulation/0001-krnl386.exe16-Emulate-mov-Eb-Gb-instruction-on-x86-p.patch
|
||||
patch_apply krnl386.exe16-GDT_LDT_Emulation/0002-krnl386.exe16-Emulate-GDT-and-LDT-access.patch
|
||||
(
|
||||
echo '+ { "Michael Müller", "krnl386.exe16: Emulate '\''mov Eb, Gb'\'' instruction on x86 processor architecture.", 1 },';
|
||||
echo '+ { "Michael Müller", "krnl386.exe16: Emulate GDT and LDT access.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset krnl386.exe16-Invalid_Console_Handles
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
|
Loading…
Reference in New Issue
Block a user