⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 win_dbg.c

📁 The source code of Doom legacy for windows
💻 C
📖 第 1 页 / 共 2 页
字号:
// 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 + -