source: trunk/src/win32k/dev32/d32init.c@ 2898

Last change on this file since 2898 was 2898, checked in by bird, 26 years ago

Symbol Database is implemented.
No scanning of the os2krnl file, the loaded image is now scaned to determin
which build, debug/retail and smp/uni.
And yet some more enhanchments like 16-bit logging.

File size: 52.9 KB
Line 
1/* $Id: d32init.c,v 1.16 2000-02-25 18:15:03 bird Exp $
2 *
3 * d32init.c - 32-bits init routines.
4 *
5 * Copyright (c) 1998-1999 knut st. osmundsen
6 *
7 * Project Odin Software License can be found in LICENSE.TXT
8 *
9 */
10
11/*******************************************************************************
12* Defined Constants *
13*******************************************************************************/
14#define MAXSIZE_PROLOG 0x18 /* Note that this must be synced with */
15 /* the one used in calltab.asm. */
16#define static /* just to make all symbols visible in the kernel debugger. */
17#if 0 /* Enable this to have extra debug logging. */
18 #define kprintf2(a) kprintf
19#else
20 #define kprintf2(a) (void)0
21#endif
22
23
24#define INCL_DOSERRORS
25#define INCL_NOPMAPI
26#define LDR_INCL_INITONLY
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include <os2.h>
32
33#include <string.h>
34
35#include "OS2Krnl.h"
36#include "options.h"
37#include "dev1632.h"
38#include "dev32.h"
39#include "dev32hlp.h"
40#include "probkrnl.h"
41#include "log.h"
42#include "asmutils.h"
43#include "malloc.h"
44#include "ldr.h"
45#include "ldrCalls.h"
46#include "macros.h"
47
48
49/*******************************************************************************
50* Global Variables *
51*******************************************************************************/
52#ifdef DEBUG
53static char * apszPE[] = {"FLAGS_PE_NOT", "FLAGS_PE_PE2LX", "FLAGS_PE_PE", "FLAGS_PE_MIXED", "!invalid!"};
54static char * apszInfoLevel[] = {"INFOLEVEL_QUIET", "INFOLEVEL_ERROR", "INFOLEVEL_WARNING", "INFOLEVEL_INFO", "INFOLEVEL_INFOALL", "!invalid!"};
55#endif
56static PMTE pKrnlMTE = NULL;
57static PSMTE pKrnlSMTE = NULL;
58static POTE pKrnlOTE = NULL;
59
60
61/*******************************************************************************
62* Internal Functions *
63*******************************************************************************/
64static ULONG readnum(const char *pszNum);
65_Inline int ModR_M_32bit(char bModRM);
66static int interpretFunctionProlog32(char *pach, BOOL fOverload);
67static int interpretFunctionProlog16(char *pach, BOOL fOverload);
68static int ImportTabInit(void);
69
70
71/* externs located in 16-bit data segement in ProbKrnl.c */
72extern ULONG _TKSSBase16;
73extern USHORT _R0FlatCS16;
74extern USHORT _R0FlatDS16;
75
76/* extern(s) located in calltab.asm */
77extern char callTab[NBR_OF_KRNLIMPORTS][MAXSIZE_PROLOG];
78
79/* extern(s) located in mytkExecPgm.asm */
80extern char mytkExecPgm;
81
82
83#ifndef DEBUGR3
84/**
85 * Ring-0, 32-bit, init function.
86 * @returns Status word.
87 * @param pRpInit Pointer init request packet.
88 * @sketch Set TKSSBase32.
89 * Set default parameters.
90 * Parse command line options.
91 * Show (kprint) configuration.
92 * Init heap.
93 * Init ldr.
94 * Init procs. (overloaded ldr procedures)
95 * @status completely implemented.
96 * @author knut st. osmundsen
97 */
98USHORT _loadds _Far32 _Pascal R0Init32(RP32INIT *pRpInit)
99{
100 char * pszTmp2;
101 char * pszTmp;
102 ULONG ul;
103 APIRET rc;
104 LOCKHANDLE lockhandle;
105
106 pulTKSSBase32 = (PULONG)_TKSSBase16;
107
108 /*---------------------*/
109 /* commandline options */
110 /*---------------------*/
111 kprintf(("Options start\n"));
112 pszTmp = strpbrk(pRpInit->InitArgs, "-/");
113 while (pszTmp != NULL)
114 {
115 int cch;
116 pszTmp++; //skip [-/]
117 cch = strlen(pszTmp);
118 switch (*pszTmp)
119 {
120 case 'c':
121 case 'C': /* -C[1|2] - com-port no, def:-C2 */
122 switch (pszTmp[1])
123 {
124 case '1':
125 options.usCom = OUTPUT_COM1;
126 break;
127
128 case '2':
129 default:
130 options.usCom = OUTPUT_COM2;
131 }
132 break;
133
134 case 'e':
135 case 'E':/* ELF */
136 pszTmp2 = strpbrk(pszTmp, ":=/- ");
137 if (pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
138 && (pszTmp2[1] == 'N' ||pszTmp2[1] == 'n' || pszTmp2[1] == 'D' || pszTmp2[1] == 'd')
139 )
140 options.fElf = FALSE;
141 else
142 options.fElf = TRUE;
143 break;
144
145 case 'h':
146 case 'H': /* Heap options */
147 pszTmp2 = strpbrk(pszTmp, ":=/- ");
148 if (pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
149 && (*pszTmp2 == ':' || *pszTmp2 == '='))
150 {
151 ul = readnum(pszTmp2 + 1);
152 if (ul > 0x1000UL && ul < 0x2000000UL) /* 4KB < ul < 32MB */
153 {
154 if (strnicmp(pszTmp, "heapm", 5) == 0)
155 options.cbSwpHeapMax = ul;
156 else
157 options.cbSwpHeapInit = ul;
158 }
159 }
160 break;
161
162 case 'l':
163 case 'L': /* -L[..]<:|=| >[<Y..|E..| > | <N..|D..>] */
164 pszTmp2 = strpbrk(pszTmp, ":=/- ");
165 if (pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
166 && (pszTmp2[1] == 'N' ||pszTmp2[1] == 'n' || pszTmp2[1] == 'D' || pszTmp2[1] == 'd')
167 )
168 options.fLogging = FALSE;
169 else
170 options.fLogging = TRUE;
171 break;
172
173 case 'n':
174 case 'N': /* NoLoader */
175 options.fNoLoader = TRUE;
176 break;
177
178 case 'p':
179 case 'P': /* PE */
180 pszTmp2 = strpbrk(pszTmp, ":=/- ");
181 if (pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
182 && (*pszTmp2 == ':' || *pszTmp2 == '='))
183 {
184 pszTmp++;
185 if (strnicmp(pszTmp, "pe2lx", 5) == 0)
186 options.fPE = FLAGS_PE_PE2LX;
187 else if (strnicmp(pszTmp, "pe", 2) == 0)
188 options.fPE = FLAGS_PE_PE;
189 else if (strnicmp(pszTmp, "mixed", 2) == 0)
190 options.fPE = FLAGS_PE_MIXED;
191 else if (strnicmp(pszTmp, "not", 2) == 0)
192 options.fPE = FLAGS_PE_NOT;
193 else
194 kprintf(("R0Init32: invalid parameter -PE:...\n"));
195 }
196 else
197 kprintf(("R0Init32: invalid parameter -PE...\n"));
198 break;
199
200 case 'q':
201 case 'Q': /* quiet initialization */
202 options.fQuiet = TRUE;
203 break;
204
205 case 'r':
206 case 'R': /* ResHeap options */
207 pszTmp2 = strpbrk(pszTmp, ":=/- ");
208 if (pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
209 && (*pszTmp2 == ':' || *pszTmp2 == '='))
210 {
211 ul = readnum(pszTmp2 + 1);
212 if (ul > 0x1000UL && ul < 0x700000UL) /* 4KB < ul < 7MB */
213 {
214 if (strnicmp(pszTmp, "resheapm", 8) == 0)
215 options.cbResHeapMax = ul;
216 else
217 options.cbResHeapInit = ul;
218 }
219 }
220 break;
221
222 case 's':
223 case 'S': /* Sym:<filename> or Script:<Yes|No> or Smp */
224 /* SMP kernel */
225 if (pszTmp[1] == 'm' || pszTmp[1] == 'M')
226 options.fKernel = KF_SMP;
227 else
228 {
229 if (pszTmp[1] == 'c' || pszTmp[1] == 'C')
230 {
231 pszTmp2 = strpbrk(pszTmp, ":=/- ");
232 options.fScript = pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
233 && (*pszTmp2 == ':' || *pszTmp2 == '=')
234 && (pszTmp2[1] == 'Y' || pszTmp2[1] == 'y');
235 }
236 }
237 break;
238
239 case 'u':
240 case 'U': /* UNI kernel */
241 options.fKernel = KF_UNI;
242 break;
243
244 case 'v':
245 case 'V': /* verbose initialization */
246 options.fQuiet = FALSE;
247 break;
248
249 case 'w':
250 case 'W':
251 if (pszTmp[1] >= '0' && pszTmp[1] <= '4')
252 options.ulInfoLevel = pszTmp[1] - '0';
253 else
254 {
255 pszTmp2 = strpbrk(pszTmp, ":=/- ");
256 if (pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
257 && (*pszTmp2 == ':' || *pszTmp2 == '=')
258 && pszTmp2[1] >= '0' && pszTmp2[1] <= '4'
259 )
260 options.ulInfoLevel = pszTmp2[1] - '0';
261 }
262 break;
263
264 }
265 pszTmp = strpbrk(pszTmp, "-/");
266 }
267
268 /* heap min/max corrections */
269 if (options.cbSwpHeapInit > options.cbSwpHeapMax)
270 options.cbSwpHeapMax = options.cbSwpHeapInit;
271 if (options.cbResHeapInit > options.cbResHeapMax)
272 options.cbResHeapMax = options.cbResHeapInit;
273
274 /* Transfer version and build number from 16-bit probkrnl.c */
275 options.ulBuild = _usBuild;
276 options.usVerMajor = _usVerMajor;
277 options.usVerMinor = _usVerMinor;
278
279 /* Log option summary */
280 #ifdef DEBUG
281 kprintf(("Options - Summary - Start\n"));
282 if (options.fQuiet)
283 kprintf(("\tQuiet init\n"));
284 else
285 kprintf(("\tVerbose init\n"));
286
287 if (options.fLogging)
288 kprintf(("\tlogging enabled\n"));
289 else
290 kprintf(("\tlogging disabled\n"));
291 kprintf(("\tCom port no.%d\n", options.usCom));
292
293 kprintf(("\tKernel: ver%d.%d build %d type %s\n",
294 options.usVerMajor,
295 options.usVerMinor,
296 options.ulBuild,
297 (options.fKernel & KF_SMP) ? "SMP" : "UNI"
298 ));
299 kprintf(("\tfPE=%d (%s)\n", options.fPE, apszPE[MIN(options.fPE, 5)]));
300 kprintf(("\tulInfoLevel=%d (%s)\n", options.ulInfoLevel, apszInfoLevel[MIN(options.ulInfoLevel, 5)]));
301 kprintf(("\tfElf=%d\n", options.fElf));
302 kprintf(("\tfScript=%d\n", options.fScript));
303 kprintf(("\tfNoLoader=%d\n", options.fNoLoader));
304 kprintf(("\tcbSwpHeapInit=0x%08x cbSwpHeapMax=0x%08x\n",
305 options.cbSwpHeapInit, options.cbSwpHeapMax));
306 kprintf(("\tcbResHeapInit=0x%08x cbResHeapMax=0x%08x\n",
307 options.cbSwpHeapInit, options.cbSwpHeapMax));
308 kprintf(("Options - Summary - End\n"));
309 #endif /* debug */
310 /* end option summary */
311
312
313 /*
314 * init sub-parts
315 */
316 /* heap */
317 if (heapInit(options.cbResHeapInit, options.cbResHeapMax,
318 options.cbSwpHeapInit, options.cbSwpHeapMax) != NO_ERROR)
319 return STATUS_DONE | STERR | ERROR_I24_QUIET_INIT_FAIL;
320
321 /* loader */
322 if (!options.fNoLoader)
323 if (ldrInit() != NO_ERROR)
324 return STATUS_DONE | STERR | ERROR_I24_QUIET_INIT_FAIL;
325
326 /* functionoverrides */
327 if (!options.fNoLoader)
328 if (ImportTabInit() != NO_ERROR)
329 return STATUS_DONE | STERR | ERROR_I24_QUIET_INIT_FAIL;
330
331 /*
332 * Lock the 32-bit objects/segments and 16-bit datasegment in memory
333 */
334 /* 32-bit code segment */
335 memset(SSToDS(&lockhandle), 0, sizeof(lockhandle));
336 rc = D32Hlp_VMLock2(&CODE32START,
337 ((unsigned)&CODE32END & ~0xFFF) - (unsigned)&CODE32START, /* Round down so we don't overlap with the next request. */
338 VMDHL_LONG,
339 SSToDS(&lockhandle));
340 if (rc != NO_ERROR)
341 kprintf(("code segment lock failed with with rc=%d\n", rc));
342
343 /* 32-bit data segment */
344 memset(SSToDS(&lockhandle), 0, sizeof(lockhandle));
345 rc = D32Hlp_VMLock2(callTab,
346 &CONST32_ROEND - (char*)callTab,
347 VMDHL_LONG | VMDHL_WRITE,
348 SSToDS(&lockhandle));
349 if (rc != NO_ERROR)
350 kprintf(("data segment lock failed with with rc=%d\n", rc));
351
352 /* 16-bit data segment - is this necessary? */
353 memset(SSToDS(&lockhandle), 0, sizeof(lockhandle));
354 rc = D32Hlp_VMLock2(&DATA16START,
355 &DATA16END - &DATA16START,
356 VMDHL_LONG | VMDHL_WRITE,
357 SSToDS(&lockhandle));
358 if (rc != NO_ERROR)
359 kprintf(("16-bit data segment lock failed with with rc=%d\n", rc));
360
361 return STATUS_DONE;
362}
363
364
365/**
366 * Reads a number (unsigned long integer) for a string.
367 * @returns number read, ~0UL on error / no number read.
368 * @param pszNum Pointer to the string containing the number.
369 * @status competely implemented.
370 * @author knut st. osmundsen
371 */
372static ULONG readnum(const char *pszNum)
373{
374 ULONG ulRet = 0;
375 ULONG ulBase = 10;
376 int i = 0;
377
378 /* determin ulBase */
379 if (*pszNum == '0')
380 if (pszNum[1] == 'x' || pszNum[1] == 'X')
381 {
382 ulBase = 16;
383 pszNum += 2;
384 }
385 else
386 {
387 ulBase = 8;
388 i = 1;
389 }
390
391 /* read digits */
392 while (ulBase == 16 ? (pszNum[i] >= '0' && pszNum[i] <= '9') || (pszNum[i] >= 'a' && pszNum[i] <= 'f') || (pszNum[i] >= 'A' && pszNum[i] <= 'F')
393 : (pszNum[i] >= '0' && pszNum[i] <= (ulBase == 10 ? '9' : '7'))
394 )
395 {
396 ulRet *= ulBase;
397 if (ulBase <= 10)
398 ulRet += pszNum[i] - '0';
399 else
400 ulRet += pszNum[i] - (pszNum[i] >= 'A' ? 'A' - 10 : (pszNum[i] >= 'a' ? 'a' + 9 : '0'));
401
402 i++;
403 }
404
405 return i > 0 ? ulRet : ~0UL;
406}
407
408
409/**
410 * Get kernel OTEs
411 * This function set pKrnlMTE, pKrnlSMTE and pKrnlOTE.
412 * @returns Strategy return code:
413 * STATUS_DONE on success.
414 * STATUS_DONE | STERR | errorcode on failure.
415 * @param pKrnlInfo Pointer to output buffer.
416 * If NULL only the three global variables are set.
417 * @status completely implemented and tested.
418 * @author knut st. osmundsen
419 * @remark Called from IOCtl.
420 * WARNING! This function is called before the initroutine (R0INIT)!
421 */
422USHORT _loadds _Far32 _Pascal GetKernelInfo32(PKRNLINFO pKrnlInfo)
423{
424 int i;
425 USHORT usRc;
426
427 /* VerifyImporTab32 is called before the initroutine! */
428 pulTKSSBase32 = (PULONG)_TKSSBase16;
429
430 /* Find the kernel OTE table */
431 pKrnlMTE = GetOS2KrnlMTE();
432 if (pKrnlMTE != NULL)
433 {
434 pKrnlSMTE = pKrnlMTE->mte_swapmte;
435 if (pKrnlSMTE != NULL)
436 {
437 if (pKrnlSMTE->smte_objcnt <= MAXKRNLOBJECTS)
438 {
439 pKrnlOTE = pKrnlSMTE->smte_objtab;
440 if (pKrnlOTE != NULL)
441 {
442 /*
443 * Thats all?
444 */
445 if (pKrnlInfo == NULL)
446 return NO_ERROR;
447
448 pKrnlInfo->cObjects = (unsigned char)pKrnlSMTE->smte_objcnt;
449
450 /*
451 * Copy OTEs
452 */
453 for (i = 0; i < pKrnlInfo->cObjects; i++)
454 {
455 memcpy((void*)&pKrnlInfo->aObjects[i], &pKrnlOTE[i], sizeof(OTE));
456 kprintf2(("GetKernelInfo32: %d base=0x%08x size=0x%08x flags=0x%08x\n",
457 i, pKrnlOTE[i].ote_base, pKrnlOTE[i].ote_size, pKrnlOTE[i].ote_flags));
458 }
459 usRc = 0;
460
461 /*
462 * Search for internal revision stuff in the two first objects.
463 */
464 pKrnlInfo->usBuild = 0;
465 for (i = 0; i < 2 && pKrnlInfo->usBuild == 0; i++)
466 {
467 const char *psz = (const char*)pKrnlOTE[i].ote_base;
468 const char *pszEnd = psz + pKrnlOTE[i].ote_size;
469
470 while (psz + 100 < pszEnd)
471 {
472 if (strncmp(psz, "Internal revision ", 18) == 0 && (psz[18] >= '0' && psz[18] <= '9'))
473 {
474 int j;
475 kprintf2(("GetOTEs32: found internal revision: '%s'\n", psz));
476
477 /* skip to end of "Internal revision " string. */
478 psz += 18;
479
480 /* Read number*/
481 while ((*psz >= '0' && *psz <= '9') || *psz == '.')
482 {
483 if (*psz != '.')
484 pKrnlInfo->usBuild = (unsigned short)(pKrnlInfo->usBuild * 10 + (*psz - '0'));
485 psz++;
486 }
487
488 /* Check if build number seems valid. */
489 if ( !(pKrnlInfo->usBuild >= 8254 && pKrnlInfo->usBuild < 8383) /* Warp 3 fp 32 -> fp 60 */
490 && !(pKrnlInfo->usBuild >= 9023 && pKrnlInfo->usBuild < 9063) /* Warp 4 GA -> fp 40 */
491 && !(pKrnlInfo->usBuild >= 14039 && pKrnlInfo->usBuild < 14080) /* Warp 4.5 GA -> fp 40 */
492 )
493 {
494 kprintf(("GetOTEs32: info summary: Build %d is invalid - invalid fixpack?\n", pKrnlInfo->usBuild));
495 usRc = 6;
496 break;
497 }
498
499 /* If this is an Aurora or Warp 3 kernel there is more info! */
500 pKrnlInfo->fSMP = (char)(*psz != ','
501 && ( (psz[1] == '_' && (psz[2] == 'S' || psz[2] == 's')) /* F_SMP */
502 || (psz[2] == '_' && (psz[1] == 'S' || psz[1] == 's'))));/* _SMP */
503
504 /* Check if its a debug kernel (look for DEBUG at start of object 3-5) */
505 j = 3;
506 pKrnlInfo->fDebug = FALSE;
507 while (j < 5)
508 {
509
510 /* There should be no iopl object preceding the debugger data object. */
511 if ((pKrnlOTE[j].ote_flags & OBJIOPL) != 0)
512 break;
513 /* Is this is? */
514 if ((pKrnlOTE[j].ote_flags & OBJINVALID) == 0
515 && (pKrnlOTE[j].ote_flags & (OBJREAD | OBJWRITE)) == (OBJREAD | OBJWRITE)
516 && strncmp((char*)pKrnlOTE[j].ote_base, "DEBUG", 5) == 0)
517 {
518 pKrnlInfo->fDebug = TRUE;
519 break;
520 }
521 j++;
522 }
523
524 /* Display info */
525 kprintf(("GetOTEs32: info summary: Build %d, fSMP=%d, fDebug=%d\n",
526 pKrnlInfo->usBuild, pKrnlInfo->fSMP, pKrnlInfo->fDebug));
527
528 /* Break out */
529 break;
530 }
531
532 /* next */
533 psz++;
534 } /* while loop searching for "Internal revision " */
535 } /* for loop on objects 0-1. */
536
537 /* Set error code if not found */
538 if (pKrnlInfo->usBuild == 0)
539 {
540 usRc = 5;
541 kprintf(("GetOTEs32: Internal revision was not found!\n"));
542 }
543 }
544 else
545 usRc = 4;
546 }
547 else
548 usRc = 3;
549 }
550 else
551 usRc = 2;
552 }
553 else
554 usRc = 1;
555
556
557 if (usRc != 0)
558 kprintf(("GetOTEs32: failed. usRc = %d\n", usRc));
559
560 return (USHORT)(usRc | (usRc != NO_ERROR ? STATUS_DONE | STERR : STATUS_DONE));
561}
562#endif /* !DEBUGR3*/
563
564
565
566/**
567 * Functions which cacluates the instructionsize given a ModR/M byte.
568 * @returns Number of bytes to add to cb and pach.
569 * @param bModRM ModR/M byte.
570 * @status completely implemented.
571 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
572 */
573_Inline int ModR_M_32bit(char bModRM)
574{
575 if ((bModRM & 0xc0) == 0x80 /* ex. mov ax,[ebp+11145543h] */
576 || ((bModRM & 0xc0) == 0 && (bModRM & 0x07) == 5)) /* ex. mov ebp,[0ff231234h] */
577 { /* 32-bit displacement */
578 return 5;
579 }
580 else if ((bModRM & 0xc0) == 0x40) /* ex. mov ecx,[esi]+4fh */
581 { /* 8-bit displacement */
582 return 2;
583 }
584 /* no displacement (only /r byte) */
585 return 1;
586}
587
588
589
590
591
592/**
593 * 32-bit! Interpret function prolog to find where to jmp back.
594 * @returns Length of prolog need to be copied - which is also the offset of
595 * where the jmp instr should be placed.
596 * On error it returns 0.
597 * @param pach Pointer to prolog.
598 * @param fOverload TRUE: Function is to be overloaded.
599 * FALSE: Function is to be imported.
600 */
601static int interpretFunctionProlog32(char *pach, BOOL fOverload)
602{
603 int cb = -3;
604
605 kprintf2(("interpretFunctionProlog32(0x%08x, %d):\n"
606 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n"
607 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n",
608 pach, fOverload,
609 pach[0], pach[1], pach[2], pach[3], pach[4], pach[5], pach[6], pach[7],
610 pach[8], pach[9], pach[10],pach[11],pach[12],pach[13],pach[14],pach[15]));
611
612 /*
613 * check for the well known prolog (the only that is supported now)
614 * which is:
615 * push ebp
616 * mov ebp,esp
617 * or
618 * push ebp
619 * mov eax, dword ptr [xxxxxxxx]
620 *
621 * These are allowed when not overloading:
622 * mov eax, imm32
623 * jmp short
624 * or
625 * mov eax, imm32
626 * push ebp
627 * or
628 * mov eax, msoff32
629 *
630 */
631 if ((pach[0] == 0x55 && (pach[1] == 0x8b || pach[1] == 0xa1)) /* two first prologs */
632 ||
633 (pach[0] == 0xB8 && (pach[5] == 0xEB || pach[5] == 0x55 ) && !fOverload) /* two next prologs */
634 ||
635 (pach[0] == 0xa1 && !fOverload) /* last prolog */
636 )
637 {
638 BOOL fForce;
639 cb = 0;
640 while (cb < 5 || fForce) /* 5 is the size of a jump instruction. */
641 {
642 int cb2;
643 fForce = FALSE;
644 switch (*pach)
645 {
646 /* simple one byte prefixes */
647 case 0x2e: /* cs segment override */
648 case 0x36: /* ss segment override */
649 case 0x3e: /* ds segment override */
650 case 0x26: /* es segment override */
651 case 0x64: /* fs segment override */
652 case 0x65: /* gs segment override */
653 fForce = TRUE;
654 break;
655
656 /* simple one byte instructions */
657 case 0x50: /* push ax */
658 case 0x51: /* push cx */
659 case 0x52: /* push dx */
660 case 0x53: /* push bx */
661 case 0x54: /* push sp */
662 case 0x55: /* push bp */
663 case 0x56: /* push si */
664 case 0x57: /* push di */
665 break;
666
667 /* simple two byte instructions */
668 case 0xb0: /* mov al, imm8 */
669 case 0xb1: /* mov cl, imm8 */
670 case 0xb2: /* mov dl, imm8 */
671 case 0xb3: /* mov bl, imm8 */
672 case 0xb4: /* mov ah, imm8 */
673 case 0xb5: /* mov ch, imm8 */
674 case 0xb6: /* mov dh, imm8 */
675 case 0xb7: /* mov bh, imm8 */
676 case 0x2c: /* sub al, imm8 */
677 case 0x34: /* xor al, imm8 */
678 case 0x3c: /* cmp al, imm8 */
679 case 0x6a: /* push <byte> */
680 case 0xa0: /* mov al, moffs8 */
681 case 0xa2: /* mov moffs8, al */
682 pach++;
683 cb++;
684 break;
685
686 /* simple five byte instructions */
687 case 0xb8: /* mov eax, imm32 */
688 case 0xb9: /* mov ecx, imm32 */
689 case 0xba: /* mov edx, imm32 */
690 case 0xbb: /* mov ebx, imm32 */
691 case 0xbc: /* mov esx, imm32 */
692 case 0xbd: /* mov ebx, imm32 */
693 case 0xbe: /* mov esi, imm32 */
694 case 0xbf: /* mov edi, imm32 */
695 case 0x2d: /* sub eax, imm32 */
696 case 0x35: /* xor eax, imm32 */
697 case 0x3d: /* cmp eax, imm32 */
698 case 0x68: /* push <dword> */
699 case 0xa1: /* mov eax, moffs16 */
700 case 0xa3: /* mov moffs16, eax */
701 pach += 4;
702 cb += 4;
703 break;
704
705 /* complex sized instructions - "/r" */
706 case 0x30: /* xor r/m8, r8 */
707 case 0x31: /* xor r/m32, r32 */
708 case 0x32: /* xor r8, r/m8 */
709 case 0x33: /* xor r32, r/m32 */
710 case 0x38: /* cmp r/m8, r8 */
711 case 0x39: /* cmp r/m32, r32 */
712 case 0x3a: /* cmp r8, r/m8 */
713 case 0x3b: /* cmp r32, r/m32 */
714 case 0x28: /* sub r/m8, r8 */
715 case 0x29: /* sub r/m32, r32 */
716 case 0x2a: /* sub r8, r/m8 */
717 case 0x2b: /* sub r32, r/m32 */
718 case 0x8b: /* mov /r */
719 case 0x8d: /* lea /r */
720 if ((pach[1] & 0x7) == 4 && (pach[1] & 0xc0) != 0xc0) /* invalid instruction!?! */
721 return -1;
722 cb += cb2 = ModR_M_32bit(pach[1]);
723 pach += cb2;
724 break;
725
726 /* complex sized instruction - "/5 ib" */
727 case 0x80: /* 5: sub r/m8, imm8 7: cmp r/m8, imm8 */
728 case 0x83: /* 5: sub r/m32, imm8 7: cmp r/m32, imm8 */
729 if ((pach[1] & 0x38) == (5<<3)
730 || (pach[1] & 0x38) == (7<<3)
731 )
732 {
733 cb += cb2 = 1 + ModR_M_32bit(pach[1]); /* 1 is the size of the imm8 */
734 pach += cb2;
735 }
736 else
737 {
738 kprintf(("interpretFunctionProlog32: unknown instruction (-3) 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
739 return -3;
740 }
741 break;
742
743 /* complex sized instruction - "/digit id" */
744 case 0x81: /* sub r/m32, imm32 + more instructions! */
745 if ((pach[1] & 0x38) == (5<<3) /* sub r/m32, imm32 */
746 || (pach[1] & 0x38) == (7<<3) /* cmp r/m32, imm32 */
747 )
748 {
749 cb += cb2 = 4 + ModR_M_32bit(pach[1]); /* 4 is the size of the imm32 */
750 pach += cb2;
751 }
752 else
753 {
754 kprintf(("interpretFunctionProlog32: unknown instruction (-2) 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
755 return -2;
756 }
757 break;
758
759 default:
760 kprintf(("interpretFunctionProlog32: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
761 return 0;
762 }
763 pach++;
764 cb++;
765 }
766 }
767 else
768 {
769 kprintf(("interpretFunctionProlog32: unknown prolog start. 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
770 cb = 0;
771 }
772 return cb;
773}
774
775
776/**
777 * 16-bit! Interpret function prolog to find where to jmp back.
778 * @returns Length of prolog need to be copied - which is also the offset of
779 * where the jmp instr should be placed.
780 * On error it returns 0.
781 * @param pach Pointer to prolog.
782 * @param fOverload TRUE: Function is to be overloaded.
783 * FALSE: Function is to be imported.
784 */
785static int interpretFunctionProlog16(char *pach, BOOL fOverload)
786{
787 int cb = -7;
788
789 kprintf2(("interpretFunctionProlog16(0x%08x, %d):\n"
790 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n"
791 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n",
792 pach, fOverload,
793 pach[0], pach[1], pach[2], pach[3], pach[4], pach[5], pach[6], pach[7],
794 pach[8], pach[9], pach[10],pach[11],pach[12],pach[13],pach[14],pach[15]));
795 /*
796 * Check for the well known prolog (the only that is supported now)
797 * which is:
798 * push 2
799 */
800 if (*pach == 0x6A) /* push 2 (don't check for the 2) */
801 {
802 BOOL fForce;
803 int cOpPrefix = 0;
804 cb = 0;
805 while (cb < 8 || fForce) /* 8 is the size of a 66h prefixed far jump instruction. */
806 {
807 fForce = FALSE;
808 switch (*pach)
809 {
810 case 0x0f: /* push gs and push fs */
811 if (pach[1] != 0xA0 && pach[1] != 0xA8)
812 {
813 kprintf(("interpretFunctionProlog16: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
814 return -11;
815 }
816 pach++;
817 cb++;
818 break;
819
820 case 0x50: /* push ax */
821 case 0x51: /* push cx */
822 case 0x52: /* push dx */
823 case 0x53: /* push bx */
824 case 0x54: /* push sp */
825 case 0x55: /* push bp */
826 case 0x56: /* push si */
827 case 0x57: /* push di */
828 break;
829
830 case 0x2e: /* cs segment override */
831 case 0x36: /* ss segment override */
832 case 0x3e: /* ds segment override */
833 case 0x26: /* es segment override */
834 case 0x64: /* fs segment override */
835 case 0x65: /* gs segment override */
836 fForce = TRUE;
837 if (cOpPrefix > 0)
838 cOpPrefix++;
839 break;
840
841 case 0x66:
842 cOpPrefix = 2; /* it's decremented once before it's used. */
843 fForce = TRUE;
844 break;
845
846 case 0x6a: /* push <byte> */
847 pach++;
848 cb++;
849 break;
850
851 case 0x68: /* push <word> */
852 if (cOpPrefix > 0)
853 {
854 pach += 2;
855 cb += 2;
856 }
857 pach += 2;
858 cb += 2;
859 break;
860
861 case 0x8b: /* mov /r */
862 if ((pach[1] & 0xc0) == 0x80 /* ex. mov ax,bp+1114h */
863 || ((pach[1] & 0xc0) == 0 && (pach[1] & 0x7) == 6)) /* ex. mov bp,0ff23h */
864 { /* 16-bit displacement */
865 if (cOpPrefix > 0)
866 {
867 pach += 2;
868 cb += 2;
869 }
870 pach += 3;
871 cb += 3;
872 }
873 else
874 if ((pach[1] & 0xc0) == 0x40) /* ex. mov ax,[si]+4fh */
875 { /* 8-bit displacement */
876 pach += 2;
877 cb += 2;
878 }
879 else
880 { /* no displacement (only /r byte) */
881 pach++;
882 cb++;
883 }
884 break;
885
886 default:
887 kprintf(("interpretFunctionProlog16: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
888 return 0;
889 }
890 pach++;
891 cb++;
892 if (cOpPrefix > 0)
893 cOpPrefix--;
894 }
895 }
896
897 fOverload = fOverload;
898 return cb;
899}
900
901
902#ifndef DEBUGR3
903/**
904 * Verifies the aImportTab.
905 * @returns 0 if ok. !0 if not ok.
906 * @remark Called from IOCtl.
907 * WARNING! This function is called before the initroutine (R0INIT)!
908 */
909USHORT _loadds _Far32 _Pascal VerifyImportTab32(void)
910{
911 int i;
912 int cb;
913 int cbmin;
914
915 /* VerifyImporTab32 is called before the initroutine! */
916 pulTKSSBase32 = (PULONG)_TKSSBase16;
917
918 /* Check that pKrnlOTE is set */
919 if (GetKernelInfo32(NULL) != NO_ERROR)
920 return STATUS_DONE | STERR | 1;
921
922 /*
923 * Verify aImportTab.
924 */
925 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
926 {
927 /*
928 * Debug info
929 */
930 kprintf2(("VerifyImportTab32: procedure no.%d is being checked: %s addr=0x%08x iObj=%d offObj=%d\n",
931 i, &_aImportTab[i].achName[0], _aImportTab[i].ulAddress,
932 _aImportTab[i].iObject, _aImportTab[i].offObject));
933
934 /* Verify that it is found */
935 if (!_aImportTab[i].fFound)
936 {
937 kprintf(("VerifyImportTab32: procedure no.%d was not fFound!\n", i));
938 return STATUS_DONE | STERR | 2;
939 }
940
941 /* Verify read/writeable. */
942 if (_aImportTab[i].iObject >= pKrnlSMTE->smte_objcnt /* object index valid? */
943 || _aImportTab[i].ulAddress < pKrnlOTE[_aImportTab[i].iObject].ote_base /* address valid? */
944 || _aImportTab[i].ulAddress + 16 > (pKrnlOTE[_aImportTab[i].iObject].ote_base +
945 pKrnlOTE[_aImportTab[i].iObject].ote_size) /* address valid? */
946 || _aImportTab[i].ulAddress - _aImportTab[i].offObject
947 != pKrnlOTE[_aImportTab[i].iObject].ote_base /* offObject ok? */
948 )
949 {
950 kprintf(("VerifyImportTab32: procedure no.%d has an invalid address or object number.!\n"
951 " %s addr=0x%08x iObj=%d offObj=%d\n",
952 i, &_aImportTab[i].achName[0], _aImportTab[i].ulAddress,
953 _aImportTab[i].iObject, _aImportTab[i].offObject));
954 return STATUS_DONE | STERR | 3;
955 }
956
957
958
959 if (_aImportTab[i].ulAddress < 0xffe00000UL)
960 {
961 kprintf(("VerifyImportTab32: procedure no.%d has an invalid address, %#08x!\n",
962 i, _aImportTab[i].ulAddress));
963 return STATUS_DONE | STERR | 4;
964 }
965
966 switch (_aImportTab[i].fType & ~EPT_BIT_MASK)
967 {
968 case EPT_PROC:
969 case EPT_PROCIMPORT:
970 /*
971 * Verify known function prolog.
972 */
973 if (EPT32BitEntry(_aImportTab[i]))
974 {
975 cb = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress,
976 _aImportTab[i].fType == EPT_PROC32);
977 cbmin = 5; /* Size of the jump instruction */
978 }
979 else
980 {
981 cb = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress,
982 _aImportTab[i].fType == EPT_PROC16);
983 cbmin = 7; /* Size of the far jump instruction */
984 }
985
986 /*
987 * Check result of the function prolog interpretations.
988 */
989 if (cb <= 0 && cb + cbmin >= MAXSIZE_PROLOG)
990 { /* failed, too small or too large. */
991 kprintf(("VerifyImportTab32: verify failed for procedure no.%d (cd=%d)\n", i, cb));
992 return STATUS_DONE | STERR | 5;
993 }
994 break;
995
996 case EPT_VARIMPORT:
997 /* do nothing! */
998 break;
999
1000 default:
1001 kprintf(("VerifyImportTab32: only EPT_PROC is implemented\n",i));
1002 Int3(); /* temporary fix! */
1003 return STATUS_DONE | STERR | 6;
1004 }
1005 }
1006
1007 return STATUS_DONE;
1008}
1009
1010
1011/**
1012 * Initiates the overrided functions.
1013 * @returns NO_ERROR on success. !0 on error.
1014 */
1015static int importTabInit(void)
1016{
1017 /* This table must be updated with the overloading functions. */
1018 static unsigned auFuncs[NBR_OF_KRNLIMPORTS] =
1019 {
1020 (unsigned)myldrRead,
1021 (unsigned)myldrOpen,
1022 (unsigned)myldrClose,
1023 (unsigned)myLDRQAppType,
1024 (unsigned)myldrEnum32bitRelRecs,
1025 0,
1026 0,
1027 0,
1028 0,
1029 0,
1030 0,
1031 0,
1032 0,
1033 (unsigned)&mytkExecPgm,
1034 0,
1035 0,
1036 0
1037 };
1038
1039 int i;
1040 int cb;
1041 int cbmin;
1042
1043 /*
1044 * verify proctable
1045 */
1046 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1047 {
1048 /* EPT_VARIMPORTs are skipped */
1049 if ((_aImportTab[i].fType & ~EPT_BIT_MASK) == EPT_VARIMPORT)
1050 continue;
1051
1052 if (EPT32BitEntry(_aImportTab[i]))
1053 {
1054 cb = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress, _aImportTab[i].fType == EPT_PROC32);
1055 cbmin = 5; /* Size of the jump instruction */
1056 }
1057 else
1058 {
1059 cb = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress, _aImportTab[i].fType == EPT_PROC16);
1060 cbmin = 7; /* Size of the far jump instruction */
1061 }
1062 if (cb <= 0 || cb + cbmin >= MAXSIZE_PROLOG)
1063 {
1064 kprintf(("ImportTabInit: Verify failed for procedure no.%d, cb=%d\n", i, cb));
1065 return 1;
1066 }
1067 }
1068
1069 /*
1070 * rehook / import
1071 */
1072 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1073 {
1074 switch (_aImportTab[i].fType)
1075 {
1076 /*
1077 * 32-bit procedure overload.
1078 * The overloading procedure is found in the auFuncs table (at the same index
1079 * as the overloaded procedure has in aImportTab).
1080 * The overloaded procedure is called by issuing a call to the callTab entry.
1081 */
1082 case EPT_PROC32:
1083 {
1084 cb = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress, TRUE);
1085 _aImportTab[i].cbProlog = (char)cb;
1086 if (cb >= 5 && cb + 5 < MAXSIZE_PROLOG) /* 5(1st): size of jump instruction in the function prolog which jumps to my overloading function */
1087 { /* 5(2nd): size of jump instruction which jumps back to the original function after executing the prolog copied to the callTab entry for this function. */
1088 /*
1089 * Copy function prolog which will be overwritten by the jmp to calltabl.
1090 */
1091 memcpy(callTab[i], (void*)_aImportTab[i].ulAddress, (size_t)cb);
1092
1093 /*
1094 * Make jump instruction which jumps from calltab to original function.
1095 * 0xE9 <four bytes displacement>
1096 * Note: the displacement is relative to the next instruction
1097 */
1098 callTab[i][cb] = 0xE9; /* jmp */
1099 *(unsigned long*)(void*)&callTab[i][cb+1] = _aImportTab[i].ulAddress + cb - (unsigned long)&callTab[i][cb+5];
1100
1101 /*
1102 * Jump from original function to my function - an cli(?) could be needed here
1103 */
1104 *(char*)_aImportTab[i].ulAddress = 0xE9; /* jmp */
1105 *(unsigned long*)(_aImportTab[i].ulAddress + 1) = auFuncs[i] - (_aImportTab[i].ulAddress + 5);
1106 }
1107 else
1108 { /* !fatal! - this could never happen really... */
1109 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n",i));
1110 Int3(); /* ipe - later! */
1111 return 1;
1112 }
1113 break;
1114 }
1115
1116
1117 /*
1118 * 16-bit procedure overload.
1119 * Currently disabled due to expected problems when calltab is a 32-bit segment.
1120 */
1121 case EPT_PROC16:
1122 {
1123 kprintf(("ImportTabInit: Overloading 16-bit procedures are not supported yet!!! Calltable in 32-bit segment!\n", i));
1124 Int3();
1125
1126 cb = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress, TRUE);
1127 _aImportTab[i].cbProlog = (char)cb;
1128 if (cb >= 8 && cb + 7 < MAXSIZE_PROLOG) /* 8: size of a 16:32 jump which jumps to my overloading function (prefixed with 66h in a 16-bit segment) */
1129 { /* 7: size of a 16:32 jump which is added to the call tab */
1130 /*
1131 * Copy function prolog which is to be overwritten.
1132 */
1133 memcpy(callTab[i], (void*)_aImportTab[i].ulAddress, (size_t)cb);
1134
1135 /*
1136 * Create far jump from calltab to original function.
1137 * 0xEA <four byte target address> <two byte target selector>
1138 */
1139 callTab[i][cb] = 0xEA; /* jmp far ptr */
1140 *(unsigned long*)(void*)&callTab[i][cb+1] = _aImportTab[i].offObject;
1141 *(unsigned short*)(void*)&callTab[i][cb+5] = _aImportTab[i].usSel;
1142
1143 /*
1144 * jump from original function to my function - an cli(?) could be needed here
1145 * 0x66 0xEA <four byte target address> <two byte target selector>
1146 */
1147 *(char*)(_aImportTab[i].ulAddress ) = 0x66; /* operandsize prefix */
1148 *(char*)(_aImportTab[i].ulAddress + 1) = 0xEA; /* jmp far ptr */
1149 *(unsigned long*)(_aImportTab[i].ulAddress + 2) = auFuncs[i]; /* FIXME? */
1150 *(unsigned short*)(_aImportTab[i].ulAddress + 6) = _R0FlatCS16; /* FIXME */
1151 }
1152 else
1153 { /* !fatal! - this could never happen really... */
1154 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n",i));
1155 Int3(); /* ipe - later! */
1156 return 1;
1157 }
1158 break;
1159 }
1160
1161
1162 /*
1163 * 32-bit imported procedure
1164 * This is called by issuing a near call to the callTab entry.
1165 */
1166 case EPT_PROCIMPORT32:
1167 {
1168 cb = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress, FALSE);
1169 _aImportTab[i].cbProlog = (char)cb;
1170 if (cb > 0) /* Since no prolog part is copied to the function table, it's ok as long as the prolog has been recognzied. */
1171 {
1172 /*
1173 * Make jump instruction which jumps from calltab to original function.
1174 * 0xE9 <four bytes displacement>
1175 * Note: the displacement is relative to the next instruction
1176 */
1177 callTab[i][0] = 0xE9; /* jmp */
1178 *(unsigned*)(void*)&callTab[i][1] = _aImportTab[i].ulAddress - (unsigned)&callTab[i][5];
1179 }
1180 else
1181 { /* !fatal! - this should never really happen... */
1182 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n",i));
1183 Int3(); /* ipe - later! */
1184 return 1;
1185 }
1186 break;
1187 }
1188
1189
1190 /*
1191 * 16-bit imported procedure.
1192 * This is called by issuing a far call to the calltab entry.
1193 */
1194 case EPT_PROCIMPORT16:
1195 {
1196 cb = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress, FALSE);
1197 _aImportTab[i].cbProlog = (char)cb;
1198 if (cb > 0) /* Since no prolog part is copied to the function table, it's ok as long as the prolog has been recognzied. */
1199 {
1200 /*
1201 * Create far jump from calltab to original function.
1202 * 0xEA <four byte target address> <two byte target selector>
1203 */
1204 callTab[i][0] = 0xEA; /* jmp far ptr */
1205 *(unsigned long*)(void*)&callTab[i][1] = _aImportTab[i].offObject;
1206 *(unsigned short*)(void*)&callTab[i][5] = _aImportTab[i].usSel;
1207 }
1208 else
1209 { /* !fatal! - this should never really happen... */
1210 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n",i));
1211 Int3(); /* ipe - later! */
1212 return 1;
1213 }
1214 break;
1215 }
1216
1217
1218 /*
1219 * 16/32-bit importe variable.
1220 * This is used by accessing the 32-bit flat address in the callTab.
1221 * callTab-entry + 4 holds the offset of the variable into the object.
1222 * callTab-entry + 8 holds the selector for the object. (These two fields is the 16:32-bit pointer to the variable.)
1223 * callTab-entry + a holds the 16-bit offset for the variable.
1224 * callTab-entry + c holds the selector for the object. (These two fiels is the 16:16-bit pointer to the variable.)
1225 */
1226 case EPT_VARIMPORT32:
1227 case EPT_VARIMPORT16:
1228 _aImportTab[i].cbProlog = (char)0;
1229 *(unsigned long*)(void*)&callTab[i][0] = _aImportTab[i].ulAddress;
1230 *(unsigned long*)(void*)&callTab[i][4] = _aImportTab[i].offObject;
1231 *(unsigned short*)(void*)&callTab[i][8] = _aImportTab[i].usSel;
1232 *(unsigned short*)(void*)&callTab[i][0xa] = (unsigned short)_aImportTab[i].offObject;
1233 *(unsigned short*)(void*)&callTab[i][0xc] = _aImportTab[i].usSel;
1234 break;
1235
1236 default:
1237 kprintf(("ImportTabInit: unsupported type. (procedure no.%d, cb=%d)\n", i, cb));
1238 Int3(); /* ipe - later! */
1239 return 1;
1240 } /* switch - type */
1241 } /* for */
1242
1243 return NO_ERROR;
1244}
1245#endif /* !DEBUGR3 */
1246
1247
1248
1249
1250/*******************************************************************************
1251* Ring-3 Debug Stuff
1252*******************************************************************************/
1253#ifdef DEBUGR3
1254#include <stdio.h>
1255
1256void main(void)
1257{
1258 char ach_ldrRead[] = {
1259 0x55, 0x8b, 0xec, 0x8d, 0x65, 0xf8, 0x53, 0x56,
1260 0x57, 0x33, 0xd2, 0x42, 0x89, 0x55, 0xf8, 0x38,
1261 0x35, 0xce, 0x70, 0x00, 0x00, 0x75, 0x4d, 0x8b,
1262 0x55, 0x08, 0x66, 0x83, 0xfa, 0xff, 0x74, 0x62
1263 };
1264 char ach_ldrOpen[] = {
1265 0x55, 0x8b, 0xec, 0x33, 0xc0, 0x38, 0x05, 0xce,
1266 0x70, 0x00, 0x00, 0x75, 0x4b, 0x50, 0xff, 0x75,
1267 0x08, 0x6a, 0x01, 0x68, 0xa3, 0x00, 0x00, 0x00,
1268 0xff, 0x75, 0x0c, 0xff, 0x15, 0xc4, 0xc1, 0x0d
1269 };
1270 char ach_ldrClose[] = {
1271 0x55, 0x8b, 0xec, 0x33, 0xc0, 0x38, 0x05, 0xce,
1272 0x70, 0x00, 0x00, 0x75, 0x13, 0x8b, 0x55, 0x08,
1273 0x0f, 0xb7, 0xd2, 0x66, 0x83, 0xfa, 0xff, 0x74,
1274 0x07, 0x52, 0xff, 0x15, 0xcc, 0xc1, 0x0d, 0x00
1275 };
1276 char ach_LDRQAppType[] = {
1277 0x55, 0x8b, 0x0d, 0xa0, 0x0a, 0x00, 0x00, 0x8b,
1278 0xec, 0x83, 0xec, 0x3c, 0x53, 0x81, 0xc1, 0x24,
1279 0x06, 0x00, 0x00, 0x57, 0x56, 0x6a, 0xff, 0x66,
1280 0xc7, 0x45, 0xc6, 0x00, 0x00, 0x51, 0xe8, 0x38
1281 };
1282 char ach_ldrEnum32bitRelRecs[] = {
1283 0x55, 0xa1, 0xe8, 0xcf, 0x0d, 0x00, 0x8b, 0xec,
1284 0x83, 0xec, 0x5c, 0x53, 0x8b, 0x55, 0x08, 0x57,
1285 0x56, 0x8b, 0x52, 0x04, 0xf6, 0x40, 0x04, 0x80,
1286 0x89, 0x55, 0xfc, 0x0f, 0x84, 0x10, 0x01, 0x00
1287 };
1288 char ach_IOSftOpen[] = {
1289 0x55, 0x8b, 0xec, 0x8d, 0xa5, 0xa0, 0xfe, 0xff,
1290 0xff, 0xf6, 0x05, 0x95, 0x2d, 0x00, 0x00, 0x80,
1291 0x74, 0x13, 0x66, 0x68, 0x50, 0x30, 0xff, 0x75,
1292 0x08, 0x6a, 0x3c, 0x6a, 0x06, 0xe8, 0x5a, 0x03
1293 };
1294 char ach_IOSftClose[] = {
1295 0x55, 0x8b, 0xec, 0x8d, 0xa5, 0x28, 0xff, 0xff,
1296 0xff, 0xf6, 0x05, 0x95, 0x2d, 0x00, 0x00, 0x80,
1297 0x74, 0x16, 0x50, 0x66, 0x68, 0x51, 0x30, 0x8b,
1298 0x45, 0x08, 0x50, 0x6a, 0x0c, 0x6a, 0x06, 0xe8
1299 };
1300 char ach_IOSftTransPath[] = {
1301 0x55, 0x8b, 0xec, 0x8d, 0xa5, 0xd8, 0xfd, 0xff,
1302 0xff, 0x53, 0x56, 0x57, 0x1e, 0x06, 0xa1, 0xa4,
1303 0x0a, 0x00, 0x00, 0x66, 0x8d, 0x9d, 0xe2, 0xfe,
1304 0xff, 0xff, 0x66, 0x89, 0x98, 0xf6, 0x01, 0x00
1305 };
1306 char ach_IOSftReadAt[] = {
1307 0xb8, 0xc4, 0x68, 0x14, 0x00, 0xeb, 0x05, 0xb8,
1308 0xcc, 0x68, 0x14, 0x00, 0x55, 0x8b, 0xec, 0x8d,
1309 0xa5, 0x20, 0xff, 0xff, 0xff, 0xf6, 0x05, 0x95,
1310 0x2d, 0x00, 0x00, 0x80, 0x74, 0x28, 0x50, 0x66
1311 };
1312 char ach_IOSftWriteAt[] = {
1313 0xb8, 0xcc, 0x68, 0x14, 0x00, 0x55, 0x8b, 0xec,
1314 0x8d, 0xa5, 0x20, 0xff, 0xff, 0xff, 0xf6, 0x05,
1315 0x95, 0x2d, 0x00, 0x00, 0x80, 0x74, 0x28, 0x50,
1316 0x66, 0x68, 0x52, 0x30, 0x8b, 0x45, 0x08, 0x25
1317 };
1318 char ach_SftFileSize[] = {
1319 0x55, 0x8b, 0xec, 0x8d, 0xa5, 0x28, 0xff, 0xff,
1320 0xff, 0x57, 0x56, 0x53, 0xc6, 0x85, 0x2b, 0xff,
1321 0xff, 0xff, 0x00, 0x8b, 0x35, 0xa4, 0x0a, 0x00,
1322 0x00, 0xf6, 0x46, 0x04, 0x01, 0x74, 0x0a, 0x80
1323 };
1324 char ach_VMAllocMem[] = {
1325 0xa1, 0xe8, 0xcf, 0x0d, 0x00, 0x55, 0x8b, 0xec,
1326 0x83, 0xec, 0x44, 0x53, 0x57, 0xf6, 0x40, 0x04,
1327 0x80, 0x56, 0x0f, 0x84, 0x34, 0x01, 0x00, 0x00,
1328 0xf6, 0x00, 0x40, 0x74, 0x44, 0xa1, 0xcc, 0x02
1329 };
1330 char ach_VMGetOwner[] = {
1331 0x55, 0x8b, 0xec, 0x83, 0xec, 0x30, 0x57, 0x66,
1332 0x8b, 0x4d, 0x08, 0x66, 0x89, 0x4d, 0xd8, 0xf6,
1333 0xc1, 0x04, 0x75, 0x39, 0x80, 0x3d, 0x40, 0x8c,
1334 0x00, 0x00, 0x00, 0x74, 0x07, 0xa1, 0xac, 0x0a
1335 };
1336 char achg_tkExecPgm[] = {
1337 0x55, 0x8b, 0xec, 0x8d, 0x65, 0xa4, 0x66, 0x89,
1338 0x5d, 0xf4, 0x66, 0x8c, 0x45, 0xf6, 0x66, 0x89,
1339 0x55, 0xfc, 0x66, 0x8c, 0x5d, 0xfe, 0x66, 0x89,
1340 0x75, 0xf0, 0x66, 0x89, 0x7d, 0xf2, 0xc7, 0x45
1341 };
1342 char achf_FuStrLenZ[] = {
1343 0x6a, 0x02, 0x52, 0x66, 0x55, 0x0f, 0xa8, 0x68,
1344 0x0c, 0x00, 0x0f, 0xa9, 0x65, 0x67, 0x66, 0x8b,
1345 0x2d, 0xa8, 0x0a, 0x00, 0x00, 0x65, 0x67, 0xff,
1346 0xb5, 0xb4, 0x1f, 0x00, 0x00, 0x65, 0x67, 0x66
1347 };
1348 char achf_FuStrLen[] = {
1349 0x6a, 0x02, 0x52, 0x66, 0x55, 0x0f, 0xa8, 0x68,
1350 0x0c, 0x00, 0x0f, 0xa9, 0x65, 0x67, 0x66, 0x8b,
1351 0x2d, 0xa8, 0x0a, 0x00, 0x00, 0x65, 0x67, 0xff,
1352 0xb5, 0xb4, 0x1f, 0x00, 0x00, 0x65, 0x67, 0x66
1353 };
1354 char achf_FuBuff[] = {
1355 0x6a, 0x02, 0x52, 0x66, 0x55, 0x0f, 0xa8, 0x68,
1356 0x0c, 0x00, 0x0f, 0xa9, 0x65, 0x67, 0x66, 0x8b,
1357 0x2d, 0xa8, 0x0a, 0x00, 0x00, 0x65, 0x67, 0xff,
1358 0xb5, 0xb4, 0x1f, 0x00, 0x00, 0x65, 0x67, 0x66
1359 };
1360
1361
1362 char *aProcs[] =
1363 {
1364 ach_ldrRead ,
1365 ach_ldrOpen ,
1366 ach_ldrClose ,
1367 ach_LDRQAppType ,
1368 ach_ldrEnum32bitRelRecs,
1369 ach_IOSftOpen ,
1370 ach_IOSftClose ,
1371 ach_IOSftTransPath ,
1372 ach_IOSftReadAt ,
1373 ach_IOSftWriteAt ,
1374 ach_SftFileSize ,
1375 ach_VMAllocMem ,
1376 ach_VMGetOwner ,
1377 achg_tkExecPgm ,
1378 achf_FuStrLenZ ,
1379 achf_FuStrLen ,
1380 achf_FuBuff ,
1381 NULL
1382 };
1383 int i;
1384
1385 /* loop thru procs */
1386 for (i = 0; aProcs[i] != NULL; i++)
1387 {
1388 unsigned cb;
1389 printf("Proc.no.%i\n", i);
1390 if (i < 14 )
1391 cb = interpretFunctionProlog32(aProcs[i], i < 5 || i == 13);
1392 else
1393 cb = interpretFunctionProlog16(aProcs[i], FALSE);
1394 printf(" cb=%d\n\n", cb);
1395 }
1396}
1397#endif
Note: See TracBrowser for help on using the repository browser.