📄 win_dbg.c
字号:
}
// --------------------------------------------------------------------------
// What we do here is trivial : open a file, write out the register information
// from the PEXCEPTION_POINTERS structure, then return EXCEPTION_CONTINUE_SEARCH
// whose magic value tells Win32 to proceed with its normal error handling
// mechanism. This is important : an error dialog will popup if possible and
// the debugger will hopefully coexist peacefully with the structured exception
// handler.
// --------------------------------------------------------------------------
int __cdecl RecordExceptionInfo (PEXCEPTION_POINTERS data, const char *Message, LPSTR lpCmdLine)
{
PEXCEPTION_RECORD Exception = data->ExceptionRecord;
PCONTEXT Context = data->ContextRecord;
char ModuleName[MAX_PATH];
char FileName[MAX_PATH] = "Unknown";
char* FilePart, *lastperiod;
char CrashModulePathName[MAX_PATH];
char* CrashModuleFileName = "Unknown";
MEMORY_BASIC_INFORMATION MemInfo;
static int BeenHere=false;
HANDLE fileHandle;
unsigned char * code;
int codebyte,i;
if (BeenHere) // Going recursive! That must mean this routine crashed!
return EXCEPTION_CONTINUE_SEARCH;
BeenHere = true;
// Create a filename to record the error information to.
// Store it in the executable directory.
if (GetModuleFileName(NULL, ModuleName, sizeof(ModuleName)) <= 0)
ModuleName[0] = 0;
FilePart = GetFilePart(ModuleName);
// Extract the file name portion and remove it's file extension. We'll
// use that name shortly.
lstrcpy (FileName, FilePart);
lastperiod = strrchr (FileName, '.');
if (lastperiod)
lastperiod[0] = 0;
// Replace the executable filename with our error log file name.
lstrcpy (FilePart, "errorlog.txt");
fileHandle = CreateFile (ModuleName, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL);
if (fileHandle == INVALID_HANDLE_VALUE)
{
OutputDebugString ("Error creating exception report");
return EXCEPTION_CONTINUE_SEARCH;
}
// Append to the error log.
SetFilePointer (fileHandle, 0, 0, FILE_END);
// Print out some blank lines to separate this error log from any previous ones.
FPrintf (fileHandle, "Email this file to Doom legacy support so we can fix the bugs\r\n");
FPrintf (fileHandle, "\r\n\r\n\r\n\r\n");
FPrintf (fileHandle, "Doom Legacy v%d.%d%s -ERROR LOG-\r\n\r\n", VERSION/100, VERSION%100, VERSIONSTRING);
FPrintf (fileHandle, "Command Line parameters: ");
for (i = 1;i<myargc;i++)
FPrintf (fileHandle, "%s ", myargv[i] );
FPrintf (fileHandle, "\r\n");
// VirtualQuery can be used to get the allocation base associated with a
// code address, which is the same as the ModuleHandle. This can be used
// to get the filename of the module that the crash happened in.
if ( VirtualQuery ((void*)Context->Eip, &MemInfo, sizeof(MemInfo)) &&
GetModuleFileName ((HINSTANCE)MemInfo.AllocationBase,
CrashModulePathName,
sizeof(CrashModulePathName)) > 0)
CrashModuleFileName = GetFilePart(CrashModulePathName);
// Print out the beginning of the error log in a Win95 error window
// compatible format.
FPrintf (fileHandle, "%s caused an %s in module %s at %04x:%08x.\r\n",
FileName, GetExceptionDescription(Exception->ExceptionCode),
CrashModuleFileName, Context->SegCs, Context->Eip);
FPrintf (fileHandle, "Exception handler called in %s.\r\n", Message);
RecordSystemInformation (fileHandle);
// If the exception was an access violation, print out some additional
// information, to the error log and the debugger.
if (Exception->ExceptionCode == STATUS_ACCESS_VIOLATION &&
Exception->NumberParameters >= 2)
{
char DebugMessage[1000];
const char* readwrite = "Read from";
if (Exception->ExceptionInformation[0])
readwrite = "Write to";
wsprintf(DebugMessage, "%s location %08x caused an access violation.\r\n",
readwrite, Exception->ExceptionInformation[1]);
#ifdef _DEBUG
// The VisualC++ debugger doesn't actually tell you whether a read
// or a write caused the access violation, nor does it tell what
// address was being read or written. So I fixed that.
OutputDebugString("Exception handler: ");
OutputDebugString(DebugMessage);
#endif
FPrintf(fileHandle, "%s", DebugMessage);
}
FPrintf(fileHandle, "\r\n");
// Print out the register values in a Win95 error window compatible format.
if ((Context->ContextFlags & CONTEXT_FULL) == CONTEXT_FULL)
{
FPrintf (fileHandle, "Registers:\r\n");
FPrintf (fileHandle, "EAX=%.8lx CS=%.4x EIP=%.8lx EFLGS=%.8lx\r\n",
Context->Eax,Context->SegCs,Context->Eip,Context->EFlags);
FPrintf (fileHandle, "EBX=%.8lx SS=%.4x ESP=%.8lx EBP=%.8lx\r\n",
Context->Ebx,Context->SegSs,Context->Esp,Context->Ebp);
FPrintf (fileHandle, "ECX=%.8lx DS=%.4x ESI=%.8lx FS=%.4x\r\n",
Context->Ecx,Context->SegDs,Context->Esi,Context->SegFs);
FPrintf (fileHandle, "EDX=%.8lx ES=%.4x EDI=%.8lx GS=%.4x\r\n",
Context->Edx,Context->SegEs,Context->Edi,Context->SegGs);
}
FPrintf (fileHandle, "Bytes at CS:EIP:\r\n");
// Print out the bytes of code at the instruction pointer. Since the
// crash may have been caused by an instruction pointer that was bad,
// this code needs to be wrapped in an exception handler, in case there
// is no memory to read. If the dereferencing of code[] fails, the
// exception handler will print '??'.
code = (unsigned char*)Context->Eip;
for (codebyte = 0; codebyte < NumCodeBytes; codebyte++)
{
__try
{
FPrintf (fileHandle, "%02x ", code[codebyte]);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
FPrintf (fileHandle, "?? ");
}
}
// Time to print part or all of the stack to the error log. This allows
// us to figure out the call stack, parameters, local variables, etc.
FPrintf (fileHandle, "\r\n"
"Stack dump:\r\n");
__try
{
// Esp contains the bottom of the stack, or at least the bottom of
// the currently used area.
DWORD* pStack = (DWORD *)Context->Esp;
DWORD* pStackTop;
int Count = 0;
char buffer[1000] = "";
const int safetyzone = 50;
char* nearend = buffer + sizeof(buffer) - safetyzone;
char* output = buffer;
char *Suffix;
__asm
{
// Load the top (highest address) of the stack from the
// thread information block. It will be found there in
// Win9x and Windows NT.
mov eax, fs:[4]
mov pStackTop, eax
}
if (pStackTop > pStack + MaxStackDump)
pStackTop = pStack + MaxStackDump;
// Too many calls to WriteFile can take a long time, causing
// confusing delays when programs crash. Therefore I implemented
// simple buffering for the stack dumping code instead of calling
// FPrintf directly.
while (pStack + 1 <= pStackTop)
{
if ((Count % StackColumns) == 0)
output += wsprintf(output, "%08x: ", pStack);
if ((++Count % StackColumns) == 0 || pStack + 2 > pStackTop)
Suffix = "\r\n";
else
Suffix = " ";
output += wsprintf(output, "%08x%s", *pStack, Suffix);
pStack++;
// Check for when the buffer is almost full, and flush it to disk.
if (output > nearend)
{
FPrintf (fileHandle, "%s", buffer);
buffer[0] = 0;
output = buffer;
}
}
// Print out any final characters from the cache.
FPrintf (fileHandle, "%s", buffer);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
FPrintf(fileHandle, "Exception encountered during stack dump.\r\n");
}
RecordModuleList (fileHandle);
CloseHandle (fileHandle);
// Return the magic value which tells Win32 that this handler didn't
// actually handle the exception - so that things will proceed as per
// normal.
//BP: should put message for end user to send this file to fix any bug
return EXCEPTION_CONTINUE_SEARCH;
}
/*
//
//FPrintf ("e-mail this file to legacy@newdoom.com , so that we can fix the problem.\r\n\r\n");
FPrintf ("Exception handler called in %s.\r\n", Message);
GetSystemTime (&systemTime);
FPrintf ("Error occured at %02d/%02d/%04d %02d:%02d:%02d.\r\n",
systemTime.wMonth, systemTime.wDay, systemTime.wYear,
systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
FPrintf ("%s\r\n", filename);
FPrintf ("Cmd-line: %s\r\n", lpCmdLine);
// Nested exceptions can occur, get info for each one
nER = 1;
while (ER)
{
if (nER++>1)
FPrintf ("Exception Record %d.\r\n", nER);
FPrintf ("application caused an %s", GetExceptionCodeStr(Exception->ExceptionCode));
if (Context->ContextFlags & CONTEXT_CONTROL)
FPrintf (" at %.4x:%.8x.\r\n", Context->SegCs, Context->Eip);
// in case of..
if (Context->Eip != (unsigned long)Exception->ExceptionAddress)
FPrintf ("Exception Address = %.8x\r\n", Exception->ExceptionAddress);
if (Exception->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
{
FPrintf ("\r\n%s location 0x%x caused an access violation.\r\n",
(Exception->ExceptionInformation[0] ? "Write to" : "Read from"),
Exception->ExceptionInformation[1]);
}
ER = Exception->ExceptionRecord;
}
if (Context->ContextFlags & CONTEXT_DEBUG_REGISTERS)
{
FPrintf ("\r\nDebug Registers:\r\n");
FPrintf ("Dr0=%.8x Dr1=%.8x Dr2=%.8x\r\n"
"Dr3=%.8x Dr6=%.8x Dr7=%.8x\r\n",
Context->Dr0, Context->Dr1, Context->Dr2,
Context->Dr3, Context->Dr6, Context->Dr7);
}
if (Context->ContextFlags & CONTEXT_FLOATING_POINT)
{
FPrintf ("\r\nFloating Save Area:\r\n");
FPrintf ("ControlWord =%.8x TagWord =%.8x ErrorSelector=%.8x DataSelector =%.8x\r\n"
"StatusWord =%.8x ErrorOffset =%.8x DataOffset =%.8x Cr0NpxState =%.8x\r\n",
Context->FloatSave.ControlWord, Context->FloatSave.TagWord, Context->FloatSave.ErrorSelector, Context->FloatSave.DataSelector,
Context->FloatSave.StatusWord, Context->FloatSave.ErrorOffset, Context->FloatSave.DataOffset, Context->FloatSave.Cr0NpxState
);
//BYTE RegisterArea[SIZE_OF_80387_REGISTERS];
}
// in case of...
if ((Context->ContextFlags & CONTEXT_FULL) != CONTEXT_FULL)
{
if (!(Context->ContextFlags & CONTEXT_SEGMENTS))
FPrintf ("Note! GS,FS,ES,DS are unspecified\r\n");
if (!(Context->ContextFlags & CONTEXT_INTEGER))
FPrintf ("Note! EDI,ESI,EBX,EDX,ECX,EAX are unspecified\r\n");
if (!(Context->ContextFlags & CONTEXT_CONTROL))
FPrintf ("Note! EBP,CS:EIP,EFlags,SS:ESP are unspecified\r\n");
}
if (hwdInstance!=NULL)
{
FPrintf ("\r\nHWDDriver loaded at %.8x\r\n", hwdInstance);
FPrintf ("DLL function pointers:\r\n");
for (loadfunc = hwdFuncTable, i=0; loadfunc->fnName!=NULL; loadfunc++,i++)
{
FPrintf ("hwdFuncTable[%d]: %s loaded at %.8x\r\n", i, loadfunc->fnName,
(unsigned long) *((void**)loadfunc->fnPointer) );
}
}
FPrintf ("\r\nBytes at CS:EIP:\r\n");
ucptr = (unsigned char*)Context->Eip;
for (i=0; i<16; i++)
FPrintf ("%.2x ", *ucptr++);
FPrintf ("\r\n\r\nStack dump:\r\n");
ulptr = (unsigned long*)Context->Esp;
for (i=0; i<16; i++)
FPrintf ("%.8x ", *ulptr++);
//FPrintf ("Bytes at CS:EIP:\r\n");
//FPrintf ("%.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x ");
for (i=0; i<16; i++)
{
FPrintf ("%x
}
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -