source: trunk/tools/dbginfo/dbgLXDumper.c@ 10366

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

Tried to fix dumper, but IBMSRC don't work properly! Don't know how to
read that data yet...

File size: 21.5 KB
Line 
1/* $Id: dbgLXDumper.c,v 1.7 2000-04-07 02:48:03 bird Exp $
2 *
3 * dbgLXDumper - reads and interprets the debuginfo found in an LX executable.
4 *
5 * Copyright (c) 2000 knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
6 *
7 * Project Odin Software License can be found in LICENSE.TXT
8 *
9 */
10
11/*******************************************************************************
12* Defined Constants And Macros *
13*******************************************************************************/
14#define INCL_DOSERRORS
15#define FOR_EXEHDR 1 /* exe386.h flag */
16#define DWORD ULONG /* Used by exe386.h / newexe.h */
17#define WORD USHORT /* Used by exe386.h / newexe.h */
18
19#define HLLVERSION100 0x0100
20#define HLLVERSION300 0x0300
21#define HLLVERSION400 0x0400
22#define HLLVERSION500 0x0500
23
24
25/*******************************************************************************
26* Header Files *
27*******************************************************************************/
28#include <os2.h>
29#include <newexe.h>
30#include <exe386.h>
31
32#include <malloc.h>
33#include <string.h>
34#include <stdio.h>
35#include <stddef.h>
36#include <ctype.h>
37
38#include "hll.h"
39
40
41
42/*******************************************************************************
43* Internal Functions *
44*******************************************************************************/
45int dbgLXDump(void *pvFile);
46int dumpHLL(FILE *phOut, PBYTE pb, int cb);
47void dumpHex(FILE *phOut, PBYTE pb, int cb);
48void * readfile(const char *pszFilename);
49signed long fsize(FILE *phFile);
50
51
52
53/*******************************************************************************
54* Global Variables *
55*******************************************************************************/
56static char achBufferDummy64[0x10000] = {0};
57char achBufferDummy128[0x20000] = {0};
58
59int main(int argc, char **argv)
60{
61 void * pvFile;
62
63 if (argc != 2)
64 {
65 fprintf(stderr, "error parameters!\n");
66 return -1;
67 }
68
69 pvFile = readfile(argv[1]);
70 if (pvFile == NULL)
71 {
72 fprintf(stderr, "error reading file %s\n", argv[1]);
73 return -2;
74 }
75
76 return dbgLXDump(pvFile);
77}
78
79
80
81/**
82 * Dumps the internals of LX dubug info.
83 * @returns error code. (0 is ok)
84 * @param pvFile Pointer to filemapping.
85 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
86 */
87int dbgLXDump(void *pvFile)
88{
89 struct exe_hdr * pehdr = (struct exe_hdr *) pvFile;
90 struct e32_exe * pe32;
91 unsigned offe32;
92 PBYTE pbFile = (PBYTE)pvFile;
93
94 /*
95 * Find LX header.
96 */
97 if (pehdr->e_magic == EMAGIC)
98 offe32 = pehdr->e_lfanew;
99 else
100 offe32 = 0;
101 pe32 = (struct e32_exe *)((unsigned)pvFile + offe32);
102 if (pe32->e32_magic[0] != E32MAGIC1 || pe32->e32_magic[1] != E32MAGIC2)
103 {
104 fprintf(stderr, "not LX executable\n");
105 return ERROR_INVALID_EXE_SIGNATURE;
106 }
107
108 /*
109 * Check if there is any debuginfo in this executable.
110 */
111 printf("e32_debuginfo 0x%08x (%d)\n"
112 "e32_debuglen 0x%08x (%d)\n",
113 pe32->e32_debuginfo, pe32->e32_debuglen);
114
115 if (pe32->e32_debuginfo != 0 && pe32->e32_debuglen > 0)
116 {
117 PBYTE pbDbg = pbFile + pe32->e32_debuginfo;
118 /*
119 * Check signature. 'NB0'
120 */
121 printf("Debug signature: %c%c%c%c\n",
122 pbDbg[0], pbDbg[1], pbDbg[2], pbDbg[3]);
123 if (pbDbg[0] == 'N' && pbDbg[1] == 'B' && pbDbg[2] == '0')
124 {
125 int i;
126
127 /*
128 * Switch on debug datatype.
129 */
130 switch (pbDbg[3])
131 {
132 case '0':
133 printf("Found 32-bit Codeview format\n");
134 break;
135
136 case '1':
137 printf("Found AIX Debugger format - unsupported\n");
138 break;
139
140 case '2':
141 printf("Found 16-bit Codeview format\n");
142 break;
143
144 case '4':
145 printf("Found 32-bit OS/2 PM Debugger format (HLL)\n");
146 return dumpHLL(stdout, pbDbg, pe32->e32_debuglen);
147
148 default:
149 printf("Invalid debug type, %c (%d)\n", pbDbg[3], pbDbg[3]);
150 return ERROR_INVALID_DATA;
151 }
152
153 /*
154 * Dump debug data
155 */
156 printf("\ndumps debug data\n");
157 dumpHex(stdout, pbDbg + 4, pe32->e32_debuglen - 4);
158 }
159 else
160 {
161 printf("Invalid debug signature\n");
162 return ERROR_INVALID_DATA;
163 }
164 }
165 else
166 printf(" - no debug info -\n");
167
168 return NO_ERROR;
169}
170
171
172/**
173 * Dumps binary data to file handle.
174 * @param phOut Output file handle.
175 * @param pb Pointer to debug data. (Starts with signature ('NB04').)
176 * @param cb Size of debug data.
177 *
178 * HLL:
179 * Starts with a 4 byte word with the offset (from start of HLL data) to
180 * the number of entries. (what entries is yet to come)
181 *
182 *
183 */
184int dumpHLL(FILE *phOut, PBYTE pb, int cb)
185{
186 int i, j, k; /* loop variables! */
187 unsigned long ulHLLVersion = 0; /* HLL version of the last module. */
188 PHLLDIR pDir;
189 PHLLHDR pHdr = (PHLLHDR)pb;
190
191 /*
192 * Dump header.
193 */
194 fprintf(phOut,
195 "- HLL header -\n"
196 " Signature %.4s\n"
197 " Directory offset 0x%08x (%d)\n"
198 "\n",
199 pHdr->achSignature,
200 pHdr->offDirectory,
201 pHdr->offDirectory);
202
203
204 /*
205 * Get and Dump directory
206 */
207 if (pHdr->offDirectory + sizeof(HLLDIR) > cb)
208 {
209 fprintf(phOut, "error: offDirectory is incorrect! (cb=%d, off=%d)\n",
210 cb, pHdr->offDirectory);
211 return ERROR_INVALID_DATA;
212 }
213 pDir = (PHLLDIR)(pb + pHdr->offDirectory);
214 fprintf(phOut,
215 "- HLL Directory -\n"
216 " Size of this struct 0x%02x (%d)\n"
217 " Size directory entry 0x%02x (%d)\n"
218 " Number of entries 0x%08x (%d)\n",
219 pDir->cb,
220 pDir->cb,
221 pDir->cbEntry,
222 pDir->cbEntry,
223 pDir->cEntries,
224 pDir->cEntries);
225
226
227 /*
228 * Directory sanity check - check that it's not too big
229 */
230 if ((PBYTE)&pDir->aEntries[pDir->cEntries] - pb > cb)
231 {
232 fprintf(phOut, "Error: Directory is to big!\n");
233 return ERROR_INVALID_DATA;
234 }
235
236
237
238 /*
239 * Loop thru the directory.
240 */
241 for (i = 0; i < pDir->cEntries; i++)
242 {
243 /*
244 * Directory entry type descriptions.
245 */
246 static const char * apsz[] =
247 {
248 "HLL_DE_MODULES",
249 "HLL_DE_PUBLICS",
250 "HLL_DE_TYPES",
251 "HLL_DE_SYMBOLS",
252 "HLL_DE_SRCLINES",
253 "HLL_DE_LIBRARIES",
254 "unknown",
255 "unknown",
256 "HLL_DE_SRCLNSEG",
257 "unknown",
258 "HLL_DE_IBMSRC"
259 };
260 const char *pszType = pDir->aEntries[i].usType >= HLL_DE_MODULES
261 && pDir->aEntries[i].usType <= HLL_DE_IBMSRC
262 ? apsz[pDir->aEntries[i].usType - HLL_DE_MODULES]
263 : "unknown";
264
265 /*
266 * Dump directroy info.
267 */
268 fprintf(phOut, "\n"
269 "- HLL Directory Entry %d (0x%x): -\n", i, i);
270 fprintf(phOut, " usType 0x%08x (%d) %s\n"
271 " iMod 0x%08x (%d)\n"
272 " off 0x%08x (%d)\n"
273 " cb 0x%08x (%d)\n",
274 pDir->aEntries[i].usType,
275 pDir->aEntries[i].usType,
276 pszType,
277 pDir->aEntries[i].iMod,
278 pDir->aEntries[i].iMod,
279 pDir->aEntries[i].off,
280 pDir->aEntries[i].off,
281 pDir->aEntries[i].cb,
282 pDir->aEntries[i].cb
283 );
284
285
286
287 /*
288 * Switch between the different entry types to do individual
289 * processing.
290 */
291 switch (pDir->aEntries[i].usType)
292 {
293 /*
294 * Module - debuginfo on an object/source module.
295 */
296 case HLL_DE_MODULES:
297 {
298 PHLLMODULE pModule = (PHLLMODULE)(pDir->aEntries[i].off + pb);
299 PHLLSEGINFO paSegInfo;
300 int c;
301
302 /*
303 * Dump module entry data.
304 */
305 fprintf(phOut,
306 " Modulename: %.*s\n"
307 " overlay %d\n"
308 " ilib %d\n"
309 " pad %d\n"
310 " cSegInfo %d\n"
311 " usDebugStyle %#04x %c%c\n"
312 " HLL Version %d.%d\n"
313 " cchName %d\n"
314 ,
315 pModule->cchName,
316 &pModule->achName[0],
317 pModule->overlay,
318 pModule->iLib,
319 pModule->pad,
320 pModule->cSegInfo,
321 pModule->usDebugStyle,
322 pModule->usDebugStyle & 0xFF,
323 pModule->usDebugStyle >> 8,
324 pModule->chVerMajor,
325 pModule->chVerMinor,
326 pModule->cchName
327 );
328
329 ulHLLVersion = pModule->chVerMajor*0x100 + pModule->chVerMinor;
330
331
332 /*
333 * Dump Segment info
334 */
335 fprintf(phOut,
336 " SegmentInfo %d\n"
337 " iObject %#x\n"
338 " off %#x\n"
339 " cb %#x\n",
340 0,
341 pModule->SegInfo0.iObject,
342 pModule->SegInfo0.off,
343 pModule->SegInfo0.cb);
344
345 c = pModule->cSegInfo > 0 ? pModule->cSegInfo : 0;
346 paSegInfo = (PHLLSEGINFO)((void*)&pModule->achName[pModule->cchName]);
347 for (j = 0; j + 1 < c; j++)
348 {
349 fprintf(phOut,
350 " SegmentInfo %d\n"
351 " iObject %#x\n"
352 " off %#x\n"
353 " cb %#x\n",
354 j + 1,
355 paSegInfo[j].iObject,
356 paSegInfo[j].off,
357 paSegInfo[j].cb);
358 }
359 break;
360 }
361
362
363 case HLL_DE_PUBLICS: /* Public symbols */
364 {
365 PHLLPUBLICSYM pPubSym = (PHLLPUBLICSYM)(pDir->aEntries[i].off + pb);
366
367 while ((char *)pPubSym - pb - pDir->aEntries[i].off < pDir->aEntries[i].cb)
368 {
369 fprintf(phOut,
370 " %#03x:%#08x iType=%#2x name=%.*s\n",
371 pPubSym->iObject,
372 pPubSym->off,
373 pPubSym->iType,
374 pPubSym->cchName,
375 pPubSym->achName);
376
377 /* next */
378 pPubSym = (PHLLPUBLICSYM)&pPubSym->achName[pPubSym->cchName];
379 }
380 break;
381 }
382
383
384 case HLL_DE_TYPES: /* Types */
385 break;
386
387 case HLL_DE_SYMBOLS: /* Symbols */
388 break;
389
390 case HLL_DE_LIBRARIES: /* Libraries */
391 break;
392
393 case HLL_DE_SRCLINES: /* Line numbers - (IBM C/2 1.1) */
394 break;
395
396 case HLL_DE_SRCLNSEG: /* Line numbers - (MSC 6.00) */
397 break;
398
399 /*
400 * Line numbers - (IBM HLL)
401 *
402 * HLL 04 have a FirstEntry before each table.
403 * HLL 03 don't seem to have... This is not implemented yet.
404 */
405 case HLL_DE_IBMSRC:
406 {
407 PHLLFIRSTENTRY pFirstEntry = (PHLLFIRSTENTRY)(pb + pDir->aEntries[i].off);
408 int cbFirstEntry;
409 int cb;
410
411
412 /*
413 * Set the size of an first entry struct based on the HLL version.
414 */
415 if (ulHLLVersion == HLLVERSION100)
416 cbFirstEntry = sizeof(pFirstEntry->hll01);
417 else
418 cbFirstEntry = sizeof(pFirstEntry->hll04);
419
420
421 /*
422 * Loop thru all the arrays in this data directory.
423 * Each array starts with an HLLFIRSTENTRY structure.
424 */
425 cb = pDir->aEntries[i].cb;
426 while (cb >= cbFirstEntry)
427 {
428 int cbEntries;
429
430 /*
431 * Dump the special first entry.
432 */
433 fprintf(phOut,
434 " First entry:\n"
435 " usLine 0x%04x\n"
436 " uchType 0x%02x\n"
437 " uchReserved 0x%02x\n"
438 " cEntries 0x%04x\n"
439 " iSeg 0x%04x\n"
440 " offBase/cb 0x%08x\n",
441 pFirstEntry->hll04.usLine,
442 pFirstEntry->hll04.uchType,
443 pFirstEntry->hll04.uchReserved,
444 pFirstEntry->hll04.cEntries,
445 pFirstEntry->hll04.iSeg,
446 pFirstEntry->hll04.u1.offBase
447 );
448
449 switch (pFirstEntry->hll03.uchType)
450 {
451 /*
452 * Source File information and offset only.
453 */
454 case 0:
455 {
456 int cbLine;
457 PHLLLINENUMBERENTRY pLines =
458 (PHLLLINENUMBERENTRY)((char*)pFirstEntry + cbFirstEntry);
459
460 /*
461 * Determin size of a line entry.
462 */
463 if (ulHLLVersion == HLLVERSION100)
464 cbLine = sizeof(pLines->hll01);
465 else
466 cbLine = sizeof(pLines->hll03);
467
468 /*
469 * Loop thru all the line info and dump it.
470 */
471 fprintf(phOut, " Lineinfo:\n");
472 for (k = 0; k < pFirstEntry->hll01.cEntries; k++) /* cEntries is similar for all formats. */
473 {
474 fprintf(phOut,
475 " usLine=%4d (0x%02x) iusSourceFile=0x%04x off=0x%08x\n",
476 pLines->hll04.usLine,
477 pLines->hll04.usLine,
478 pLines->hll04.iusSourceFile,
479 pLines->hll04.off
480 );
481 /* next */
482 pLines = (PHLLLINENUMBERENTRY)((char*)pLines + cbLine);
483 }
484
485 cbEntries = cbLine * pFirstEntry->hll01.cEntries; /* cEntries is similar for all formats. */
486 break;
487 }
488
489
490 /*
491 * Filenames.
492 */
493 case 3:
494 {
495 PCHAR pch;
496 PHLLFILENAMEENTRY pFilenameEntry =
497 (PHLLFILENAMEENTRY)((char*)pFirstEntry + cbFirstEntry);
498
499 fprintf(phOut,
500 " FilenameEntry:\n"
501 " offSource 0x%08x\n"
502 " cSourceRecords 0x%08x\n"
503 " cSourceFiles 0x%08x\n"
504 " cchName 0x%02x\n",
505 pFilenameEntry->offSource,
506 pFilenameEntry->cSourceRecords,
507 pFilenameEntry->cSourceFiles,
508 pFilenameEntry->cchName
509 );
510
511 fprintf(phOut,
512 " Filenames:\n");
513 pch = &pFilenameEntry->cchName;
514 cbEntries = 0;
515 for (k = 0; k < pFilenameEntry->cSourceFiles; k++)
516 {
517 fprintf(phOut,
518 " %.*s\n", *pch, pch+1);
519 /* next */
520 cbEntries += 1 + *pch;
521 pch += 1 + *pch;
522 }
523
524 if (ulHLLVersion == HLLVERSION100)
525 cbEntries = pFirstEntry->hll01.u1.cbFileNameTable;
526 else
527 cbEntries = pFirstEntry->hll03.u1.cbFileNameTable;
528 cbEntries += offsetof(HLLFILENAMEENTRY, cchName);
529 break;
530 }
531
532
533 default:
534 fprintf(phOut, "warning: unsupported entry type, %d\n", pFirstEntry->hll03.uchType);
535 cbEntries = cb = 0;
536 }
537
538
539 /*
540 * Next
541 */
542 cb -= cbEntries + sizeof(HLLFIRSTENTRY);
543 pFirstEntry = (PHLLFIRSTENTRY)((char*)pFirstEntry + cbEntries + sizeof(HLLFIRSTENTRY));
544 }
545
546 dumpHex(phOut,
547 pDir->aEntries[i].off + pb,
548 pDir->aEntries[i].cb);
549 break;
550 }
551
552 default:
553 fprintf(phOut, " Error - unknown entry type. (%x)\n", pDir->aEntries[i].usType);
554 }
555
556 }
557
558
559 /* - temporary - */
560 printf("\ndumps debug data\n");
561 dumpHex(phOut, pb, cb);
562
563 return NO_ERROR;
564}
565
566
567
568/**
569 * Dumps binary data to file handle.
570 * @param phOut Output file handle.
571 * @param pb Pointer to data.
572 * @param cb Count of bytes to dump.
573 */
574void dumpHex(FILE *phOut, PBYTE pb, int cb)
575{
576 int i;
577
578 for (i = 0; i < cb; i += 16)
579 {
580 int j;
581 /* write offset */
582 fprintf(phOut, "%08x ", i);
583
584 /* write data (hex value) */
585 for (j = 0; j < 16; j++)
586 {
587 int f = i + j < cb;
588 unsigned char uch = f ? pb[i + j] : 0;
589 if (j == 3 || j == 11)
590 fprintf(phOut, f ? "%02x-" : " -", uch);
591 else if (j == 7)
592 fprintf(phOut, f ? "%02x - " : " - ", uch);
593 else
594 fprintf(phOut, f ? "%02x " : " ", uch);
595 }
596 fprintf(phOut, " ");
597
598 /* write ASCII */
599 for (j = 0; j < 16; j++)
600 {
601 if (i + j < cb)
602 {
603 if (isprint(pb[i + j]))
604 fprintf(phOut, "%c", pb[i + j]);
605 else
606 fprintf(phOut, ".");
607 }
608 else
609 fprintf(phOut, " ");
610 }
611 fprintf(phOut, "\n");
612 }
613}
614
615
616
617/**
618 * Creates a memory buffer for a binary file.
619 * @returns Pointer to file memoryblock. NULL on error.
620 * @param pszFilename Pointer to filename string.
621 * @remark This function is the one using most of the execution
622 * time (DosRead + DosOpen) - about 70% of the execution time!
623 */
624void *readfile(const char *pszFilename)
625{
626 void *pvFile = NULL;
627 FILE *phFile;
628
629 phFile = fopen(pszFilename, "rb");
630 if (phFile != NULL)
631 {
632 signed long cbFile = fsize(phFile);
633 if (cbFile > 0)
634 {
635 pvFile = malloc(cbFile + 1);
636 if (pvFile != NULL)
637 {
638 memset(pvFile, 0, cbFile + 1);
639 if (fread(pvFile, 1, cbFile, phFile) == 0)
640 { /* failed! */
641 free(pvFile);
642 pvFile = NULL;
643 }
644 }
645 else
646 fprintf(stderr, "warning/error: failed to open file %s\n", pszFilename);
647 }
648 fclose(phFile);
649 }
650 return pvFile;
651}
652
653
654
655/**
656 * Find the size of a file.
657 * @returns Size of file. -1 on error.
658 * @param phFile File handle.
659 */
660signed long fsize(FILE *phFile)
661{
662 int ipos;
663 signed long cb;
664
665 if ((ipos = ftell(phFile)) < 0
666 ||
667 fseek(phFile, 0, SEEK_END) != 0
668 ||
669 (cb = ftell(phFile)) < 0
670 ||
671 fseek(phFile, ipos, SEEK_SET) != 0
672 )
673 cb = -1;
674 return cb;
675}
676
Note: See TracBrowser for help on using the repository browser.