| 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 |  | 
|---|