source: trunk/tools/common/kFileLX.cpp@ 5120

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

Corrected kFileLX and kFilePE constructors.
Made kDump.exe work again.
Added import module dump to kFilePE.

File size: 18.6 KB
Line 
1/* $Id: kFileLX.cpp,v 1.4 2001-02-02 08:45:41 bird Exp $
2 *
3 *
4 *
5 * Copyright (c) 2000 knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
6 *
7 * Project Odin Software License can be found in LICENSE.TXT
8 *
9 */
10
11/*******************************************************************************
12* Defined Constants *
13*******************************************************************************/
14/* emx fixups */
15#ifdef __EMX__
16 #define __stdcall
17 #define max(a,b) (((a) > (b)) ? (a) : (b))
18 #define min(a,b) (((a) < (b)) ? (a) : (b))
19#endif
20#define INCL_DOSERRORS
21#define FOR_EXEHDR 1 /* exe386.h flag */
22#define DWORD ULONG /* Used by exe386.h / newexe.h */
23#define WORD USHORT /* Used by exe386.h / newexe.h */
24
25
26/******************************************************************************
27* Header Files *
28******************************************************************************/
29#ifdef __EMX__
30#define INT INT_
31#define PCHAR PCHAR_
32#endif
33#include <os2.h>
34#ifdef __EMX__
35#undef PCHAR
36#undef INT
37#endif
38#include <newexe.h>
39#include <exe386.h>
40
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#include <malloc.h>
45
46#include <assert.h>
47
48#include "kFile.h"
49#include "kFileFormatBase.h"
50#include "kInterfaces.h"
51#include "kFileLX.h"
52
53
54/*******************************************************************************
55* Structures and Typedefs *
56*******************************************************************************/
57typedef struct _export_state
58{
59 struct b32_bundle * pb32; /* Pointer to current bundle. */
60 int iOrdinalBundle; /* The ordinal the bundle starts at. */
61 struct e32_entry * pe32; /* Pointer to the current bundle entry. */
62 int iOrdinal; /* The current ordinal. */
63} EXPSTATE, *PEXPSTATE;
64
65
66
67BOOL kFileLX::queryExportName(int iOrdinal, char *pszBuffer)
68{
69 PUSHORT pus;
70 PUCHAR puch;
71
72 /* resident name table */
73 if (pe32->e32_restab)
74 {
75 puch = (PUCHAR)pvBase + offLXHdr + pe32->e32_restab;
76 while (*puch != 0)
77 {
78 pus = (PUSHORT)(puch + 1 + *puch);
79 if (*pus == iOrdinal)
80 {
81 memcpy(pszBuffer, puch + 1, *puch);
82 pszBuffer[*puch] = '\0';
83 return TRUE;
84 }
85 puch += *puch + 1 + 2;
86 }
87 }
88
89 /* not found, check the non-resident name table too */
90 if (pe32->e32_nrestab)
91 {
92 puch = (PUCHAR)pvBase + pe32->e32_nrestab;
93 while (*puch != 0)
94 {
95 pus = (PUSHORT)(puch + 1 + *puch);
96 if (*pus == iOrdinal)
97 {
98 memcpy(pszBuffer, puch + 1, *puch);
99 pszBuffer[*puch] = '\0';
100 return TRUE;
101 }
102 puch += *puch + 1 + 2;
103 }
104 }
105
106 return FALSE;
107}
108
109
110
111/**
112 * Create an LX file object from an LX executable image.
113 * @param pszFilename LX executable image name.
114 */
115kFileLX::kFileLX(const char *pszFilename) throw (int)
116: pvBase(NULL)
117{
118 struct exe_hdr * pehdr;
119
120 /* create filemapping */
121 pvBase = kFileFormatBase::readfile(pszFilename);
122 if (pvBase == NULL)
123 throw(1);
124
125 pehdr = (struct exe_hdr*)pvBase;
126 if (pehdr->e_magic == EMAGIC)
127 offLXHdr = pehdr->e_lfanew;
128 else
129 offLXHdr = 0;
130
131 pe32 = (struct e32_exe*)((char*)pvBase + offLXHdr);
132 if (*(PUSHORT)pe32 != E32MAGIC)
133 {
134 free(pvBase);
135 pvBase = NULL;
136 throw(2);
137 }
138
139 paObject = pe32->e32_objtab && pe32->e32_objcnt
140 ? (struct o32_obj*)((char*)pvBase + pe32->e32_objtab + offLXHdr) : NULL;
141 paMap = pe32->e32_objmap
142 ? (struct o32_map*)((char*)pvBase + pe32->e32_objmap + offLXHdr) : NULL;
143}
144
145
146/**
147 * Create an LX file object from an LX executable image.
148 * @param pFile Pointer to opened LX file.
149 */
150kFileLX::kFileLX(kFile *pFile) throw (int)
151: pvBase(NULL)
152{
153 struct exe_hdr * pehdr;
154
155 /* create filemapping */
156 pvBase = pFile->readFile();
157 if (pvBase == NULL)
158 throw(1);
159
160 pehdr = (struct exe_hdr*)pvBase;
161 if (pehdr->e_magic == EMAGIC)
162 offLXHdr = pehdr->e_lfanew;
163 else
164 offLXHdr = 0;
165
166 pe32 = (struct e32_exe*)((char*)pvBase + offLXHdr);
167 if (*(PUSHORT)pe32 != E32MAGIC)
168 {
169 free(pvBase);
170 pvBase = NULL;
171 throw(2);
172 }
173
174 paObject = pe32->e32_objtab && pe32->e32_objcnt
175 ? (struct o32_obj*)((char*)pvBase + pe32->e32_objtab + offLXHdr) : NULL;
176 paMap = pe32->e32_objmap
177 ? (struct o32_map*)((char*)pvBase + pe32->e32_objmap + offLXHdr) : NULL;
178}
179
180
181
182/**
183 * Destructor.
184 */
185kFileLX::~kFileLX()
186{
187 if (pvBase != NULL)
188 free(pvBase);
189 pvBase = NULL;
190}
191
192
193
194BOOL kFileLX::queryModuleName(char *pszBuffer)
195{
196 /* The module name is the 0 ordinal entry in resident name table */
197 return queryExportName(0, pszBuffer);
198}
199
200
201
202BOOL kFileLX::findFirstExport(PEXPORTENTRY pExport)
203{
204 struct b32_bundle * pBundle = (struct b32_bundle*)((char*)pvBase + pe32->e32_enttab + offLXHdr);
205 struct e32_entry * pEntry;
206 int iOrdinal = 1;
207
208 if (pe32->e32_enttab)
209 {
210 while (pBundle->b32_cnt != 0)
211 {
212 /* skip empty bundles */
213 while (pBundle->b32_cnt != 0 && pBundle->b32_type == EMPTY)
214 {
215 iOrdinal += pBundle->b32_cnt;
216 pBundle = (struct b32_bundle*)((char*)pBundle + 2);
217 }
218
219 /* FIXME forwarders are not implemented so we'll skip them too. */
220 while (pBundle->b32_cnt != 0 && (pBundle->b32_type & ~TYPEINFO) == ENTRYFWD)
221 {
222 iOrdinal += pBundle->b32_cnt;
223 pBundle = (struct b32_bundle*)((char*)(pBundle + 1) + pBundle->b32_cnt * 7);
224 }
225
226 /* we'll ignore any flags for the moment - TODO */
227 if (pBundle->b32_cnt != 0)
228 {
229 pExport->ulOrdinal = iOrdinal;
230 pExport->iObject = pBundle->b32_obj;
231
232 /* look for name */
233 pExport->achIntName[0] = '\0';
234 if (!queryExportName(iOrdinal, pExport->achName))
235 pExport->achName[0] = '\0';
236
237 pEntry = (struct e32_entry*)(pBundle+1);
238 switch (pBundle->b32_type & ~TYPEINFO)
239 {
240 case ENTRY16:
241 pExport->offset = pEntry->e32_variant.e32_offset.offset16;
242 break;
243
244 case ENTRY32:
245 pExport->offset = pEntry->e32_variant.e32_offset.offset32;
246 break;
247
248 case GATE16:
249 pExport->offset = pEntry->e32_variant.e32_callgate.offset;
250 break;
251 default:
252 assert(!"ARG!!!! invalid bundle type!");
253 }
254
255 /* store status - current export entry */
256 PEXPSTATE pExpState = (PEXPSTATE)malloc(sizeof(EXPSTATE));
257 pExport->pv = pExpState;
258 pExpState->pb32 = pBundle;
259 pExpState->iOrdinalBundle = iOrdinal;
260 pExpState->pe32 = pEntry;
261 pExpState->iOrdinal = iOrdinal;
262 return TRUE;
263 }
264 }
265
266 }
267
268 return FALSE;
269}
270
271
272
273BOOL kFileLX::findNextExport(PEXPORTENTRY pExport)
274{
275 static int acbEntry[] =
276 {
277 0, /* EMPTY */
278 3, /* ENTRY16 */
279 5, /* GATE16 */
280 5, /* ENTRY32 */
281 7 /* ENTRYFWD */
282 };
283
284 PEXPSTATE pExpState = (PEXPSTATE)pExport->pv;
285
286 /*
287 * Get more ordinals from the current bundle if any left.
288 */
289 if (pExpState->pb32->b32_cnt > (pExpState->iOrdinal - pExpState->iOrdinalBundle + 1))
290 {
291 /* skip to the next entry */
292 pExpState->iOrdinal++;
293 pExpState->pe32 = (struct e32_entry*)((char*)pExpState->pe32
294 + acbEntry[pExpState->pb32->b32_type & ~TYPEINFO]);
295
296 /* fill output struct */
297 pExport->ulOrdinal = pExpState->iOrdinal;
298 pExport->iObject = pExpState->pb32->b32_obj;
299
300 /* look for name */
301 pExport->achIntName[0] = '\0';
302 if (!queryExportName(pExpState->iOrdinal, pExport->achName))
303 pExport->achName[0] = '\0';
304
305 /* offset */
306 switch (pExpState->pb32->b32_type & ~TYPEINFO)
307 {
308 case ENTRY16:
309 pExport->offset = pExpState->pe32->e32_variant.e32_offset.offset16;
310 break;
311
312 case ENTRY32:
313 pExport->offset = pExpState->pe32->e32_variant.e32_offset.offset32;
314 break;
315
316 case GATE16:
317 pExport->offset = pExpState->pe32->e32_variant.e32_callgate.offset;
318 break;
319 }
320
321 return TRUE;
322 }
323
324 /*
325 * next bundle.
326 */
327 pExpState->pb32 = (struct b32_bundle*)((char*)(pExpState->pb32 + 1) +
328 pExpState->pb32->b32_cnt * acbEntry[pExpState->pb32->b32_type & ~TYPEINFO]);
329 while (pExpState->pb32->b32_cnt != 0)
330 {
331 /* skip empty bundles */
332 while (pExpState->pb32->b32_cnt != 0 && pExpState->pb32->b32_type == EMPTY)
333 {
334 pExpState->iOrdinal += pExpState->pb32->b32_cnt;
335 pExpState->pb32 = (struct b32_bundle*)((char*)pExpState->pb32 + 2);
336 }
337
338 /* FIXME forwarders are not implemented so we'll skip them too. */
339 while (pExpState->pb32->b32_cnt != 0 && (pExpState->pb32->b32_type & ~TYPEINFO) == ENTRYFWD)
340 {
341 pExpState->iOrdinal += pExpState->pb32->b32_cnt;
342 pExpState->pb32 = (struct b32_bundle*)((char*)(pExpState->pb32 + 1) + pExpState->pb32->b32_cnt * 7);
343 }
344
345 /* we'll ignore any flags for the moment - TODO */
346 if (pExpState->pb32->b32_cnt != 0)
347 {
348 pExpState->iOrdinalBundle = pExpState->iOrdinal;
349
350 pExport->ulOrdinal = pExpState->iOrdinal;
351 pExport->iObject = pExpState->pb32->b32_obj;
352
353 /* look for name */
354 pExport->achIntName[0] = '\0';
355 if (!queryExportName(pExpState->iOrdinal, pExport->achName))
356 pExport->achName[0] = '\0';
357
358 pExpState->pe32 = (struct e32_entry*)(pExpState->pb32+1);
359 switch (pExpState->pb32->b32_type & ~TYPEINFO)
360 {
361 case ENTRY16:
362 pExport->offset = pExpState->pe32->e32_variant.e32_offset.offset16;
363 break;
364
365 case ENTRY32:
366 pExport->offset = pExpState->pe32->e32_variant.e32_offset.offset32;
367 break;
368
369 case GATE16:
370 pExport->offset = pExpState->pe32->e32_variant.e32_callgate.offset;
371 break;
372 default:
373 assert(!"ARG!!!! invalid bundle type!");
374 }
375
376 return TRUE;
377 }
378 }
379
380
381 /*
382 * No more exports - clean up
383 */
384 free(pExport->pv);
385 pExport->pv = NULL;
386 return FALSE;
387}
388
389
390/**
391 * Gets a specific LX object.
392 * @returns Pointer to object. NULL on error / invalid index.
393 * @param iObject object number (0-based)
394 */
395struct o32_obj * kFileLX::getObject(int iObject)
396{
397
398 if (iObject < pe32->e32_objcnt)
399 return &paObject[iObject];
400 return NULL;
401}
402
403
404/**
405 * Gets the count of LX objects.
406 * @returns Count of LX objects.
407 */
408int kFileLX::getObjectCount()
409{
410 return (int)pe32->e32_objcnt;
411}
412
413#if 0
414
415/** @cat Get and put page methods. (the first ones are generic) */
416BOOL kFileLX::getPage(char *pachPage, ULONG ulAddress)
417{
418 int iObj;
419
420 for (iObj = 0; iObj < pe32->e32_objcnt; iObj++)
421 if ( paObject[iObj].o32_base > ulAddress
422 && paObject[iObj].o32_base + paObject[iObj].o32_size > ulAddress
423 )
424 return getPage(pachPage, iObj, ulAddress - paObject[iObj].o32_base);
425
426 return FALSE;
427}
428
429BOOL kFileLX::getPage(char *pachPage, int iObject, int offObject)
430{
431 offObject &= ~(PAGESIZE - 1);
432 if ( iObject >= pe32->e32_objcnt
433 && offObject >= paObject[iObject].o32_size
434 )
435 return FALSE;
436
437 /*
438 * Is there a pagemap entry for the requested page?
439 */
440 if ((offObject >> PAGESHIFT) < paObject[iObject].o32_mapsize)
441 { /* yes */
442 int iPage = (offObject >> PAGESIZE) + paObject[iObject].o32_pagemap - 1;
443 char * pchPageData = (char*)((paMap[iPage].o32_pagedataoffset << pe32->e32_pageshift) + pe32->e32_datapage + (char*)pvBase);
444
445 if (pchPageData )
446 {
447 }
448
449 }
450 else
451 { /* no, so it's a zero page */
452 memset(pachPage, 0, PAGESIZE);
453 }
454
455 return FALSE;
456}
457
458BOOL kFileLX::putPage(const char *pachPage, ULONG ulAddress)
459{
460 return FALSE;
461}
462
463BOOL kFileLX::putPage(const char *pachPage, int iObject, int offObject)
464{
465 return FALSE;
466}
467
468BOOL kFileLX::getPageLX(char *pachPage, int iObject, int iPage)
469{
470 return FALSE;
471}
472
473BOOL kFileLX::getPageLX(char *pachPage, int iPage)
474{
475 return FALSE;
476}
477
478BOOL kFileLX::putPageLX(const char *pachPage, int iObject, int iPage)
479{
480 return FALSE;
481}
482
483BOOL kFileLX::putPageLX(const char *pachPage, int iPage)
484{
485 return FALSE;
486}
487
488
489/**
490 * Expands a page compressed with the old exepack method introduced with OS/2 2.0.
491 * (/EXEPACK or just /EXEPACK)
492 * @returns Successindicator.
493 * @param pachPage Pointer to output page. size: PAGESIZE
494 * Upon successful return this will contain the expanded page data.
495 * @param pachSrcPage Pointer to source data. size: cchSrcPage.
496 * This data should be compressed with EXEPACK:2!
497 * @sketch Have no good idea right now.
498 * @status Completely implemented.
499 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
500 * @remark
501 */
502BOOL kFileLX::expandPage1(char *pachPage, const char * pachSrcPage, int cchSrcPage)
503{
504 struct LX_Iter *pIter = (struct LX_Iter *)pachSrcPage;
505 char * pachDestPage = pachPage; /* Store the pointer for boundrary checking. */
506
507 /* Validate size of data. */
508 if (cchSrcPage >= PAGESIZE - 2)
509 return FALSE;
510
511 /*
512 * Expand the page.
513 */
514 while (pIter->LX_nIter)
515 {
516 /* Check if we're out of bound. */
517 if ( pachPage - pachDesPage + pIter->LX_nIter * pIter->LX_nBytes > PAGESIZE
518 || cchSrcPage <= 0)
519 return FALSE;
520
521 if (pIter->LX_nBytes == 1)
522 { /* one databyte */
523 memset(pachPage, &pIter->LX_Iterdata, pIter->LX_nIter);
524 pchPage += pIter->LX_nIter;
525 cchSrcPage -= pIter->LX_nIter + 4;
526 pIter++;
527 }
528 else
529 {
530 for (int i = 0; i < pIter->LX_nIter; i++, pachPage += pIter->LX_nBytes)
531 memcpy(pachPage, &pIter->LX_Iterdata, pIter->LX_nBytes);
532 cchSrcPage -= 4 + pIter->LX_nBytes;
533 pIter = (pIter)((char*)pIter 4 + pIter->LX_nBytes);
534 }
535 }
536 return TRUE;
537#if 0
538/* example code */
539 int off;
540 struct LX_Iter *pIter;
541 char * pch = pvPage; /* Current position on page */
542
543 off = pe32->e32_datapage + (pObjMap->o32_pagedataoffset << pe32->e32_pageshift);
544 if (pObjMap->o32_pagesize && (off + pObjMap->o32_pagesize - 1) >= cbFile)
545 {
546 fprintf(stderr, "Error: Page resides outside of the file.\n");
547 return 1;
548 }
549 pIter = (struct LX_Iter *)((char*)pvFile + off);
550
551 /* expand page */
552 while (pIter->LX_nIter > 0)
553 {
554 if (pch + (pIter->LX_nBytes * pIter->LX_nIter) > (char*)pvPage + OBJPAGELEN)
555 {
556 fprintf(stderr, "Error: Iterated page expands to more than a page!\n");
557 return 1;
558 }
559
560 if (pIter->LX_nBytes == 1)
561 {
562 memset(pch, pIter->LX_Iterdata, pIter->LX_nIter);
563 pch += pIter->LX_nIter;
564 pIter++;
565 }
566 else
567 {
568 int i;
569 for (i = 0; i < pIter->LX_nIter; i++, pch += pIter->LX_nBytes)
570 memcpy(pch, &pIter->LX_Iterdata, pIter->LX_nBytes);
571 #if 1 /* curious */
572 if (pIter->LX_nBytes > 2) fprintf(stdout, "pIter->LX_nBytes = %\n", pIter->LX_nBytes);
573 #endif
574
575 pIter = (struct LX_Iter*)((char*)pIter + 4 + pIter->LX_nBytes);
576 }
577 }
578
579 return FALSE;
580#endif
581}
582
583
584/**
585 * Expands a page compressed with the exepack method introduced with OS/2 Warp 3.0.
586 * (/EXEPACK:2)
587 * @returns Successindicator.
588 * @param pachPage Pointer to output page. size: PAGESIZE
589 * Upon successful return this will contain the expanded page data.
590 * @param pachSrcPage Pointer to source data. size: cchSrcPage.
591 * This data should be compressed with EXEPACK:2!
592 * @sketch Have no good idea right now.
593 * @status Stub.
594 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
595 * @remark
596 */
597BOOL kFileLX::expandPage2(char *pachPage, const char * pachSrcPage, int cchSrcPage)
598{
599 NOREF(pachPage);
600 NOREF(pachSrcPage);
601 NOREF(cchSrcPage);
602 return FALSE;
603}
604
605
606/**
607 * Compresses a page using the old exepack method introduced with OS/2 2.0.
608 * (/EXEPACK:1 or just /EXEPACK)
609 * @returns Size of the compressed page in the pachPage buffer.
610 * PAGESIZE if failed to compress the page.
611 * -1 on error.
612 * @param pachPage Pointer to output buffer. size: PAGESIZE.
613 * This will hold the compressed page data upon return.
614 * @param pachSrcPage Pointer to page to compress. size: PAGESIZE.
615 * @sketch
616 * @status stub.
617 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
618 * @remark Not implemented.
619 */
620int kFileLX::compressPage1(char *pachPage, const char * pachSrcPage)
621{
622 NOREF(pachPage);
623 NOREF(pachSrcPage);
624 return -1;
625}
626
627
628/**
629 * Compresses a page using the exepack method introduced with OS/2 Warp 3.0.
630 * (/EXEPACK:2)
631 * @returns Size of the compressed page in the pachPage buffer.
632 * PAGESIZE if failed to compress the page.
633 * -1 on error.
634 * @param pachPage Pointer to output buffer. size: PAGESIZE.
635 * This will hold the compressed page data upon return.
636 * @param pachSrcPage Pointer to page to compress. size: PAGESIZE.
637 * @sketch Have no idea!
638 * @status stub.
639 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
640 * @remark Not implemented.
641 */
642int kFileLX::compressPage2(char *pachPage, const char * pachSrcPage)
643{
644 NOREF(pachPage);
645 NOREF(pachSrcPage);
646 return -1;
647}
648
649#endif
Note: See TracBrowser for help on using the repository browser.