326d1845a5ad33574cb834270779589136854527vboxsync/* $Id$ */
326d1845a5ad33574cb834270779589136854527vboxsync/** @file
326d1845a5ad33574cb834270779589136854527vboxsync * IPRT - RTNtDbgHelp - Tool for working/exploring DbgHelp.dll.
326d1845a5ad33574cb834270779589136854527vboxsync */
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync/*
326d1845a5ad33574cb834270779589136854527vboxsync * Copyright (C) 2013 Oracle Corporation
326d1845a5ad33574cb834270779589136854527vboxsync *
326d1845a5ad33574cb834270779589136854527vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
326d1845a5ad33574cb834270779589136854527vboxsync * available from http://www.virtualbox.org. This file is free software;
326d1845a5ad33574cb834270779589136854527vboxsync * you can redistribute it and/or modify it under the terms of the GNU
326d1845a5ad33574cb834270779589136854527vboxsync * General Public License (GPL) as published by the Free Software
326d1845a5ad33574cb834270779589136854527vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
326d1845a5ad33574cb834270779589136854527vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
326d1845a5ad33574cb834270779589136854527vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
326d1845a5ad33574cb834270779589136854527vboxsync *
326d1845a5ad33574cb834270779589136854527vboxsync * The contents of this file may alternatively be used under the terms
326d1845a5ad33574cb834270779589136854527vboxsync * of the Common Development and Distribution License Version 1.0
326d1845a5ad33574cb834270779589136854527vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
326d1845a5ad33574cb834270779589136854527vboxsync * VirtualBox OSE distribution, in which case the provisions of the
326d1845a5ad33574cb834270779589136854527vboxsync * CDDL are applicable instead of those of the GPL.
326d1845a5ad33574cb834270779589136854527vboxsync *
326d1845a5ad33574cb834270779589136854527vboxsync * You may elect to license modified versions of this file under the
326d1845a5ad33574cb834270779589136854527vboxsync * terms and conditions of either the GPL or the CDDL or both.
326d1845a5ad33574cb834270779589136854527vboxsync */
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync/*******************************************************************************
326d1845a5ad33574cb834270779589136854527vboxsync* Header Files *
326d1845a5ad33574cb834270779589136854527vboxsync*******************************************************************************/
326d1845a5ad33574cb834270779589136854527vboxsync#include <Windows.h>
326d1845a5ad33574cb834270779589136854527vboxsync#include <Dbghelp.h>
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync#include <iprt/alloca.h>
326d1845a5ad33574cb834270779589136854527vboxsync#include <iprt/dir.h>
326d1845a5ad33574cb834270779589136854527vboxsync#include <iprt/file.h>
326d1845a5ad33574cb834270779589136854527vboxsync#include <iprt/getopt.h>
326d1845a5ad33574cb834270779589136854527vboxsync#include <iprt/env.h>
326d1845a5ad33574cb834270779589136854527vboxsync#include <iprt/initterm.h>
326d1845a5ad33574cb834270779589136854527vboxsync#include <iprt/list.h>
326d1845a5ad33574cb834270779589136854527vboxsync#include <iprt/mem.h>
326d1845a5ad33574cb834270779589136854527vboxsync#include <iprt/message.h>
326d1845a5ad33574cb834270779589136854527vboxsync#include <iprt/path.h>
326d1845a5ad33574cb834270779589136854527vboxsync#include <iprt/stream.h>
326d1845a5ad33574cb834270779589136854527vboxsync#include <iprt/string.h>
326d1845a5ad33574cb834270779589136854527vboxsync#include <iprt/err.h>
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync#include <iprt/win/lazy-dbghelp.h>
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync#include <iprt/ldrlazy.h>
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync/*******************************************************************************
326d1845a5ad33574cb834270779589136854527vboxsync* Structures and Typedefs *
326d1845a5ad33574cb834270779589136854527vboxsync*******************************************************************************/
326d1845a5ad33574cb834270779589136854527vboxsync/**
326d1845a5ad33574cb834270779589136854527vboxsync * Debug module record.
326d1845a5ad33574cb834270779589136854527vboxsync *
326d1845a5ad33574cb834270779589136854527vboxsync * Used for dumping the whole context.
326d1845a5ad33574cb834270779589136854527vboxsync */
326d1845a5ad33574cb834270779589136854527vboxsynctypedef struct RTNTDBGHELPMOD
326d1845a5ad33574cb834270779589136854527vboxsync{
326d1845a5ad33574cb834270779589136854527vboxsync /** The list bits. */
326d1845a5ad33574cb834270779589136854527vboxsync RTLISTNODE ListEntry;
326d1845a5ad33574cb834270779589136854527vboxsync /** The module address. */
326d1845a5ad33574cb834270779589136854527vboxsync uint64_t uModAddr;
326d1845a5ad33574cb834270779589136854527vboxsync /** Pointer to the name part of szFullName. */
326d1845a5ad33574cb834270779589136854527vboxsync char *pszName;
326d1845a5ad33574cb834270779589136854527vboxsync /** The module name. */
326d1845a5ad33574cb834270779589136854527vboxsync char szFullName[1];
326d1845a5ad33574cb834270779589136854527vboxsync} RTNTDBGHELPMOD;
326d1845a5ad33574cb834270779589136854527vboxsync/** Pointer to a debug module. */
326d1845a5ad33574cb834270779589136854527vboxsynctypedef RTNTDBGHELPMOD *PRTNTDBGHELPMOD;
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync/*******************************************************************************
326d1845a5ad33574cb834270779589136854527vboxsync* Global Variables *
326d1845a5ad33574cb834270779589136854527vboxsync*******************************************************************************/
326d1845a5ad33574cb834270779589136854527vboxsync/** Verbosity level. */
326d1845a5ad33574cb834270779589136854527vboxsyncstatic int g_iOptVerbose = 1;
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync/** Fake process handle. */
326d1845a5ad33574cb834270779589136854527vboxsyncstatic HANDLE g_hFake = (HANDLE)0x1234567;
326d1845a5ad33574cb834270779589136854527vboxsync/** Number of modules in the list. */
326d1845a5ad33574cb834270779589136854527vboxsyncstatic uint32_t g_cModules = 0;
326d1845a5ad33574cb834270779589136854527vboxsync/** Module list. */
326d1845a5ad33574cb834270779589136854527vboxsyncstatic RTLISTANCHOR g_ModuleList;
326d1845a5ad33574cb834270779589136854527vboxsync/** Set when initialized, clear until then. Lazy init on first operation. */
326d1845a5ad33574cb834270779589136854527vboxsyncstatic bool g_fInitialized = false;
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync/** The current address register. */
326d1845a5ad33574cb834270779589136854527vboxsyncstatic uint64_t g_uCurAddress = 0;
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync/**
326d1845a5ad33574cb834270779589136854527vboxsync * For debug/verbose output.
326d1845a5ad33574cb834270779589136854527vboxsync *
326d1845a5ad33574cb834270779589136854527vboxsync * @param iMin The minimum verbosity level for this message.
326d1845a5ad33574cb834270779589136854527vboxsync * @param pszFormat The format string.
326d1845a5ad33574cb834270779589136854527vboxsync * @param ... The arguments referenced in the format string.
326d1845a5ad33574cb834270779589136854527vboxsync */
326d1845a5ad33574cb834270779589136854527vboxsyncstatic void infoPrintf(int iMin, const char *pszFormat, ...)
326d1845a5ad33574cb834270779589136854527vboxsync{
326d1845a5ad33574cb834270779589136854527vboxsync if (g_iOptVerbose >= iMin)
326d1845a5ad33574cb834270779589136854527vboxsync {
326d1845a5ad33574cb834270779589136854527vboxsync va_list va;
326d1845a5ad33574cb834270779589136854527vboxsync va_start(va, pszFormat);
326d1845a5ad33574cb834270779589136854527vboxsync RTPrintf("info: ");
326d1845a5ad33574cb834270779589136854527vboxsync RTPrintfV(pszFormat, va);
326d1845a5ad33574cb834270779589136854527vboxsync va_end(va);
326d1845a5ad33574cb834270779589136854527vboxsync }
326d1845a5ad33574cb834270779589136854527vboxsync}
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsyncstatic BOOL CALLBACK symDebugCallback64(HANDLE hProcess, ULONG uAction, ULONG64 ullData, ULONG64 ullUserCtx)
326d1845a5ad33574cb834270779589136854527vboxsync{
326d1845a5ad33574cb834270779589136854527vboxsync NOREF(hProcess); NOREF(ullUserCtx);
326d1845a5ad33574cb834270779589136854527vboxsync switch (uAction)
326d1845a5ad33574cb834270779589136854527vboxsync {
326d1845a5ad33574cb834270779589136854527vboxsync case CBA_DEBUG_INFO:
326d1845a5ad33574cb834270779589136854527vboxsync {
326d1845a5ad33574cb834270779589136854527vboxsync const char *pszMsg = (const char *)(uintptr_t)ullData;
326d1845a5ad33574cb834270779589136854527vboxsync size_t cchMsg = strlen(pszMsg);
326d1845a5ad33574cb834270779589136854527vboxsync if (cchMsg > 0 && pszMsg[cchMsg - 1] == '\n')
326d1845a5ad33574cb834270779589136854527vboxsync RTPrintf("cba_debug_info: %s", pszMsg);
326d1845a5ad33574cb834270779589136854527vboxsync else
326d1845a5ad33574cb834270779589136854527vboxsync RTPrintf("cba_debug_info: %s\n", pszMsg);
326d1845a5ad33574cb834270779589136854527vboxsync return TRUE;
326d1845a5ad33574cb834270779589136854527vboxsync }
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync case CBA_DEFERRED_SYMBOL_LOAD_CANCEL:
326d1845a5ad33574cb834270779589136854527vboxsync return FALSE;
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync case CBA_EVENT:
326d1845a5ad33574cb834270779589136854527vboxsync return FALSE;
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync default:
326d1845a5ad33574cb834270779589136854527vboxsync RTPrintf("cba_???: uAction=%#x ullData=%#llx\n", uAction, ullData);
326d1845a5ad33574cb834270779589136854527vboxsync break;
326d1845a5ad33574cb834270779589136854527vboxsync }
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync return FALSE;
326d1845a5ad33574cb834270779589136854527vboxsync}
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync/**
326d1845a5ad33574cb834270779589136854527vboxsync * Lazy initialization.
326d1845a5ad33574cb834270779589136854527vboxsync * @returns Exit code with any relevant complaints printed.
326d1845a5ad33574cb834270779589136854527vboxsync */
326d1845a5ad33574cb834270779589136854527vboxsyncstatic RTEXITCODE ensureInitialized(void)
326d1845a5ad33574cb834270779589136854527vboxsync{
326d1845a5ad33574cb834270779589136854527vboxsync if (!g_fInitialized)
326d1845a5ad33574cb834270779589136854527vboxsync {
326d1845a5ad33574cb834270779589136854527vboxsync if (!SymInitialize(g_hFake, NULL, FALSE))
326d1845a5ad33574cb834270779589136854527vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "SymInitialied failed: %u\n", GetLastError());
326d1845a5ad33574cb834270779589136854527vboxsync if (!SymRegisterCallback64(g_hFake, symDebugCallback64, 0))
326d1845a5ad33574cb834270779589136854527vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "SymRegisterCallback64 failed: %u\n", GetLastError());
326d1845a5ad33574cb834270779589136854527vboxsync g_fInitialized = true;
326d1845a5ad33574cb834270779589136854527vboxsync infoPrintf(2, "SymInitialized(,,)\n");
326d1845a5ad33574cb834270779589136854527vboxsync }
326d1845a5ad33574cb834270779589136854527vboxsync return RTEXITCODE_SUCCESS;
326d1845a5ad33574cb834270779589136854527vboxsync}
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync/**
326d1845a5ad33574cb834270779589136854527vboxsync * Loads the given module, the address is either automatic or a previously given
326d1845a5ad33574cb834270779589136854527vboxsync * one.
326d1845a5ad33574cb834270779589136854527vboxsync *
326d1845a5ad33574cb834270779589136854527vboxsync * @returns Exit code with any relevant complaints printed.
326d1845a5ad33574cb834270779589136854527vboxsync * @param pszFile The file to load.
326d1845a5ad33574cb834270779589136854527vboxsync */
326d1845a5ad33574cb834270779589136854527vboxsyncstatic RTEXITCODE loadModule(const char *pszFile)
326d1845a5ad33574cb834270779589136854527vboxsync{
326d1845a5ad33574cb834270779589136854527vboxsync RTEXITCODE rcExit = ensureInitialized();
326d1845a5ad33574cb834270779589136854527vboxsync if (rcExit != RTEXITCODE_SUCCESS)
326d1845a5ad33574cb834270779589136854527vboxsync return rcExit;
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync uint64_t uModAddrReq = g_uCurAddress == 0 ? UINT64_C(0x1000000) * g_cModules : g_uCurAddress;
326d1845a5ad33574cb834270779589136854527vboxsync uint64_t uModAddrGot = SymLoadModuleEx(g_hFake, NULL /*hFile*/, pszFile, NULL /*pszModuleName*/,
326d1845a5ad33574cb834270779589136854527vboxsync uModAddrReq, 0, NULL /*pData*/, 0 /*fFlags*/);
326d1845a5ad33574cb834270779589136854527vboxsync if (uModAddrGot == 0)
326d1845a5ad33574cb834270779589136854527vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "SymLoadModuleEx failed: %u\n", GetLastError());
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync size_t cbFullName = strlen(pszFile) + 1;
326d1845a5ad33574cb834270779589136854527vboxsync PRTNTDBGHELPMOD pMod = (PRTNTDBGHELPMOD)RTMemAlloc(RT_OFFSETOF(RTNTDBGHELPMOD, szFullName[cbFullName + 1]));
326d1845a5ad33574cb834270779589136854527vboxsync memcpy(pMod->szFullName, pszFile, cbFullName);
326d1845a5ad33574cb834270779589136854527vboxsync pMod->pszName = RTPathFilename(pMod->szFullName);
326d1845a5ad33574cb834270779589136854527vboxsync pMod->uModAddr = uModAddrGot;
326d1845a5ad33574cb834270779589136854527vboxsync RTListAppend(&g_ModuleList, &pMod->ListEntry);
e4fd4a5aeda0e74e8b509db8147d0dd3482054f4vboxsync infoPrintf(1, "%#018RX64 %s\n", pMod->uModAddr, pMod->pszName);
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync return RTEXITCODE_SUCCESS;
326d1845a5ad33574cb834270779589136854527vboxsync}
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync/**
326d1845a5ad33574cb834270779589136854527vboxsync * Translates SYM_TYPE to string.
326d1845a5ad33574cb834270779589136854527vboxsync *
326d1845a5ad33574cb834270779589136854527vboxsync * @returns String.
326d1845a5ad33574cb834270779589136854527vboxsync * @param enmType The symbol type value.
326d1845a5ad33574cb834270779589136854527vboxsync */
326d1845a5ad33574cb834270779589136854527vboxsyncstatic const char *symTypeName(SYM_TYPE enmType)
326d1845a5ad33574cb834270779589136854527vboxsync{
326d1845a5ad33574cb834270779589136854527vboxsync switch (enmType)
326d1845a5ad33574cb834270779589136854527vboxsync {
326d1845a5ad33574cb834270779589136854527vboxsync case SymCoff: return "SymCoff";
326d1845a5ad33574cb834270779589136854527vboxsync case SymCv: return "SymCv";
326d1845a5ad33574cb834270779589136854527vboxsync case SymPdb: return "SymPdb";
326d1845a5ad33574cb834270779589136854527vboxsync case SymExport: return "SymExport";
326d1845a5ad33574cb834270779589136854527vboxsync case SymDeferred: return "SymDeferred";
326d1845a5ad33574cb834270779589136854527vboxsync case SymSym: return "SymSym";
326d1845a5ad33574cb834270779589136854527vboxsync case SymDia: return "SymDia";
326d1845a5ad33574cb834270779589136854527vboxsync case SymVirtual: return "SymVirtual";
326d1845a5ad33574cb834270779589136854527vboxsync }
326d1845a5ad33574cb834270779589136854527vboxsync static char s_szBuf[32];
326d1845a5ad33574cb834270779589136854527vboxsync RTStrPrintf(s_szBuf, sizeof(s_szBuf), "Unknown-%#x", enmType);
326d1845a5ad33574cb834270779589136854527vboxsync return s_szBuf;
326d1845a5ad33574cb834270779589136854527vboxsync}
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync/**
326d1845a5ad33574cb834270779589136854527vboxsync * Symbol enumeration callback.
326d1845a5ad33574cb834270779589136854527vboxsync *
326d1845a5ad33574cb834270779589136854527vboxsync * @returns TRUE (continue enum).
326d1845a5ad33574cb834270779589136854527vboxsync * @param pSymInfo The symbol info.
326d1845a5ad33574cb834270779589136854527vboxsync * @param cbSymbol The symbol length (calculated).
326d1845a5ad33574cb834270779589136854527vboxsync * @param pvUser NULL.
326d1845a5ad33574cb834270779589136854527vboxsync */
326d1845a5ad33574cb834270779589136854527vboxsyncstatic BOOL CALLBACK dumpSymbolCallback(PSYMBOL_INFO pSymInfo, ULONG cbSymbol, PVOID pvUser)
326d1845a5ad33574cb834270779589136854527vboxsync{
326d1845a5ad33574cb834270779589136854527vboxsync NOREF(pvUser);
e4fd4a5aeda0e74e8b509db8147d0dd3482054f4vboxsync RTPrintf(" %#018RX64 LB %#07x %s\n", pSymInfo->Address, cbSymbol, pSymInfo->Name);
326d1845a5ad33574cb834270779589136854527vboxsync return TRUE;
326d1845a5ad33574cb834270779589136854527vboxsync}
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync/**
326d1845a5ad33574cb834270779589136854527vboxsync * Dumps all info.
326d1845a5ad33574cb834270779589136854527vboxsync * @returns Exit code with any relevant complaints printed.
326d1845a5ad33574cb834270779589136854527vboxsync */
326d1845a5ad33574cb834270779589136854527vboxsyncstatic RTEXITCODE dumpAll(void)
326d1845a5ad33574cb834270779589136854527vboxsync{
326d1845a5ad33574cb834270779589136854527vboxsync RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
326d1845a5ad33574cb834270779589136854527vboxsync PRTNTDBGHELPMOD pMod;
326d1845a5ad33574cb834270779589136854527vboxsync RTListForEach(&g_ModuleList, pMod, RTNTDBGHELPMOD, ListEntry)
326d1845a5ad33574cb834270779589136854527vboxsync {
e4fd4a5aeda0e74e8b509db8147d0dd3482054f4vboxsync RTPrintf("*** %#018RX64 - %s ***\n", pMod->uModAddr, pMod->szFullName);
326d1845a5ad33574cb834270779589136854527vboxsync
db073d0e5fab95903c54296592a82cb35d565520vboxsync static const int8_t s_acbVariations[] = { 0, -4, -8, -12, -16, -20, -24, -28, -32, 4, 8, 12, 16, 20, 24, 28, 32 };
db073d0e5fab95903c54296592a82cb35d565520vboxsync unsigned iVariation = 0;
db073d0e5fab95903c54296592a82cb35d565520vboxsync union
326d1845a5ad33574cb834270779589136854527vboxsync {
db073d0e5fab95903c54296592a82cb35d565520vboxsync IMAGEHLP_MODULE64 ModInfo;
db073d0e5fab95903c54296592a82cb35d565520vboxsync uint8_t abPadding[sizeof(IMAGEHLP_MODULE64) + 64];
db073d0e5fab95903c54296592a82cb35d565520vboxsync } u;
db073d0e5fab95903c54296592a82cb35d565520vboxsync
db073d0e5fab95903c54296592a82cb35d565520vboxsync BOOL fRc;
db073d0e5fab95903c54296592a82cb35d565520vboxsync do
db073d0e5fab95903c54296592a82cb35d565520vboxsync {
db073d0e5fab95903c54296592a82cb35d565520vboxsync RT_ZERO(u.ModInfo);
db073d0e5fab95903c54296592a82cb35d565520vboxsync u.ModInfo.SizeOfStruct = sizeof(u.ModInfo) + s_acbVariations[iVariation++];
db073d0e5fab95903c54296592a82cb35d565520vboxsync fRc = SymGetModuleInfo64(g_hFake, pMod->uModAddr, &u.ModInfo);
db073d0e5fab95903c54296592a82cb35d565520vboxsync } while (!fRc && GetLastError() == ERROR_INVALID_PARAMETER && iVariation < RT_ELEMENTS(s_acbVariations));
db073d0e5fab95903c54296592a82cb35d565520vboxsync
db073d0e5fab95903c54296592a82cb35d565520vboxsync if (fRc)
db073d0e5fab95903c54296592a82cb35d565520vboxsync {
db073d0e5fab95903c54296592a82cb35d565520vboxsync RTPrintf(" BaseOfImage = %#018llx\n", u.ModInfo.BaseOfImage);
db073d0e5fab95903c54296592a82cb35d565520vboxsync RTPrintf(" ImageSize = %#010x\n", u.ModInfo.ImageSize);
db073d0e5fab95903c54296592a82cb35d565520vboxsync RTPrintf(" TimeDateStamp = %#010x\n", u.ModInfo.TimeDateStamp);
db073d0e5fab95903c54296592a82cb35d565520vboxsync RTPrintf(" CheckSum = %#010x\n", u.ModInfo.CheckSum);
db073d0e5fab95903c54296592a82cb35d565520vboxsync RTPrintf(" NumSyms = %#010x (%u)\n", u.ModInfo.NumSyms, u.ModInfo.NumSyms);
db073d0e5fab95903c54296592a82cb35d565520vboxsync RTPrintf(" SymType = %s\n", symTypeName(u.ModInfo.SymType));
db073d0e5fab95903c54296592a82cb35d565520vboxsync RTPrintf(" ModuleName = %.32s\n", u.ModInfo.ModuleName);
db073d0e5fab95903c54296592a82cb35d565520vboxsync RTPrintf(" ImageName = %.256s\n", u.ModInfo.ImageName);
db073d0e5fab95903c54296592a82cb35d565520vboxsync RTPrintf(" LoadedImageName = %.256s\n", u.ModInfo.LoadedImageName);
db073d0e5fab95903c54296592a82cb35d565520vboxsync RTPrintf(" LoadedPdbName = %.256s\n", u.ModInfo.LoadedPdbName);
db073d0e5fab95903c54296592a82cb35d565520vboxsync RTPrintf(" CVSig = %#010x\n", u.ModInfo.CVSig);
326d1845a5ad33574cb834270779589136854527vboxsync /** @todo CVData. */
db073d0e5fab95903c54296592a82cb35d565520vboxsync RTPrintf(" PdbSig = %#010x\n", u.ModInfo.PdbSig);
db073d0e5fab95903c54296592a82cb35d565520vboxsync RTPrintf(" PdbSig70 = %RTuuid\n", &u.ModInfo.PdbSig70);
db073d0e5fab95903c54296592a82cb35d565520vboxsync RTPrintf(" PdbAge = %#010x\n", u.ModInfo.PdbAge);
db073d0e5fab95903c54296592a82cb35d565520vboxsync RTPrintf(" PdbUnmatched = %RTbool\n", u.ModInfo.PdbUnmatched);
db073d0e5fab95903c54296592a82cb35d565520vboxsync RTPrintf(" DbgUnmatched = %RTbool\n", u.ModInfo.DbgUnmatched);
db073d0e5fab95903c54296592a82cb35d565520vboxsync RTPrintf(" LineNumbers = %RTbool\n", u.ModInfo.LineNumbers);
db073d0e5fab95903c54296592a82cb35d565520vboxsync RTPrintf(" GlobalSymbols = %RTbool\n", u.ModInfo.GlobalSymbols);
db073d0e5fab95903c54296592a82cb35d565520vboxsync RTPrintf(" TypeInfo = %RTbool\n", u.ModInfo.TypeInfo);
db073d0e5fab95903c54296592a82cb35d565520vboxsync RTPrintf(" SourceIndexed = %RTbool\n", u.ModInfo.SourceIndexed);
db073d0e5fab95903c54296592a82cb35d565520vboxsync RTPrintf(" Publics = %RTbool\n", u.ModInfo.Publics);
326d1845a5ad33574cb834270779589136854527vboxsync }
326d1845a5ad33574cb834270779589136854527vboxsync else
326d1845a5ad33574cb834270779589136854527vboxsync rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "SymGetModuleInfo64 failed: %u\n", GetLastError());
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync if (!SymEnumSymbols(g_hFake, pMod->uModAddr, NULL, dumpSymbolCallback, NULL))
326d1845a5ad33574cb834270779589136854527vboxsync rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "SymEnumSymbols failed: %u\n", GetLastError());
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync }
326d1845a5ad33574cb834270779589136854527vboxsync return rcExit;
326d1845a5ad33574cb834270779589136854527vboxsync}
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsyncint main(int argc, char **argv)
326d1845a5ad33574cb834270779589136854527vboxsync{
326d1845a5ad33574cb834270779589136854527vboxsync int rc = RTR3InitExe(argc, &argv, 0 /*fFlags*/);
326d1845a5ad33574cb834270779589136854527vboxsync if (RT_FAILURE(rc))
326d1845a5ad33574cb834270779589136854527vboxsync return RTMsgInitFailure(rc);
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync RTListInit(&g_ModuleList);
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync /*
326d1845a5ad33574cb834270779589136854527vboxsync * Parse options.
326d1845a5ad33574cb834270779589136854527vboxsync */
326d1845a5ad33574cb834270779589136854527vboxsync static const RTGETOPTDEF s_aOptions[] =
326d1845a5ad33574cb834270779589136854527vboxsync {
326d1845a5ad33574cb834270779589136854527vboxsync { "--dump-all", 'd', RTGETOPT_REQ_NOTHING },
326d1845a5ad33574cb834270779589136854527vboxsync { "--load", 'l', RTGETOPT_REQ_STRING },
326d1845a5ad33574cb834270779589136854527vboxsync { "--set-address", 'a', RTGETOPT_REQ_UINT64 },
326d1845a5ad33574cb834270779589136854527vboxsync#define OPT_SET_DEBUG_INFO 0x1000
326d1845a5ad33574cb834270779589136854527vboxsync { "--set-debug-info", OPT_SET_DEBUG_INFO, RTGETOPT_REQ_NOTHING },
326d1845a5ad33574cb834270779589136854527vboxsync { "--verbose", 'v', RTGETOPT_REQ_NOTHING },
326d1845a5ad33574cb834270779589136854527vboxsync { "--quiet", 'q', RTGETOPT_REQ_NOTHING },
326d1845a5ad33574cb834270779589136854527vboxsync };
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
326d1845a5ad33574cb834270779589136854527vboxsync const char *pszOutput = "-";
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync int ch;
326d1845a5ad33574cb834270779589136854527vboxsync RTGETOPTUNION ValueUnion;
326d1845a5ad33574cb834270779589136854527vboxsync RTGETOPTSTATE GetState;
326d1845a5ad33574cb834270779589136854527vboxsync RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1,
326d1845a5ad33574cb834270779589136854527vboxsync RTGETOPTINIT_FLAGS_OPTS_FIRST);
326d1845a5ad33574cb834270779589136854527vboxsync while ((ch = RTGetOpt(&GetState, &ValueUnion)) != 0)
326d1845a5ad33574cb834270779589136854527vboxsync {
326d1845a5ad33574cb834270779589136854527vboxsync switch (ch)
326d1845a5ad33574cb834270779589136854527vboxsync {
326d1845a5ad33574cb834270779589136854527vboxsync case 'v':
326d1845a5ad33574cb834270779589136854527vboxsync g_iOptVerbose++;
326d1845a5ad33574cb834270779589136854527vboxsync break;
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync case 'q':
326d1845a5ad33574cb834270779589136854527vboxsync g_iOptVerbose++;
326d1845a5ad33574cb834270779589136854527vboxsync break;
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync case 'l':
326d1845a5ad33574cb834270779589136854527vboxsync rcExit = loadModule(ValueUnion.psz);
326d1845a5ad33574cb834270779589136854527vboxsync break;
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync case 'a':
326d1845a5ad33574cb834270779589136854527vboxsync g_uCurAddress = ValueUnion.u64;
326d1845a5ad33574cb834270779589136854527vboxsync break;
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync case 'd':
326d1845a5ad33574cb834270779589136854527vboxsync rcExit = dumpAll();
326d1845a5ad33574cb834270779589136854527vboxsync break;
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync case OPT_SET_DEBUG_INFO:
326d1845a5ad33574cb834270779589136854527vboxsync rcExit = ensureInitialized();
326d1845a5ad33574cb834270779589136854527vboxsync if (rcExit == RTEXITCODE_SUCCESS && !SymSetOptions(SymGetOptions() | SYMOPT_DEBUG))
326d1845a5ad33574cb834270779589136854527vboxsync rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "SymSetOptions failed: %u\n", GetLastError());
326d1845a5ad33574cb834270779589136854527vboxsync break;
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync case 'V':
326d1845a5ad33574cb834270779589136854527vboxsync RTPrintf("$Revision$");
326d1845a5ad33574cb834270779589136854527vboxsync break;
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync case 'h':
db073d0e5fab95903c54296592a82cb35d565520vboxsync RTPrintf("usage: %s [-v|--verbose] [-q|--quiet] [--set-debug-info] [-a <addr>] [-l <file>] [-d] [...]\n"
326d1845a5ad33574cb834270779589136854527vboxsync " or: %s [-V|--version]\n"
326d1845a5ad33574cb834270779589136854527vboxsync " or: %s [-h|--help]\n",
326d1845a5ad33574cb834270779589136854527vboxsync argv[0], argv[0], argv[0]);
326d1845a5ad33574cb834270779589136854527vboxsync return RTEXITCODE_SUCCESS;
326d1845a5ad33574cb834270779589136854527vboxsync
326d1845a5ad33574cb834270779589136854527vboxsync case VINF_GETOPT_NOT_OPTION:
326d1845a5ad33574cb834270779589136854527vboxsync default:
326d1845a5ad33574cb834270779589136854527vboxsync return RTGetOptPrintError(ch, &ValueUnion);
326d1845a5ad33574cb834270779589136854527vboxsync }
326d1845a5ad33574cb834270779589136854527vboxsync if (rcExit != RTEXITCODE_SUCCESS)
326d1845a5ad33574cb834270779589136854527vboxsync break;
326d1845a5ad33574cb834270779589136854527vboxsync }
326d1845a5ad33574cb834270779589136854527vboxsync return rcExit;
326d1845a5ad33574cb834270779589136854527vboxsync}
326d1845a5ad33574cb834270779589136854527vboxsync