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

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

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

File size: 45.9 KB
Line 
1/* $Id: probkrnl.c,v 1.16 2000-02-25 18:15:02 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
52
53/*******************************************************************************
54* Header Files *
55*******************************************************************************/
56#include <os2.h>
57
58#include <exe386.h>
59#include <strat2.h>
60#include <reqpkt.h>
61
62#include "os2krnl.h" /* must be included before dev1632.h! */
63#include "sym.h"
64#include "probkrnl.h"
65#include "dev16.h"
66#include "dev1632.h"
67#include "vprntf16.h"
68#include "log.h"
69
70
71/*******************************************************************************
72* Global Variables *
73* Note: must be inited or else we'll get BSS segment *
74*******************************************************************************/
75/*
76 * kernel data - !only valid during init!
77 */
78
79/*
80 * aImportTab defines the imported and overloaded OS/2 kernel functions.
81 * IMPORTANT: aImportTab has a sibling array in d32init.c, aulProc, which must
82 * match entry by entry. Adding/removing/shuffling aImportTab, aulProc
83 * has to be updated immediately!
84 */
85IMPORTKRNLSYM aImportTab[NBR_OF_KRNLIMPORTS] =
86{/* iFound cchName offObject usSel fType */
87 /* iObject achName ulAddress cProlog */
88 {FALSE, -1, 8, "_ldrRead", -1, -1, -1, -1, EPT_PROC32}, /* 0 */
89 {FALSE, -1, 8, "_ldrOpen", -1, -1, -1, -1, EPT_PROC32}, /* 1 */
90 {FALSE, -1, 9, "_ldrClose", -1, -1, -1, -1, EPT_PROC32}, /* 2 */
91 {FALSE, -1, 12, "_LDRQAppType", -1, -1, -1, -1, EPT_PROC32}, /* 3 */
92 {FALSE, -1, 20, "_ldrEnum32bitRelRecs", -1, -1, -1, -1, EPT_PROC32}, /* 4 */
93 {FALSE, -1, 10, "_IOSftOpen", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 5 */
94 {FALSE, -1, 11, "_IOSftClose", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 6 */
95 {FALSE, -1, 15, "_IOSftTransPath", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 7 */
96 {FALSE, -1, 12, "_IOSftReadAt", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 8 */
97 {FALSE, -1, 13, "_IOSftWriteAt", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 9 */
98 {FALSE, -1, 12, "_SftFileSize", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 10 */
99 {FALSE, -1, 11, "_VMAllocMem", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 11 */
100 {FALSE, -1, 11, "_VMGetOwner", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 12 */
101 {FALSE, -1, 11, "g_tkExecPgm", -1, -1, -1, -1, EPT_PROC32}, /* 13 */ /* currently disabled! */
102 {FALSE, -1, 11, "f_FuStrLenZ", -1, -1, -1, -1, EPT_PROCIMPORT16}, /* 14 */
103 {FALSE, -1, 10, "f_FuStrLen", -1, -1, -1, -1, EPT_PROCIMPORT16}, /* 14 */
104 {FALSE, -1, 8, "f_FuBuff", -1, -1, -1, -1, EPT_PROCIMPORT16} /* 15 */
105/* {FALSE, -1, 11, "", -1, -1, -1, EPT_PROCIMPORT16} */ /* 16 */
106};
107
108unsigned short int usBuild = 0;
109unsigned short usVerMajor = 0;
110unsigned short usVerMinor = 0;
111unsigned char fSMP = FALSE;
112unsigned char fDebug = FALSE;
113
114
115/*
116 * privat data
117 */
118static int fQuiet = 0;
119static char szUsrOS2Krnl[50] = {0};
120static char szOS2Krnl[] = {"c:\\os2krnl"};
121
122static char szUsrSym[50] = {0};
123static char * apszSym[] =
124{
125 {"c:\\os2krnl.sym"}, /* usual for debugkernel */
126 {"c:\\os2\\pdpsi\\pmdf\\warp4\\os2krnlr.sym"}, /* warp 4 */
127 {"c:\\os2\\pdpsi\\pmdf\\warp4\\os2krnld.sym"}, /* warp 4 */
128 {"c:\\os2\\pdpsi\\pmdf\\warp4\\os2krnlb.sym"}, /* warp 4 */
129 {"c:\\os2\\pdpsi\\pmdf\\warp45_u\\os2krnlr.sym"}, /* warp 45 */
130 {"c:\\os2\\pdpsi\\pmdf\\warp45_u\\os2krnld.sym"}, /* warp 45 */
131 {"c:\\os2\\pdpsi\\pmdf\\warp45_u\\os2krnlb.sym"}, /* warp 45 */
132 {"c:\\os2\\pdpsi\\pmdf\\warp45_s\\os2krnlr.sym"}, /* warp 45 */
133 {"c:\\os2\\pdpsi\\pmdf\\warp45_s\\os2krnld.sym"}, /* warp 45 */
134 {"c:\\os2\\pdpsi\\pmdf\\warp45_s\\os2krnlb.sym"}, /* warp 45 */
135 {"c:\\os2\\system\\trace\\os2krnl.sym"}, /* warp 3 ?*/
136 {"c:\\os2\\system\\pmdf\\os2krnlr.sym"}, /* warp 3 ?*/
137 {"c:\\os2krnlr.sym"}, /* custom */
138 {"c:\\os2krnlh.sym"}, /* custom */
139 {"c:\\os2krnld.sym"}, /* custom */
140 NULL
141};
142
143/* Result from GetKernelInfo/ReadOS2Krnl. */
144static unsigned char cObjects = 0;
145static POTE paKrnlOTEs = NULL;
146
147
148
149/*******************************************************************************
150* Internal Functions *
151*******************************************************************************/
152/* File an output replacements */
153static HFILE fopen(const char * pszFilename, const char * pszIgnored);
154static int fread(void * pvBuffer, USHORT cbBlock, USHORT cBlock, HFILE hFile);
155static int fseek(HFILE hfile, signed long off, int iOrg);
156static unsigned long fsize(HFILE hFile);
157static void puts(char *psz);
158
159/* C-library replacements. */
160static void kmemcpy(char *psz1, const char *psz2, int cch);
161static char * kstrstr(const char *psz1, const char *psz2);
162static int kstrcmp(const char *psz1, const char *psz2);
163static int kstrncmp(const char *psz1, const char *psz2, int cch);
164static int kstrnicmp(const char *psz1, const char *psz2, int cch);
165static int kstrlen(const char *psz);
166static char * kstrcpy(char * pszTarget, const char * pszSource);
167static int kargncpy(char *pszTarget, const char *pszArg, unsigned cchMaxlen);
168
169/* Workers */
170static int LookupKrnlEntry(unsigned uBuild, unsigned char chType,
171 unsigned char fSMP, unsigned char cObjects);
172static int VerifyPrologs(void);
173static int ProbeSymFile(const char *pszFilename);
174static int GetKernelInfo(void);
175
176/* Ouput */
177static void ShowDecNumber(unsigned long ul);
178static void ShowHexNumber(unsigned long ul);
179static void ShowResult(int rc, int iSym);
180
181/* Others used while debugging in R3. */
182static int VerifyKernelVer(void);
183static int ReadOS2Krnl(char *pszFilename);
184static int ReadOS2Krnl2(HFILE hKrnl, unsigned long cbKrnl);
185static int processFile(const char *pszFilename);
186
187
188
189
190/*******************************************************************************
191* Implementation of Internal Helper Functions *
192*******************************************************************************/
193
194/**
195 * Quick implementation of fopen.
196 * @param pszFilename name of file to open (sz)
197 * @param pszIgnored whatever - it is ignored
198 * @return Handle to file. (not pointer to a FILE stream as in C-library)
199 * @remark binary and readonly is assumed!
200 */
201static HFILE fopen(const char * pszFilename, const char * pszIgnored)
202{
203 HFILE hFile = 0;
204 USHORT rc;
205 unsigned short Action = 0;
206
207 rc = DosOpen(
208 (char*)pszFilename,
209 &hFile,
210 &Action,
211 0,
212 FILE_NORMAL,
213 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
214 OPEN_SHARE_DENYNONE + OPEN_ACCESS_READONLY,
215 NULL);
216
217 pszIgnored = pszIgnored;
218 return hFile;
219}
220
221
222/**
223 * fread emulation
224 * @returns Number of blocks read.
225 * @param pvBuffer Buffer to read into
226 * @param cbBlock Blocksize
227 * @param cBlock Block count
228 * @param hFile Handle to file (HFILE)
229 */
230static int fread(void * pvBuffer, USHORT cbBlock, USHORT cBlock, HFILE hFile)
231{
232 USHORT ulRead;
233 USHORT rc;
234
235 rc = DosRead(hFile, pvBuffer, (USHORT)(cbBlock*cBlock), &ulRead);
236 if (rc == 0)
237 rc = (USHORT)cBlock;
238 else
239 rc = 0;
240
241 return rc;
242}
243
244
245/**
246 * fseek emultation
247 * @returns Same as DosChgFilePtr
248 * @param hFile Filehandle
249 * @param off offset into file from origin
250 * @param org origin
251 */
252static int fseek(HFILE hFile, signed long off, int iOrg)
253{
254 ULONG ul;
255 return (int)DosChgFilePtr(hFile, off, iOrg, &ul);
256}
257
258
259/**
260 * Get filesize in bytes.
261 * @returns Filesize.
262 * @param hFile Filehandle
263 * @remark This function sets the file position to end of file.
264 */
265static unsigned long fsize(HFILE hFile)
266{
267 USHORT rc;
268 unsigned long cb;
269
270 rc = DosChgFilePtr(hFile, 0, FILE_END, &cb);
271
272 return cb;
273}
274
275
276/**
277 * puts lookalike
278 */
279static void puts(char * psz)
280{
281 DosPutMessage(0, kstrlen(psz), psz);
282}
283
284
285/**
286 * kmemcpy - memory copy - slow!
287 * @param psz1 target
288 * @param psz2 source
289 * @param cch length
290 */
291static void kmemcpy(char *psz1, const char *psz2, int cch)
292{
293 while (cch-- != 0)
294 *psz1++ = *psz2++;
295}
296
297
298/**
299 * Finds psz2 in psz2.
300 * @returns Pointer to occurence of psz2 in psz1.
301 * @param psz1 String to be search.
302 * @param psz2 Substring to search for.
303 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
304 */
305static char *kstrstr(const char *psz1, const char *psz2)
306{
307 while (*psz1 != '\0')
308 {
309 register int i = 0;
310 while (psz2[i] != '\0' && psz1[i] == psz2[i])
311 i++;
312
313 /* found it? */
314 if (psz2[i] == '\0')
315 return (char*)psz1;
316 if (psz1[i] == '\0' )
317 break;
318 psz1++;
319 }
320
321 return NULL;
322}
323
324
325#if 0 /* not in use */
326/**
327 * kstrcmp - String compare
328 * @returns 0 - equal else !0
329 * @param psz1 String 1
330 * @param psz2 String 2
331 */
332static int kstrcmp(const char *psz1, const char *psz2);
333{
334 while (*psz1 == *psz2 && *psz1 != '\0' && *psz2 != '\0')
335 {
336 psz1++;
337 psz2++;
338 }
339 return *psz1 - *psz2;
340}
341#endif
342
343
344/**
345 * kstrncmp - String 'n' compare.
346 * @returns 0 - equal else !0
347 * @param p1 String 1
348 * @param p2 String 2
349 * @param len length
350 */
351static int kstrncmp(register const char *psz1, register const char *psz2, int cch)
352{
353 int i = 0;
354 while (i < cch && *psz1 == *psz2 && *psz1 != '\0' && *psz2 != '\0')
355 {
356 psz1++;
357 psz2++;
358 i++;
359 }
360
361 return i - cch;
362}
363
364
365#if 0 /* not in use */
366/**
367 * kstrnicmp - String 'n' compare, case-insensitive.
368 * @returns 0 - equal else !0
369 * @param p1 String 1
370 * @param p2 String 2
371 * @param len length
372 */
373static int kstrnicmp(const char *psz1, const char *psz2, int cch)
374{
375 register char ch1, ch2;
376
377 do
378 {
379 ch1 = *psz1++;
380 if (ch1 >= 'A' && ch1 <= 'Z')
381 ch1 += 'a' - 'A'; /* to lower case */
382 ch2 = *psz2++;
383 if (ch2 >= 'A' && ch2 <= 'Z')
384 ch2 += 'a' - 'A'; /* to lower case */
385 } while (--cch > 0 && ch1 == ch2 && ch1 != '\0' && ch2 != '\0');
386
387 return ch1 - ch2;
388}
389#endif
390
391
392/**
393 * kstrlen - String length.
394 * @returns Length of the string.
395 * @param psz Pointer to string.
396 * @status completely implemented and tested.
397 * @author knut st. osmundsen
398 */
399static int kstrlen(register const char * psz)
400{
401 register int cch = 0;
402 while (*psz++ != '\0')
403 cch++;
404 return cch;
405}
406
407
408/**
409 * String copy (strcpy).
410 * @returns Pointer to target string.
411 * @param pszTarget Target string.
412 * @param pszSource Source string.
413 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
414 */
415static char * kstrcpy(char * pszTarget, register const char * pszSource)
416{
417 register char *psz = pszTarget;
418
419 while (*pszSource != '\0')
420 *psz++ = *pszSource++;
421
422 return pszTarget;
423}
424
425
426
427
428/**
429 * Copy an argument to a buffer. Ie. "-K[=|:]c:\os2krnl ....". Supports quotes
430 * @returns Number of chars of pszArg that has been processed.
431 * @param pszTarget - pointer to target buffer.
432 * @param pszArg - pointer to source argument string.
433 * @param cchMaxlen - maximum chars to copy.
434 */
435static int kargncpy(char * pszTarget, const char * pszArg, unsigned cchMaxlen)
436{
437 int i = 0;
438 int fQuote = FALSE;
439
440 /* skip option word/letter */
441 while (*pszArg != '\0' && *pszArg != ' ' && *pszArg != ':' &&
442 *pszArg != '=' && *pszArg != '-' && *pszArg != '/')
443 {
444 pszArg++;
445 i++;
446 }
447
448 if (*pszArg == ' ' || *pszArg == '-' || *pszArg == '/' || *pszArg == '\0')
449 return 0;
450
451
452 do
453 {
454 pszArg++;
455 i++;
456 } while (*pszArg != '\0' && *pszArg == ' ');
457
458 /* copy maxlen or less */
459 /* check for quotes */
460 if (*pszArg == '"')
461 {
462 fQuote = TRUE;
463 pszArg++;
464 i++;
465 }
466 /* copy loop */
467 while (cchMaxlen > 1 && (fQuote ? *pszArg != '"' : *pszArg != ' ') && *pszArg != '\0')
468 {
469 *pszTarget++ = *pszArg++;
470 i++;
471 cchMaxlen--;
472 }
473
474 /* terminate pszTarget */
475 pszTarget = '\0';
476
477 return i;
478}
479
480
481
482/*******************************************************************************
483* Implementation Of The Important Functions *
484*******************************************************************************/
485#ifndef EXTRACT
486/**
487 * Checks if this kernel is within the kernel symbol database.
488 * If an entry for the kernel is found, the data is copied from the
489 * database entry to aImportTab.
490 * @returns NO_ERROR on succes (0)
491 * 1 if not found.
492 * Error code on error.
493 * @param uBuild Build level.
494 * @param chType 'A' all strict
495 * 'H' half strict
496 * 'R' retail
497 * @param fSMP TRUE: SMP
498 * FALSE: UNI
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 chType, unsigned char fSMP, 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].chType == chType
515 && aKrnlSymDB[i].fSMP == fSMP
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 fSMP = KrnlInfo.fSMP;
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', fSMP, 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')
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' ? "TRUE" : "FALSE", /* UNI: TRUE SMP: FALSE */
1425 aImportTab[0].iObject + 1); /* ASSUMES that DOSCODE32 is the last object. */
1426
1427 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1428 {
1429 char *psz = aImportTab[i].achName;
1430 printf16(" {%2d, 0x%08lx}, /* %s */\n",
1431 aImportTab[i].iObject,
1432 aImportTab[i].offObject,
1433 (char *)&aImportTab[i].achName[0]
1434 );
1435 }
1436 printf16(" }\n"
1437 " },\n");
1438 }
1439 else
1440 printf16("ProbeSymFile failed with rc=%d\n", rc);
1441
1442 return rc;
1443}
1444
1445
1446/**
1447 * Extract program.
1448 *
1449 * This is some initial trial-and-error for creating an "database" of
1450 * kernel entrypoints.
1451 *
1452 * Output to stderr the structs generated for the passed in *.sym file.
1453 *
1454 */
1455int main(int argc, char **argv)
1456{
1457 APIRET rc;
1458
1459 if (argc > 1)
1460 {
1461 /*
1462 * Arguments: extract.exe <symfiles...>
1463 */
1464 int i;
1465 for (i = 0; i < argc; i++)
1466 {
1467 rc = processFile(argv[i]);
1468 if (rc != NO_ERROR)
1469 {
1470 printf16("processFile failed with rc=%d for file %s\n",
1471 rc, argv[i]);
1472 return rc;
1473 }
1474 }
1475 }
1476 else
1477 {
1478 /*
1479 * Arguments: extract.exe
1480 *
1481 * Action: Scan current directory for *.sym files.
1482 *
1483 */
1484 USHORT usSearch = 1;
1485 HDIR hDir = HDIR_CREATE;
1486 FILEFINDBUF ffb;
1487 int i;
1488
1489 printf16("/* $Id: probkrnl.c,v 1.16 2000-02-25 18:15:02 bird Exp $\n"
1490 "*\n"
1491 "* Autogenerated kernel symbol database.\n"
1492 "*\n"
1493 "* Copyright (c) 2000 knut st. osmundsen (knut.stange.osmundsen@pmsc.no)\n"
1494 "*\n"
1495 "* Project Odin Software License can be found in LICENSE.TXT\n"
1496 "*\n"
1497 "*/\n");
1498
1499 printf16("\n"
1500 "#include <os2.h>\n"
1501 "#include \"probkrnl.h\"\n"
1502 "\n");
1503
1504 printf16("KRNLDBENTRY aKrnlSymDB[] = \n"
1505 "{\n");
1506
1507 rc = DosFindFirst("*.sym", &hDir, FILE_NORMAL,
1508 &ffb, sizeof(ffb),
1509 &usSearch, 0UL);
1510 while (rc == NO_ERROR & usSearch > 0)
1511 {
1512 rc = processFile(&ffb.achName[0]);
1513 if (rc != NO_ERROR)
1514 {
1515 printf16("processFile failed with rc=%d for file %s\n",
1516 rc, &ffb.achName[0]);
1517 return rc;
1518 }
1519
1520 /* next file */
1521 rc = DosFindNext(hDir, &ffb, sizeof(ffb), &usSearch);
1522 }
1523 DosFindClose(hDir);
1524
1525 printf16(" { /* Terminating entry */\n"
1526 " 0,0,0,0,\n"
1527 " {\n");
1528 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1529 printf16(" {0,0},\n");
1530 printf16(" }\n"
1531 " }\n"
1532 "}; /* end of aKrnlSymDB[] */\n"
1533 );
1534 }
1535
1536
1537 return rc;
1538}
1539#endif /* EXTRACT */
1540
Note: See TracBrowser for help on using the repository browser.