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

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

Work in progress...

File size: 51.7 KB
Line 
1/* $Id: kHll.cpp,v 1.14 2000-05-29 19:46:28 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#include <assert.h>
38
39#include <kList.h>
40#include <kFile.h>
41
42#include "hll.h"
43#include "kHll.h"
44
45
46/*******************************************************************************
47* Internal Functions *
48*******************************************************************************/
49signed long fsize(FILE *phFile);
50
51
52
53
54/*******************************************************************************
55* *
56* kHllBaseEntry *
57* *
58* kHllBaseEntry *
59* *
60*******************************************************************************/
61
62
63/**
64 * Writes a list to disk.
65 * @returns Number of bytes written.
66 * @returns Count of bytes written on success. (includes 0)
67 * -3 Invalid offsets.
68 * -2 Seek error.
69 * -1 Write error.
70 * @param phFile Output filehandle.
71 * @param pEntry Pointer to the start of the list which is to be written.
72 */
73int kHllBaseEntry::writeList(FILE *phFile, kHllBaseEntry *pEntry)
74{
75 int cch;
76 int cchWritten = 0;
77
78 /*
79 * Loop thru the list and write all the entries to disk.
80 */
81 while (pEntry != NULL)
82 {
83 cchWritten += cch = pEntry->write(phFile);
84 if (cch < 0)
85 return cch;
86 if (cch == 0)
87 return -1;
88 pEntry = (kHllBaseEntry*)pEntry->getNext();
89 }
90
91 return cchWritten;
92}
93
94
95
96/**
97 * Loops thru the given list and call the dump method for each
98 * node with the passed in parameters.
99 * @param ph Dump file handle.
100 * @param cchIndent Indent.
101 * @param pEntry Indent.
102 */
103void kHllBaseEntry::dumpList(FILE *ph, int cchIndent, kHllBaseEntry *pEntry)
104{
105 /*
106 * Loop thru the list staring at pEntry and call dump for each entry.
107 */
108 while (pEntry != NULL)
109 {
110 pEntry->dump(ph, cchIndent);
111 pEntry = (kHllBaseEntry*)pEntry->getNext();
112 }
113}
114
115
116/**
117 * Loops thru the given list and call the ida method for each
118 * node with the passed in parameters.
119 * !!!NOTE!!! THIS IS ONLY TO BE USED FOR YOUR OWN PROGRAMS!!!
120 * @param pFile Output file.
121 * @param pEntry Indent.
122 */
123void kHllBaseEntry::idaList(kFile *pFile, kHllBaseEntry *pEntry)
124{
125 /*
126 * Loop thru the list staring at pEntry and call ida for each entry.
127 */
128 while (pEntry != NULL)
129 {
130 pEntry->ida(pFile);
131 pEntry = (kHllBaseEntry*)pEntry->getNext();
132 }
133}
134
135
136
137
138/*******************************************************************************
139* *
140* kHllPubSymEntry *
141* *
142* kHllPubSymEntry *
143* *
144*******************************************************************************/
145
146
147
148
149
150/**
151 * Creates an HLL public symbol entry.
152 * @param pachName Symbol name.
153 * @param cchName Length of symbol name.
154 * @param off Offset into the object.
155 * @param iObject LX Object index.
156 * @param iType Type index. (index into type table)
157 */
158kHllPubSymEntry::kHllPubSymEntry(
159 const char * pachName,
160 int cchName,
161 unsigned long off,
162 unsigned short iObject,
163 unsigned short iType
164 )
165{
166 pPubSym = (PHLLPUBLICSYM)malloc(cchName + sizeof(HLLPUBLICSYM));
167 assert(pPubSym != NULL);
168
169 pPubSym->cchName = (unsigned char)cchName;
170 pPubSym->achName[0] = '\0';
171 strncat((char*)&pPubSym->achName[0], pachName, cchName);
172 pPubSym->off = off;
173 pPubSym->iObject = iObject;
174 pPubSym->iType = iType;
175}
176
177
178
179/**
180 * Destructor.
181 */
182kHllPubSymEntry::~kHllPubSymEntry()
183{
184 if (pPubSym != NULL)
185 free(pPubSym);
186 pPubSym = NULL;
187}
188
189
190
191/**
192 * Write this entry to file.
193 * @returns Count of bytes written (on success).
194 * -3 Invalid offsets.
195 * -2 Seek error.
196 * -1 Write error.
197 * 0 No data written. Concidered as an error!
198 * @param phFile Filehandle.
199 */
200int kHllPubSymEntry::write(FILE *phFile)
201{
202 assert(pPubSym != NULL);
203 return fwrite(pPubSym,
204 1,
205 offsetof(HLLPUBLICSYM, achName) + pPubSym->cchName,
206 phFile);
207}
208
209
210/**
211 * Dumps the HLL entry to ph in a human readable fashion.
212 * @param ph Output file handle the dump is to be written to.
213 * @param cchIndent Number of char to indents the output dump.
214 */
215void kHllPubSymEntry::dump(FILE *ph, int cchIndent)
216{
217 /*
218 * Dump public symbol entry
219 */
220 fprintf(ph, "%*.s0x%04x:0x%08x type:%5d(0x%04x) name: %.*s\n",
221 cchIndent, "",
222 pPubSym->iObject,
223 pPubSym->off,
224 pPubSym->iType,
225 pPubSym->iType,
226 pPubSym->cchName, &pPubSym->achName[0]
227 );
228}
229
230
231/**
232 * Create IDC (IDA Pro) calls which adds info contained in the entry
233 * to the ida pro database.
234 * !!!NOTE!!! THIS IS ONLY TO BE USED FOR YOUR OWN PROGRAMS!!!
235 * @param pFile Output file.
236 */
237void kHllPubSymEntry::ida(kFile *pFile) throw(int)
238{
239 #if 0
240 pFile->printf(" /* PubSym %.*s */\n",
241 pPubSym->cchName, &pPubSym->achName[0]);
242 #endif
243 pFile->printf(" ea = SegByBase(%d) + 0x%08x; MakeName(ea, \"\"); MakeName(ea, \"%.*s\");\n",
244 pPubSym->iObject,
245 pPubSym->off,
246 pPubSym->cchName, &pPubSym->achName[0]
247 );
248}
249
250
251
252
253
254
255
256
257
258
259
260/*******************************************************************************
261* *
262* kHllLineNumberChunk *
263* *
264* kHllLineNumberChunk *
265* *
266*******************************************************************************/
267
268
269
270
271 int cLines;
272 PHLLLINENUMBERENTRY paLines;
273 HLLFIRSTENTRY FirstEntry;
274
275/**
276 * Constructor.
277 * @param iSeg Segment number for these linenumbers.
278 * @param offBase Base offset for all line number offsets. (defaults to 0)
279 */
280kHllLineNumberChunk::kHllLineNumberChunk(
281 unsigned short int iSeg,
282 unsigned long int offBase /*= 0*/
283 )
284{
285 memset(&FirstEntry, 0, sizeof(FirstEntry));
286 FirstEntry.hll04.iSeg = iSeg;
287 FirstEntry.hll04.u1.offBase = offBase;
288 FirstEntry.hll04.uchType = 0;
289}
290
291
292
293/**
294 * Destructor.
295 */
296kHllLineNumberChunk::~kHllLineNumberChunk()
297{
298 if (paLines != NULL)
299 free(paLines);
300 paLines = 0;
301 FirstEntry.hll04.cEntries = 0;
302}
303
304
305
306/**
307 * Adds a line information.
308 * @returns Success indicator.
309 * @param iusFile File index.
310 * @param usLine Line number
311 * @param off Offset into object.
312 */
313BOOL kHllLineNumberChunk::addLineInfo(
314 unsigned short int iusFile,
315 unsigned short int usLine,
316 unsigned long int off
317 )
318{
319 /*
320 * Allocate more memory?
321 */
322 if (FirstEntry.hll04.cEntries % 20 == 0)
323 {
324 void *pv = realloc(paLines, (FirstEntry.hll04.cEntries + 20) * sizeof(paLines[0].hll04));
325 assert(pv != NULL);
326 if (pv == NULL)
327 return FALSE;
328 paLines = (PHLLLINENUMBERENTRY)pv;
329 }
330
331 /*
332 * Add line info entry.
333 */
334 paLines[FirstEntry.hll04.cEntries].hll04.iusSourceFile = iusFile;
335 paLines[FirstEntry.hll04.cEntries].hll04.off = off;
336 paLines[FirstEntry.hll04.cEntries].hll04.usLine = usLine;
337 FirstEntry.hll04.cEntries++;
338
339 return FALSE;
340}
341
342
343/**
344 * Write this entry to file.
345 * @returns Count of bytes written (on success).
346 * -3 Invalid offsets.
347 * -2 Seek error.
348 * -1 Write error.
349 * 0 No data written. Concidered as an error!
350 * @param phFile Filehandle.
351 */
352int kHllLineNumberChunk::write(FILE *phFile)
353{
354 int cb;
355 int cbWritten;
356
357 /*
358 * First entry
359 */
360 cb = sizeof(paLines[0])*FirstEntry.hll04.cEntries;
361 cbWritten = fwrite(&FirstEntry, 1, cb, phFile);
362 if (cbWritten != cb)
363 return -1;
364
365 /*
366 * Line array.
367 */
368 cb = sizeof(paLines[0])*FirstEntry.hll04.cEntries;
369 cbWritten = fwrite(paLines, 1, cb, phFile);
370 if (cbWritten != cb)
371 return -1;
372
373 return cbWritten + sizeof(FirstEntry.hll04);
374}
375
376
377
378/**
379 * Dumps the HLL entry to ph in a human readable fashion.
380 * @param ph Output file handle the dump is to be written to.
381 * @param cchIndent Number of char to indents the output dump.
382 */
383void kHllLineNumberChunk::dump(FILE *ph, int cchIndent)
384{
385 int i;
386
387 /*
388 * Write header.
389 * Dump first entry.
390 * Dump linenumbers.
391 * Write footer.
392 */
393 fprintf(ph, "%*.s------- start kHllLineNumberChunk object 0x%08x -------\n",
394 cchIndent, "", this);
395
396 /* ASSUMES - TODO - FIXME: HLL version 3 or 4. */
397 fprintf(ph, "%*.sBaseLine: %04d Type: 0x%02x Entries: 0x%04(%d) iSeg: 0x04x(%d) ",
398 cchIndent, "",
399 FirstEntry.hll04.usLine,
400 FirstEntry.hll04.uchType,
401 FirstEntry.hll04.cEntries,
402 FirstEntry.hll04.cEntries,
403 FirstEntry.hll04.iSeg,
404 FirstEntry.hll04.iSeg
405 );
406 if (FirstEntry.hll04.uchType == 0)
407 fprintf(ph, "offBase: 0x%08x\n", FirstEntry.hll04.u1.offBase);
408 else
409 fprintf(ph, "u1: 0x%08x\n", FirstEntry.hll04.u1.offBase);
410
411
412 /* ASSUMES - TODO - FIXME: HLL version 3 or 4. */
413 for (i = 0; i < FirstEntry.hll04.cEntries; i++)
414 fprintf(ph, "%*.sFile: %04d Line: %04d Offset: 0x%08x\n",
415 cchIndent, "",
416 paLines[i].hll04.iusSourceFile,
417 paLines[i].hll04.usLine,
418 paLines[i].hll04.off
419 );
420
421
422 fprintf(ph, "%*.s------- end kHllLineNumberChunk object 0x%08x -------\n",
423 cchIndent, "", this);
424}
425
426
427/**
428 * Create IDC (IDA Pro) calls which adds info contained in the entry
429 * to the ida pro database.
430 * !!!NOTE!!! THIS IS ONLY TO BE USED FOR YOUR OWN PROGRAMS!!!
431 * @param pFile Output file.
432 */
433void kHllLineNumberChunk::ida(kFile *pFile) throw(int)
434{
435 pFile->printf(" /* Line number chunk */\n");
436}
437
438
439
440
441
442
443
444
445
446/*******************************************************************************
447* *
448* kHllSrcEntry *
449* *
450* kHllSrcEntry *
451* *
452*******************************************************************************/
453
454
455
456
457
458/**
459 * Constructor.
460 */
461kHllSrcEntry::kHllSrcEntry()
462 :
463 cFilenames(0),
464 pachFilenames(NULL),
465 cbFilenames(0),
466 cbFilenamesAllocated(0)
467{
468}
469
470
471/**
472 * Destructor.
473 */
474kHllSrcEntry::~kHllSrcEntry()
475{
476 if (pachFilenames != NULL)
477 free(pachFilenames);
478 pachFilenames = NULL;
479 cFilenames = cbFilenames = cbFilenamesAllocated = 0;
480}
481
482
483
484/**
485 * Add/queries a Linenumber chunk.
486 * A linenumber chunk is a collection of linenumber information for a
487 * module segement.
488 * @returns Pointer to linenumber chunk which you may add linenumber info to.
489 * NULL on failiure.
490 * @param iSeg Segment number for these linenumbers.
491 * @param offBase Base offset for all line number offsets. (defaults to 0)
492 */
493kHllLineNumberChunk *
494 kHllSrcEntry::addLineNumberChunk(
495 unsigned short int iSeg,
496 unsigned long int offBase/* = 0*/
497 )
498{
499 kHllLineNumberChunk *pChunk;
500
501 /*
502 * Try find existing chunk.
503 */
504 pChunk = Lines.getFirst();
505 while (pChunk != NULL && pChunk->getSeg() != iSeg)
506 pChunk = (kHllLineNumberChunk*)pChunk->getNext();
507
508 /*
509 * If not found, then create a new one and add it to the list.
510 */
511 if (pChunk != NULL)
512 {
513 pChunk = new kHllLineNumberChunk(iSeg, offBase);
514 assert(pChunk != NULL);
515 if (pChunk != NULL)
516 Lines.insert(pChunk);
517 }
518
519 return pChunk;
520}
521
522
523
524/**
525 * Adds a file for this module.
526 * @returns Filename index used when adding linenumbers.
527 * @param pszFilename Pointer to filaname string.
528 */
529unsigned short kHllSrcEntry::addFile(
530 const char * pszFilename
531 )
532{
533 return addFile(pszFilename, strlen(pszFilename));
534}
535
536
537
538/**
539 * Adds a file for this module.
540 * @returns Filename index used when adding linenumbers.
541 * 0 on error.
542 * @param pachFilename Pointer to filaname string (not zero terminated).
543 * @param cchFilename Length of filename.
544 */
545unsigned short kHllSrcEntry::addFile(
546 const char * pachFilename,
547 int cchFilename
548 )
549{
550 assert(pachFilename != NULL);
551 assert(cchFilename < 256);
552 if (cchFilename >= 256)
553 cchFilename = 255;
554
555 /*
556 * Allocate more memory?
557 */
558 if ((cbFilenames + cchFilename + 1) >= cbFilenamesAllocated)
559 {
560 void *pv = realloc(pachFilenames, (size_t)cbFilenamesAllocated + 256);
561 assert(pv != NULL);
562 if (pv == NULL)
563 return 0;
564 pachFilenames = (char*)pv;
565 cbFilenamesAllocated += 256;
566 }
567
568
569 /*
570 * Add filename
571 */
572 pachFilenames[cbFilenames++] = (char)cchFilename;
573 memcpy(&pachFilenames[cbFilenames], pachFilename, cchFilename);
574 cbFilenames += cchFilename;
575
576 return (unsigned short)++cFilenames;
577}
578
579
580
581/**
582 * Write this entry to file.
583 * @returns Count of bytes written (on success).
584 * -3 Invalid offsets.
585 * -2 Seek error.
586 * -1 Write error.
587 * 0 No data written. Concidered as an error!
588 * @param phFile Filehandle.
589 */
590int kHllSrcEntry::write(FILE *phFile)
591{
592 HLLFIRSTENTRY FirstEntry;
593 HLLFILENAMEENTRY FilenameEntry;
594 int cb;
595 int cbWrote;
596 int cbWritten;
597
598 /*
599 * Filenames - if no filename present we'll add a dummy filename!
600 * First entry for the filenames.
601 * Filename entry header.
602 * Write filename entries.
603 */
604 FirstEntry.hll04.usLine = 0;
605 FirstEntry.hll04.uchType = 3; /* filename */
606 FirstEntry.hll04.uchReserved = 0;
607 FirstEntry.hll04.cEntries = (unsigned short)max(cFilenames, 1);
608 FirstEntry.hll04.iSeg = 0;
609 FirstEntry.hll04.u1.cbFileNameTable = cbFilenames != 0 ? cbFilenames : 8;
610 cb = sizeof(FirstEntry.hll04);
611 cbWritten = cbWrote = fwrite(&FirstEntry, 1, cb, phFile);
612 if (cb != cbWrote)
613 return -1;
614
615 FilenameEntry.cSourceFiles = max(cFilenames, 1);
616 FilenameEntry.offSource = 0;
617 FilenameEntry.cSourceRecords = 0;
618 cb = offsetof(HLLFILENAMEENTRY, cchName);
619 cbWritten += cbWrote = fwrite(&FilenameEntry, 1, cb, phFile);
620 if (cbWrote != cb)
621 return -1;
622
623 if (cbFilenames != 0)
624 {
625 cbWritten += cbWrote = fwrite(pachFilenames, 1, cbFilenames, phFile);
626 if (cbWrote != cbFilenames)
627 return -1;
628 }
629 else
630 { /* no filename - write dummy empty */
631 cbWritten += cbWrote = fwrite("\07dummy.c", 1, 8, phFile);
632 if (cbWrote != 8)
633 return -1;
634 }
635
636
637 /*
638 * Write linenumbers.
639 */
640 if (Lines.getFirst() != NULL)
641 {
642 cbWritten += cbWrote = kHllBaseEntry::writeList(phFile, Lines.getFirst());
643 if (cbWrote < 0)
644 return cbWrote;
645 }
646
647 return cbWritten;
648}
649
650
651
652/**
653 * Dumps the HLL entry to ph in a human readable fashion.
654 * @param ph Output file handle the dump is to be written to.
655 * @param cchIndent Number of char to indents the output dump.
656 */
657void kHllSrcEntry::dump(FILE *ph, int cchIndent)
658{
659 int i;
660 char * pach;
661
662 /*
663 * Write header with filename count.
664 * Write filenames.
665 * Dump linenumber list.
666 * Write footer with filename count.
667 */
668 fprintf(ph, "%*.s------- start kHllSrcEntry object 0x%08x --- %d -------\n",
669 cchIndent, "", this, cFilenames);
670
671 for (i = 0, pach = pachFilenames; i < cFilenames; i++, pach += 1 + *pach)
672 fprintf(ph, "%*.s%.2d - %.*s\n",
673 cchIndent, "",
674 i, *pach, pach + 1);
675
676 kHllBaseEntry::dumpList(ph, cchIndent + 4, Lines.getFirst());
677
678 fprintf(ph, "%*.s------- end kHllSrcEntry object 0x%08x --- %d -------\n",
679 cchIndent, "", this, cFilenames);
680}
681
682
683/**
684 * Create IDC (IDA Pro) calls which adds info contained in the entry
685 * to the ida pro database.
686 * !!!NOTE!!! THIS IS ONLY TO BE USED FOR YOUR OWN PROGRAMS!!!
687 * @param pFile Output file.
688 */
689void kHllSrcEntry::ida(kFile *pFile) throw(int)
690{
691 pFile->printf(" /* Source entry */\n");
692}
693
694
695
696
697
698/*******************************************************************************
699* *
700* kHllModuleEntry *
701* *
702* kHllModuleEntry *
703* *
704*******************************************************************************/
705
706
707
708
709
710
711
712/**
713 * Creates an HLL module entry.
714 * @param pszName Module name. (NULL is not allowed!)
715 * @param iLib Library index.
716 * @param cSegInfo Number of objects in the array.
717 * @param paSegInfo Pointer to an array of objects.
718 */
719kHllModuleEntry::kHllModuleEntry(
720 const char * pszName,
721 unsigned short iLib,
722 unsigned char cSegInfo/*= 0 */,
723 PHLLSEGINFO paSegInfo/*= NULL */
724 )
725: fValidOffsetsAndSizes(FALSE)
726{
727 int i;
728 int cchName;
729 PHLLSEGINFO pSegInfo;
730
731 /*
732 * Debug parameter validations.
733 */
734 assert(pszName != NULL);
735 assert(cSegInfo == 0 || paSegInfo != NULL);
736
737 /*
738 * Allocate data storage and fill HLL structure.
739 */
740 cchName = strlen(pszName);
741 cchName = min(cchName, 255);
742 pModule = (PHLLMODULE)malloc(sizeof(HLLMODULE) + cchName +
743 (sizeof(HLLSEGINFO) * max((cSegInfo - 1), 3)));
744 assert(pModule != NULL);
745 memset(pModule, 0, sizeof(*pModule));
746 pModule->cchName = (unsigned char)cchName;
747 memcpy(&pModule->achName[0], pszName, cchName);
748 pModule->chVerMajor = 4;
749 pModule->chVerMinor = 0;
750 pModule->cSegInfo = cSegInfo;
751 pModule->iLib = iLib;
752 pModule->usDebugStyle = HLL_MOD_STYLE;
753 pModule->overlay = 0;
754 pModule->pad = 0;
755
756 /* objects */
757 if (cSegInfo != 0)
758 {
759 pModule->SegInfo0.iObject = paSegInfo->iObject;
760 pModule->SegInfo0.cb = paSegInfo->cb;
761 pModule->SegInfo0.off = paSegInfo->off;
762
763 for (i = 1, pSegInfo = (PHLLSEGINFO)&pModule->achName[cchName]; i < cSegInfo; i++, pSegInfo++)
764 {
765 pSegInfo->iObject = paSegInfo[i].iObject;
766 pSegInfo->cb = paSegInfo[i].cb;
767 pSegInfo->off = paSegInfo[i].off;
768 }
769 }
770}
771
772
773/**
774 * Destructor - free storage.
775 */
776kHllModuleEntry::~kHllModuleEntry()
777{
778 if (pModule != NULL)
779 free(pModule);
780 pModule = NULL;
781}
782
783
784
785/**
786 * Adds an object to the module.
787 * @returns Success indicator.
788 * @param iObject LX Object index.
789 * @param off Offset into the object to the module data.
790 * @param cb Size of module data (in the object).
791 */
792BOOL kHllModuleEntry::addSegInfo(
793 unsigned short int iObject,
794 unsigned long off,
795 unsigned long cb
796 )
797{
798 assert(pModule != NULL);
799
800 /*
801 * Reallocate? (Note that we'll initially allocated space for 3 objects.)
802 */
803 if (pModule->cSegInfo >= 3)
804 {
805 void *pv = realloc(pModule, sizeof(HLLMODULE) + pModule->cchName
806 + (pModule->cSegInfo + 1) * sizeof(HLLSEGINFO));
807 assert(pv != NULL);
808 if (pv == NULL)
809 return FALSE;
810 pModule = (PHLLMODULE)pv;
811 }
812
813
814 /*
815 * Add module.
816 */
817 if (pModule->cSegInfo == 0)
818 {
819 pModule->SegInfo0.cb = cb;
820 pModule->SegInfo0.off = off;
821 pModule->SegInfo0.iObject = iObject;
822 }
823 else
824 {
825 PHLLSEGINFO pSegInfo = (PHLLSEGINFO)((pModule->cSegInfo - 1) * sizeof(HLLSEGINFO)
826 + &pModule->achName[pModule->cchName]);
827 pSegInfo->cb = cb;
828 pSegInfo->off = off;
829 pSegInfo->iObject = iObject;
830 }
831 pModule->cSegInfo++;
832
833 return TRUE;
834}
835
836
837
838/**
839 * Adds a public symbol.
840 * @returns Handle to the symbol. NULL on error.
841 * @param pszName Symbol name.
842 * @param off Offset into the LX Object of the symbol.
843 * @param iObject LX Object index.
844 * @param pvType Type handle. NULL if not type.
845 */
846const void * kHllModuleEntry::addPublicSymbol(
847 const char * pszName,
848 unsigned long int off,
849 unsigned short int iObject,
850 const void * pvType
851 )
852{
853 assert(pszName != NULL);
854 return addPublicSymbol(pszName, strlen(pszName), off, iObject, pvType);
855}
856
857
858
859/**
860 * Adds a public symbol.
861 * @returns Handle to the symbol. NULL on error.
862 * @param pachName Symbol name.
863 * @param cchName Name length.
864 * @param off Offset into the LX Object of the symbol.
865 * @param iObject LX Object index.
866 * @param pvType Type handle. NULL if not type.
867 */
868const void * kHllModuleEntry::addPublicSymbol(
869 const char * pachName,
870 int cchName,
871 unsigned long int off,
872 unsigned short int iObject,
873 const void * pvType
874 )
875{
876 kHllPubSymEntry * pEntry;
877
878 /* parameter assertion */
879 assert(pachName != NULL);
880
881 /*
882 * Create a public symbol entry
883 * Insert into it's list.
884 * Invalidate offsets.
885 */
886 pEntry = new kHllPubSymEntry(
887 pachName,
888 cchName,
889 off,
890 iObject,
891 (unsigned short)(pvType == NULL ? 0 : -1) //FIXME/TODO: Types->getIndex(pvType); check if 0 or -1.
892 );
893
894 PublicSymbols.insert(pEntry);
895
896 fValidOffsetsAndSizes = FALSE;
897
898 return pEntry;
899}
900
901
902
903
904/**
905 * Write this HLL entry to file.
906 * @returns Count of bytes written.
907 * -3 Invalid offsets.
908 * -2 Seek error.
909 * -1 Write error.
910 * @param phFile Filehandle.
911 * @param off Current offset into the HLL data.
912 * This is stored and used when making the directory
913 * entries for this module.
914 */
915int kHllModuleEntry::write(FILE *phFile, unsigned long off)
916{
917 int cch;
918 int cchToWrite;
919 int cchWritten = 0;
920
921 /* validate object state */
922 assert(pModule != NULL);
923
924 /*
925 * Write module HLL data.
926 */
927 offModule = off;
928 cchToWrite = offsetof(HLLMODULE, achName) + pModule->cchName + sizeof(HLLSEGINFO) * max(pModule->cSegInfo-1, 0);
929 cch = fwrite(pModule, 1, cchToWrite, phFile);
930 if (cch != cchToWrite)
931 return -1;
932 cchWritten += cch;
933 cbModule = cch;
934 off += cch;
935
936 /*
937 * Write the lists.
938 * Public Symbols
939 * Types
940 * Symbols
941 * Source
942 */
943 offPublicSymbols = off;
944 cbPublicSymbols = cch = kHllBaseEntry::writeList(phFile, PublicSymbols.getFirst());
945 if (cch < 0)
946 return cch;
947 cchWritten += cch;
948 off += cch;
949
950 /*
951 offTypes = off;
952 cbTypes = cch = kHllBaseEntry::writeList(phFile, Types.getFirst());
953 if (cch < 0)
954 return cch;
955 cchWritten += cch;
956 off += cch;
957
958
959 offSymbols = off;
960 cbSymbols = cch = kHllBaseEntry::writeList(phFile, Symbols.getFirst());
961 if (cch < 0)
962 return cch;
963 cchWritten += cch;
964 off += cch;
965 */
966
967 offSource = off;
968 cbSource = cch = Source.write(phFile);
969 if (cch < 0)
970 return cch;
971 cchWritten += cch;
972 off += cch;
973
974 /*
975 * Marks offsets and sizes valid and returns succesfully.
976 */
977 fValidOffsetsAndSizes = TRUE;
978 return cchWritten;
979}
980
981
982
983/**
984 * Writes the directory entries for this module to file.
985 * @returns Count of bytes written on success.
986 * -3 Invalid offsets.
987 * -2 Seek error.
988 * -1 Write error.
989 * 0 no data written (this is an error condition!)
990 * @param phFile Filehandle.
991 * @param iMod Index of this module.
992 */
993int kHllModuleEntry::writeDirEntries(FILE *phFile, unsigned short iMod)
994{
995 HLLDIRENTRY hllDirEntry;
996 int cch;
997 int cchWritten = 0;
998
999 /*
1000 * Check that offsets are valid!
1001 */
1002 assert(fValidOffsetsAndSizes);
1003 if (!fValidOffsetsAndSizes)
1004 return -3;
1005
1006 /*
1007 * Write Directory Entries.
1008 * Module.
1009 * Public Symbols. (if any)
1010 * Types. (if any)
1011 * Symbols. (if any)
1012 * Source. (if any)
1013 */
1014 hllDirEntry.usType = HLL_DE_MODULES;
1015 hllDirEntry.cb = cbModule;
1016 hllDirEntry.off = offModule;
1017 hllDirEntry.iMod = iMod;
1018 cch = fwrite(&hllDirEntry, 1, sizeof(hllDirEntry), phFile);
1019 if (cch != sizeof(hllDirEntry))
1020 return -1;
1021 cchWritten += cch;
1022
1023 if (cbPublicSymbols != 0)
1024 {
1025 hllDirEntry.usType = HLL_DE_PUBLICS;
1026 hllDirEntry.cb = cbPublicSymbols;
1027 hllDirEntry.off = offPublicSymbols;
1028 hllDirEntry.iMod = iMod;
1029 cch = fwrite(&hllDirEntry, 1, sizeof(hllDirEntry), phFile);
1030 if (cch != sizeof(hllDirEntry))
1031 return -1;
1032 cchWritten += cch;
1033 }
1034
1035 /*
1036 if (cbTypes > 0)
1037 {
1038 hllDirEntry.usType = HLL_DE_TYPES;
1039 hllDirEntry.cb = cbTypes;
1040 hllDirEntry.off = offTypes;
1041 hllDirEntry.iMod = iMod;
1042 cch = fwrite(&hllDirEntry, 1, sizeof(hllDirEntry), phFile);
1043 if (cch != sizeof(hllDirEntry))
1044 return -1;
1045 cchWritten += cch;
1046 }
1047
1048 if (cbSymbols > 0)
1049 {
1050 hllDirEntry.usType = HLL_DE_SYMBOLS;
1051 hllDirEntry.cb = cbSymbols;
1052 hllDirEntry.off = offSymbols;
1053 hllDirEntry.iMod = iMod;
1054 cch = fwrite(&hllDirEntry, 1, sizeof(hllDirEntry), phFile);
1055 if (cch != sizeof(hllDirEntry))
1056 return -1;
1057 cchWritten += cch;
1058 }
1059 */
1060
1061 if (cbSource != 0)
1062 {
1063 hllDirEntry.usType = HLL_DE_IBMSRC;
1064 hllDirEntry.cb = cbSource;
1065 hllDirEntry.off = offSource;
1066 hllDirEntry.iMod = iMod;
1067 cch = fwrite(&hllDirEntry, 1, sizeof(hllDirEntry), phFile);
1068 if (cch != sizeof(hllDirEntry))
1069 return -1;
1070 cchWritten += cch;
1071 }
1072
1073
1074 return cchWritten;
1075}
1076
1077
1078/**
1079 * Dumps this module entry to the given file.
1080 * @param ph Filehandle to dump this module entry to.
1081 */
1082void kHllModuleEntry::dump(FILE *ph)
1083{
1084 PHLLSEGINFO pSegInfo;
1085 int i;
1086
1087 fprintf(ph, " ------- start dumping kHllModuleEntry object 0x%08x -------\n", this);
1088
1089 /*
1090 * Dump HLL module entry.
1091 */
1092 fprintf(ph, " Modulename: %.*s Style: %.2s HLL ver: %d.%d #SegInfos: %d\n",
1093 pModule->cchName, pModule->achName,
1094 &pModule->usDebugStyle,
1095 pModule->chVerMajor, pModule->chVerMinor,
1096 pModule->cSegInfo
1097 );
1098
1099 for (i = 0, pSegInfo = &pModule->SegInfo0; i < pModule->cSegInfo; i++)
1100 {
1101 fprintf(ph, " Obj.no.: 0x%04x Offset: 0x%08x Size: 0x%08x(%d)\n",
1102 pSegInfo->iObject, pSegInfo->off, pSegInfo->cb, pSegInfo->cb);
1103
1104 /* next */
1105 if (i == 0)
1106 pSegInfo = (PHLLSEGINFO)&pModule->achName[pModule->cchName];
1107 else
1108 pSegInfo++;
1109 }
1110
1111
1112 /*
1113 * Dump the sub-entries.
1114 */
1115 kHllBaseEntry::dumpList(ph, 8, PublicSymbols.getFirst());
1116 /*
1117 kHllBaseEntry::dumpList(ph, 8, Types.getFirst());
1118 kHllBaseEntry::dumpList(ph, 8, Symbols.getFirst());
1119 kHllBaseEntry::dumpList(ph, 8, Source.getFirst());
1120 */
1121 Source.dump(ph, 8);
1122
1123
1124 fprintf(ph, " ------- end dumping kHllModuleEntry object 0x%08x -------\n", this);
1125}
1126
1127
1128/**
1129 * Create IDC (IDA Pro) calls which adds info contained in the entry
1130 * to the ida pro database.
1131 * !!!NOTE!!! THIS IS ONLY TO BE USED FOR YOUR OWN PROGRAMS!!!
1132 * @param pFile Output file.
1133 */
1134void kHllModuleEntry::ida(kFile *pFile) throw(int)
1135{
1136 pFile->printf(" /* kHllModuleEntry */\n");
1137
1138 /*
1139 * Write the sub-entries.
1140 */
1141 kHllBaseEntry::idaList(pFile, PublicSymbols.getFirst());
1142 /*
1143 kHllBaseEntry::dumpList(ph, 8, Types.getFirst());
1144 kHllBaseEntry::dumpList(ph, 8, Symbols.getFirst());
1145 kHllBaseEntry::dumpList(ph, 8, Source.getFirst());
1146 */
1147 Source.ida(pFile);
1148}
1149
1150
1151
1152
1153
1154
1155/*******************************************************************************
1156* *
1157* kHll *
1158* *
1159* kHll *
1160* *
1161*******************************************************************************/
1162
1163
1164
1165/**
1166 * Writes HLL debuginfo to the given file at the current position.
1167 * The file should be opened in write mode.
1168 * @returns Number of bytes written.
1169 * @param phFile Filehandle to output file. Starts writing at current pos.
1170 */
1171int kHll::write(FILE *phFile)
1172{
1173 HLLHDR hllHdr;
1174 HLLDIR hllDir;
1175 kHllModuleEntry * pModule;
1176 int cch; /* Number of bytes written to the file in an operation. */
1177 int cchWritten = 0; /* Number of bytes written to the file. */
1178 long int lPosStart; /* Starting position. */
1179 long int lPosDir; /* Directory position. */
1180 long int lPos; /* A file position. */
1181 int iMod; /* Module index (passed in to writeDirEntries) */
1182
1183 /* Get starting position. */
1184 lPosStart = ftell(phFile);
1185
1186 /* Make temporary header and write it */
1187 memcpy(hllHdr.achSignature, "NB04", 4);
1188 hllHdr.offDirectory = 0;
1189 cch = fwrite(&hllHdr, 1, sizeof(hllHdr), phFile);
1190 if (cch != sizeof(hllHdr))
1191 return -1;
1192 cchWritten += cch;
1193
1194
1195 /*
1196 * Start writing modules
1197 */
1198 pModule = (kHllModuleEntry*)Modules.getFirst();
1199 while (pModule != NULL)
1200 {
1201 cch = pModule->write(phFile, cchWritten);
1202 if (cch <= 0)
1203 return cch;
1204 cchWritten += cch;
1205 pModule = (kHllModuleEntry *)pModule->getNext();
1206 }
1207
1208
1209 /*
1210 * Write libraries.
1211 */
1212 //Not implemented yet - TODO/FIXME!
1213
1214
1215 /*
1216 * Write directory.
1217 * Make and write temporary directory header.
1218 * Write directory entries per module.
1219 * Write directory entry for libraries.
1220 * Remake and rewrite directory header. (correct cEntries)
1221 */
1222 lPosDir = ftell(phFile);
1223 hllDir.cEntries = 0;
1224 hllDir.cb = offsetof(HLLDIR, aEntries);
1225 hllDir.cbEntry = sizeof(HLLDIRENTRY);
1226 cch = fwrite(&hllDir, 1, offsetof(HLLDIR, aEntries), phFile);
1227 if (cch != offsetof(HLLDIR, aEntries))
1228 return -1;
1229 cchWritten += cch;
1230
1231 iMod = 1;
1232 pModule = (kHllModuleEntry*)Modules.getFirst();
1233 while (pModule != NULL)
1234 {
1235 cch = pModule->writeDirEntries(phFile, (unsigned short)iMod);
1236 if (cch == -1)
1237 return -1;
1238 cchWritten += cch;
1239 pModule = (kHllModuleEntry *)pModule->getNext();
1240 iMod++;
1241 }
1242
1243 //Library - TODO/FIXME
1244
1245 lPos = ftell(phFile);
1246 hllDir.cEntries = (lPos - lPosDir - offsetof(HLLDIR, aEntries)) / sizeof(HLLDIRENTRY);
1247 if (fseek(phFile, lPosDir, SEEK_SET) != 0)
1248 return -2;
1249 cch = fwrite(&hllDir, 1, offsetof(HLLDIR, aEntries), phFile);
1250 if (cch != offsetof(HLLDIR, aEntries))
1251 return -1;
1252
1253 /*
1254 * Rewrite HLL header (with correct directory offset).
1255 */
1256 hllHdr.offDirectory = lPosDir - lPosStart;
1257 if (fseek(phFile, lPosStart, SEEK_SET) != 0)
1258 return -2;
1259 cch = fwrite(&hllHdr, 1, sizeof(hllHdr), phFile);
1260 if (cch != sizeof(hllHdr))
1261 return -1;
1262
1263 /*
1264 * Hacking:
1265 * Writing an extra HLL header pointing to an non-existing directory
1266 * staring at the last byte of this header. This is present when linking
1267 * with ilink...
1268 */
1269 if (fseek(phFile, lPosStart + cchWritten, SEEK_SET) != 0)
1270 return -2;
1271 hllHdr.offDirectory = cchWritten + sizeof(hllHdr);
1272 cch = fwrite(&hllHdr, 1, sizeof(hllHdr), phFile);
1273 if (cch != sizeof(hllHdr))
1274 return -1;
1275 cchWritten += cch;
1276
1277 return cchWritten;
1278}
1279
1280
1281
1282/**
1283 * Constructor - Creates an empty HLL object.
1284 */
1285kHll::kHll()
1286{
1287}
1288
1289
1290/**
1291 * Creates a kHll object from debugdata found in a file (LX layout).
1292 * @param pFile Pointer to file object which the data is to be read from.
1293 * The file object is positioned at the start of the debuginfo.
1294 * start of the debuginfo.
1295 * Note. The file object is set to throw on errors.
1296 */
1297kHll::kHll(kFile *pFile) throw (int)
1298{
1299 long offHllHdr; /* Offset of debug data in file. */
1300 HLLHDR hllHdr; /* HLL data header. */
1301 HLLDIR hllDir; /* HLL directory (header only) */
1302 PHLLDIR pHllDir; /* HLL directory (all) */
1303 PHLLDIRENTRY pDirEntry; /* Current HLL directory entry. */
1304 int iDir;
1305
1306 /* auto throw */
1307 pFile->setThrowOnErrors();
1308
1309 /* Save file offset of debugdata. */
1310 offHllHdr = pFile->getPos();
1311
1312 /* Read HLL header */
1313 pFile->read(&hllHdr, sizeof(hllHdr));
1314 if (memcmp(hllHdr.achSignature, "NB04", 4) != 0)
1315 throw(ERROR_INVALID_EXE_SIGNATURE);
1316
1317 /*
1318 * Read the Directory head to get the directory size.
1319 * Allocate memory for the entire directory and read it.
1320 */
1321 pFile->readAt(&hllDir, sizeof(hllDir), offHllHdr + hllHdr.offDirectory);
1322 pHllDir = (PHLLDIR)malloc((size_t)(hllDir.cbEntry * hllDir.cEntries + hllDir.cb));
1323 if (pHllDir == NULL) throw(ERROR_NOT_ENOUGH_MEMORY);
1324 pFile->readAt(pHllDir, hllDir.cbEntry * hllDir.cEntries + hllDir.cb, offHllHdr + hllHdr.offDirectory);
1325
1326
1327 /*
1328 * Loop thru the directory entries and add them we have implemented.
1329 */
1330 unsigned long ulHLLVersion = 0; /* HLL version of the last module. */
1331 kHllModuleEntry *pCurMod = NULL; /* Current Module. */
1332 int iCurMod = 0; /* Current Module index (import). */
1333
1334 for (iDir = 0, pDirEntry = (PHLLDIRENTRY)((char*)pHllDir + hllDir.cb);
1335 iDir < pHllDir->cEntries;
1336 iDir++, pDirEntry = (PHLLDIRENTRY)((char*)pDirEntry + hllDir.cbEntry)
1337 )
1338 {
1339 CHAR szName[1024];
1340
1341 switch (pDirEntry->usType)
1342 {
1343 /*
1344 * Source filename(=Module) entry.
1345 */
1346 case HLL_DE_MODULES:
1347 {
1348 HLLMODULE hllMod;
1349 PHLLSEGINFO paSegInfo;
1350
1351 /*
1352 * Read hllmod, filename and seginfo table if any.
1353 */
1354 pFile->readAt(&hllMod, sizeof(hllMod), offHllHdr + pDirEntry->off);
1355 pFile->move(-1);
1356 pFile->read(szName, hllMod.cchName);
1357 szName[hllMod.cchName] = '\0';
1358 if (hllMod.cSegInfo != 0)
1359 {
1360 paSegInfo = (PHLLSEGINFO)malloc(sizeof(HLLSEGINFO) * hllMod.cSegInfo);
1361 if (pHllDir == NULL) throw(ERROR_NOT_ENOUGH_MEMORY);
1362 memcpy(paSegInfo, &hllMod.SegInfo0, sizeof(HLLSEGINFO));
1363 if (hllMod.cSegInfo > 1)
1364 pFile->read(&paSegInfo[1], sizeof(HLLSEGINFO) * (hllMod.cSegInfo - 1));
1365 }
1366 else
1367 paSegInfo = NULL;
1368
1369 /*
1370 * Add the module and save module data for later use.
1371 * Cleanup seginfo.
1372 */
1373 pCurMod = this->addModule(szName, hllMod.cchName, NULL, hllMod.cSegInfo, paSegInfo);
1374 iCurMod = pDirEntry->iMod;
1375 ulHLLVersion = HLLMAKEVER(hllMod.chVerMajor, hllMod.chVerMinor);
1376
1377 if (paSegInfo != NULL)
1378 free(paSegInfo);
1379 break;
1380 }
1381
1382
1383 /*
1384 * Public symbols
1385 */
1386 case HLL_DE_PUBLICS:
1387 {
1388 HLLPUBLICSYM pubSym;
1389
1390 if (pCurMod == NULL || iCurMod != pDirEntry->iMod)
1391 {
1392 fprintf(stderr, "hmm. iMod in public entry not equal to current module\n");
1393 break;
1394 }
1395
1396 fprintf(stderr, "HLL_DE_PUBLICS\n");
1397 pFile->set(pDirEntry->off + offHllHdr);
1398 while (pFile->getPos() - pDirEntry->off - offHllHdr < pDirEntry->cb)
1399 {
1400 pFile->read(&pubSym, sizeof(pubSym) - 1);
1401 pFile->read(szName, pubSym.cchName);
1402 szName[pubSym.cchName] = '\0';
1403
1404 fprintf(stderr, "HLL_DE_PUBLICS\n");
1405 pCurMod->addPublicSymbol(szName,
1406 pubSym.cchName,
1407 pubSym.off,
1408 pubSym.iObject,
1409 (void*)pubSym.iType);
1410 }
1411 }
1412
1413 case HLL_DE_TYPES: /* Types */
1414 fprintf(stderr, "Types directory entry\n");
1415 break;
1416
1417 case HLL_DE_SYMBOLS: /* Symbols */
1418 fprintf(stderr, "Symbols directory entry\n");
1419 break;
1420
1421 case HLL_DE_LIBRARIES: /* Libraries */
1422 fprintf(stderr, "Libraries directory entry\n");
1423 break;
1424
1425 case HLL_DE_SRCLINES: /* Line numbers - (IBM C/2 1.1) */
1426 fprintf(stderr, "SRCLINES directory entry\n");
1427 break;
1428
1429 case HLL_DE_SRCLNSEG: /* Line numbers - (MSC 6.00) */
1430 fprintf(stderr, "SRCLNSEG directory entry\n");
1431 break;
1432
1433 case HLL_DE_IBMSRC: /* Line numbers - (IBM HLL) */
1434 fprintf(stderr, "IBMSRC directory entry\n");
1435 break;
1436
1437 default:
1438 /* Unsupported directory entry - ignore */
1439 fprintf(stderr, "Unsupported directory entry %d\n", pDirEntry->usType);
1440 break;
1441 }
1442 }
1443
1444 /* cleanup */
1445 free(pHllDir);
1446}
1447
1448
1449/**
1450 * Destructor.
1451 */
1452kHll::~kHll()
1453{
1454}
1455
1456
1457
1458/**
1459 * Adds a module.
1460 * @returns Pointer to the module object added. NULL on error.
1461 * @param pszName Module name
1462 * @param pvLib Library module handle.
1463 * @param cSegInfo Number of objects in the array.
1464 * @param paSegInfo Pointer to an array of objects.
1465 */
1466kHllModuleEntry * kHll::addModule(
1467 const char * pszName,
1468 const void * pvLib,
1469 unsigned cSegInfo,
1470 PHLLSEGINFO paSegInfo)
1471{
1472 kHllModuleEntry * pEntry;
1473 assert(pszName != NULL);
1474
1475 pEntry = new kHllModuleEntry(
1476 pszName,
1477 (unsigned short)(pvLib == NULL ? 0 : -1), //FIXME/TODO: Libs->getIndex(pvLib); check if 0 or -1;
1478 (unsigned char) cSegInfo,
1479 paSegInfo);
1480
1481 Modules.insert(pEntry);
1482 return pEntry;
1483}
1484
1485
1486
1487/**
1488 * Adds a module.
1489 * @returns Pointer to the module object added. NULL on error.
1490 * @param pachName Module name
1491 * @param cchName Length of modulename
1492 * @param pvLib Library module handle.
1493 * @param cSegInfo Number of objects in the array.
1494 * @param paSegInfo Pointer to an array of objects.
1495 */
1496kHllModuleEntry * kHll::addModule(
1497 const char * pachName,
1498 unsigned cchName,
1499 const void * pvLib,
1500 unsigned cSegInfo,
1501 PHLLSEGINFO paSegInfo)
1502{
1503 char szModName[256];
1504 kHllModuleEntry * pEntry;
1505 assert(pachName != NULL && cchName != 0);
1506
1507 szModName[0] = '\0';
1508 strncat(szModName, pachName, min(cchName, 255));
1509 pEntry = new kHllModuleEntry(
1510 szModName,
1511 (unsigned short)(pvLib == NULL ? 0 : -1), //FIXME/TODO: Libs->getIndex(pvLib); check if 0 or -1;
1512 (unsigned char)cSegInfo,
1513 paSegInfo);
1514
1515 Modules.insert(pEntry);
1516 return pEntry;
1517}
1518
1519
1520/**
1521 * Dump the object in a human readable fashion to stdout.
1522 */
1523void kHll::dump()
1524{
1525 FILE *ph = stdout;
1526
1527 fprintf(ph,
1528 "------- start dumping kHll object 0x%08x --- %d modules -------\n",
1529 this, Modules.getCount());
1530
1531 kHllModuleEntry * pMod = Modules.getFirst();
1532 while (pMod != NULL)
1533 {
1534 /* Dump it */
1535 pMod->dump(ph);
1536
1537 /* Next module */
1538 pMod = (kHllModuleEntry*)pMod->getNext();
1539 }
1540
1541 fprintf(ph,
1542 "------- end dumping kHll object 0x%08x --- %d modules -------\n",
1543 this, Modules.getCount());
1544}
1545
1546
1547/**
1548 * Create IDC (IDA Pro) scripts which adds debuginfo to the ida pro database.
1549 * !!!NOTE!!! THIS IS ONLY TO BE USED FOR YOUR OWN PROGRAMS!!!
1550 * @param pFile Output file.
1551 */
1552void kHll::ida(kFile *pFile) throw(int)
1553{
1554 pFile->printf("/* !!!NOTE!!! THIS IS ONLY TO BE USED FOR YOUR OWN PROGRAMS!!!*/\n"
1555 "#include <idc.idc>\n"
1556 "static main() {\n"
1557 " auto ea;\n"
1558 );
1559
1560 kHllModuleEntry * pMod = Modules.getFirst();
1561 while (pMod != NULL)
1562 {
1563 /* Dump it */
1564 pMod->ida(pFile);
1565
1566 /* Next module */
1567 pMod = (kHllModuleEntry*)pMod->getNext();
1568 }
1569
1570 pFile->printf("}\n\n");
1571}
1572
1573
1574
1575/**
1576 * Creates a kHll object of the HLL debug information found a LX file.
1577 * (An empty object is returned when no info is found.)
1578 * @return Pointer to kHll object on success.
1579 * NULL on error. Message is printed.
1580 */
1581kHll * kHll::readLX(
1582 const char *pszFilename
1583 )
1584{
1585 try
1586 {
1587 struct exe_hdr ehdr;
1588 struct e32_exe e32;
1589 long offLXHdr;
1590
1591 kFile file(pszFilename);
1592
1593 /*
1594 * Find and read the LX header.
1595 */
1596 file.read(&ehdr, sizeof(ehdr));
1597 if (ehdr.e_magic == EMAGIC)
1598 offLXHdr = ehdr.e_lfanew;
1599 else
1600 offLXHdr = 0;
1601 file.readAt(&e32, sizeof(e32), offLXHdr);
1602 if (*(PSHORT)&e32.e32_magic[0] != E32MAGIC)
1603 throw (ERROR_INVALID_EXE_SIGNATURE);
1604
1605 /*
1606 * Is there any debug info in this LX header?
1607 */
1608 if (e32.e32_debuginfo != 0UL && e32.e32_debuglen != 0UL
1609 && file.set(e32.e32_debuginfo))
1610 return new kHll(&file);
1611 else
1612 return new kHll();
1613 }
1614 catch (int iOS2Error)
1615 {
1616 fprintf(stderr, "failed to create kHll object for file %s. Failed with OS2 error %d.\n",
1617 pszFilename, iOS2Error);
1618 }
1619 return NULL;
1620}
1621
1622
1623/**
1624 * Writes the HLL info to a file. (Not LX?)
1625 * @returns Success indicator.
1626 * @param pszFilename Name of the output file.
1627 * @remark IMPORTANT! This is mostly for debugging!
1628 * It completely overwrites the file if it exists!
1629 */
1630BOOL kHll::write(
1631 const char *pszFilename
1632 )
1633{
1634 FILE * phFile;
1635
1636 phFile = fopen(pszFilename, "wb");
1637 if (phFile != NULL)
1638 {
1639 int cch = write(phFile);
1640 if (cch > 0)
1641 {
1642 fclose(phFile);
1643 return TRUE;
1644 }
1645 else
1646 fprintf(stderr, "write failed with cch=%d\n", cch);
1647 fclose(phFile);
1648 }
1649
1650 return FALSE;
1651}
1652
1653
1654
1655/**
1656 * Writes the HLL info to a file. (Not LX?)
1657 * Failes if there is debuginfo in the file.
1658 * No backup is made. (sorry)
1659 * @returns OS2 return code.
1660 * @param pszFilename Name of the output file.
1661 */
1662APIRET kHll::writeToLX(
1663 const char *pszFilename
1664 )
1665{
1666 APIRET rc;
1667 FILE * phFile;
1668
1669 phFile = fopen(pszFilename, "rb+");
1670 if (phFile != NULL)
1671 {
1672 struct exe_hdr ehdr;
1673 struct e32_exe e32;
1674 int cch;
1675 long lPosLXHdr;
1676 long cbLXFile;
1677
1678 /*
1679 * Read exe header
1680 */
1681 cch = fread(&ehdr, 1, sizeof(ehdr), phFile);
1682 if (cch == sizeof(ehdr))
1683 {
1684 cbLXFile = fsize(phFile);
1685 if (ehdr.e_magic == EMAGIC)
1686 lPosLXHdr = ehdr.e_lfanew;
1687 else
1688 lPosLXHdr = 0;
1689 if (fseek(phFile, lPosLXHdr, SEEK_SET) == 0)
1690 {
1691 cch = fread(&e32, 1, sizeof(e32), phFile);
1692 if (cch == sizeof(e32))
1693 {
1694 if (*(unsigned short*)&e32.e32_magic[0] == E32MAGIC)
1695 {
1696 /*
1697 * Found exeheader.
1698 * Check if there is any debug info.
1699 */
1700 if ((e32.e32_debuginfo == 0 && e32.e32_debuginfo == 0)
1701 || (cbLXFile == e32.e32_debuglen + e32.e32_debuginfo)
1702 )
1703 {
1704 long lPosDebug;
1705
1706 if (e32.e32_debuginfo != 0 && e32.e32_debuglen != 0)
1707 lPosDebug = e32.e32_debuginfo;
1708 else
1709 lPosDebug = (cbLXFile + 0x400) & ~0x1FF; //try do some alignment.
1710
1711 /*
1712 * Go to debug info position in the file and write debug info.
1713 */
1714 if (fseek(phFile, lPosDebug, SEEK_SET) == 0)
1715 {
1716 /*
1717 * Write the HLL data to disk.
1718 */
1719 cch = write(phFile);
1720 if (cch > 0)
1721 {
1722 /*
1723 * Update exeheader.
1724 */
1725 e32.e32_debuglen = cch;
1726 e32.e32_debuginfo = lPosDebug;
1727 if (fseek(phFile, lPosLXHdr, SEEK_SET) == 0)
1728 {
1729 /*
1730 * Write the updated header to disk.
1731 */
1732 cch = fwrite(&e32, 1, sizeof(e32), phFile);
1733 if (cch == sizeof(e32))
1734 rc = NO_ERROR;
1735 else
1736 rc = ERROR_WRITE_FAULT;
1737 }
1738 else
1739 rc = ERROR_SEEK;
1740 }
1741 else
1742 {
1743 fprintf(stderr, "error - write failed with cch=%d\n", cch);
1744 rc = ERROR_WRITE_FAULT;
1745 }
1746 }
1747 else
1748 rc = ERROR_SEEK;
1749 }
1750 else
1751 {
1752 fprintf(stderr, "error - debuginfo exists\n");
1753 rc = ERROR_BAD_EXE_FORMAT;
1754 }
1755
1756 }
1757 else
1758 rc = ERROR_INVALID_EXE_SIGNATURE;
1759 }
1760 else
1761 rc = ERROR_BAD_EXE_FORMAT;
1762 }
1763 else
1764 rc = ERROR_BAD_EXE_FORMAT;
1765 }
1766 else
1767 rc = ERROR_READ_FAULT;
1768
1769 fclose(phFile);
1770 }
1771 else
1772 rc = ERROR_ACCESS_DENIED; //?
1773
1774
1775 return rc;
1776}
1777
1778
1779/**
1780 * Find the size of a file.
1781 * @returns Size of file. -1 on error.
1782 * @param phFile File handle.
1783 */
1784signed long fsize(FILE *phFile)
1785{
1786 long ipos;
1787 signed long cb;
1788
1789 if ((ipos = ftell(phFile)) < 0
1790 ||
1791 fseek(phFile, 0, SEEK_END) != 0
1792 ||
1793 (cb = ftell(phFile)) < 0
1794 ||
1795 fseek(phFile, ipos, SEEK_SET) != 0
1796 )
1797 cb = -1;
1798 return cb;
1799}
1800
1801
1802
1803#if 1
1804/**
1805 * Debugging entry point for the readLX constructor.
1806 * It reads this executable and dumps it.
1807 * @param argc Argument count.
1808 * @param argv Argument vector - only the first entry is used.
1809 */
1810void main(int argc, char **argv)
1811{
1812 kHll *pHll;
1813
1814 /* read last argument */
1815 pHll = kHll::readLX(argv[argc-1]);
1816 if (pHll)
1817 {
1818 printf("Successfully read %s\n", argv[0]);
1819 pHll->dump();
1820 kFile kidc("dbg.idc", FALSE);
1821 pHll->ida(&kidc);
1822 }
1823 argc = argc;
1824 delete (pHll);
1825}
1826
1827#ifdef __IBMCPP__
1828#include "klist.cpp"
1829#endif
1830
1831#endif
Note: See TracBrowser for help on using the repository browser.