src/os/windows/vm/decoder_windows.cpp

Fri, 05 Apr 2013 11:15:13 -0700

author
ccheung
date
Fri, 05 Apr 2013 11:15:13 -0700
changeset 4893
4b7cf00ccb08
parent 4675
63e54c37ac64
child 5667
38f750491293
permissions
-rw-r--r--

8006001: [parfait] Possible file leak in hotspot/src/os/linux/vm/perfMemory_linux.cpp
Reviewed-by: zgu, coleenp, hseigel, dholmes

     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;
    36   _decoder_status = no_error;
    37   initialize();
    38 }
    40 void WindowsDecoder::initialize() {
    41   if (!has_error() && _dbghelp_handle == NULL) {
    42     HMODULE handle = ::LoadLibrary("dbghelp.dll");
    43     if (!handle) {
    44       _decoder_status = helper_not_found;
    45       return;
    46     }
    48     _dbghelp_handle = handle;
    50     pfn_SymSetOptions _pfnSymSetOptions = (pfn_SymSetOptions)::GetProcAddress(handle, "SymSetOptions");
    51     pfn_SymInitialize _pfnSymInitialize = (pfn_SymInitialize)::GetProcAddress(handle, "SymInitialize");
    52     _pfnSymGetSymFromAddr64 = (pfn_SymGetSymFromAddr64)::GetProcAddress(handle, "SymGetSymFromAddr64");
    53     _pfnUndecorateSymbolName = (pfn_UndecorateSymbolName)::GetProcAddress(handle, "UnDecorateSymbolName");
    55     if (_pfnSymSetOptions == NULL || _pfnSymInitialize == NULL || _pfnSymGetSymFromAddr64 == NULL) {
    56       _pfnSymGetSymFromAddr64 = NULL;
    57       _pfnUndecorateSymbolName = NULL;
    58       ::FreeLibrary(handle);
    59       _dbghelp_handle = NULL;
    60       _decoder_status = helper_func_error;
    61       return;
    62     }
    64     HANDLE hProcess = ::GetCurrentProcess();
    65     _pfnSymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_EXACT_SYMBOLS);
    66     if (!_pfnSymInitialize(hProcess, NULL, TRUE)) {
    67       _pfnSymGetSymFromAddr64 = NULL;
    68       _pfnUndecorateSymbolName = NULL;
    69       ::FreeLibrary(handle);
    70       _dbghelp_handle = NULL;
    71       _decoder_status = helper_init_error;
    72       return;
    73     }
    75     // set pdb search paths
    76     pfn_SymSetSearchPath  _pfn_SymSetSearchPath =
    77       (pfn_SymSetSearchPath)::GetProcAddress(handle, "SymSetSearchPath");
    78     pfn_SymGetSearchPath  _pfn_SymGetSearchPath =
    79       (pfn_SymGetSearchPath)::GetProcAddress(handle, "SymGetSearchPath");
    80     if (_pfn_SymSetSearchPath != NULL && _pfn_SymGetSearchPath != NULL) {
    81       char paths[MAX_PATH];
    82       int  len = sizeof(paths);
    83       if (!_pfn_SymGetSearchPath(hProcess, paths, len)) {
    84         paths[0] = '\0';
    85       } else {
    86         // available spaces in path buffer
    87         len -= (int)strlen(paths);
    88       }
    90       char tmp_path[MAX_PATH];
    91       DWORD dwSize;
    92       HMODULE hJVM = ::GetModuleHandle("jvm.dll");
    93       tmp_path[0] = '\0';
    94       // append the path where jvm.dll is located
    95       if (hJVM != NULL && (dwSize = ::GetModuleFileName(hJVM, tmp_path, sizeof(tmp_path))) > 0) {
    96         while (dwSize > 0 && tmp_path[dwSize] != '\\') {
    97           dwSize --;
    98         }
   100         tmp_path[dwSize] = '\0';
   102         if (dwSize > 0 && len > (int)dwSize + 1) {
   103           strncat(paths, os::path_separator(), 1);
   104           strncat(paths, tmp_path, dwSize);
   105           len -= dwSize + 1;
   106         }
   107       }
   109       // append $JRE/bin. Arguments::get_java_home actually returns $JRE
   110       // path
   111       char *p = Arguments::get_java_home();
   112       assert(p != NULL, "empty java home");
   113       size_t java_home_len = strlen(p);
   114       if (len > (int)java_home_len + 5) {
   115         strncat(paths, os::path_separator(), 1);
   116         strncat(paths, p, java_home_len);
   117         strncat(paths, "\\bin", 4);
   118         len -= (int)(java_home_len + 5);
   119       }
   121       // append $JDK/bin path if it exists
   122       assert(java_home_len < MAX_PATH, "Invalid path length");
   123       // assume $JRE is under $JDK, construct $JDK/bin path and
   124       // see if it exists or not
   125       if (strncmp(&p[java_home_len - 3], "jre", 3) == 0) {
   126         strncpy(tmp_path, p, java_home_len - 3);
   127         tmp_path[java_home_len - 3] = '\0';
   128         strncat(tmp_path, "bin", 3);
   130         // if the directory exists
   131         DWORD dwAttrib = GetFileAttributes(tmp_path);
   132         if (dwAttrib != INVALID_FILE_ATTRIBUTES &&
   133             (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) {
   134           // tmp_path should have the same length as java_home_len, since we only
   135           // replaced 'jre' with 'bin'
   136           if (len > (int)java_home_len + 1) {
   137             strncat(paths, os::path_separator(), 1);
   138             strncat(paths, tmp_path, java_home_len);
   139           }
   140         }
   141       }
   143       _pfn_SymSetSearchPath(hProcess, paths);
   144     }
   146      // find out if jvm.dll contains private symbols, by decoding
   147      // current function and comparing the result
   148      address addr = (address)Decoder::demangle;
   149      char buf[MAX_PATH];
   150      if (decode(addr, buf, sizeof(buf), NULL)) {
   151        _can_decode_in_vm = !strcmp(buf, "Decoder::demangle");
   152      }
   153   }
   154 }
   156 void WindowsDecoder::uninitialize() {
   157   _pfnSymGetSymFromAddr64 = NULL;
   158   _pfnUndecorateSymbolName = NULL;
   159   if (_dbghelp_handle != NULL) {
   160     ::FreeLibrary(_dbghelp_handle);
   161   }
   162   _dbghelp_handle = NULL;
   163 }
   165 bool WindowsDecoder::can_decode_C_frame_in_vm() const {
   166   return  (!has_error() && _can_decode_in_vm);
   167 }
   170 bool WindowsDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* modulepath)  {
   171   if (_pfnSymGetSymFromAddr64 != NULL) {
   172     PIMAGEHLP_SYMBOL64 pSymbol;
   173     char symbolInfo[MAX_PATH + sizeof(IMAGEHLP_SYMBOL64)];
   174     pSymbol = (PIMAGEHLP_SYMBOL64)symbolInfo;
   175     pSymbol->MaxNameLength = MAX_PATH;
   176     pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
   177     DWORD64 displacement;
   178     if (_pfnSymGetSymFromAddr64(::GetCurrentProcess(), (DWORD64)addr, &displacement, pSymbol)) {
   179       if (buf != NULL) {
   180         if (demangle(pSymbol->Name, buf, buflen)) {
   181           jio_snprintf(buf, buflen, "%s", pSymbol->Name);
   182         }
   183       }
   184       if(offset != NULL) *offset = (int)displacement;
   185       return true;
   186     }
   187   }
   188   if (buf != NULL && buflen > 0) buf[0] = '\0';
   189   if (offset != NULL) *offset = -1;
   190   return false;
   191 }
   193 bool WindowsDecoder::demangle(const char* symbol, char *buf, int buflen) {
   194   return _pfnUndecorateSymbolName != NULL &&
   195          _pfnUndecorateSymbolName(symbol, buf, buflen, UNDNAME_COMPLETE);
   196 }

mercurial