16-bit bridging code now protects %es register.
authorRyan C. Gordon <icculus@icculus.org>
Tue, 01 Nov 2016 21:37:57 -0400
changeset 73 b8295997c8d2
parent 72 75ded8736bbd
child 74 50eae5a78040
16-bit bridging code now protects %es register.

Fixes crash with Info-Zip's unzip.exe blowing up calling into ncurses
via VioGetMode().
lx_loader.c
lx_loader.h
native/os2native16.h
--- a/lx_loader.c	Sat Oct 29 23:53:47 2016 -0400
+++ b/lx_loader.c	Tue Nov 01 21:37:57 2016 -0400
@@ -730,8 +730,11 @@
     *(ptr++) = 0x66;  /* mov cx,0x8888... */
     *(ptr++) = 0xB9;  /*  ...mov cx,0x8888 */
     memcpy(ptr, &GLoaderState->original_ds, 2); ptr += 2;
-    *(ptr++) = 0x8E;  /* mov ds,ecx... */
-    *(ptr++) = 0xD9;  /*  ...mov ds,ecx */
+    *(ptr++) = 0x66;  /* mov cx,0x8888... */
+    *(ptr++) = 0xB9;  /*  ...mov cx,0x8888 */
+    memcpy(ptr, &GLoaderState->original_es, 2); ptr += 2;
+    *(ptr++) = 0x8E;  /* mov es,ecx... */ \
+    *(ptr++) = 0xC1;  /*  ...mov es,ecx */ \
     // okay, CPU is in a sane state again, call the trampoline. Don't bother cleaning up.
     *(ptr++) = 0x68;  // pushl immediate
     memcpy(ptr, &entry, sizeof (char *));
@@ -2076,10 +2079,12 @@
     unsigned int segment = 0;
     __asm__ __volatile__ ( "movw %%cs, %%ax  \n\t" : "=a" (segment) );
     GLoaderState->original_cs = segment;
+    __asm__ __volatile__ ( "movw %%ds, %%ax  \n\t" : "=a" (segment) );
+    GLoaderState->original_ds = segment;
+    __asm__ __volatile__ ( "movw %%es, %%ax  \n\t" : "=a" (segment) );
+    GLoaderState->original_es = segment;
     __asm__ __volatile__ ( "movw %%ss, %%ax  \n\t" : "=a" (segment) );
     GLoaderState->original_ss = segment;
-    __asm__ __volatile__ ( "movw %%ds, %%ax  \n\t" : "=a" (segment) );
-    GLoaderState->original_ds = segment;
 
     const char *envr = getenv("IS_2INE");
     GLoaderState->subprocess = (envr != NULL);
--- a/lx_loader.h	Sat Oct 29 23:53:47 2016 -0400
+++ b/lx_loader.h	Tue Nov 01 21:37:57 2016 -0400
@@ -212,8 +212,9 @@
     int running;
     int trace_native;
     uint16 original_cs;
+    uint16 original_ds;
+    uint16 original_es;
     uint16 original_ss;
-    uint16 original_ds;
     uint32 ldt[8192];
     char *libpath;
     uint32 libpathlen;
--- a/native/os2native16.h	Sat Oct 29 23:53:47 2016 -0400
+++ b/native/os2native16.h	Tue Nov 01 21:37:57 2016 -0400
@@ -86,15 +86,21 @@
 
 PUSH EBX  ; save original ss:sp to stack.
 PUSH DS  ; save off the caller's data segment.
+PUSH ES  ; save off the caller's %es register.
+
 MOV CX, 0x8888  ; restore our linear data segment.
 MOV DS, CX
 
+MOV CX, 0x9999  ; restore %es register.
+MOV ES, CX
+
 PUSH EAX  ; make this the sole argument to the bridge function.
 MOV EAX, 0x55555555  ; absolute address of our 32-bit bridging function in C.
 CALL [EAX]  ; call our 32-bit bridging function in C.
 ; don't touch EAX anymore, it has the return value now!
 ADD ESP, 4  ; dump our function argument.
 
+POP ES  ; get back caller's %es register.
 POP DS  ; get back our 16-bit data segment.
 
 ; Restore 16:16 stack.  !!! FIXME: can use LSS if we figure out prefix and DS politics.
@@ -152,11 +158,17 @@
     *(ptr++) = 0x04;  /*  ...add eax,byte +0x4 */ \
     *(ptr++) = 0x53;  /* push ebx */ \
     *(ptr++) = 0x1E;  /* push ds */ \
+    *(ptr++) = 0x06;  /* push es */ \
     *(ptr++) = 0x66;  /* mov cx,0x8888... */ \
     *(ptr++) = 0xB9;  /*  ...mov cx,0x8888 */ \
     memcpy(ptr, &GLoaderState->original_ds, 2); ptr += 2; \
     *(ptr++) = 0x8E;  /* mov ds,ecx... */ \
     *(ptr++) = 0xD9;  /*  ...mov ds,ecx */ \
+    *(ptr++) = 0x66;  /* mov cx,0x9999... */ \
+    *(ptr++) = 0xB9;  /*  ...mov cx,0x9999 */ \
+    memcpy(ptr, &GLoaderState->original_es, 2); ptr += 2; \
+    *(ptr++) = 0x8E;  /* mov es,ecx... */ \
+    *(ptr++) = 0xC1;  /*  ...mov es,ecx */ \
     *(ptr++) = 0x50;  /* push eax */ \
     *(ptr++) = 0xB8;  /* mov eax,0x55555555... */ \
     const uint32 callbridgeaddr = (uint32) bridge16to32_##fn; \
@@ -166,6 +178,7 @@
     *(ptr++) = 0x83;  /* add esp,byte +0x4... */ \
     *(ptr++) = 0xC4;  /*  ...add esp,byte +0x4 */ \
     *(ptr++) = 0x04;  /*  ...add esp,byte +0x4 */ \
+    *(ptr++) = 0x07;  /* pop es */ \
     *(ptr++) = 0x1F;  /* pop ds */ \
     *(ptr++) = 0x66;  /* pop bx... */ \
     *(ptr++) = 0x5B;  /*  ...pop bx */ \