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

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

* empty log message *

File size: 34.9 KB
Line 
1/* $Id: kHll.cpp,v 1.11 2000-04-07 17:20:24 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#include <stdio.h>
32#include <string.h>
33#include <stddef.h>
34#include <stdlib.h>
35#include <assert.h>
36
37#include "hll.h"
38#include "kList.h"
39#include "kHll.h"
40
41
42/*******************************************************************************
43* Internal Functions *
44*******************************************************************************/
45signed long fsize(FILE *phFile);
46
47
48
49
50/*******************************************************************************
51* *
52* kHllBaseEntry *
53* *
54* kHllBaseEntry *
55* *
56*******************************************************************************/
57
58
59/**
60 * Writes a list to disk.
61 * @returns Number of bytes written.
62 * @returns Count of bytes written on success. (includes 0)
63 * -3 Invalid offsets.
64 * -2 Seek error.
65 * -1 Write error.
66 * @param phFile Output filehandle.
67 * @param pEntry Pointer to the start of the list which is to be written.
68 */
69int kHllBaseEntry::writeList(FILE *phFile, kHllBaseEntry *pEntry)
70{
71 int cch;
72 int cchWritten = 0;
73
74 /*
75 * Loop thru the list and write all the entries to disk.
76 */
77 while (pEntry != NULL)
78 {
79 cchWritten += cch = pEntry->write(phFile);
80 if (cch < 0)
81 return cch;
82 if (cch == 0)
83 return -1;
84 pEntry = (kHllBaseEntry*)pEntry->getNext();
85 }
86
87 return cchWritten;
88}
89
90
91
92
93
94
95/*******************************************************************************
96* *
97* kHllPubSymEntry *
98* *
99* kHllPubSymEntry *
100* *
101*******************************************************************************/
102
103
104
105/**
106 * Creates an HLL public symbol entry.
107 * @param pachName Symbol name.
108 * @param cchName Length of symbol name.
109 * @param off Offset into the object.
110 * @param iObject LX Object index.
111 * @param iType Type index. (index into type table)
112 */
113kHllPubSymEntry::kHllPubSymEntry(
114 const char * pachName,
115 int cchName,
116 unsigned long off,
117 unsigned short iObject,
118 unsigned short iType
119 )
120{
121 pPubSym = (PHLLPUBLICSYM)malloc(cchName + sizeof(HLLPUBLICSYM));
122 assert(pPubSym != NULL);
123
124 pPubSym->cchName = cchName;
125 pPubSym->achName[0] = '\0';
126 strncat((char*)&pPubSym->achName[0], pachName, cchName);
127 pPubSym->off = off;
128 pPubSym->iObject = iObject;
129 pPubSym->iType = iType;
130}
131
132
133
134/**
135 * Destructor.
136 */
137kHllPubSymEntry::~kHllPubSymEntry()
138{
139 if (pPubSym != NULL)
140 free(pPubSym);
141 pPubSym = NULL;
142}
143
144
145
146/**
147 * Write this entry to file.
148 * @returns Count of bytes written (on success).
149 * -3 Invalid offsets.
150 * -2 Seek error.
151 * -1 Write error.
152 * 0 No data written. Concidered as an error!
153 * @param phFile Filehandle.
154 */
155int kHllPubSymEntry::write(FILE *phFile)
156{
157 assert(pPubSym != NULL);
158 return fwrite(pPubSym,
159 1,
160 offsetof(HLLPUBLICSYM, achName) + pPubSym->cchName,
161 phFile);
162}
163
164
165
166
167
168
169
170/*******************************************************************************
171* *
172* kHllLineNumberChunk *
173* *
174* kHllLineNumberChunk *
175* *
176*******************************************************************************/
177
178
179
180
181 int cLines;
182 PHLLLINENUMBERENTRY paLines;
183 HLLFIRSTENTRY FirstEntry;
184
185/**
186 * Constructor.
187 * @param iSeg Segment number for these linenumbers.
188 * @param offBase Base offset for all line number offsets. (defaults to 0)
189 */
190kHllLineNumberChunk::kHllLineNumberChunk(
191 unsigned short int iSeg,
192 unsigned long int offBase /*= 0*/
193 )
194{
195 memset(&FirstEntry, 0, sizeof(FirstEntry));
196 FirstEntry.hll04.iSeg = iSeg;
197 FirstEntry.hll04.u1.offBase = offBase;
198 FirstEntry.hll04.uchType = 0;
199}
200
201
202
203/**
204 * Destructor.
205 */
206kHllLineNumberChunk::~kHllLineNumberChunk()
207{
208 if (paLines != NULL)
209 free(paLines);
210 paLines = 0;
211 FirstEntry.hll04.cEntries = 0;
212}
213
214
215
216/**
217 * Adds a line information.
218 * @returns Success indicator.
219 * @param iusFile File index.
220 * @param usLine Line number
221 * @param off Offset into object.
222 */
223BOOL kHllLineNumberChunk::addLineInfo(
224 unsigned short int iusFile,
225 unsigned short int usLine,
226 unsigned long int off
227 )
228{
229 /*
230 * Allocate more memory?
231 */
232 if (FirstEntry.hll04.cEntries % 20 == 0)
233 {
234 void *pv = realloc(paLines, (FirstEntry.hll04.cEntries + 20) * sizeof(paLines[0].hll04));
235 assert(pv != NULL);
236 if (pv == NULL)
237 return FALSE;
238 paLines = (PHLLLINENUMBERENTRY)pv;
239 }
240
241 /*
242 * Add line info entry.
243 */
244 paLines[FirstEntry.hll04.cEntries].hll04.iusSourceFile = iusFile;
245 paLines[FirstEntry.hll04.cEntries].hll04.off = off;
246 paLines[FirstEntry.hll04.cEntries].hll04.usLine = usLine;
247 FirstEntry.hll04.cEntries++;
248
249 return FALSE;
250}
251
252
253/**
254 * Write this entry to file.
255 * @returns Count of bytes written (on success).
256 * -3 Invalid offsets.
257 * -2 Seek error.
258 * -1 Write error.
259 * 0 No data written. Concidered as an error!
260 * @param phFile Filehandle.
261 */
262int kHllLineNumberChunk::write(FILE *phFile)
263{
264 int cb;
265 int cbWritten;
266
267 /*
268 * First entry
269 */
270 cb = sizeof(paLines[0])*FirstEntry.hll04.cEntries;
271 cbWritten = fwrite(&FirstEntry, 1, cb, phFile);
272 if (cbWritten != cb)
273 return -1;
274
275 /*
276 * Line array.
277 */
278 cb = sizeof(paLines[0])*FirstEntry.hll04.cEntries;
279 cbWritten = fwrite(paLines, 1, cb, phFile);
280 if (cbWritten != cb)
281 return -1;
282
283 return cbWritten + sizeof(FirstEntry.hll04);
284}
285
286
287
288
289
290/*******************************************************************************
291* *
292* kHllSrcEntry *
293* *
294* kHllSrcEntry *
295* *
296*******************************************************************************/
297
298
299
300
301
302/**
303 * Constructor.
304 */
305kHllSrcEntry::kHllSrcEntry()
306 :
307 cFilenames(0),
308 pachFilenames(NULL),
309 cbFilenames(0),
310 cbFilenamesAllocated(0)
311{
312}
313
314
315/**
316 * Destructor.
317 */
318kHllSrcEntry::~kHllSrcEntry()
319{
320 if (pachFilenames != NULL)
321 free(pachFilenames);
322 pachFilenames = NULL;
323 cFilenames = cbFilenames = cbFilenamesAllocated = 0;
324}
325
326
327
328/**
329 * Add/queries a Linenumber chunk.
330 * A linenumber chunk is a collection of linenumber information for a
331 * module segement.
332 * @returns Pointer to linenumber chunk which you may add linenumber info to.
333 * NULL on failiure.
334 * @param iSeg Segment number for these linenumbers.
335 * @param offBase Base offset for all line number offsets. (defaults to 0)
336 */
337kHllLineNumberChunk *
338 kHllSrcEntry::addLineNumberChunk(
339 unsigned short int iSeg,
340 unsigned long int offBase/* = 0*/
341 )
342{
343 kHllLineNumberChunk *pChunk;
344
345 /*
346 * Try find existing chunk.
347 */
348 pChunk = Lines.getFirst();
349 while (pChunk != NULL && pChunk->getSeg() != iSeg)
350 pChunk = (kHllLineNumberChunk*)pChunk->getNext();
351
352 /*
353 * If not found, then create a new one and add it to the list.
354 */
355 if (pChunk != NULL)
356 {
357 pChunk = new kHllLineNumberChunk(iSeg, offBase);
358 assert(pChunk != NULL);
359 if (pChunk != NULL)
360 Lines.insert(pChunk);
361 }
362
363 return pChunk;
364}
365
366
367
368/**
369 * Adds a file for this module.
370 * @returns Filename index used when adding linenumbers.
371 * @param pszFilename Pointer to filaname string.
372 */
373unsigned short kHllSrcEntry::addFile(
374 const char * pszFilename
375 )
376{
377 return addFile(pszFilename, strlen(pszFilename));
378}
379
380
381
382/**
383 * Adds a file for this module.
384 * @returns Filename index used when adding linenumbers.
385 * 0 on error.
386 * @param pachFilename Pointer to filaname string (not zero terminated).
387 * @param cchFilename Length of filename.
388 */
389unsigned short kHllSrcEntry::addFile(
390 const char * pachFilename,
391 int cchFilename
392 )
393{
394 assert(pachFilename != NULL);
395 assert(cchFilename < 256);
396 if (cchFilename >= 256)
397 cchFilename = 255;
398
399 /*
400 * Allocate more memory?
401 */
402 if ((cbFilenames + cchFilename + 1) >= cbFilenamesAllocated)
403 {
404 void *pv = realloc(pachFilenames, cbFilenamesAllocated + 256);
405 assert(pv != NULL);
406 if (pv == NULL)
407 return 0;
408 pachFilenames = (char*)pv;
409 cbFilenamesAllocated += 256;
410 }
411
412
413 /*
414 * Add filename
415 */
416 pachFilenames[cbFilenames++] = cchFilename;
417 memcpy(&pachFilenames[cbFilenames], pachFilename, cchFilename);
418 cbFilenames += cchFilename;
419
420 return ++cFilenames;
421}
422
423
424
425/**
426 * Write this entry to file.
427 * @returns Count of bytes written (on success).
428 * -3 Invalid offsets.
429 * -2 Seek error.
430 * -1 Write error.
431 * 0 No data written. Concidered as an error!
432 * @param phFile Filehandle.
433 */
434int kHllSrcEntry::write(FILE *phFile)
435{
436 HLLFIRSTENTRY FirstEntry;
437 HLLFILENAMEENTRY FilenameEntry;
438 int cb;
439 int cbWrote;
440 int cbWritten;
441
442 /*
443 * Filenames - if no filename present we'll add a dummy filename!
444 * First entry for the filenames.
445 * Filename entry header.
446 * Write filename entries.
447 */
448 FirstEntry.hll04.usLine = 0;
449 FirstEntry.hll04.uchType = 3; /* filename */
450 FirstEntry.hll04.uchReserved = 0;
451 FirstEntry.hll04.cEntries = max(cFilenames, 1);
452 FirstEntry.hll04.iSeg = 0;
453 FirstEntry.hll04.u1.cbFileNameTable = cbFilenames > 0 ? cbFilenames : 8;
454 cb = sizeof(FirstEntry.hll04);
455 cbWritten = cbWrote = fwrite(&FirstEntry, 1, cb, phFile);
456 if (cb != cbWrote)
457 return -1;
458
459 FilenameEntry.cSourceFiles = max(cFilenames, 1);
460 FilenameEntry.offSource = 0;
461 FilenameEntry.cSourceRecords = 0;
462 cb = offsetof(HLLFILENAMEENTRY, cchName);
463 cbWritten += cbWrote = fwrite(&FilenameEntry, 1, cb, phFile);
464 if (cbWrote != cb)
465 return -1;
466
467 if (cbFilenames > 0)
468 {
469 cbWritten += cbWrote = fwrite(pachFilenames, 1, cbFilenames, phFile);
470 if (cbWrote != cbFilenames)
471 return -1;
472 }
473 else
474 { /* no filename - write dummy empty */
475 cbWritten += cbWrote = fwrite("\07dummy.c", 1, 8, phFile);
476 if (cbWrote != 8)
477 return -1;
478 }
479
480
481 /*
482 * Write linenumbers.
483 */
484 if (Lines.getFirst() != NULL)
485 {
486 cbWritten += cbWrote = kHllBaseEntry::writeList(phFile, Lines.getFirst());
487 if (cbWrote < 0)
488 return cbWrote;
489 }
490
491 return cbWritten;
492}
493
494
495
496
497
498/*******************************************************************************
499* *
500* kHllModuleEntry *
501* *
502* kHllModuleEntry *
503* *
504*******************************************************************************/
505
506
507
508
509
510
511
512/**
513 * Creates an HLL module entry.
514 * @param pszName Module name. (NULL is not allowed!)
515 * @param iLib Library index.
516 * @param cSegInfo Number of objects in the array.
517 * @param paSegInfo Pointer to an array of objects.
518 */
519kHllModuleEntry::kHllModuleEntry(
520 const char * pszName,
521 unsigned short iLib,
522 unsigned char cSegInfo/*= 0 */,
523 PHLLSEGINFO paSegInfo/*= NULL */
524 )
525: fValidOffsetsAndSizes(FALSE)
526{
527 int i;
528 int cchName;
529 PHLLSEGINFO pSegInfo;
530
531 /*
532 * Debug parameter validations.
533 */
534 assert(pszName != NULL);
535 assert(cSegInfo == 0 || paSegInfo != NULL);
536
537 /*
538 * Allocate data storage and fill HLL structure.
539 */
540 cchName = strlen(pszName);
541 pModule = (PHLLMODULE)malloc(sizeof(HLLMODULE) + cchName +
542 sizeof(HLLSEGINFO) * max((cSegInfo - 1), 3));
543 assert(pModule != NULL);
544 memset(pModule, 0, sizeof(*pModule));
545 pModule->cchName = cchName;
546 strcpy((char*)&pModule->achName[0], pszName);
547 pModule->chVerMajor = 4;
548 pModule->chVerMinor = 0;
549 pModule->cSegInfo = cSegInfo;
550 pModule->iLib = iLib;
551 pModule->usDebugStyle = HLL_MOD_STYLE;
552 pModule->overlay = 0;
553 pModule->pad = 0;
554
555 /* objects */
556 if (cSegInfo > 0)
557 {
558 pModule->SegInfo0.iObject = paSegInfo->iObject;
559 pModule->SegInfo0.cb = paSegInfo->cb;
560 pModule->SegInfo0.off = paSegInfo->off;
561
562 for (i = 1, pSegInfo = (PHLLSEGINFO)&pModule->achName[cchName]; i < cSegInfo; i++, pSegInfo++)
563 {
564 pSegInfo->iObject = paSegInfo[i].iObject;
565 pSegInfo->cb = paSegInfo[i].cb;
566 pSegInfo->off = paSegInfo[i].off;
567 }
568 }
569}
570
571
572/**
573 * Destructor - free storage.
574 */
575kHllModuleEntry::~kHllModuleEntry()
576{
577 if (pModule != NULL)
578 free(pModule);
579 pModule = NULL;
580}
581
582
583
584/**
585 * Adds an object to the module.
586 * @returns Success indicator.
587 * @param iObject LX Object index.
588 * @param off Offset into the object to the module data.
589 * @param cb Size of module data (in the object).
590 */
591BOOL kHllModuleEntry::addSegInfo(
592 unsigned short int iObject,
593 unsigned long off,
594 unsigned long cb
595 )
596{
597 assert(pModule != NULL);
598
599 /*
600 * Reallocate? (Note that we'll initially allocated space for 3 objects.)
601 */
602 if (pModule->cSegInfo >= 3)
603 {
604 void *pv = realloc(pModule, sizeof(HLLMODULE) + pModule->cchName
605 + (pModule->cSegInfo + 1) * sizeof(HLLSEGINFO));
606 assert(pv != NULL);
607 if (pv == NULL)
608 return FALSE;
609 pModule = (PHLLMODULE)pv;
610 }
611
612
613 /*
614 * Add module.
615 */
616 if (pModule->cSegInfo == 0)
617 {
618 pModule->SegInfo0.cb = cb;
619 pModule->SegInfo0.off = off;
620 pModule->SegInfo0.iObject = iObject;
621 }
622 else
623 {
624 PHLLSEGINFO pSegInfo = (PHLLSEGINFO)((pModule->cSegInfo - 1) * sizeof(HLLSEGINFO)
625 + &pModule->achName[pModule->cchName]);
626 pSegInfo->cb = cb;
627 pSegInfo->off = off;
628 pSegInfo->iObject = iObject;
629 }
630 pModule->cSegInfo++;
631
632 return TRUE;
633}
634
635
636
637/**
638 * Adds a public symbol.
639 * @returns Handle to the symbol. NULL on error.
640 * @param pszName Symbol name.
641 * @param off Offset into the LX Object of the symbol.
642 * @param iObject LX Object index.
643 * @param pvType Type handle. NULL if not type.
644 */
645const void * kHllModuleEntry::addPublicSymbol(
646 const char * pszName,
647 unsigned long int off,
648 unsigned short int iObject,
649 const void * pvType
650 )
651{
652 assert(pszName != NULL);
653 return addPublicSymbol(pszName, strlen(pszName), off, iObject, pvType);
654}
655
656
657
658/**
659 * Adds a public symbol.
660 * @returns Handle to the symbol. NULL on error.
661 * @param pachName Symbol name.
662 * @param cchName Name length.
663 * @param off Offset into the LX Object of the symbol.
664 * @param iObject LX Object index.
665 * @param pvType Type handle. NULL if not type.
666 */
667const void * kHllModuleEntry::addPublicSymbol(
668 const char * pachName,
669 int cchName,
670 unsigned long int off,
671 unsigned short int iObject,
672 const void * pvType
673 )
674{
675 kHllPubSymEntry * pEntry;
676
677 /* parameter assertion */
678 assert(pachName != NULL);
679
680 /*
681 * Create a public symbol entry
682 * Insert into it's list.
683 * Invalidate offsets.
684 */
685 pEntry = new kHllPubSymEntry(
686 pachName,
687 cchName,
688 off,
689 iObject,
690 pvType == NULL ? 0 : -1 //FIXME/TODO: Types->getIndex(pvType); check if 0 or -1.
691 );
692
693 PublicSymbols.insert(pEntry);
694
695 fValidOffsetsAndSizes = FALSE;
696
697 return pEntry;
698}
699
700
701
702
703/**
704 * Write this HLL entry to file.
705 * @returns Count of bytes written.
706 * -3 Invalid offsets.
707 * -2 Seek error.
708 * -1 Write error.
709 * @param phFile Filehandle.
710 * @param off Current offset into the HLL data.
711 * This is stored and used when making the directory
712 * entries for this module.
713 */
714int kHllModuleEntry::write(FILE *phFile, unsigned long off)
715{
716 int cch;
717 int cchToWrite;
718 int cchWritten = 0;
719
720 /* validate object state */
721 assert(pModule != NULL);
722
723 /*
724 * Write module HLL data.
725 */
726 offModule = off;
727 cchToWrite = offsetof(HLLMODULE, achName) + pModule->cchName + sizeof(HLLSEGINFO) * max(pModule->cSegInfo-1, 0);
728 cch = fwrite(pModule, 1, cchToWrite, phFile);
729 if (cch != cchToWrite)
730 return -1;
731 cchWritten += cch;
732 cbModule = cch;
733 off += cch;
734
735 /*
736 * Write the lists.
737 * Public Symbols
738 * Types
739 * Symbols
740 * Source
741 */
742 offPublicSymbols = off;
743 cbPublicSymbols = cch = kHllBaseEntry::writeList(phFile, PublicSymbols.getFirst());
744 if (cch < 0)
745 return cch;
746 cchWritten += cch;
747 off += cch;
748
749 /*
750 offTypes = off;
751 cbTypes = cch = kHllBaseEntry::writeList(phFile, Types.getFirst());
752 if (cch < 0)
753 return cch;
754 cchWritten += cch;
755 off += cch;
756
757
758 offSymbols = off;
759 cbSymbols = cch = kHllBaseEntry::writeList(phFile, Symbols.getFirst());
760 if (cch < 0)
761 return cch;
762 cchWritten += cch;
763 off += cch;
764 */
765
766 offSource = off;
767 cbSource = cch = Source.write(phFile);
768 if (cch < 0)
769 return cch;
770 cchWritten += cch;
771 off += cch;
772
773 /*
774 * Marks offsets and sizes valid and returns succesfully.
775 */
776 fValidOffsetsAndSizes = TRUE;
777 return cchWritten;
778}
779
780
781
782/**
783 * Writes the directory entries for this module to file.
784 * @returns Count of bytes written on success.
785 * -3 Invalid offsets.
786 * -2 Seek error.
787 * -1 Write error.
788 * 0 no data written (this is an error condition!)
789 * @param phFile Filehandle.
790 * @param iMod Index of this module.
791 */
792int kHllModuleEntry::writeDirEntries(FILE *phFile, unsigned short iMod)
793{
794 HLLDIRENTRY hllDirEntry;
795 int cch;
796 int cchWritten = 0;
797
798 /*
799 * Check that offsets are valid!
800 */
801 assert(fValidOffsetsAndSizes);
802 if (!fValidOffsetsAndSizes)
803 return -3;
804
805 /*
806 * Write Directory Entries.
807 * Module.
808 * Public Symbols. (if any)
809 * Types. (if any)
810 * Symbols. (if any)
811 * Source. (if any)
812 */
813 hllDirEntry.usType = HLL_DE_MODULES;
814 hllDirEntry.cb = cbModule;
815 hllDirEntry.off = offModule;
816 hllDirEntry.iMod = iMod;
817 cch = fwrite(&hllDirEntry, 1, sizeof(hllDirEntry), phFile);
818 if (cch != sizeof(hllDirEntry))
819 return -1;
820 cchWritten += cch;
821
822 if (cbPublicSymbols > 0)
823 {
824 hllDirEntry.usType = HLL_DE_PUBLICS;
825 hllDirEntry.cb = cbPublicSymbols;
826 hllDirEntry.off = offPublicSymbols;
827 hllDirEntry.iMod = iMod;
828 cch = fwrite(&hllDirEntry, 1, sizeof(hllDirEntry), phFile);
829 if (cch != sizeof(hllDirEntry))
830 return -1;
831 cchWritten += cch;
832 }
833
834 /*
835 if (cbTypes > 0)
836 {
837 hllDirEntry.usType = HLL_DE_TYPES;
838 hllDirEntry.cb = cbTypes;
839 hllDirEntry.off = offTypes;
840 hllDirEntry.iMod = iMod;
841 cch = fwrite(&hllDirEntry, 1, sizeof(hllDirEntry), phFile);
842 if (cch != sizeof(hllDirEntry))
843 return -1;
844 cchWritten += cch;
845 }
846
847 if (cbSymbols > 0)
848 {
849 hllDirEntry.usType = HLL_DE_SYMBOLS;
850 hllDirEntry.cb = cbSymbols;
851 hllDirEntry.off = offSymbols;
852 hllDirEntry.iMod = iMod;
853 cch = fwrite(&hllDirEntry, 1, sizeof(hllDirEntry), phFile);
854 if (cch != sizeof(hllDirEntry))
855 return -1;
856 cchWritten += cch;
857 }
858 */
859
860 if (cbSource > 0)
861 {
862 hllDirEntry.usType = HLL_DE_IBMSRC;
863 hllDirEntry.cb = cbSource;
864 hllDirEntry.off = offSource;
865 hllDirEntry.iMod = iMod;
866 cch = fwrite(&hllDirEntry, 1, sizeof(hllDirEntry), phFile);
867 if (cch != sizeof(hllDirEntry))
868 return -1;
869 cchWritten += cch;
870 }
871
872
873 return cchWritten;
874}
875
876
877
878
879
880
881
882
883
884
885
886
887/*******************************************************************************
888* *
889* kHll *
890* *
891* kHll *
892* *
893*******************************************************************************/
894
895
896
897/**
898 * Writes HLL debuginfo to the given file at the current position.
899 * The file should be opened in write mode.
900 * @returns Number of bytes written.
901 * @param phFile Filehandle to output file. Starts writing at current pos.
902 */
903int kHll::write(FILE *phFile)
904{
905 HLLHDR hllHdr;
906 HLLDIR hllDir;
907 kHllModuleEntry * pModule;
908 int cch; /* Number of bytes written to the file in an operation. */
909 int cchWritten = 0; /* Number of bytes written to the file. */
910 long int lPosStart; /* Starting position. */
911 long int lPosDir; /* Directory position. */
912 long int lPos; /* A file position. */
913 int iMod; /* Module index (passed in to writeDirEntries) */
914
915 /* Get starting position. */
916 lPosStart = ftell(phFile);
917
918 /* Make temporary header and write it */
919 memcpy(hllHdr.achSignature, "NB04", 4);
920 hllHdr.offDirectory = 0;
921 cch = fwrite(&hllHdr, 1, sizeof(hllHdr), phFile);
922 if (cch != sizeof(hllHdr))
923 return -1;
924 cchWritten += cch;
925
926
927 /*
928 * Start writing modules
929 */
930 pModule = (kHllModuleEntry*)Modules.getFirst();
931 while (pModule != NULL)
932 {
933 cch = pModule->write(phFile, cchWritten);
934 if (cch <= 0)
935 return cch;
936 cchWritten += cch;
937 pModule = (kHllModuleEntry *)pModule->getNext();
938 }
939
940
941 /*
942 * Write libraries.
943 */
944 //Not implemented yet - TODO/FIXME!
945
946
947 /*
948 * Write directory.
949 * Make and write temporary directory header.
950 * Write directory entries per module.
951 * Write directory entry for libraries.
952 * Remake and rewrite directory header. (correct cEntries)
953 */
954 lPosDir = ftell(phFile);
955 hllDir.cEntries = 0;
956 hllDir.cb = offsetof(HLLDIR, aEntries);
957 hllDir.cbEntry = sizeof(HLLDIRENTRY);
958 cch = fwrite(&hllDir, 1, offsetof(HLLDIR, aEntries), phFile);
959 if (cch != offsetof(HLLDIR, aEntries))
960 return -1;
961 cchWritten += cch;
962
963 iMod = 1;
964 pModule = (kHllModuleEntry*)Modules.getFirst();
965 while (pModule != NULL)
966 {
967 cch = pModule->writeDirEntries(phFile, iMod);
968 if (cch == -1)
969 return -1;
970 cchWritten += cch;
971 pModule = (kHllModuleEntry *)pModule->getNext();
972 iMod++;
973 }
974
975 //Library - TODO/FIXME
976
977 lPos = ftell(phFile);
978 hllDir.cEntries = (lPos - lPosDir - offsetof(HLLDIR, aEntries)) / sizeof(HLLDIRENTRY);
979 if (fseek(phFile, lPosDir, SEEK_SET) != 0)
980 return -2;
981 cch = fwrite(&hllDir, 1, offsetof(HLLDIR, aEntries), phFile);
982 if (cch != offsetof(HLLDIR, aEntries))
983 return -1;
984
985 /*
986 * Rewrite HLL header (with correct directory offset).
987 */
988 hllHdr.offDirectory = lPosDir - lPosStart;
989 if (fseek(phFile, lPosStart, SEEK_SET) != 0)
990 return -2;
991 cch = fwrite(&hllHdr, 1, sizeof(hllHdr), phFile);
992 if (cch != sizeof(hllHdr))
993 return -1;
994
995 /*
996 * Hacking:
997 * Writing an extra HLL header pointing to an non-existing directory
998 * staring at the last byte of this header. This is present when linking
999 * with ilink...
1000 */
1001 if (fseek(phFile, lPosStart + cchWritten, SEEK_SET) != 0)
1002 return -2;
1003 hllHdr.offDirectory = cchWritten + sizeof(hllHdr);
1004 cch = fwrite(&hllHdr, 1, sizeof(hllHdr), phFile);
1005 if (cch != sizeof(hllHdr))
1006 return -1;
1007 cchWritten += cch;
1008
1009 return cchWritten;
1010}
1011
1012
1013
1014/**
1015 * Constructor - Creates an empty HLL object.
1016 */
1017kHll::kHll()
1018{
1019}
1020
1021
1022
1023/**
1024 * Destructor.
1025 */
1026kHll::~kHll()
1027{
1028}
1029
1030
1031
1032/**
1033 * Adds a module.
1034 * @returns Pointer to the module object added. NULL on error.
1035 * @param pszName Module name
1036 * @param pvLib Library module handle.
1037 * @param cSegInfo Number of objects in the array.
1038 * @param paSegInfo Pointer to an array of objects.
1039 */
1040kHllModuleEntry * kHll::addModule(
1041 const char * pszName,
1042 const void * pvLib,
1043 unsigned cSegInfo,
1044 PHLLSEGINFO paSegInfo)
1045{
1046 kHllModuleEntry * pEntry;
1047 assert(pszName != NULL);
1048
1049 pEntry = new kHllModuleEntry(
1050 pszName,
1051 pvLib == NULL ? 0 : -1, //FIXME/TODO: Libs->getIndex(pvLib); check if 0 or -1;
1052 cSegInfo,
1053 paSegInfo);
1054
1055 Modules.insert(pEntry);
1056 return pEntry;
1057}
1058
1059
1060
1061/**
1062 * Adds a module.
1063 * @returns Pointer to the module object added. NULL on error.
1064 * @param pachName Module name
1065 * @param cchName Length of modulename
1066 * @param pvLib Library module handle.
1067 * @param cSegInfo Number of objects in the array.
1068 * @param paSegInfo Pointer to an array of objects.
1069 */
1070kHllModuleEntry * kHll::addModule(
1071 const char * pachName,
1072 unsigned cchName,
1073 const void * pvLib,
1074 unsigned cSegInfo,
1075 PHLLSEGINFO paSegInfo)
1076{
1077 char szModName[256];
1078 kHllModuleEntry * pEntry;
1079 assert(pachName != NULL && cchName > 0);
1080
1081 szModName[0] = '\0';
1082 strncat(szModName, pachName, min(cchName, 255));
1083 pEntry = new kHllModuleEntry(
1084 szModName,
1085 pvLib == NULL ? 0 : -1, //FIXME/TODO: Libs->getIndex(pvLib); check if 0 or -1;
1086 cSegInfo,
1087 paSegInfo);
1088
1089 Modules.insert(pEntry);
1090 return pEntry;
1091}
1092
1093
1094
1095/**
1096 * Writes the HLL info to a file. (Not LX?)
1097 * @returns Success indicator.
1098 * @param pszFilename Name of the output file.
1099 * @remark IMPORTANT! This is mostly for debugging!
1100 * It completely overwrites the file if it exists!
1101 */
1102BOOL kHll::write(
1103 const char *pszFilename
1104 )
1105{
1106 FILE * phFile;
1107
1108 phFile = fopen(pszFilename, "wb");
1109 if (phFile != NULL)
1110 {
1111 int cch = write(phFile);
1112 if (cch > 0)
1113 {
1114 fclose(phFile);
1115 return TRUE;
1116 }
1117 else
1118 fprintf(stderr, "write failed with cch=%d\n", cch);
1119 fclose(phFile);
1120 }
1121
1122 return FALSE;
1123}
1124
1125
1126
1127/**
1128 * Writes the HLL info to a file. (Not LX?)
1129 * Failes if there is debuginfo in the file.
1130 * No backup is made. (sorry)
1131 * @returns OS2 return code.
1132 * @param pszFilename Name of the output file.
1133 */
1134APIRET kHll::writeToLX(
1135 const char *pszFilename
1136 )
1137{
1138 APIRET rc;
1139 FILE * phFile;
1140
1141 phFile = fopen(pszFilename, "rb+");
1142 if (phFile != NULL)
1143 {
1144 struct exe_hdr ehdr;
1145 struct e32_exe e32;
1146 int cch;
1147 long lPosLXHdr;
1148 long cbLXFile;
1149
1150 /*
1151 * Read exe header
1152 */
1153 cch = fread(&ehdr, 1, sizeof(ehdr), phFile);
1154 if (cch == sizeof(ehdr))
1155 {
1156 cbLXFile = fsize(phFile);
1157 if (ehdr.e_magic == EMAGIC)
1158 lPosLXHdr = ehdr.e_lfanew;
1159 else
1160 lPosLXHdr = 0;
1161 if (fseek(phFile, lPosLXHdr, SEEK_SET) == 0)
1162 {
1163 cch = fread(&e32, 1, sizeof(e32), phFile);
1164 if (cch == sizeof(e32))
1165 {
1166 if (*(unsigned short*)&e32.e32_magic[0] == E32MAGIC)
1167 {
1168 /*
1169 * Found exeheader.
1170 * Check if there is any debug info.
1171 */
1172 if ((e32.e32_debuginfo == 0 && e32.e32_debuginfo == 0)
1173 || (cbLXFile == e32.e32_debuglen + e32.e32_debuginfo)
1174 )
1175 {
1176 long lPosDebug;
1177
1178 if (e32.e32_debuginfo != 0 && e32.e32_debuglen != 0)
1179 lPosDebug = e32.e32_debuginfo;
1180 else
1181 lPosDebug = (cbLXFile + 0x400) & ~0x1FF; //try do some alignment.
1182
1183 /*
1184 * Go to debug info position in the file and write debug info.
1185 */
1186 if (fseek(phFile, lPosDebug, SEEK_SET) == 0)
1187 {
1188 /*
1189 * Write the HLL data to disk.
1190 */
1191 cch = write(phFile);
1192 if (cch > 0)
1193 {
1194 /*
1195 * Update exeheader.
1196 */
1197 e32.e32_debuglen = cch;
1198 e32.e32_debuginfo = lPosDebug;
1199 if (fseek(phFile, lPosLXHdr, SEEK_SET) == 0)
1200 {
1201 /*
1202 * Write the updated header to disk.
1203 */
1204 cch = fwrite(&e32, 1, sizeof(e32), phFile);
1205 if (cch == sizeof(e32))
1206 rc = NO_ERROR;
1207 else
1208 rc = ERROR_WRITE_FAULT;
1209 }
1210 else
1211 rc = ERROR_SEEK;
1212 }
1213 else
1214 {
1215 fprintf(stderr, "error - write failed with cch=%d\n", cch);
1216 rc = ERROR_WRITE_FAULT;
1217 }
1218 }
1219 else
1220 rc = ERROR_SEEK;
1221 }
1222 else
1223 {
1224 fprintf(stderr, "error - debuginfo exists\n");
1225 rc = ERROR_BAD_EXE_FORMAT;
1226 }
1227
1228 }
1229 else
1230 rc = ERROR_INVALID_EXE_SIGNATURE;
1231 }
1232 else
1233 rc = ERROR_BAD_EXE_FORMAT;
1234 }
1235 else
1236 rc = ERROR_BAD_EXE_FORMAT;
1237 }
1238 else
1239 rc = ERROR_READ_FAULT;
1240
1241 fclose(phFile);
1242 }
1243 else
1244 rc = ERROR_ACCESS_DENIED; //?
1245
1246
1247 return rc;
1248}
1249
1250
1251/**
1252 * Find the size of a file.
1253 * @returns Size of file. -1 on error.
1254 * @param phFile File handle.
1255 */
1256signed long fsize(FILE *phFile)
1257{
1258 int ipos;
1259 signed long cb;
1260
1261 if ((ipos = ftell(phFile)) < 0
1262 ||
1263 fseek(phFile, 0, SEEK_END) != 0
1264 ||
1265 (cb = ftell(phFile)) < 0
1266 ||
1267 fseek(phFile, ipos, SEEK_SET) != 0
1268 )
1269 cb = -1;
1270 return cb;
1271}
1272
Note: See TracBrowser for help on using the repository browser.