source: trunk/tools/dbginfo/kHll.cpp@ 5280

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

Addjusted and commented the signature fix.

File size: 75.1 KB
Line 
1/* $Id: kHll.cpp,v 1.17 2000-09-16 17:30:25 bird Exp $
2 *
3 * kHll - Implementation of the class kHll.
4 * That class is used to create HLL debuginfo.
5 *
6 * Copyright (c) 2000 knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
7 *
8 * Project Odin Software License can be found in LICENSE.TXT
9 *
10 */
11
12
13/*******************************************************************************
14* Defined Constants And Macros *
15*******************************************************************************/
16#define INCL_TYPES
17#define INCL_DOSERRORS
18#define FOR_EXEHDR 1 /* exe386.h flag */
19#define DWORD ULONG /* Used by exe386.h / newexe.h */
20#define WORD USHORT /* Used by exe386.h / newexe.h */
21
22
23/*******************************************************************************
24* Internal Functions *
25*******************************************************************************/
26#include <os2.h>
27#include <newexe.h>
28#include <exe386.h>
29
30#include <malloc.h>
31#define free(a) memset(a, '7', _msize(a)) //overload free for debugging purposes.
32#define malloc(a) memset(malloc(a), '3', a) //overload free for debugging purposes.
33#include <stdio.h>
34#include <string.h>
35#include <stddef.h>
36#include <stdlib.h>
37
38#include <kList.h>
39#include <kFile.h>
40#include <kFileFormatBase.h>
41#include <kFileLX.h>
42
43#include "hll.h"
44#include "sym.h"
45#include "kHll.h"
46
47
48/*******************************************************************************
49* Internal Functions *
50*******************************************************************************/
51signed long fsize(FILE *phFile);
52
53
54
55
56/*******************************************************************************
57* *
58* kHllBaseEntry *
59* *
60* kHllBaseEntry *
61* *
62*******************************************************************************/
63
64
65/**
66 * Writes a list to disk.
67 * @returns Number of bytes written.
68 * @returns Count of bytes written on success. (includes 0)
69 * -3 Invalid offsets.
70 * -2 Seek error.
71 * -1 Write error.
72 * @param phFile Output filehandle.
73 * @param pEntry Pointer to the start of the list which is to be written.
74 */
75int kHllBaseEntry::writeList(FILE *phFile, kHllBaseEntry *pEntry)
76{
77 int cch;
78 int cchWritten = 0;
79
80 /*
81 * Loop thru the list and write all the entries to disk.
82 */
83 while (pEntry != NULL)
84 {
85 cchWritten += cch = pEntry->write(phFile);
86 if (cch < 0)
87 return cch;
88 if (cch == 0)
89 return -1;
90 pEntry = (kHllBaseEntry*)pEntry->getNext();
91 }
92
93 return cchWritten;
94}
95
96
97
98/**
99 * Loops thru the given list and call the dump method for each
100 * node with the passed in parameters.
101 * @param ph Dump file handle.
102 * @param cchIndent Indent.
103 * @param pEntry Indent.
104 */
105void kHllBaseEntry::dumpList(FILE *ph, int cchIndent, kHllBaseEntry *pEntry)
106{
107 /*
108 * Loop thru the list staring at pEntry and call dump for each entry.
109 */
110 while (pEntry != NULL)
111 {
112 pEntry->dump(ph, cchIndent);
113 pEntry = (kHllBaseEntry*)pEntry->getNext();
114 }
115}
116
117
118/**
119 * Loops thru the given list and call the ida method for each
120 * node with the passed in parameters.
121 * !!!NOTE!!! THIS IS ONLY TO BE USED FOR YOUR OWN PROGRAMS!!!
122 * @param pFile Output file.
123 * @param pEntry Indent.
124 */
125void kHllBaseEntry::idaList(kFile *pFile, kHllBaseEntry *pEntry)
126{
127 /*
128 * Loop thru the list staring at pEntry and call ida for each entry.
129 */
130 while (pEntry != NULL)
131 {
132 pEntry->ida(pFile);
133 pEntry = (kHllBaseEntry*)pEntry->getNext();
134 }
135}
136
137
138
139
140/*******************************************************************************
141* *
142* kHllPubSymEntry *
143* *
144* kHllPubSymEntry *
145* *
146*******************************************************************************/
147
148
149
150
151
152/**
153 * Creates an HLL public symbol entry.
154 * @param pachName Symbol name.
155 * @param cchName Length of symbol name.
156 * @param off Offset into the object.
157 * @param iObject LX Object index. (1 based)
158 * @param iType Type index. (index into type table)
159 */
160kHllPubSymEntry::kHllPubSymEntry(
161 const char * pachName,
162 int cchName,
163 unsigned long off,
164 unsigned short iObject,
165 unsigned short iType
166 )
167{
168 pPubSym = (PHLLPUBLICSYM)malloc(cchName + sizeof(HLLPUBLICSYM));
169 assert(pPubSym != NULL);
170
171 pPubSym->cchName = (unsigned char)cchName;
172 pPubSym->achName[0] = '\0';
173 strncat((char*)&pPubSym->achName[0], pachName, cchName);
174 pPubSym->off = off;
175 pPubSym->iObject = iObject;
176 pPubSym->iType = iType;
177}
178
179
180
181/**
182 * Destructor.
183 */
184kHllPubSymEntry::~kHllPubSymEntry()
185{
186 if (pPubSym != NULL)
187 free(pPubSym);
188 pPubSym = NULL;
189}
190
191
192
193/**
194 * Write this entry to file.
195 * @returns Count of bytes written (on success).
196 * -3 Invalid offsets.
197 * -2 Seek error.
198 * -1 Write error.
199 * 0 No data written. Concidered as an error!
200 * @param phFile Filehandle.
201 */
202int kHllPubSymEntry::write(FILE *phFile)
203{
204 assert(pPubSym != NULL);
205 return fwrite(pPubSym,
206 1,
207 offsetof(HLLPUBLICSYM, achName) + pPubSym->cchName,
208 phFile);
209}
210
211
212/**
213 * Dumps the HLL entry to ph in a human readable fashion.
214 * @param ph Output file handle the dump is to be written to.
215 * @param cchIndent Number of char to indents the output dump.
216 */
217void kHllPubSymEntry::dump(FILE *ph, int cchIndent)
218{
219 /*
220 * Dump public symbol entry
221 */
222 fprintf(ph, "%*.s0x%04x:0x%08x type:%5d(0x%04x) name: %.*s\n",
223 cchIndent, "",
224 pPubSym->iObject,
225 pPubSym->off,
226 pPubSym->iType,
227 pPubSym->iType,
228 pPubSym->cchName, &pPubSym->achName[0]
229 );
230}
231
232
233/**
234 * Create IDC (IDA Pro) calls which adds info contained in the entry
235 * to the ida pro database.
236 * !!!NOTE!!! THIS IS ONLY TO BE USED FOR YOUR OWN PROGRAMS!!!
237 * @param pFile Output file.
238 */
239void kHllPubSymEntry::ida(kFile *pFile) throw(int)
240{
241 #if 0
242 pFile->printf(" /* PubSym %.*s */\n",
243 pPubSym->cchName, &pPubSym->achName[0]);
244 #endif
245 pFile->printf(" ea = SegByBase(%d) + 0x%08x; MakeName(ea, \"\"); MakeName(ea, \"%.*s\");\n",
246 pPubSym->iObject,
247 pPubSym->off,
248 pPubSym->cchName, &pPubSym->achName[0]
249 );
250}
251
252
253BOOL kHllPubSymEntry::operator==(const kHllPubSymEntry &entry) const
254{
255 return pPubSym->iObject == entry.pPubSym->iObject
256 && pPubSym->off == entry.pPubSym->off;
257}
258
259BOOL kHllPubSymEntry::operator!=(const kHllPubSymEntry &entry) const
260{
261 return pPubSym->iObject != entry.pPubSym->iObject
262 || pPubSym->off != entry.pPubSym->off;
263}
264
265BOOL kHllPubSymEntry::operator< (const kHllPubSymEntry &entry) const
266{
267 return pPubSym->iObject < entry.pPubSym->iObject
268 || (pPubSym->iObject == entry.pPubSym->iObject && pPubSym->off < entry.pPubSym->off);
269}
270
271BOOL kHllPubSymEntry::operator<=(const kHllPubSymEntry &entry) const
272{
273 return pPubSym->iObject < entry.pPubSym->iObject
274 || (pPubSym->iObject == entry.pPubSym->iObject && pPubSym->off <= entry.pPubSym->off);
275}
276
277BOOL kHllPubSymEntry::operator> (const kHllPubSymEntry &entry) const
278{
279 return pPubSym->iObject > entry.pPubSym->iObject
280 || (pPubSym->iObject == entry.pPubSym->iObject && pPubSym->off > entry.pPubSym->off);
281}
282
283BOOL kHllPubSymEntry::operator>=(const kHllPubSymEntry &entry) const
284{
285 return pPubSym->iObject > entry.pPubSym->iObject
286 || (pPubSym->iObject == entry.pPubSym->iObject && pPubSym->off >= entry.pPubSym->off);
287}
288
289
290
291
292
293
294
295
296
297/*******************************************************************************
298* *
299* kHllLineNumberChunk *
300* *
301* kHllLineNumberChunk *
302* *
303*******************************************************************************/
304
305
306
307
308 int cLines;
309 PHLLLINENUMBERENTRY paLines;
310 HLLFIRSTENTRY FirstEntry;
311
312/**
313 * Constructor.
314 * @param iSeg Segment number for these linenumbers. (1 based)
315 * @param offBase Base offset for all line number offsets. (defaults to 0)
316 */
317kHllLineNumberChunk::kHllLineNumberChunk(
318 unsigned short int iSeg,
319 unsigned long int offBase /*= 0*/
320 )
321{
322 memset(&FirstEntry, 0, sizeof(FirstEntry));
323 FirstEntry.hll04.iSeg = iSeg;
324 FirstEntry.hll04.u1.offBase = offBase;
325 FirstEntry.hll04.uchType = 0;
326}
327
328
329
330/**
331 * Destructor.
332 */
333kHllLineNumberChunk::~kHllLineNumberChunk()
334{
335 if (paLines != NULL)
336 free(paLines);
337 paLines = 0;
338 FirstEntry.hll04.cEntries = 0;
339}
340
341
342
343/**
344 * Adds a line information.
345 * @returns Success indicator.
346 * @param iusFile File index.
347 * @param usLine Line number
348 * @param off Offset into object.
349 */
350BOOL kHllLineNumberChunk::addLineInfo(
351 unsigned short int iusFile,
352 unsigned short int usLine,
353 unsigned long int off
354 )
355{
356 /*
357 * Allocate more memory?
358 */
359 if (FirstEntry.hll04.cEntries % 20 == 0)
360 {
361 void *pv = realloc(paLines, (FirstEntry.hll04.cEntries + 20) * sizeof(paLines[0].hll04));
362 assert(pv != NULL);
363 if (pv == NULL)
364 return FALSE;
365 paLines = (PHLLLINENUMBERENTRY)pv;
366 }
367
368 /*
369 * Add line info entry.
370 */
371 paLines[FirstEntry.hll04.cEntries].hll04.iusSourceFile = iusFile;
372 paLines[FirstEntry.hll04.cEntries].hll04.off = off;
373 paLines[FirstEntry.hll04.cEntries].hll04.usLine = usLine;
374 FirstEntry.hll04.cEntries++;
375
376 return FALSE;
377}
378
379
380/**
381 * Write this entry to file.
382 * @returns Count of bytes written (on success).
383 * -3 Invalid offsets.
384 * -2 Seek error.
385 * -1 Write error.
386 * 0 No data written. Concidered as an error!
387 * @param phFile Filehandle.
388 */
389int kHllLineNumberChunk::write(FILE *phFile)
390{
391 int cb;
392 int cbWritten;
393
394 /*
395 * First entry
396 */
397 cb = sizeof(paLines[0])*FirstEntry.hll04.cEntries;
398 cbWritten = fwrite(&FirstEntry, 1, cb, phFile);
399 if (cbWritten != cb)
400 return -1;
401
402 /*
403 * Line array.
404 */
405 cb = sizeof(paLines[0])*FirstEntry.hll04.cEntries;
406 cbWritten = fwrite(paLines, 1, cb, phFile);
407 if (cbWritten != cb)
408 return -1;
409
410 return cbWritten + sizeof(FirstEntry.hll04);
411}
412
413
414
415/**
416 * Dumps the HLL entry to ph in a human readable fashion.
417 * @param ph Output file handle the dump is to be written to.
418 * @param cchIndent Number of char to indents the output dump.
419 */
420void kHllLineNumberChunk::dump(FILE *ph, int cchIndent)
421{
422 int i;
423
424 /*
425 * Write header.
426 * Dump first entry.
427 * Dump linenumbers.
428 * Write footer.
429 */
430 fprintf(ph, "%*.s------- start kHllLineNumberChunk object 0x%08x -------\n",
431 cchIndent, "", this);
432
433 /* ASSUMES - TODO - FIXME: HLL version 3 or 4. */
434 fprintf(ph, "%*.sBaseLine: %04d Type: 0x%02x Entries: 0x%04(%d) iSeg: 0x04x(%d) ",
435 cchIndent, "",
436 FirstEntry.hll04.usLine,
437 FirstEntry.hll04.uchType,
438 FirstEntry.hll04.cEntries,
439 FirstEntry.hll04.cEntries,
440 FirstEntry.hll04.iSeg,
441 FirstEntry.hll04.iSeg
442 );
443 if (FirstEntry.hll04.uchType == 0)
444 fprintf(ph, "offBase: 0x%08x\n", FirstEntry.hll04.u1.offBase);
445 else
446 fprintf(ph, "u1: 0x%08x\n", FirstEntry.hll04.u1.offBase);
447
448
449 /* ASSUMES - TODO - FIXME: HLL version 3 or 4. */
450 for (i = 0; i < FirstEntry.hll04.cEntries; i++)
451 fprintf(ph, "%*.sFile: %04d Line: %04d Offset: 0x%08x\n",
452 cchIndent, "",
453 paLines[i].hll04.iusSourceFile,
454 paLines[i].hll04.usLine,
455 paLines[i].hll04.off
456 );
457
458
459 fprintf(ph, "%*.s------- end kHllLineNumberChunk object 0x%08x -------\n",
460 cchIndent, "", this);
461}
462
463
464/**
465 * Create IDC (IDA Pro) calls which adds info contained in the entry
466 * to the ida pro database.
467 * !!!NOTE!!! THIS IS ONLY TO BE USED FOR YOUR OWN PROGRAMS!!!
468 * @param pFile Output file.
469 */
470void kHllLineNumberChunk::ida(kFile *pFile) throw(int)
471{
472 pFile->printf(" /* Line number chunk */\n");
473}
474
475
476
477
478
479
480
481
482
483/*******************************************************************************
484* *
485* kHllSrcEntry *
486* *
487* kHllSrcEntry *
488* *
489*******************************************************************************/
490
491
492
493
494
495/**
496 * Constructor.
497 */
498kHllSrcEntry::kHllSrcEntry()
499 :
500 cFilenames(0),
501 pachFilenames(NULL),
502 cbFilenames(0),
503 cbFilenamesAllocated(0)
504{
505}
506
507
508/**
509 * Destructor.
510 */
511kHllSrcEntry::~kHllSrcEntry()
512{
513 if (pachFilenames != NULL)
514 free(pachFilenames);
515 pachFilenames = NULL;
516 cFilenames = cbFilenames = cbFilenamesAllocated = 0;
517}
518
519
520
521/**
522 * Add/queries a Linenumber chunk.
523 * A linenumber chunk is a collection of linenumber information for a
524 * module segement.
525 * @returns Pointer to linenumber chunk which you may add linenumber info to.
526 * NULL on failiure.
527 * @param iSeg Segment number for these linenumbers. (1 based)
528 * @param offBase Base offset for all line number offsets. (defaults to 0)
529 */
530kHllLineNumberChunk *
531 kHllSrcEntry::addLineNumberChunk(
532 unsigned short int iSeg,
533 unsigned long int offBase/* = 0*/
534 )
535{
536 kHllLineNumberChunk *pChunk;
537
538 /*
539 * Try find existing chunk.
540 */
541 pChunk = Lines.getFirst();
542 while (pChunk != NULL && pChunk->getSeg() != iSeg)
543 pChunk = (kHllLineNumberChunk*)pChunk->getNext();
544
545 /*
546 * If not found, then create a new one and add it to the list.
547 */
548 if (pChunk != NULL)
549 {
550 pChunk = new kHllLineNumberChunk(iSeg, offBase);
551 assert(pChunk != NULL);
552 if (pChunk != NULL)
553 Lines.insert(pChunk);
554 }
555
556 return pChunk;
557}
558
559
560
561/**
562 * Adds a file for this module.
563 * @returns Filename index used when adding linenumbers.
564 * @param pszFilename Pointer to filaname string.
565 */
566unsigned short kHllSrcEntry::addFile(
567 const char * pszFilename
568 )
569{
570 return addFile(pszFilename, strlen(pszFilename));
571}
572
573
574
575/**
576 * Adds a file for this module.
577 * @returns Filename index used when adding linenumbers.
578 * 0 on error.
579 * @param pachFilename Pointer to filaname string (not zero terminated).
580 * @param cchFilename Length of filename.
581 */
582unsigned short kHllSrcEntry::addFile(
583 const char * pachFilename,
584 int cchFilename
585 )
586{
587 assert(pachFilename != NULL);
588 assert(cchFilename < 256);
589 if (cchFilename >= 256)
590 cchFilename = 255;
591
592 /*
593 * Allocate more memory?
594 */
595 if ((cbFilenames + cchFilename + 1) >= cbFilenamesAllocated)
596 {
597 void *pv = realloc(pachFilenames, (size_t)cbFilenamesAllocated + 256);
598 assert(pv != NULL);
599 if (pv == NULL)
600 return 0;
601 pachFilenames = (char*)pv;
602 cbFilenamesAllocated += 256;
603 }
604
605
606 /*
607 * Add filename
608 */
609 pachFilenames[cbFilenames++] = (char)cchFilename;
610 memcpy(&pachFilenames[cbFilenames], pachFilename, cchFilename);
611 cbFilenames += cchFilename;
612
613 return (unsigned short)++cFilenames;
614}
615
616
617
618/**
619 * Write this entry to file.
620 * @returns Count of bytes written (on success).
621 * -3 Invalid offsets.
622 * -2 Seek error.
623 * -1 Write error.
624 * 0 No data written. Concidered as an error!
625 * @param phFile Filehandle.
626 */
627int kHllSrcEntry::write(FILE *phFile)
628{
629 HLLFIRSTENTRY FirstEntry;
630 HLLFILENAMEENTRY FilenameEntry;
631 int cb;
632 int cbWrote;
633 int cbWritten;
634
635 /*
636 * Filenames - if no filename present we'll add a dummy filename!
637 * First entry for the filenames.
638 * Filename entry header.
639 * Write filename entries.
640 */
641 FirstEntry.hll04.usLine = 0;
642 FirstEntry.hll04.uchType = 3; /* filename */
643 FirstEntry.hll04.uchReserved = 0;
644 FirstEntry.hll04.cEntries = (unsigned short)max(cFilenames, 1);
645 FirstEntry.hll04.iSeg = 0;
646 FirstEntry.hll04.u1.cbFileNameTable = cbFilenames != 0 ? cbFilenames : 8;
647 cb = sizeof(FirstEntry.hll04);
648 cbWritten = cbWrote = fwrite(&FirstEntry, 1, cb, phFile);
649 if (cb != cbWrote)
650 return -1;
651
652 FilenameEntry.cSourceFiles = max(cFilenames, 1);
653 FilenameEntry.offSource = 0;
654 FilenameEntry.cSourceRecords = 0;
655 cb = offsetof(HLLFILENAMEENTRY, cchName);
656 cbWritten += cbWrote = fwrite(&FilenameEntry, 1, cb, phFile);
657 if (cbWrote != cb)
658 return -1;
659
660 if (cbFilenames != 0)
661 {
662 cbWritten += cbWrote = fwrite(pachFilenames, 1, cbFilenames, phFile);
663 if (cbWrote != cbFilenames)
664 return -1;
665 }
666 else
667 { /* no filename - write dummy empty */
668 cbWritten += cbWrote = fwrite("\07dummy.c", 1, 8, phFile);
669 if (cbWrote != 8)
670 return -1;
671 }
672
673
674 /*
675 * Write linenumbers.
676 */
677 if (Lines.getFirst() != NULL)
678 {
679 cbWritten += cbWrote = kHllBaseEntry::writeList(phFile, Lines.getFirst());
680 if (cbWrote < 0)
681 return cbWrote;
682 }
683
684 return cbWritten;
685}
686
687
688
689/**
690 * Dumps the HLL entry to ph in a human readable fashion.
691 * @param ph Output file handle the dump is to be written to.
692 * @param cchIndent Number of char to indents the output dump.
693 */
694void kHllSrcEntry::dump(FILE *ph, int cchIndent)
695{
696 int i;
697 char * pach;
698
699 /*
700 * Write header with filename count.
701 * Write filenames.
702 * Dump linenumber list.
703 * Write footer with filename count.
704 */
705 fprintf(ph, "%*.s------- start kHllSrcEntry object 0x%08x --- %d -------\n",
706 cchIndent, "", this, cFilenames);
707
708 for (i = 0, pach = pachFilenames; i < cFilenames; i++, pach += 1 + *pach)
709 fprintf(ph, "%*.s%.2d - %.*s\n",
710 cchIndent, "",
711 i, *pach, pach + 1);
712
713 kHllBaseEntry::dumpList(ph, cchIndent + 4, Lines.getFirst());
714
715 fprintf(ph, "%*.s------- end kHllSrcEntry object 0x%08x --- %d -------\n",
716 cchIndent, "", this, cFilenames);
717}
718
719
720/**
721 * Create IDC (IDA Pro) calls which adds info contained in the entry
722 * to the ida pro database.
723 * !!!NOTE!!! THIS IS ONLY TO BE USED FOR YOUR OWN PROGRAMS!!!
724 * @param pFile Output file.
725 */
726void kHllSrcEntry::ida(kFile *pFile) throw(int)
727{
728 pFile->printf(" /* Source entry */\n");
729}
730
731
732
733
734
735/*******************************************************************************
736* *
737* kHllModuleEntry *
738* *
739* kHllModuleEntry *
740* *
741*******************************************************************************/
742
743
744
745
746
747
748
749/**
750 * Creates an HLL module entry.
751 * @param pszName Module name. (NULL is not allowed!)
752 * @param iLib Library index.
753 * @param cSegInfo Number of objects in the array.
754 * @param paSegInfo Pointer to an array of objects.
755 */
756kHllModuleEntry::kHllModuleEntry(
757 const char * pszName,
758 unsigned short iLib,
759 unsigned char cSegInfo/*= 0 */,
760 PHLLSEGINFO paSegInfo/*= NULL */
761 )
762: fValidOffsetsAndSizes(FALSE), iObjectMax(0)
763{
764 int i;
765 int cchName;
766 PHLLSEGINFO pSegInfo;
767
768 /*
769 * Debug parameter validations.
770 */
771 assert(pszName != NULL);
772 assert(cSegInfo == 0 || paSegInfo != NULL);
773
774 /*
775 * Allocate data storage and fill HLL structure.
776 */
777 cchName = strlen(pszName);
778 cchName = min(cchName, 255);
779 pModule = (PHLLMODULE)malloc(sizeof(HLLMODULE) + cchName +
780 (sizeof(HLLSEGINFO) * max((cSegInfo - 1), 3)));
781 assert(pModule != NULL);
782 memset(pModule, 0, sizeof(*pModule));
783 pModule->cchName = (unsigned char)cchName;
784 memcpy(&pModule->achName[0], pszName, cchName);
785 pModule->chVerMajor = 4;
786 pModule->chVerMinor = 0;
787 pModule->cSegInfo = cSegInfo;
788 pModule->iLib = iLib;
789 pModule->usDebugStyle = HLL_MOD_STYLE;
790 pModule->overlay = 0;
791 pModule->pad = 0;
792
793 /* objects */
794 if (cSegInfo != 0)
795 {
796 assert(paSegInfo->iObject != 0);
797 pModule->SegInfo0.iObject = paSegInfo->iObject;
798 pModule->SegInfo0.cb = paSegInfo->cb;
799 pModule->SegInfo0.off = paSegInfo->off;
800 iObjectMax = pModule->SegInfo0.iObject;
801
802 for (i = 1, pSegInfo = (PHLLSEGINFO)&pModule->achName[cchName]; i < cSegInfo; i++, pSegInfo++)
803 {
804 assert(paSegInfo->iObject != 0);
805 pSegInfo->iObject = paSegInfo[i].iObject;
806 pSegInfo->cb = paSegInfo[i].cb;
807 pSegInfo->off = paSegInfo[i].off;
808 if (pSegInfo->iObject > iObjectMax)
809 iObjectMax = pSegInfo->iObject;
810 }
811 }
812}
813
814
815/**
816 * Destructor - free storage.
817 */
818kHllModuleEntry::~kHllModuleEntry()
819{
820 if (pModule != NULL)
821 free(pModule);
822 pModule = NULL;
823}
824
825
826
827/**
828 * Adds an object to the module.
829 * @returns Success indicator.
830 * @param iObject LX Object index. (1 based)
831 * @param off Offset into the object to the module data.
832 * @param cb Size of module data (in the object).
833 */
834BOOL kHllModuleEntry::addSegInfo(
835 unsigned short int iObject,
836 unsigned long off,
837 unsigned long cb
838 )
839{
840 assert(pModule != NULL);
841 assert(iObject != 0);
842
843 /*
844 * Reallocate? (Note that we'll initially allocated space for 3 objects.)
845 */
846 if (pModule->cSegInfo >= 3)
847 {
848 void *pv = realloc(pModule, sizeof(HLLMODULE) + pModule->cchName
849 + (pModule->cSegInfo + 1) * sizeof(HLLSEGINFO));
850 assert(pv != NULL);
851 if (pv == NULL)
852 return FALSE;
853 pModule = (PHLLMODULE)pv;
854 }
855
856
857 /*
858 * Add module.
859 */
860 if (pModule->cSegInfo == 0)
861 {
862 pModule->SegInfo0.cb = cb;
863 pModule->SegInfo0.off = off;
864 pModule->SegInfo0.iObject = iObject;
865 if (pModule->SegInfo0.iObject > iObjectMax)
866 iObjectMax = pModule->SegInfo0.iObject;
867 }
868 else
869 {
870 PHLLSEGINFO pSegInfo = (PHLLSEGINFO)((pModule->cSegInfo - 1) * sizeof(HLLSEGINFO)
871 + &pModule->achName[pModule->cchName]);
872 pSegInfo->cb = cb;
873 pSegInfo->off = off;
874 pSegInfo->iObject = iObject;
875 if (pSegInfo->iObject > iObjectMax)
876 iObjectMax = pSegInfo->iObject;
877 }
878 pModule->cSegInfo++;
879
880 return TRUE;
881}
882
883
884
885/**
886 * Adds a public symbol.
887 * @returns Handle to the symbol. NULL on error.
888 * @param pszName Symbol name.
889 * @param off Offset into the LX Object of the symbol.
890 * @param iObject LX Object index. (1 based)
891 * @param pvType Type handle. NULL if not type.
892 */
893const void * kHllModuleEntry::addPublicSymbol(
894 const char * pszName,
895 unsigned long int off,
896 unsigned short int iObject,
897 const void * pvType
898 )
899{
900 assert(pszName != NULL);
901 if (iObject > iObjectMax)
902 iObjectMax = iObject;
903 return addPublicSymbol(pszName, strlen(pszName), off, iObject, pvType);
904}
905
906
907
908/**
909 * Adds a public symbol.
910 * @returns Handle to the symbol. NULL on error.
911 * @param pachName Symbol name.
912 * @param cchName Name length.
913 * @param off Offset into the LX Object of the symbol.
914 * @param iObject LX Object index. (1 based)
915 * @param pvType Type handle. NULL if not type.
916 */
917const void * kHllModuleEntry::addPublicSymbol(
918 const char * pachName,
919 int cchName,
920 unsigned long int off,
921 unsigned short int iObject,
922 const void * pvType
923 )
924{
925 kHllPubSymEntry * pEntry;
926
927 /* parameter assertion */
928 assert(pachName != NULL);
929 assert(iObject != 0);
930 if (iObject > iObjectMax)
931 iObjectMax = iObject;
932
933 /*
934 * Create a public symbol entry
935 * Insert into it's list.
936 * Invalidate offsets.
937 */
938 pEntry = new kHllPubSymEntry(
939 pachName,
940 cchName,
941 off,
942 iObject,
943 (unsigned short)(pvType == NULL ? 0 : -1) //FIXME/TODO: Types->getIndex(pvType); check if 0 or -1.
944 );
945
946 PublicSymbols.insert(pEntry);
947
948 fValidOffsetsAndSizes = FALSE;
949
950 return pEntry;
951}
952
953
954
955
956/**
957 * Write this HLL entry to file.
958 * @returns Count of bytes written.
959 * -3 Invalid offsets.
960 * -2 Seek error.
961 * -1 Write error.
962 * @param phFile Filehandle.
963 * @param off Current offset into the HLL data.
964 * This is stored and used when making the directory
965 * entries for this module.
966 */
967int kHllModuleEntry::write(FILE *phFile, unsigned long off)
968{
969 int cch;
970 int cchToWrite;
971 int cchWritten = 0;
972
973 /* validate object state */
974 assert(pModule != NULL);
975
976 /*
977 * Write module HLL data.
978 */
979 offModule = off;
980 cchToWrite = offsetof(HLLMODULE, achName) + pModule->cchName + sizeof(HLLSEGINFO) * max(pModule->cSegInfo-1, 0);
981 cch = fwrite(pModule, 1, cchToWrite, phFile);
982 if (cch != cchToWrite)
983 return -1;
984 cchWritten += cch;
985 cbModule = cch;
986 off += cch;
987
988 /*
989 * Write the lists.
990 * Public Symbols
991 * Types
992 * Symbols
993 * Source
994 */
995 offPublicSymbols = off;
996 cbPublicSymbols = cch = kHllBaseEntry::writeList(phFile, PublicSymbols.getFirst());
997 if (cch < 0)
998 return cch;
999 cchWritten += cch;
1000 off += cch;
1001
1002 /*
1003 offTypes = off;
1004 cbTypes = cch = kHllBaseEntry::writeList(phFile, Types.getFirst());
1005 if (cch < 0)
1006 return cch;
1007 cchWritten += cch;
1008 off += cch;
1009
1010
1011 offSymbols = off;
1012 cbSymbols = cch = kHllBaseEntry::writeList(phFile, Symbols.getFirst());
1013 if (cch < 0)
1014 return cch;
1015 cchWritten += cch;
1016 off += cch;
1017 */
1018
1019 offSource = off;
1020 cbSource = cch = Source.write(phFile);
1021 if (cch < 0)
1022 return cch;
1023 cchWritten += cch;
1024 off += cch;
1025
1026 /*
1027 * Marks offsets and sizes valid and returns succesfully.
1028 */
1029 fValidOffsetsAndSizes = TRUE;
1030 return cchWritten;
1031}
1032
1033
1034
1035/**
1036 * Writes the directory entries for this module to file.
1037 * @returns Count of bytes written on success.
1038 * -3 Invalid offsets.
1039 * -2 Seek error.
1040 * -1 Write error.
1041 * 0 no data written (this is an error condition!)
1042 * @param phFile Filehandle.
1043 * @param iMod Index of this module.
1044 */
1045int kHllModuleEntry::writeDirEntries(FILE *phFile, unsigned short iMod)
1046{
1047 HLLDIRENTRY hllDirEntry;
1048 int cch;
1049 int cchWritten = 0;
1050
1051 /*
1052 * Check that offsets are valid!
1053 */
1054 assert(fValidOffsetsAndSizes);
1055 if (!fValidOffsetsAndSizes)
1056 return -3;
1057
1058 /*
1059 * Write Directory Entries.
1060 * Module.
1061 * Public Symbols. (if any)
1062 * Types. (if any)
1063 * Symbols. (if any)
1064 * Source. (if any)
1065 */
1066 hllDirEntry.usType = HLL_DE_MODULES;
1067 hllDirEntry.cb = cbModule;
1068 hllDirEntry.off = offModule;
1069 hllDirEntry.iMod = iMod;
1070 cch = fwrite(&hllDirEntry, 1, sizeof(hllDirEntry), phFile);
1071 if (cch != sizeof(hllDirEntry))
1072 return -1;
1073 cchWritten += cch;
1074
1075 if (cbPublicSymbols != 0)
1076 {
1077 hllDirEntry.usType = HLL_DE_PUBLICS;
1078 hllDirEntry.cb = cbPublicSymbols;
1079 hllDirEntry.off = offPublicSymbols;
1080 hllDirEntry.iMod = iMod;
1081 cch = fwrite(&hllDirEntry, 1, sizeof(hllDirEntry), phFile);
1082 if (cch != sizeof(hllDirEntry))
1083 return -1;
1084 cchWritten += cch;
1085 }
1086
1087 /*
1088 if (cbTypes > 0)
1089 {
1090 hllDirEntry.usType = HLL_DE_TYPES;
1091 hllDirEntry.cb = cbTypes;
1092 hllDirEntry.off = offTypes;
1093 hllDirEntry.iMod = iMod;
1094 cch = fwrite(&hllDirEntry, 1, sizeof(hllDirEntry), phFile);
1095 if (cch != sizeof(hllDirEntry))
1096 return -1;
1097 cchWritten += cch;
1098 }
1099
1100 if (cbSymbols > 0)
1101 {
1102 hllDirEntry.usType = HLL_DE_SYMBOLS;
1103 hllDirEntry.cb = cbSymbols;
1104 hllDirEntry.off = offSymbols;
1105 hllDirEntry.iMod = iMod;
1106 cch = fwrite(&hllDirEntry, 1, sizeof(hllDirEntry), phFile);
1107 if (cch != sizeof(hllDirEntry))
1108 return -1;
1109 cchWritten += cch;
1110 }
1111 */
1112
1113 if (cbSource != 0)
1114 {
1115 hllDirEntry.usType = HLL_DE_IBMSRC;
1116 hllDirEntry.cb = cbSource;
1117 hllDirEntry.off = offSource;
1118 hllDirEntry.iMod = iMod;
1119 cch = fwrite(&hllDirEntry, 1, sizeof(hllDirEntry), phFile);
1120 if (cch != sizeof(hllDirEntry))
1121 return -1;
1122 cchWritten += cch;
1123 }
1124
1125
1126 return cchWritten;
1127}
1128
1129
1130/**
1131 * Converts and writes SYM seginfo a segment for this module entry.
1132 * @returns Count of bytes written on success.
1133 * -4 Out of memory.
1134 * -3 Invalid offsets.
1135 * -2 Seek error.
1136 * -1 Write error.
1137 * 0 no data written (this is an error condition!)
1138 * @param pFile Pointer to output file object.
1139 * @param iSeg Segment number which we processing. (1 based)
1140 * @param pSegDef Segment definition. This is to be updated (count).
1141 * @param paoffSyms Reference symbol offset table.
1142 * Insert 16 byte aligned symbol offsets.
1143 * This table should be reallocated when full.
1144 * @param coffsymsAllocated Reference to allocated size of the symbol offset table.
1145 * @param offSegDef Offset of the segement definition.
1146 *
1147 */
1148void kHllModuleEntry::writeSymSeg(kFile *pFile, int iSeg, PSEGDEF pSegDef,
1149 unsigned short * &paoffSyms, int &coffSymsAllocated,
1150 unsigned long offSegDef) throw(int)
1151{
1152 kHllPubSymEntry* pPubSym;
1153 char achBuffer[CCHMAXPATH + sizeof(SYMDEF32)];
1154 PSYMDEF32 pSym = (PSYMDEF32)&achBuffer[0];
1155 int cbSym;
1156 long off = pFile->getPos();
1157
1158 assert(iSeg > 0);
1159
1160 /*
1161 * Add module name symbol.
1162 * -see if this module has a segment info entry for the current segment.
1163 */
1164 if (pModule->cSegInfo != 0)
1165 {
1166 PHLLSEGINFO pSegInfo;
1167 if (pModule->SegInfo0.iObject == iSeg)
1168 pSegInfo = &pModule->SegInfo0;
1169 else
1170 {
1171 int i;
1172 for (i = pModule->cSegInfo,
1173 pSegInfo = (PHLLSEGINFO)&pModule->achName[pModule->cchName];
1174 i > 0 && pSegInfo->iObject != iSeg;
1175 i--, pSegInfo++
1176 )
1177 i = i; //
1178 if (i <= 0)
1179 pSegInfo = NULL;
1180 }
1181
1182 /* anything to write? */
1183 if (pSegInfo)
1184 {
1185 pSym->wSymVal = pSegInfo->off;
1186 pSym->cbSymName = pModule->cchName;
1187 memcpy(pSym->achSymName, pModule->achName, pModule->cchName);
1188 pSym->cbSymName += sprintf(pSym->achSymName + pModule->cchName, "_Start_Seg%d", iSeg);
1189 cbSym = sizeof(SYMDEF32) + pSym->cbSymName - 1;
1190 pFile->write(pSym, cbSym);
1191 if (coffSymsAllocated <= pSegDef->cSymbols + 1)
1192 {
1193 void *pv;
1194 pv = realloc(paoffSyms, (coffSymsAllocated + 50) * sizeof(unsigned short));
1195 if (pv == NULL)
1196 throw(ERROR_NOT_ENOUGH_MEMORY);
1197 paoffSyms = (unsigned short *)pv;
1198 coffSymsAllocated += 50;
1199 }
1200 paoffSyms[pSegDef->cSymbols] = (unsigned short)(off - offSegDef);
1201 pSegDef->cSymbols++;
1202 off += cbSym;
1203 }
1204 }
1205
1206
1207 /*
1208 * Add all public symbols.
1209 */
1210 pPubSym = (kHllPubSymEntry*)PublicSymbols.getFirst();
1211 while (pPubSym != NULL)
1212 {
1213 /* if the current segement then make a symbol entry */
1214 if (pPubSym->getObjectIndex() == iSeg)
1215 {
1216 pSym->wSymVal = pPubSym->getOffset();
1217 pSym->cbSymName = pPubSym->getNameLength();
1218 memcpy(pSym->achSymName, pPubSym->getName(), pSym->cbSymName);
1219 cbSym = sizeof(SYMDEF32) + pSym->cbSymName - 1;
1220 pFile->write(pSym, cbSym);
1221 if (coffSymsAllocated <= pSegDef->cSymbols + 1)
1222 {
1223 void *pv;
1224 pv = realloc(paoffSyms, (coffSymsAllocated + 50) * sizeof(unsigned short));
1225 if (pv == NULL)
1226 throw(ERROR_NOT_ENOUGH_MEMORY);
1227 paoffSyms = (unsigned short *)pv;
1228 coffSymsAllocated += 50;
1229 }
1230 paoffSyms[pSegDef->cSymbols] = (unsigned short)(off - offSegDef);
1231 pSegDef->cSymbols++;
1232 off += cbSym;
1233 }
1234
1235 /* next entry */
1236 pPubSym = (kHllPubSymEntry*)pPubSym->getNext();
1237 }
1238}
1239
1240
1241/**
1242 * Gets the highest object index. (ie. object count since it is 1 based.)
1243 * @returns Highest object index.
1244 */
1245int kHllModuleEntry::queryMaxObjectIndex()
1246{
1247 return iObjectMax;
1248}
1249
1250
1251
1252/**
1253 * Dumps this module entry to the given file.
1254 * @param ph Filehandle to dump this module entry to.
1255 */
1256void kHllModuleEntry::dump(FILE *ph)
1257{
1258 PHLLSEGINFO pSegInfo;
1259 int i;
1260
1261 fprintf(ph, " ------- start dumping kHllModuleEntry object 0x%08x -------\n", this);
1262
1263 /*
1264 * Dump HLL module entry.
1265 */
1266 fprintf(ph, " Modulename: %.*s Style: %.2s HLL ver: %d.%d #SegInfos: %d\n",
1267 pModule->cchName, pModule->achName,
1268 &pModule->usDebugStyle,
1269 pModule->chVerMajor, pModule->chVerMinor,
1270 pModule->cSegInfo
1271 );
1272
1273 for (i = 0, pSegInfo = &pModule->SegInfo0; i < pModule->cSegInfo; i++)
1274 {
1275 fprintf(ph, " Obj.no.: 0x%04x Offset: 0x%08x Size: 0x%08x(%d)\n",
1276 pSegInfo->iObject, pSegInfo->off, pSegInfo->cb, pSegInfo->cb);
1277
1278 /* next */
1279 if (i == 0)
1280 pSegInfo = (PHLLSEGINFO)&pModule->achName[pModule->cchName];
1281 else
1282 pSegInfo++;
1283 }
1284
1285
1286 /*
1287 * Dump the sub-entries.
1288 */
1289 kHllBaseEntry::dumpList(ph, 8, PublicSymbols.getFirst());
1290 /*
1291 kHllBaseEntry::dumpList(ph, 8, Types.getFirst());
1292 kHllBaseEntry::dumpList(ph, 8, Symbols.getFirst());
1293 kHllBaseEntry::dumpList(ph, 8, Source.getFirst());
1294 */
1295 Source.dump(ph, 8);
1296
1297
1298 fprintf(ph, " ------- end dumping kHllModuleEntry object 0x%08x -------\n", this);
1299}
1300
1301
1302/**
1303 * Create IDC (IDA Pro) calls which adds info contained in the entry
1304 * to the ida pro database.
1305 * !!!NOTE!!! THIS IS ONLY TO BE USED FOR YOUR OWN PROGRAMS!!!
1306 * @param pFile Output file.
1307 */
1308void kHllModuleEntry::ida(kFile *pFile) throw(int)
1309{
1310 pFile->printf(" /* kHllModuleEntry */\n");
1311
1312 /*
1313 * Write the sub-entries.
1314 */
1315 kHllBaseEntry::idaList(pFile, PublicSymbols.getFirst());
1316 /*
1317 kHllBaseEntry::dumpList(ph, 8, Types.getFirst());
1318 kHllBaseEntry::dumpList(ph, 8, Symbols.getFirst());
1319 kHllBaseEntry::dumpList(ph, 8, Source.getFirst());
1320 */
1321 Source.ida(pFile);
1322}
1323
1324
1325
1326
1327
1328
1329/*******************************************************************************
1330* *
1331* kHll *
1332* *
1333* kHll *
1334* *
1335*******************************************************************************/
1336
1337
1338
1339/**
1340 * Writes HLL debuginfo to the given file at the current position.
1341 * The file should be opened in write mode.
1342 * @returns Number of bytes written.
1343 * @param phFile Filehandle to output file. Starts writing at current pos.
1344 */
1345int kHll::write(FILE *phFile)
1346{
1347 HLLHDR hllHdr;
1348 HLLDIR hllDir;
1349 kHllModuleEntry * pModule;
1350 int cch; /* Number of bytes written to the file in an operation. */
1351 int cchWritten = 0; /* Number of bytes written to the file. */
1352 long int lPosStart; /* Starting position. */
1353 long int lPosDir; /* Directory position. */
1354 long int lPos; /* A file position. */
1355 int iMod; /* Module index (passed in to writeDirEntries) */
1356
1357 /* Get starting position. */
1358 lPosStart = ftell(phFile);
1359
1360 /* Make temporary header and write it */
1361 memcpy(hllHdr.achSignature, "NB04", 4);
1362 hllHdr.offDirectory = 0;
1363 cch = fwrite(&hllHdr, 1, sizeof(hllHdr), phFile);
1364 if (cch != sizeof(hllHdr))
1365 return -1;
1366 cchWritten += cch;
1367
1368
1369 /*
1370 * Start writing modules
1371 */
1372 pModule = (kHllModuleEntry*)Modules.getFirst();
1373 while (pModule != NULL)
1374 {
1375 cch = pModule->write(phFile, cchWritten);
1376 if (cch <= 0)
1377 return cch;
1378 cchWritten += cch;
1379 pModule = (kHllModuleEntry *)pModule->getNext();
1380 }
1381
1382
1383 /*
1384 * Write libraries.
1385 */
1386 //Not implemented yet - TODO/FIXME!
1387
1388
1389 /*
1390 * Write directory.
1391 * Make and write temporary directory header.
1392 * Write directory entries per module.
1393 * Write directory entry for libraries.
1394 * Remake and rewrite directory header. (correct cEntries)
1395 */
1396 lPosDir = ftell(phFile);
1397 hllDir.cEntries = 0;
1398 hllDir.cb = offsetof(HLLDIR, aEntries);
1399 hllDir.cbEntry = sizeof(HLLDIRENTRY);
1400 cch = fwrite(&hllDir, 1, offsetof(HLLDIR, aEntries), phFile);
1401 if (cch != offsetof(HLLDIR, aEntries))
1402 return -1;
1403 cchWritten += cch;
1404
1405 iMod = 1;
1406 pModule = (kHllModuleEntry*)Modules.getFirst();
1407 while (pModule != NULL)
1408 {
1409 cch = pModule->writeDirEntries(phFile, (unsigned short)iMod);
1410 if (cch == -1)
1411 return -1;
1412 cchWritten += cch;
1413 pModule = (kHllModuleEntry *)pModule->getNext();
1414 iMod++;
1415 }
1416
1417 //Library - TODO/FIXME
1418
1419 lPos = ftell(phFile);
1420 hllDir.cEntries = (lPos - lPosDir - offsetof(HLLDIR, aEntries)) / sizeof(HLLDIRENTRY);
1421 if (fseek(phFile, lPosDir, SEEK_SET) != 0)
1422 return -2;
1423 cch = fwrite(&hllDir, 1, offsetof(HLLDIR, aEntries), phFile);
1424 if (cch != offsetof(HLLDIR, aEntries))
1425 return -1;
1426
1427 /*
1428 * Rewrite HLL header (with correct directory offset).
1429 */
1430 hllHdr.offDirectory = lPosDir - lPosStart;
1431 if (fseek(phFile, lPosStart, SEEK_SET) != 0)
1432 return -2;
1433 cch = fwrite(&hllHdr, 1, sizeof(hllHdr), phFile);
1434 if (cch != sizeof(hllHdr))
1435 return -1;
1436
1437 /*
1438 * Hacking:
1439 * Writing an extra HLL header pointing to an non-existing directory
1440 * staring at the last byte of this header. This is present when linking
1441 * with ilink...
1442 */
1443 if (fseek(phFile, lPosStart + cchWritten, SEEK_SET) != 0)
1444 return -2;
1445 hllHdr.offDirectory = cchWritten + sizeof(hllHdr);
1446 cch = fwrite(&hllHdr, 1, sizeof(hllHdr), phFile);
1447 if (cch != sizeof(hllHdr))
1448 return -1;
1449 cchWritten += cch;
1450
1451 return cchWritten;
1452}
1453
1454
1455
1456/**
1457 * Constructor - Creates an empty HLL object.
1458 */
1459kHll::kHll() : pszModName(NULL)
1460{
1461}
1462
1463
1464/**
1465 * Creates a kHll object from debugdata found in a file (LX layout).
1466 * @param pFile Pointer to file object which the data is to be read from.
1467 * The file object is positioned at the start of the debuginfo.
1468 * start of the debuginfo.
1469 * Note. The file object is set to throw on errors.
1470 */
1471kHll::kHll(kFile *pFile) throw (int) : pszModName(NULL)
1472{
1473 long offHllHdr; /* Offset of debug data in file. */
1474 HLLHDR hllHdr; /* HLL data header. */
1475 HLLDIR hllDir; /* HLL directory (header only) */
1476 PHLLDIR pHllDir; /* HLL directory (all) */
1477 PHLLDIRENTRY pDirEntry; /* Current HLL directory entry. */
1478 int iDir;
1479
1480 /* auto throw */
1481 pFile->setThrowOnErrors();
1482
1483 /* Save file offset of debugdata. */
1484 offHllHdr = pFile->getPos();
1485
1486 /* Read HLL header */
1487 pFile->read(&hllHdr, sizeof(hllHdr));
1488 if (memcmp(hllHdr.achSignature, "NB04", 4) != 0)
1489 throw(ERROR_INVALID_EXE_SIGNATURE);
1490
1491 /*
1492 * Read the Directory head to get the directory size.
1493 * Allocate memory for the entire directory and read it.
1494 */
1495 pFile->readAt(&hllDir, sizeof(hllDir), offHllHdr + hllHdr.offDirectory);
1496 pHllDir = (PHLLDIR)malloc((size_t)(hllDir.cbEntry * hllDir.cEntries + hllDir.cb));
1497 if (pHllDir == NULL) throw(ERROR_NOT_ENOUGH_MEMORY);
1498 pFile->readAt(pHllDir, hllDir.cbEntry * hllDir.cEntries + hllDir.cb, offHllHdr + hllHdr.offDirectory);
1499
1500
1501 /*
1502 * Loop thru the directory entries and add them we have implemented.
1503 */
1504 //unsigned long ulHLLVersion = 0; /* HLL version of the last module. */
1505 kHllModuleEntry *pCurMod = NULL; /* Current Module. */
1506 int iCurMod = 0; /* Current Module index (import). */
1507
1508 for (iDir = 0, pDirEntry = (PHLLDIRENTRY)((char*)pHllDir + hllDir.cb);
1509 iDir < pHllDir->cEntries;
1510 iDir++, pDirEntry = (PHLLDIRENTRY)((char*)pDirEntry + hllDir.cbEntry)
1511 )
1512 {
1513 CHAR szName[1024];
1514
1515 switch (pDirEntry->usType)
1516 {
1517 /*
1518 * Source filename(=Module) entry.
1519 */
1520 case HLL_DE_MODULES:
1521 {
1522 HLLMODULE hllMod;
1523 PHLLSEGINFO paSegInfo;
1524
1525 /*
1526 * Read hllmod, filename and seginfo table if any.
1527 */
1528 pFile->readAt(&hllMod, sizeof(hllMod), offHllHdr + pDirEntry->off);
1529 pFile->move(-1);
1530 pFile->read(szName, hllMod.cchName);
1531 szName[hllMod.cchName] = '\0';
1532 if (hllMod.cSegInfo != 0)
1533 {
1534 paSegInfo = (PHLLSEGINFO)malloc(sizeof(HLLSEGINFO) * hllMod.cSegInfo);
1535 if (pHllDir == NULL) throw(ERROR_NOT_ENOUGH_MEMORY);
1536 memcpy(paSegInfo, &hllMod.SegInfo0, sizeof(HLLSEGINFO));
1537 if (hllMod.cSegInfo > 1)
1538 pFile->read(&paSegInfo[1], sizeof(HLLSEGINFO) * (hllMod.cSegInfo - 1));
1539 }
1540 else
1541 paSegInfo = NULL;
1542
1543 /*
1544 * Add the module and save module data for later use.
1545 * Cleanup seginfo.
1546 */
1547 pCurMod = this->addModule(szName, hllMod.cchName, NULL, hllMod.cSegInfo, paSegInfo);
1548 iCurMod = pDirEntry->iMod;
1549 //ulHLLVersion = HLLMAKEVER(hllMod.chVerMajor, hllMod.chVerMinor);
1550
1551 if (paSegInfo != NULL)
1552 free(paSegInfo);
1553 break;
1554 }
1555
1556
1557 /*
1558 * Public symbols
1559 */
1560 case HLL_DE_PUBLICS:
1561 {
1562 HLLPUBLICSYM pubSym;
1563
1564 if (pCurMod == NULL || iCurMod != pDirEntry->iMod)
1565 {
1566 fprintf(stderr, "hmm. iMod in public entry not equal to current module\n");
1567 break;
1568 }
1569
1570 fprintf(stderr, "HLL_DE_PUBLICS\n");
1571 pFile->set(pDirEntry->off + offHllHdr);
1572 while (pFile->getPos() - pDirEntry->off - offHllHdr < pDirEntry->cb)
1573 {
1574 pFile->read(&pubSym, sizeof(pubSym) - 1);
1575 pFile->read(szName, pubSym.cchName);
1576 szName[pubSym.cchName] = '\0';
1577
1578 fprintf(stderr, "HLL_DE_PUBLICS\n");
1579 pCurMod->addPublicSymbol(szName,
1580 pubSym.cchName,
1581 pubSym.off,
1582 pubSym.iObject,
1583 (void*)pubSym.iType);
1584 }
1585 }
1586
1587 case HLL_DE_TYPES: /* Types */
1588 fprintf(stderr, "Types directory entry\n");
1589 break;
1590
1591 case HLL_DE_SYMBOLS: /* Symbols */
1592 fprintf(stderr, "Symbols directory entry\n");
1593 break;
1594
1595 case HLL_DE_LIBRARIES: /* Libraries */
1596 fprintf(stderr, "Libraries directory entry\n");
1597 break;
1598
1599 case HLL_DE_SRCLINES: /* Line numbers - (IBM C/2 1.1) */
1600 fprintf(stderr, "SRCLINES directory entry\n");
1601 break;
1602
1603 case HLL_DE_SRCLNSEG: /* Line numbers - (MSC 6.00) */
1604 fprintf(stderr, "SRCLNSEG directory entry\n");
1605 break;
1606
1607 case HLL_DE_IBMSRC: /* Line numbers - (IBM HLL) */
1608 fprintf(stderr, "IBMSRC directory entry\n");
1609 break;
1610
1611 default:
1612 /* Unsupported directory entry - ignore */
1613 fprintf(stderr, "Unsupported directory entry %d\n", pDirEntry->usType);
1614 break;
1615 }
1616 }
1617
1618 /* cleanup */
1619 free(pHllDir);
1620}
1621
1622
1623/**
1624 * Destructor.
1625 */
1626kHll::~kHll()
1627{
1628 if (pszModName != NULL)
1629 free(pszModName);
1630 pszModName = NULL;
1631}
1632
1633
1634
1635/**
1636 * Adds a module.
1637 * @returns Pointer to the module object added. NULL on error.
1638 * @param pszName Module name
1639 * @param pvLib Library module handle.
1640 * @param cSegInfo Number of objects in the array.
1641 * @param paSegInfo Pointer to an array of objects.
1642 */
1643kHllModuleEntry * kHll::addModule(
1644 const char * pszName,
1645 const void * pvLib,
1646 unsigned cSegInfo,
1647 PHLLSEGINFO paSegInfo)
1648{
1649 kHllModuleEntry * pEntry;
1650 assert(pszName != NULL);
1651
1652 pEntry = new kHllModuleEntry(
1653 pszName,
1654 (unsigned short)(pvLib == NULL ? 0 : -1), //FIXME/TODO: Libs->getIndex(pvLib); check if 0 or -1;
1655 (unsigned char) cSegInfo,
1656 paSegInfo);
1657
1658 Modules.insert(pEntry);
1659 return pEntry;
1660}
1661
1662
1663
1664/**
1665 * Adds a module.
1666 * @returns Pointer to the module object added. NULL on error.
1667 * @param pachName Module name
1668 * @param cchName Length of modulename
1669 * @param pvLib Library module handle.
1670 * @param cSegInfo Number of objects in the array.
1671 * @param paSegInfo Pointer to an array of objects.
1672 */
1673kHllModuleEntry * kHll::addModule(
1674 const char * pachName,
1675 unsigned cchName,
1676 const void * pvLib,
1677 unsigned cSegInfo,
1678 PHLLSEGINFO paSegInfo)
1679{
1680 char szModName[256];
1681 kHllModuleEntry * pEntry;
1682 assert(pachName != NULL && cchName != 0);
1683
1684 szModName[0] = '\0';
1685 strncat(szModName, pachName, min(cchName, 255));
1686 pEntry = new kHllModuleEntry(
1687 szModName,
1688 (unsigned short)(pvLib == NULL ? 0 : -1), //FIXME/TODO: Libs->getIndex(pvLib); check if 0 or -1;
1689 (unsigned char)cSegInfo,
1690 paSegInfo);
1691
1692 Modules.insert(pEntry);
1693 return pEntry;
1694}
1695
1696/**
1697 * Sets the modulename.
1698 * @returns Success indicator.
1699 * @param pszModName Pointer to modulename.
1700 * If a filename is given the path and extention is removed.
1701 */
1702BOOL kHll::setModName(
1703 const char * pszModName
1704 )
1705{
1706 const char *pszEnd = pszModName + strlen(pszModName) - 1;
1707
1708 /* remove path */
1709 while (pszEnd >= pszModName && *pszEnd != '\\' && *pszEnd != '/')
1710 pszEnd--;
1711 pszModName = ++pszEnd;
1712
1713 /* find extention (if any) */
1714 while (*pszEnd != '\0' && *pszEnd != '.')
1715 pszEnd++;
1716 return setModName(pszModName, pszEnd - pszModName);
1717}
1718
1719
1720/**
1721 * Sets the modulename.
1722 * @returns Success indicator.
1723 * @param pszModName Pointer to modulename.
1724 * @param cchModName Length of modulename.
1725 */
1726BOOL kHll::setModName(
1727 const char * pachModName,
1728 int cchModName
1729 )
1730{
1731
1732 /* allocate memory for the module name */
1733 if (pszModName != NULL)
1734 free(this->pszModName);
1735 pszModName = (char*)malloc(cchModName + 1);
1736 if (pszModName == NULL)
1737 return FALSE;
1738
1739 /* copy the module name */
1740 memcpy(pszModName, pachModName, cchModName);
1741 pszModName[cchModName] = '\0';
1742
1743 return TRUE;
1744}
1745
1746
1747/**
1748 * Get the modulename. If not set we'll try make one...
1749 * @returns Const pointer to modulename.
1750 * NULL if no modulename.
1751 * @sketch
1752 */
1753const char * kHll::getModName()
1754{
1755 if (pszModName != NULL)
1756 return pszModName;
1757 return NULL;
1758}
1759
1760
1761/**
1762 * Dump the object in a human readable fashion to stdout.
1763 */
1764void kHll::dump(FILE *ph)
1765{
1766 fprintf(ph,
1767 "------- start dumping kHll object 0x%08x --- %d modules -------\n",
1768 this, Modules.getCount());
1769
1770 kHllModuleEntry * pMod = Modules.getFirst();
1771 while (pMod != NULL)
1772 {
1773 /* Dump it */
1774 pMod->dump(ph);
1775
1776 /* Next module */
1777 pMod = (kHllModuleEntry*)pMod->getNext();
1778 }
1779
1780 fprintf(ph,
1781 "------- end dumping kHll object 0x%08x --- %d modules -------\n",
1782 this, Modules.getCount());
1783}
1784
1785
1786/**
1787 * Create IDC (IDA Pro) scripts which adds debuginfo to the ida pro database.
1788 * !!!NOTE!!! THIS IS ONLY TO BE USED FOR YOUR OWN PROGRAMS!!!
1789 * @param pFile Output file.
1790 */
1791void kHll::ida(kFile *pFile) throw(int)
1792{
1793 pFile->printf("/* !!!NOTE!!! THIS IS ONLY TO BE USED FOR YOUR OWN PROGRAMS!!!*/\n"
1794 "#include <idc.idc>\n"
1795 "static main() {\n"
1796 " auto ea;\n"
1797 );
1798
1799 kHllModuleEntry * pMod = Modules.getFirst();
1800 while (pMod != NULL)
1801 {
1802 /* Dump it */
1803 pMod->ida(pFile);
1804
1805 /* Next module */
1806 pMod = (kHllModuleEntry*)pMod->getNext();
1807 }
1808
1809 pFile->printf("}\n\n");
1810 pFile->setSize();
1811}
1812
1813
1814
1815/**
1816 * Creates a kHll object of the HLL debug information found a LX file.
1817 * (An empty object is returned when no info is found.)
1818 * @return Pointer to kHll object on success.
1819 * NULL on error. Message is printed.
1820 */
1821kHll * kHll::readLX(
1822 const char *pszFilename
1823 )
1824{
1825 try
1826 {
1827 struct exe_hdr ehdr;
1828 struct e32_exe e32;
1829 long offLXHdr;
1830
1831 kFile file(pszFilename);
1832
1833 /*
1834 * Find and read the LX header.
1835 */
1836 file.read(&ehdr, sizeof(ehdr));
1837 if (ehdr.e_magic == EMAGIC)
1838 offLXHdr = ehdr.e_lfanew;
1839 else
1840 offLXHdr = 0;
1841 file.readAt(&e32, sizeof(e32), offLXHdr);
1842 if (*(PSHORT)&e32.e32_magic[0] != E32MAGIC)
1843 throw (ERROR_INVALID_EXE_SIGNATURE);
1844
1845 /*
1846 * Is there any debug info in this LX header?
1847 */
1848 if (e32.e32_debuginfo != 0UL && e32.e32_debuglen != 0UL
1849 && file.set(e32.e32_debuginfo))
1850 return new kHll(&file);
1851 else
1852 return new kHll();
1853 }
1854 catch (int iOS2Error)
1855 {
1856 fprintf(stderr, "failed to create kHll object for file %s. Failed with OS2 error %d.\n",
1857 pszFilename, iOS2Error);
1858 }
1859 return NULL;
1860}
1861
1862
1863/**
1864 * Create a kHll object from an LX export table.
1865 * @returns Pointer to kHll object.
1866 * @param pFileLX Pointer to the LX file.
1867 */
1868kHll * kHll::readLXExports(
1869 kFileLX *pFileLX
1870 ) throw(int)
1871{
1872 char szBuffer[CCHMAXPATH];
1873 kHll * pHll = new kHll();
1874 kHllModuleEntry * pModule;
1875 int i;
1876
1877
1878 /*
1879 * Set modulename.
1880 */
1881 if (!pFileLX->queryModuleName(szBuffer))
1882 strcpy(szBuffer, "HMM");
1883 pHll->setModName(szBuffer);
1884
1885
1886 /*
1887 * Make fake module.
1888 */
1889 pModule = pHll->addModule(szBuffer, NULL);
1890 if (pModule == NULL)
1891 {
1892 fprintf(stderr, "addModule failed\n");
1893 delete pHll;
1894 return NULL;
1895 }
1896 pModule->getSourceEntry()->addFile(szBuffer);
1897
1898
1899 /*
1900 * Add segment to the module.
1901 */
1902 for (i = 0; i < pFileLX->getObjectCount(); i++)
1903 {
1904 struct o32_obj *pLXObject = pFileLX->getObject((USHORT)i);
1905 if (pLXObject)
1906 {
1907 if (!pModule->addSegInfo((USHORT)(i+1), 0, pLXObject->o32_size))
1908 fprintf(stderr, "warning: addseginfo failed!\n");
1909 }
1910 else
1911 fprintf(stderr, "warning: pFileLX->getObject failed for Segment no.=%d (0 based)\n", i);
1912 }
1913
1914
1915 /*
1916 * Exports
1917 */
1918 EXPORTENTRY export;
1919 if (pFileLX->findFirstExport(&export))
1920 {
1921 do
1922 {
1923 if (export.achName[0] == '\0')
1924 sprintf(export.achName, "Ordinal%03d", export.ulOrdinal);
1925 pModule->addPublicSymbol(export.achName, export.offset,
1926 (unsigned short)export.iObject, NULL);
1927 } while (pFileLX->findNextExport(&export));
1928 }
1929
1930 return pHll;
1931}
1932
1933
1934/**
1935 * Create a kHll object from a Symbol file.
1936 * @returns Pointer to kHll object.
1937 * @param pFile Pointer to Symbol file file object.
1938 * @param pFileLX Pointer to corresponding LX (only LX - FIXME!) file. [optional].
1939 */
1940kHll * kHll::readSym(
1941 kFile *pFile,
1942 kFileLX *pFileLX /*= NULL */
1943 )
1944{
1945 kHll *pHll = NULL;
1946
1947 /*
1948 * Start conversion.
1949 */
1950 PBYTE pbSym = (PBYTE)pFile->readFile();
1951 if (pbSym != NULL)
1952 {
1953 kHllModuleEntry * pModule;
1954 PMAPDEF pMapDef; /* Mapfile header */
1955
1956 pHll = new kHll();
1957
1958 pMapDef = (PMAPDEF)pbSym;
1959 while (pMapDef != NULL)
1960 {
1961 int iSeg;
1962 PSEGDEF pSegDef; /* Segment header */
1963
1964 /*
1965 * Map definition.
1966 */
1967 printf("- Map definition -\n"
1968 " ppNextMap 0x%04x paragraph pointer to next map\n"
1969 " bFlags 0x%02x symbol types\n"
1970 " bReserved1 0x%02x reserved\n"
1971 " pSegEntry 0x%04x segment entry point value\n"
1972 " cConsts 0x%04x count of constants in map\n"
1973 " pConstDef 0x%04x pointer to constant chain\n"
1974 " cSegs 0x%04x count of segments in map\n"
1975 " ppSegDef 0x%04x paragraph pointer to first segment\n"
1976 " cbMaxSym 0x%02x maximum symbol-name length\n"
1977 " cbModName 0x%02x length of module name\n"
1978 " achModName %.*s\n"
1979 "\n",
1980 pMapDef->ppNextMap,
1981 pMapDef->bFlags,
1982 pMapDef->bReserved1,
1983 pMapDef->pSegEntry,
1984 pMapDef->cConsts,
1985 pMapDef->pConstDef,
1986 pMapDef->cSegs,
1987 pMapDef->ppSegDef,
1988 pMapDef->cbMaxSym,
1989 pMapDef->cbModName,
1990 pMapDef->cbModName,
1991 pMapDef->achModName
1992 );
1993
1994 /*
1995 * Add Module and modulename.
1996 */
1997 pHll->setModName(pMapDef->achModName, pMapDef->cbModName);
1998 pModule = pHll->addModule(pMapDef->achModName, pMapDef->cbModName, NULL);
1999 if (pModule == NULL)
2000 {
2001 fprintf(stderr, "addModule failed\n");
2002 delete pHll;
2003 return NULL;
2004 }
2005 pModule->getSourceEntry()->addFile(pMapDef->achModName, pMapDef->cbModName);
2006
2007
2008 /*
2009 * Read and convert segments with info.
2010 */
2011 pSegDef = SEGDEFPTR(pbSym, *pMapDef);
2012 iSeg = 1;
2013 while (pSegDef != NULL)
2014 {
2015 struct o32_obj *pLXObject;
2016 PSYMDEF32 pSymDef32; /* Symbol definition 32-bit */
2017 PSYMDEF16 pSymDef16; /* Symbol definition 16-bit */
2018 int iSym;
2019
2020
2021 /*
2022 * Dump Segment definition.
2023 */
2024 printf(" - Segment Definition -\n"
2025 " ppNextSeg 0x%04x paragraph pointer to next segment\n"
2026 " cSymbols 0x%04x count of symbols in list\n"
2027 " pSymDef 0x%04x offset of symbol chain\n"
2028 " wSegNum 0x%04x segment number (1-based)\n"
2029 " wReserved2 0x%04x reserved\n"
2030 " wReserved3 0x%04x reserved\n"
2031 " wReserved4 0x%04x reserved\n"
2032 " bFlags 0x%04x symbol types\n"
2033 " bReserved1 0x%04x reserved\n"
2034 " ppLineDef 0x%04x offset of line number record\n"
2035 " bReserved2 0x%04x reserved\n"
2036 " bReserved3 0x%04x reserved\n"
2037 " cbSegName 0x%04x length of segment name\n"
2038 " achSegName %.*s\n",
2039 pSegDef->ppNextSeg,
2040 pSegDef->cSymbols,
2041 pSegDef->pSymDef,
2042 pSegDef->wSegNum,
2043 pSegDef->wReserved2,
2044 pSegDef->wReserved3,
2045 pSegDef->wReserved4,
2046 pSegDef->bFlags,
2047 pSegDef->bReserved1,
2048 pSegDef->ppLineDef ,
2049 pSegDef->bReserved2,
2050 pSegDef->bReserved3,
2051 pSegDef->cbSegName,
2052 pSegDef->cbSegName,
2053 pSegDef->achSegName
2054 );
2055
2056 /*
2057 * Add segment to the module - FIXME - need info from the LX Object table...
2058 */
2059 if (pFileLX)
2060 {
2061 pLXObject = pFileLX->getObject((USHORT)iSeg-1);
2062 if (pLXObject == NULL)
2063 fprintf(stderr, "warning: pFileLX->getObject failed for iSeg=%d\n",
2064 iSeg);
2065 }
2066
2067 if (pLXObject != NULL)
2068 { /* Make fake LX object info */
2069
2070 }
2071
2072 if (pLXObject)
2073 {
2074 if (!pModule->addSegInfo((USHORT)iSeg, 0, pLXObject->o32_size))
2075 fprintf(stderr, "warning: addseginfo failed!\n");
2076 }
2077
2078 /*
2079 * Read and convert symbols
2080 */
2081 for (iSym = 0; iSym < pSegDef->cSymbols; iSym++)
2082 {
2083 unsigned long offset;
2084 int cchName;
2085 const char * pachName;
2086 pSymDef32 = SYMDEFPTR32(pbSym, pSegDef, iSym);
2087 pSymDef16 = (PSYMDEF16)pSymDef32;
2088
2089 if (SEG32BitSegment(*pSegDef))
2090 { /* pSymDef32 */
2091 offset = pSymDef32->wSymVal;
2092 cchName = pSymDef32->cbSymName;
2093 pachName = pSymDef32->achSymName;
2094 }
2095 else
2096 { /* pSymDef16 */
2097 offset = pSymDef16->wSymVal;
2098 cchName = pSymDef16->cbSymName;
2099 pachName = pSymDef16->achSymName;
2100 }
2101
2102 printf(" 0x%08x %.*s\n",
2103 offset,
2104 cchName,
2105 pachName);
2106
2107 /*
2108 * Add symbol - currently we define it as public - it's a symbol local to this module really.
2109 */
2110 pModule->addPublicSymbol(pachName, cchName, offset, (USHORT)iSeg, 0);
2111 }
2112
2113
2114 /*
2115 * Next segment
2116 */
2117 printf("\n");
2118 pSegDef = NEXTSEGDEFPTR(pbSym, *pSegDef);
2119 iSeg++;
2120 }
2121
2122
2123 /*
2124 * Next map
2125 */
2126 pMapDef = NEXTMAPDEFPTR(pbSym, *pMapDef);
2127 if (pMapDef != NULL)
2128 {
2129 if (pMapDef->ppNextMap == 0)
2130 { /* last map */
2131 PLAST_MAPDEF pLastMapDef = (PLAST_MAPDEF)pMapDef;
2132 printf("- Last Map definition -\n"
2133 " ppNextMap 0x%04x always zero\n"
2134 " version 0x%02x release number (minor version number)\n"
2135 " release 0x%02x major version number\n",
2136 pLastMapDef->ppNextMap,
2137 pLastMapDef->release,
2138 pLastMapDef->version
2139 );
2140 break;
2141 }
2142 }
2143 } /* Map loop */
2144 }
2145
2146 return pHll;
2147}
2148
2149
2150/**
2151 * Writes the HLL info to a file. (Not LX?)
2152 * @returns Success indicator.
2153 * @param pszFilename Name of the output file.
2154 * @remark IMPORTANT! This is mostly for debugging!
2155 * It completely overwrites the file if it exists!
2156 */
2157BOOL kHll::write(
2158 const char *pszFilename
2159 )
2160{
2161 FILE * phFile;
2162
2163 phFile = fopen(pszFilename, "wb");
2164 if (phFile != NULL)
2165 {
2166 int cch = write(phFile);
2167 if (cch > 0)
2168 {
2169 fclose(phFile);
2170 return TRUE;
2171 }
2172 else
2173 fprintf(stderr, "write failed with cch=%d\n", cch);
2174 fclose(phFile);
2175 }
2176
2177 return FALSE;
2178}
2179
2180
2181
2182/**
2183 * Writes the HLL info to a file. (Not LX?)
2184 * Failes if there is debuginfo in the file.
2185 * No backup is made. (sorry)
2186 * @returns OS2 return code.
2187 * @param pszFilename Name of the output file.
2188 */
2189APIRET kHll::writeToLX(
2190 const char *pszFilename
2191 )
2192{
2193 APIRET rc;
2194 FILE * phFile;
2195
2196 phFile = fopen(pszFilename, "rb+");
2197 if (phFile != NULL)
2198 {
2199 struct exe_hdr ehdr;
2200 struct e32_exe e32;
2201 int cch;
2202 long lPosLXHdr;
2203 long cbLXFile;
2204
2205 /*
2206 * Read exe header
2207 */
2208 cch = fread(&ehdr, 1, sizeof(ehdr), phFile);
2209 if (cch == sizeof(ehdr))
2210 {
2211 cbLXFile = fsize(phFile);
2212 if (ehdr.e_magic == EMAGIC)
2213 lPosLXHdr = ehdr.e_lfanew;
2214 else
2215 lPosLXHdr = 0;
2216 if (fseek(phFile, lPosLXHdr, SEEK_SET) == 0)
2217 {
2218 cch = fread(&e32, 1, sizeof(e32), phFile);
2219 if (cch == sizeof(e32))
2220 {
2221 if (*(unsigned short*)&e32.e32_magic[0] == E32MAGIC)
2222 {
2223 /*
2224 * Found exeheader.
2225 * Check if there is any debug info.
2226 */
2227 if ((e32.e32_debuginfo == 0 && e32.e32_debuginfo == 0)
2228 || (cbLXFile == e32.e32_debuglen + e32.e32_debuginfo)
2229 )
2230 {
2231 long lPosDebug;
2232
2233 if (e32.e32_debuginfo != 0 && e32.e32_debuglen != 0)
2234 lPosDebug = e32.e32_debuginfo;
2235 else
2236 lPosDebug = cbLXFile;
2237 //lPosDebug = (cbLXFile + 0x400) & ~0x1FF; //try do some alignment.
2238
2239 /*
2240 * Go to debug info position in the file and write debug info.
2241 */
2242 if (fseek(phFile, lPosDebug, SEEK_SET) == 0)
2243 {
2244 /*
2245 * Write the HLL data to disk.
2246 */
2247 cch = write(phFile);
2248 if (cch > 0)
2249 {
2250 /*
2251 * Write dummy signature (_VerifySignature in the OS2KRNL checks this).
2252 * The signatures size is the last dword in the file.
2253 * If we pad that dword with 0 (or a number larger than the filesize)
2254 * the module is verified successfully by the OS2KRNL.
2255 *
2256 * FYI. If the verify fails a DosExit is issued in the init process,
2257 * and it will crash due to a bad exception handler point (at fs:0)
2258 * when the termination exception occures. Which so leads to another
2259 * exception in the exceptionhandler (which don't check for NULL
2260 * pointers to exceptionhandlers only -1 pointers).
2261 */
2262 static char achFakeSig[4] = {0};
2263 if (fseek(phFile, 0, SEEK_END) == 0)
2264 {
2265 if (fwrite(&achFakeSig[0], 1, sizeof(achFakeSig), phFile) == sizeof(achFakeSig))
2266 {
2267 cch += sizeof(achFakeSig);
2268
2269 /*
2270 * Update exeheader.
2271 */
2272 e32.e32_debuglen = cch;
2273 e32.e32_debuginfo = lPosDebug;
2274 if (fseek(phFile, lPosLXHdr, SEEK_SET) == 0)
2275 {
2276 /*
2277 * Write the updated header to disk.
2278 */
2279 cch = fwrite(&e32, 1, sizeof(e32), phFile);
2280 if (cch == sizeof(e32))
2281 rc = NO_ERROR;
2282 else
2283 rc = ERROR_WRITE_FAULT;
2284 }
2285 else
2286 rc = ERROR_SEEK;
2287 }
2288 else
2289 {
2290 fprintf(stderr, "warning - failed to write fake signature.\n");
2291 rc = ERROR_WRITE_FAULT;
2292 }
2293 }
2294 else
2295 rc = ERROR_SEEK;
2296 }
2297 else
2298 {
2299 fprintf(stderr, "error - write failed with cch=%d\n", cch);
2300 rc = ERROR_WRITE_FAULT;
2301 }
2302 }
2303 else
2304 rc = ERROR_SEEK;
2305 }
2306 else
2307 {
2308 fprintf(stderr, "error - debuginfo exists\n");
2309 rc = ERROR_BAD_EXE_FORMAT;
2310 }
2311
2312 }
2313 else
2314 rc = ERROR_INVALID_EXE_SIGNATURE;
2315 }
2316 else
2317 rc = ERROR_BAD_EXE_FORMAT;
2318 }
2319 else
2320 rc = ERROR_BAD_EXE_FORMAT;
2321 }
2322 else
2323 rc = ERROR_READ_FAULT;
2324
2325 fclose(phFile);
2326 }
2327 else
2328 rc = ERROR_ACCESS_DENIED; //?
2329
2330
2331 return rc;
2332}
2333
2334
2335/**
2336 * Converts HLL info to a Sym file.
2337 * No backup is made. (sorry)
2338 * @returns OS2 return code.
2339 * @param pFile Pointer to output file object.
2340 */
2341void kHll::writeSym(
2342 kFile * pFile
2343 ) throw(int)
2344{
2345 long off;
2346 int rc = 0;
2347 long offEndMap;
2348 int cbMapDef;
2349 PMAPDEF pMapDef = (PMAPDEF)malloc(sizeof(MAPDEF) + CCHMAXPATH); /* Mapfile header */
2350 PLAST_MAPDEF pEndMapDef = (PLAST_MAPDEF)pMapDef;
2351 int iSeg; /* (1 based) */
2352 int cSegs = queryMaxObjectIndex();
2353
2354 /* If any I/O operation failes, it should throw errors to our caller. */
2355 pFile->setThrowOnErrors();
2356
2357 /* Ensure that there is a module name. */
2358 if (getModName() == NULL)
2359 setModName(pFile->getFilename());
2360
2361 /* Make mapdef. */
2362 memset(pMapDef, 0, sizeof(MAPDEF) + CCHMAXPATH);
2363 pMapDef->bFlags = 2; //what's this?
2364 pMapDef->pSegEntry = 1; //dummy
2365 pMapDef->cbMaxSym = 64;
2366 strcpy(pMapDef->achModName, getModName());
2367 pMapDef->cbModName = (unsigned char)strlen(pMapDef->achModName);
2368 cbMapDef = (int)((sizeof(MAPDEF) - 1 + pMapDef->cbModName + 15UL) & ~15UL);
2369 pMapDef->ppSegDef = (unsigned short)(cbMapDef >> 4);
2370 pMapDef->cSegs = (unsigned short)cSegs;
2371 pFile->write(pMapDef, cbMapDef);
2372
2373
2374 /*
2375 * Make segment info.
2376 * -determin number of segments
2377 * -loop thru every segment and write symbols.
2378 */
2379 for (iSeg = 1; iSeg <= cSegs && rc == 0; iSeg++)
2380 {
2381 char achBufferSegDef[CCHMAXPATH + sizeof(SEGDEF)];
2382 int cbSegDef;
2383 PSEGDEF pSegDef = (PSEGDEF)&achBufferSegDef[0];
2384 long offSegDef = pFile->getPos();
2385 kHllModuleEntry * pModule;
2386 int coffSymsAllocated = 100;
2387 unsigned short * paoffSyms = (unsigned short *)malloc(sizeof(unsigned short) * coffSymsAllocated);
2388
2389 /* Make and write segdef. */
2390 memset(pSegDef, 0, sizeof(SEGDEF));
2391 sprintf(pSegDef->achSegName, "Segment%d", iSeg);
2392 pSegDef->wSegNum = (unsigned short)iSeg;
2393 pSegDef->bReserved3 = (char)0xff;
2394 pSegDef->cbSegName = (unsigned char)strlen(pSegDef->achSegName);
2395 pSegDef->bFlags = SEG_FLAGS_32BIT;
2396 cbSegDef = (int)(((sizeof(SEGDEF) + pSegDef->cbSegName) + 15UL) & ~15UL);
2397 pFile->write(pSegDef, cbSegDef);
2398
2399
2400 /* Write symbols. */
2401 pModule = (kHllModuleEntry*)Modules.getFirst();
2402 while (pModule && rc == 0)
2403 {
2404 pModule->writeSymSeg(pFile, iSeg, pSegDef, paoffSyms, coffSymsAllocated, offSegDef);
2405 pModule = (kHllModuleEntry*)pModule->getNext();
2406 }
2407
2408
2409 /* Write offset array */
2410 off = pFile->getPos();
2411 pSegDef->pSymDef = (unsigned short)(off - offSegDef);
2412 pFile->write(paoffSyms, pSegDef->cSymbols * sizeof(unsigned short));
2413 pFile->write(pSegDef, (size_t)(16 - (pFile->getPos() % 16)));
2414
2415
2416 /* Write updated segdef. */
2417 off = pFile->getPos();
2418 assert((off % 16) == 0);
2419 if (iSeg < cSegs)
2420 pSegDef->ppNextSeg = (unsigned short)(off >> 4);
2421 pFile->writeAt(pSegDef, sizeof(SEGDEF), offSegDef);
2422 pFile->set(off);
2423 free(paoffSyms);
2424 }
2425
2426
2427 /*
2428 * Write the updated mapdef and the last mapdef entry.
2429 */
2430 offEndMap = pFile->getPos();
2431 assert((offEndMap % 16) == 0);
2432 pMapDef->ppNextMap = (unsigned short)(offEndMap >> 4);
2433 pFile->writeAt(pMapDef, sizeof(MAPDEF), 0);
2434
2435 pEndMapDef->ppNextMap = 0;
2436 pEndMapDef->release = 1;
2437 pEndMapDef->version = 5;
2438 pFile->writeAt(pEndMapDef, sizeof(LAST_MAPDEF), offEndMap);
2439 pFile->setSize();
2440
2441 /*
2442 * Cleanup
2443 */
2444 free(pMapDef);
2445}
2446
2447
2448/**
2449 * Gets the highest object index.
2450 * @returns Higest object index used. (1 based?)
2451 */
2452int kHll::queryMaxObjectIndex()
2453{
2454 int iObjectMax = 0;
2455 kHllModuleEntry *pModule = (kHllModuleEntry*)Modules.getFirst();
2456 while (pModule != NULL)
2457 {
2458 int iObject = pModule->queryMaxObjectIndex();
2459
2460 if (iObject > iObjectMax)
2461 iObjectMax = iObject;
2462
2463 /* next */
2464 pModule = (kHllModuleEntry*)pModule->getNext();
2465 }
2466 return iObjectMax;
2467}
2468
2469
2470/**
2471 * Find the size of a file.
2472 * @returns Size of file. -1 on error.
2473 * @param phFile File handle.
2474 */
2475signed long fsize(FILE *phFile)
2476{
2477 long ipos;
2478 signed long cb;
2479
2480 if ((ipos = ftell(phFile)) < 0
2481 ||
2482 fseek(phFile, 0, SEEK_END) != 0
2483 ||
2484 (cb = ftell(phFile)) < 0
2485 ||
2486 fseek(phFile, ipos, SEEK_SET) != 0
2487 )
2488 cb = -1;
2489 return cb;
2490}
2491
Note: See TracBrowser for help on using the repository browser.