| 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 | *******************************************************************************/
|
|---|
| 45 | int dbgLXDump(void *pvFile);
|
|---|
| 46 | int dumpHLL(FILE *phOut, PBYTE pb, int cb);
|
|---|
| 47 | void dumpHex(FILE *phOut, PBYTE pb, int cb);
|
|---|
| 48 | void * readfile(const char *pszFilename);
|
|---|
| 49 | signed long fsize(FILE *phFile);
|
|---|
| 50 |
|
|---|
| 51 |
|
|---|
| 52 |
|
|---|
| 53 | /*******************************************************************************
|
|---|
| 54 | * Global Variables *
|
|---|
| 55 | *******************************************************************************/
|
|---|
| 56 | static char achBufferDummy64[0x10000] = {0};
|
|---|
| 57 | char achBufferDummy128[0x20000] = {0};
|
|---|
| 58 |
|
|---|
| 59 | int 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 | */
|
|---|
| 87 | int 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 | */
|
|---|
| 184 | int 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 | */
|
|---|
| 574 | void 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 | */
|
|---|
| 624 | void *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 | */
|
|---|
| 660 | signed 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 |
|
|---|