Skip to content

Latest commit

 

History

History
209 lines (185 loc) · 7.78 KB

os2native16.h

File metadata and controls

209 lines (185 loc) · 7.78 KB
 
Oct 27, 2016
Oct 27, 2016
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#ifndef _INCL_OS2NATIVE16_H_
#define _INCL_OS2NATIVE16_H_
#include "os2native.h"
// !!! FIXME: _lots_ of macro salsa in here.
#define LX_NATIVE_MODULE_16BIT_SUPPORT() \
static LxMmaps obj16;
// These are the 16-bit entry points, which are exported to the LX loader
// (not when linking directly to this shared library).
#define LX_NATIVE_MODULE_16BIT_API(fn) \
static void *fn##16 = NULL;
#define LX_NATIVE_MODULE_16BIT_SUPPORT_END()
#define LX_NATIVE_MODULE_DEINIT_16BIT_SUPPORT() \
if ((obj16.alias != 0xFFFF) && (GLoaderState)) { \
GLoaderState->freeSelector(obj16.alias); \
} \
if (obj16.mapped != NULL) { \
munmap(obj16.mapped, obj16.size); \
} \
obj16.mapped = obj16.addr = NULL; \
obj16.size = 0; \
obj16.alias = 0xFFFF; \
#define LX_NATIVE_MODULE_INIT_16BIT_SUPPORT() \
obj16.mapped = obj16.addr = NULL; \
obj16.size = 0; \
obj16.alias = 0xFFFF; \
\
const size_t vsize = 0x10000 * 2; \
void *mmapaddr = mmap(NULL, vsize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); \
if (mmapaddr == ((void *) MAP_FAILED)) { \
fprintf(stderr, "mmap(NULL, 0x20000, RW-, ANON|PRIVATE, -1, 0) failed (%d): %s\n", errno, strerror(errno)); \
return 0; \
} \
\
obj16.mapped = mmapaddr; \
obj16.size = vsize; \
\
/* force objects with a 16:16 alias to a 64k boundary. */ \
size_t adjust = (size_t) mmapaddr; \
if ((adjust % 0x10000) != 0) { \
const size_t diff = 0x10000 - (adjust % 0x10000); \
adjust += diff; \
mmapaddr = (void *) adjust; \
} \
obj16.addr = mmapaddr; \
\
uint16 offset = 0; \
if (!GLoaderState->findSelector((uint32) obj16.addr, &obj16.alias, &offset)) { \
fprintf(stderr, "couldn't find a selector for 16-bit entry points!\n"); \
munmap(obj16.mapped, vsize); \
obj16.mapped = obj16.addr = NULL; \
obj16.size = 0; \
obj16.alias = 0xFFFF; \
return 0; \
} \
assert(offset == 0); \
\
uint8 *ptr = (uint8 *) mmapaddr;
/* This is the original assembly code, for use with NASM.
USE16 ; start in 16-bit code where our 16-bit caller lands.
MOV BX, SS ; save off ss:sp
SHL EBX, 16 ; scootch over!
MOV BX, SP ; save off ss:sp
; our stack is tiled, so we can easily find the linear address of it.
MOV AX, SS ; move the stack segment into the low word.
SHR AX, 3 ; shift out the control bits from the segment.
SHL EAX, 16 ; move the remaining selector bits to the high word of %eax
MOV AX, SP ; move the stack offset into the low word. Now %eax has the linear stack pointer.
JMP DWORD 0x7788:0x33332222 ; jmp into the 32-bit code segment (the next instruction!).
USE32
MOV CX, 0xABCD ; original linear stack segment from lx_loader's main().
MOV SS, CX
MOV ESP, EAX ; and the same stack pointer, but linear.
ADD EAX, 4 ; %eax now points to original function arguments on the stack.
PUSH EBX ; save original ss:sp to stack.
PUSH DS ; save off the caller's data segment.
MOV CX, 0x8888 ; restore our linear data segment.
MOV DS, 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 DS ; get back our 16-bit data segment.
; Restore 16:16 stack. !!! FIXME: can use LSS if we figure out prefix and DS politics.
POP BX ; Get our original ss back.
POP CX ; Get our original sp back.
JMP WORD 0xAAAA:0xBBBB ; back into 16-bit land (the next instruction!).
USE16
MOV SS, CX
MOV SP, BX
RETF 0x22 ; ...and back to the (far) caller, clearing the args (Pascal calling convention!) with retval in AX.
*/
Oct 27, 2016
Oct 27, 2016
112
#define LX_NATIVE_INIT_16BIT_BRIDGE(fn, argbytes) { \
Oct 27, 2016
Oct 27, 2016
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
fn##16 = ptr; \
\
/* instructions are in Intel syntax here, not AT&T. */ \
/* USE16 */ \
*(ptr++) = 0x8C; /* mov bx,ss... */ \
*(ptr++) = 0xD3; /* ...mov bx,ss */ \
*(ptr++) = 0x66; /* shl ebx,byte 0x10... */ \
*(ptr++) = 0xC1; /* ...shl ebx,byte 0x10 */ \
*(ptr++) = 0xE3; /* ...shl ebx,byte 0x10 */ \
*(ptr++) = 0x10; /* ...shl ebx,byte 0x10 */ \
*(ptr++) = 0x89; /* mov bx,sp... */ \
*(ptr++) = 0xE3; /* ...mov bx,sp */ \
*(ptr++) = 0x8C; /* mov ax,ss... */ \
*(ptr++) = 0xD0; /* ...mov ax,ss */ \
*(ptr++) = 0xC1; /* shr ax,byte 0x3... */ \
*(ptr++) = 0xE8; /* ...shr ax,byte 0x3 */ \
*(ptr++) = 0x03; /* ...shr ax,byte 0x3 */ \
*(ptr++) = 0x66; /* shl eax,byte 0x10... */ \
*(ptr++) = 0xC1; /* ...shl eax,byte 0x10 */ \
*(ptr++) = 0xE0; /* ...shl eax,byte 0x10 */ \
*(ptr++) = 0x10; /* ...shl eax,byte 0x10 */ \
*(ptr++) = 0x89; /* mov ax,sp... */ \
*(ptr++) = 0xE0; /* ...mov ax,sp */ \
*(ptr++) = 0x66; /* jmp dword 0x7788:0x33332222... */ \
*(ptr++) = 0xEA; /* ...jmp dword 0x7788:0x33332222 */ \
const uint32 jmp32addr = (uint32) (ptr + 6); \
memcpy(ptr, &jmp32addr, 4); ptr += 4; \
memcpy(ptr, &GLoaderState->original_cs, 2); ptr += 2; \
\
/* USE32 */ \
*(ptr++) = 0x66; /* mov cx,0xabcd... */ \
*(ptr++) = 0xB9; /* ...mov cx,0xabcd */ \
memcpy(ptr, &GLoaderState->original_ss, 2); ptr += 2; \
*(ptr++) = 0x8E; /* mov ss,ecx... */ \
*(ptr++) = 0xD1; /* ...mov ss,ecx */ \
*(ptr++) = 0x89; /* mov esp,eax... */ \
*(ptr++) = 0xC4; /* ...mov esp,eax */ \
*(ptr++) = 0x83; /* add eax,byte +0x4... */ \
*(ptr++) = 0xC0; /* ...add eax,byte +0x4 */ \
*(ptr++) = 0x04; /* ...add eax,byte +0x4 */ \
*(ptr++) = 0x53; /* push ebx */ \
*(ptr++) = 0x1E; /* push ds */ \
*(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++) = 0x50; /* push eax */ \
*(ptr++) = 0xB8; /* mov eax,0x55555555... */ \
const uint32 callbridgeaddr = (uint32) bridge16to32_##fn; \
memcpy(ptr, &callbridgeaddr, 4); ptr += 4; \
*(ptr++) = 0xFF; /* call dword [eax]... */ \
*(ptr++) = 0xD0; /* ...call dword [eax] */ \
*(ptr++) = 0x83; /* add esp,byte +0x4... */ \
*(ptr++) = 0xC4; /* ...add esp,byte +0x4 */ \
*(ptr++) = 0x04; /* ...add esp,byte +0x4 */ \
*(ptr++) = 0x1F; /* pop ds */ \
*(ptr++) = 0x66; /* pop bx... */ \
*(ptr++) = 0x5B; /* ...pop bx */ \
*(ptr++) = 0x66; /* pop cx... */ \
*(ptr++) = 0x59; /* ...pop cx */ \
*(ptr++) = 0x66; /* jmp word 0xaaaa:0xbbbb... */ \
*(ptr++) = 0xEA; /* ...jmp word 0xaaaa:0xbbbb */ \
const uint16 jmp16offset = (uint16) ((((uint32)ptr) - ((uint32)mmapaddr))+4); \
memcpy(ptr, &jmp16offset, 2); ptr += 2; \
const uint16 jmp16segment = (obj16.alias << 3) | 7; \
memcpy(ptr, &jmp16segment, 2); ptr += 2; \
\
/* USE16 */ \
*(ptr++) = 0x8E; /* mov ss,cx... */ \
*(ptr++) = 0xD1; /* ...mov ss,cx */ \
*(ptr++) = 0x89; /* mov sp,bx... */ \
*(ptr++) = 0xDC; /* ...mov sp,bx */ \
*(ptr++) = 0xCA; /* retf 0x22... */ \
const uint16 argbytecount = argbytes; \
memcpy(ptr, &argbytecount, 2); ptr += 2; \
Oct 27, 2016
Oct 27, 2016
189
}
Oct 27, 2016
Oct 27, 2016
190
Oct 27, 2016
Oct 27, 2016
191
#define LX_NATIVE_MODULE_INIT_16BIT_SUPPORT_END() { \
Oct 27, 2016
Oct 27, 2016
192
193
194
195
196
197
198
199
200
201
assert((((uint32)ptr) - ((uint32)mmapaddr)) < 0x10000); /* don't be more than 64k. */ \
if (mprotect(obj16.mapped, vsize, PROT_READ | PROT_EXEC) == -1) { \
fprintf(stderr, "mprotect() failed for 16-bit bridge code!\n"); \
munmap(obj16.mapped, vsize); \
GLoaderState->freeSelector(obj16.alias); \
obj16.mapped = obj16.addr = NULL; \
obj16.size = 0; \
obj16.alias = 0xFFFF; \
return 0; \
} \
Oct 27, 2016
Oct 27, 2016
202
}
Oct 27, 2016
Oct 27, 2016
203
204
205
206
207
208
#define LX_NATIVE_EXPORT16(fn, ord) { ord, #fn, &fn##16, &obj16 }
#endif
// end of os2native16.h ...