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

Last change on this file since 10367 was 8247, checked in by bird, 23 years ago

Updated so it compiles and workes with latest kFile*.h changes.

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