src/os/windows/vm/decoder_windows.cpp

Wed, 27 Apr 2016 01:25:04 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:25:04 +0800
changeset 0
f90c822e73f8
child 6876
710a3c8b516e
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/
changeset: 6782:28b50d07f6f8
tag: jdk8u25-b17

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation.
aoqi@0 8 *
aoqi@0 9 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 12 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 13 * accompanied this code).
aoqi@0 14 *
aoqi@0 15 * You should have received a copy of the GNU General Public License version
aoqi@0 16 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 18 *
aoqi@0 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 20 * or visit www.oracle.com if you need additional information or have any
aoqi@0 21 * questions.
aoqi@0 22 *
aoqi@0 23 */
aoqi@0 24
aoqi@0 25 #include "precompiled.hpp"
aoqi@0 26 #include "prims/jvm.h"
aoqi@0 27 #include "runtime/arguments.hpp"
aoqi@0 28 #include "decoder_windows.hpp"
aoqi@0 29
aoqi@0 30 WindowsDecoder::WindowsDecoder() {
aoqi@0 31 _dbghelp_handle = NULL;
aoqi@0 32 _can_decode_in_vm = false;
aoqi@0 33 _pfnSymGetSymFromAddr64 = NULL;
aoqi@0 34 _pfnUndecorateSymbolName = NULL;
aoqi@0 35 #ifdef AMD64
aoqi@0 36 _pfnStackWalk64 = NULL;
aoqi@0 37 _pfnSymFunctionTableAccess64 = NULL;
aoqi@0 38 _pfnSymGetModuleBase64 = NULL;
aoqi@0 39 #endif
aoqi@0 40 _decoder_status = no_error;
aoqi@0 41 initialize();
aoqi@0 42 }
aoqi@0 43
aoqi@0 44 void WindowsDecoder::initialize() {
aoqi@0 45 if (!has_error() && _dbghelp_handle == NULL) {
aoqi@0 46 HMODULE handle = ::LoadLibrary("dbghelp.dll");
aoqi@0 47 if (!handle) {
aoqi@0 48 _decoder_status = helper_not_found;
aoqi@0 49 return;
aoqi@0 50 }
aoqi@0 51
aoqi@0 52 _dbghelp_handle = handle;
aoqi@0 53
aoqi@0 54 pfn_SymSetOptions _pfnSymSetOptions = (pfn_SymSetOptions)::GetProcAddress(handle, "SymSetOptions");
aoqi@0 55 pfn_SymInitialize _pfnSymInitialize = (pfn_SymInitialize)::GetProcAddress(handle, "SymInitialize");
aoqi@0 56 _pfnSymGetSymFromAddr64 = (pfn_SymGetSymFromAddr64)::GetProcAddress(handle, "SymGetSymFromAddr64");
aoqi@0 57 _pfnUndecorateSymbolName = (pfn_UndecorateSymbolName)::GetProcAddress(handle, "UnDecorateSymbolName");
aoqi@0 58
aoqi@0 59 if (_pfnSymSetOptions == NULL || _pfnSymInitialize == NULL || _pfnSymGetSymFromAddr64 == NULL) {
aoqi@0 60 uninitialize();
aoqi@0 61 _decoder_status = helper_func_error;
aoqi@0 62 return;
aoqi@0 63 }
aoqi@0 64
aoqi@0 65 #ifdef AMD64
aoqi@0 66 _pfnStackWalk64 = (pfn_StackWalk64)::GetProcAddress(handle, "StackWalk64");
aoqi@0 67 _pfnSymFunctionTableAccess64 = (pfn_SymFunctionTableAccess64)::GetProcAddress(handle, "SymFunctionTableAccess64");
aoqi@0 68 _pfnSymGetModuleBase64 = (pfn_SymGetModuleBase64)::GetProcAddress(handle, "SymGetModuleBase64");
aoqi@0 69 if (_pfnStackWalk64 == NULL || _pfnSymFunctionTableAccess64 == NULL || _pfnSymGetModuleBase64 == NULL) {
aoqi@0 70 // We can't call StackWalk64 to walk the stack, but we are still
aoqi@0 71 // able to decode the symbols. Let's limp on.
aoqi@0 72 _pfnStackWalk64 = NULL;
aoqi@0 73 _pfnSymFunctionTableAccess64 = NULL;
aoqi@0 74 _pfnSymGetModuleBase64 = NULL;
aoqi@0 75 }
aoqi@0 76 #endif
aoqi@0 77
aoqi@0 78 HANDLE hProcess = ::GetCurrentProcess();
aoqi@0 79 _pfnSymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_EXACT_SYMBOLS);
aoqi@0 80 if (!_pfnSymInitialize(hProcess, NULL, TRUE)) {
aoqi@0 81 _pfnSymGetSymFromAddr64 = NULL;
aoqi@0 82 _pfnUndecorateSymbolName = NULL;
aoqi@0 83 ::FreeLibrary(handle);
aoqi@0 84 _dbghelp_handle = NULL;
aoqi@0 85 _decoder_status = helper_init_error;
aoqi@0 86 return;
aoqi@0 87 }
aoqi@0 88
aoqi@0 89 // set pdb search paths
aoqi@0 90 pfn_SymSetSearchPath _pfn_SymSetSearchPath =
aoqi@0 91 (pfn_SymSetSearchPath)::GetProcAddress(handle, "SymSetSearchPath");
aoqi@0 92 pfn_SymGetSearchPath _pfn_SymGetSearchPath =
aoqi@0 93 (pfn_SymGetSearchPath)::GetProcAddress(handle, "SymGetSearchPath");
aoqi@0 94 if (_pfn_SymSetSearchPath != NULL && _pfn_SymGetSearchPath != NULL) {
aoqi@0 95 char paths[MAX_PATH];
aoqi@0 96 int len = sizeof(paths);
aoqi@0 97 if (!_pfn_SymGetSearchPath(hProcess, paths, len)) {
aoqi@0 98 paths[0] = '\0';
aoqi@0 99 } else {
aoqi@0 100 // available spaces in path buffer
aoqi@0 101 len -= (int)strlen(paths);
aoqi@0 102 }
aoqi@0 103
aoqi@0 104 char tmp_path[MAX_PATH];
aoqi@0 105 DWORD dwSize;
aoqi@0 106 HMODULE hJVM = ::GetModuleHandle("jvm.dll");
aoqi@0 107 tmp_path[0] = '\0';
aoqi@0 108 // append the path where jvm.dll is located
aoqi@0 109 if (hJVM != NULL && (dwSize = ::GetModuleFileName(hJVM, tmp_path, sizeof(tmp_path))) > 0) {
aoqi@0 110 while (dwSize > 0 && tmp_path[dwSize] != '\\') {
aoqi@0 111 dwSize --;
aoqi@0 112 }
aoqi@0 113
aoqi@0 114 tmp_path[dwSize] = '\0';
aoqi@0 115
aoqi@0 116 if (dwSize > 0 && len > (int)dwSize + 1) {
aoqi@0 117 strncat(paths, os::path_separator(), 1);
aoqi@0 118 strncat(paths, tmp_path, dwSize);
aoqi@0 119 len -= dwSize + 1;
aoqi@0 120 }
aoqi@0 121 }
aoqi@0 122
aoqi@0 123 // append $JRE/bin. Arguments::get_java_home actually returns $JRE
aoqi@0 124 // path
aoqi@0 125 char *p = Arguments::get_java_home();
aoqi@0 126 assert(p != NULL, "empty java home");
aoqi@0 127 size_t java_home_len = strlen(p);
aoqi@0 128 if (len > (int)java_home_len + 5) {
aoqi@0 129 strncat(paths, os::path_separator(), 1);
aoqi@0 130 strncat(paths, p, java_home_len);
aoqi@0 131 strncat(paths, "\\bin", 4);
aoqi@0 132 len -= (int)(java_home_len + 5);
aoqi@0 133 }
aoqi@0 134
aoqi@0 135 // append $JDK/bin path if it exists
aoqi@0 136 assert(java_home_len < MAX_PATH, "Invalid path length");
aoqi@0 137 // assume $JRE is under $JDK, construct $JDK/bin path and
aoqi@0 138 // see if it exists or not
aoqi@0 139 if (strncmp(&p[java_home_len - 3], "jre", 3) == 0) {
aoqi@0 140 strncpy(tmp_path, p, java_home_len - 3);
aoqi@0 141 tmp_path[java_home_len - 3] = '\0';
aoqi@0 142 strncat(tmp_path, "bin", 3);
aoqi@0 143
aoqi@0 144 // if the directory exists
aoqi@0 145 DWORD dwAttrib = GetFileAttributes(tmp_path);
aoqi@0 146 if (dwAttrib != INVALID_FILE_ATTRIBUTES &&
aoqi@0 147 (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) {
aoqi@0 148 // tmp_path should have the same length as java_home_len, since we only
aoqi@0 149 // replaced 'jre' with 'bin'
aoqi@0 150 if (len > (int)java_home_len + 1) {
aoqi@0 151 strncat(paths, os::path_separator(), 1);
aoqi@0 152 strncat(paths, tmp_path, java_home_len);
aoqi@0 153 }
aoqi@0 154 }
aoqi@0 155 }
aoqi@0 156
aoqi@0 157 _pfn_SymSetSearchPath(hProcess, paths);
aoqi@0 158 }
aoqi@0 159
aoqi@0 160 // find out if jvm.dll contains private symbols, by decoding
aoqi@0 161 // current function and comparing the result
aoqi@0 162 address addr = (address)Decoder::demangle;
aoqi@0 163 char buf[MAX_PATH];
aoqi@0 164 if (decode(addr, buf, sizeof(buf), NULL)) {
aoqi@0 165 _can_decode_in_vm = !strcmp(buf, "Decoder::demangle");
aoqi@0 166 }
aoqi@0 167 }
aoqi@0 168 }
aoqi@0 169
aoqi@0 170 void WindowsDecoder::uninitialize() {
aoqi@0 171 _pfnSymGetSymFromAddr64 = NULL;
aoqi@0 172 _pfnUndecorateSymbolName = NULL;
aoqi@0 173 #ifdef AMD64
aoqi@0 174 _pfnStackWalk64 = NULL;
aoqi@0 175 _pfnSymFunctionTableAccess64 = NULL;
aoqi@0 176 _pfnSymGetModuleBase64 = NULL;
aoqi@0 177 #endif
aoqi@0 178 if (_dbghelp_handle != NULL) {
aoqi@0 179 ::FreeLibrary(_dbghelp_handle);
aoqi@0 180 }
aoqi@0 181 _dbghelp_handle = NULL;
aoqi@0 182 }
aoqi@0 183
aoqi@0 184 bool WindowsDecoder::can_decode_C_frame_in_vm() const {
aoqi@0 185 return (!has_error() && _can_decode_in_vm);
aoqi@0 186 }
aoqi@0 187
aoqi@0 188
aoqi@0 189 bool WindowsDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* modulepath) {
aoqi@0 190 if (_pfnSymGetSymFromAddr64 != NULL) {
aoqi@0 191 PIMAGEHLP_SYMBOL64 pSymbol;
aoqi@0 192 char symbolInfo[MAX_PATH + sizeof(IMAGEHLP_SYMBOL64)];
aoqi@0 193 pSymbol = (PIMAGEHLP_SYMBOL64)symbolInfo;
aoqi@0 194 pSymbol->MaxNameLength = MAX_PATH;
aoqi@0 195 pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
aoqi@0 196 DWORD64 displacement;
aoqi@0 197 if (_pfnSymGetSymFromAddr64(::GetCurrentProcess(), (DWORD64)addr, &displacement, pSymbol)) {
aoqi@0 198 if (buf != NULL) {
aoqi@0 199 if (demangle(pSymbol->Name, buf, buflen)) {
aoqi@0 200 jio_snprintf(buf, buflen, "%s", pSymbol->Name);
aoqi@0 201 }
aoqi@0 202 }
aoqi@0 203 if(offset != NULL) *offset = (int)displacement;
aoqi@0 204 return true;
aoqi@0 205 }
aoqi@0 206 }
aoqi@0 207 if (buf != NULL && buflen > 0) buf[0] = '\0';
aoqi@0 208 if (offset != NULL) *offset = -1;
aoqi@0 209 return false;
aoqi@0 210 }
aoqi@0 211
aoqi@0 212 bool WindowsDecoder::demangle(const char* symbol, char *buf, int buflen) {
aoqi@0 213 return _pfnUndecorateSymbolName != NULL &&
aoqi@0 214 _pfnUndecorateSymbolName(symbol, buf, buflen, UNDNAME_COMPLETE);
aoqi@0 215 }
aoqi@0 216
aoqi@0 217 #ifdef AMD64
aoqi@0 218 BOOL WindowsDbgHelp::StackWalk64(DWORD MachineType,
aoqi@0 219 HANDLE hProcess,
aoqi@0 220 HANDLE hThread,
aoqi@0 221 LPSTACKFRAME64 StackFrame,
aoqi@0 222 PVOID ContextRecord,
aoqi@0 223 PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
aoqi@0 224 PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
aoqi@0 225 PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
aoqi@0 226 PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress) {
aoqi@0 227 DecoderLocker locker;
aoqi@0 228 WindowsDecoder* wd = (WindowsDecoder*)locker.decoder();
aoqi@0 229
aoqi@0 230 if (!wd->has_error() && wd->_pfnStackWalk64) {
aoqi@0 231 return wd->_pfnStackWalk64(MachineType,
aoqi@0 232 hProcess,
aoqi@0 233 hThread,
aoqi@0 234 StackFrame,
aoqi@0 235 ContextRecord,
aoqi@0 236 ReadMemoryRoutine,
aoqi@0 237 FunctionTableAccessRoutine,
aoqi@0 238 GetModuleBaseRoutine,
aoqi@0 239 TranslateAddress);
aoqi@0 240 } else {
aoqi@0 241 return false;
aoqi@0 242 }
aoqi@0 243 }
aoqi@0 244
aoqi@0 245 PVOID WindowsDbgHelp::SymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase) {
aoqi@0 246 DecoderLocker locker;
aoqi@0 247 WindowsDecoder* wd = (WindowsDecoder*)locker.decoder();
aoqi@0 248
aoqi@0 249 if (!wd->has_error() && wd->_pfnSymFunctionTableAccess64) {
aoqi@0 250 return wd->_pfnSymFunctionTableAccess64(hProcess, AddrBase);
aoqi@0 251 } else {
aoqi@0 252 return NULL;
aoqi@0 253 }
aoqi@0 254 }
aoqi@0 255
aoqi@0 256 pfn_SymFunctionTableAccess64 WindowsDbgHelp::pfnSymFunctionTableAccess64() {
aoqi@0 257 DecoderLocker locker;
aoqi@0 258 WindowsDecoder* wd = (WindowsDecoder*)locker.decoder();
aoqi@0 259
aoqi@0 260 if (!wd->has_error()) {
aoqi@0 261 return wd->_pfnSymFunctionTableAccess64;
aoqi@0 262 } else {
aoqi@0 263 return NULL;
aoqi@0 264 }
aoqi@0 265 }
aoqi@0 266
aoqi@0 267 pfn_SymGetModuleBase64 WindowsDbgHelp::pfnSymGetModuleBase64() {
aoqi@0 268 DecoderLocker locker;
aoqi@0 269 WindowsDecoder* wd = (WindowsDecoder*)locker.decoder();
aoqi@0 270
aoqi@0 271 if (!wd->has_error()) {
aoqi@0 272 return wd->_pfnSymGetModuleBase64;
aoqi@0 273 } else {
aoqi@0 274 return NULL;
aoqi@0 275 }
aoqi@0 276 }
aoqi@0 277
aoqi@0 278 #endif // AMD64

mercurial