1 /*
   2  * Copyright (c) 1997, 2010, 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  */
  24 
  25 #include "precompiled.hpp"
  26 #include "prims/jvm.h"
  27 #include "runtime/os.hpp"
  28 #include "utilities/decoder.hpp"
  29 
  30 HMODULE                   Decoder::_dbghelp_handle = NULL;
  31 bool                      Decoder::_can_decode_in_vm = false;
  32 pfn_SymGetSymFromAddr64   Decoder::_pfnSymGetSymFromAddr64 = NULL;
  33 pfn_UndecorateSymbolName  Decoder::_pfnUndecorateSymbolName = NULL;
  34 
  35 void Decoder::initialize() {
  36   if (!_initialized) {
  37     _initialized = true;
  38 
  39     HINSTANCE handle = os::win32::load_Windows_dll("dbghelp.dll", NULL, 0);
  40     if (!handle) {
  41       _decoder_status = helper_not_found;
  42         return;
  43     }
  44 
  45     _dbghelp_handle = handle;
  46 
  47     pfn_SymSetOptions _pfnSymSetOptions = (pfn_SymSetOptions)::GetProcAddress(handle, "SymSetOptions");
  48     pfn_SymInitialize _pfnSymInitialize = (pfn_SymInitialize)::GetProcAddress(handle, "SymInitialize");
  49     _pfnSymGetSymFromAddr64 = (pfn_SymGetSymFromAddr64)::GetProcAddress(handle, "SymGetSymFromAddr64");
  50     _pfnUndecorateSymbolName = (pfn_UndecorateSymbolName)GetProcAddress(handle, "UnDecorateSymbolName");
  51 
  52     if (_pfnSymSetOptions == NULL || _pfnSymInitialize == NULL || _pfnSymGetSymFromAddr64 == NULL) {
  53       _pfnSymGetSymFromAddr64 = NULL;
  54       _pfnUndecorateSymbolName = NULL;
  55       ::FreeLibrary(handle);
  56       _dbghelp_handle = NULL;
  57       _decoder_status = helper_func_error;
  58       return;
  59     }
  60 
  61     _pfnSymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS);
  62     if (!_pfnSymInitialize(GetCurrentProcess(), NULL, TRUE)) {
  63       _pfnSymGetSymFromAddr64 = NULL;
  64       _pfnUndecorateSymbolName = NULL;
  65       ::FreeLibrary(handle);
  66       _dbghelp_handle = NULL;
  67       _decoder_status = helper_init_error;
  68       return;
  69     }
  70 
  71      // find out if jvm.dll contains private symbols, by decoding
  72      // current function and comparing the result
  73      address addr = (address)Decoder::initialize;
  74      char buf[MAX_PATH];
  75      if (decode(addr, buf, sizeof(buf), NULL) == no_error) {
  76        _can_decode_in_vm = !strcmp(buf, "Decoder::initialize");
  77      }
  78   }
  79 }
  80 
  81 void Decoder::uninitialize() {
  82   assert(_initialized, "Decoder not yet initialized");
  83   _pfnSymGetSymFromAddr64 = NULL;
  84   _pfnUndecorateSymbolName = NULL;
  85   if (_dbghelp_handle != NULL) {
  86     ::FreeLibrary(_dbghelp_handle);
  87   }
  88   _initialized = false;
  89 }
  90 
  91 bool Decoder::can_decode_C_frame_in_vm() {
  92   initialize();
  93   return  _can_decode_in_vm;
  94 }
  95 
  96 
  97 Decoder::decoder_status Decoder::decode(address addr, char *buf, int buflen, int *offset) {
  98   assert(_initialized, "Decoder not yet initialized");
  99   if (_pfnSymGetSymFromAddr64 != NULL) {
 100     PIMAGEHLP_SYMBOL64 pSymbol;
 101     char symbolInfo[MAX_PATH + sizeof(IMAGEHLP_SYMBOL64)];
 102     pSymbol = (PIMAGEHLP_SYMBOL64)symbolInfo;
 103     pSymbol->MaxNameLength = MAX_PATH;
 104     pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
 105     DWORD64 displacement;
 106     if (_pfnSymGetSymFromAddr64(::GetCurrentProcess(), (DWORD64)addr, &displacement, pSymbol)) {
 107       if (buf != NULL) {
 108         if (!demangle(pSymbol->Name, buf, buflen)) {
 109           jio_snprintf(buf, buflen, "%s", pSymbol->Name);
 110         }
 111       }
 112       if (offset != NULL) *offset = (int)displacement;
 113       return no_error;
 114     }
 115   }
 116   return helper_not_found;
 117 }
 118 
 119 bool Decoder::demangle(const char* symbol, char *buf, int buflen) {
 120   assert(_initialized, "Decoder not yet initialized");
 121   return _pfnUndecorateSymbolName != NULL &&
 122          _pfnUndecorateSymbolName(symbol, buf, buflen, UNDNAME_COMPLETE);
 123 }
 124