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

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

Removed ulReserved from HLLHDR.
ulReserved from HLLDIR is two shorts, cb and cbEntry.

File size: 14.7 KB
Line 
1/* $Id: dbgLXDumper.c,v 1.5 2000-03-27 12:36:16 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
20/*******************************************************************************
21* Header Files *
22*******************************************************************************/
23#include <os2.h>
24#include <newexe.h>
25#include <exe386.h>
26
27#include <malloc.h>
28#include <string.h>
29#include <stdio.h>
30#include <stddef.h>
31#include <ctype.h>
32
33#include "hll.h"
34
35
36
37/*******************************************************************************
38* Internal Functions *
39*******************************************************************************/
40int dbgLXDump(void *pvFile);
41int dumpHLL(FILE *phOut, PBYTE pb, int cb);
42void dumpHex(FILE *phOut, PBYTE pb, int cb);
43void * readfile(const char *pszFilename);
44signed long fsize(FILE *phFile);
45
46
47
48/*******************************************************************************
49* Global Variables *
50*******************************************************************************/
51static char achBufferDummy64[0x10000] = {0};
52char achBufferDummy128[0x20000] = {0};
53
54int main(int argc, char **argv)
55{
56 void * pvFile;
57
58 if (argc != 2)
59 {
60 fprintf(stderr, "error parameters!\n");
61 return -1;
62 }
63
64 pvFile = readfile(argv[1]);
65 if (pvFile == NULL)
66 {
67 fprintf(stderr, "error reading file %s\n", argv[1]);
68 return -2;
69 }
70
71 return dbgLXDump(pvFile);
72}
73
74
75
76/**
77 * Dumps the internals of LX dubug info.
78 * @returns error code. (0 is ok)
79 * @param pvFile Pointer to filemapping.
80 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
81 */
82int dbgLXDump(void *pvFile)
83{
84 struct exe_hdr * pehdr = (struct exe_hdr *) pvFile;
85 struct e32_exe * pe32;
86 unsigned offe32;
87 PBYTE pbFile = (PBYTE)pvFile;
88
89 /*
90 * Find LX header.
91 */
92 if (pehdr->e_magic == EMAGIC)
93 offe32 = pehdr->e_lfanew;
94 else
95 offe32 = 0;
96 pe32 = (struct e32_exe *)((unsigned)pvFile + offe32);
97 if (pe32->e32_magic[0] != E32MAGIC1 || pe32->e32_magic[1] != E32MAGIC2)
98 {
99 fprintf(stderr, "not LX executable\n");
100 return ERROR_INVALID_EXE_SIGNATURE;
101 }
102
103 /*
104 * Check if there is any debuginfo in this executable.
105 */
106 printf("e32_debuginfo 0x%08x (%d)\n"
107 "e32_debuglen 0x%08x (%d)\n",
108 pe32->e32_debuginfo, pe32->e32_debuglen);
109
110 if (pe32->e32_debuginfo != 0 && pe32->e32_debuglen > 0)
111 {
112 PBYTE pbDbg = pbFile + pe32->e32_debuginfo;
113 /*
114 * Check signature. 'NB0'
115 */
116 printf("Debug signature: %c%c%c%c\n",
117 pbDbg[0], pbDbg[1], pbDbg[2], pbDbg[3]);
118 if (pbDbg[0] == 'N' && pbDbg[1] == 'B' && pbDbg[2] == '0')
119 {
120 int i;
121
122 /*
123 * Switch on debug datatype.
124 */
125 switch (pbDbg[3])
126 {
127 case '0':
128 printf("Found 32-bit Codeview format\n");
129 break;
130
131 case '1':
132 printf("Found AIX Debugger format - unsupported\n");
133 break;
134
135 case '2':
136 printf("Found 16-bit Codeview format\n");
137 break;
138
139 case '4':
140 printf("Found 32-bit OS/2 PM Debugger format (HLL)\n");
141 return dumpHLL(stdout, pbDbg, pe32->e32_debuglen);
142
143 default:
144 printf("Invalid debug type, %c (%d)\n", pbDbg[3], pbDbg[3]);
145 return ERROR_INVALID_DATA;
146 }
147
148 /*
149 * Dump debug data
150 */
151 printf("\ndumps debug data\n");
152 dumpHex(stdout, pbDbg + 4, pe32->e32_debuglen - 4);
153 }
154 else
155 {
156 printf("Invalid debug signature\n");
157 return ERROR_INVALID_DATA;
158 }
159 }
160 else
161 printf(" - no debug info -\n");
162
163 return NO_ERROR;
164}
165
166
167/**
168 * Dumps binary data to file handle.
169 * @param phOut Output file handle.
170 * @param pb Pointer to debug data. (Starts with signature ('NB04').)
171 * @param cb Size of debug data.
172 *
173 * HLL:
174 * Starts with a 4 byte word with the offset (from start of HLL data) to
175 * the number of entries. (what entries is yet to come)
176 *
177 *
178 */
179int dumpHLL(FILE *phOut, PBYTE pb, int cb)
180{
181 PHLLDIR pDir;
182 int i;
183 PHLLHDR pHdr = (PHLLHDR)pb;
184
185 /*
186 * Dump header.
187 */
188 fprintf(phOut,
189 "- HLL header -\n"
190 " Signature %.4s\n"
191 " Directory offset 0x%08x (%d)\n"
192 "\n",
193 pHdr->achSignature,
194 pHdr->offDirectory,
195 pHdr->offDirectory);
196
197
198 /*
199 * Get and Dump directory
200 */
201 if (pHdr->offDirectory + sizeof(HLLDIR) > cb)
202 {
203 fprintf(phOut, "error: offDirectory is incorrect! (cb=%d, off=%d)\n",
204 cb, pHdr->offDirectory);
205 return ERROR_INVALID_DATA;
206 }
207 pDir = (PHLLDIR)(pb + pHdr->offDirectory);
208 fprintf(phOut,
209 "- HLL Directory -\n"
210 " Size of this struct 0x%02x (%d)\n"
211 " Size directory entry 0x%02x (%d)\n"
212 " Number of entries 0x%08x (%d)\n",
213 pDir->cb,
214 pDir->cb,
215 pDir->cbEntry,
216 pDir->cbEntry,
217 pDir->cEntries,
218 pDir->cEntries);
219
220
221 /*
222 * Directory sanity check - check that it's not too big
223 */
224 if ((PBYTE)&pDir->aEntries[pDir->cEntries] - pb > cb)
225 {
226 fprintf(phOut, "Error: Directory is to big!\n");
227 return ERROR_INVALID_DATA;
228 }
229
230
231
232 /*
233 * Loop thru the directory.
234 */
235 for (i = 0; i < pDir->cEntries; i++)
236 {
237 /*
238 * Directory entry type descriptions.
239 */
240 static const char * apsz[] =
241 {
242 "HLL_DE_MODULES",
243 "HLL_DE_PUBLICS",
244 "HLL_DE_TYPES",
245 "HLL_DE_SYMBOLS",
246 "HLL_DE_SRCLINES",
247 "HLL_DE_LIBRARIES",
248 "unknown",
249 "unknown",
250 "HLL_DE_SRCLNSEG",
251 "unknown",
252 "HLL_DE_IBMSRC"
253 };
254 const char *pszType = pDir->aEntries[i].usType >= HLL_DE_MODULES
255 && pDir->aEntries[i].usType <= HLL_DE_IBMSRC
256 ? apsz[pDir->aEntries[i].usType - HLL_DE_MODULES]
257 : "unknown";
258
259 /*
260 * Dump directroy info.
261 */
262 fprintf(phOut, "\n"
263 "- HLL Directory Entry %d (0x%x): -\n", i, i);
264 fprintf(phOut, " usType 0x%08x (%d) %s\n"
265 " iMod 0x%08x (%d)\n"
266 " off 0x%08x (%d)\n"
267 " cb 0x%08x (%d)\n",
268 pDir->aEntries[i].usType,
269 pDir->aEntries[i].usType,
270 pszType,
271 pDir->aEntries[i].iMod,
272 pDir->aEntries[i].iMod,
273 pDir->aEntries[i].off,
274 pDir->aEntries[i].off,
275 pDir->aEntries[i].cb,
276 pDir->aEntries[i].cb
277 );
278
279
280
281 /*
282 * Switch between the different entry types to do individual
283 * processing.
284 */
285 switch (pDir->aEntries[i].usType)
286 {
287 /*
288 * Module - debuginfo on an object/source module.
289 */
290 case HLL_DE_MODULES:
291 {
292 PHLLMODULE pModule = (PHLLMODULE)(pDir->aEntries[i].off + pb);
293 PHLLSEGINFO paSegInfo;
294 int j, c;
295
296 /*
297 * Dump module entry data.
298 */
299 fprintf(phOut,
300 " Modulename: %.*s\n"
301 " overlay %d\n"
302 " ilib %d\n"
303 " pad %d\n"
304 " cSegInfo %d\n"
305 " usDebugStyle %#04x %c%c\n"
306 " HLL Version %d.%d\n"
307 " cchName %d\n"
308 ,
309 pModule->cchName,
310 &pModule->achName[0],
311 pModule->overlay,
312 pModule->iLib,
313 pModule->pad,
314 pModule->cSegInfo,
315 pModule->usDebugStyle,
316 pModule->usDebugStyle & 0xFF,
317 pModule->usDebugStyle >> 8,
318 pModule->chVerMajor,
319 pModule->chVerMinor,
320 pModule->cchName
321 );
322
323
324 /*
325 * Dump Segment info
326 */
327 fprintf(phOut,
328 " SegmentInfo %d\n"
329 " iObject %#x\n"
330 " off %#x\n"
331 " cb %#x\n",
332 0,
333 pModule->SegInfo0.iObject,
334 pModule->SegInfo0.off,
335 pModule->SegInfo0.cb);
336
337 c = pModule->cSegInfo > 0 ? pModule->cSegInfo : 0;
338 paSegInfo = (PHLLSEGINFO)((void*)&pModule->achName[pModule->cchName]);
339 for (j = 0; j + 1 < c; j++)
340 {
341 fprintf(phOut,
342 " SegmentInfo %d\n"
343 " iObject %#x\n"
344 " off %#x\n"
345 " cb %#x\n",
346 j + 1,
347 paSegInfo[j].iObject,
348 paSegInfo[j].off,
349 paSegInfo[j].cb);
350 }
351 break;
352 }
353
354
355 case HLL_DE_PUBLICS: /* Public symbols */
356 {
357 PHLLPUBLICSYM pPubSym = (PHLLPUBLICSYM)(pDir->aEntries[i].off + pb);
358
359 while ((char *)pPubSym - pb - pDir->aEntries[i].off < pDir->aEntries[i].cb)
360 {
361 fprintf(phOut,
362 " %#03x:%#08x iType=%#2x name=%.*s\n",
363 pPubSym->iObject,
364 pPubSym->off,
365 pPubSym->iType,
366 pPubSym->cchName,
367 pPubSym->achName);
368
369 /* next */
370 pPubSym = (PHLLPUBLICSYM)&pPubSym->achName[pPubSym->cchName];
371 }
372 break;
373 }
374
375
376 case HLL_DE_TYPES: /* Types */
377 break;
378
379 case HLL_DE_SYMBOLS: /* Symbols */
380 break;
381
382 case HLL_DE_LIBRARIES: /* Libraries */
383 break;
384
385 case HLL_DE_SRCLINES: /* Line numbers - (IBM C/2 1.1) */
386 break;
387
388 case HLL_DE_SRCLNSEG: /* Line numbers - (MSC 6.00) */
389 break;
390
391 case HLL_DE_IBMSRC: /* Line numbers - (IBM HLL) */
392 break;
393
394 default:
395 fprintf(phOut, " Error - unknown entry type. (%x)\n", pDir->aEntries[i].usType);
396 }
397
398 }
399
400
401 /* - temporary - */
402 printf("\ndumps debug data\n");
403 dumpHex(stdout, pb, cb);
404
405 return NO_ERROR;
406}
407
408
409
410/**
411 * Dumps binary data to file handle.
412 * @param phOut Output file handle.
413 * @param pb Pointer to data.
414 * @param cb Count of bytes to dump.
415 */
416void dumpHex(FILE *phOut, PBYTE pb, int cb)
417{
418 int i;
419
420 for (i = 0; i < cb; i += 16)
421 {
422 int j;
423 /* write offset */
424 fprintf(phOut, "%08x ", i);
425
426 /* write data (hex value) */
427 for (j = 0; j < 16; j++)
428 {
429 int f = i + j < cb;
430 unsigned char uch = f ? pb[i + j] : 0;
431 if (j == 3 || j == 11)
432 fprintf(phOut, f ? "%02x-" : " -", uch);
433 else if (j == 7)
434 fprintf(phOut, f ? "%02x - " : " - ", uch);
435 else
436 fprintf(phOut, f ? "%02x " : " ", uch);
437 }
438 fprintf(phOut, " ");
439
440 /* write ASCII */
441 for (j = 0; j < 16; j++)
442 {
443 if (i + j < cb)
444 {
445 if (isprint(pb[i + j]))
446 fprintf(phOut, "%c", pb[i + j]);
447 else
448 fprintf(phOut, ".");
449 }
450 else
451 fprintf(phOut, " ");
452 }
453 fprintf(phOut, "\n");
454 }
455}
456
457
458
459/**
460 * Creates a memory buffer for a binary file.
461 * @returns Pointer to file memoryblock. NULL on error.
462 * @param pszFilename Pointer to filename string.
463 * @remark This function is the one using most of the execution
464 * time (DosRead + DosOpen) - about 70% of the execution time!
465 */
466void *readfile(const char *pszFilename)
467{
468 void *pvFile = NULL;
469 FILE *phFile;
470
471 phFile = fopen(pszFilename, "rb");
472 if (phFile != NULL)
473 {
474 signed long cbFile = fsize(phFile);
475 if (cbFile > 0)
476 {
477 pvFile = malloc(cbFile + 1);
478 if (pvFile != NULL)
479 {
480 memset(pvFile, 0, cbFile + 1);
481 if (fread(pvFile, 1, cbFile, phFile) == 0)
482 { /* failed! */
483 free(pvFile);
484 pvFile = NULL;
485 }
486 }
487 else
488 fprintf(stderr, "warning/error: failed to open file %s\n", pszFilename);
489 }
490 fclose(phFile);
491 }
492 return pvFile;
493}
494
495
496
497/**
498 * Find the size of a file.
499 * @returns Size of file. -1 on error.
500 * @param phFile File handle.
501 */
502signed long fsize(FILE *phFile)
503{
504 int ipos;
505 signed long cb;
506
507 if ((ipos = ftell(phFile)) < 0
508 ||
509 fseek(phFile, 0, SEEK_END) != 0
510 ||
511 (cb = ftell(phFile)) < 0
512 ||
513 fseek(phFile, ipos, SEEK_SET) != 0
514 )
515 cb = -1;
516 return cb;
517}
518
Note: See TracBrowser for help on using the repository browser.