[8] | 1 | /*
|
---|
| 2 | *@@sourcefile debug.c:
|
---|
| 3 | * this file contains debugging functions for the
|
---|
| 4 | * exception handlers in except.c.
|
---|
| 5 | *
|
---|
| 6 | * This code is capable of unwinding the stack from
|
---|
| 7 | * a given address and trying to get function names
|
---|
| 8 | * and source line numbers, either from the respective
|
---|
| 9 | * module's debug code (if present) or from a SYM file,
|
---|
| 10 | * which is searched for in the directory of the module
|
---|
| 11 | * or in ?:\OS2\PDPSI\PMDF\WARP4.
|
---|
| 12 | *
|
---|
| 13 | * This file incorporates code from the following:
|
---|
| 14 | * -- Marc Fiammante, John Currier, Kim Rasmussen,
|
---|
| 15 | * Anthony Cruise (EXCEPT3.ZIP package for a generic
|
---|
| 16 | * exception handling DLL, available at Hobbes).
|
---|
| 17 | *
|
---|
| 18 | * Usage: All OS/2 programs.
|
---|
| 19 | *
|
---|
| 20 | * Note: Version numbering in this file relates to XWorkplace version
|
---|
| 21 | * numbering.
|
---|
| 22 | *
|
---|
| 23 | *@@changed V0.9.0 [umoeller]: made some declarations C++-compatible
|
---|
| 24 | *@@changed V0.9.1 (2000-01-30) [umoeller]: greatly cleaned up this file
|
---|
| 25 | *
|
---|
| 26 | *@@header "helpers\debug.h"
|
---|
| 27 | */
|
---|
| 28 |
|
---|
| 29 | /*
|
---|
[384] | 30 | * This file Copyright (C) 1992-2010 Ulrich Mller,
|
---|
| 31 | * Kim Rasmussen,
|
---|
| 32 | * Marc Fiammante,
|
---|
| 33 | * John Currier,
|
---|
| 34 | * Anthony Cruise.
|
---|
[14] | 35 | * This file is part of the "XWorkplace helpers" source package.
|
---|
| 36 | * This is free software; you can redistribute it and/or modify
|
---|
[8] | 37 | * it under the terms of the GNU General Public License as published
|
---|
| 38 | * by the Free Software Foundation, in version 2 as it comes in the
|
---|
| 39 | * "COPYING" file of the XWorkplace main distribution.
|
---|
| 40 | * This program is distributed in the hope that it will be useful,
|
---|
| 41 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 42 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
| 43 | * GNU General Public License for more details.
|
---|
| 44 | */
|
---|
| 45 |
|
---|
[229] | 46 | //#define DEBUG_SYMDUMP // enable to dump sym file to log V1.0.0 (2002-08-21) [paperino]
|
---|
[212] | 47 |
|
---|
[8] | 48 | #define OS2EMX_PLAIN_CHAR
|
---|
| 49 | // this is needed for "os2emx.h"; if this is defined,
|
---|
| 50 | // emx will define PSZ as _signed_ char, otherwise
|
---|
| 51 | // as unsigned char
|
---|
| 52 |
|
---|
[14] | 53 | #define INCL_DOSPROCESS
|
---|
| 54 | #define INCL_DOSMODULEMGR
|
---|
| 55 | #define INCL_DOSMISC
|
---|
| 56 | #define INCL_DOSERRORS
|
---|
[8] | 57 | #include <os2.h>
|
---|
| 58 |
|
---|
| 59 | #include <stdlib.h>
|
---|
| 60 | #include <stdio.h>
|
---|
| 61 | #include <string.h>
|
---|
| 62 |
|
---|
| 63 | #define DONT_REPLACE_MALLOC
|
---|
| 64 | #include "setup.h" // code generation and debugging options
|
---|
| 65 |
|
---|
| 66 | #include "helpers\debug.h"
|
---|
| 67 | #include "helpers\dosh.h"
|
---|
| 68 |
|
---|
| 69 | #pragma hdrstop
|
---|
| 70 |
|
---|
| 71 | #include <fcntl.h>
|
---|
| 72 | #ifdef __EMX__
|
---|
| 73 | #include <sys\types.h> // required for sys\stat.h; UM 99-10-22
|
---|
| 74 | #endif
|
---|
| 75 | #include <sys\stat.h>
|
---|
| 76 | #include <share.h>
|
---|
| 77 | #include <io.h>
|
---|
| 78 |
|
---|
| 79 | #ifndef DWORD
|
---|
| 80 | #define DWORD unsigned long
|
---|
| 81 | #endif
|
---|
| 82 | #ifndef WORD
|
---|
| 83 | #define WORD unsigned short
|
---|
| 84 | #endif
|
---|
| 85 |
|
---|
| 86 | #pragma stack16(512)
|
---|
| 87 | #define HF_STDERR 2
|
---|
| 88 |
|
---|
| 89 | /*
|
---|
| 90 | *@@category: Helpers\Control program helpers\Exceptions/debugging
|
---|
[21] | 91 | * See except.c and debug.c.
|
---|
[8] | 92 | */
|
---|
| 93 |
|
---|
| 94 | /* ******************************************************************
|
---|
[14] | 95 | *
|
---|
| 96 | * Global variables
|
---|
| 97 | *
|
---|
[8] | 98 | ********************************************************************/
|
---|
| 99 |
|
---|
| 100 | // this specifies whether we're dealing with 32-bit code;
|
---|
| 101 | // this gets changed whenever 16-bit count is detected
|
---|
[222] | 102 | STATIC BOOL f32bit = TRUE;
|
---|
[8] | 103 |
|
---|
| 104 | /*
|
---|
| 105 | * Global variables for Read32PmDebug:
|
---|
| 106 | *
|
---|
| 107 | */
|
---|
| 108 |
|
---|
| 109 | ULONG func_ofs;
|
---|
| 110 | ULONG pubfunc_ofs;
|
---|
| 111 | char func_name[128];
|
---|
| 112 | ULONG var_ofs = 0;
|
---|
| 113 |
|
---|
| 114 | struct {
|
---|
| 115 | BYTE name[128];
|
---|
| 116 | ULONG stack_offset;
|
---|
| 117 | USHORT type_idx;
|
---|
| 118 | } autovar_def[100];
|
---|
| 119 |
|
---|
| 120 | #pragma pack(1)
|
---|
| 121 |
|
---|
| 122 | BYTE *type_name[] =
|
---|
| 123 | {
|
---|
| 124 | "8 bit signed ",
|
---|
| 125 | "16 bit signed ",
|
---|
| 126 | "32 bit signed ",
|
---|
| 127 | "Unknown (0x83) ",
|
---|
| 128 | "8 bit unsigned ",
|
---|
| 129 | "16 bit unsigned ",
|
---|
| 130 | "32 bit unsigned ",
|
---|
| 131 | "Unknown (0x87) ",
|
---|
| 132 | "32 bit real ",
|
---|
| 133 | "64 bit real ",
|
---|
| 134 | "80 bit real ",
|
---|
| 135 | "Unknown (0x8B) ",
|
---|
| 136 | "64 bit complex ",
|
---|
| 137 | "128 bit complex ",
|
---|
| 138 | "160 bit complex ",
|
---|
| 139 | "Unknown (0x8F) ",
|
---|
| 140 | "8 bit boolean ",
|
---|
| 141 | "16 bit boolean ",
|
---|
| 142 | "32 bit boolean ",
|
---|
| 143 | "Unknown (0x93) ",
|
---|
| 144 | "8 bit character ",
|
---|
| 145 | "16 bit characters ",
|
---|
| 146 | "32 bit characters ",
|
---|
| 147 | "void ",
|
---|
| 148 | "15 bit unsigned ",
|
---|
| 149 | "24 bit unsigned ",
|
---|
| 150 | "31 bit unsigned ",
|
---|
| 151 | "Unknown (0x9B) ",
|
---|
| 152 | "Unknown (0x9C) ",
|
---|
| 153 | "Unknown (0x9D) ",
|
---|
| 154 | "Unknown (0x9E) ",
|
---|
| 155 | "Unknown (0x9F) ",
|
---|
| 156 | "near pointer to 8 bit signed ",
|
---|
| 157 | "near pointer to 16 bit signed ",
|
---|
| 158 | "near pointer to 32 bit signed ",
|
---|
| 159 | "Unknown (0xA3) ",
|
---|
| 160 | "near pointer to 8 bit unsigned ",
|
---|
| 161 | "near pointer to 16 bit unsigned ",
|
---|
| 162 | "near pointer to 32 bit unsigned ",
|
---|
| 163 | "Unknown (0xA7) ",
|
---|
| 164 | "near pointer to 32 bit real ",
|
---|
| 165 | "near pointer to 64 bit real ",
|
---|
| 166 | "near pointer to 80 bit real ",
|
---|
| 167 | "Unknown (0xAB) ",
|
---|
| 168 | "near pointer to 64 bit complex ",
|
---|
| 169 | "near pointer to 128 bit complex ",
|
---|
| 170 | "near pointer to 160 bit complex ",
|
---|
| 171 | "Unknown (0xAF) ",
|
---|
| 172 | "near pointer to 8 bit boolean ",
|
---|
| 173 | "near pointer to 16 bit boolean ",
|
---|
| 174 | "near pointer to 32 bit boolean ",
|
---|
| 175 | "Unknown (0xB3) ",
|
---|
| 176 | "near pointer to 8 bit character ",
|
---|
| 177 | "near pointer to 16 bit characters",
|
---|
| 178 | "near pointer to 32 bit characters",
|
---|
| 179 | "near pointer to void ",
|
---|
| 180 | "near pointer to 15 bit unsigned ",
|
---|
| 181 | "near pointer to 24 bit unsigned ",
|
---|
| 182 | "near pointer to 31 bit unsigned ",
|
---|
| 183 | "Unknown (0xBB) ",
|
---|
| 184 | "Unknown (0xBC) ",
|
---|
| 185 | "Unknown (0xBD) ",
|
---|
| 186 | "Unknown (0xBE) ",
|
---|
| 187 | "Unknown (0xBF) ",
|
---|
| 188 | "far pointer to 8 bit signed ",
|
---|
| 189 | "far pointer to 16 bit signed ",
|
---|
| 190 | "far pointer to 32 bit signed ",
|
---|
| 191 | "Unknown (0xC3) ",
|
---|
| 192 | "far pointer to 8 bit unsigned ",
|
---|
| 193 | "far pointer to 16 bit unsigned ",
|
---|
| 194 | "far pointer to 32 bit unsigned ",
|
---|
| 195 | "Unknown (0xC7) ",
|
---|
| 196 | "far pointer to 32 bit real ",
|
---|
| 197 | "far pointer to 64 bit real ",
|
---|
| 198 | "far pointer to 80 bit real ",
|
---|
| 199 | "Unknown (0xCB) ",
|
---|
| 200 | "far pointer to 64 bit complex ",
|
---|
| 201 | "far pointer to 128 bit complex ",
|
---|
| 202 | "far pointer to 160 bit complex ",
|
---|
| 203 | "Unknown (0xCF) ",
|
---|
| 204 | "far pointer to 8 bit boolean ",
|
---|
| 205 | "far pointer to 16 bit boolean ",
|
---|
| 206 | "far pointer to 32 bit boolean ",
|
---|
| 207 | "Unknown (0xD3) ",
|
---|
| 208 | "far pointer to 8 bit character ",
|
---|
| 209 | "far pointer to 16 bit characters ",
|
---|
| 210 | "far pointer to 32 bit characters ",
|
---|
| 211 | "far pointer to void ",
|
---|
| 212 | "far pointer to 15 bit unsigned ",
|
---|
| 213 | "far pointer to 24 bit unsigned ",
|
---|
| 214 | "far pointer to 31 bit unsigned ",
|
---|
| 215 | };
|
---|
| 216 |
|
---|
| 217 | // Thanks to John Currier:
|
---|
| 218 | // Do not call 16 bit code in myHandler function to prevent call
|
---|
| 219 | // to __EDCThunkProlog and problems is guard page exception handling
|
---|
| 220 | // Also reduce the stack size to 1K for true 16 bit calls.
|
---|
| 221 | // 16 bit calls thunk will now only occur on fatal exceptions
|
---|
| 222 | #pragma stack16(1024)
|
---|
| 223 |
|
---|
| 224 | // ------------------------------------------------------------------
|
---|
| 225 | // Last 8 bytes of 16:16 file when CODEVIEW debugging info is present
|
---|
| 226 | #pragma pack(1)
|
---|
| 227 | struct _eodbug
|
---|
| 228 | {
|
---|
| 229 | unsigned short dbug; // 'NB' signature
|
---|
| 230 | unsigned short ver; // version
|
---|
| 231 | unsigned long dfaBase; // size of codeview info
|
---|
| 232 | } G_eodbug;
|
---|
| 233 |
|
---|
| 234 | #define DBUGSIG 0x424E
|
---|
| 235 | #define SSTMODULES 0x0101
|
---|
| 236 | #define SSTPUBLICS 0x0102
|
---|
| 237 | #define SSTTYPES 0x0103
|
---|
| 238 | #define SSTSYMBOLS 0x0104
|
---|
| 239 | #define SSTSRCLINES 0x0105
|
---|
| 240 | #define SSTLIBRARIES 0x0106
|
---|
| 241 | #define SSTSRCLINES2 0x0109
|
---|
| 242 | #define SSTSRCLINES32 0x010B
|
---|
| 243 |
|
---|
| 244 | typedef struct _SYMBASE
|
---|
| 245 | {
|
---|
| 246 | unsigned short dbug; // 'NB' signature
|
---|
| 247 | unsigned short ver; // version
|
---|
| 248 | unsigned long lfoDir; // file offset to dir entries
|
---|
| 249 | } SYMBASE;
|
---|
| 250 |
|
---|
| 251 | typedef struct _SSDIR
|
---|
| 252 | {
|
---|
| 253 | unsigned short sst; // SubSection Type
|
---|
| 254 | unsigned short modindex; // Module index number
|
---|
| 255 | unsigned long lfoStart; // Start of section
|
---|
| 256 | unsigned short cb; // Size of section
|
---|
| 257 | } SSDIR;
|
---|
| 258 |
|
---|
| 259 | typedef struct _SSDIR32
|
---|
| 260 | {
|
---|
| 261 | unsigned short sst; // SubSection Type
|
---|
| 262 | unsigned short modindex; // Module index number
|
---|
| 263 | unsigned long lfoStart; // Start of section
|
---|
| 264 | unsigned long cb; // Size of section
|
---|
| 265 | } SSDIR32;
|
---|
| 266 |
|
---|
| 267 | typedef struct _SSMODULE
|
---|
| 268 | {
|
---|
| 269 | unsigned short csBase; // code segment base
|
---|
| 270 | unsigned short csOff; // code segment offset
|
---|
| 271 | unsigned short csLen; // code segment length
|
---|
| 272 | unsigned short ovrNum; // overlay number
|
---|
| 273 | unsigned short indxSS; // Index into sstLib or 0
|
---|
| 274 | unsigned short reserved;
|
---|
| 275 | char csize; // size of prefix string
|
---|
| 276 | } SSMODULE;
|
---|
| 277 |
|
---|
| 278 | typedef struct _SSMOD32
|
---|
| 279 | {
|
---|
| 280 | unsigned short csBase; // code segment base
|
---|
| 281 | unsigned long csOff; // code segment offset
|
---|
| 282 | unsigned long csLen; // code segment length
|
---|
| 283 | unsigned long ovrNum; // overlay number
|
---|
| 284 | unsigned short indxSS; // Index into sstLib or 0
|
---|
| 285 | unsigned long reserved;
|
---|
| 286 | char csize; // size of prefix string
|
---|
| 287 | } SSMOD32;
|
---|
| 288 |
|
---|
| 289 | typedef struct _SSPUBLIC
|
---|
| 290 | {
|
---|
| 291 | unsigned short offset;
|
---|
| 292 | unsigned short segment;
|
---|
| 293 | unsigned short type;
|
---|
| 294 | char csize;
|
---|
| 295 | } SSPUBLIC;
|
---|
| 296 |
|
---|
| 297 | typedef struct _SSPUBLIC32
|
---|
| 298 | {
|
---|
| 299 | unsigned long offset;
|
---|
| 300 | unsigned short segment;
|
---|
| 301 | unsigned short type;
|
---|
| 302 | char csize;
|
---|
| 303 | } SSPUBLIC32;
|
---|
| 304 |
|
---|
| 305 | typedef struct _SSLINEENTRY32
|
---|
| 306 | {
|
---|
| 307 | unsigned short LineNum;
|
---|
| 308 | unsigned short FileNum;
|
---|
| 309 | unsigned long Offset;
|
---|
| 310 | } SSLINEENTRY32;
|
---|
| 311 |
|
---|
| 312 | typedef struct _FIRSTLINEENTRY32
|
---|
| 313 | {
|
---|
| 314 | unsigned short LineNum;
|
---|
| 315 | unsigned char entry_type;
|
---|
| 316 | unsigned char reserved;
|
---|
| 317 | unsigned short numlines;
|
---|
| 318 | unsigned short segnum;
|
---|
| 319 | } FIRSTLINEENTRY32;
|
---|
| 320 |
|
---|
| 321 | typedef struct _SSFILENUM32
|
---|
| 322 | {
|
---|
| 323 | unsigned long first_displayable; // Not used
|
---|
| 324 | unsigned long number_displayable; // Not used
|
---|
| 325 | unsigned long file_count; // number of source files
|
---|
| 326 | } SSFILENUM32;
|
---|
| 327 |
|
---|
| 328 | /*
|
---|
| 329 | *@@ XDEBUGINFO:
|
---|
| 330 | * buffers for Read... funcs.
|
---|
| 331 | *
|
---|
| 332 | *@@added V0.9.4 (2000-06-15) [umoeller]
|
---|
| 333 | */
|
---|
| 334 |
|
---|
| 335 | typedef struct _XDEBUGINFO
|
---|
| 336 | {
|
---|
| 337 | char szNrFile[300]; // receives source file
|
---|
| 338 | char szNrLine[300]; // receives line number
|
---|
| 339 | char szNrPub[300]; // receives function name
|
---|
| 340 |
|
---|
| 341 | struct new_seg *pseg;
|
---|
| 342 | struct o32_obj *pobj; // flat .EXE object table entry
|
---|
| 343 |
|
---|
| 344 | SYMBASE base;
|
---|
| 345 |
|
---|
| 346 | SSDIR *pDirTab;
|
---|
| 347 | SSDIR32 *pDirTab32;
|
---|
| 348 | unsigned char *pEntTab;
|
---|
| 349 | unsigned long lfaBase;
|
---|
| 350 | SSMOD32 ssmod32;
|
---|
| 351 | SSPUBLIC32 sspub32;
|
---|
| 352 |
|
---|
| 353 | SSMODULE ssmod;
|
---|
| 354 | SSPUBLIC sspub;
|
---|
| 355 | } XDEBUGINFO, *PXDEBUGINFO;
|
---|
| 356 |
|
---|
| 357 | #pragma pack()
|
---|
| 358 |
|
---|
| 359 | /* ******************************************************************
|
---|
[14] | 360 | *
|
---|
| 361 | * PART 1: ANALYZE DEBUG CODE
|
---|
| 362 | *
|
---|
[8] | 363 | ********************************************************************/
|
---|
| 364 |
|
---|
[222] | 365 | STATIC int Read16CodeView(FILE *LogFile, PXDEBUGINFO pxdi, int fh, int TrapSeg, int TrapOff, CHAR *FileName);
|
---|
| 366 | STATIC int Read32PmDebug(FILE *LogFile, PXDEBUGINFO pxdi, int fh, int TrapSeg, int TrapOff, CHAR *FileName);
|
---|
[8] | 367 |
|
---|
| 368 | /*
|
---|
[68] | 369 | *@@ WriteAddressInfo:
|
---|
| 370 | * formats and writes a line into the trap log
|
---|
| 371 | * file.
|
---|
| 372 | *
|
---|
| 373 | * This gets called for each line from the
|
---|
| 374 | * stack dump. At this point, the line in the
|
---|
| 375 | * trap log already has:
|
---|
| 376 | *
|
---|
| 377 | + CS:EIP : 000109FF XMLVIEW :0
|
---|
| 378 | + ^^^ and we write here
|
---|
| 379 | * After this call, we have.
|
---|
| 380 | *
|
---|
| 381 | + CS:EIP : 000109FF XMLVIEW :0 xxx.c 123 ConfirmCreate__Fv
|
---|
| 382 | + ^^^ and we write here
|
---|
| 383 | *
|
---|
| 384 | *@@added V0.9.12 (2001-05-12) [umoeller]
|
---|
| 385 | */
|
---|
| 386 |
|
---|
[222] | 387 | STATIC VOID WriteDebugInfo(FILE *LogFile, // in: open log file
|
---|
[142] | 388 | PXDEBUGINFO pxdi) // in: debug info
|
---|
[68] | 389 | {
|
---|
| 390 | fprintf(LogFile,
|
---|
| 391 | "%s%s%s",
|
---|
| 392 | pxdi->szNrFile,
|
---|
| 393 | pxdi->szNrLine,
|
---|
| 394 | pxdi->szNrPub);
|
---|
| 395 | }
|
---|
| 396 |
|
---|
| 397 | /*
|
---|
[8] | 398 | *@@ dbgPrintDebugInfo:
|
---|
| 399 | * this is the main entry point into analyzing debug
|
---|
| 400 | * code.
|
---|
[68] | 401 | *
|
---|
[8] | 402 | * This analyzes a given address and tries to find
|
---|
| 403 | * debug code descriptions for this address. If found,
|
---|
| 404 | * the information is written to the given log file.
|
---|
| 405 | *
|
---|
| 406 | * Gets called from dbgPrintStack.
|
---|
| 407 | *
|
---|
| 408 | * This returns NO_ERROR if the could was successfully
|
---|
| 409 | * analyzed or something != 0 if we failed.
|
---|
| 410 | *
|
---|
| 411 | * New with V0.84.
|
---|
| 412 | */
|
---|
| 413 |
|
---|
| 414 | APIRET dbgPrintDebugInfo(FILE *LogFile, // out: log file to write to
|
---|
| 415 | CHAR *FileName, // in: EXE/DLL module file name
|
---|
[68] | 416 | ULONG Object, // in: trapping object (from DosQueryModFromEIP)
|
---|
| 417 | ULONG TrapOffset) // in: trapping address (from DosQueryModFromEIP)
|
---|
[8] | 418 | {
|
---|
| 419 | APIRET rc = 0;
|
---|
| 420 | int ModuleFile = 0;
|
---|
| 421 | static struct exe_hdr OldExeHeader;
|
---|
| 422 | static struct new_exe NewExeHeader;
|
---|
| 423 |
|
---|
[68] | 424 | ULONG ulSegment = Object + 1; // segment no. is object no. + 1
|
---|
| 425 |
|
---|
[8] | 426 | XDEBUGINFO xdi;
|
---|
| 427 | memset(&xdi, 0, sizeof(xdi));
|
---|
| 428 |
|
---|
| 429 | // open the module file for reading to analyze the code
|
---|
| 430 | ModuleFile = sopen(FileName, O_RDONLY | O_BINARY, SH_DENYNO);
|
---|
| 431 |
|
---|
| 432 | if (ModuleFile != -1)
|
---|
| 433 | {
|
---|
| 434 | // file found:
|
---|
| 435 | // read old Exe header
|
---|
| 436 | if (read(ModuleFile, (void*)&OldExeHeader, 64) == -1L)
|
---|
| 437 | {
|
---|
| 438 | fprintf(LogFile, "errno %d reading old exe header\n", errno);
|
---|
| 439 | close(ModuleFile);
|
---|
| 440 | return 2;
|
---|
| 441 | }
|
---|
| 442 | // seek to new Exe header
|
---|
| 443 | if (lseek(ModuleFile, (long)E_LFANEW(OldExeHeader), SEEK_SET) == -1L)
|
---|
| 444 | {
|
---|
| 445 | fprintf(LogFile, "errno %d seeking to new exe header\n", errno);
|
---|
| 446 | close(ModuleFile);
|
---|
| 447 | return 3;
|
---|
| 448 | }
|
---|
| 449 | if (read(ModuleFile, (void *)&NewExeHeader, 64) == -1L)
|
---|
| 450 | {
|
---|
| 451 | fprintf(LogFile, "errno %d reading new exe header\n", errno);
|
---|
| 452 | close(ModuleFile);
|
---|
| 453 | return 4;
|
---|
| 454 | }
|
---|
| 455 |
|
---|
| 456 | // check EXE signature
|
---|
| 457 | if (NE_MAGIC(NewExeHeader) == E32MAGIC)
|
---|
| 458 | {
|
---|
| 459 | /*
|
---|
| 460 | * flat 32 executable:
|
---|
| 461 | *
|
---|
| 462 | */
|
---|
| 463 |
|
---|
| 464 | // do analysis for 32-bit code
|
---|
[68] | 465 | if (!(rc = Read32PmDebug(LogFile,
|
---|
| 466 | &xdi, // output
|
---|
| 467 | ModuleFile,
|
---|
| 468 | ulSegment,
|
---|
| 469 | TrapOffset,
|
---|
| 470 | FileName)))
|
---|
| 471 | WriteDebugInfo(LogFile, &xdi);
|
---|
| 472 |
|
---|
[8] | 473 | close(ModuleFile);
|
---|
| 474 |
|
---|
| 475 | // rc !=0 try with DBG file
|
---|
| 476 | if (rc != 0)
|
---|
| 477 | {
|
---|
| 478 | strcpy(FileName + strlen(FileName) - 3, "DBG"); // Build DBG File name
|
---|
| 479 | ModuleFile = sopen(FileName, O_RDONLY | O_BINARY, SH_DENYNO);
|
---|
| 480 | if (ModuleFile != -1)
|
---|
| 481 | {
|
---|
[68] | 482 | if (!(rc = Read32PmDebug(LogFile,
|
---|
| 483 | &xdi,
|
---|
| 484 | ModuleFile,
|
---|
| 485 | ulSegment,
|
---|
| 486 | TrapOffset,
|
---|
| 487 | FileName)))
|
---|
| 488 | WriteDebugInfo(LogFile, &xdi);
|
---|
| 489 |
|
---|
[8] | 490 | close(ModuleFile);
|
---|
| 491 | }
|
---|
[68] | 492 | }
|
---|
[8] | 493 |
|
---|
| 494 | return rc;
|
---|
| 495 | }
|
---|
| 496 | else
|
---|
| 497 | {
|
---|
| 498 | if (NE_MAGIC(NewExeHeader) == NEMAGIC)
|
---|
| 499 | {
|
---|
| 500 | /*
|
---|
| 501 | * 16:16 executable:
|
---|
| 502 | *
|
---|
| 503 | */
|
---|
| 504 |
|
---|
[68] | 505 | if ((xdi.pseg = (struct new_seg *)calloc(NE_CSEG(NewExeHeader),
|
---|
| 506 | sizeof(struct new_seg)))
|
---|
| 507 | == NULL)
|
---|
[8] | 508 | {
|
---|
| 509 | fprintf(LogFile, "Out of memory!");
|
---|
| 510 | close(ModuleFile);
|
---|
| 511 | return -1;
|
---|
| 512 | }
|
---|
[68] | 513 | if ( lseek(ModuleFile,
|
---|
| 514 | E_LFANEW(OldExeHeader) + NE_SEGTAB(NewExeHeader),
|
---|
| 515 | SEEK_SET) == -1L)
|
---|
[8] | 516 | {
|
---|
| 517 | fprintf(LogFile, "Error %u seeking segment table in %s\n", errno, FileName);
|
---|
| 518 | free(xdi.pseg);
|
---|
| 519 | close(ModuleFile);
|
---|
| 520 | return 9;
|
---|
| 521 | }
|
---|
| 522 |
|
---|
[68] | 523 | if (read(ModuleFile,
|
---|
| 524 | (void *)xdi.pseg,
|
---|
| 525 | NE_CSEG(NewExeHeader) * sizeof(struct new_seg))
|
---|
| 526 | == -1)
|
---|
[8] | 527 | {
|
---|
| 528 | fprintf(LogFile, "Error %u reading segment table from %s\n", errno, FileName);
|
---|
| 529 | free(xdi.pseg);
|
---|
| 530 | close(ModuleFile);
|
---|
| 531 | return 10;
|
---|
| 532 | }
|
---|
[68] | 533 |
|
---|
| 534 | if (!(rc = Read16CodeView(LogFile,
|
---|
| 535 | &xdi,
|
---|
| 536 | ModuleFile,
|
---|
| 537 | ulSegment,
|
---|
| 538 | TrapOffset,
|
---|
| 539 | FileName)))
|
---|
| 540 | WriteDebugInfo(LogFile, &xdi);
|
---|
| 541 |
|
---|
[8] | 542 | free(xdi.pseg);
|
---|
| 543 | close(ModuleFile);
|
---|
| 544 |
|
---|
| 545 | // rc !=0 try with DBG file
|
---|
| 546 | if (rc != 0)
|
---|
| 547 | {
|
---|
| 548 | strcpy(FileName + strlen(FileName) - 3, "DBG"); // Build DBG File name
|
---|
[68] | 549 | ModuleFile = sopen(FileName,
|
---|
| 550 | O_RDONLY | O_BINARY, SH_DENYNO);
|
---|
[8] | 551 | if (ModuleFile != -1)
|
---|
| 552 | {
|
---|
[68] | 553 | if (!(rc = Read16CodeView(LogFile,
|
---|
| 554 | &xdi,
|
---|
| 555 | ModuleFile,
|
---|
| 556 | ulSegment,
|
---|
| 557 | TrapOffset,
|
---|
| 558 | FileName)))
|
---|
| 559 | WriteDebugInfo(LogFile, &xdi);
|
---|
| 560 |
|
---|
[8] | 561 | close(ModuleFile);
|
---|
| 562 | }
|
---|
[68] | 563 | }
|
---|
[8] | 564 | return rc;
|
---|
| 565 | }
|
---|
| 566 | else
|
---|
| 567 | {
|
---|
| 568 | /*
|
---|
| 569 | * Unknown executable:
|
---|
| 570 | *
|
---|
| 571 | */
|
---|
| 572 |
|
---|
| 573 | fprintf(LogFile, "Error, could not find exe signature");
|
---|
| 574 | close(ModuleFile);
|
---|
| 575 | return 11;
|
---|
| 576 | }
|
---|
| 577 | }
|
---|
| 578 | } // end if (ModuleFile != -1)
|
---|
| 579 | else
|
---|
| 580 | {
|
---|
| 581 | fprintf(LogFile, "Error %d opening module file %s", errno, FileName);
|
---|
| 582 | return 1;
|
---|
| 583 | } // endif
|
---|
| 584 |
|
---|
| 585 | // return 0; we never get here
|
---|
| 586 | }
|
---|
| 587 |
|
---|
| 588 | char fname[128],
|
---|
| 589 | ModName[80];
|
---|
| 590 | char ename[128],
|
---|
| 591 | dummy[128];
|
---|
| 592 |
|
---|
| 593 | #define MAX_USERDEFS 300 // raised from 150 V0.9.1 (2000-01-30) [umoeller]
|
---|
| 594 | #define MAX_POINTERS 300 // raised from 150 V0.9.1 (2000-01-30) [umoeller]
|
---|
| 595 |
|
---|
| 596 | USHORT userdef_count;
|
---|
| 597 | USHORT pointer_count;
|
---|
| 598 |
|
---|
| 599 | struct one_userdef_rec
|
---|
| 600 | {
|
---|
| 601 | USHORT idx;
|
---|
| 602 | USHORT type_index;
|
---|
| 603 | BYTE name[33];
|
---|
| 604 | } one_userdef[MAX_USERDEFS];
|
---|
| 605 |
|
---|
| 606 | struct one_pointer_rec
|
---|
| 607 | {
|
---|
| 608 | USHORT idx;
|
---|
| 609 | USHORT type_index;
|
---|
| 610 | BYTE type_qual;
|
---|
| 611 | BYTE name[33];
|
---|
| 612 | } one_pointer[MAX_POINTERS];
|
---|
| 613 |
|
---|
| 614 | /*
|
---|
| 615 | * Read32PmDebug:
|
---|
| 616 | * parses 32-bit debug code.
|
---|
| 617 | * Called from dbgPrintDebugInfo for 32-bit modules.
|
---|
| 618 | */
|
---|
| 619 |
|
---|
[222] | 620 | STATIC int Read32PmDebug(FILE *LogFile, // in: text log file to write to
|
---|
[142] | 621 | PXDEBUGINFO pxdi,
|
---|
| 622 | int ModuleFile, // in: module file opened with sopen()
|
---|
| 623 | int TrapSeg,
|
---|
| 624 | int TrapOff,
|
---|
| 625 | CHAR *FileName)
|
---|
[8] | 626 | {
|
---|
| 627 | static unsigned int CurrSymSeg, NrSymbol,
|
---|
| 628 | /* offset, */ NrPublic,
|
---|
| 629 | NrFile, NrLine, /* NrEntry */
|
---|
| 630 | numdir, namelen,
|
---|
| 631 | numlines /* , line */;
|
---|
| 632 | static int ModIndex;
|
---|
| 633 | static int bytesread, i, j;
|
---|
| 634 | static SSLINEENTRY32 LineEntry;
|
---|
| 635 | static SSFILENUM32 FileInfo;
|
---|
| 636 | static FIRSTLINEENTRY32 FirstLine;
|
---|
| 637 | static BYTE dump_vars = FALSE;
|
---|
| 638 | static USHORT idx;
|
---|
| 639 | static BOOL read_types;
|
---|
| 640 | static LONG lSize;
|
---|
| 641 |
|
---|
| 642 | ModIndex = 0;
|
---|
| 643 | // See if any CODEVIEW info
|
---|
| 644 | if (lseek(ModuleFile, -8L, SEEK_END) == -1)
|
---|
| 645 | {
|
---|
| 646 | fprintf(LogFile, "Error %u seeking CodeView table in %s\n", errno, FileName);
|
---|
[441] | 647 | return 18;
|
---|
[8] | 648 | }
|
---|
| 649 |
|
---|
[68] | 650 | if (read(ModuleFile,
|
---|
| 651 | (void *)&G_eodbug, 8)
|
---|
| 652 | == -1)
|
---|
[8] | 653 | {
|
---|
| 654 | fprintf(LogFile, "Error %u reading debug info from %s\n", errno, FileName);
|
---|
[441] | 655 | return 19;
|
---|
[8] | 656 | }
|
---|
| 657 | if (G_eodbug.dbug != DBUGSIG)
|
---|
| 658 | {
|
---|
| 659 | // fprintf(LogFile,"\nNo CodeView information stored.\n");
|
---|
[441] | 660 | return 100;
|
---|
[8] | 661 | }
|
---|
| 662 |
|
---|
[68] | 663 | if ( (pxdi->lfaBase = lseek(ModuleFile,
|
---|
| 664 | -(LONG)G_eodbug.dfaBase,
|
---|
| 665 | SEEK_END))
|
---|
| 666 | == -1L)
|
---|
[8] | 667 | {
|
---|
| 668 | fprintf(LogFile, "Error %u seeking base codeview data in %s\n", errno, FileName);
|
---|
[441] | 669 | return 20;
|
---|
[8] | 670 | }
|
---|
| 671 |
|
---|
[68] | 672 | if (read(ModuleFile,
|
---|
| 673 | (void *)&pxdi->base, 8)
|
---|
| 674 | == -1)
|
---|
[8] | 675 | {
|
---|
| 676 | fprintf(LogFile, "Error %u reading base codeview data in %s\n", errno, FileName);
|
---|
[441] | 677 | return 21;
|
---|
[8] | 678 | }
|
---|
| 679 |
|
---|
[68] | 680 | if (lseek(ModuleFile,
|
---|
| 681 | pxdi->base.lfoDir - 8 + 4,
|
---|
| 682 | SEEK_CUR)
|
---|
| 683 | == -1)
|
---|
[8] | 684 | {
|
---|
| 685 | fprintf(LogFile, "Error %u seeking dir codeview data in %s\n", errno, FileName);
|
---|
[441] | 686 | return 22;
|
---|
[8] | 687 | }
|
---|
| 688 |
|
---|
[68] | 689 | if (read(ModuleFile,
|
---|
| 690 | (void *)&numdir, 4)
|
---|
| 691 | == -1)
|
---|
[8] | 692 | {
|
---|
| 693 | fprintf(LogFile, "Error %u reading dir codeview data in %s\n", errno, FileName);
|
---|
[441] | 694 | return 23;
|
---|
[8] | 695 | }
|
---|
| 696 |
|
---|
| 697 | // Read dir table into buffer
|
---|
[68] | 698 | if ( (pxdi->pDirTab32 = (SSDIR32*)calloc(numdir,
|
---|
| 699 | sizeof(SSDIR32)))
|
---|
| 700 | == NULL)
|
---|
[8] | 701 | {
|
---|
| 702 | fprintf(LogFile, "Out of memory!");
|
---|
[441] | 703 | return -1;
|
---|
[8] | 704 | }
|
---|
| 705 |
|
---|
[68] | 706 | if (read(ModuleFile,
|
---|
| 707 | (void*)pxdi->pDirTab32,
|
---|
| 708 | numdir * sizeof(SSDIR32))
|
---|
| 709 | == -1)
|
---|
[8] | 710 | {
|
---|
| 711 | fprintf(LogFile, "Error %u reading codeview dir table from %s\n", errno, FileName);
|
---|
| 712 | free(pxdi->pDirTab32);
|
---|
[441] | 713 | return 24;
|
---|
[8] | 714 | }
|
---|
| 715 |
|
---|
| 716 | i = 0;
|
---|
| 717 | while (i < numdir)
|
---|
| 718 | {
|
---|
| 719 | if (pxdi->pDirTab32[i].sst != SSTMODULES)
|
---|
| 720 | {
|
---|
| 721 | i++;
|
---|
| 722 | continue;
|
---|
| 723 | }
|
---|
[68] | 724 |
|
---|
[8] | 725 | NrPublic = 0x0;
|
---|
| 726 | NrSymbol = 0;
|
---|
| 727 | NrLine = 0x0;
|
---|
| 728 | NrFile = 0x0;
|
---|
| 729 | CurrSymSeg = 0;
|
---|
| 730 | // point to subsection
|
---|
[68] | 731 | lseek(ModuleFile,
|
---|
| 732 | pxdi->pDirTab32[i].lfoStart + pxdi->lfaBase,
|
---|
| 733 | SEEK_SET);
|
---|
| 734 | read(ModuleFile,
|
---|
| 735 | (void*)&pxdi->ssmod32.csBase,
|
---|
| 736 | sizeof(SSMOD32));
|
---|
| 737 | read(ModuleFile,
|
---|
| 738 | (void*)ModName,
|
---|
| 739 | (unsigned)pxdi->ssmod32.csize);
|
---|
[8] | 740 | ModIndex = pxdi->pDirTab32[i].modindex;
|
---|
| 741 | ModName[pxdi->ssmod32.csize] = '\0';
|
---|
| 742 | i++;
|
---|
| 743 |
|
---|
| 744 | read_types = FALSE;
|
---|
| 745 |
|
---|
| 746 | while ( (pxdi->pDirTab32[i].modindex == ModIndex)
|
---|
| 747 | && (i < numdir)
|
---|
| 748 | )
|
---|
| 749 | {
|
---|
| 750 | // point to subsection
|
---|
[68] | 751 | lseek(ModuleFile,
|
---|
| 752 | pxdi->pDirTab32[i].lfoStart + pxdi->lfaBase,
|
---|
| 753 | SEEK_SET);
|
---|
| 754 |
|
---|
[8] | 755 | switch (pxdi->pDirTab32[i].sst)
|
---|
| 756 | {
|
---|
| 757 | case SSTPUBLICS:
|
---|
| 758 | bytesread = 0;
|
---|
| 759 | while (bytesread < pxdi->pDirTab32[i].cb)
|
---|
| 760 | {
|
---|
[68] | 761 | bytesread += read(ModuleFile,
|
---|
| 762 | (void *)&pxdi->sspub32.offset,
|
---|
| 763 | sizeof(pxdi->sspub32));
|
---|
| 764 | bytesread += read(ModuleFile,
|
---|
| 765 | (void*)ename,
|
---|
| 766 | (unsigned)pxdi->sspub32.csize);
|
---|
[8] | 767 | ename[pxdi->sspub32.csize] = '\0';
|
---|
| 768 | if ( (pxdi->sspub32.segment == TrapSeg)
|
---|
| 769 | && (pxdi->sspub32.offset <= TrapOff)
|
---|
| 770 | && (pxdi->sspub32.offset >= NrPublic)
|
---|
| 771 | )
|
---|
| 772 | {
|
---|
| 773 | NrPublic = pubfunc_ofs = pxdi->sspub32.offset;
|
---|
| 774 | read_types = TRUE;
|
---|
[13] | 775 | sprintf(pxdi->szNrPub,
|
---|
[68] | 776 | "%s %s (%s)\n",
|
---|
| 777 | (pxdi->sspub32.type == 1)
|
---|
| 778 | ? " Abs"
|
---|
| 779 | : " ",
|
---|
[8] | 780 | ename,
|
---|
[68] | 781 | ModName
|
---|
[8] | 782 | );
|
---|
| 783 | // but continue, because there might be a
|
---|
| 784 | // symbol that comes closer
|
---|
| 785 | }
|
---|
| 786 | }
|
---|
| 787 | break;
|
---|
| 788 |
|
---|
| 789 | // Read symbols, so we can dump the variables on the stack
|
---|
| 790 | case SSTSYMBOLS:
|
---|
| 791 | if (TrapSeg != pxdi->ssmod32.csBase)
|
---|
| 792 | break;
|
---|
| 793 |
|
---|
| 794 | bytesread = 0;
|
---|
| 795 | while (bytesread < pxdi->pDirTab32[i].cb)
|
---|
| 796 | {
|
---|
| 797 | static USHORT usLength;
|
---|
| 798 | static BYTE b1,
|
---|
| 799 | b2;
|
---|
| 800 | static BYTE bType;
|
---|
| 801 | // *ptr;
|
---|
| 802 | static ULONG ofs;
|
---|
| 803 | // static ULONG last_addr = 0;
|
---|
| 804 | static BYTE str[256];
|
---|
| 805 | static struct symseg_rec symseg;
|
---|
| 806 | static struct symauto_rec symauto;
|
---|
| 807 | static struct symproc_rec symproc;
|
---|
| 808 |
|
---|
| 809 | // Read the length of this subentry
|
---|
| 810 | bytesread += read(ModuleFile, &b1, 1);
|
---|
| 811 | if (b1 & 0x80)
|
---|
| 812 | {
|
---|
| 813 | bytesread += read(ModuleFile, &b2, 1);
|
---|
| 814 | usLength = ((b1 & 0x7F) << 8) + b2;
|
---|
| 815 | }
|
---|
| 816 | else
|
---|
| 817 | usLength = b1;
|
---|
| 818 |
|
---|
| 819 | ofs = tell(ModuleFile);
|
---|
| 820 |
|
---|
| 821 | bytesread += read(ModuleFile, &bType, 1);
|
---|
| 822 |
|
---|
| 823 | switch (bType)
|
---|
| 824 | {
|
---|
| 825 | case SYM_CHANGESEG:
|
---|
| 826 | read(ModuleFile, &symseg, sizeof(symseg));
|
---|
| 827 | CurrSymSeg = symseg.seg_no;
|
---|
| 828 | break;
|
---|
| 829 |
|
---|
| 830 | case SYM_PROC:
|
---|
| 831 | case SYM_CPPPROC:
|
---|
| 832 | read(ModuleFile, &symproc, sizeof(symproc));
|
---|
| 833 | read(ModuleFile, str, symproc.name_len);
|
---|
| 834 | str[symproc.name_len] = 0;
|
---|
| 835 |
|
---|
| 836 | if ((CurrSymSeg == TrapSeg) &&
|
---|
| 837 | (symproc.offset <= TrapOff) &&
|
---|
| 838 | (symproc.offset >= NrSymbol))
|
---|
| 839 | {
|
---|
| 840 |
|
---|
| 841 | dump_vars = TRUE;
|
---|
| 842 | var_ofs = 0;
|
---|
| 843 | NrSymbol = symproc.offset;
|
---|
| 844 | func_ofs = symproc.offset;
|
---|
| 845 |
|
---|
| 846 | strcpy(func_name, str);
|
---|
| 847 | }
|
---|
| 848 | else
|
---|
| 849 | {
|
---|
| 850 | dump_vars = FALSE;
|
---|
| 851 | }
|
---|
| 852 | break;
|
---|
| 853 |
|
---|
| 854 | case SYM_AUTO:
|
---|
| 855 | if (!dump_vars)
|
---|
| 856 | break;
|
---|
| 857 |
|
---|
| 858 | read(ModuleFile, &symauto, sizeof(symauto));
|
---|
| 859 | read(ModuleFile, str, symauto.name_len);
|
---|
| 860 | str[symauto.name_len] = 0;
|
---|
| 861 |
|
---|
| 862 | strcpy(autovar_def[var_ofs].name, str);
|
---|
| 863 | autovar_def[var_ofs].stack_offset = symauto.stack_offset;
|
---|
| 864 | autovar_def[var_ofs].type_idx = symauto.type_idx;
|
---|
| 865 | var_ofs++;
|
---|
| 866 | break;
|
---|
| 867 |
|
---|
| 868 | }
|
---|
| 869 |
|
---|
| 870 | bytesread += usLength;
|
---|
| 871 |
|
---|
| 872 | lseek(ModuleFile, ofs + usLength, SEEK_SET);
|
---|
| 873 | }
|
---|
| 874 | break;
|
---|
| 875 |
|
---|
| 876 | case SSTTYPES:
|
---|
| 877 | // if (ModIndex != TrapSeg)
|
---|
| 878 | if (!read_types)
|
---|
| 879 | break;
|
---|
| 880 |
|
---|
| 881 | bytesread = 0;
|
---|
| 882 | idx = 0x200;
|
---|
| 883 | userdef_count = 0;
|
---|
| 884 | pointer_count = 0;
|
---|
| 885 | while (bytesread < pxdi->pDirTab32[i].cb)
|
---|
| 886 | {
|
---|
| 887 | static struct type_rec type;
|
---|
| 888 | static struct type_userdefrec udef;
|
---|
| 889 | static struct type_pointerrec point;
|
---|
| 890 | static ULONG ofs;
|
---|
| 891 | static BYTE str[256];
|
---|
| 892 |
|
---|
| 893 | // Read the length of this subentry
|
---|
| 894 | ofs = tell(ModuleFile);
|
---|
| 895 |
|
---|
| 896 | read(ModuleFile, &type, sizeof(type));
|
---|
| 897 | bytesread += sizeof(type);
|
---|
| 898 |
|
---|
| 899 | switch (type.type)
|
---|
| 900 | {
|
---|
| 901 | case TYPE_USERDEF:
|
---|
| 902 | if (userdef_count >= MAX_USERDEFS)
|
---|
| 903 | break;
|
---|
| 904 |
|
---|
| 905 | read(ModuleFile, &udef, sizeof(udef));
|
---|
| 906 | read(ModuleFile, str, udef.name_len);
|
---|
| 907 | str[udef.name_len] = 0;
|
---|
| 908 |
|
---|
| 909 | // Insert userdef in table
|
---|
| 910 | one_userdef[userdef_count].idx = idx;
|
---|
| 911 | one_userdef[userdef_count].type_index = udef.type_index;
|
---|
| 912 | memcpy(one_userdef[userdef_count].name,
|
---|
| 913 | str,
|
---|
| 914 | _min(udef.name_len + 1, 32));
|
---|
| 915 | one_userdef[userdef_count].name[32] = 0;
|
---|
| 916 | userdef_count++;
|
---|
| 917 | break;
|
---|
| 918 |
|
---|
| 919 | case TYPE_POINTER:
|
---|
| 920 | if (pointer_count >= MAX_POINTERS)
|
---|
| 921 | break;
|
---|
| 922 |
|
---|
| 923 | read(ModuleFile, &point, sizeof(point));
|
---|
| 924 | read(ModuleFile, str, point.name_len);
|
---|
| 925 | str[point.name_len] = 0;
|
---|
| 926 |
|
---|
| 927 | // Insert userdef in table
|
---|
| 928 | one_pointer[pointer_count].idx = idx;
|
---|
| 929 | one_pointer[pointer_count].type_index = point.type_index;
|
---|
| 930 | memcpy(one_pointer[pointer_count].name,
|
---|
| 931 | str,
|
---|
| 932 | _min(point.name_len + 1, 32));
|
---|
| 933 | one_pointer[pointer_count].name[32] = 0;
|
---|
| 934 | one_pointer[pointer_count].type_qual = type.type_qual;
|
---|
| 935 | pointer_count++;
|
---|
| 936 | break;
|
---|
| 937 | }
|
---|
| 938 |
|
---|
| 939 | ++idx;
|
---|
| 940 |
|
---|
| 941 | bytesread += type.length;
|
---|
| 942 |
|
---|
| 943 | lseek(ModuleFile, ofs + type.length + 2, SEEK_SET);
|
---|
| 944 | }
|
---|
| 945 | break;
|
---|
| 946 |
|
---|
| 947 | case SSTSRCLINES32:
|
---|
| 948 | if (TrapSeg != pxdi->ssmod32.csBase)
|
---|
| 949 | break;
|
---|
| 950 |
|
---|
| 951 | // read first line
|
---|
| 952 | do
|
---|
| 953 | {
|
---|
| 954 | read(ModuleFile, (void *)&FirstLine, sizeof(FirstLine));
|
---|
| 955 |
|
---|
| 956 | if (FirstLine.LineNum != 0)
|
---|
| 957 | {
|
---|
| 958 | fprintf(LogFile, "Missing Line table information\n");
|
---|
| 959 | break;
|
---|
| 960 | } // endif
|
---|
| 961 | numlines = FirstLine.numlines;
|
---|
| 962 | // Other type of data skip 4 more bytes
|
---|
| 963 | if (FirstLine.entry_type < 4)
|
---|
| 964 | {
|
---|
| 965 | read(ModuleFile, (void *)&lSize, 4);
|
---|
| 966 | if (FirstLine.entry_type == 3)
|
---|
| 967 | lseek(ModuleFile, lSize, SEEK_CUR);
|
---|
| 968 | }
|
---|
| 969 | }
|
---|
| 970 | while (FirstLine.entry_type == 3);
|
---|
| 971 |
|
---|
| 972 | for (j = 0; j < numlines; j++)
|
---|
| 973 | {
|
---|
| 974 | switch (FirstLine.entry_type)
|
---|
| 975 | {
|
---|
| 976 | case 0:
|
---|
| 977 | read(ModuleFile, (void *)&LineEntry, sizeof(LineEntry));
|
---|
| 978 | // Changed by Kim Rasmussen 26/06 1996 to ignore linenumber 0
|
---|
| 979 | // if (LineEntry.Offset+ssmod32.csOff<=TrapOff && LineEntry.Offset+ssmod32.csOff>=NrLine) {
|
---|
| 980 | if ( (LineEntry.LineNum)
|
---|
| 981 | && (LineEntry.Offset + pxdi->ssmod32.csOff
|
---|
| 982 | <= TrapOff)
|
---|
| 983 | && (LineEntry.Offset + pxdi->ssmod32.csOff >= NrLine)
|
---|
| 984 | )
|
---|
| 985 | {
|
---|
| 986 | NrLine = LineEntry.Offset;
|
---|
| 987 | NrFile = LineEntry.FileNum;
|
---|
| 988 | /*pOffset =sprintf(szNrLine,"%04X:%08X line #%hu ",
|
---|
| 989 | * ssmod32.csBase,LineEntry.Offset,
|
---|
| 990 | * LineEntry.LineNum); */
|
---|
| 991 | sprintf(pxdi->szNrLine, "% 6hu", LineEntry.LineNum);
|
---|
| 992 | }
|
---|
| 993 | break;
|
---|
| 994 |
|
---|
| 995 | case 1:
|
---|
| 996 | lseek(ModuleFile, sizeof(struct linlist_rec), SEEK_CUR);
|
---|
| 997 | break;
|
---|
| 998 |
|
---|
| 999 | case 2:
|
---|
| 1000 | lseek(ModuleFile, sizeof(struct linsourcelist_rec), SEEK_CUR);
|
---|
| 1001 | break;
|
---|
| 1002 |
|
---|
| 1003 | case 3:
|
---|
| 1004 | lseek(ModuleFile, sizeof(struct filenam_rec), SEEK_CUR);
|
---|
| 1005 | break;
|
---|
| 1006 |
|
---|
| 1007 | case 4:
|
---|
| 1008 | lseek(ModuleFile, sizeof(struct pathtab_rec), SEEK_CUR);
|
---|
| 1009 | break;
|
---|
| 1010 |
|
---|
| 1011 | }
|
---|
| 1012 | }
|
---|
| 1013 |
|
---|
| 1014 | if (NrFile != 0)
|
---|
| 1015 | {
|
---|
| 1016 | // file found:
|
---|
| 1017 | read(ModuleFile, (void*)&FileInfo, sizeof(FileInfo));
|
---|
| 1018 | namelen = 0;
|
---|
| 1019 | for (j = 1; j <= FileInfo.file_count; j++)
|
---|
| 1020 | {
|
---|
| 1021 | namelen = 0;
|
---|
| 1022 | read(ModuleFile, (void *)&namelen, 1);
|
---|
| 1023 | read(ModuleFile, (void *)ename, namelen);
|
---|
| 1024 | if (j == NrFile)
|
---|
| 1025 | break;
|
---|
| 1026 | }
|
---|
| 1027 | ename[namelen] = '\0';
|
---|
| 1028 | // pOffset=sprintf(szNrLine+pOffset," (%s) (%s)\n",ename,ModName);
|
---|
| 1029 | sprintf(pxdi->szNrFile, "%11.11s ", ename);
|
---|
| 1030 | }
|
---|
| 1031 | else
|
---|
| 1032 | {
|
---|
| 1033 | // strcat(szNrLine,"\n"); avoid new line for empty name fill
|
---|
| 1034 | strcpy(pxdi->szNrFile, "file? ");
|
---|
| 1035 | } // endif
|
---|
| 1036 | break;
|
---|
| 1037 | } // end switch
|
---|
| 1038 |
|
---|
| 1039 | i++;
|
---|
| 1040 | } // end while modindex
|
---|
| 1041 | } // End While i < numdir
|
---|
[441] | 1042 |
|
---|
[8] | 1043 | free(pxdi->pDirTab32);
|
---|
[441] | 1044 |
|
---|
| 1045 | return 0;
|
---|
[8] | 1046 | }
|
---|
| 1047 |
|
---|
| 1048 | /*
|
---|
| 1049 | * Read16CodeView:
|
---|
| 1050 | * parses 16-bit debug code.
|
---|
| 1051 | * Called from dbgPrintDebugInfo for 16-bit modules.
|
---|
| 1052 | */
|
---|
| 1053 |
|
---|
[222] | 1054 | STATIC int Read16CodeView(FILE *LogFile, // in: text log file to write to
|
---|
[142] | 1055 | PXDEBUGINFO pxdi,
|
---|
| 1056 | int fh,
|
---|
| 1057 | int TrapSeg,
|
---|
| 1058 | int TrapOff,
|
---|
| 1059 | CHAR *FileName)
|
---|
[8] | 1060 | {
|
---|
| 1061 | static unsigned short int offset,
|
---|
| 1062 | NrPublic, NrLine,
|
---|
| 1063 | numdir,
|
---|
| 1064 | namelen, numlines,
|
---|
| 1065 | line;
|
---|
| 1066 | static int ModIndex;
|
---|
| 1067 | static int bytesread, i, j;
|
---|
| 1068 |
|
---|
| 1069 | ModIndex = 0;
|
---|
| 1070 | // See if any CODEVIEW info
|
---|
| 1071 | if (lseek(fh, -8L, SEEK_END) == -1)
|
---|
| 1072 | {
|
---|
| 1073 | fprintf(LogFile, "Error %u seeking CodeView table in %s\n", errno, FileName);
|
---|
[441] | 1074 | return 18;
|
---|
[8] | 1075 | }
|
---|
| 1076 |
|
---|
| 1077 | if (read(fh, (void *)&G_eodbug, 8) == -1)
|
---|
| 1078 | {
|
---|
| 1079 | fprintf(LogFile, "Error %u reading debug info from %s\n", errno, FileName);
|
---|
[441] | 1080 | return 19;
|
---|
[8] | 1081 | }
|
---|
| 1082 | if (G_eodbug.dbug != DBUGSIG)
|
---|
| 1083 | {
|
---|
| 1084 | // fprintf(LogFile,"\nNo CodeView information stored.\n");
|
---|
[441] | 1085 | return 100;
|
---|
[8] | 1086 | }
|
---|
| 1087 |
|
---|
| 1088 | if ((pxdi->lfaBase = lseek(fh, -(LONG)G_eodbug.dfaBase, SEEK_END)) == -1L)
|
---|
| 1089 | {
|
---|
| 1090 | fprintf(LogFile, "Error %u seeking base codeview data in %s\n", errno, FileName);
|
---|
[441] | 1091 | return 20;
|
---|
[8] | 1092 | }
|
---|
| 1093 |
|
---|
| 1094 | if (read(fh, (void *)&pxdi->base, 8) == -1)
|
---|
| 1095 | {
|
---|
| 1096 | fprintf(LogFile, "Error %u reading base codeview data in %s\n", errno, FileName);
|
---|
[441] | 1097 | return 21;
|
---|
[8] | 1098 | }
|
---|
| 1099 |
|
---|
| 1100 | if (lseek(fh, pxdi->base.lfoDir - 8, SEEK_CUR) == -1)
|
---|
| 1101 | {
|
---|
| 1102 | fprintf(LogFile, "Error %u seeking dir codeview data in %s\n", errno, FileName);
|
---|
[441] | 1103 | return 22;
|
---|
[8] | 1104 | }
|
---|
| 1105 |
|
---|
| 1106 | if (read(fh, (void *)&numdir, 2) == -1)
|
---|
| 1107 | {
|
---|
| 1108 | fprintf(LogFile, "Error %u reading dir codeview data in %s\n", errno, FileName);
|
---|
[441] | 1109 | return 23;
|
---|
[8] | 1110 | }
|
---|
| 1111 |
|
---|
| 1112 | // Read dir table into buffer
|
---|
| 1113 | if ((pxdi->pDirTab = (SSDIR*)calloc(numdir, sizeof(SSDIR))) == NULL)
|
---|
| 1114 | {
|
---|
| 1115 | fprintf(LogFile, "Out of memory!");
|
---|
[441] | 1116 | return -1;
|
---|
[8] | 1117 | }
|
---|
| 1118 |
|
---|
| 1119 | if (read(fh, (void*)pxdi->pDirTab, numdir * sizeof(SSDIR)) == -1)
|
---|
| 1120 | {
|
---|
| 1121 | fprintf(LogFile, "Error %u reading codeview dir table from %s\n", errno, FileName);
|
---|
| 1122 | free(pxdi->pDirTab);
|
---|
[441] | 1123 | return 24;
|
---|
[8] | 1124 | }
|
---|
| 1125 |
|
---|
| 1126 | i = 0;
|
---|
| 1127 | while (i < numdir)
|
---|
| 1128 | {
|
---|
| 1129 | if (pxdi->pDirTab[i].sst != SSTMODULES)
|
---|
| 1130 | {
|
---|
| 1131 | i++;
|
---|
| 1132 | continue;
|
---|
| 1133 | }
|
---|
| 1134 | NrPublic = 0x0;
|
---|
| 1135 | NrLine = 0x0;
|
---|
| 1136 | // point to subsection
|
---|
| 1137 | lseek(fh, pxdi->pDirTab[i].lfoStart + pxdi->lfaBase, SEEK_SET);
|
---|
| 1138 | read(fh, (void *)&pxdi->ssmod.csBase, sizeof(SSMODULE));
|
---|
| 1139 | read(fh, (void *)ModName, (unsigned)pxdi->ssmod.csize);
|
---|
| 1140 | ModIndex = pxdi->pDirTab[i].modindex;
|
---|
| 1141 | ModName[pxdi->ssmod.csize] = '\0';
|
---|
| 1142 | i++;
|
---|
| 1143 | while (pxdi->pDirTab[i].modindex == ModIndex && i < numdir)
|
---|
| 1144 | {
|
---|
| 1145 | // point to subsection
|
---|
| 1146 | lseek(fh, pxdi->pDirTab[i].lfoStart + pxdi->lfaBase, SEEK_SET);
|
---|
| 1147 | switch (pxdi->pDirTab[i].sst)
|
---|
| 1148 | {
|
---|
| 1149 | case SSTPUBLICS:
|
---|
| 1150 | bytesread = 0;
|
---|
| 1151 | while (bytesread < pxdi->pDirTab[i].cb)
|
---|
| 1152 | {
|
---|
| 1153 | bytesread += read(fh, (void *)&pxdi->sspub.offset, sizeof(pxdi->sspub));
|
---|
| 1154 | bytesread += read(fh, (void *)ename, (unsigned)pxdi->sspub.csize);
|
---|
| 1155 | ename[pxdi->sspub.csize] = '\0';
|
---|
| 1156 | if ((pxdi->sspub.segment == TrapSeg) &&
|
---|
| 1157 | (pxdi->sspub.offset <= TrapOff) &&
|
---|
| 1158 | (pxdi->sspub.offset >= NrPublic))
|
---|
| 1159 | {
|
---|
| 1160 | NrPublic = pxdi->sspub.offset;
|
---|
| 1161 | sprintf(pxdi->szNrPub, "%s %s (%s) %04hX:%04hX\n",
|
---|
| 1162 | (pxdi->sspub.type == 1) ? " Abs" : " ", ename,
|
---|
| 1163 | ModName, // ()
|
---|
| 1164 | pxdi->sspub.segment,
|
---|
| 1165 | pxdi->sspub.offset
|
---|
| 1166 | );
|
---|
| 1167 | }
|
---|
| 1168 | }
|
---|
| 1169 | break;
|
---|
| 1170 |
|
---|
| 1171 | case SSTSRCLINES2:
|
---|
| 1172 | case SSTSRCLINES:
|
---|
| 1173 | if (TrapSeg != pxdi->ssmod.csBase)
|
---|
| 1174 | break;
|
---|
| 1175 | namelen = 0;
|
---|
| 1176 | read(fh, (void *)&namelen, 1);
|
---|
| 1177 | read(fh, (void *)ename, namelen);
|
---|
| 1178 | ename[namelen] = '\0';
|
---|
| 1179 | // skip 2 zero bytes
|
---|
| 1180 | if (pxdi->pDirTab[i].sst == SSTSRCLINES2)
|
---|
| 1181 | read(fh, (void *)&numlines, 2);
|
---|
| 1182 | read(fh, (void *)&numlines, 2);
|
---|
| 1183 | for (j = 0; j < numlines; j++)
|
---|
| 1184 | {
|
---|
| 1185 | read(fh, (void *)&line, 2);
|
---|
| 1186 | read(fh, (void *)&offset, 2);
|
---|
| 1187 | if (offset <= TrapOff && offset >= NrLine)
|
---|
| 1188 | {
|
---|
| 1189 | NrLine = offset;
|
---|
| 1190 | sprintf(pxdi->szNrFile, "% 12.12s ", ename);
|
---|
| 1191 | sprintf(pxdi->szNrLine, "% 6hu", line);
|
---|
| 1192 | /*sprintf(szNrLine,"%04hX:%04hX line #%hu (%s) (%s)\n",
|
---|
| 1193 | * ssmod.csBase,offset,line,ModName,ename); */
|
---|
| 1194 | }
|
---|
| 1195 | }
|
---|
| 1196 | break;
|
---|
| 1197 | } // end switch
|
---|
| 1198 | i++;
|
---|
| 1199 | } // end while modindex
|
---|
| 1200 | } // End While i < numdir
|
---|
[441] | 1201 |
|
---|
[8] | 1202 | free(pxdi->pDirTab);
|
---|
[441] | 1203 |
|
---|
| 1204 | return 0;
|
---|
[8] | 1205 | }
|
---|
| 1206 |
|
---|
| 1207 | /* ******************************************************************
|
---|
[14] | 1208 | *
|
---|
| 1209 | * PART 2: ANALYZE VARIABLES
|
---|
| 1210 | *
|
---|
[8] | 1211 | ********************************************************************/
|
---|
| 1212 |
|
---|
| 1213 | /*
|
---|
| 1214 | * var_value:
|
---|
| 1215 | * writes a description of a variable type to
|
---|
| 1216 | * the specified buffer, depending on "type".
|
---|
| 1217 | *
|
---|
| 1218 | *@@changed V0.9.1 (2000-01-30) [umoeller]: changed prototype to use external buffer
|
---|
| 1219 | */
|
---|
| 1220 |
|
---|
[222] | 1221 | STATIC VOID var_value(void *varptr, // in: address of the variable on the stack
|
---|
[142] | 1222 | char *pszBuf, // out: information
|
---|
| 1223 | BYTE type) // in: type; if >= 32, we'll call DosQueryMem
|
---|
[8] | 1224 | {
|
---|
| 1225 | ULONG Size = 1,
|
---|
| 1226 | Attr = 0;
|
---|
| 1227 |
|
---|
| 1228 | if (DosQueryMem(varptr, &Size, &Attr) != NO_ERROR)
|
---|
| 1229 | {
|
---|
| 1230 | sprintf(pszBuf, "type %d, DosQueryMem failed", type);
|
---|
| 1231 | return;
|
---|
| 1232 | }
|
---|
| 1233 |
|
---|
| 1234 | if ((Attr & PAG_READ) == 0)
|
---|
| 1235 | {
|
---|
| 1236 | sprintf(pszBuf, "type %d, read-access to value denied", type);
|
---|
| 1237 | return;
|
---|
| 1238 | }
|
---|
| 1239 |
|
---|
| 1240 | if (type == 0)
|
---|
| 1241 | sprintf(pszBuf, "%hd", *(signed char*)varptr);
|
---|
| 1242 | else if (type == 1)
|
---|
| 1243 | sprintf(pszBuf, "%hd", *(signed short*)varptr);
|
---|
| 1244 | else if (type == 2)
|
---|
| 1245 | sprintf(pszBuf, "%ld", *(signed long*)varptr);
|
---|
| 1246 | else if (type == 4)
|
---|
| 1247 | sprintf(pszBuf, "%hu", *(BYTE*) varptr);
|
---|
| 1248 | else if (type == 5)
|
---|
| 1249 | sprintf(pszBuf, "%hu", *(USHORT*)varptr);
|
---|
| 1250 | else if (type == 6)
|
---|
| 1251 | sprintf(pszBuf, "0x%lX (%lu)", *((ULONG*)varptr), *((ULONG*)varptr));
|
---|
| 1252 | else if (type == 8)
|
---|
| 1253 | sprintf(pszBuf, "%f", *(float*)varptr);
|
---|
| 1254 | else if (type == 9)
|
---|
| 1255 | sprintf(pszBuf, "%f", *(double*)varptr);
|
---|
| 1256 | else if (type == 10)
|
---|
[13] | 1257 | sprintf(pszBuf, "%f", (double)(*(long double*)varptr));
|
---|
[8] | 1258 | else if (type == 16)
|
---|
| 1259 | sprintf(pszBuf, "%s", *(char*)varptr ? "TRUE" : "FALSE");
|
---|
| 1260 | else if (type == 17)
|
---|
| 1261 | sprintf(pszBuf, "%s", *(short*)varptr ? "TRUE" : "FALSE");
|
---|
| 1262 | else if (type == 18)
|
---|
| 1263 | sprintf(pszBuf, "%s", *(long*)varptr ? "TRUE" : "FALSE");
|
---|
| 1264 | else if (type == 20)
|
---|
| 1265 | sprintf(pszBuf, "%c", *(char*)varptr);
|
---|
| 1266 | else if (type == 21)
|
---|
[13] | 1267 | sprintf(pszBuf, "%hd", (*(short*)varptr));
|
---|
[8] | 1268 | else if (type == 22)
|
---|
[13] | 1269 | sprintf(pszBuf, "%ld", *(long*)varptr);
|
---|
[8] | 1270 | else if (type == 23)
|
---|
| 1271 | sprintf(pszBuf, "void");
|
---|
| 1272 | else if (type >= 32)
|
---|
| 1273 | {
|
---|
[13] | 1274 | sprintf(pszBuf, "0x%p", (void*)(*(ULONG*)varptr));
|
---|
[8] | 1275 | if (Attr & PAG_FREE)
|
---|
| 1276 | {
|
---|
| 1277 | strcat(pszBuf, " unallocated memory");
|
---|
| 1278 | }
|
---|
| 1279 | else
|
---|
| 1280 | {
|
---|
| 1281 | if ((Attr & PAG_COMMIT) == 0x0U)
|
---|
| 1282 | {
|
---|
| 1283 | strcat(pszBuf, " uncommitted");
|
---|
| 1284 | } // endif
|
---|
| 1285 | if ((Attr & PAG_WRITE) == 0x0U)
|
---|
| 1286 | {
|
---|
| 1287 | strcat(pszBuf, " unwritable");
|
---|
| 1288 | } // endif
|
---|
| 1289 | if ((Attr & PAG_READ) == 0x0U)
|
---|
| 1290 | {
|
---|
| 1291 | strcat(pszBuf, " unreadable");
|
---|
| 1292 | } // endif
|
---|
| 1293 | } // endif
|
---|
| 1294 | } // endif
|
---|
| 1295 | else
|
---|
| 1296 | sprintf(pszBuf, "Unknown type %d", type);
|
---|
| 1297 | }
|
---|
| 1298 |
|
---|
| 1299 | /*
|
---|
| 1300 | * search_userdefs:
|
---|
| 1301 | * searches the table of userdef's-
|
---|
| 1302 | * Return TRUE if found.
|
---|
| 1303 | */
|
---|
| 1304 |
|
---|
[222] | 1305 | STATIC BOOL search_userdefs(FILE *LogFile, // in: text log file to write to
|
---|
[142] | 1306 | ULONG stackofs,
|
---|
| 1307 | USHORT var_no)
|
---|
[8] | 1308 | {
|
---|
| 1309 | USHORT pos;
|
---|
| 1310 |
|
---|
| 1311 | for (pos = 0;
|
---|
| 1312 | pos < userdef_count;
|
---|
| 1313 | pos++)
|
---|
| 1314 | {
|
---|
| 1315 | if (one_userdef[pos].idx == autovar_def[var_no].type_idx)
|
---|
| 1316 | {
|
---|
| 1317 | if ( (one_userdef[pos].type_index >= 0x80)
|
---|
| 1318 | // && (one_userdef[pos].type_index <= 0xDA)
|
---|
| 1319 | )
|
---|
| 1320 | {
|
---|
| 1321 | static char sszVar3[500] = "complex";
|
---|
| 1322 | if (one_userdef[pos].type_index <= 0xDA)
|
---|
| 1323 | var_value((void*)(stackofs + autovar_def[var_no].stack_offset),
|
---|
| 1324 | sszVar3,
|
---|
| 1325 | one_userdef[pos].type_index - 0x80);
|
---|
| 1326 |
|
---|
[13] | 1327 | fprintf(LogFile,
|
---|
| 1328 | " %- 6ld %- 20.20s %- 33.33s %s (user)\n",
|
---|
[8] | 1329 | autovar_def[var_no].stack_offset, // stack offset
|
---|
| 1330 | autovar_def[var_no].name, // identifier
|
---|
| 1331 | one_userdef[pos].name, // type name
|
---|
| 1332 | sszVar3 // composed by var_value
|
---|
| 1333 | );
|
---|
| 1334 | return TRUE;
|
---|
| 1335 | }
|
---|
| 1336 | else
|
---|
| 1337 | return FALSE;
|
---|
| 1338 | }
|
---|
| 1339 | }
|
---|
| 1340 |
|
---|
| 1341 | return FALSE;
|
---|
| 1342 | }
|
---|
| 1343 |
|
---|
| 1344 | /*
|
---|
| 1345 | * search_pointers:
|
---|
| 1346 | *
|
---|
| 1347 | */
|
---|
| 1348 |
|
---|
[222] | 1349 | STATIC BOOL search_pointers(FILE *LogFile, // in: text log file to write to
|
---|
[142] | 1350 | ULONG stackofs,
|
---|
| 1351 | USHORT var_no)
|
---|
[8] | 1352 | {
|
---|
| 1353 | USHORT pos, upos;
|
---|
| 1354 | static BYTE str[35];
|
---|
| 1355 | static char sszVar[500];
|
---|
| 1356 |
|
---|
| 1357 | // BYTE type_index;
|
---|
| 1358 |
|
---|
| 1359 | for (pos = 0;
|
---|
| 1360 | ( (pos < pointer_count)
|
---|
| 1361 | && (one_pointer[pos].idx != autovar_def[var_no].type_idx)
|
---|
| 1362 | );
|
---|
| 1363 | pos++);
|
---|
| 1364 |
|
---|
| 1365 | if (pos < pointer_count)
|
---|
| 1366 | {
|
---|
| 1367 | if ( (one_pointer[pos].type_index >= 0x80)
|
---|
| 1368 | && (one_pointer[pos].type_index <= 0xDA)
|
---|
| 1369 | )
|
---|
| 1370 | {
|
---|
| 1371 | strcpy(str, type_name[one_pointer[pos].type_index - 0x80]);
|
---|
| 1372 | strcat(str, " *");
|
---|
| 1373 | var_value((void*)(stackofs + autovar_def[var_no].stack_offset),
|
---|
| 1374 | sszVar,
|
---|
| 1375 | 32);
|
---|
[13] | 1376 | fprintf(LogFile, " %- 6ld %- 20.20s %- 33.33s %s (ptr1)\n",
|
---|
[8] | 1377 | autovar_def[var_no].stack_offset,
|
---|
| 1378 | autovar_def[var_no].name,
|
---|
| 1379 | str,
|
---|
| 1380 | sszVar);
|
---|
| 1381 | return TRUE;
|
---|
| 1382 | }
|
---|
| 1383 | else
|
---|
| 1384 | {
|
---|
| 1385 | // If the result isn't a simple type, look for it in the other lists
|
---|
| 1386 | for (upos = 0;
|
---|
| 1387 | ( (upos < userdef_count)
|
---|
| 1388 | && (one_userdef[upos].idx != one_pointer[pos].type_index)
|
---|
| 1389 | );
|
---|
| 1390 | upos++)
|
---|
| 1391 | ;
|
---|
| 1392 |
|
---|
| 1393 | if (upos < userdef_count)
|
---|
| 1394 | {
|
---|
| 1395 | strcpy(str, one_userdef[upos].name);
|
---|
| 1396 | strcat(str, " *");
|
---|
| 1397 | var_value((void *)(stackofs + autovar_def[var_no].stack_offset),
|
---|
| 1398 | sszVar,
|
---|
| 1399 | 32);
|
---|
[13] | 1400 | fprintf(LogFile, " %- 6ld %- 20.20s %- 33.33s %s (ptr2)\n",
|
---|
[8] | 1401 | autovar_def[var_no].stack_offset,
|
---|
| 1402 | autovar_def[var_no].name,
|
---|
| 1403 | str,
|
---|
| 1404 | sszVar);
|
---|
| 1405 | return TRUE;
|
---|
| 1406 | }
|
---|
| 1407 | else
|
---|
| 1408 | {
|
---|
| 1409 | // if it isn't a userdef, for now give up and just print
|
---|
| 1410 | // as much as we know
|
---|
| 1411 | sprintf(str, "Pointer to type 0x%X", one_pointer[pos].type_index);
|
---|
| 1412 |
|
---|
| 1413 | var_value((void *)(stackofs + autovar_def[var_no].stack_offset),
|
---|
| 1414 | sszVar,
|
---|
| 1415 | 32);
|
---|
[13] | 1416 | fprintf(LogFile, " %- 6ld %- 20.20s %- 33.33s %s (ptr3)\n",
|
---|
[8] | 1417 | autovar_def[var_no].stack_offset,
|
---|
| 1418 | autovar_def[var_no].name,
|
---|
| 1419 | str,
|
---|
| 1420 | sszVar);
|
---|
| 1421 |
|
---|
| 1422 | return TRUE;
|
---|
| 1423 | }
|
---|
| 1424 | }
|
---|
| 1425 | }
|
---|
| 1426 |
|
---|
| 1427 | return FALSE;
|
---|
| 1428 | }
|
---|
| 1429 |
|
---|
| 1430 | /*
|
---|
| 1431 | *@@ dbgPrintVariables:
|
---|
| 1432 | * Dumps variables for the specified stack offset
|
---|
| 1433 | * to the specified log file.
|
---|
| 1434 | *
|
---|
| 1435 | * New with V0.84.
|
---|
| 1436 | */
|
---|
| 1437 |
|
---|
| 1438 | void dbgPrintVariables(FILE *LogFile, // in: text log file to write to
|
---|
| 1439 | ULONG stackofs)
|
---|
| 1440 | {
|
---|
| 1441 | USHORT n; // , pos;
|
---|
| 1442 | BOOL AutoVarsFound = FALSE;
|
---|
| 1443 |
|
---|
| 1444 | if (/* 1 || */ func_ofs == pubfunc_ofs)
|
---|
| 1445 | {
|
---|
| 1446 | for (n = 0;
|
---|
| 1447 | n < var_ofs;
|
---|
| 1448 | n++)
|
---|
| 1449 | {
|
---|
| 1450 | if (AutoVarsFound == FALSE)
|
---|
| 1451 | {
|
---|
| 1452 | AutoVarsFound = TRUE;
|
---|
[13] | 1453 | fprintf(LogFile, " List of auto variables at EBP %p in %s:\n",
|
---|
| 1454 | (PVOID)stackofs,
|
---|
| 1455 | func_name);
|
---|
[8] | 1456 | fprintf(LogFile, " Offset Name Type Value \n");
|
---|
| 1457 | fprintf(LogFile, " ÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\n");
|
---|
| 1458 | }
|
---|
| 1459 |
|
---|
| 1460 | // If it's one of the simple types
|
---|
| 1461 | if ( (autovar_def[n].type_idx >= 0x80)
|
---|
| 1462 | && (autovar_def[n].type_idx <= 0xDA)
|
---|
| 1463 | )
|
---|
| 1464 | {
|
---|
| 1465 | static char sszVar2[500];
|
---|
| 1466 |
|
---|
| 1467 | var_value((void *)(stackofs + autovar_def[n].stack_offset),
|
---|
| 1468 | sszVar2,
|
---|
| 1469 | autovar_def[n].type_idx - 0x80);
|
---|
| 1470 |
|
---|
[13] | 1471 | fprintf(LogFile, " %- 6ld %- 20.20s %- 33.33s %s (simple)\n",
|
---|
[8] | 1472 | autovar_def[n].stack_offset,
|
---|
| 1473 | autovar_def[n].name,
|
---|
| 1474 | type_name[autovar_def[n].type_idx - 0x80],
|
---|
| 1475 | sszVar2);
|
---|
| 1476 | }
|
---|
| 1477 | else
|
---|
| 1478 | { // Complex type, check if we know what it is
|
---|
| 1479 | if (!search_userdefs(LogFile, stackofs, n))
|
---|
| 1480 | {
|
---|
| 1481 | if (!search_pointers(LogFile, stackofs, n))
|
---|
| 1482 | {
|
---|
[13] | 1483 | fprintf(LogFile, " %- 6ld %-20.20s 0x%X (unknown)\n",
|
---|
[8] | 1484 | autovar_def[n].stack_offset,
|
---|
| 1485 | autovar_def[n].name,
|
---|
| 1486 | autovar_def[n].type_idx);
|
---|
| 1487 | }
|
---|
| 1488 | }
|
---|
| 1489 | }
|
---|
| 1490 | }
|
---|
| 1491 | /* if (AutoVarsFound == FALSE)
|
---|
| 1492 | {
|
---|
| 1493 | fprintf(LogFile, " No auto variables found in %s.\n", func_name);
|
---|
| 1494 | } */
|
---|
| 1495 | fprintf(LogFile, "\n");
|
---|
| 1496 | }
|
---|
| 1497 | }
|
---|
| 1498 |
|
---|
| 1499 | /* ******************************************************************
|
---|
[14] | 1500 | *
|
---|
| 1501 | * PART 3: ANALYZE SYMBOL (.SYM) FILE
|
---|
| 1502 | *
|
---|
[8] | 1503 | ********************************************************************/
|
---|
| 1504 |
|
---|
| 1505 | /*
|
---|
| 1506 | *@@ dbgPrintSYMInfo:
|
---|
| 1507 | * this gets called by dbgPrintStack if dbgPrintDebugInfo
|
---|
| 1508 | * failed (because no debug code was found) to check if
|
---|
| 1509 | * maybe a SYM file with the same filename exists and try
|
---|
| 1510 | * to get the info from there.
|
---|
| 1511 | *
|
---|
| 1512 | * This gets called for every line of the stack
|
---|
| 1513 | * walk, but only if getting the information from
|
---|
| 1514 | * the debug code failed, e.g. because no debug code
|
---|
| 1515 | * was available for an address.
|
---|
| 1516 | *
|
---|
| 1517 | * The file pointer is in the "Source file" column
|
---|
| 1518 | * every time this gets called.
|
---|
| 1519 | *
|
---|
| 1520 | * New with V0.84.
|
---|
| 1521 | *
|
---|
| 1522 | * Returns 0 if reading the SYM file was successful.
|
---|
| 1523 | *
|
---|
| 1524 | *@@changed V0.9.1 (2000-01-30) [umoeller]: added return code; this used to be VOID
|
---|
| 1525 | */
|
---|
| 1526 |
|
---|
| 1527 | int dbgPrintSYMInfo(FILE *LogFile, // in: text log file to write to
|
---|
| 1528 | CHAR *SymFileName, // in: SYM file name (can be fully q'fied)
|
---|
| 1529 | ULONG Object,
|
---|
| 1530 | ULONG TrapOffset)
|
---|
| 1531 | {
|
---|
| 1532 | static FILE *SymFile;
|
---|
| 1533 | static MAPDEF MapDef;
|
---|
| 1534 | static SEGDEF SegDef;
|
---|
| 1535 | static SYMDEF32 SymDef32;
|
---|
| 1536 | static SYMDEF16 SymDef16;
|
---|
| 1537 | static char Buffer[256];
|
---|
| 1538 | static int SegNum, SymNum, LastVal;
|
---|
| 1539 | static unsigned long int SegOffset,
|
---|
| 1540 | SymOffset, SymPtrOffset;
|
---|
| 1541 |
|
---|
| 1542 | // open .SYM file
|
---|
[229] | 1543 | #ifdef DEBUG_SYMDUMP // V1.0.0 (2002-08-21) [paperino]
|
---|
[212] | 1544 | fprintf(LogFile,"Dump of '%s' for object %d\n",SymFileName,Object);
|
---|
| 1545 | #endif
|
---|
[8] | 1546 | SymFile = fopen(SymFileName, "rb");
|
---|
| 1547 | if (SymFile == 0)
|
---|
[441] | 1548 | return 2;
|
---|
[8] | 1549 |
|
---|
| 1550 | // read in first map definition
|
---|
| 1551 | fread(&MapDef, sizeof(MAPDEF), 1, SymFile);
|
---|
[212] | 1552 | #ifdef DEBUG_SYMDUMP
|
---|
| 1553 | Buffer[0] = MapDef.achModName[0];
|
---|
| 1554 | fread(&Buffer[1], 1, MapDef.cbModName-1, SymFile);
|
---|
| 1555 | Buffer[MapDef.cbModName] = 0x00;
|
---|
| 1556 | fprintf(LogFile,"Module name '%s'\n",Buffer);
|
---|
| 1557 | #endif
|
---|
[8] | 1558 |
|
---|
| 1559 | SegOffset = SEGDEFOFFSET(MapDef);
|
---|
[212] | 1560 | #ifdef DEBUG_SYMDUMP
|
---|
| 1561 | fprintf(LogFile,"SegOffset %0x\n",SegOffset);
|
---|
| 1562 | #endif
|
---|
[8] | 1563 |
|
---|
| 1564 | // go thru all segments
|
---|
| 1565 | for (SegNum = 0;
|
---|
| 1566 | SegNum < MapDef.cSegs;
|
---|
| 1567 | SegNum++)
|
---|
| 1568 | {
|
---|
[212] | 1569 | #ifdef DEBUG_SYMDUMP
|
---|
| 1570 | fprintf(LogFile,"Scanning segment #%d Offset %08X\n",SegNum,SegOffset);
|
---|
| 1571 | #endif
|
---|
[8] | 1572 | if (fseek(SymFile, SegOffset, SEEK_SET))
|
---|
| 1573 | // seek error
|
---|
[441] | 1574 | return 3;
|
---|
[8] | 1575 |
|
---|
| 1576 | // read in segment definition
|
---|
| 1577 | fread(&SegDef, sizeof(SEGDEF), 1, SymFile);
|
---|
[212] | 1578 | Buffer[0] = SegDef.achSegName[0];
|
---|
| 1579 | fread(&Buffer[1], 1, SegDef.cbSegName-1, SymFile);
|
---|
| 1580 | Buffer[SegDef.cbSegName] = 0x00;
|
---|
| 1581 | #ifdef DEBUG_SYMDUMP
|
---|
| 1582 | fprintf(LogFile,"Segment name '%s', number %d, flags %02x\n",Buffer,SegNum,SegDef.bFlags);
|
---|
| 1583 | #endif
|
---|
| 1584 |
|
---|
[8] | 1585 | if (SegNum == Object)
|
---|
| 1586 | {
|
---|
| 1587 | // stack object found:
|
---|
| 1588 | Buffer[0] = 0x00;
|
---|
| 1589 | LastVal = 0;
|
---|
| 1590 |
|
---|
| 1591 | // go thru all symbols in this object
|
---|
[212] | 1592 | #ifdef DEBUG_SYMDUMP
|
---|
| 1593 | fprintf(LogFile,"Scanning #%d symbols\n",SegDef.cSymbols);
|
---|
| 1594 | #endif
|
---|
[8] | 1595 | for (SymNum = 0; SymNum < SegDef.cSymbols; SymNum++)
|
---|
| 1596 | {
|
---|
[229] | 1597 | // fixed syms > 64 K V1.0.0 (2002-08-21) [paperino]
|
---|
[8] | 1598 | if (SegDef.bFlags & 0x01)
|
---|
| 1599 | {
|
---|
| 1600 | // 32-bit symbol:
|
---|
| 1601 | fread(&SymDef32, sizeof(SYMDEF32), 1, SymFile);
|
---|
| 1602 | if (SymDef32.wSymVal > TrapOffset)
|
---|
| 1603 | {
|
---|
| 1604 | // symbol found
|
---|
[121] | 1605 | fprintf(LogFile,
|
---|
| 1606 | "between %s + 0x%lX ",
|
---|
| 1607 | Buffer,
|
---|
| 1608 | TrapOffset - LastVal);
|
---|
[13] | 1609 | /* fprintf(LogFile, "(ppLineDef: 0x%lX) ",
|
---|
[8] | 1610 | LINEDEFOFFSET(SegDef)
|
---|
[13] | 1611 | ); */
|
---|
[8] | 1612 | fprintf(LogFile, "\n");
|
---|
| 1613 | }
|
---|
| 1614 |
|
---|
| 1615 | LastVal = SymDef32.wSymVal;
|
---|
| 1616 | Buffer[0] = SymDef32.achSymName[0];
|
---|
[212] | 1617 | fread(&Buffer[1], 1, SymDef32.cbSymName-1, SymFile);
|
---|
[8] | 1618 | Buffer[SymDef32.cbSymName] = 0x00;
|
---|
[212] | 1619 | #ifdef DEBUG_SYMDUMP
|
---|
| 1620 | fprintf(LogFile,"32 Bit Symbol Address %08p <%s> \n",SymDef32.wSymVal,Buffer);
|
---|
| 1621 | #endif
|
---|
[8] | 1622 |
|
---|
| 1623 | if (SymDef32.wSymVal > TrapOffset)
|
---|
| 1624 | {
|
---|
| 1625 | // symbol found, as above
|
---|
[121] | 1626 | fprintf(LogFile,
|
---|
| 1627 | " "
|
---|
| 1628 | "and %s - 0x%lX ",
|
---|
| 1629 | Buffer,
|
---|
| 1630 | LastVal - TrapOffset);
|
---|
[8] | 1631 | fprintf(LogFile, "\n");
|
---|
| 1632 | break;
|
---|
| 1633 | }
|
---|
| 1634 | }
|
---|
| 1635 | else
|
---|
| 1636 | {
|
---|
| 1637 | // 16-bit symbol:
|
---|
| 1638 | fread(&SymDef16, sizeof(SYMDEF16), 1, SymFile);
|
---|
| 1639 | if (SymDef16.wSymVal > TrapOffset)
|
---|
| 1640 | {
|
---|
[121] | 1641 | fprintf(LogFile,
|
---|
| 1642 | "between %s + %lX\n",
|
---|
| 1643 | Buffer,
|
---|
| 1644 | TrapOffset - LastVal);
|
---|
[8] | 1645 | }
|
---|
| 1646 | LastVal = SymDef16.wSymVal;
|
---|
| 1647 | Buffer[0] = SymDef16.achSymName[0];
|
---|
[212] | 1648 | fread(&Buffer[1], 1, SymDef16.cbSymName-1, SymFile);
|
---|
[8] | 1649 | Buffer[SymDef16.cbSymName] = 0x00;
|
---|
| 1650 | if (SymDef16.wSymVal > TrapOffset)
|
---|
| 1651 | {
|
---|
[121] | 1652 | fprintf(LogFile,
|
---|
| 1653 | " "
|
---|
| 1654 | "and %s - %lX\n",
|
---|
| 1655 | Buffer,
|
---|
| 1656 | LastVal - TrapOffset);
|
---|
[8] | 1657 | break;
|
---|
| 1658 | }
|
---|
[212] | 1659 | #ifdef DEBUG_SYMDUMP
|
---|
| 1660 | fprintf(LogFile,"16 Bit Symbol <%s> Address %p\n",Buffer,SymDef16.wSymVal);
|
---|
| 1661 | #endif
|
---|
[8] | 1662 | } // endif
|
---|
| 1663 | }
|
---|
| 1664 | break;
|
---|
| 1665 | } // endif
|
---|
| 1666 | SegOffset = NEXTSEGDEFOFFSET(SegDef);
|
---|
| 1667 | } // endwhile
|
---|
[441] | 1668 |
|
---|
[8] | 1669 | fclose(SymFile);
|
---|
[441] | 1670 |
|
---|
| 1671 | return 0; // no error
|
---|
[8] | 1672 | }
|
---|
| 1673 |
|
---|
| 1674 | /* ******************************************************************
|
---|
[14] | 1675 | *
|
---|
| 1676 | * PART 4: dbgPrintStack
|
---|
| 1677 | *
|
---|
[8] | 1678 | ********************************************************************/
|
---|
| 1679 |
|
---|
| 1680 | /*
|
---|
| 1681 | *@@ dbgPrintStackFrame:
|
---|
| 1682 | * parses and dumps one stack frame.
|
---|
| 1683 | * Called from excPrintStackFrame.
|
---|
| 1684 | *
|
---|
| 1685 | * This calls dbgPrintDebugInfo and, if
|
---|
| 1686 | * that fails, dbgPrintSYMInfo.
|
---|
| 1687 | *
|
---|
| 1688 | *@@added V0.9.2 (2000-03-10) [umoeller]
|
---|
| 1689 | *@@changed V0.9.3 (2000-04-10) [umoeller]: added support for non-Warp 4 SYM files
|
---|
| 1690 | *@@changed V0.9.3 (2000-04-26) [umoeller]: this broke Warp 4 FP 13, fixed
|
---|
[430] | 1691 | *@@changed V1.0.12 (2017-01-15) [rwalsh]: improve handling for Warp 4.5 SYM files
|
---|
[8] | 1692 | */
|
---|
| 1693 |
|
---|
| 1694 | BOOL dbgPrintStackFrame(FILE *LogFile,
|
---|
| 1695 | PSZ pszModuleName, // in: module name (fully q'fied)
|
---|
| 1696 | ULONG ulObject,
|
---|
| 1697 | ULONG ulOffset)
|
---|
| 1698 | {
|
---|
[430] | 1699 | APIRET arc = 0;
|
---|
| 1700 | PSZ pszFilename;
|
---|
| 1701 | PSZ pszVersionDir;
|
---|
| 1702 | ULONG aulBuf[3];
|
---|
| 1703 | CHAR szSymName[CCHMAXPATH];
|
---|
| 1704 | CHAR szSymPath[CCHMAXPATH];
|
---|
[8] | 1705 |
|
---|
[430] | 1706 | // look for .sym in the module's directory
|
---|
| 1707 | strcpy(szSymName, pszModuleName);
|
---|
| 1708 | strcpy(szSymName + strlen(szSymName) - 3, "SYM");
|
---|
| 1709 | if (!dbgPrintSYMInfo(LogFile, szSymName, ulObject, ulOffset))
|
---|
| 1710 | return TRUE;
|
---|
| 1711 |
|
---|
| 1712 | pszFilename = strrchr(szSymName, '\\');
|
---|
| 1713 | if (!pszFilename)
|
---|
[8] | 1714 | {
|
---|
[430] | 1715 | fprintf(LogFile, "Cannot find symbol file for %s\n", pszModuleName);
|
---|
| 1716 | return FALSE;
|
---|
| 1717 | }
|
---|
| 1718 | pszFilename++;
|
---|
[8] | 1719 |
|
---|
[430] | 1720 | // check the SYM files in the \OS2 directory,
|
---|
| 1721 | // depending on the OS/2 version level:
|
---|
| 1722 | DosQuerySysInfo(QSV_VERSION_MAJOR, QSV_VERSION_MINOR,
|
---|
| 1723 | &aulBuf, sizeof(aulBuf));
|
---|
[8] | 1724 |
|
---|
[430] | 1725 | // Warp 3 is reported as 20.30
|
---|
| 1726 | // Warp 4 is reported as 20.40
|
---|
| 1727 | // WSEB is reported as 20.45
|
---|
| 1728 | // (NOTE: Warp 4 FP 13 now returns 45 also,
|
---|
| 1729 | // but the SYM files are still in the WARP4 directory)
|
---|
[8] | 1730 |
|
---|
[430] | 1731 | // try the directories used by the "real" Warp 4.5 first
|
---|
| 1732 | if (aulBuf[1] == 45)
|
---|
| 1733 | {
|
---|
| 1734 | sprintf(szSymPath, "%c:\\OS2\\PDPSI\\PMDF\\%s\\%s",
|
---|
| 1735 | doshQueryBootDrive(), "WARP45", pszFilename);
|
---|
| 1736 | if (!dbgPrintSYMInfo(LogFile, szSymPath, ulObject, ulOffset))
|
---|
| 1737 | return TRUE;
|
---|
[8] | 1738 |
|
---|
[430] | 1739 | // use the nbr of processors to decide which directory to search
|
---|
| 1740 | if (DosQuerySysInfo(QSV_NUMPROCESSORS, QSV_NUMPROCESSORS,
|
---|
| 1741 | &aulBuf[2], sizeof(aulBuf[2]))
|
---|
| 1742 | || aulBuf[2] == 1)
|
---|
| 1743 | pszVersionDir = "WARP45_U";
|
---|
| 1744 | else
|
---|
| 1745 | pszVersionDir = "WARP45_S";
|
---|
[8] | 1746 |
|
---|
[430] | 1747 | sprintf(szSymPath, "%c:\\OS2\\PDPSI\\PMDF\\%s\\%s",
|
---|
| 1748 | doshQueryBootDrive(), pszVersionDir, pszFilename);
|
---|
| 1749 | if (!dbgPrintSYMInfo(LogFile, szSymPath, ulObject, ulOffset))
|
---|
| 1750 | return TRUE;
|
---|
[8] | 1751 | }
|
---|
| 1752 |
|
---|
[430] | 1753 | // deal with Warp 3 and Warp4 pre- and post-FP13
|
---|
| 1754 | if (aulBuf[1] == 30)
|
---|
| 1755 | pszVersionDir = "WARP3";
|
---|
| 1756 | else
|
---|
| 1757 | pszVersionDir = "WARP4";
|
---|
| 1758 |
|
---|
| 1759 | sprintf(szSymPath, "%c:\\OS2\\PDPSI\\PMDF\\%s\\%s",
|
---|
| 1760 | doshQueryBootDrive(), pszVersionDir, pszFilename);
|
---|
| 1761 | arc = dbgPrintSYMInfo(LogFile, szSymPath, ulObject, ulOffset);
|
---|
| 1762 |
|
---|
| 1763 | if (arc == 2)
|
---|
| 1764 | fprintf(LogFile, "Cannot find symbol file %s\n",
|
---|
| 1765 | szSymName);
|
---|
| 1766 | else if (arc != 0)
|
---|
| 1767 | fprintf(LogFile, "Error %lu reading symbol file %s\n",
|
---|
| 1768 | arc, szSymName);
|
---|
| 1769 |
|
---|
[8] | 1770 | return (arc == NO_ERROR);
|
---|
| 1771 | }
|
---|
| 1772 |
|
---|
| 1773 | /*
|
---|
| 1774 | *@@ dbgPrintStack:
|
---|
| 1775 | * this takes stack data from the TIB and
|
---|
| 1776 | * context record data structures and tries
|
---|
| 1777 | * to analyse what the different stack frames
|
---|
| 1778 | * point to.
|
---|
| 1779 | *
|
---|
| 1780 | * For each stack frame, this calls dbgPrintDebugInfo,
|
---|
| 1781 | * and, if that fails, dbgPrintSYMInfo.
|
---|
| 1782 | *
|
---|
| 1783 | * New with V0.84.
|
---|
| 1784 | *
|
---|
| 1785 | *@@changed V0.9.2 (2000-03-08) [umoeller]: now searching OS2\PDPSI\PMDF for SYM files also
|
---|
[384] | 1786 | *@@changed XWP V1.0.9 (2010-04-16) [pr]: fixed module name display bugs
|
---|
[8] | 1787 | */
|
---|
| 1788 |
|
---|
| 1789 | VOID dbgPrintStack(FILE *LogFile, // in: text log file to write to
|
---|
| 1790 | PUSHORT StackBottom,
|
---|
| 1791 | PUSHORT StackTop,
|
---|
| 1792 | PUSHORT Ebp,
|
---|
| 1793 | PUSHORT ExceptionAddress)
|
---|
| 1794 | {
|
---|
| 1795 | PUSHORT RetAddr = 0;
|
---|
| 1796 | PUSHORT LastEbp = 0;
|
---|
| 1797 | APIRET rc = 0;
|
---|
| 1798 | ULONG Size = 0,
|
---|
| 1799 | Attr = 0;
|
---|
| 1800 | USHORT Cs = 0,
|
---|
| 1801 | Ip = 0,
|
---|
| 1802 | // Bp,
|
---|
| 1803 | Sp = 0;
|
---|
[384] | 1804 | char Name[CCHMAXPATH];
|
---|
[8] | 1805 | HMODULE hMod = 0;
|
---|
| 1806 | ULONG ObjNum = 0;
|
---|
| 1807 | ULONG Offset = 0;
|
---|
| 1808 | BOOL fExceptionAddress = TRUE; // Use Exception Addr 1st time thru
|
---|
| 1809 |
|
---|
| 1810 | // Note: we can't handle stacks bigger than 64K for now...
|
---|
| 1811 | Sp = (USHORT) (((ULONG) StackBottom) >> 16);
|
---|
| 1812 | // Bp = ;
|
---|
| 1813 |
|
---|
| 1814 | if (!f32bit)
|
---|
| 1815 | Ebp = (PUSHORT) MAKEULONG(((USHORT)(ULONG)Ebp), Sp);
|
---|
| 1816 |
|
---|
| 1817 | fprintf(LogFile, "\n\nCall stack:\n");
|
---|
| 1818 | fprintf(LogFile, " Source Line Nearest\n");
|
---|
| 1819 | fprintf(LogFile, " EBP Address Module Obj# File Numbr Public Symbol\n");
|
---|
| 1820 | fprintf(LogFile, " ÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄ- ÄÄÄÄÄÄÄÄ ÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄ-\n");
|
---|
| 1821 |
|
---|
| 1822 | do
|
---|
| 1823 | {
|
---|
| 1824 | Size = 10;
|
---|
| 1825 | rc = DosQueryMem((PVOID) (Ebp + 2), &Size, &Attr);
|
---|
| 1826 | if (rc != NO_ERROR)
|
---|
| 1827 | {
|
---|
[13] | 1828 | fprintf(LogFile, "Invalid EBP %8.8lX (DosQueryMem returned %lu)\n", (ULONG)Ebp, rc);
|
---|
[8] | 1829 | break;
|
---|
| 1830 | }
|
---|
| 1831 | if (!(Attr & PAG_COMMIT))
|
---|
| 1832 | {
|
---|
[13] | 1833 | fprintf(LogFile, "Invalid EBP %8.8lX (not committed)\n", (ULONG)Ebp);
|
---|
[8] | 1834 | break;
|
---|
| 1835 | }
|
---|
| 1836 | if (Size < 10)
|
---|
| 1837 | {
|
---|
[13] | 1838 | fprintf(LogFile, "Invalid EBP %8.8lX (mem block size < 10)\n", (ULONG)Ebp);
|
---|
[8] | 1839 | break;
|
---|
| 1840 | }
|
---|
| 1841 |
|
---|
| 1842 | if (fExceptionAddress)
|
---|
| 1843 | RetAddr = ExceptionAddress;
|
---|
| 1844 | else
|
---|
| 1845 | RetAddr = (PUSHORT) (*((PULONG) (Ebp + 2)));
|
---|
| 1846 |
|
---|
| 1847 | if (RetAddr == (PUSHORT) 0x00000053)
|
---|
| 1848 | {
|
---|
| 1849 | // For some reason there's a "return address" of 0x53 following
|
---|
| 1850 | // EBP on the stack and we have to adjust EBP by 44 bytes to get
|
---|
| 1851 | // at the real return address. This has something to do with
|
---|
| 1852 | // thunking from 32bits to 16bits...
|
---|
| 1853 | // Serious kludge, and it's probably dependent on versions of C(++)
|
---|
| 1854 | // runtime or OS, but it works for now!
|
---|
| 1855 | Ebp += 22;
|
---|
| 1856 | RetAddr = (PUSHORT) (*((PULONG) (Ebp + 2)));
|
---|
| 1857 | }
|
---|
| 1858 |
|
---|
| 1859 | // Get the (possibly) 16bit CS and IP
|
---|
| 1860 | if (fExceptionAddress)
|
---|
| 1861 | {
|
---|
| 1862 | Cs = (USHORT) (((ULONG) ExceptionAddress) >> 16);
|
---|
| 1863 | Ip = (USHORT) (ULONG) ExceptionAddress;
|
---|
| 1864 | }
|
---|
| 1865 | else
|
---|
| 1866 | {
|
---|
| 1867 | Cs = *(Ebp + 2);
|
---|
| 1868 | Ip = *(Ebp + 1);
|
---|
| 1869 | }
|
---|
| 1870 |
|
---|
| 1871 | // if the return address points to the stack then it's really just
|
---|
| 1872 | // a pointer to the return address (UGH!).
|
---|
| 1873 | if ( (USHORT) (((ULONG) RetAddr) >> 16) == Sp
|
---|
| 1874 | )
|
---|
| 1875 | RetAddr = (PUSHORT) (*((PULONG) RetAddr));
|
---|
| 1876 |
|
---|
| 1877 | if (Ip == 0 && *Ebp == 0)
|
---|
| 1878 | {
|
---|
| 1879 | // End of the stack so these are both shifted by 2 bytes:
|
---|
| 1880 | Cs = *(Ebp + 3);
|
---|
| 1881 | Ip = *(Ebp + 2);
|
---|
| 1882 | }
|
---|
| 1883 |
|
---|
| 1884 | // 16bit programs have on the stack:
|
---|
| 1885 | // BP:IP:CS
|
---|
| 1886 | // where CS may be thunked
|
---|
| 1887 | //
|
---|
| 1888 | // in dump swapped
|
---|
| 1889 | // BP IP CS BP CS IP
|
---|
| 1890 | // 4677 53B5 F7D0 7746 D0F7 B553
|
---|
| 1891 | //
|
---|
| 1892 | // 32bit programs have:
|
---|
| 1893 | // EBP:EIP
|
---|
| 1894 | // and you'd have something like this (with SP added) (not
|
---|
| 1895 | // accurate values)
|
---|
| 1896 | //
|
---|
| 1897 | // in dump swapped
|
---|
| 1898 | // EBP EIP EBP EIP
|
---|
| 1899 | // 4677 2900 53B5 F7D0 0029 7746 D0F7 B553
|
---|
| 1900 | //
|
---|
| 1901 | // So the basic difference is that 32bit programs have a 32bit
|
---|
| 1902 | // EBP and we can attempt to determine whether we have a 32bit
|
---|
| 1903 | // EBP by checking to see if its 'selector' is the same as SP.
|
---|
| 1904 | // Note that this technique limits us to checking stacks < 64K.
|
---|
| 1905 | //
|
---|
| 1906 | // Soooo, if IP (which maps into the same USHORT as the swapped
|
---|
| 1907 | // stack page in EBP) doesn't point to the stack (i.e. it could
|
---|
| 1908 | // be a 16bit IP) then see if CS is valid (as is or thunked).
|
---|
| 1909 | //
|
---|
| 1910 | // Note that there's the possibility of a 16bit return address
|
---|
| 1911 | // that has an offset that's the same as SP so we'll think it's
|
---|
| 1912 | // a 32bit return address and won't be able to successfully resolve
|
---|
| 1913 | // its details.
|
---|
| 1914 | if (Ip != Sp)
|
---|
| 1915 | {
|
---|
| 1916 | if (DOS16SIZESEG(Cs, &Size) == NO_ERROR)
|
---|
| 1917 | {
|
---|
| 1918 | RetAddr = (USHORT * _Seg16) MAKEULONG(Ip, Cs);
|
---|
| 1919 | f32bit = FALSE;
|
---|
| 1920 | }
|
---|
| 1921 | else if (DOS16SIZESEG((Cs << 3) + 7, &Size) == NO_ERROR)
|
---|
| 1922 | {
|
---|
| 1923 | Cs = (Cs << 3) + 7;
|
---|
| 1924 | RetAddr = (USHORT * _Seg16) MAKEULONG(Ip, Cs);
|
---|
| 1925 | f32bit = FALSE;
|
---|
| 1926 | }
|
---|
| 1927 | else
|
---|
| 1928 | f32bit = TRUE;
|
---|
| 1929 | }
|
---|
| 1930 | else
|
---|
| 1931 | f32bit = TRUE;
|
---|
| 1932 |
|
---|
| 1933 |
|
---|
| 1934 | // "EBP" column
|
---|
| 1935 | if (fExceptionAddress)
|
---|
| 1936 | fprintf(LogFile, " Trap -> ");
|
---|
| 1937 | else
|
---|
[13] | 1938 | fprintf(LogFile, " %8.8lX ", (ULONG)Ebp);
|
---|
[8] | 1939 |
|
---|
| 1940 | // "Address" column
|
---|
| 1941 | if (f32bit)
|
---|
[13] | 1942 | fprintf(LogFile, ":%8.8lX ", (ULONG)RetAddr);
|
---|
[8] | 1943 | else
|
---|
| 1944 | fprintf(LogFile, "%04.04X:%04.04X ", Cs, Ip);
|
---|
| 1945 |
|
---|
| 1946 | // Version check omitted; the following requires
|
---|
| 1947 | // OS/2 2.10 or later (*UM)
|
---|
| 1948 | // if (Version[0] >= 20 && Version[1] >= 10)
|
---|
| 1949 | {
|
---|
| 1950 | // Make a 'tick' sound to let the user know we're still alive
|
---|
| 1951 | DosBeep(2000, 10);
|
---|
| 1952 |
|
---|
| 1953 | Size = 10; // Inserted by Kim Rasmussen 26/06 1996 to avoid error 87 when Size is 0
|
---|
| 1954 |
|
---|
| 1955 | // "Module"/"Object" columns
|
---|
| 1956 | rc = DosQueryMem((PVOID) RetAddr, &Size, &Attr);
|
---|
| 1957 | if (rc != NO_ERROR || !(Attr & PAG_COMMIT))
|
---|
| 1958 | {
|
---|
[13] | 1959 | fprintf(LogFile, "Invalid RetAddr: %8.8lX\n", (ULONG)RetAddr);
|
---|
[8] | 1960 | break; // avoid infinite loops
|
---|
| 1961 | }
|
---|
| 1962 | else
|
---|
| 1963 | {
|
---|
| 1964 | rc = DOSQUERYMODFROMEIP(&hMod,
|
---|
| 1965 | &ObjNum,
|
---|
| 1966 | sizeof(Name), Name,
|
---|
| 1967 | &Offset,
|
---|
| 1968 | (PVOID)RetAddr);
|
---|
| 1969 | if ( (rc == NO_ERROR)
|
---|
| 1970 | // && (ObjNum != -1)
|
---|
| 1971 | )
|
---|
| 1972 | {
|
---|
| 1973 | DosQueryModuleName(hMod, sizeof(Name), Name);
|
---|
| 1974 | // print module and object
|
---|
[384] | 1975 | fprintf(LogFile, "%-8s %04lX ", Name, ObjNum + 1);
|
---|
[8] | 1976 |
|
---|
| 1977 | if (strlen(Name) > 3)
|
---|
| 1978 | {
|
---|
[430] | 1979 | // look for embedded debug info;
|
---|
| 1980 | // if that fails, look for a .sym file
|
---|
| 1981 | if (dbgPrintDebugInfo(LogFile,
|
---|
| 1982 | Name,
|
---|
| 1983 | ObjNum,
|
---|
| 1984 | Offset))
|
---|
| 1985 | dbgPrintStackFrame(LogFile,
|
---|
| 1986 | Name,
|
---|
| 1987 | ObjNum,
|
---|
| 1988 | Offset);
|
---|
[8] | 1989 | }
|
---|
| 1990 | }
|
---|
| 1991 | else
|
---|
| 1992 | fprintf(LogFile,
|
---|
[13] | 1993 | "DosQueryModFromEIP failed, returned %lu\n",
|
---|
[8] | 1994 | rc);
|
---|
| 1995 | }
|
---|
| 1996 | }
|
---|
| 1997 |
|
---|
| 1998 | if ( ((*Ebp) == 0)
|
---|
| 1999 | && ((*Ebp + 1) == 0)
|
---|
| 2000 | )
|
---|
| 2001 | {
|
---|
| 2002 | fprintf(LogFile, "End of call stack\n");
|
---|
| 2003 | break;
|
---|
| 2004 | }
|
---|
| 2005 |
|
---|
| 2006 | if (!fExceptionAddress)
|
---|
| 2007 | {
|
---|
| 2008 | LastEbp = Ebp;
|
---|
| 2009 | #if 0
|
---|
| 2010 | Ebp = (PUSHORT) MAKEULONG(Bp, Sp);
|
---|
| 2011 | #else // Inserted by Kim Rasmussen 26/06 1996 to allow big stacks
|
---|
| 2012 | if (f32bit)
|
---|
| 2013 | Ebp = (PUSHORT) *(PULONG) LastEbp;
|
---|
| 2014 | else
|
---|
| 2015 | Ebp = (PUSHORT) MAKEULONG((*Ebp), Sp);
|
---|
| 2016 | #endif
|
---|
| 2017 | if (f32bit)
|
---|
| 2018 | {
|
---|
| 2019 | dbgPrintVariables(LogFile, (ULONG) Ebp);
|
---|
| 2020 | } // endif
|
---|
| 2021 |
|
---|
| 2022 | if (Ebp < LastEbp)
|
---|
| 2023 | {
|
---|
| 2024 | fprintf(LogFile, "... lost stack chain - new EBP below previous\n");
|
---|
| 2025 | break;
|
---|
| 2026 | }
|
---|
| 2027 | }
|
---|
| 2028 | else
|
---|
| 2029 | fExceptionAddress = FALSE;
|
---|
| 2030 |
|
---|
| 2031 | Size = 4;
|
---|
| 2032 | rc = DosQueryMem((PVOID) Ebp, &Size, &Attr);
|
---|
| 2033 | if ((rc != NO_ERROR) || (Size < 4))
|
---|
| 2034 | {
|
---|
[13] | 2035 | fprintf(LogFile, "... lost stack chain - invalid EBP: %8.8lX\n", (ULONG)Ebp);
|
---|
[8] | 2036 | break;
|
---|
| 2037 | }
|
---|
| 2038 | } while (TRUE);
|
---|
| 2039 |
|
---|
| 2040 | fprintf(LogFile, "\n");
|
---|
| 2041 | }
|
---|
| 2042 |
|
---|