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