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

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

Fixed makefile, added missing sym.h and removed warnings in kHll.cpp and Sym2Hll.cpp.

File size: 35.0 KB
Line 
1/* $Id: kHll.cpp,v 1.12 2000-04-24 21:38:12 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 = (unsigned char)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, (size_t)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++] = (char)cchFilename;
417 memcpy(&pachFilenames[cbFilenames], pachFilename, cchFilename);
418 cbFilenames += cchFilename;
419
420 return (unsigned short)++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 = (unsigned short)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 = (unsigned char)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 (unsigned short)(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, (unsigned short)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 (unsigned short)(pvLib == NULL ? 0 : -1), //FIXME/TODO: Libs->getIndex(pvLib); check if 0 or -1;
1052 (unsigned char) 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 (unsigned short)(pvLib == NULL ? 0 : -1), //FIXME/TODO: Libs->getIndex(pvLib); check if 0 or -1;
1086 (unsigned char)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 long 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.