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

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

mercurial