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

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

New interface (kHllMain).
Able to spit out symbol files.
Able to read symbol files and the entry table of LX files.

File size: 73.0 KB
Line 
1/* $Id: kHll.cpp,v 1.15 2000-08-31 03:02:27 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 + 0x400) & ~0x1FF; //try do some alignment.
2237
2238 /*
2239 * Go to debug info position in the file and write debug info.
2240 */
2241 if (fseek(phFile, lPosDebug, SEEK_SET) == 0)
2242 {
2243 /*
2244 * Write the HLL data to disk.
2245 */
2246 cch = write(phFile);
2247 if (cch > 0)
2248 {
2249 /*
2250 * Update exeheader.
2251 */
2252 e32.e32_debuglen = cch;
2253 e32.e32_debuginfo = lPosDebug;
2254 if (fseek(phFile, lPosLXHdr, SEEK_SET) == 0)
2255 {
2256 /*
2257 * Write the updated header to disk.
2258 */
2259 cch = fwrite(&e32, 1, sizeof(e32), phFile);
2260 if (cch == sizeof(e32))
2261 rc = NO_ERROR;
2262 else
2263 rc = ERROR_WRITE_FAULT;
2264 }
2265 else
2266 rc = ERROR_SEEK;
2267 }
2268 else
2269 {
2270 fprintf(stderr, "error - write failed with cch=%d\n", cch);
2271 rc = ERROR_WRITE_FAULT;
2272 }
2273 }
2274 else
2275 rc = ERROR_SEEK;
2276 }
2277 else
2278 {
2279 fprintf(stderr, "error - debuginfo exists\n");
2280 rc = ERROR_BAD_EXE_FORMAT;
2281 }
2282
2283 }
2284 else
2285 rc = ERROR_INVALID_EXE_SIGNATURE;
2286 }
2287 else
2288 rc = ERROR_BAD_EXE_FORMAT;
2289 }
2290 else
2291 rc = ERROR_BAD_EXE_FORMAT;
2292 }
2293 else
2294 rc = ERROR_READ_FAULT;
2295
2296 fclose(phFile);
2297 }
2298 else
2299 rc = ERROR_ACCESS_DENIED; //?
2300
2301
2302 return rc;
2303}
2304
2305
2306/**
2307 * Converts HLL info to a Sym file.
2308 * No backup is made. (sorry)
2309 * @returns OS2 return code.
2310 * @param pFile Pointer to output file object.
2311 */
2312void kHll::writeSym(
2313 kFile * pFile
2314 ) throw(int)
2315{
2316 long off;
2317 int rc = 0;
2318 long offEndMap;
2319 int cbMapDef;
2320 PMAPDEF pMapDef = (PMAPDEF)malloc(sizeof(MAPDEF) + CCHMAXPATH); /* Mapfile header */
2321 PLAST_MAPDEF pEndMapDef = (PLAST_MAPDEF)pMapDef;
2322 int iSeg; /* (1 based) */
2323 int cSegs = queryMaxObjectIndex();
2324
2325 /* If any I/O operation failes, it should throw errors to our caller. */
2326 pFile->setThrowOnErrors();
2327
2328 /* Ensure that there is a module name. */
2329 if (getModName() == NULL)
2330 setModName(pFile->getFilename());
2331
2332 /* Make mapdef. */
2333 memset(pMapDef, 0, sizeof(MAPDEF) + CCHMAXPATH);
2334 pMapDef->bFlags = 2; //what's this?
2335 pMapDef->pSegEntry = 1; //dummy
2336 pMapDef->cbMaxSym = 64;
2337 strcpy(pMapDef->achModName, getModName());
2338 pMapDef->cbModName = (unsigned char)strlen(pMapDef->achModName);
2339 cbMapDef = (int)((sizeof(MAPDEF) - 1 + pMapDef->cbModName + 15UL) & ~15UL);
2340 pMapDef->ppSegDef = (unsigned short)(cbMapDef >> 4);
2341 pMapDef->cSegs = (unsigned short)cSegs;
2342 pFile->write(pMapDef, cbMapDef);
2343
2344
2345 /*
2346 * Make segment info.
2347 * -determin number of segments
2348 * -loop thru every segment and write symbols.
2349 */
2350 for (iSeg = 1; iSeg <= cSegs && rc == 0; iSeg++)
2351 {
2352 char achBufferSegDef[CCHMAXPATH + sizeof(SEGDEF)];
2353 int cbSegDef;
2354 PSEGDEF pSegDef = (PSEGDEF)&achBufferSegDef[0];
2355 long offSegDef = pFile->getPos();
2356 kHllModuleEntry * pModule;
2357 int coffSymsAllocated = 100;
2358 unsigned short * paoffSyms = (unsigned short *)malloc(sizeof(unsigned short) * coffSymsAllocated);
2359
2360 /* Make and write segdef. */
2361 memset(pSegDef, 0, sizeof(SEGDEF));
2362 sprintf(pSegDef->achSegName, "Segment%d", iSeg);
2363 pSegDef->wSegNum = (unsigned short)iSeg;
2364 pSegDef->bReserved3 = (char)0xff;
2365 pSegDef->cbSegName = (unsigned char)strlen(pSegDef->achSegName);
2366 pSegDef->bFlags = SEG_FLAGS_32BIT;
2367 cbSegDef = (int)(((sizeof(SEGDEF) + pSegDef->cbSegName) + 15UL) & ~15UL);
2368 pFile->write(pSegDef, cbSegDef);
2369
2370
2371 /* Write symbols. */
2372 pModule = (kHllModuleEntry*)Modules.getFirst();
2373 while (pModule && rc == 0)
2374 {
2375 pModule->writeSymSeg(pFile, iSeg, pSegDef, paoffSyms, coffSymsAllocated, offSegDef);
2376 pModule = (kHllModuleEntry*)pModule->getNext();
2377 }
2378
2379
2380 /* Write offset array */
2381 off = pFile->getPos();
2382 pSegDef->pSymDef = (unsigned short)(off - offSegDef);
2383 pFile->write(paoffSyms, pSegDef->cSymbols * sizeof(unsigned short));
2384 pFile->write(pSegDef, (size_t)(16 - (pFile->getPos() % 16)));
2385
2386
2387 /* Write updated segdef. */
2388 off = pFile->getPos();
2389 assert((off % 16) == 0);
2390 if (iSeg < cSegs)
2391 pSegDef->ppNextSeg = (unsigned short)(off >> 4);
2392 pFile->writeAt(pSegDef, sizeof(SEGDEF), offSegDef);
2393 pFile->set(off);
2394 free(paoffSyms);
2395 }
2396
2397
2398 /*
2399 * Write the updated mapdef and the last mapdef entry.
2400 */
2401 offEndMap = pFile->getPos();
2402 assert((offEndMap % 16) == 0);
2403 pMapDef->ppNextMap = (unsigned short)(offEndMap >> 4);
2404 pFile->writeAt(pMapDef, sizeof(MAPDEF), 0);
2405
2406 pEndMapDef->ppNextMap = 0;
2407 pEndMapDef->release = 1;
2408 pEndMapDef->version = 5;
2409 pFile->writeAt(pEndMapDef, sizeof(LAST_MAPDEF), offEndMap);
2410 pFile->setSize();
2411
2412 /*
2413 * Cleanup
2414 */
2415 free(pMapDef);
2416}
2417
2418
2419/**
2420 * Gets the highest object index.
2421 * @returns Higest object index used. (1 based?)
2422 */
2423int kHll::queryMaxObjectIndex()
2424{
2425 int iObjectMax = 0;
2426 kHllModuleEntry *pModule = (kHllModuleEntry*)Modules.getFirst();
2427 while (pModule != NULL)
2428 {
2429 int iObject = pModule->queryMaxObjectIndex();
2430
2431 if (iObject > iObjectMax)
2432 iObjectMax = iObject;
2433
2434 /* next */
2435 pModule = (kHllModuleEntry*)pModule->getNext();
2436 }
2437 return iObjectMax;
2438}
2439
2440
2441/**
2442 * Find the size of a file.
2443 * @returns Size of file. -1 on error.
2444 * @param phFile File handle.
2445 */
2446signed long fsize(FILE *phFile)
2447{
2448 long ipos;
2449 signed long cb;
2450
2451 if ((ipos = ftell(phFile)) < 0
2452 ||
2453 fseek(phFile, 0, SEEK_END) != 0
2454 ||
2455 (cb = ftell(phFile)) < 0
2456 ||
2457 fseek(phFile, ipos, SEEK_SET) != 0
2458 )
2459 cb = -1;
2460 return cb;
2461}
2462
Note: See TracBrowser for help on using the repository browser.