source: trunk/src/win32k/dev16/probkrnl.c@ 3832

Last change on this file since 3832 was 3411, checked in by bird, 25 years ago

Added new function import.
Added some new modules.

File size: 46.4 KB
Line 
1/* $Id: probkrnl.c,v 1.20 2000-04-17 01:56:48 bird Exp $
2 *
3 * Description: Autoprobes the os2krnl file and os2krnl[*].sym files.
4 * Another Hack!
5 *
6 * 16-bit inittime code.
7 *
8 * All data has to be initiated because this is 16-bit C code
9 * and is to be linked with 32-bit C/C++ code. Uninitiazlied
10 * data ends up in the BSS segment, and that segment can't
11 * both be 32-bit and 16-bit. I have not found any other way
12 * around this problem that initiating all data.
13 *
14 * How this works:
15 * 1. parses the device-line parameters and collects some "SysInfo".
16 * 2. gets the kernel object table. (elf$)
17 * 3. finds the kernel image and scans it for a build number.
18 * 4. locates and scans the symbol-file(s) for the entrypoints which are wanted.
19 * 5. the entry points are verified. (elf$)
20 * 6. finished.
21 *
22 * Copyright (c) 1998-2000 knut st. osmundsen
23 *
24 * Project Odin Software License can be found in LICENSE.TXT
25 *
26 */
27
28
29/*******************************************************************************
30* Defined Constants And Macros *
31*******************************************************************************/
32/* Disable logging when doing extracts */
33#if defined(EXTRACT) || defined(RING0)
34 #define NOLOGGING 1
35#endif
36
37#define fclose(a) DosClose(a)
38#define SEEK_SET FILE_BEGIN
39#define SEEK_END FILE_END
40
41#define WORD unsigned short int
42#define DWORD unsigned long int
43
44/* "@#IBM:14.039#@ os2krnl... "*/
45/* "@#IBM:8.264#@ os2krnl... "*/
46#define KERNEL_ID_STRING_LENGTH 42
47#define KERNEL_READ_SIZE 512
48
49#define INCL_BASE
50#define INCL_DOS
51#define INCL_NOPMAPI
52
53
54/*******************************************************************************
55* Header Files *
56*******************************************************************************/
57#include <os2.h>
58
59#include <exe386.h>
60#include <strat2.h>
61#include <reqpkt.h>
62
63#include "os2krnl.h" /* must be included before dev1632.h! */
64#include "sym.h"
65#include "probkrnl.h"
66#include "dev16.h"
67#include "dev1632.h"
68#include "vprntf16.h"
69#include "log.h"
70
71
72/*******************************************************************************
73* Global Variables *
74* Note: must be inited or else we'll get BSS segment *
75*******************************************************************************/
76/*
77 * kernel data - !only valid during init!
78 */
79
80/*
81 * aImportTab defines the imported and overloaded OS/2 kernel functions.
82 * IMPORTANT: aImportTab has a sibling array in d32init.c, aulProc, which must
83 * match entry by entry. Adding/removing/shuffling aImportTab, aulProc
84 * has to be updated immediately!
85 */
86IMPORTKRNLSYM aImportTab[NBR_OF_KRNLIMPORTS] =
87{/* iFound cchName offObject usSel fType */
88 /* iObject achName ulAddress cProlog */
89 {FALSE, -1, 8, "_ldrRead", -1, -1, -1, -1, EPT_PROC32}, /* 0 */
90 {FALSE, -1, 8, "_ldrOpen", -1, -1, -1, -1, EPT_PROC32}, /* 1 */
91 {FALSE, -1, 9, "_ldrClose", -1, -1, -1, -1, EPT_PROC32}, /* 2 */
92 {FALSE, -1, 12, "_LDRQAppType", -1, -1, -1, -1, EPT_PROC32}, /* 3 */
93 {FALSE, -1, 20, "_ldrEnum32bitRelRecs", -1, -1, -1, -1, EPT_PROC32}, /* 4 */
94 {FALSE, -1, 10, "_IOSftOpen", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 5 */
95 {FALSE, -1, 11, "_IOSftClose", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 6 */
96 {FALSE, -1, 15, "_IOSftTransPath", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 7 */
97 {FALSE, -1, 12, "_IOSftReadAt", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 8 */
98 {FALSE, -1, 13, "_IOSftWriteAt", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 9 */
99 {FALSE, -1, 12, "_SftFileSize", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 10 */
100 {FALSE, -1, 11, "_VMAllocMem", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 11 */
101 {FALSE, -1, 11, "_VMGetOwner", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 12 */
102 {FALSE, -1, 11, "g_tkExecPgm", -1, -1, -1, -1, EPT_PROC32}, /* 13 */
103 {FALSE, -1, 11, "f_FuStrLenZ", -1, -1, -1, -1, EPT_PROCIMPORT16}, /* 14 */
104 {FALSE, -1, 10, "f_FuStrLen", -1, -1, -1, -1, EPT_PROCIMPORT16}, /* 15 */
105 {FALSE, -1, 8, "f_FuBuff", -1, -1, -1, -1, EPT_PROCIMPORT16}, /* 16 */
106 {FALSE, -1, 16, "_VMObjHandleInfo", -1, -1, -1, -1, EPT_PROCIMPORT} /* 17 */
107/* {FALSE, -1, 11, "", -1, -1, -1, EPT_PROCIMPORT16} */ /* 16 */
108};
109
110unsigned short int usBuild = 0;
111unsigned short usVerMajor = 0;
112unsigned short usVerMinor = 0;
113unsigned char fchType = TYPE_UNI; /* TYPE_SMP, TYPE_UNI, TYPE_W4 */
114unsigned char fDebug = FALSE;
115
116
117/*
118 * privat data
119 */
120static int fQuiet = 0;
121static char szUsrOS2Krnl[50] = {0};
122static char szOS2Krnl[] = {"c:\\os2krnl"};
123
124static char szUsrSym[50] = {0};
125static char * apszSym[] =
126{
127 {"c:\\os2krnl.sym"}, /* usual for debugkernel */
128 {"c:\\os2\\pdpsi\\pmdf\\warp4\\os2krnlr.sym"}, /* warp 4 */
129 {"c:\\os2\\pdpsi\\pmdf\\warp4\\os2krnld.sym"}, /* warp 4 */
130 {"c:\\os2\\pdpsi\\pmdf\\warp4\\os2krnlb.sym"}, /* warp 4 */
131 {"c:\\os2\\pdpsi\\pmdf\\warp45_u\\os2krnlr.sym"}, /* warp 45 */
132 {"c:\\os2\\pdpsi\\pmdf\\warp45_u\\os2krnld.sym"}, /* warp 45 */
133 {"c:\\os2\\pdpsi\\pmdf\\warp45_u\\os2krnlb.sym"}, /* warp 45 */
134 {"c:\\os2\\pdpsi\\pmdf\\warp45_s\\os2krnlr.sym"}, /* warp 45 */
135 {"c:\\os2\\pdpsi\\pmdf\\warp45_s\\os2krnld.sym"}, /* warp 45 */
136 {"c:\\os2\\pdpsi\\pmdf\\warp45_s\\os2krnlb.sym"}, /* warp 45 */
137 {"c:\\os2\\system\\trace\\os2krnl.sym"}, /* warp 3 ?*/
138 {"c:\\os2\\system\\pmdf\\os2krnlr.sym"}, /* warp 3 ?*/
139 {"c:\\os2krnlr.sym"}, /* custom */
140 {"c:\\os2krnlh.sym"}, /* custom */
141 {"c:\\os2krnld.sym"}, /* custom */
142 NULL
143};
144
145/* Result from GetKernelInfo/ReadOS2Krnl. */
146static unsigned char cObjects = 0;
147static POTE paKrnlOTEs = NULL;
148
149
150
151/*******************************************************************************
152* Internal Functions *
153*******************************************************************************/
154/* File an output replacements */
155static HFILE fopen(const char * pszFilename, const char * pszIgnored);
156static int fread(void * pvBuffer, USHORT cbBlock, USHORT cBlock, HFILE hFile);
157static int fseek(HFILE hfile, signed long off, int iOrg);
158static unsigned long fsize(HFILE hFile);
159static void puts(char *psz);
160
161/* C-library replacements. */
162static void kmemcpy(char *psz1, const char *psz2, int cch);
163static char * kstrstr(const char *psz1, const char *psz2);
164static int kstrcmp(const char *psz1, const char *psz2);
165static int kstrncmp(const char *psz1, const char *psz2, int cch);
166static int kstrnicmp(const char *psz1, const char *psz2, int cch);
167static int kstrlen(const char *psz);
168static char * kstrcpy(char * pszTarget, const char * pszSource);
169static int kargncpy(char *pszTarget, const char *pszArg, unsigned cchMaxlen);
170
171/* Workers */
172static int LookupKrnlEntry(unsigned uBuild, unsigned char chType,
173 unsigned char fchType, unsigned char cObjects);
174static int VerifyPrologs(void);
175static int ProbeSymFile(const char *pszFilename);
176static int GetKernelInfo(void);
177
178/* Ouput */
179static void ShowDecNumber(unsigned long ul);
180static void ShowHexNumber(unsigned long ul);
181static void ShowResult(int rc, int iSym);
182
183/* Others used while debugging in R3. */
184static int VerifyKernelVer(void);
185static int ReadOS2Krnl(char *pszFilename);
186static int ReadOS2Krnl2(HFILE hKrnl, unsigned long cbKrnl);
187static int processFile(const char *pszFilename);
188
189
190
191
192/*******************************************************************************
193* Implementation of Internal Helper Functions *
194*******************************************************************************/
195
196/**
197 * Quick implementation of fopen.
198 * @param pszFilename name of file to open (sz)
199 * @param pszIgnored whatever - it is ignored
200 * @return Handle to file. (not pointer to a FILE stream as in C-library)
201 * @remark binary and readonly is assumed!
202 */
203static HFILE fopen(const char * pszFilename, const char * pszIgnored)
204{
205 HFILE hFile = 0;
206 USHORT rc;
207 unsigned short Action = 0;
208
209 rc = DosOpen(
210 (char*)pszFilename,
211 &hFile,
212 &Action,
213 0,
214 FILE_NORMAL,
215 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
216 OPEN_SHARE_DENYNONE + OPEN_ACCESS_READONLY,
217 NULL);
218
219 pszIgnored = pszIgnored;
220 return hFile;
221}
222
223
224/**
225 * fread emulation
226 * @returns Number of blocks read.
227 * @param pvBuffer Buffer to read into
228 * @param cbBlock Blocksize
229 * @param cBlock Block count
230 * @param hFile Handle to file (HFILE)
231 */
232static int fread(void * pvBuffer, USHORT cbBlock, USHORT cBlock, HFILE hFile)
233{
234 USHORT ulRead;
235 USHORT rc;
236
237 rc = DosRead(hFile, pvBuffer, (USHORT)(cbBlock*cBlock), &ulRead);
238 if (rc == 0)
239 rc = (USHORT)cBlock;
240 else
241 rc = 0;
242
243 return rc;
244}
245
246
247/**
248 * fseek emultation
249 * @returns Same as DosChgFilePtr
250 * @param hFile Filehandle
251 * @param off offset into file from origin
252 * @param org origin
253 */
254static int fseek(HFILE hFile, signed long off, int iOrg)
255{
256 ULONG ul;
257 return (int)DosChgFilePtr(hFile, off, iOrg, &ul);
258}
259
260
261/**
262 * Get filesize in bytes.
263 * @returns Filesize.
264 * @param hFile Filehandle
265 * @remark This function sets the file position to end of file.
266 */
267static unsigned long fsize(HFILE hFile)
268{
269 USHORT rc;
270 unsigned long cb;
271
272 rc = DosChgFilePtr(hFile, 0, FILE_END, &cb);
273
274 return cb;
275}
276
277
278/**
279 * puts lookalike
280 */
281static void puts(char * psz)
282{
283 DosPutMessage(0, kstrlen(psz), psz);
284}
285
286
287/**
288 * kmemcpy - memory copy - slow!
289 * @param psz1 target
290 * @param psz2 source
291 * @param cch length
292 */
293static void kmemcpy(char *psz1, const char *psz2, int cch)
294{
295 while (cch-- != 0)
296 *psz1++ = *psz2++;
297}
298
299
300/**
301 * Finds psz2 in psz2.
302 * @returns Pointer to occurence of psz2 in psz1.
303 * @param psz1 String to be search.
304 * @param psz2 Substring to search for.
305 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
306 */
307static char *kstrstr(const char *psz1, const char *psz2)
308{
309 while (*psz1 != '\0')
310 {
311 register int i = 0;
312 while (psz2[i] != '\0' && psz1[i] == psz2[i])
313 i++;
314
315 /* found it? */
316 if (psz2[i] == '\0')
317 return (char*)psz1;
318 if (psz1[i] == '\0' )
319 break;
320 psz1++;
321 }
322
323 return NULL;
324}
325
326
327#if 0 /* not in use */
328/**
329 * kstrcmp - String compare
330 * @returns 0 - equal else !0
331 * @param psz1 String 1
332 * @param psz2 String 2
333 */
334static int kstrcmp(const char *psz1, const char *psz2);
335{
336 while (*psz1 == *psz2 && *psz1 != '\0' && *psz2 != '\0')
337 {
338 psz1++;
339 psz2++;
340 }
341 return *psz1 - *psz2;
342}
343#endif
344
345
346/**
347 * kstrncmp - String 'n' compare.
348 * @returns 0 - equal else !0
349 * @param p1 String 1
350 * @param p2 String 2
351 * @param len length
352 */
353static int kstrncmp(register const char *psz1, register const char *psz2, int cch)
354{
355 int i = 0;
356 while (i < cch && *psz1 == *psz2 && *psz1 != '\0' && *psz2 != '\0')
357 {
358 psz1++;
359 psz2++;
360 i++;
361 }
362
363 return i - cch;
364}
365
366
367#if 0 /* not in use */
368/**
369 * kstrnicmp - String 'n' compare, case-insensitive.
370 * @returns 0 - equal else !0
371 * @param p1 String 1
372 * @param p2 String 2
373 * @param len length
374 */
375static int kstrnicmp(const char *psz1, const char *psz2, int cch)
376{
377 register char ch1, ch2;
378
379 do
380 {
381 ch1 = *psz1++;
382 if (ch1 >= 'A' && ch1 <= 'Z')
383 ch1 += 'a' - 'A'; /* to lower case */
384 ch2 = *psz2++;
385 if (ch2 >= 'A' && ch2 <= 'Z')
386 ch2 += 'a' - 'A'; /* to lower case */
387 } while (--cch > 0 && ch1 == ch2 && ch1 != '\0' && ch2 != '\0');
388
389 return ch1 - ch2;
390}
391#endif
392
393
394/**
395 * kstrlen - String length.
396 * @returns Length of the string.
397 * @param psz Pointer to string.
398 * @status completely implemented and tested.
399 * @author knut st. osmundsen
400 */
401static int kstrlen(register const char * psz)
402{
403 register int cch = 0;
404 while (*psz++ != '\0')
405 cch++;
406 return cch;
407}
408
409
410/**
411 * String copy (strcpy).
412 * @returns Pointer to target string.
413 * @param pszTarget Target string.
414 * @param pszSource Source string.
415 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
416 */
417static char * kstrcpy(char * pszTarget, register const char * pszSource)
418{
419 register char *psz = pszTarget;
420
421 while (*pszSource != '\0')
422 *psz++ = *pszSource++;
423
424 return pszTarget;
425}
426
427
428
429
430/**
431 * Copy an argument to a buffer. Ie. "-K[=|:]c:\os2krnl ....". Supports quotes
432 * @returns Number of chars of pszArg that has been processed.
433 * @param pszTarget - pointer to target buffer.
434 * @param pszArg - pointer to source argument string.
435 * @param cchMaxlen - maximum chars to copy.
436 */
437static int kargncpy(char * pszTarget, const char * pszArg, unsigned cchMaxlen)
438{
439 int i = 0;
440 int fQuote = FALSE;
441
442 /* skip option word/letter */
443 while (*pszArg != '\0' && *pszArg != ' ' && *pszArg != ':' &&
444 *pszArg != '=' && *pszArg != '-' && *pszArg != '/')
445 {
446 pszArg++;
447 i++;
448 }
449
450 if (*pszArg == ' ' || *pszArg == '-' || *pszArg == '/' || *pszArg == '\0')
451 return 0;
452
453
454 do
455 {
456 pszArg++;
457 i++;
458 } while (*pszArg != '\0' && *pszArg == ' ');
459
460 /* copy maxlen or less */
461 /* check for quotes */
462 if (*pszArg == '"')
463 {
464 fQuote = TRUE;
465 pszArg++;
466 i++;
467 }
468 /* copy loop */
469 while (cchMaxlen > 1 && (fQuote ? *pszArg != '"' : *pszArg != ' ') && *pszArg != '\0')
470 {
471 *pszTarget++ = *pszArg++;
472 i++;
473 cchMaxlen--;
474 }
475
476 /* terminate pszTarget */
477 pszTarget = '\0';
478
479 return i;
480}
481
482
483
484/*******************************************************************************
485* Implementation Of The Important Functions *
486*******************************************************************************/
487#ifndef EXTRACT
488/**
489 * Checks if this kernel is within the kernel symbol database.
490 * If an entry for the kernel is found, the data is copied from the
491 * database entry to aImportTab.
492 * @returns NO_ERROR on succes (0)
493 * 1 if not found.
494 * Error code on error.
495 * @param uBuild Build level.
496 * @param fchBldType 'A' all strict
497 * 'H' half strict
498 * 'R' retail
499 * @param fchType TYPE_SMP, TYPE_UNI, TYPE_W4
500 * @param cObjects Count of object in the running kernel.
501 * @sketch Loop thru the table.
502 * @status completely implemented.
503 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
504 */
505static int LookupKrnlEntry(unsigned uBuild, unsigned char fchBldType, unsigned char fchType, unsigned char cObjects)
506{
507 int i;
508
509 /*
510 * Loop tru the DB entries until a NULL pointer is found.
511 */
512 for (i = 0; aKrnlSymDB[i].usBuild != 0; i++)
513 {
514 if (aKrnlSymDB[i].usBuild == uBuild
515 && aKrnlSymDB[i].fchBldType == fchBldType
516 && aKrnlSymDB[i].fchType == fchType
517 && aKrnlSymDB[i].cObjects == cObjects)
518 { /* found matching entry! */
519 int j;
520 int rc;
521 register PKRNLDBENTRY pEntry = &aKrnlSymDB[i];
522
523 dprintf(("LookUpKrnlEntry - found entry for this kernel!\n"));
524
525 /*
526 * Copy symbol data from the DB to aImportTab.
527 */
528 for (j = 0; j < NBR_OF_KRNLIMPORTS; j++)
529 {
530 aImportTab[j].offObject = pEntry->aSyms[j].offObject;
531 aImportTab[j].iObject = pEntry->aSyms[j].iObject;
532 aImportTab[j].ulAddress = paKrnlOTEs[pEntry->aSyms[j].iObject].ote_base
533 + pEntry->aSyms[j].offObject;
534 aImportTab[j].usSel = paKrnlOTEs[pEntry->aSyms[j].iObject].ote_sel;
535 aImportTab[j].fFound = TRUE;
536 dprintf((" %-3d addr=0x%08lx off=0x%08lx %s\n",
537 j, aImportTab[j].ulAddress, aImportTab[j].offObject,
538 aImportTab[j].achName));
539 }
540
541 /* Verify prologs*/
542 rc = VerifyPrologs();
543
544 /* set sym name */
545 if (rc == 0)
546 kstrcpy(szUsrSym, "Win32k Symbol Database");
547 return rc;
548 }
549 }
550
551 /* not found */
552 return 1;
553}
554#endif /* !EXTRACT */
555
556/**
557 * Verifies the that the addresses in aImportTab are valid.
558 * This is done at Ring-0 of course.
559 * @returns 0 if ok, not 0 if not ok.
560 */
561static int VerifyPrologs(void)
562{
563#if !defined(DEBUGR3) && !defined(EXTRACT)
564 APIRET rc;
565 HFILE hDev0 = 0;
566 USHORT usAction = 0;
567
568 rc = DosOpen("\\dev\\elf$", &hDev0, &usAction, 0UL, FILE_NORMAL,
569 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
570 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY,
571 0UL);
572 if (rc == NO_ERROR)
573 {
574 rc = DosDevIOCtl("", "", D16_IOCTL_VERIFYIMPORTTAB, D16_IOCTL_CAT, hDev0);
575 DosClose(hDev0);
576 }
577
578 return rc;
579#else
580 return 0;
581#endif
582}
583
584
585/**
586 * Check a symbol file. Searches for the wanted entry-point addresses.
587 * @returns 0 on success - something else on failiure.
588 * @param pszFilename Name of file to probe.
589 * @precond Must be called after kernel-file is found and processed.
590 * @remark Error codes starts at -50.
591 */
592static int ProbeSymFile(const char * pszFilename)
593{
594 HFILE hSym; /* Filehandle */
595 int cLeftToFind; /* Symbols left to find */
596 unsigned long iSeg; /* Outer search loop: Segment number */
597 unsigned iSym; /* Middle search loop: Symbol number */
598 unsigned i; /* Inner search loop: ProcTab index */
599 int rc;
600
601 MAPDEF MapDef; /* Mapfile header */
602 SEGDEF SegDef; /* Segment header */
603 SYMDEF32 SymDef32; /* Symbol definition 32-bit */
604 SYMDEF16 SymDef16; /* Symbol definition 16-bit */
605 char achBuffer[256]; /* Name buffer */
606 unsigned long offSegment; /* Segment definition offset */
607 unsigned long offSymPtr; /* Symbol pointer(offset) offset */
608 unsigned short offSym; /* Symbol definition offset */
609
610
611 /*
612 * Open the symbol file
613 */
614 hSym = fopen(pszFilename, "rb");
615 if (hSym==0)
616 {
617 dprintf(("Error opening file %s\n", pszFilename));
618 return -50;
619 }
620 dprintf(("\nSuccessfully opened symbolfile: %s\n", pszFilename));
621
622
623 /*
624 * (Open were successfully.)
625 * Now read header and display it.
626 */
627 rc = fread(&MapDef, sizeof(MAPDEF), 1, hSym);
628 if (!rc)
629 { /* oops! read failed, close file and fail. */
630 fclose(hSym);
631 return -51;
632 }
633 achBuffer[0] = MapDef.achModName[0];
634 fread(&achBuffer[1], 1, MapDef.cbModName, hSym);
635 achBuffer[MapDef.cbModName] = '\0';
636 dprintf(("*Module name: %s\n", achBuffer));
637 dprintf(("*Segments: %d\n*MaxSymbolLength: %d\n", MapDef.cSegs, MapDef.cbMaxSym));
638 dprintf(("*ppNextMap: 0x%x\n", MapDef.ppNextMap ));
639
640
641 /*
642 * Verify that the modulename of the symbol file is OS2KRNL.
643 */
644 if (MapDef.cbModName == 7 && kstrncmp(achBuffer, "OS2KRNL", 7) != 0)
645 { /* modulename was not OS2KRNL, fail. */
646 dprintf(("Modulename verify failed\n"));
647 fclose(hSym);
648 return -51;
649 }
650
651
652 /*
653 * Verify that the number of segments is equal to the number objects in OS2KRNL.
654 */
655 #ifndef EXTRACT
656 if (MapDef.cSegs != cObjects)
657 { /* incorrect count of segments. */
658 dprintf(("Segment No. verify failed\n"));
659 fclose(hSym);
660 return -52;
661 }
662 #endif /* !EXTRACT */
663
664
665 /*
666 * Reset ProcTab
667 */
668 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
669 {
670 aImportTab[i].fFound = 0;
671 #ifdef DEBUG
672 aImportTab[i].offObject = 0;
673 aImportTab[i].ulAddress = 0;
674 aImportTab[i].usSel = 0;
675 #endif
676 }
677
678
679 /*
680 * Fileoffset of the first segment.
681 * And set cLeftToFind.
682 */
683 offSegment = SEGDEFOFFSET(MapDef);
684 cLeftToFind = NBR_OF_KRNLIMPORTS;
685
686 /*
687 * Search thru the entire file, segment by segment.
688 *
689 * ASSUME: last segment is the only 32-bit code segment.
690 *
691 */
692 for (iSeg = 0; iSeg < MapDef.cSegs; iSeg++, offSegment = NEXTSEGDEFOFFSET(SegDef))
693 {
694 int fSegEPTBitType; /* Type of segment, 16 or 32 bit, expressed in EPT_XXBIT flags */
695 int fCode; /* Set if this is a code segment, else clear. */
696
697 /*
698 * Read the segment definition.
699 */
700 if (fseek(hSym, offSegment, SEEK_SET))
701 { /* Failed to seek to the segment definition, fail! */
702 fclose(hSym);
703 return -53;
704 }
705 rc = fread(&SegDef, sizeof(SEGDEF), 1, hSym);
706 if (!rc)
707 { /* Failed to read the segment definition, fail! */
708 fclose(hSym);
709 return -53;
710 }
711
712 /*
713 * Some debugging info.
714 */
715 achBuffer[0] = SegDef.achSegName[0];
716 fread(&achBuffer[1], 1, SegDef.cbSegName, hSym);
717 achBuffer[SegDef.cbSegName] = '\0';
718 dprintf(("Segment %.2li Flags=0x%02x cSymbols=0x%04x Name=%s\n",
719 iSeg, SegDef.bFlags, SegDef.cSymbols, &achBuffer[0]));
720
721 /*
722 * Determin segment bit type.
723 */
724 fSegEPTBitType = SEG32BitSegment(SegDef) ? EPT_32BIT : EPT_16BIT;
725 fCode = kstrstr(achBuffer, "CODE") != NULL;
726
727 /*
728 * Search thru all the symbols in this segment
729 * while we look for the requested symbols in aImportTab.
730 */
731 for (iSym = 0; iSym < SegDef.cSymbols && cLeftToFind; iSym++)
732 {
733 unsigned cchName;
734 /*
735 * Fileoffset of the current symbol.
736 * Set filepointer to that position.
737 * Read word (which is the offset of the symbol).
738 */
739 offSymPtr = SYMDEFOFFSET(offSegment, SegDef, iSym);
740 rc = fseek(hSym, offSymPtr, SEEK_SET);
741 if (rc)
742 { /* Symboloffset seek failed, try read next symbol. */
743 dprintf(("Warning: Seek failed (offSymPtr=%d, rc=%d)\n", offSymPtr, rc));
744 continue;
745 }
746 rc = fread(&offSym, sizeof(unsigned short int), 1, hSym);
747 if (!rc)
748 { /* Symboloffset read failed, try read next symbol. */
749 dprintf(("Warning: read failed (offSymPtr=%d, rc=%d)\n", offSymPtr, rc));
750 continue;
751 }
752 rc = fseek(hSym, offSym + offSegment, SEEK_SET);
753 if (rc)
754 { /* Symbol Seek failed, try read next symbol. */
755 dprintf(("Warning: Seek failed (offSym=%d, rc=%d)\n", offSym, rc));
756 continue;
757 }
758
759
760 /*
761 * Read symbol and symbolname.
762 */
763 if (SegDef.bFlags & 0x01)
764 rc = fread(&SymDef32, sizeof(SYMDEF32), 1, hSym);
765 else
766 rc = fread(&SymDef16, sizeof(SYMDEF16), 1, hSym);
767 if (!rc)
768 { /* Symbol read failed, try read next symbol */
769 dprintf(("Warning: Read(1) failed (offSym=%d, rc=%d)\n", offSym, rc));
770 continue;
771 }
772 achBuffer[0] = (SegDef.bFlags & 0x01) ? SymDef32.achSymName[0] : SymDef16.achSymName[0];
773 cchName = (SegDef.bFlags & 0x01) ? SymDef32.cbSymName : SymDef16.cbSymName;
774 rc = fread(&achBuffer[1], 1, cchName, hSym);
775 if (!rc)
776 { /* Symbol read failed, try read next symbol */
777 dprintf(("Warning: Read(2) failed (offSym=%d, rc=%d)\n", offSym, rc));
778 continue;
779 }
780 achBuffer[cchName] = '\0';
781
782
783 /*
784 * Search proctable.
785 */
786 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
787 {
788 if (!aImportTab[i].fFound /* Not allready found */
789 && (aImportTab[i].fType & EPT_BIT_MASK) == fSegEPTBitType /* Equal bittype */
790 && (fCode || (aImportTab[i].fType & EPT_VARIMPORT)) /* Don't look for code in a data segment and vice versa */
791 && aImportTab[i].cchName == cchName /* Equal name length */
792 && kstrncmp(aImportTab[i].achName, achBuffer, cchName) == 0 /* Equal name */
793 )
794 { /* Symbol was found */
795 aImportTab[i].offObject = (SegDef.bFlags & 0x01 ? SymDef32.wSymVal : SymDef16.wSymVal);
796 aImportTab[i].ulAddress = aImportTab[i].offObject + paKrnlOTEs[iSeg].ote_base;
797 aImportTab[i].iObject = (unsigned char)iSeg;
798 aImportTab[i].usSel = paKrnlOTEs[iSeg].ote_sel;
799 dprintf(("debug: base=%lx, size=%lx iSeg=%d\n", paKrnlOTEs[iSeg].ote_base, paKrnlOTEs[iSeg].ote_size, iSeg));
800
801 /* Paranoia test! */
802 #ifndef EXTRACT
803 if (aImportTab[i].offObject < paKrnlOTEs[iSeg].ote_size)
804 {
805 aImportTab[i].fFound = TRUE;
806 cLeftToFind--;
807 dprintf(("Found: %s at off 0x%lx addr 0x%lx, sel=0x%x\n",
808 aImportTab[i].achName, aImportTab[i].offObject,
809 aImportTab[i].ulAddress, aImportTab[i].usSel));
810 }
811 else/* test failed, continue on next symbol*/
812 dprintf(("Error: Paranoia test failed for %s\n", aImportTab[i].achName));;
813 #else
814 aImportTab[i].fFound = TRUE;
815 cLeftToFind--;
816 #endif /* !EXTRACT */
817 break;
818 }
819
820 } /* aImportTab for-loop */
821
822 } /* Symbol for-loop */
823
824 } /* Segment for-loop */
825
826 /*
827 * Close symbol file.
828 */
829 fclose(hSym);
830
831 /*
832 * If not all procedures were found fail.
833 */
834 if (cLeftToFind != 0)
835 return -57;
836
837 /*
838 * Verify function prologs and return.
839 */
840 return VerifyPrologs();
841}
842
843
844/**
845 * Gets the os/2 kernel OTE's (object table entries).
846 * @returns 0 on success. Not 0 on error.
847 */
848static int GetKernelInfo(void)
849{
850#if !defined(DEBUGR3) && !defined(EXTRACT) /* IOCtl not available after inittime! */
851 static KRNLINFO KrnlInfo = {0};
852 APIRET rc;
853 HFILE hDev0 = 0;
854 USHORT usAction = 0;
855
856 rc = DosOpen("\\dev\\elf$", &hDev0, &usAction, 0UL, FILE_NORMAL,
857 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
858 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY,
859 0UL);
860 if (rc == NO_ERROR)
861 {
862 rc = DosDevIOCtl(&KrnlInfo, "", D16_IOCTL_GETKRNLINFO, D16_IOCTL_CAT, hDev0);
863 if (rc == NO_ERROR)
864 {
865 int i;
866
867 /* Set the exported parameters */
868 usBuild = KrnlInfo.usBuild;
869 fchType = KrnlInfo.fchType;
870 fDebug = KrnlInfo.fDebug;
871 cObjects = KrnlInfo.cObjects;
872 paKrnlOTEs = &KrnlInfo.aObjects[0];
873 #ifdef DEBUG
874 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
875 dprintf(("debug: no.%2d base=%lx size=%lx sel=%x\n",
876 i,
877 paKrnlOTEs[i].ote_base,
878 paKrnlOTEs[i].ote_size,
879 paKrnlOTEs[i].ote_sel));
880 #endif
881
882 }
883 DosClose(hDev0);
884 }
885
886 if (rc != NO_ERROR)
887 printf16("Failed to get kernel OTEs\r\n");
888
889 return rc;
890
891#else
892 #ifndef EXTRACT
893 APIRET rc;
894
895 /*--------------*/
896 /* read kernel */
897 /*--------------*/
898 if (szUsrOS2Krnl[0] != '\0')
899 {
900 rc = ReadOS2Krnl(szUsrOS2Krnl);
901 if (rc != 0)
902 {
903 puts("Warning: Invalid kernel file specified. Tries defaults.\n\r");
904 szUsrOS2Krnl[0] = '\0';
905 rc = ReadOS2Krnl(szOS2Krnl);
906 }
907 }
908 else
909 rc = ReadOS2Krnl(szOS2Krnl);
910 return rc;
911 #else
912 return 0;
913 #endif
914#endif
915}
916
917
918/**
919 * Shows result of kernelprobing if not quiet or on error.
920 * @param rc Return code.
921 * @param iSym index of .sym-file into static struct.
922 */
923#ifndef EXTRACT
924static void ShowResult(int rc, int iSym)
925{
926 int i;
927
928 /*
929 * Complain even if quiet on error
930 */
931 if (!fQuiet || rc != 0)
932 {
933 printf16("Win32k - Odin32 support driver.\n");
934
935 /*
936 * kernel stuff
937 */
938 if (rc <= -50 || rc == 0)
939 {
940 #ifdef DEBUGR3
941 printf16(" Found kernel: %s\n", szOS2Krnl);
942 #endif
943 printf16(" Build: %d - v%d.%d\n",
944 usBuild, usVerMajor, usVerMinor);
945 }
946 else
947 printf16(" Kernel probing failed with rc=%d.\n", rc);
948
949 /*
950 * symbol-file
951 */
952 if (rc == 0)
953 printf16(" Found symbolfile: %s\n",
954 szUsrSym[0] == '\0' ? apszSym[iSym] : szUsrSym);
955 else
956 printf16(" Failed to find symbolfile! rc=%d\n", rc);
957
958 /*
959 * function listing
960 */
961 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
962 {
963 printf16(" %-20s at ",aImportTab[i].achName);
964 if (aImportTab[i].fFound)
965 printf16("0x%08lx%s", aImportTab[i].ulAddress, (i % 2) == 0 ? "" : "\n");
966 else
967 printf16("failed!%s", (i % 2) == 0 ? "" : "\n");
968 }
969 if (i % 2) printf16("\n");
970 }
971}
972
973
974/**
975 * "main" function.
976 * Note that the option -Noloader causes nothing to be done.
977 * @returns 0 on success, something else on error.
978 * @param pReqPack Pointer to init request packet
979 * @remark
980 */
981int ProbeKernel(PRPINITIN pReqPack)
982{
983 int rc;
984 int i;
985 int n;
986 SEL selGIS;
987 SEL selLIS;
988 PGINFOSEG pGIS;
989 PLINFOSEG pLIS;
990 USHORT usBootDrive;
991
992 /*----------------*/
993 /* parse InitArgs */
994 /*----------------*/
995 if (pReqPack != NULL && pReqPack->InitArgs != NULL)
996 {
997 n = kstrlen(pReqPack->InitArgs);
998 for (i = 0; i < n; i++)
999 {
1000 if ((pReqPack->InitArgs[i] == '/' || pReqPack->InitArgs[i] == '-') && (i+1) < n)
1001 {
1002 i++;
1003 switch (pReqPack->InitArgs[i])
1004 {
1005 case 'k':
1006 case 'K': /* Kernel file */
1007 i++;
1008 i += kargncpy(szUsrOS2Krnl, &pReqPack->InitArgs[i], sizeof(szUsrOS2Krnl));
1009 break;
1010
1011 case 'n':
1012 case 'N': /* NoLoader */
1013 return 0;
1014
1015 case 'q':
1016 case 'Q': /* Quiet */
1017 fQuiet = 1;
1018 break;
1019
1020 case 's':
1021 case 'S': /* Symbol file */
1022 i++;
1023 if (pReqPack->InitArgs[i] == 'Y' || pReqPack->InitArgs[i] == 'y')
1024 i += kargncpy(szUsrSym, &pReqPack->InitArgs[i], sizeof(szUsrSym));
1025 break;
1026
1027 case 'v':
1028 case 'V': /* Verbose */
1029 fQuiet = 0;
1030 break;
1031 }
1032 }
1033 }
1034 }
1035
1036 /*---------------------*/
1037 /* determin boot drive */
1038 /*---------------------*/
1039 rc = DosGetInfoSeg(&selGIS, &selLIS);
1040 if (rc != NO_ERROR)
1041 return rc;
1042
1043 pLIS = MAKEPLINFOSEG(selLIS);
1044 pGIS = MAKEPGINFOSEG(selGIS);
1045 usBootDrive = pGIS->bootdrive;
1046 usVerMajor = pGIS->uchMajorVersion;
1047 usVerMinor = pGIS->uchMinorVersion;
1048 dprintf(("BootDrive: %d\n", usBootDrive));
1049
1050 /* set driveletter in constants strings */
1051 usBootDrive = (char)usBootDrive + (char)'a' - 1;
1052 szOS2Krnl[0] = (char)usBootDrive;
1053 for (i = 0; apszSym[i] != NULL; i++)
1054 apszSym[i][0] = (char)usBootDrive;
1055
1056 /*-----------------*/
1057 /* get kernel info */
1058 /*-----------------*/
1059 rc = GetKernelInfo();
1060 if (rc != NO_ERROR)
1061 return rc;
1062
1063 /*--------------*/
1064 /* read symfile */
1065 /*--------------*/
1066 if (!rc)
1067 {
1068 rc = 1;
1069 if (szUsrSym[0] != '\0')
1070 {
1071 rc = ProbeSymFile(szUsrSym);
1072 if (rc)
1073 {
1074 puts("Warning: Invalid symbol file specified. Tries defaults.\n\r");
1075 szUsrSym[0] = '\0';
1076 }
1077 }
1078 if (rc != 0) /* if user sym failed or don't exists. */
1079 {
1080 /*
1081 * Check database - only if not a debug kernel!
1082 * You usually have a .sym-file when using a debug kernel.
1083 * (Currently I am not able to distinguish between half and all strict kernels...)
1084 */
1085 if (fDebug ||
1086 (rc = LookupKrnlEntry((unsigned short)usBuild, 'R', fchType, cObjects)) != 0
1087 )
1088 {
1089 /* search on disk */
1090 i = 0;
1091 while (apszSym[i] != NULL && (rc = ProbeSymFile(apszSym[i])) != 0)
1092 i++;
1093 }
1094 }
1095 }
1096
1097 /* show the result and set return-value */
1098 dprintf(("rc=%d; i=%d\n", rc, i));
1099 ShowResult(rc, i);
1100
1101 return rc;
1102}
1103#endif
1104
1105
1106#ifdef DEBUGR3
1107/**
1108 * Verifies that build no, matches kernel number.
1109 * @returns 0 on equal, !0 on error.
1110 */
1111static int VerifyKernelVer(void)
1112{
1113 int VerMinor, VerMajor;
1114
1115 VerMajor = usBuild < 20000 ? 20 : 30/*?*/;
1116 VerMinor = usBuild < 6600 ? 10 : usBuild < 8000 ? 11 : usBuild < 9000 ? 30 :
1117 usBuild < 10000 ? 40 : usBuild < 15000 ? 45 : 50;
1118
1119 return VerMajor - (int)usVerMajor | VerMinor - (int)usVerMinor;
1120}
1121
1122
1123/**
1124 * Reads and verifies OS/2 kernel.
1125 * @returns 0 on success, not 0 on failure.
1126 * @param filename Filename of the OS/2 kernel.
1127 * @result usBuild is set.
1128 * @remark This step will be eliminated by searching thru the DOSGROUP datasegment
1129 * in the kernel memory. This segment have a string "Internal revision 9.034[smp|uni]"
1130 * This would be much faster than reading the kernel file. It will also give us a more precise
1131 * answer to the question! This is currently a TODO issue. !FIXME!
1132 */
1133static int ReadOS2Krnl(char * pszFilename)
1134{
1135 HFILE hKrnl;
1136 unsigned long cbKrnl;
1137 int rc;
1138
1139 hKrnl = fopen(pszFilename, "rb");
1140 if (hKrnl != 0)
1141 {
1142 cbKrnl = fsize(hKrnl);
1143 if (!fseek(hKrnl, 0, SEEK_SET))
1144 rc = ReadOS2Krnl2(hKrnl, cbKrnl);
1145 else
1146 rc = -2;
1147 fclose(hKrnl);
1148 }
1149 else
1150 {
1151 dprintf(("Could not open file\n"));
1152 rc = -1;
1153 }
1154 return rc;
1155}
1156
1157
1158/**
1159 * Worker function for ReadOS2Krnl
1160 * @returns 0 on success.
1161 * errorcodes on failure. (-1 >= rc >= -14)
1162 * @param hKrnl Handle to the kernel file.
1163 * @param cbKrnl Size of the kernel file.
1164 * @author knut st. osmundsen
1165 */
1166static int ReadOS2Krnl2(HFILE hKrnl, unsigned long cbKrnl)
1167{
1168 #if defined(DEBUGR3) || !defined(EXTRACT)
1169 static KRNLINFO KrnlInfo = {0};
1170 #endif
1171 int i, j;
1172 int rc = 0;
1173 char achBuffer[KERNEL_ID_STRING_LENGTH + KERNEL_READ_SIZE];
1174 unsigned long offLXHdr;
1175 struct e32_exe *pLXHdr;
1176
1177
1178 /* find bldlevel string - "@#IBM:14.020#@ IBM OS/2 Kernel - 14.020F" */
1179 if (fseek(hKrnl, 0, SEEK_SET))
1180 return -2;
1181
1182 if (!fread(&achBuffer[KERNEL_ID_STRING_LENGTH], 1, KERNEL_READ_SIZE, hKrnl))
1183 return -3;
1184
1185 i = KERNEL_ID_STRING_LENGTH;
1186 while (cbKrnl > 0)
1187 {
1188 if (i == KERNEL_READ_SIZE)
1189 {
1190
1191 kmemcpy(achBuffer, &achBuffer[KERNEL_READ_SIZE], KERNEL_ID_STRING_LENGTH);
1192 if (!fread(&achBuffer[KERNEL_ID_STRING_LENGTH], 1, cbKrnl > KERNEL_READ_SIZE ? KERNEL_READ_SIZE : (int)cbKrnl, hKrnl))
1193 return -3;
1194
1195 i = 0;
1196 }
1197
1198 if (kstrncmp("@#IBM:", &achBuffer[i], 6) == 0)
1199 break;
1200
1201 /* next */
1202 i++;
1203 cbKrnl--;
1204 }
1205
1206 if (cbKrnl == 0)
1207 {
1208 fclose(hKrnl);
1209 return -4;
1210 }
1211
1212 /* displacement */
1213 j = 0;
1214 while (j < 6 && achBuffer[i+10+j] != '#')
1215 j++;
1216
1217 /* verify signature */
1218 if (kstrncmp(&achBuffer[i+10+j], "#@ IBM OS/2 Kernel", 19) != 0)
1219 return -5;
1220
1221 /* read usBuild */
1222 usBuild = (char)(achBuffer[i+6] - '0') * 1000;
1223 if (achBuffer[i+7] != '.')
1224 {
1225 /* this code is for Warp5 */
1226 usBuild *= 10;
1227 usBuild += (char)(achBuffer[i+7] - '0') * 1000;
1228 i++;
1229 j--;
1230 if (achBuffer[i+7] != '.')
1231 {
1232 usBuild = usBuild * 10;
1233 usBuild = usBuild + (unsigned short)(achBuffer[i+7] - '0') * 1000;
1234 i++;
1235 j--;
1236 }
1237 }
1238
1239 if (j == 0)
1240 {
1241 usBuild += (achBuffer[i+ 8] - '0') * 10;
1242 usBuild += (achBuffer[i+ 9] - '0') * 1;
1243 }
1244 else
1245 {
1246 if (j == 3)
1247 return -9;
1248 usBuild += (achBuffer[i+ 8] - '0') * 100;
1249 usBuild += (achBuffer[i+ 9] - '0') * 10;
1250 usBuild += (achBuffer[i+10] - '0');
1251 }
1252
1253 if (VerifyKernelVer())
1254 return -9;
1255 dprintf(("usBuild: %d\n", usBuild));
1256
1257 /* get segment number */
1258 /* read-MZheader */
1259 if (fseek(hKrnl,0,SEEK_SET))
1260 return -2;
1261
1262 if (!fread(achBuffer, 1, 0x40, hKrnl))
1263 return -3;
1264
1265 offLXHdr = *(unsigned long int *)&achBuffer[0x3c];
1266
1267 if (offLXHdr > 0x2000 && offLXHdr < 0x80) /* just to detect garbage */
1268 return -6;
1269
1270 if (fseek(hKrnl, offLXHdr, SEEK_SET))
1271 return -2;
1272
1273 if (!fread(achBuffer, 1, sizeof(struct e32_exe), hKrnl))
1274 return -3;
1275
1276 /* check LX-magic */
1277 if (achBuffer[0] != 'L' || achBuffer[1] != 'X')
1278 return -7;
1279
1280#if !defined(DEBUGR3) && !defined(EXTRACT)
1281 /* check object count - match it with what we got from the kernel. */
1282 pLXHdr = (struct e32_exe *)achBuffer;
1283 if ((UCHAR)pLXHdr->e32_objcnt != cObjects)
1284 return -8;
1285
1286 if (pLXHdr->e32_objcnt < 10)
1287 return -9;
1288
1289 /* check objects (sizes and flags(?)) */
1290 if (!fseek(hKrnl, (LONG)offLXHdr + (LONG)pLXHdr->e32_objtab, SEEK_SET))
1291 {
1292 struct o32_obj *pObj = (struct o32_obj *)achBuffer;
1293 for (i = 0; i < (int)cObjects; i++)
1294 {
1295 if (!fread(achBuffer, 1, sizeof(OTE), hKrnl))
1296 return -11;
1297 if (pObj->o32_size < paKrnlOTEs[i].ote_size)
1298 return -12;
1299
1300 #if 0 /* don't work! */
1301 if ((pObj->o32_flags & 0xffffUL) != (paKrnlOTEs[i].ote_flags & 0xffffUL))
1302 return -14;
1303 #endif
1304 }
1305 }
1306 else
1307 return -10;
1308#else
1309 /* Since we can't get the OTEs from the kernel when debugging in RING-3,
1310 * we'll use what we find in the kernel.
1311 */
1312
1313 /* object count */
1314 pLXHdr = (struct e32_exe *)achBuffer;
1315 cObjects = (UCHAR)pLXHdr->e32_objcnt;
1316 paKrnlOTEs = &KrnlInfo.aObjects[0];
1317
1318 /* get OTEs */
1319 if (!fseek(hKrnl, (LONG)offLXHdr + (LONG)pLXHdr->e32_objtab, SEEK_SET))
1320 {
1321 struct o32_obj *pObj = (struct o32_obj *)achBuffer;
1322 for (i = 0; i < (int)cObjects; i++)
1323 if (!fread(&paKrnlOTEs[i], 1, sizeof(struct o32_obj), hKrnl))
1324 return -11;
1325 }
1326 else
1327 return -10;
1328#endif
1329
1330 return 0;
1331}
1332
1333
1334
1335/**
1336 * Debug - Main procedure for standalone testing.
1337 */
1338void main(int argc, char **argv)
1339{
1340 char szParm[512];
1341 RPINITIN ReqPack;
1342 int j;
1343 int i = 0;
1344 int argi = 0;
1345
1346 while (argi < argc)
1347 {
1348 j = 0;
1349 while (argv[argi][j] != '\0')
1350 szParm[i++] = argv[argi][j++];
1351 szParm[i++] = ' ';
1352
1353 /* next */
1354 argi++;
1355 }
1356 szParm[i++] = '\0';
1357
1358 ReqPack.InitArgs = szParm;
1359
1360 ProbeKernel(&ReqPack);
1361}
1362#endif
1363
1364
1365#ifdef EXTRACT
1366/**
1367 * Dumps writes a KRNLDBENTRY struct to stderr for the given .sym-file.
1368 * The filesnames are on this format:
1369 * nnnn[n]tm.SYM
1370 * Where: n - are the build number 4 or 5 digits.
1371 * t - kernel type. R = retail, H = half strict, A = all strict.
1372 * m - UNI or SMP. U = UNI processor kernel. S = SMP processor kernel.
1373 * @returns NO_ERROR on success. Untracable error code on error.
1374 * @param pszFilename Pointer to read only filename of the .sym-file.
1375 * @status completely implemented.
1376 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
1377 * @remark Currently only retail kernels are processed. See note below.
1378 */
1379static int processFile(const char *pszFilename)
1380{
1381 APIRET rc;
1382 int cch = kstrlen(pszFilename);
1383
1384 /* Filename check */
1385 if (cch < 10 || cch > 11
1386 || !(pszFilename[0] >= '0' && pszFilename[0] <= '9')
1387 || !(pszFilename[1] >= '0' && pszFilename[1] <= '9')
1388 || !(pszFilename[2] >= '0' && pszFilename[2] <= '9')
1389 || !(pszFilename[3] >= '0' && pszFilename[3] <= '9')
1390 || !(pszFilename[cch-7] >= '0' && pszFilename[cch-7] <= '9')
1391 || !(pszFilename[cch-6] == 'A' || pszFilename[cch-6] == 'H' || pszFilename[cch-6] == 'R')
1392 || !(pszFilename[cch-5] == 'S' || pszFilename[cch-5] == 'U' || pszFilename[cch-5] == '4')
1393 )
1394 {
1395 printf16("invalid filename: %s\n", pszFilename);
1396 return 2;
1397 }
1398
1399 /** @remark
1400 * All a/h-strict files are currently ignored.
1401 * When a debug kernel is used we'll have to use the
1402 * .sym-file for it. This is so because I can't distinguish
1403 * between a all-strick and a half-strick kernel (yet).
1404 */
1405 if (pszFilename[cch-6] != 'R')
1406 return 0;
1407
1408 /*
1409 * Probe kernelfile
1410 */
1411 rc = ProbeSymFile(pszFilename);
1412
1413
1414 /*
1415 * on success dump a struct for this kernel
1416 */
1417 if (rc == 0)
1418 {
1419 int i;
1420
1421 printf16(" { /* %s */\n"
1422 " %.*s, \'%c\', %s, %d,\n"
1423 " {\n",
1424 pszFilename,
1425 cch - 6, &pszFilename[0], /* build number */
1426 pszFilename[cch - 6], /* Type, A=astrict, H=halfstrict, R=Retail */
1427 pszFilename[cch - 5] == 'S' ? /* UNI: TYPE_UNI SMP: TYPE_SMP W4: TYPE_W4 */
1428 "TYPE_SMP" : pszFilename[cch - 5] == '4' ? "TYPE_W4" : "TYPE_UNI",
1429 aImportTab[0].iObject + 1); /* ASSUMES that DOSCODE32 is the last object. */
1430
1431 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1432 {
1433 char *psz = aImportTab[i].achName;
1434 printf16(" {%2d, 0x%08lx}, /* %s */\n",
1435 aImportTab[i].iObject,
1436 aImportTab[i].offObject,
1437 (char *)&aImportTab[i].achName[0]
1438 );
1439 }
1440 printf16(" }\n"
1441 " },\n");
1442 }
1443 else
1444 printf16("ProbeSymFile failed with rc=%d\n", rc);
1445
1446 return rc;
1447}
1448
1449
1450/**
1451 * Extract program.
1452 *
1453 * This is some initial trial-and-error for creating an "database" of
1454 * kernel entrypoints.
1455 *
1456 * Output to stderr the structs generated for the passed in *.sym file.
1457 *
1458 */
1459int main(int argc, char **argv)
1460{
1461 APIRET rc;
1462
1463
1464 /*
1465 * Set paKrnlOTEs to point to an zeroed array of OTEs.
1466 */
1467 static KRNLINFO KrnlInfo = {0};
1468 paKrnlOTEs = &KrnlInfo.aObjects[0];
1469
1470 if (argc > 1)
1471 {
1472 /*
1473 * Arguments: extract.exe <symfiles...>
1474 */
1475 int i;
1476 for (i = 0; i < argc; i++)
1477 {
1478 rc = processFile(argv[i]);
1479 if (rc != NO_ERROR)
1480 {
1481 printf16("processFile failed with rc=%d for file %s\n",
1482 rc, argv[i]);
1483 return rc;
1484 }
1485 }
1486 }
1487 else
1488 {
1489 /*
1490 * Arguments: extract.exe
1491 *
1492 * Action: Scan current directory for *.sym files.
1493 *
1494 */
1495 USHORT usSearch = 1;
1496 HDIR hDir = HDIR_CREATE;
1497 FILEFINDBUF ffb;
1498 int i;
1499
1500 printf16("/* $Id: probkrnl.c,v 1.20 2000-04-17 01:56:48 bird Exp $\n"
1501 "*\n"
1502 "* Autogenerated kernel symbol database.\n"
1503 "*\n"
1504 "* Copyright (c) 2000 knut st. osmundsen (knut.stange.osmundsen@pmsc.no)\n"
1505 "*\n"
1506 "* Project Odin Software License can be found in LICENSE.TXT\n"
1507 "*\n"
1508 "*/\n");
1509
1510 printf16("\n"
1511 "#define INCL_NOPMAPI\n"
1512 "#define INCL_NOBASEAPI\n"
1513 "#include <os2.h>\n"
1514 "#include \"probkrnl.h\"\n"
1515 "\n");
1516
1517 printf16("KRNLDBENTRY aKrnlSymDB[] = \n"
1518 "{\n");
1519
1520 rc = DosFindFirst("*.sym", &hDir, FILE_NORMAL,
1521 &ffb, sizeof(ffb),
1522 &usSearch, 0UL);
1523 while (rc == NO_ERROR & usSearch > 0)
1524 {
1525 rc = processFile(&ffb.achName[0]);
1526 if (rc != NO_ERROR)
1527 {
1528 printf16("processFile failed with rc=%d for file %s\n",
1529 rc, &ffb.achName[0]);
1530 return rc;
1531 }
1532
1533 /* next file */
1534 rc = DosFindNext(hDir, &ffb, sizeof(ffb), &usSearch);
1535 }
1536 DosFindClose(hDir);
1537
1538 printf16(" { /* Terminating entry */\n"
1539 " 0,0,0,0,\n"
1540 " {\n");
1541 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1542 printf16(" {0,0},\n");
1543 printf16(" }\n"
1544 " }\n"
1545 "}; /* end of aKrnlSymDB[] */\n"
1546 );
1547 }
1548
1549
1550 return rc;
1551}
1552#endif /* EXTRACT */
1553
Note: See TracBrowser for help on using the repository browser.