Path: blob/master/src/hotspot/os/windows/windbghelp.cpp
40931 views
/*1* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "utilities/ostream.hpp"26#include "windbghelp.hpp"2728#include <windows.h>2930typedef DWORD (WINAPI *pfn_SymSetOptions)(DWORD);31typedef DWORD (WINAPI *pfn_SymGetOptions)(void);32typedef BOOL (WINAPI *pfn_SymInitialize)(HANDLE, PCTSTR, BOOL);33typedef BOOL (WINAPI *pfn_SymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64);34typedef DWORD (WINAPI *pfn_UnDecorateSymbolName)(const char*, char*, DWORD, DWORD);35typedef BOOL (WINAPI *pfn_SymSetSearchPath)(HANDLE, PCTSTR);36typedef BOOL (WINAPI *pfn_SymGetSearchPath)(HANDLE, PTSTR, int);37typedef BOOL (WINAPI *pfn_StackWalk64)(DWORD MachineType,38HANDLE hProcess,39HANDLE hThread,40LPSTACKFRAME64 StackFrame,41PVOID ContextRecord,42PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,43PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,44PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,45PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);46typedef PVOID (WINAPI *pfn_SymFunctionTableAccess64)(HANDLE hProcess, DWORD64 AddrBase);47typedef DWORD64 (WINAPI *pfn_SymGetModuleBase64)(HANDLE hProcess, DWORD64 dwAddr);48typedef BOOL (WINAPI *pfn_MiniDumpWriteDump) (HANDLE hProcess, DWORD ProcessId, HANDLE hFile,49MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,50PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,51PMINIDUMP_CALLBACK_INFORMATION CallbackParam);52typedef BOOL (WINAPI *pfn_SymGetLineFromAddr64) (HANDLE hProcess, DWORD64 dwAddr,53PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line);54typedef LPAPI_VERSION (WINAPI *pfn_ImagehlpApiVersion)(void);5556// Add functions as needed.57#define FOR_ALL_FUNCTIONS(DO) \58DO(ImagehlpApiVersion) \59DO(SymGetOptions) \60DO(SymSetOptions) \61DO(SymInitialize) \62DO(SymGetSymFromAddr64) \63DO(UnDecorateSymbolName) \64DO(SymSetSearchPath) \65DO(SymGetSearchPath) \66DO(StackWalk64) \67DO(SymFunctionTableAccess64) \68DO(SymGetModuleBase64) \69DO(MiniDumpWriteDump) \70DO(SymGetLineFromAddr64)717273#define DECLARE_FUNCTION_POINTER(functionname) \74static pfn_##functionname g_pfn_##functionname;7576FOR_ALL_FUNCTIONS(DECLARE_FUNCTION_POINTER)777879static HMODULE g_dll_handle = NULL;80static DWORD g_dll_load_error = 0;81static API_VERSION g_version = { 0, 0, 0, 0 };8283static enum {84state_uninitialized = 0,85state_ready = 1,86state_error = 287} g_state = state_uninitialized;8889static void initialize() {9091assert(g_state == state_uninitialized, "wrong sequence");92g_state = state_error;9394g_dll_handle = ::LoadLibrary("DBGHELP.DLL");95if (g_dll_handle == NULL) {96g_dll_load_error = ::GetLastError();97} else {98// Note: We loaded the DLL successfully. From here on we count99// initialization as success. We still may fail to load all of the100// desired function pointers successfully, but DLL may still be usable101// enough for our purposes.102g_state = state_ready;103104#define DO_RESOLVE(functionname) \105g_pfn_##functionname = (pfn_##functionname) ::GetProcAddress(g_dll_handle, #functionname);106107FOR_ALL_FUNCTIONS(DO_RESOLVE)108109// Retrieve version information.110if (g_pfn_ImagehlpApiVersion) {111const API_VERSION* p = g_pfn_ImagehlpApiVersion();112memcpy(&g_version, p, sizeof(API_VERSION));113}114}115116}117118119///////////////////// External functions //////////////////////////120121// All outside facing functions are synchronized. Also, we run122// initialization on first touch.123124static CRITICAL_SECTION g_cs;125126namespace { // Do not export.127class WindowsDbgHelpEntry {128public:129WindowsDbgHelpEntry() {130::EnterCriticalSection(&g_cs);131if (g_state == state_uninitialized) {132initialize();133}134}135~WindowsDbgHelpEntry() {136::LeaveCriticalSection(&g_cs);137}138};139}140141// Called at DLL_PROCESS_ATTACH.142void WindowsDbgHelp::pre_initialize() {143::InitializeCriticalSection(&g_cs);144}145146DWORD WindowsDbgHelp::symSetOptions(DWORD arg) {147WindowsDbgHelpEntry entry_guard;148if (g_pfn_SymSetOptions != NULL) {149return g_pfn_SymSetOptions(arg);150}151return 0;152}153154DWORD WindowsDbgHelp::symGetOptions(void) {155WindowsDbgHelpEntry entry_guard;156if (g_pfn_SymGetOptions != NULL) {157return g_pfn_SymGetOptions();158}159return 0;160}161162BOOL WindowsDbgHelp::symInitialize(HANDLE hProcess, PCTSTR UserSearchPath, BOOL fInvadeProcess) {163WindowsDbgHelpEntry entry_guard;164if (g_pfn_SymInitialize != NULL) {165return g_pfn_SymInitialize(hProcess, UserSearchPath, fInvadeProcess);166}167return FALSE;168}169170BOOL WindowsDbgHelp::symGetSymFromAddr64(HANDLE hProcess, DWORD64 the_address,171PDWORD64 Displacement, PIMAGEHLP_SYMBOL64 Symbol) {172WindowsDbgHelpEntry entry_guard;173if (g_pfn_SymGetSymFromAddr64 != NULL) {174return g_pfn_SymGetSymFromAddr64(hProcess, the_address, Displacement, Symbol);175}176return FALSE;177}178179DWORD WindowsDbgHelp::unDecorateSymbolName(const char* DecoratedName, char* UnDecoratedName,180DWORD UndecoratedLength, DWORD Flags) {181WindowsDbgHelpEntry entry_guard;182if (g_pfn_UnDecorateSymbolName != NULL) {183return g_pfn_UnDecorateSymbolName(DecoratedName, UnDecoratedName, UndecoratedLength, Flags);184}185if (UnDecoratedName != NULL && UndecoratedLength > 0) {186UnDecoratedName[0] = '\0';187}188return 0;189}190191BOOL WindowsDbgHelp::symSetSearchPath(HANDLE hProcess, PCTSTR SearchPath) {192WindowsDbgHelpEntry entry_guard;193if (g_pfn_SymSetSearchPath != NULL) {194return g_pfn_SymSetSearchPath(hProcess, SearchPath);195}196return FALSE;197}198199BOOL WindowsDbgHelp::symGetSearchPath(HANDLE hProcess, PTSTR SearchPath, int SearchPathLength) {200WindowsDbgHelpEntry entry_guard;201if (g_pfn_SymGetSearchPath != NULL) {202return g_pfn_SymGetSearchPath(hProcess, SearchPath, SearchPathLength);203}204return FALSE;205}206207BOOL WindowsDbgHelp::stackWalk64(DWORD MachineType,208HANDLE hProcess,209HANDLE hThread,210LPSTACKFRAME64 StackFrame,211PVOID ContextRecord) {212WindowsDbgHelpEntry entry_guard;213if (g_pfn_StackWalk64 != NULL) {214return g_pfn_StackWalk64(MachineType, hProcess, hThread, StackFrame,215ContextRecord,216NULL, // ReadMemoryRoutine217g_pfn_SymFunctionTableAccess64, // FunctionTableAccessRoutine,218g_pfn_SymGetModuleBase64, // GetModuleBaseRoutine219NULL // TranslateAddressRoutine220);221}222return FALSE;223}224225PVOID WindowsDbgHelp::symFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase) {226WindowsDbgHelpEntry entry_guard;227if (g_pfn_SymFunctionTableAccess64 != NULL) {228return g_pfn_SymFunctionTableAccess64(hProcess, AddrBase);229}230return NULL;231}232233DWORD64 WindowsDbgHelp::symGetModuleBase64(HANDLE hProcess, DWORD64 dwAddr) {234WindowsDbgHelpEntry entry_guard;235if (g_pfn_SymGetModuleBase64 != NULL) {236return g_pfn_SymGetModuleBase64(hProcess, dwAddr);237}238return 0;239}240241BOOL WindowsDbgHelp::miniDumpWriteDump(HANDLE hProcess, DWORD ProcessId, HANDLE hFile,242MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,243PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,244PMINIDUMP_CALLBACK_INFORMATION CallbackParam) {245WindowsDbgHelpEntry entry_guard;246if (g_pfn_MiniDumpWriteDump != NULL) {247return g_pfn_MiniDumpWriteDump(hProcess, ProcessId, hFile, DumpType,248ExceptionParam, UserStreamParam, CallbackParam);249}250return FALSE;251}252253BOOL WindowsDbgHelp::symGetLineFromAddr64(HANDLE hProcess, DWORD64 dwAddr,254PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line) {255WindowsDbgHelpEntry entry_guard;256if (g_pfn_SymGetLineFromAddr64 != NULL) {257return g_pfn_SymGetLineFromAddr64(hProcess, dwAddr, pdwDisplacement, Line);258}259return FALSE;260}261262// Print one liner describing state (if library loaded, which functions are263// missing - if any, and the dbhelp API version)264void WindowsDbgHelp::print_state_on(outputStream* st) {265// Note: We should not lock while printing, but this should be266// safe to do without lock anyway.267st->print("dbghelp: ");268269if (g_state == state_uninitialized) {270st->print("uninitialized.");271} else if (g_state == state_error) {272st->print("loading error: %u", g_dll_load_error);273} else {274st->print("loaded successfully ");275276// We may want to print dll file name here - which may be interesting for277// cases where more than one version exists on the system, e.g. with a278// debugging sdk separately installed. But we get the file name in the DLL279// section of the hs-err file too, so this may be redundant.280281// Print version.282st->print("- version: %u.%u.%u",283g_version.MajorVersion, g_version.MinorVersion, g_version.Revision);284285// Print any functions which failed to load.286int num_missing = 0;287st->print(" - missing functions: ");288289#define CHECK_AND_PRINT_IF_NULL(functionname) \290if (g_pfn_##functionname == NULL) { \291st->print("%s" #functionname, ((num_missing > 0) ? ", " : "")); \292num_missing ++; \293}294295FOR_ALL_FUNCTIONS(CHECK_AND_PRINT_IF_NULL)296297if (num_missing == 0) {298st->print("none");299}300}301st->cr();302}303304305306