Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/os/windows/vm/decoder_windows.cpp
32285 views
/*1* Copyright (c) 1997, 2013, 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 "prims/jvm.h"26#include "runtime/arguments.hpp"27#include "decoder_windows.hpp"2829WindowsDecoder::WindowsDecoder() {30_dbghelp_handle = NULL;31_can_decode_in_vm = false;32_pfnSymGetSymFromAddr64 = NULL;33_pfnUndecorateSymbolName = NULL;34#ifdef AMD6435_pfnStackWalk64 = NULL;36_pfnSymFunctionTableAccess64 = NULL;37_pfnSymGetModuleBase64 = NULL;38#endif39_decoder_status = no_error;40initialize();41}4243void WindowsDecoder::initialize() {44if (!has_error() && _dbghelp_handle == NULL) {45HMODULE handle = ::LoadLibrary("dbghelp.dll");46if (!handle) {47_decoder_status = helper_not_found;48return;49}5051_dbghelp_handle = handle;5253pfn_SymSetOptions _pfnSymSetOptions = (pfn_SymSetOptions)::GetProcAddress(handle, "SymSetOptions");54pfn_SymInitialize _pfnSymInitialize = (pfn_SymInitialize)::GetProcAddress(handle, "SymInitialize");55_pfnSymGetSymFromAddr64 = (pfn_SymGetSymFromAddr64)::GetProcAddress(handle, "SymGetSymFromAddr64");56_pfnUndecorateSymbolName = (pfn_UndecorateSymbolName)::GetProcAddress(handle, "UnDecorateSymbolName");5758if (_pfnSymSetOptions == NULL || _pfnSymInitialize == NULL || _pfnSymGetSymFromAddr64 == NULL) {59uninitialize();60_decoder_status = helper_func_error;61return;62}6364#ifdef AMD6465_pfnStackWalk64 = (pfn_StackWalk64)::GetProcAddress(handle, "StackWalk64");66_pfnSymFunctionTableAccess64 = (pfn_SymFunctionTableAccess64)::GetProcAddress(handle, "SymFunctionTableAccess64");67_pfnSymGetModuleBase64 = (pfn_SymGetModuleBase64)::GetProcAddress(handle, "SymGetModuleBase64");68if (_pfnStackWalk64 == NULL || _pfnSymFunctionTableAccess64 == NULL || _pfnSymGetModuleBase64 == NULL) {69// We can't call StackWalk64 to walk the stack, but we are still70// able to decode the symbols. Let's limp on.71_pfnStackWalk64 = NULL;72_pfnSymFunctionTableAccess64 = NULL;73_pfnSymGetModuleBase64 = NULL;74}75#endif7677HANDLE hProcess = ::GetCurrentProcess();78_pfnSymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_EXACT_SYMBOLS);79if (!_pfnSymInitialize(hProcess, NULL, TRUE)) {80_pfnSymGetSymFromAddr64 = NULL;81_pfnUndecorateSymbolName = NULL;82::FreeLibrary(handle);83_dbghelp_handle = NULL;84_decoder_status = helper_init_error;85return;86}8788// set pdb search paths89pfn_SymSetSearchPath _pfn_SymSetSearchPath =90(pfn_SymSetSearchPath)::GetProcAddress(handle, "SymSetSearchPath");91pfn_SymGetSearchPath _pfn_SymGetSearchPath =92(pfn_SymGetSearchPath)::GetProcAddress(handle, "SymGetSearchPath");93if (_pfn_SymSetSearchPath != NULL && _pfn_SymGetSearchPath != NULL) {94char paths[MAX_PATH];95int len = sizeof(paths);96if (!_pfn_SymGetSearchPath(hProcess, paths, len)) {97paths[0] = '\0';98} else {99// available spaces in path buffer100len -= (int)strlen(paths);101}102103char tmp_path[MAX_PATH];104DWORD dwSize;105HMODULE hJVM = ::GetModuleHandle("jvm.dll");106tmp_path[0] = '\0';107// append the path where jvm.dll is located108if (hJVM != NULL && (dwSize = ::GetModuleFileName(hJVM, tmp_path, sizeof(tmp_path))) > 0) {109while (dwSize > 0 && tmp_path[dwSize] != '\\') {110dwSize --;111}112113tmp_path[dwSize] = '\0';114115if (dwSize > 0 && len > (int)dwSize + 1) {116strncat(paths, os::path_separator(), 1);117strncat(paths, tmp_path, dwSize);118len -= dwSize + 1;119}120}121122// append $JRE/bin. Arguments::get_java_home actually returns $JRE123// path124char *p = Arguments::get_java_home();125assert(p != NULL, "empty java home");126size_t java_home_len = strlen(p);127if (len > (int)java_home_len + 5) {128strncat(paths, os::path_separator(), 1);129strncat(paths, p, java_home_len);130strncat(paths, "\\bin", 4);131len -= (int)(java_home_len + 5);132}133134// append $JDK/bin path if it exists135assert(java_home_len < MAX_PATH, "Invalid path length");136// assume $JRE is under $JDK, construct $JDK/bin path and137// see if it exists or not138if (strncmp(&p[java_home_len - 3], "jre", 3) == 0) {139strncpy(tmp_path, p, java_home_len - 3);140tmp_path[java_home_len - 3] = '\0';141strncat(tmp_path, "bin", 3);142143// if the directory exists144DWORD dwAttrib = GetFileAttributes(tmp_path);145if (dwAttrib != INVALID_FILE_ATTRIBUTES &&146(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) {147// tmp_path should have the same length as java_home_len, since we only148// replaced 'jre' with 'bin'149if (len > (int)java_home_len + 1) {150strncat(paths, os::path_separator(), 1);151strncat(paths, tmp_path, java_home_len);152}153}154}155156_pfn_SymSetSearchPath(hProcess, paths);157}158159// find out if jvm.dll contains private symbols, by decoding160// current function and comparing the result161address addr = (address)Decoder::demangle;162char buf[MAX_PATH];163if (decode(addr, buf, sizeof(buf), NULL)) {164_can_decode_in_vm = !strcmp(buf, "Decoder::demangle");165}166}167}168169void WindowsDecoder::uninitialize() {170_pfnSymGetSymFromAddr64 = NULL;171_pfnUndecorateSymbolName = NULL;172#ifdef AMD64173_pfnStackWalk64 = NULL;174_pfnSymFunctionTableAccess64 = NULL;175_pfnSymGetModuleBase64 = NULL;176#endif177if (_dbghelp_handle != NULL) {178::FreeLibrary(_dbghelp_handle);179}180_dbghelp_handle = NULL;181}182183bool WindowsDecoder::can_decode_C_frame_in_vm() const {184return (!has_error() && _can_decode_in_vm);185}186187188bool WindowsDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* modulepath) {189if (_pfnSymGetSymFromAddr64 != NULL) {190PIMAGEHLP_SYMBOL64 pSymbol;191char symbolInfo[MAX_PATH + sizeof(IMAGEHLP_SYMBOL64)];192pSymbol = (PIMAGEHLP_SYMBOL64)symbolInfo;193pSymbol->MaxNameLength = MAX_PATH;194pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);195DWORD64 displacement;196if (_pfnSymGetSymFromAddr64(::GetCurrentProcess(), (DWORD64)addr, &displacement, pSymbol)) {197if (buf != NULL) {198if (demangle(pSymbol->Name, buf, buflen)) {199jio_snprintf(buf, buflen, "%s", pSymbol->Name);200}201}202if(offset != NULL) *offset = (int)displacement;203return true;204}205}206if (buf != NULL && buflen > 0) buf[0] = '\0';207if (offset != NULL) *offset = -1;208return false;209}210211bool WindowsDecoder::demangle(const char* symbol, char *buf, int buflen) {212return _pfnUndecorateSymbolName != NULL &&213_pfnUndecorateSymbolName(symbol, buf, buflen, UNDNAME_COMPLETE);214}215216#ifdef AMD64217BOOL WindowsDbgHelp::StackWalk64(DWORD MachineType,218HANDLE hProcess,219HANDLE hThread,220LPSTACKFRAME64 StackFrame,221PVOID ContextRecord,222PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,223PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,224PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,225PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress) {226DecoderLocker locker;227WindowsDecoder* wd = (WindowsDecoder*)locker.decoder();228229if (!wd->has_error() && wd->_pfnStackWalk64) {230return wd->_pfnStackWalk64(MachineType,231hProcess,232hThread,233StackFrame,234ContextRecord,235ReadMemoryRoutine,236FunctionTableAccessRoutine,237GetModuleBaseRoutine,238TranslateAddress);239} else {240return false;241}242}243244PVOID WindowsDbgHelp::SymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase) {245DecoderLocker locker;246WindowsDecoder* wd = (WindowsDecoder*)locker.decoder();247248if (!wd->has_error() && wd->_pfnSymFunctionTableAccess64) {249return wd->_pfnSymFunctionTableAccess64(hProcess, AddrBase);250} else {251return NULL;252}253}254255pfn_SymFunctionTableAccess64 WindowsDbgHelp::pfnSymFunctionTableAccess64() {256DecoderLocker locker;257WindowsDecoder* wd = (WindowsDecoder*)locker.decoder();258259if (!wd->has_error()) {260return wd->_pfnSymFunctionTableAccess64;261} else {262return NULL;263}264}265266pfn_SymGetModuleBase64 WindowsDbgHelp::pfnSymGetModuleBase64() {267DecoderLocker locker;268WindowsDecoder* wd = (WindowsDecoder*)locker.decoder();269270if (!wd->has_error()) {271return wd->_pfnSymGetModuleBase64;272} else {273return NULL;274}275}276277#endif // AMD64278279280