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