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

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

No PM apis needed!

File size: 45.9 KB
Line 
1/* $Id: probkrnl.c,v 1.17 2000-02-26 17:49:28 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 */ /* currently disabled! */
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}, /* 14 */
105 {FALSE, -1, 8, "f_FuBuff", -1, -1, -1, -1, EPT_PROCIMPORT16} /* 15 */
106/* {FALSE, -1, 11, "", -1, -1, -1, EPT_PROCIMPORT16} */ /* 16 */
107};
108
109unsigned short int usBuild = 0;
110unsigned short usVerMajor = 0;
111unsigned short usVerMinor = 0;
112unsigned char fSMP = FALSE;
113unsigned char fDebug = FALSE;
114
115
116/*
117 * privat data
118 */
119static int fQuiet = 0;
120static char szUsrOS2Krnl[50] = {0};
121static char szOS2Krnl[] = {"c:\\os2krnl"};
122
123static char szUsrSym[50] = {0};
124static char * apszSym[] =
125{
126 {"c:\\os2krnl.sym"}, /* usual for debugkernel */
127 {"c:\\os2\\pdpsi\\pmdf\\warp4\\os2krnlr.sym"}, /* warp 4 */
128 {"c:\\os2\\pdpsi\\pmdf\\warp4\\os2krnld.sym"}, /* warp 4 */
129 {"c:\\os2\\pdpsi\\pmdf\\warp4\\os2krnlb.sym"}, /* warp 4 */
130 {"c:\\os2\\pdpsi\\pmdf\\warp45_u\\os2krnlr.sym"}, /* warp 45 */
131 {"c:\\os2\\pdpsi\\pmdf\\warp45_u\\os2krnld.sym"}, /* warp 45 */
132 {"c:\\os2\\pdpsi\\pmdf\\warp45_u\\os2krnlb.sym"}, /* warp 45 */
133 {"c:\\os2\\pdpsi\\pmdf\\warp45_s\\os2krnlr.sym"}, /* warp 45 */
134 {"c:\\os2\\pdpsi\\pmdf\\warp45_s\\os2krnld.sym"}, /* warp 45 */
135 {"c:\\os2\\pdpsi\\pmdf\\warp45_s\\os2krnlb.sym"}, /* warp 45 */
136 {"c:\\os2\\system\\trace\\os2krnl.sym"}, /* warp 3 ?*/
137 {"c:\\os2\\system\\pmdf\\os2krnlr.sym"}, /* warp 3 ?*/
138 {"c:\\os2krnlr.sym"}, /* custom */
139 {"c:\\os2krnlh.sym"}, /* custom */
140 {"c:\\os2krnld.sym"}, /* custom */
141 NULL
142};
143
144/* Result from GetKernelInfo/ReadOS2Krnl. */
145static unsigned char cObjects = 0;
146static POTE paKrnlOTEs = NULL;
147
148
149
150/*******************************************************************************
151* Internal Functions *
152*******************************************************************************/
153/* File an output replacements */
154static HFILE fopen(const char * pszFilename, const char * pszIgnored);
155static int fread(void * pvBuffer, USHORT cbBlock, USHORT cBlock, HFILE hFile);
156static int fseek(HFILE hfile, signed long off, int iOrg);
157static unsigned long fsize(HFILE hFile);
158static void puts(char *psz);
159
160/* C-library replacements. */
161static void kmemcpy(char *psz1, const char *psz2, int cch);
162static char * kstrstr(const char *psz1, const char *psz2);
163static int kstrcmp(const char *psz1, const char *psz2);
164static int kstrncmp(const char *psz1, const char *psz2, int cch);
165static int kstrnicmp(const char *psz1, const char *psz2, int cch);
166static int kstrlen(const char *psz);
167static char * kstrcpy(char * pszTarget, const char * pszSource);
168static int kargncpy(char *pszTarget, const char *pszArg, unsigned cchMaxlen);
169
170/* Workers */
171static int LookupKrnlEntry(unsigned uBuild, unsigned char chType,
172 unsigned char fSMP, unsigned char cObjects);
173static int VerifyPrologs(void);
174static int ProbeSymFile(const char *pszFilename);
175static int GetKernelInfo(void);
176
177/* Ouput */
178static void ShowDecNumber(unsigned long ul);
179static void ShowHexNumber(unsigned long ul);
180static void ShowResult(int rc, int iSym);
181
182/* Others used while debugging in R3. */
183static int VerifyKernelVer(void);
184static int ReadOS2Krnl(char *pszFilename);
185static int ReadOS2Krnl2(HFILE hKrnl, unsigned long cbKrnl);
186static int processFile(const char *pszFilename);
187
188
189
190
191/*******************************************************************************
192* Implementation of Internal Helper Functions *
193*******************************************************************************/
194
195/**
196 * Quick implementation of fopen.
197 * @param pszFilename name of file to open (sz)
198 * @param pszIgnored whatever - it is ignored
199 * @return Handle to file. (not pointer to a FILE stream as in C-library)
200 * @remark binary and readonly is assumed!
201 */
202static HFILE fopen(const char * pszFilename, const char * pszIgnored)
203{
204 HFILE hFile = 0;
205 USHORT rc;
206 unsigned short Action = 0;
207
208 rc = DosOpen(
209 (char*)pszFilename,
210 &hFile,
211 &Action,
212 0,
213 FILE_NORMAL,
214 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
215 OPEN_SHARE_DENYNONE + OPEN_ACCESS_READONLY,
216 NULL);
217
218 pszIgnored = pszIgnored;
219 return hFile;
220}
221
222
223/**
224 * fread emulation
225 * @returns Number of blocks read.
226 * @param pvBuffer Buffer to read into
227 * @param cbBlock Blocksize
228 * @param cBlock Block count
229 * @param hFile Handle to file (HFILE)
230 */
231static int fread(void * pvBuffer, USHORT cbBlock, USHORT cBlock, HFILE hFile)
232{
233 USHORT ulRead;
234 USHORT rc;
235
236 rc = DosRead(hFile, pvBuffer, (USHORT)(cbBlock*cBlock), &ulRead);
237 if (rc == 0)
238 rc = (USHORT)cBlock;
239 else
240 rc = 0;
241
242 return rc;
243}
244
245
246/**
247 * fseek emultation
248 * @returns Same as DosChgFilePtr
249 * @param hFile Filehandle
250 * @param off offset into file from origin
251 * @param org origin
252 */
253static int fseek(HFILE hFile, signed long off, int iOrg)
254{
255 ULONG ul;
256 return (int)DosChgFilePtr(hFile, off, iOrg, &ul);
257}
258
259
260/**
261 * Get filesize in bytes.
262 * @returns Filesize.
263 * @param hFile Filehandle
264 * @remark This function sets the file position to end of file.
265 */
266static unsigned long fsize(HFILE hFile)
267{
268 USHORT rc;
269 unsigned long cb;
270
271 rc = DosChgFilePtr(hFile, 0, FILE_END, &cb);
272
273 return cb;
274}
275
276
277/**
278 * puts lookalike
279 */
280static void puts(char * psz)
281{
282 DosPutMessage(0, kstrlen(psz), psz);
283}
284
285
286/**
287 * kmemcpy - memory copy - slow!
288 * @param psz1 target
289 * @param psz2 source
290 * @param cch length
291 */
292static void kmemcpy(char *psz1, const char *psz2, int cch)
293{
294 while (cch-- != 0)
295 *psz1++ = *psz2++;
296}
297
298
299/**
300 * Finds psz2 in psz2.
301 * @returns Pointer to occurence of psz2 in psz1.
302 * @param psz1 String to be search.
303 * @param psz2 Substring to search for.
304 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
305 */
306static char *kstrstr(const char *psz1, const char *psz2)
307{
308 while (*psz1 != '\0')
309 {
310 register int i = 0;
311 while (psz2[i] != '\0' && psz1[i] == psz2[i])
312 i++;
313
314 /* found it? */
315 if (psz2[i] == '\0')
316 return (char*)psz1;
317 if (psz1[i] == '\0' )
318 break;
319 psz1++;
320 }
321
322 return NULL;
323}
324
325
326#if 0 /* not in use */
327/**
328 * kstrcmp - String compare
329 * @returns 0 - equal else !0
330 * @param psz1 String 1
331 * @param psz2 String 2
332 */
333static int kstrcmp(const char *psz1, const char *psz2);
334{
335 while (*psz1 == *psz2 && *psz1 != '\0' && *psz2 != '\0')
336 {
337 psz1++;
338 psz2++;
339 }
340 return *psz1 - *psz2;
341}
342#endif
343
344
345/**
346 * kstrncmp - String 'n' compare.
347 * @returns 0 - equal else !0
348 * @param p1 String 1
349 * @param p2 String 2
350 * @param len length
351 */
352static int kstrncmp(register const char *psz1, register const char *psz2, int cch)
353{
354 int i = 0;
355 while (i < cch && *psz1 == *psz2 && *psz1 != '\0' && *psz2 != '\0')
356 {
357 psz1++;
358 psz2++;
359 i++;
360 }
361
362 return i - cch;
363}
364
365
366#if 0 /* not in use */
367/**
368 * kstrnicmp - String 'n' compare, case-insensitive.
369 * @returns 0 - equal else !0
370 * @param p1 String 1
371 * @param p2 String 2
372 * @param len length
373 */
374static int kstrnicmp(const char *psz1, const char *psz2, int cch)
375{
376 register char ch1, ch2;
377
378 do
379 {
380 ch1 = *psz1++;
381 if (ch1 >= 'A' && ch1 <= 'Z')
382 ch1 += 'a' - 'A'; /* to lower case */
383 ch2 = *psz2++;
384 if (ch2 >= 'A' && ch2 <= 'Z')
385 ch2 += 'a' - 'A'; /* to lower case */
386 } while (--cch > 0 && ch1 == ch2 && ch1 != '\0' && ch2 != '\0');
387
388 return ch1 - ch2;
389}
390#endif
391
392
393/**
394 * kstrlen - String length.
395 * @returns Length of the string.
396 * @param psz Pointer to string.
397 * @status completely implemented and tested.
398 * @author knut st. osmundsen
399 */
400static int kstrlen(register const char * psz)
401{
402 register int cch = 0;
403 while (*psz++ != '\0')
404 cch++;
405 return cch;
406}
407
408
409/**
410 * String copy (strcpy).
411 * @returns Pointer to target string.
412 * @param pszTarget Target string.
413 * @param pszSource Source string.
414 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
415 */
416static char * kstrcpy(char * pszTarget, register const char * pszSource)
417{
418 register char *psz = pszTarget;
419
420 while (*pszSource != '\0')
421 *psz++ = *pszSource++;
422
423 return pszTarget;
424}
425
426
427
428
429/**
430 * Copy an argument to a buffer. Ie. "-K[=|:]c:\os2krnl ....". Supports quotes
431 * @returns Number of chars of pszArg that has been processed.
432 * @param pszTarget - pointer to target buffer.
433 * @param pszArg - pointer to source argument string.
434 * @param cchMaxlen - maximum chars to copy.
435 */
436static int kargncpy(char * pszTarget, const char * pszArg, unsigned cchMaxlen)
437{
438 int i = 0;
439 int fQuote = FALSE;
440
441 /* skip option word/letter */
442 while (*pszArg != '\0' && *pszArg != ' ' && *pszArg != ':' &&
443 *pszArg != '=' && *pszArg != '-' && *pszArg != '/')
444 {
445 pszArg++;
446 i++;
447 }
448
449 if (*pszArg == ' ' || *pszArg == '-' || *pszArg == '/' || *pszArg == '\0')
450 return 0;
451
452
453 do
454 {
455 pszArg++;
456 i++;
457 } while (*pszArg != '\0' && *pszArg == ' ');
458
459 /* copy maxlen or less */
460 /* check for quotes */
461 if (*pszArg == '"')
462 {
463 fQuote = TRUE;
464 pszArg++;
465 i++;
466 }
467 /* copy loop */
468 while (cchMaxlen > 1 && (fQuote ? *pszArg != '"' : *pszArg != ' ') && *pszArg != '\0')
469 {
470 *pszTarget++ = *pszArg++;
471 i++;
472 cchMaxlen--;
473 }
474
475 /* terminate pszTarget */
476 pszTarget = '\0';
477
478 return i;
479}
480
481
482
483/*******************************************************************************
484* Implementation Of The Important Functions *
485*******************************************************************************/
486#ifndef EXTRACT
487/**
488 * Checks if this kernel is within the kernel symbol database.
489 * If an entry for the kernel is found, the data is copied from the
490 * database entry to aImportTab.
491 * @returns NO_ERROR on succes (0)
492 * 1 if not found.
493 * Error code on error.
494 * @param uBuild Build level.
495 * @param chType 'A' all strict
496 * 'H' half strict
497 * 'R' retail
498 * @param fSMP TRUE: SMP
499 * FALSE: UNI
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 chType, unsigned char fSMP, 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].chType == chType
516 && aKrnlSymDB[i].fSMP == fSMP
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 fSMP = KrnlInfo.fSMP;
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 GDT;
987 SEL LDT;
988 PGINFOSEG pInfoSeg;
989 USHORT usBootDrive;
990
991 /*----------------*/
992 /* parse InitArgs */
993 /*----------------*/
994 if (pReqPack != NULL && pReqPack->InitArgs != NULL)
995 {
996 n = kstrlen(pReqPack->InitArgs);
997 for (i = 0; i < n; i++)
998 {
999 if ((pReqPack->InitArgs[i] == '/' || pReqPack->InitArgs[i] == '-') && (i+1) < n)
1000 {
1001 i++;
1002 switch (pReqPack->InitArgs[i])
1003 {
1004 case 'k':
1005 case 'K': /* Kernel file */
1006 i++;
1007 i += kargncpy(szUsrOS2Krnl, &pReqPack->InitArgs[i], sizeof(szUsrOS2Krnl));
1008 break;
1009
1010 case 'n':
1011 case 'N': /* NoLoader */
1012 return 0;
1013
1014 case 'q':
1015 case 'Q': /* Quiet */
1016 fQuiet = 1;
1017 break;
1018
1019 case 's':
1020 case 'S': /* Symbol file */
1021 i++;
1022 if (pReqPack->InitArgs[i] == 'Y' || pReqPack->InitArgs[i] == 'y')
1023 i += kargncpy(szUsrSym, &pReqPack->InitArgs[i], sizeof(szUsrSym));
1024 break;
1025
1026 case 'v':
1027 case 'V': /* Verbose */
1028 fQuiet = 0;
1029 break;
1030 }
1031 }
1032 }
1033 }
1034
1035 /*---------------------*/
1036 /* determin boot drive */
1037 /*---------------------*/
1038 rc = DosGetInfoSeg(&GDT, &LDT);
1039 if (rc != NO_ERROR)
1040 return rc;
1041
1042 pInfoSeg = MAKEPGINFOSEG(GDT);
1043 usBootDrive = pInfoSeg->bootdrive;
1044 usVerMajor = pInfoSeg->uchMajorVersion;
1045 usVerMinor = pInfoSeg->uchMinorVersion;
1046 dprintf(("BootDrive: %d\n", usBootDrive));
1047
1048 /* set driveletter in constants strings */
1049 usBootDrive = (char)usBootDrive + (char)'a' - 1;
1050 szOS2Krnl[0] = (char)usBootDrive;
1051 for (i = 0; apszSym[i] != NULL; i++)
1052 apszSym[i][0] = (char)usBootDrive;
1053
1054 /*-----------------*/
1055 /* get kernel info */
1056 /*-----------------*/
1057 rc = GetKernelInfo();
1058 if (rc != NO_ERROR)
1059 return rc;
1060
1061 /*--------------*/
1062 /* read symfile */
1063 /*--------------*/
1064 if (!rc)
1065 {
1066 rc = 1;
1067 if (szUsrSym[0] != '\0')
1068 {
1069 rc = ProbeSymFile(szUsrSym);
1070 if (rc)
1071 {
1072 puts("Warning: Invalid symbol file specified. Tries defaults.\n\r");
1073 szUsrSym[0] = '\0';
1074 }
1075 }
1076 if (rc != 0) /* if user sym failed or don't exists. */
1077 {
1078 /*
1079 * Check database - only if not a debug kernel!
1080 * You usually have a .sym-file when using a debug kernel.
1081 * (Currently I am not able to distinguish between half and all strict kernels...)
1082 */
1083 if (fDebug ||
1084 (rc = LookupKrnlEntry((unsigned short)usBuild, 'R', fSMP, cObjects)) != 0
1085 )
1086 {
1087 /* search on disk */
1088 i = 0;
1089 while (apszSym[i] != NULL && (rc = ProbeSymFile(apszSym[i])) != 0)
1090 i++;
1091 }
1092 }
1093 }
1094
1095 /* show the result and set return-value */
1096 dprintf(("rc=%d; i=%d\n", rc, i));
1097 ShowResult(rc, i);
1098
1099 return rc;
1100}
1101#endif
1102
1103
1104#ifdef DEBUGR3
1105/**
1106 * Verifies that build no, matches kernel number.
1107 * @returns 0 on equal, !0 on error.
1108 */
1109static int VerifyKernelVer(void)
1110{
1111 int VerMinor, VerMajor;
1112
1113 VerMajor = usBuild < 20000 ? 20 : 30/*?*/;
1114 VerMinor = usBuild < 6600 ? 10 : usBuild < 8000 ? 11 : usBuild < 9000 ? 30 :
1115 usBuild < 10000 ? 40 : usBuild < 15000 ? 45 : 50;
1116
1117 return VerMajor - (int)usVerMajor | VerMinor - (int)usVerMinor;
1118}
1119
1120
1121/**
1122 * Reads and verifies OS/2 kernel.
1123 * @returns 0 on success, not 0 on failure.
1124 * @param filename Filename of the OS/2 kernel.
1125 * @result usBuild is set.
1126 * @remark This step will be eliminated by searching thru the DOSGROUP datasegment
1127 * in the kernel memory. This segment have a string "Internal revision 9.034[smp|uni]"
1128 * This would be much faster than reading the kernel file. It will also give us a more precise
1129 * answer to the question! This is currently a TODO issue. !FIXME!
1130 */
1131static int ReadOS2Krnl(char * pszFilename)
1132{
1133 HFILE hKrnl;
1134 unsigned long cbKrnl;
1135 int rc;
1136
1137 hKrnl = fopen(pszFilename, "rb");
1138 if (hKrnl != 0)
1139 {
1140 cbKrnl = fsize(hKrnl);
1141 if (!fseek(hKrnl, 0, SEEK_SET))
1142 rc = ReadOS2Krnl2(hKrnl, cbKrnl);
1143 else
1144 rc = -2;
1145 fclose(hKrnl);
1146 }
1147 else
1148 {
1149 dprintf(("Could not open file\n"));
1150 rc = -1;
1151 }
1152 return rc;
1153}
1154
1155
1156/**
1157 * Worker function for ReadOS2Krnl
1158 * @returns 0 on success.
1159 * errorcodes on failure. (-1 >= rc >= -14)
1160 * @param hKrnl Handle to the kernel file.
1161 * @param cbKrnl Size of the kernel file.
1162 * @author knut st. osmundsen
1163 */
1164static int ReadOS2Krnl2(HFILE hKrnl, unsigned long cbKrnl)
1165{
1166 #if defined(DEBUGR3) || !defined(EXTRACT)
1167 static KRNLINFO KrnlInfo = {0};
1168 #endif
1169 int i, j;
1170 int rc = 0;
1171 char achBuffer[KERNEL_ID_STRING_LENGTH + KERNEL_READ_SIZE];
1172 unsigned long offLXHdr;
1173 struct e32_exe *pLXHdr;
1174
1175
1176 /* find bldlevel string - "@#IBM:14.020#@ IBM OS/2 Kernel - 14.020F" */
1177 if (fseek(hKrnl, 0, SEEK_SET))
1178 return -2;
1179
1180 if (!fread(&achBuffer[KERNEL_ID_STRING_LENGTH], 1, KERNEL_READ_SIZE, hKrnl))
1181 return -3;
1182
1183 i = KERNEL_ID_STRING_LENGTH;
1184 while (cbKrnl > 0)
1185 {
1186 if (i == KERNEL_READ_SIZE)
1187 {
1188
1189 kmemcpy(achBuffer, &achBuffer[KERNEL_READ_SIZE], KERNEL_ID_STRING_LENGTH);
1190 if (!fread(&achBuffer[KERNEL_ID_STRING_LENGTH], 1, cbKrnl > KERNEL_READ_SIZE ? KERNEL_READ_SIZE : (int)cbKrnl, hKrnl))
1191 return -3;
1192
1193 i = 0;
1194 }
1195
1196 if (kstrncmp("@#IBM:", &achBuffer[i], 6) == 0)
1197 break;
1198
1199 /* next */
1200 i++;
1201 cbKrnl--;
1202 }
1203
1204 if (cbKrnl == 0)
1205 {
1206 fclose(hKrnl);
1207 return -4;
1208 }
1209
1210 /* displacement */
1211 j = 0;
1212 while (j < 6 && achBuffer[i+10+j] != '#')
1213 j++;
1214
1215 /* verify signature */
1216 if (kstrncmp(&achBuffer[i+10+j], "#@ IBM OS/2 Kernel", 19) != 0)
1217 return -5;
1218
1219 /* read usBuild */
1220 usBuild = (char)(achBuffer[i+6] - '0') * 1000;
1221 if (achBuffer[i+7] != '.')
1222 {
1223 /* this code is for Warp5 */
1224 usBuild *= 10;
1225 usBuild += (char)(achBuffer[i+7] - '0') * 1000;
1226 i++;
1227 j--;
1228 if (achBuffer[i+7] != '.')
1229 {
1230 usBuild = usBuild * 10;
1231 usBuild = usBuild + (unsigned short)(achBuffer[i+7] - '0') * 1000;
1232 i++;
1233 j--;
1234 }
1235 }
1236
1237 if (j == 0)
1238 {
1239 usBuild += (achBuffer[i+ 8] - '0') * 10;
1240 usBuild += (achBuffer[i+ 9] - '0') * 1;
1241 }
1242 else
1243 {
1244 if (j == 3)
1245 return -9;
1246 usBuild += (achBuffer[i+ 8] - '0') * 100;
1247 usBuild += (achBuffer[i+ 9] - '0') * 10;
1248 usBuild += (achBuffer[i+10] - '0');
1249 }
1250
1251 if (VerifyKernelVer())
1252 return -9;
1253 dprintf(("usBuild: %d\n", usBuild));
1254
1255 /* get segment number */
1256 /* read-MZheader */
1257 if (fseek(hKrnl,0,SEEK_SET))
1258 return -2;
1259
1260 if (!fread(achBuffer, 1, 0x40, hKrnl))
1261 return -3;
1262
1263 offLXHdr = *(unsigned long int *)&achBuffer[0x3c];
1264
1265 if (offLXHdr > 0x2000 && offLXHdr < 0x80) /* just to detect garbage */
1266 return -6;
1267
1268 if (fseek(hKrnl, offLXHdr, SEEK_SET))
1269 return -2;
1270
1271 if (!fread(achBuffer, 1, sizeof(struct e32_exe), hKrnl))
1272 return -3;
1273
1274 /* check LX-magic */
1275 if (achBuffer[0] != 'L' || achBuffer[1] != 'X')
1276 return -7;
1277
1278#if !defined(DEBUGR3) && !defined(EXTRACT)
1279 /* check object count - match it with what we got from the kernel. */
1280 pLXHdr = (struct e32_exe *)achBuffer;
1281 if ((UCHAR)pLXHdr->e32_objcnt != cObjects)
1282 return -8;
1283
1284 if (pLXHdr->e32_objcnt < 10)
1285 return -9;
1286
1287 /* check objects (sizes and flags(?)) */
1288 if (!fseek(hKrnl, (LONG)offLXHdr + (LONG)pLXHdr->e32_objtab, SEEK_SET))
1289 {
1290 struct o32_obj *pObj = (struct o32_obj *)achBuffer;
1291 for (i = 0; i < (int)cObjects; i++)
1292 {
1293 if (!fread(achBuffer, 1, sizeof(OTE), hKrnl))
1294 return -11;
1295 if (pObj->o32_size < paKrnlOTEs[i].ote_size)
1296 return -12;
1297
1298 #if 0 /* don't work! */
1299 if ((pObj->o32_flags & 0xffffUL) != (paKrnlOTEs[i].ote_flags & 0xffffUL))
1300 return -14;
1301 #endif
1302 }
1303 }
1304 else
1305 return -10;
1306#else
1307 /* Since we can't get the OTEs from the kernel when debugging in RING-3,
1308 * we'll use what we find in the kernel.
1309 */
1310
1311 /* object count */
1312 pLXHdr = (struct e32_exe *)achBuffer;
1313 cObjects = (UCHAR)pLXHdr->e32_objcnt;
1314 paKrnlOTEs = &KrnlInfo.aObjects[0];
1315
1316 /* get OTEs */
1317 if (!fseek(hKrnl, (LONG)offLXHdr + (LONG)pLXHdr->e32_objtab, SEEK_SET))
1318 {
1319 struct o32_obj *pObj = (struct o32_obj *)achBuffer;
1320 for (i = 0; i < (int)cObjects; i++)
1321 if (!fread(&paKrnlOTEs[i], 1, sizeof(struct o32_obj), hKrnl))
1322 return -11;
1323 }
1324 else
1325 return -10;
1326#endif
1327
1328 return 0;
1329}
1330
1331
1332
1333/**
1334 * Debug - Main procedure for standalone testing.
1335 */
1336void main(int argc, char **argv)
1337{
1338 char szParm[512];
1339 RPINITIN ReqPack;
1340 int j;
1341 int i = 0;
1342 int argi = 0;
1343
1344 while (argi < argc)
1345 {
1346 j = 0;
1347 while (argv[argi][j] != '\0')
1348 szParm[i++] = argv[argi][j++];
1349 szParm[i++] = ' ';
1350
1351 /* next */
1352 argi++;
1353 }
1354 szParm[i++] = '\0';
1355
1356 ReqPack.InitArgs = szParm;
1357
1358 ProbeKernel(&ReqPack);
1359}
1360#endif
1361
1362
1363#ifdef EXTRACT
1364/**
1365 * Dumps writes a KRNLDBENTRY struct to stderr for the given .sym-file.
1366 * The filesnames are on this format:
1367 * nnnn[n]tm.SYM
1368 * Where: n - are the build number 4 or 5 digits.
1369 * t - kernel type. R = retail, H = half strict, A = all strict.
1370 * m - UNI or SMP. U = UNI processor kernel. S = SMP processor kernel.
1371 * @returns NO_ERROR on success. Untracable error code on error.
1372 * @param pszFilename Pointer to read only filename of the .sym-file.
1373 * @status completely implemented.
1374 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
1375 * @remark Currently only retail kernels are processed. See note below.
1376 */
1377static int processFile(const char *pszFilename)
1378{
1379 APIRET rc;
1380 int cch = kstrlen(pszFilename);
1381
1382 /* Filename check */
1383 if (cch < 10 || cch > 11
1384 || !(pszFilename[0] >= '0' && pszFilename[0] <= '9')
1385 || !(pszFilename[1] >= '0' && pszFilename[1] <= '9')
1386 || !(pszFilename[2] >= '0' && pszFilename[2] <= '9')
1387 || !(pszFilename[3] >= '0' && pszFilename[3] <= '9')
1388 || !(pszFilename[cch-7] >= '0' && pszFilename[cch-7] <= '9')
1389 || !(pszFilename[cch-6] == 'A' || pszFilename[cch-6] == 'H' || pszFilename[cch-6] == 'R')
1390 || !(pszFilename[cch-5] == 'S' || pszFilename[cch-5] == 'U')
1391 )
1392 {
1393 printf16("invalid filename: %s\n", pszFilename);
1394 return 2;
1395 }
1396
1397 /** @remark
1398 * All a/h-strict files are currently ignored.
1399 * When a debug kernel is used we'll have to use the
1400 * .sym-file for it. This is so because I can't distinguish
1401 * between a all-strick and a half-strick kernel (yet).
1402 */
1403 if (pszFilename[cch-6] != 'R')
1404 return 0;
1405
1406 /*
1407 * Probe kernelfile
1408 */
1409 rc = ProbeSymFile(pszFilename);
1410
1411
1412 /*
1413 * on success dump a struct for this kernel
1414 */
1415 if (rc == 0)
1416 {
1417 int i;
1418
1419 printf16(" { /* %s */\n"
1420 " %.*s, \'%c\', %s, %d,\n"
1421 " {\n",
1422 pszFilename,
1423 cch - 6, &pszFilename[0], /* build number */
1424 pszFilename[cch - 6], /* Type, A=astrict, H=halfstrict, R=Retail */
1425 pszFilename[cch - 5] == 'S' ? "TRUE" : "FALSE", /* UNI: TRUE SMP: FALSE */
1426 aImportTab[0].iObject + 1); /* ASSUMES that DOSCODE32 is the last object. */
1427
1428 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1429 {
1430 char *psz = aImportTab[i].achName;
1431 printf16(" {%2d, 0x%08lx}, /* %s */\n",
1432 aImportTab[i].iObject,
1433 aImportTab[i].offObject,
1434 (char *)&aImportTab[i].achName[0]
1435 );
1436 }
1437 printf16(" }\n"
1438 " },\n");
1439 }
1440 else
1441 printf16("ProbeSymFile failed with rc=%d\n", rc);
1442
1443 return rc;
1444}
1445
1446
1447/**
1448 * Extract program.
1449 *
1450 * This is some initial trial-and-error for creating an "database" of
1451 * kernel entrypoints.
1452 *
1453 * Output to stderr the structs generated for the passed in *.sym file.
1454 *
1455 */
1456int main(int argc, char **argv)
1457{
1458 APIRET rc;
1459
1460 if (argc > 1)
1461 {
1462 /*
1463 * Arguments: extract.exe <symfiles...>
1464 */
1465 int i;
1466 for (i = 0; i < argc; i++)
1467 {
1468 rc = processFile(argv[i]);
1469 if (rc != NO_ERROR)
1470 {
1471 printf16("processFile failed with rc=%d for file %s\n",
1472 rc, argv[i]);
1473 return rc;
1474 }
1475 }
1476 }
1477 else
1478 {
1479 /*
1480 * Arguments: extract.exe
1481 *
1482 * Action: Scan current directory for *.sym files.
1483 *
1484 */
1485 USHORT usSearch = 1;
1486 HDIR hDir = HDIR_CREATE;
1487 FILEFINDBUF ffb;
1488 int i;
1489
1490 printf16("/* $Id: probkrnl.c,v 1.17 2000-02-26 17:49:28 bird Exp $\n"
1491 "*\n"
1492 "* Autogenerated kernel symbol database.\n"
1493 "*\n"
1494 "* Copyright (c) 2000 knut st. osmundsen (knut.stange.osmundsen@pmsc.no)\n"
1495 "*\n"
1496 "* Project Odin Software License can be found in LICENSE.TXT\n"
1497 "*\n"
1498 "*/\n");
1499
1500 printf16("\n"
1501 "#include <os2.h>\n"
1502 "#include \"probkrnl.h\"\n"
1503 "\n");
1504
1505 printf16("KRNLDBENTRY aKrnlSymDB[] = \n"
1506 "{\n");
1507
1508 rc = DosFindFirst("*.sym", &hDir, FILE_NORMAL,
1509 &ffb, sizeof(ffb),
1510 &usSearch, 0UL);
1511 while (rc == NO_ERROR & usSearch > 0)
1512 {
1513 rc = processFile(&ffb.achName[0]);
1514 if (rc != NO_ERROR)
1515 {
1516 printf16("processFile failed with rc=%d for file %s\n",
1517 rc, &ffb.achName[0]);
1518 return rc;
1519 }
1520
1521 /* next file */
1522 rc = DosFindNext(hDir, &ffb, sizeof(ffb), &usSearch);
1523 }
1524 DosFindClose(hDir);
1525
1526 printf16(" { /* Terminating entry */\n"
1527 " 0,0,0,0,\n"
1528 " {\n");
1529 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1530 printf16(" {0,0},\n");
1531 printf16(" }\n"
1532 " }\n"
1533 "}; /* end of aKrnlSymDB[] */\n"
1534 );
1535 }
1536
1537
1538 return rc;
1539}
1540#endif /* EXTRACT */
1541
Note: See TracBrowser for help on using the repository browser.