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

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

Support for Warp 4 Fixpack 13 in symbol database.

File size: 46.3 KB
Line 
1/* $Id: probkrnl.c,v 1.19 2000-04-05 18:40:38 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}, /* 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 fchType = TYPE_UNI; /* TYPE_SMP, TYPE_UNI, TYPE_W4 */
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 fchType, 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 fchBldType 'A' all strict
496 * 'H' half strict
497 * 'R' retail
498 * @param fchType TYPE_SMP, TYPE_UNI, TYPE_W4
499 * @param cObjects Count of object in the running kernel.
500 * @sketch Loop thru the table.
501 * @status completely implemented.
502 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
503 */
504static int LookupKrnlEntry(unsigned uBuild, unsigned char fchBldType, unsigned char fchType, unsigned char cObjects)
505{
506 int i;
507
508 /*
509 * Loop tru the DB entries until a NULL pointer is found.
510 */
511 for (i = 0; aKrnlSymDB[i].usBuild != 0; i++)
512 {
513 if (aKrnlSymDB[i].usBuild == uBuild
514 && aKrnlSymDB[i].fchBldType == fchBldType
515 && aKrnlSymDB[i].fchType == fchType
516 && aKrnlSymDB[i].cObjects == cObjects)
517 { /* found matching entry! */
518 int j;
519 int rc;
520 register PKRNLDBENTRY pEntry = &aKrnlSymDB[i];
521
522 dprintf(("LookUpKrnlEntry - found entry for this kernel!\n"));
523
524 /*
525 * Copy symbol data from the DB to aImportTab.
526 */
527 for (j = 0; j < NBR_OF_KRNLIMPORTS; j++)
528 {
529 aImportTab[j].offObject = pEntry->aSyms[j].offObject;
530 aImportTab[j].iObject = pEntry->aSyms[j].iObject;
531 aImportTab[j].ulAddress = paKrnlOTEs[pEntry->aSyms[j].iObject].ote_base
532 + pEntry->aSyms[j].offObject;
533 aImportTab[j].usSel = paKrnlOTEs[pEntry->aSyms[j].iObject].ote_sel;
534 aImportTab[j].fFound = TRUE;
535 dprintf((" %-3d addr=0x%08lx off=0x%08lx %s\n",
536 j, aImportTab[j].ulAddress, aImportTab[j].offObject,
537 aImportTab[j].achName));
538 }
539
540 /* Verify prologs*/
541 rc = VerifyPrologs();
542
543 /* set sym name */
544 if (rc == 0)
545 kstrcpy(szUsrSym, "Win32k Symbol Database");
546 return rc;
547 }
548 }
549
550 /* not found */
551 return 1;
552}
553#endif /* !EXTRACT */
554
555/**
556 * Verifies the that the addresses in aImportTab are valid.
557 * This is done at Ring-0 of course.
558 * @returns 0 if ok, not 0 if not ok.
559 */
560static int VerifyPrologs(void)
561{
562#if !defined(DEBUGR3) && !defined(EXTRACT)
563 APIRET rc;
564 HFILE hDev0 = 0;
565 USHORT usAction = 0;
566
567 rc = DosOpen("\\dev\\elf$", &hDev0, &usAction, 0UL, FILE_NORMAL,
568 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
569 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY,
570 0UL);
571 if (rc == NO_ERROR)
572 {
573 rc = DosDevIOCtl("", "", D16_IOCTL_VERIFYIMPORTTAB, D16_IOCTL_CAT, hDev0);
574 DosClose(hDev0);
575 }
576
577 return rc;
578#else
579 return 0;
580#endif
581}
582
583
584/**
585 * Check a symbol file. Searches for the wanted entry-point addresses.
586 * @returns 0 on success - something else on failiure.
587 * @param pszFilename Name of file to probe.
588 * @precond Must be called after kernel-file is found and processed.
589 * @remark Error codes starts at -50.
590 */
591static int ProbeSymFile(const char * pszFilename)
592{
593 HFILE hSym; /* Filehandle */
594 int cLeftToFind; /* Symbols left to find */
595 unsigned long iSeg; /* Outer search loop: Segment number */
596 unsigned iSym; /* Middle search loop: Symbol number */
597 unsigned i; /* Inner search loop: ProcTab index */
598 int rc;
599
600 MAPDEF MapDef; /* Mapfile header */
601 SEGDEF SegDef; /* Segment header */
602 SYMDEF32 SymDef32; /* Symbol definition 32-bit */
603 SYMDEF16 SymDef16; /* Symbol definition 16-bit */
604 char achBuffer[256]; /* Name buffer */
605 unsigned long offSegment; /* Segment definition offset */
606 unsigned long offSymPtr; /* Symbol pointer(offset) offset */
607 unsigned short offSym; /* Symbol definition offset */
608
609
610 /*
611 * Open the symbol file
612 */
613 hSym = fopen(pszFilename, "rb");
614 if (hSym==0)
615 {
616 dprintf(("Error opening file %s\n", pszFilename));
617 return -50;
618 }
619 dprintf(("\nSuccessfully opened symbolfile: %s\n", pszFilename));
620
621
622 /*
623 * (Open were successfully.)
624 * Now read header and display it.
625 */
626 rc = fread(&MapDef, sizeof(MAPDEF), 1, hSym);
627 if (!rc)
628 { /* oops! read failed, close file and fail. */
629 fclose(hSym);
630 return -51;
631 }
632 achBuffer[0] = MapDef.achModName[0];
633 fread(&achBuffer[1], 1, MapDef.cbModName, hSym);
634 achBuffer[MapDef.cbModName] = '\0';
635 dprintf(("*Module name: %s\n", achBuffer));
636 dprintf(("*Segments: %d\n*MaxSymbolLength: %d\n", MapDef.cSegs, MapDef.cbMaxSym));
637 dprintf(("*ppNextMap: 0x%x\n", MapDef.ppNextMap ));
638
639
640 /*
641 * Verify that the modulename of the symbol file is OS2KRNL.
642 */
643 if (MapDef.cbModName == 7 && kstrncmp(achBuffer, "OS2KRNL", 7) != 0)
644 { /* modulename was not OS2KRNL, fail. */
645 dprintf(("Modulename verify failed\n"));
646 fclose(hSym);
647 return -51;
648 }
649
650
651 /*
652 * Verify that the number of segments is equal to the number objects in OS2KRNL.
653 */
654 #ifndef EXTRACT
655 if (MapDef.cSegs != cObjects)
656 { /* incorrect count of segments. */
657 dprintf(("Segment No. verify failed\n"));
658 fclose(hSym);
659 return -52;
660 }
661 #endif /* !EXTRACT */
662
663
664 /*
665 * Reset ProcTab
666 */
667 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
668 {
669 aImportTab[i].fFound = 0;
670 #ifdef DEBUG
671 aImportTab[i].offObject = 0;
672 aImportTab[i].ulAddress = 0;
673 aImportTab[i].usSel = 0;
674 #endif
675 }
676
677
678 /*
679 * Fileoffset of the first segment.
680 * And set cLeftToFind.
681 */
682 offSegment = SEGDEFOFFSET(MapDef);
683 cLeftToFind = NBR_OF_KRNLIMPORTS;
684
685 /*
686 * Search thru the entire file, segment by segment.
687 *
688 * ASSUME: last segment is the only 32-bit code segment.
689 *
690 */
691 for (iSeg = 0; iSeg < MapDef.cSegs; iSeg++, offSegment = NEXTSEGDEFOFFSET(SegDef))
692 {
693 int fSegEPTBitType; /* Type of segment, 16 or 32 bit, expressed in EPT_XXBIT flags */
694 int fCode; /* Set if this is a code segment, else clear. */
695
696 /*
697 * Read the segment definition.
698 */
699 if (fseek(hSym, offSegment, SEEK_SET))
700 { /* Failed to seek to the segment definition, fail! */
701 fclose(hSym);
702 return -53;
703 }
704 rc = fread(&SegDef, sizeof(SEGDEF), 1, hSym);
705 if (!rc)
706 { /* Failed to read the segment definition, fail! */
707 fclose(hSym);
708 return -53;
709 }
710
711 /*
712 * Some debugging info.
713 */
714 achBuffer[0] = SegDef.achSegName[0];
715 fread(&achBuffer[1], 1, SegDef.cbSegName, hSym);
716 achBuffer[SegDef.cbSegName] = '\0';
717 dprintf(("Segment %.2li Flags=0x%02x cSymbols=0x%04x Name=%s\n",
718 iSeg, SegDef.bFlags, SegDef.cSymbols, &achBuffer[0]));
719
720 /*
721 * Determin segment bit type.
722 */
723 fSegEPTBitType = SEG32BitSegment(SegDef) ? EPT_32BIT : EPT_16BIT;
724 fCode = kstrstr(achBuffer, "CODE") != NULL;
725
726 /*
727 * Search thru all the symbols in this segment
728 * while we look for the requested symbols in aImportTab.
729 */
730 for (iSym = 0; iSym < SegDef.cSymbols && cLeftToFind; iSym++)
731 {
732 unsigned cchName;
733 /*
734 * Fileoffset of the current symbol.
735 * Set filepointer to that position.
736 * Read word (which is the offset of the symbol).
737 */
738 offSymPtr = SYMDEFOFFSET(offSegment, SegDef, iSym);
739 rc = fseek(hSym, offSymPtr, SEEK_SET);
740 if (rc)
741 { /* Symboloffset seek failed, try read next symbol. */
742 dprintf(("Warning: Seek failed (offSymPtr=%d, rc=%d)\n", offSymPtr, rc));
743 continue;
744 }
745 rc = fread(&offSym, sizeof(unsigned short int), 1, hSym);
746 if (!rc)
747 { /* Symboloffset read failed, try read next symbol. */
748 dprintf(("Warning: read failed (offSymPtr=%d, rc=%d)\n", offSymPtr, rc));
749 continue;
750 }
751 rc = fseek(hSym, offSym + offSegment, SEEK_SET);
752 if (rc)
753 { /* Symbol Seek failed, try read next symbol. */
754 dprintf(("Warning: Seek failed (offSym=%d, rc=%d)\n", offSym, rc));
755 continue;
756 }
757
758
759 /*
760 * Read symbol and symbolname.
761 */
762 if (SegDef.bFlags & 0x01)
763 rc = fread(&SymDef32, sizeof(SYMDEF32), 1, hSym);
764 else
765 rc = fread(&SymDef16, sizeof(SYMDEF16), 1, hSym);
766 if (!rc)
767 { /* Symbol read failed, try read next symbol */
768 dprintf(("Warning: Read(1) failed (offSym=%d, rc=%d)\n", offSym, rc));
769 continue;
770 }
771 achBuffer[0] = (SegDef.bFlags & 0x01) ? SymDef32.achSymName[0] : SymDef16.achSymName[0];
772 cchName = (SegDef.bFlags & 0x01) ? SymDef32.cbSymName : SymDef16.cbSymName;
773 rc = fread(&achBuffer[1], 1, cchName, hSym);
774 if (!rc)
775 { /* Symbol read failed, try read next symbol */
776 dprintf(("Warning: Read(2) failed (offSym=%d, rc=%d)\n", offSym, rc));
777 continue;
778 }
779 achBuffer[cchName] = '\0';
780
781
782 /*
783 * Search proctable.
784 */
785 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
786 {
787 if (!aImportTab[i].fFound /* Not allready found */
788 && (aImportTab[i].fType & EPT_BIT_MASK) == fSegEPTBitType /* Equal bittype */
789 && (fCode || (aImportTab[i].fType & EPT_VARIMPORT)) /* Don't look for code in a data segment and vice versa */
790 && aImportTab[i].cchName == cchName /* Equal name length */
791 && kstrncmp(aImportTab[i].achName, achBuffer, cchName) == 0 /* Equal name */
792 )
793 { /* Symbol was found */
794 aImportTab[i].offObject = (SegDef.bFlags & 0x01 ? SymDef32.wSymVal : SymDef16.wSymVal);
795 aImportTab[i].ulAddress = aImportTab[i].offObject + paKrnlOTEs[iSeg].ote_base;
796 aImportTab[i].iObject = (unsigned char)iSeg;
797 aImportTab[i].usSel = paKrnlOTEs[iSeg].ote_sel;
798 dprintf(("debug: base=%lx, size=%lx iSeg=%d\n", paKrnlOTEs[iSeg].ote_base, paKrnlOTEs[iSeg].ote_size, iSeg));
799
800 /* Paranoia test! */
801 #ifndef EXTRACT
802 if (aImportTab[i].offObject < paKrnlOTEs[iSeg].ote_size)
803 {
804 aImportTab[i].fFound = TRUE;
805 cLeftToFind--;
806 dprintf(("Found: %s at off 0x%lx addr 0x%lx, sel=0x%x\n",
807 aImportTab[i].achName, aImportTab[i].offObject,
808 aImportTab[i].ulAddress, aImportTab[i].usSel));
809 }
810 else/* test failed, continue on next symbol*/
811 dprintf(("Error: Paranoia test failed for %s\n", aImportTab[i].achName));;
812 #else
813 aImportTab[i].fFound = TRUE;
814 cLeftToFind--;
815 #endif /* !EXTRACT */
816 break;
817 }
818
819 } /* aImportTab for-loop */
820
821 } /* Symbol for-loop */
822
823 } /* Segment for-loop */
824
825 /*
826 * Close symbol file.
827 */
828 fclose(hSym);
829
830 /*
831 * If not all procedures were found fail.
832 */
833 if (cLeftToFind != 0)
834 return -57;
835
836 /*
837 * Verify function prologs and return.
838 */
839 return VerifyPrologs();
840}
841
842
843/**
844 * Gets the os/2 kernel OTE's (object table entries).
845 * @returns 0 on success. Not 0 on error.
846 */
847static int GetKernelInfo(void)
848{
849#if !defined(DEBUGR3) && !defined(EXTRACT) /* IOCtl not available after inittime! */
850 static KRNLINFO KrnlInfo = {0};
851 APIRET rc;
852 HFILE hDev0 = 0;
853 USHORT usAction = 0;
854
855 rc = DosOpen("\\dev\\elf$", &hDev0, &usAction, 0UL, FILE_NORMAL,
856 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
857 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY,
858 0UL);
859 if (rc == NO_ERROR)
860 {
861 rc = DosDevIOCtl(&KrnlInfo, "", D16_IOCTL_GETKRNLINFO, D16_IOCTL_CAT, hDev0);
862 if (rc == NO_ERROR)
863 {
864 int i;
865
866 /* Set the exported parameters */
867 usBuild = KrnlInfo.usBuild;
868 fchType = KrnlInfo.fchType;
869 fDebug = KrnlInfo.fDebug;
870 cObjects = KrnlInfo.cObjects;
871 paKrnlOTEs = &KrnlInfo.aObjects[0];
872 #ifdef DEBUG
873 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
874 dprintf(("debug: no.%2d base=%lx size=%lx sel=%x\n",
875 i,
876 paKrnlOTEs[i].ote_base,
877 paKrnlOTEs[i].ote_size,
878 paKrnlOTEs[i].ote_sel));
879 #endif
880
881 }
882 DosClose(hDev0);
883 }
884
885 if (rc != NO_ERROR)
886 printf16("Failed to get kernel OTEs\r\n");
887
888 return rc;
889
890#else
891 #ifndef EXTRACT
892 APIRET rc;
893
894 /*--------------*/
895 /* read kernel */
896 /*--------------*/
897 if (szUsrOS2Krnl[0] != '\0')
898 {
899 rc = ReadOS2Krnl(szUsrOS2Krnl);
900 if (rc != 0)
901 {
902 puts("Warning: Invalid kernel file specified. Tries defaults.\n\r");
903 szUsrOS2Krnl[0] = '\0';
904 rc = ReadOS2Krnl(szOS2Krnl);
905 }
906 }
907 else
908 rc = ReadOS2Krnl(szOS2Krnl);
909 return rc;
910 #else
911 return 0;
912 #endif
913#endif
914}
915
916
917/**
918 * Shows result of kernelprobing if not quiet or on error.
919 * @param rc Return code.
920 * @param iSym index of .sym-file into static struct.
921 */
922#ifndef EXTRACT
923static void ShowResult(int rc, int iSym)
924{
925 int i;
926
927 /*
928 * Complain even if quiet on error
929 */
930 if (!fQuiet || rc != 0)
931 {
932 printf16("Win32k - Odin32 support driver.\n");
933
934 /*
935 * kernel stuff
936 */
937 if (rc <= -50 || rc == 0)
938 {
939 #ifdef DEBUGR3
940 printf16(" Found kernel: %s\n", szOS2Krnl);
941 #endif
942 printf16(" Build: %d - v%d.%d\n",
943 usBuild, usVerMajor, usVerMinor);
944 }
945 else
946 printf16(" Kernel probing failed with rc=%d.\n", rc);
947
948 /*
949 * symbol-file
950 */
951 if (rc == 0)
952 printf16(" Found symbolfile: %s\n",
953 szUsrSym[0] == '\0' ? apszSym[iSym] : szUsrSym);
954 else
955 printf16(" Failed to find symbolfile! rc=%d\n", rc);
956
957 /*
958 * function listing
959 */
960 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
961 {
962 printf16(" %-20s at ",aImportTab[i].achName);
963 if (aImportTab[i].fFound)
964 printf16("0x%08lx%s", aImportTab[i].ulAddress, (i % 2) == 0 ? "" : "\n");
965 else
966 printf16("failed!%s", (i % 2) == 0 ? "" : "\n");
967 }
968 if (i % 2) printf16("\n");
969 }
970}
971
972
973/**
974 * "main" function.
975 * Note that the option -Noloader causes nothing to be done.
976 * @returns 0 on success, something else on error.
977 * @param pReqPack Pointer to init request packet
978 * @remark
979 */
980int ProbeKernel(PRPINITIN pReqPack)
981{
982 int rc;
983 int i;
984 int n;
985 SEL GDT;
986 SEL LDT;
987 PGINFOSEG pInfoSeg;
988 USHORT usBootDrive;
989
990 /*----------------*/
991 /* parse InitArgs */
992 /*----------------*/
993 if (pReqPack != NULL && pReqPack->InitArgs != NULL)
994 {
995 n = kstrlen(pReqPack->InitArgs);
996 for (i = 0; i < n; i++)
997 {
998 if ((pReqPack->InitArgs[i] == '/' || pReqPack->InitArgs[i] == '-') && (i+1) < n)
999 {
1000 i++;
1001 switch (pReqPack->InitArgs[i])
1002 {
1003 case 'k':
1004 case 'K': /* Kernel file */
1005 i++;
1006 i += kargncpy(szUsrOS2Krnl, &pReqPack->InitArgs[i], sizeof(szUsrOS2Krnl));
1007 break;
1008
1009 case 'n':
1010 case 'N': /* NoLoader */
1011 return 0;
1012
1013 case 'q':
1014 case 'Q': /* Quiet */
1015 fQuiet = 1;
1016 break;
1017
1018 case 's':
1019 case 'S': /* Symbol file */
1020 i++;
1021 if (pReqPack->InitArgs[i] == 'Y' || pReqPack->InitArgs[i] == 'y')
1022 i += kargncpy(szUsrSym, &pReqPack->InitArgs[i], sizeof(szUsrSym));
1023 break;
1024
1025 case 'v':
1026 case 'V': /* Verbose */
1027 fQuiet = 0;
1028 break;
1029 }
1030 }
1031 }
1032 }
1033
1034 /*---------------------*/
1035 /* determin boot drive */
1036 /*---------------------*/
1037 rc = DosGetInfoSeg(&GDT, &LDT);
1038 if (rc != NO_ERROR)
1039 return rc;
1040
1041 pInfoSeg = MAKEPGINFOSEG(GDT);
1042 usBootDrive = pInfoSeg->bootdrive;
1043 usVerMajor = pInfoSeg->uchMajorVersion;
1044 usVerMinor = pInfoSeg->uchMinorVersion;
1045 dprintf(("BootDrive: %d\n", usBootDrive));
1046
1047 /* set driveletter in constants strings */
1048 usBootDrive = (char)usBootDrive + (char)'a' - 1;
1049 szOS2Krnl[0] = (char)usBootDrive;
1050 for (i = 0; apszSym[i] != NULL; i++)
1051 apszSym[i][0] = (char)usBootDrive;
1052
1053 /*-----------------*/
1054 /* get kernel info */
1055 /*-----------------*/
1056 rc = GetKernelInfo();
1057 if (rc != NO_ERROR)
1058 return rc;
1059
1060 /*--------------*/
1061 /* read symfile */
1062 /*--------------*/
1063 if (!rc)
1064 {
1065 rc = 1;
1066 if (szUsrSym[0] != '\0')
1067 {
1068 rc = ProbeSymFile(szUsrSym);
1069 if (rc)
1070 {
1071 puts("Warning: Invalid symbol file specified. Tries defaults.\n\r");
1072 szUsrSym[0] = '\0';
1073 }
1074 }
1075 if (rc != 0) /* if user sym failed or don't exists. */
1076 {
1077 /*
1078 * Check database - only if not a debug kernel!
1079 * You usually have a .sym-file when using a debug kernel.
1080 * (Currently I am not able to distinguish between half and all strict kernels...)
1081 */
1082 if (fDebug ||
1083 (rc = LookupKrnlEntry((unsigned short)usBuild, 'R', fchType, cObjects)) != 0
1084 )
1085 {
1086 /* search on disk */
1087 i = 0;
1088 while (apszSym[i] != NULL && (rc = ProbeSymFile(apszSym[i])) != 0)
1089 i++;
1090 }
1091 }
1092 }
1093
1094 /* show the result and set return-value */
1095 dprintf(("rc=%d; i=%d\n", rc, i));
1096 ShowResult(rc, i);
1097
1098 return rc;
1099}
1100#endif
1101
1102
1103#ifdef DEBUGR3
1104/**
1105 * Verifies that build no, matches kernel number.
1106 * @returns 0 on equal, !0 on error.
1107 */
1108static int VerifyKernelVer(void)
1109{
1110 int VerMinor, VerMajor;
1111
1112 VerMajor = usBuild < 20000 ? 20 : 30/*?*/;
1113 VerMinor = usBuild < 6600 ? 10 : usBuild < 8000 ? 11 : usBuild < 9000 ? 30 :
1114 usBuild < 10000 ? 40 : usBuild < 15000 ? 45 : 50;
1115
1116 return VerMajor - (int)usVerMajor | VerMinor - (int)usVerMinor;
1117}
1118
1119
1120/**
1121 * Reads and verifies OS/2 kernel.
1122 * @returns 0 on success, not 0 on failure.
1123 * @param filename Filename of the OS/2 kernel.
1124 * @result usBuild is set.
1125 * @remark This step will be eliminated by searching thru the DOSGROUP datasegment
1126 * in the kernel memory. This segment have a string "Internal revision 9.034[smp|uni]"
1127 * This would be much faster than reading the kernel file. It will also give us a more precise
1128 * answer to the question! This is currently a TODO issue. !FIXME!
1129 */
1130static int ReadOS2Krnl(char * pszFilename)
1131{
1132 HFILE hKrnl;
1133 unsigned long cbKrnl;
1134 int rc;
1135
1136 hKrnl = fopen(pszFilename, "rb");
1137 if (hKrnl != 0)
1138 {
1139 cbKrnl = fsize(hKrnl);
1140 if (!fseek(hKrnl, 0, SEEK_SET))
1141 rc = ReadOS2Krnl2(hKrnl, cbKrnl);
1142 else
1143 rc = -2;
1144 fclose(hKrnl);
1145 }
1146 else
1147 {
1148 dprintf(("Could not open file\n"));
1149 rc = -1;
1150 }
1151 return rc;
1152}
1153
1154
1155/**
1156 * Worker function for ReadOS2Krnl
1157 * @returns 0 on success.
1158 * errorcodes on failure. (-1 >= rc >= -14)
1159 * @param hKrnl Handle to the kernel file.
1160 * @param cbKrnl Size of the kernel file.
1161 * @author knut st. osmundsen
1162 */
1163static int ReadOS2Krnl2(HFILE hKrnl, unsigned long cbKrnl)
1164{
1165 #if defined(DEBUGR3) || !defined(EXTRACT)
1166 static KRNLINFO KrnlInfo = {0};
1167 #endif
1168 int i, j;
1169 int rc = 0;
1170 char achBuffer[KERNEL_ID_STRING_LENGTH + KERNEL_READ_SIZE];
1171 unsigned long offLXHdr;
1172 struct e32_exe *pLXHdr;
1173
1174
1175 /* find bldlevel string - "@#IBM:14.020#@ IBM OS/2 Kernel - 14.020F" */
1176 if (fseek(hKrnl, 0, SEEK_SET))
1177 return -2;
1178
1179 if (!fread(&achBuffer[KERNEL_ID_STRING_LENGTH], 1, KERNEL_READ_SIZE, hKrnl))
1180 return -3;
1181
1182 i = KERNEL_ID_STRING_LENGTH;
1183 while (cbKrnl > 0)
1184 {
1185 if (i == KERNEL_READ_SIZE)
1186 {
1187
1188 kmemcpy(achBuffer, &achBuffer[KERNEL_READ_SIZE], KERNEL_ID_STRING_LENGTH);
1189 if (!fread(&achBuffer[KERNEL_ID_STRING_LENGTH], 1, cbKrnl > KERNEL_READ_SIZE ? KERNEL_READ_SIZE : (int)cbKrnl, hKrnl))
1190 return -3;
1191
1192 i = 0;
1193 }
1194
1195 if (kstrncmp("@#IBM:", &achBuffer[i], 6) == 0)
1196 break;
1197
1198 /* next */
1199 i++;
1200 cbKrnl--;
1201 }
1202
1203 if (cbKrnl == 0)
1204 {
1205 fclose(hKrnl);
1206 return -4;
1207 }
1208
1209 /* displacement */
1210 j = 0;
1211 while (j < 6 && achBuffer[i+10+j] != '#')
1212 j++;
1213
1214 /* verify signature */
1215 if (kstrncmp(&achBuffer[i+10+j], "#@ IBM OS/2 Kernel", 19) != 0)
1216 return -5;
1217
1218 /* read usBuild */
1219 usBuild = (char)(achBuffer[i+6] - '0') * 1000;
1220 if (achBuffer[i+7] != '.')
1221 {
1222 /* this code is for Warp5 */
1223 usBuild *= 10;
1224 usBuild += (char)(achBuffer[i+7] - '0') * 1000;
1225 i++;
1226 j--;
1227 if (achBuffer[i+7] != '.')
1228 {
1229 usBuild = usBuild * 10;
1230 usBuild = usBuild + (unsigned short)(achBuffer[i+7] - '0') * 1000;
1231 i++;
1232 j--;
1233 }
1234 }
1235
1236 if (j == 0)
1237 {
1238 usBuild += (achBuffer[i+ 8] - '0') * 10;
1239 usBuild += (achBuffer[i+ 9] - '0') * 1;
1240 }
1241 else
1242 {
1243 if (j == 3)
1244 return -9;
1245 usBuild += (achBuffer[i+ 8] - '0') * 100;
1246 usBuild += (achBuffer[i+ 9] - '0') * 10;
1247 usBuild += (achBuffer[i+10] - '0');
1248 }
1249
1250 if (VerifyKernelVer())
1251 return -9;
1252 dprintf(("usBuild: %d\n", usBuild));
1253
1254 /* get segment number */
1255 /* read-MZheader */
1256 if (fseek(hKrnl,0,SEEK_SET))
1257 return -2;
1258
1259 if (!fread(achBuffer, 1, 0x40, hKrnl))
1260 return -3;
1261
1262 offLXHdr = *(unsigned long int *)&achBuffer[0x3c];
1263
1264 if (offLXHdr > 0x2000 && offLXHdr < 0x80) /* just to detect garbage */
1265 return -6;
1266
1267 if (fseek(hKrnl, offLXHdr, SEEK_SET))
1268 return -2;
1269
1270 if (!fread(achBuffer, 1, sizeof(struct e32_exe), hKrnl))
1271 return -3;
1272
1273 /* check LX-magic */
1274 if (achBuffer[0] != 'L' || achBuffer[1] != 'X')
1275 return -7;
1276
1277#if !defined(DEBUGR3) && !defined(EXTRACT)
1278 /* check object count - match it with what we got from the kernel. */
1279 pLXHdr = (struct e32_exe *)achBuffer;
1280 if ((UCHAR)pLXHdr->e32_objcnt != cObjects)
1281 return -8;
1282
1283 if (pLXHdr->e32_objcnt < 10)
1284 return -9;
1285
1286 /* check objects (sizes and flags(?)) */
1287 if (!fseek(hKrnl, (LONG)offLXHdr + (LONG)pLXHdr->e32_objtab, SEEK_SET))
1288 {
1289 struct o32_obj *pObj = (struct o32_obj *)achBuffer;
1290 for (i = 0; i < (int)cObjects; i++)
1291 {
1292 if (!fread(achBuffer, 1, sizeof(OTE), hKrnl))
1293 return -11;
1294 if (pObj->o32_size < paKrnlOTEs[i].ote_size)
1295 return -12;
1296
1297 #if 0 /* don't work! */
1298 if ((pObj->o32_flags & 0xffffUL) != (paKrnlOTEs[i].ote_flags & 0xffffUL))
1299 return -14;
1300 #endif
1301 }
1302 }
1303 else
1304 return -10;
1305#else
1306 /* Since we can't get the OTEs from the kernel when debugging in RING-3,
1307 * we'll use what we find in the kernel.
1308 */
1309
1310 /* object count */
1311 pLXHdr = (struct e32_exe *)achBuffer;
1312 cObjects = (UCHAR)pLXHdr->e32_objcnt;
1313 paKrnlOTEs = &KrnlInfo.aObjects[0];
1314
1315 /* get OTEs */
1316 if (!fseek(hKrnl, (LONG)offLXHdr + (LONG)pLXHdr->e32_objtab, SEEK_SET))
1317 {
1318 struct o32_obj *pObj = (struct o32_obj *)achBuffer;
1319 for (i = 0; i < (int)cObjects; i++)
1320 if (!fread(&paKrnlOTEs[i], 1, sizeof(struct o32_obj), hKrnl))
1321 return -11;
1322 }
1323 else
1324 return -10;
1325#endif
1326
1327 return 0;
1328}
1329
1330
1331
1332/**
1333 * Debug - Main procedure for standalone testing.
1334 */
1335void main(int argc, char **argv)
1336{
1337 char szParm[512];
1338 RPINITIN ReqPack;
1339 int j;
1340 int i = 0;
1341 int argi = 0;
1342
1343 while (argi < argc)
1344 {
1345 j = 0;
1346 while (argv[argi][j] != '\0')
1347 szParm[i++] = argv[argi][j++];
1348 szParm[i++] = ' ';
1349
1350 /* next */
1351 argi++;
1352 }
1353 szParm[i++] = '\0';
1354
1355 ReqPack.InitArgs = szParm;
1356
1357 ProbeKernel(&ReqPack);
1358}
1359#endif
1360
1361
1362#ifdef EXTRACT
1363/**
1364 * Dumps writes a KRNLDBENTRY struct to stderr for the given .sym-file.
1365 * The filesnames are on this format:
1366 * nnnn[n]tm.SYM
1367 * Where: n - are the build number 4 or 5 digits.
1368 * t - kernel type. R = retail, H = half strict, A = all strict.
1369 * m - UNI or SMP. U = UNI processor kernel. S = SMP processor kernel.
1370 * @returns NO_ERROR on success. Untracable error code on error.
1371 * @param pszFilename Pointer to read only filename of the .sym-file.
1372 * @status completely implemented.
1373 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
1374 * @remark Currently only retail kernels are processed. See note below.
1375 */
1376static int processFile(const char *pszFilename)
1377{
1378 APIRET rc;
1379 int cch = kstrlen(pszFilename);
1380
1381 /* Filename check */
1382 if (cch < 10 || cch > 11
1383 || !(pszFilename[0] >= '0' && pszFilename[0] <= '9')
1384 || !(pszFilename[1] >= '0' && pszFilename[1] <= '9')
1385 || !(pszFilename[2] >= '0' && pszFilename[2] <= '9')
1386 || !(pszFilename[3] >= '0' && pszFilename[3] <= '9')
1387 || !(pszFilename[cch-7] >= '0' && pszFilename[cch-7] <= '9')
1388 || !(pszFilename[cch-6] == 'A' || pszFilename[cch-6] == 'H' || pszFilename[cch-6] == 'R')
1389 || !(pszFilename[cch-5] == 'S' || pszFilename[cch-5] == 'U' || pszFilename[cch-5] == '4')
1390 )
1391 {
1392 printf16("invalid filename: %s\n", pszFilename);
1393 return 2;
1394 }
1395
1396 /** @remark
1397 * All a/h-strict files are currently ignored.
1398 * When a debug kernel is used we'll have to use the
1399 * .sym-file for it. This is so because I can't distinguish
1400 * between a all-strick and a half-strick kernel (yet).
1401 */
1402 if (pszFilename[cch-6] != 'R')
1403 return 0;
1404
1405 /*
1406 * Probe kernelfile
1407 */
1408 rc = ProbeSymFile(pszFilename);
1409
1410
1411 /*
1412 * on success dump a struct for this kernel
1413 */
1414 if (rc == 0)
1415 {
1416 int i;
1417
1418 printf16(" { /* %s */\n"
1419 " %.*s, \'%c\', %s, %d,\n"
1420 " {\n",
1421 pszFilename,
1422 cch - 6, &pszFilename[0], /* build number */
1423 pszFilename[cch - 6], /* Type, A=astrict, H=halfstrict, R=Retail */
1424 pszFilename[cch - 5] == 'S' ? /* UNI: TYPE_UNI SMP: TYPE_SMP W4: TYPE_W4 */
1425 "TYPE_SMP" : pszFilename[cch - 5] == '4' ? "TYPE_W4" : "TYPE_UNI",
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
1461 /*
1462 * Set paKrnlOTEs to point to an zeroed array of OTEs.
1463 */
1464 static KRNLINFO KrnlInfo = {0};
1465 paKrnlOTEs = &KrnlInfo.aObjects[0];
1466
1467 if (argc > 1)
1468 {
1469 /*
1470 * Arguments: extract.exe <symfiles...>
1471 */
1472 int i;
1473 for (i = 0; i < argc; i++)
1474 {
1475 rc = processFile(argv[i]);
1476 if (rc != NO_ERROR)
1477 {
1478 printf16("processFile failed with rc=%d for file %s\n",
1479 rc, argv[i]);
1480 return rc;
1481 }
1482 }
1483 }
1484 else
1485 {
1486 /*
1487 * Arguments: extract.exe
1488 *
1489 * Action: Scan current directory for *.sym files.
1490 *
1491 */
1492 USHORT usSearch = 1;
1493 HDIR hDir = HDIR_CREATE;
1494 FILEFINDBUF ffb;
1495 int i;
1496
1497 printf16("/* $Id: probkrnl.c,v 1.19 2000-04-05 18:40:38 bird Exp $\n"
1498 "*\n"
1499 "* Autogenerated kernel symbol database.\n"
1500 "*\n"
1501 "* Copyright (c) 2000 knut st. osmundsen (knut.stange.osmundsen@pmsc.no)\n"
1502 "*\n"
1503 "* Project Odin Software License can be found in LICENSE.TXT\n"
1504 "*\n"
1505 "*/\n");
1506
1507 printf16("\n"
1508 "#define INCL_NOPMAPI\n"
1509 "#define INCL_NOBASEAPI\n"
1510 "#include <os2.h>\n"
1511 "#include \"probkrnl.h\"\n"
1512 "\n");
1513
1514 printf16("KRNLDBENTRY aKrnlSymDB[] = \n"
1515 "{\n");
1516
1517 rc = DosFindFirst("*.sym", &hDir, FILE_NORMAL,
1518 &ffb, sizeof(ffb),
1519 &usSearch, 0UL);
1520 while (rc == NO_ERROR & usSearch > 0)
1521 {
1522 rc = processFile(&ffb.achName[0]);
1523 if (rc != NO_ERROR)
1524 {
1525 printf16("processFile failed with rc=%d for file %s\n",
1526 rc, &ffb.achName[0]);
1527 return rc;
1528 }
1529
1530 /* next file */
1531 rc = DosFindNext(hDir, &ffb, sizeof(ffb), &usSearch);
1532 }
1533 DosFindClose(hDir);
1534
1535 printf16(" { /* Terminating entry */\n"
1536 " 0,0,0,0,\n"
1537 " {\n");
1538 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1539 printf16(" {0,0},\n");
1540 printf16(" }\n"
1541 " }\n"
1542 "}; /* end of aKrnlSymDB[] */\n"
1543 );
1544 }
1545
1546
1547 return rc;
1548}
1549#endif /* EXTRACT */
1550
Note: See TracBrowser for help on using the repository browser.