📄 win_dbg.c
字号:
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id: win_dbg.c,v 1.8 2001/01/25 22:15:45 bpereira Exp $
//
// Copyright (C) 1998-2000 by DooM Legacy Team.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// $Log: win_dbg.c,v $
// Revision 1.8 2001/01/25 22:15:45 bpereira
// added heretic support
//
// Revision 1.7 2000/09/28 20:57:22 bpereira
// no message
//
// Revision 1.6 2000/09/01 19:34:38 bpereira
// no message
//
// Revision 1.5 2000/08/03 17:57:42 bpereira
// no message
//
// Revision 1.4 2000/04/24 20:24:39 bpereira
// no message
//
// Revision 1.3 2000/04/16 18:38:07 bpereira
// no message
//
// Revision 1.2 2000/02/27 00:42:12 hurdler
// fix CR+LF problem
//
// Revision 1.1.1.1 2000/02/22 20:32:33 hurdler
// Initial import into CVS (v1.29 pr3)
//
//
// DESCRIPTION:
// this source file contains the exception handler for recording error
// information after crashes.
// Sources from GameDeveloper magazine article, January 1998, by Bruce Dawson.
//
//-----------------------------------------------------------------------------
#include "../doomdef.h" //just for VERSION ..
#include "win_dbg.h"
#include "win_main.h"
#include "../m_argv.h" //print the parameter in the log
#define NumCodeBytes 16 // Number of code bytes to record.
#define MaxStackDump 2048 // Maximum number of DWORDS in stack dumps.
#define StackColumns 8 // Number of columns in stack dump.
#define ONEK 1024
#define SIXTYFOURK (64*ONEK)
#define ONEM (ONEK*ONEK)
#define ONEG (ONEK*ONEK*ONEK)
// --------------------------------------------------------------------------
// return a description for an ExceptionCode
// --------------------------------------------------------------------------
static char* GetExceptionDescription (DWORD ExceptionCode)
{
int i;
struct ExceptionNames
{
DWORD ExceptionCode;
char* ExceptionName;
};
struct ExceptionNames ExceptionMap[] =
{
{EXCEPTION_ACCESS_VIOLATION, "an Access Violation"},
{EXCEPTION_ARRAY_BOUNDS_EXCEEDED, "a Array Bounds Exceeded"},
{EXCEPTION_BREAKPOINT, "a Breakpoint"},
{EXCEPTION_DATATYPE_MISALIGNMENT, "a Datatype Misalignment"},
{EXCEPTION_FLT_DENORMAL_OPERAND, "a Float Denormal Operand"},
{EXCEPTION_FLT_DIVIDE_BY_ZERO, "a Float Divide By Zero"},
{EXCEPTION_FLT_INEXACT_RESULT, "a Float Inexact Result"},
{EXCEPTION_FLT_INVALID_OPERATION, "a Float Invalid Operation"},
{EXCEPTION_FLT_OVERFLOW, "a Float Overflow"},
{EXCEPTION_FLT_STACK_CHECK, "a Float Stack Check"},
{EXCEPTION_FLT_UNDERFLOW, "a Float Underflow"},
{EXCEPTION_ILLEGAL_INSTRUCTION, "an Illegal Instruction"},
{EXCEPTION_IN_PAGE_ERROR, "an In Page Error"},
{EXCEPTION_INT_DIVIDE_BY_ZERO, "an Integer Divide By Zero"},
{EXCEPTION_INT_OVERFLOW, "an Integer Overflow"},
{EXCEPTION_INVALID_DISPOSITION, "an Invalid Disposition"},
{EXCEPTION_NONCONTINUABLE_EXCEPTION, "Noncontinuable Exception"},
{EXCEPTION_PRIV_INSTRUCTION, "a Privileged Instruction"},
{EXCEPTION_SINGLE_STEP, "a Single Step"},
{EXCEPTION_STACK_OVERFLOW, "a Stack Overflow"},
{0x40010005, "a Control-C"},
{0x40010008, "a Control-Break"},
{0xc0000006, "an In Page Error"},
{0xc0000017, "a No Memory"},
{0xc000001d, "an Illegal Instruction"},
{0xc0000025, "a Noncontinuable Exception"},
{0xc0000142, "a DLL Initialization Failed"},
{0xe06d7363, "a Microsoft C++ Exception"},
};
for (i = 0; i < sizeof(ExceptionMap) / sizeof(ExceptionMap[0]); i++)
if (ExceptionCode == ExceptionMap[i].ExceptionCode)
return ExceptionMap[i].ExceptionName;
return "Unknown exception type";
}
// --------------------------------------------------------------------------
// Directly output a formatted string to the errorlog file, using win32 funcs
// --------------------------------------------------------------------------
void FPrintf (HANDLE fileHandle, LPCTSTR lpFmt, ...)
{
char str[1999];
va_list arglist;
DWORD bytesWritten;
va_start (arglist, lpFmt);
vsprintf (str, lpFmt, arglist);
va_end (arglist);
WriteFile (fileHandle, str, strlen(str), &bytesWritten, NULL);
}
// --------------------------------------------------------------------------
// Print the specified FILETIME to output in a human readable format,
// without using the C run time.
// --------------------------------------------------------------------------
static void PrintTime (char *output, FILETIME TimeToPrint)
{
WORD Date, Time;
if (FileTimeToLocalFileTime (&TimeToPrint, &TimeToPrint) &&
FileTimeToDosDateTime (&TimeToPrint, &Date, &Time))
{
// What a silly way to print out the file date/time.
wsprintf( output, "%d/%d/%d %02d:%02d:%02d",
(Date / 32) & 15, Date & 31, (Date / 512) + 1980,
(Time / 2048), (Time / 32) & 63, (Time & 31) * 2);
}
else
output[0] = 0;
}
static char* GetFilePart(char *source)
{
char *result = strrchr(source, '\\');
if (result)
result++;
else
result = source;
return result;
}
// --------------------------------------------------------------------------
// Print information about a code module (DLL or EXE) such as its size,
// location, time stamp, etc.
// --------------------------------------------------------------------------
static void ShowModuleInfo(HANDLE LogFile, HINSTANCE ModuleHandle)
{
char ModName[MAX_PATH];
IMAGE_DOS_HEADER *DosHeader;
IMAGE_NT_HEADERS *NTHeader;
HANDLE ModuleFile;
char TimeBuffer[100] = "";
DWORD FileSize = 0;
__try
{
if (GetModuleFileName(ModuleHandle, ModName, sizeof(ModName)) > 0)
{
// If GetModuleFileName returns greater than zero then this must
// be a valid code module address. Therefore we can try to walk
// our way through its structures to find the link time stamp.
DosHeader = (IMAGE_DOS_HEADER*)ModuleHandle;
if (IMAGE_DOS_SIGNATURE != DosHeader->e_magic)
return;
NTHeader = (IMAGE_NT_HEADERS*)((char *)DosHeader
+ DosHeader->e_lfanew);
if (IMAGE_NT_SIGNATURE != NTHeader->Signature)
return;
// Open the code module file so that we can get its file date
// and size.
ModuleFile = CreateFile(ModName, GENERIC_READ,
FILE_SHARE_READ, 0, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, 0);
if (ModuleFile != INVALID_HANDLE_VALUE)
{
FILETIME LastWriteTime;
FileSize = GetFileSize(ModuleFile, 0);
if (GetFileTime(ModuleFile, 0, 0, &LastWriteTime))
{
wsprintf(TimeBuffer, " - file date is ");
PrintTime(TimeBuffer + lstrlen(TimeBuffer), LastWriteTime);
}
CloseHandle(ModuleFile);
}
FPrintf (LogFile, "%s, loaded at 0x%08x - %d bytes - %08x%s\r\n",
ModName, ModuleHandle, FileSize,
NTHeader->FileHeader.TimeDateStamp, TimeBuffer);
}
}
// Handle any exceptions by continuing from this point.
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
}
// --------------------------------------------------------------------------
// Scan memory looking for code modules (DLLs or EXEs). VirtualQuery is used
// to find all the blocks of address space that were reserved or committed,
// and ShowModuleInfo will display module information if they are code
// modules.
// --------------------------------------------------------------------------
static void RecordModuleList(HANDLE LogFile)
{
SYSTEM_INFO SystemInfo;
size_t PageSize;
size_t NumPages;
size_t pageNum = 0;
void *LastAllocationBase = 0;
FPrintf (LogFile, "\r\n"
"\tModule list: names, addresses, sizes, time stamps "
"and file times:\r\n");
// Set NumPages to the number of pages in the 4GByte address space,
// while being careful to avoid overflowing ints.
GetSystemInfo(&SystemInfo);
PageSize = SystemInfo.dwPageSize;
NumPages = 4 * (unsigned int)(ONEG / PageSize);
while (pageNum < NumPages)
{
MEMORY_BASIC_INFORMATION MemInfo;
if (VirtualQuery((void *)(pageNum * PageSize), &MemInfo,
sizeof(MemInfo)))
{
if (MemInfo.RegionSize > 0)
{
// Adjust the page number to skip over this block of memory.
pageNum += MemInfo.RegionSize / PageSize;
if (MemInfo.State == MEM_COMMIT && MemInfo.AllocationBase >
LastAllocationBase)
{
// Look for new blocks of committed memory, and try
// recording their module names - this will fail
// gracefully if they aren't code modules.
LastAllocationBase = MemInfo.AllocationBase;
ShowModuleInfo(LogFile, (HINSTANCE)LastAllocationBase);
}
}
else
pageNum += SIXTYFOURK / PageSize;
}
else
pageNum += SIXTYFOURK / PageSize;
// If VirtualQuery fails we advance by 64K because that is the
// granularity of address space doled out by VirtualAlloc().
}
}
// --------------------------------------------------------------------------
// Record information about the user's system, such as processor type, amount
// of memory, etc.
// --------------------------------------------------------------------------
static void RecordSystemInformation(HANDLE fileHandle)
{
FILETIME CurrentTime;
char TimeBuffer[100];
char ModuleName[MAX_PATH];
char UserName[200];
DWORD UserNameSize;
SYSTEM_INFO SystemInfo;
MEMORYSTATUS MemInfo;
GetSystemTimeAsFileTime (&CurrentTime);
PrintTime (TimeBuffer, CurrentTime);
FPrintf(fileHandle, "Error occurred at %s.\r\n", TimeBuffer);
if (GetModuleFileName (NULL, ModuleName, sizeof(ModuleName)) <= 0)
lstrcpy (ModuleName, "Unknown");
UserNameSize = sizeof(UserName);
if (!GetUserName (UserName, &UserNameSize))
lstrcpy (UserName, "Unknown");
FPrintf(fileHandle, "%s, run by %s.\r\n", ModuleName, UserName);
GetSystemInfo (&SystemInfo);
FPrintf (fileHandle, "%d processor(s), type %d %d.%d.\r\n"
"Program Memory from 0x%p to 0x%p\r\n",
SystemInfo.dwNumberOfProcessors,
SystemInfo.dwProcessorType,
SystemInfo.wProcessorLevel,
SystemInfo.wProcessorRevision,
SystemInfo.lpMinimumApplicationAddress,
SystemInfo.lpMaximumApplicationAddress);
MemInfo.dwLength = sizeof(MemInfo);
GlobalMemoryStatus(&MemInfo);
// Print out the amount of physical memory, rounded up.
FPrintf(fileHandle, "%d MBytes physical memory.\r\n", (MemInfo.dwTotalPhys +
ONEM - 1) / ONEM);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -