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

Last change on this file since 3239 was 3239, checked in by bird, 26 years ago

Temporary commit.

File size: 22.6 KB
Line 
1/* $Id: kHll.cpp,v 1.3 2000-03-26 14:16:18 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
44
45
46/*******************************************************************************
47* *
48* kHllBaseEntry *
49* *
50* kHllBaseEntry *
51* *
52*******************************************************************************/
53
54
55/**
56 * Writes a list to disk.
57 * @returns Number of bytes written.
58 * @returns Count of bytes written on success. (includes 0)
59 * -3 Invalid offsets.
60 * -2 Seek error.
61 * -1 Write error.
62 * @param phFile Output filehandle.
63 * @param pEntry Pointer to the start of the list which is to be written.
64 */
65int kHllBaseEntry::writeList(FILE *phFile, kHllBaseEntry *pEntry)
66{
67 int cch;
68 int cchWritten = 0;
69
70 /*
71 * Loop thru the list and write all the entries to disk.
72 */
73 while (pEntry != NULL)
74 {
75 cchWritten += cch = pEntry->write(phFile);
76 if (cch < 0)
77 return cch;
78 if (cch == 0)
79 return -1;
80 pEntry = (kHllBaseEntry*)pEntry->getNext();
81 }
82
83 return cchWritten;
84}
85
86
87
88
89
90
91/*******************************************************************************
92* *
93* kHllPubSymEntry *
94* *
95* kHllPubSymEntry *
96* *
97*******************************************************************************/
98
99
100
101/**
102 * Creates an HLL public symbol entry.
103 * @param pszName Symbol name.
104 * @param off Offset into the object.
105 * @param iObj LX Object index.
106 * @param iType Type index. (index into type table)
107 */
108kHllPubSymEntry::kHllPubSymEntry(
109 const char * pszName,
110 unsigned long off,
111 unsigned short iObj,
112 unsigned short iType
113 )
114{
115 pPubSym = (PHLLPUBLICSYM)malloc(strlen(pszName) + sizeof(HLLPUBLICSYM));
116 assert(pPubSym != NULL);
117
118 pPubSym->cchName = strlen(pszName);
119 strcpy((char*)&pPubSym->achName[0], pszName);
120 pPubSym->off = off;
121 pPubSym->iObj = iObj;
122 pPubSym->iType = iType;
123}
124
125
126
127/**
128 * Destructor.
129 */
130kHllPubSymEntry::~kHllPubSymEntry()
131{
132 if (pPubSym != NULL)
133 free(pPubSym);
134 pPubSym = NULL;
135}
136
137
138
139/**
140 * Write this entry to file.
141 * @returns Number of bytes written.
142 * @param phFile File handle.
143 */
144int kHllPubSymEntry::write(FILE *phFile)
145{
146 assert(pPubSym != NULL);
147 return fwrite(pPubSym,
148 1,
149 offsetof(HLLPUBLICSYM, achName) + pPubSym->cchName,
150 phFile);
151}
152
153
154
155
156
157/*******************************************************************************
158* *
159* kHllModuleEntry *
160* *
161* kHllModuleEntry *
162* *
163*******************************************************************************/
164
165
166
167
168
169
170
171/**
172 * Creates an HLL module entry.
173 * @param pszName Module name. (NULL is not allowed!)
174 * @param iLib Library index.
175 * @param cObjects Number of objects in the array.
176 * @param paObjects Pointer to an array of objects.
177 */
178kHllModuleEntry::kHllModuleEntry(
179 const char * pszName,
180 unsigned short iLib,
181 unsigned char cObjects/*= 0 */,
182 PMODOBJECT paObjects/*= NULL */
183 )
184: fValidOffsetsAndSizes(FALSE)
185{
186 int i;
187 int cchName;
188 PHLLOBJECT pObj;
189
190 /*
191 * Debug parameter validations.
192 */
193 assert(pszName != NULL);
194 assert(cObjects == 0 || paObjects != NULL);
195
196 /*
197 * Allocate data storage and fill HLL structure.
198 */
199 cchName = strlen(pszName);
200 pModule = (PHLLMODULE)malloc(sizeof(HLLMODULE) + cchName +
201 sizeof(HLLOBJECT) * min((cObjects - 1), 3));
202 assert(pModule != NULL);
203 memset(pModule, 0, sizeof(*pModule));
204 pModule->cchName = cchName;
205 strcpy((char*)&pModule->achName[0], pszName);
206 pModule->chVerMajor = 4;
207 pModule->chVerMinor = 0;
208 pModule->cObjects = cObjects;
209 pModule->iLib = iLib;
210 pModule->usDebugStyle = HLL_MOD_STYLE;
211 pModule->overlay = 0;
212 pModule->pad = 0;
213
214 /* objects */
215 if (cObjects > 0)
216 {
217 pModule->Object.cb = paObjects->cb;
218 pModule->Object.iObj = paObjects->iObject;
219 pModule->Object.off = paObjects->offset;
220
221 for (i = 1, pObj = (PHLLOBJECT)&pModule->achName[cchName]; i < cObjects; i++, pObj++)
222 {
223 pObj->cb = paObjects[i].cb;
224 pObj->iObj = paObjects[i].iObject;
225 pObj->off = paObjects[i].offset;
226 }
227 }
228}
229
230
231/**
232 * Destructor - free storage.
233 */
234kHllModuleEntry::~kHllModuleEntry()
235{
236 if (pModule != NULL)
237 free(pModule);
238 pModule = NULL;
239}
240
241
242
243/**
244 * Adds an object to the module.
245 * @returns Success indicator.
246 * @param iObject LX Object index.
247 * @param off Offset into the object to the module data.
248 * @param cb Size of module data (in the object).
249 */
250BOOL kHllModuleEntry::addObject(
251 unsigned short int iObject,
252 unsigned long off,
253 unsigned long cb
254 )
255{
256 assert(pModule != NULL);
257
258 /*
259 * Reallocate? (Note that we'll initially allocated space for 3 objects.)
260 */
261 if (pModule->cObjects >= 3)
262 {
263 void *pv = realloc(pModule, sizeof(HLLMODULE) + pModule->cchName
264 + (pModule->cObjects + 1) * sizeof(HLLOBJECT));
265 assert(pv != NULL);
266 if (pv == NULL)
267 return FALSE;
268 pModule = (PHLLMODULE)pv;
269 }
270
271
272 /*
273 * Add module.
274 */
275 if (pModule->cObjects == 0)
276 {
277 pModule->Object.cb = cb;
278 pModule->Object.off = off;
279 pModule->Object.iObj = iObject;
280 }
281 else
282 {
283 PHLLOBJECT pObject = (PHLLOBJECT)(pModule->cObjects * sizeof(HLLOBJECT)
284 + pModule->achName[pModule->cchName]);
285 pObject->cb = cb;
286 pObject->off = off;
287 pObject->iObj = iObject;
288 }
289 pModule->cObjects++;
290
291 return TRUE;
292}
293
294
295
296/**
297 * Adds a public symbol.
298 * @returns Handle to the symbol. NULL on error.
299 * @param pszName Symbol name.
300 * @param off Offset into the LX Object of the symbol.
301 * @param iObject LX Object index.
302 * @param pvType Type handle. NULL if not type.
303 */
304const void * kHllModuleEntry::addPublicSymbol(
305 const char * pszName,
306 unsigned long int off,
307 unsigned short int iObject,
308 const void * pvType
309 )
310{
311 kHllPubSymEntry * pEntry;
312
313 /* parameter assertion */
314 assert(pszName != NULL);
315
316 /*
317 * Create a public symbol entry
318 * Insert into it's list.
319 * Invalidate offsets.
320 */
321 pEntry = new kHllPubSymEntry(
322 pszName,
323 off,
324 iObject,
325 pvType == NULL ? 0 : -1 //FIXME/TODO: Types->getIndex(pvType); check if 0 or -1.
326 );
327
328 PublicSymbols.insert(pEntry);
329
330 fValidOffsetsAndSizes = FALSE;
331
332 return pEntry;
333}
334
335
336
337/**
338 * Write this HLL entry to file.
339 * @returns Count of bytes written. -1 on error.
340 * @param phFile Filehandle.
341 * @param off Current offset into the HLL data.
342 * This is stored and used when making the directory
343 * entries for this module.
344 */
345int kHllModuleEntry::write(FILE *phFile, unsigned long off)
346{
347 int cch;
348 int cchWritten = 0;
349
350 /* validate object state */
351 assert(pModule != NULL);
352
353 /*
354 * Write module HLL data.
355 */
356 offModule = off;
357 cch = fwrite(pModule, 1, offsetof(HLLMODULE, achName) + pModule->cchName, phFile);
358 if (cch != offsetof(HLLMODULE, achName) + pModule->cchName)
359 return -1;
360 cchWritten += cch;
361 cbModule = cch;
362 off += cch;
363
364 /*
365 * Write the lists.
366 * Public Symbols
367 * Types
368 * Symbols
369 * Source
370 */
371 offPublicSymbols = off;
372 cbPublicSymbols = cch = kHllBaseEntry::writeList(phFile, PublicSymbols.getFirst());
373 if (cch < 0)
374 return cch;
375 cchWritten += cch;
376 off += cch;
377
378 /*
379 offTypes = off;
380 cbTypes = cch = kHllBaseEntry::writeList(phFile, Types.getFirst());
381 if (cch < 0)
382 return cch;
383 cchWritten += cch;
384 off += cch;
385
386
387 offSymbols = off;
388 cbSymbols = cch = kHllBaseEntry::writeList(phFile, Symbols.getFirst());
389 if (cch < 0)
390 return cch;
391 cchWritten += cch;
392 off += cch;
393
394 offSource = off;
395 cbSource = cch = kHllBaseEntry::writeList(phFile, Source.getFirst());
396 if (cch < 0)
397 return cch;
398 cchWritten += cch;
399 off += cch;
400 */
401
402 /*
403 * Marks offsets and sizes valid and returns succesfully.
404 */
405 fValidOffsetsAndSizes = TRUE;
406 return cchWritten;
407}
408
409
410
411/**
412 * Writes the directory entries for this module to file.
413 * @returns Count of bytes written on success.
414 * -3 Invalid offsets.
415 * -2 Seek error.
416 * -1 Write error.
417 * 0 no data written (this is an error condition!)
418 * @param phFile Filehandle.
419 * @param iMod Index of this module.
420 */
421int kHllModuleEntry::writeDirEntries(FILE *phFile, unsigned short iMod)
422{
423 HLLDIRENTRY hllDirEntry;
424 int cch;
425 int cchWritten = 0;
426
427 /*
428 * Check that offsets are valid!
429 */
430 assert(fValidOffsetsAndSizes);
431 if (!fValidOffsetsAndSizes)
432 return -3;
433
434 /*
435 * Write Directory Entries.
436 * Module.
437 * Public Symbols. (if any)
438 * Types. (if any)
439 * Symbols. (if any)
440 * Source. (if any)
441 */
442 hllDirEntry.usType = HLL_DE_MODULES;
443 hllDirEntry.cb = cbModule;
444 hllDirEntry.off = offModule;
445 hllDirEntry.iMod = iMod;
446 cch = fwrite(&hllDirEntry, 1, sizeof(hllDirEntry), phFile);
447 if (cch != sizeof(hllDirEntry))
448 return -1;
449 cchWritten += cch;
450
451 if (cbPublicSymbols > 0)
452 {
453 hllDirEntry.usType = HLL_DE_PUBLICS;
454 hllDirEntry.cb = cbPublicSymbols;
455 hllDirEntry.off = offPublicSymbols;
456 hllDirEntry.iMod = iMod;
457 cch = fwrite(&hllDirEntry, 1, sizeof(hllDirEntry), phFile);
458 if (cch != sizeof(hllDirEntry))
459 return -1;
460 cchWritten += cch;
461 }
462
463 /*
464 if (cbTypes > 0)
465 {
466 hllDirEntry.usType = HLL_DE_TYPES;
467 hllDirEntry.cb = cbTypes;
468 hllDirEntry.off = offTypes;
469 hllDirEntry.iMod = iMod;
470 cch = fwrite(&hllDirEntry, 1, sizeof(hllDirEntry), phFile);
471 if (cch != sizeof(hllDirEntry))
472 return -1;
473 cchWritten += cch;
474 }
475
476 if (cbSymbols > 0)
477 {
478 hllDirEntry.usType = HLL_DE_SYMBOLS;
479 hllDirEntry.cb = cbSymbols;
480 hllDirEntry.off = offSymbols;
481 hllDirEntry.iMod = iMod;
482 cch = fwrite(&hllDirEntry, 1, sizeof(hllDirEntry), phFile);
483 if (cch != sizeof(hllDirEntry))
484 return -1;
485 cchWritten += cch;
486 }
487
488 if (cbSource > 0)
489 {
490 hllDirEntry.usType = HLL_DE_IBMSRC;
491 hllDirEntry.cb = cbSource;
492 hllDirEntry.off = offSource;
493 hllDirEntry.iMod = iMod;
494 cch = fwrite(&hllDirEntry, 1, sizeof(hllDirEntry), phFile);
495 if (cch != sizeof(hllDirEntry))
496 return -1;
497 cchWritten += cch;
498 }
499
500 */
501
502 return cchWritten;
503}
504
505
506
507
508
509
510
511
512
513
514
515
516/*******************************************************************************
517* *
518* kHll *
519* *
520* kHll *
521* *
522*******************************************************************************/
523
524
525
526/**
527 * Writes HLL debuginfo to the given file at the current position.
528 * The file should be opened in write mode.
529 * @returns Number of bytes written.
530 * @param phFile Filehandle to output file. Starts writing at current pos.
531 */
532int kHll::write(FILE *phFile)
533{
534 HLLHDR hllHdr;
535 HLLDIR hllDir;
536 kHllModuleEntry * pModule;
537 int cch; /* Number of bytes written to the file in an operation. */
538 int cchWritten = 0; /* Number of bytes written to the file. */
539 long int lPosStart; /* Starting position. */
540 long int lPosDir; /* Directory position. */
541 long int lPos; /* A file position. */
542 int iMod; /* Module index (passed in to writeDirEntries) */
543
544 /* Get starting position. */
545 lPosStart = ftell(phFile);
546
547 /* Make temporary header and write it */
548 memcpy(hllHdr.achSignature, "NB04", 4);
549 hllHdr.offDirectory = 0;
550 hllHdr.ulReserved = 1;
551 cch = fwrite(&hllHdr, 1, sizeof(hllHdr), phFile);
552 if (cch != sizeof(hllHdr))
553 return -1;
554 cchWritten += cch;
555
556
557 /*
558 * Start writing modules
559 */
560 pModule = (kHllModuleEntry*)Modules.getFirst();
561 while (pModule != NULL)
562 {
563 cch = pModule->write(phFile, cchWritten);
564 if (cch <= 0)
565 return cch;
566 cchWritten += cch;
567 pModule = (kHllModuleEntry *)pModule->getNext();
568 }
569
570
571 /*
572 * Write libraries.
573 */
574 //Not implemented yet - TODO/FIXME!
575
576
577 /*
578 * Write directory.
579 * Make and write temporary directory header.
580 * Write directory entries per module.
581 * Write directory entry for libraries.
582 * Remake and rewrite directory header. (correct cEntries)
583 */
584 lPosDir = ftell(phFile);
585 hllDir.cEntries = 0;
586 hllDir.ulReserved = 0; //FIXME/TODO - not quite sure what this is or should be!
587 cch = fwrite(&hllDir, 1, offsetof(HLLDIR, aEntries), phFile);
588 if (cch != offsetof(HLLDIR, aEntries))
589 return -1;
590 cchWritten += cch;
591
592 iMod = 1;
593 pModule = (kHllModuleEntry*)Modules.getFirst();
594 while (pModule != NULL)
595 {
596 cch = pModule->writeDirEntries(phFile, iMod);
597 if (cch == -1)
598 return -1;
599 cchWritten += cch;
600 pModule = (kHllModuleEntry *)pModule->getNext();
601 iMod++;
602 }
603
604 //Library - TODO/FIXME
605
606 lPos = ftell(phFile);
607 hllDir.cEntries = (lPos - lPosDir - offsetof(HLLDIR, aEntries)) / sizeof(HLLDIRENTRY);
608 if (fseek(phFile, lPosDir, SEEK_SET) != 0)
609 return -2;
610 cch = fwrite(&hllDir, 1, offsetof(HLLDIR, aEntries), phFile);
611 if (cch != offsetof(HLLDIR, aEntries))
612 return -1;
613
614 /*
615 * Rewrite HLL header (with correct directory offset).
616 */
617 hllHdr.offDirectory = lPosDir - lPosStart;
618 cch = fwrite(&hllHdr, 1, sizeof(hllHdr), phFile);
619 if (cch != sizeof(hllHdr))
620 return -1;
621
622
623 return cch;
624}
625
626
627
628/**
629 * Constructor - Creates an empty HLL object.
630 */
631kHll::kHll()
632{
633}
634
635
636
637/**
638 * Destructor.
639 */
640kHll::~kHll()
641{
642}
643
644
645
646/**
647 * Adds a module.
648 * @returns Pointer to the module object added. NULL on error.
649 * @param pszName Module name
650 * @param pvLib Library module handle.
651 * @param cObjects Number of objects in the array.
652 * @param paObjects Pointer to an array of objects.
653 */
654kHllModuleEntry * kHll::addModule(
655 const char * pszName,
656 const void * pvLib,
657 unsigned cObjects,
658 PMODOBJECT paObjects)
659{
660 kHllModuleEntry * pEntry;
661 assert(pszName != NULL);
662
663 pEntry = new kHllModuleEntry(
664 pszName,
665 pvLib == NULL ? 0 : -1, //FIXME/TODO: Libs->getIndex(pvLib); check if 0 or -1;
666 cObjects,
667 paObjects);
668
669 Modules.insert(pEntry);
670 return pEntry;
671}
672
673
674
675/**
676 * Writes the HLL info to a file. (Not LX?)
677 * @returns Success indicator.
678 * @param pszFilename Name of the output file.
679 * @remark IMPORTANT! This is mostly for debugging!
680 * It completely overwrites the file if it exists!
681 */
682BOOL kHll::write(
683 const char *pszFilename
684 )
685{
686 FILE * phFile;
687
688 phFile = fopen(pszFilename, "wb");
689 if (phFile != NULL)
690 {
691 int cch = write(phFile);
692 if (cch > 0)
693 {
694 fclose(phFile);
695 return TRUE;
696 }
697 else
698 fprintf(stderr, "write failed with cch=%d\n", cch);
699 fclose(phFile);
700 }
701
702 return FALSE;
703}
704
705
706
707/**
708 * Writes the HLL info to a file. (Not LX?)
709 * Failes if there is debuginfo in the file.
710 * No backup is made. (sorry)
711 * @returns OS2 return code.
712 * @param pszFilename Name of the output file.
713 */
714APIRET kHll::writeToLX(
715 const char *pszFilename
716 )
717{
718 APIRET rc;
719 FILE * phFile;
720
721 phFile = fopen(pszFilename, "rb+");
722 if (phFile != NULL)
723 {
724 struct exe_hdr ehdr;
725 struct e32_exe e32;
726 int cch;
727 long lPosLXHdr;
728
729 /*
730 * Read exe header
731 */
732 cch = fread(&ehdr, 1, sizeof(ehdr), phFile);
733 if (cch == sizeof(ehdr))
734 {
735 if (ehdr.e_magic == NEMAGIC)
736 lPosLXHdr = ehdr.e_lfanew;
737 else
738 lPosLXHdr = 0;
739 if (fseek(phFile, lPosLXHdr, SEEK_SET) == 0)
740 {
741 cch = fread(&e32, 1, sizeof(e32), phFile);
742 if (cch == sizeof(e32))
743 {
744 if (*(unsigned short*)&e32.e32_magic[0] == E32MAGIC)
745 {
746 /*
747 * Found exeheader.
748 * Check if there is any debug info.
749 */
750 if (e32.e32_debuginfo > 0 && e32.e32_debuginfo > 0)
751 {
752 long lPosDebug;
753
754 /*
755 * Go to end of file and write debug info.
756 */
757 if (fseek(phFile, 0, SEEK_END) == 0
758 &&
759 (lPosDebug = ftell(phFile)) != -1
760 )
761 {
762 /*
763 * Write the HLL data to disk.
764 */
765 cch = write(phFile);
766 if (cch > 0)
767 {
768 /*
769 * Update exeheader.
770 */
771 e32.e32_debuglen = cch;
772 e32.e32_debuginfo = lPosDebug;
773 if (fseek(phFile, lPosLXHdr, SEEK_SET) == 0)
774 {
775 /*
776 * Write the updated header to disk.
777 */
778 cch = fwrite(&e32, 1, sizeof(e32), phFile);
779 if (cch == sizeof(e32))
780 rc = NO_ERROR;
781 else
782 rc = ERROR_WRITE_FAULT;
783 }
784 else
785 rc = ERROR_SEEK;
786 }
787 else
788 {
789 fprintf(stderr, "error - write failed with cch=%d\n", cch);
790 rc = ERROR_WRITE_FAULT;
791 }
792 }
793 else
794 rc = ERROR_SEEK;
795 }
796 else
797 {
798 fprintf(stderr, "error - debuginfo exists\n");
799 rc = ERROR_BAD_EXE_FORMAT;
800 }
801
802 }
803 else
804 rc = ERROR_INVALID_EXE_SIGNATURE;
805 }
806 else
807 rc = ERROR_BAD_EXE_FORMAT;
808 }
809 else
810 rc = ERROR_BAD_EXE_FORMAT;
811 }
812 else
813 rc = ERROR_READ_FAULT;
814
815 fclose(phFile);
816 }
817 else
818 rc = ERROR_ACCESS_DENIED; //?
819
820
821 return rc;
822}
823
824
825
Note: See TracBrowser for help on using the repository browser.