mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 14:24:46 +02:00
7071311: Decoder enhancement
Made decoder thread-safe Reviewed-by: coleenp, kamg
This commit is contained in:
parent
8efd785f67
commit
43bb0877fc
20 changed files with 471 additions and 275 deletions
31
hotspot/src/os/bsd/vm/decoder_machO.cpp
Normal file
31
hotspot/src/os/bsd/vm/decoder_machO.cpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.hpp"
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include "decoder_machO.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -22,45 +22,21 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "prims/jvm.h"
|
#ifndef OS_BSD_VM_DECODER_MACHO_HPP
|
||||||
#include "utilities/decoder.hpp"
|
#define OS_BSD_VM_DECODER_MACHO_HPP
|
||||||
|
|
||||||
#include <cxxabi.h>
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
|
|
||||||
void Decoder::initialize() {
|
#include "utilities/decoder.hpp"
|
||||||
_initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Decoder::uninitialize() {
|
|
||||||
_initialized = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Decoder::can_decode_C_frame_in_vm() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Decoder::decoder_status Decoder::decode(address addr, const char* filepath, char *buf, int buflen, int *offset) {
|
|
||||||
return symbol_not_found;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Just a placehold for now
|
||||||
|
class MachODecoder: public NullDecoder {
|
||||||
|
public:
|
||||||
|
MachODecoder() { }
|
||||||
|
~MachODecoder() { }
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool Decoder::demangle(const char* symbol, char *buf, int buflen) {
|
#endif // OS_BSD_VM_DECODER_MACHO_HPP
|
||||||
int status;
|
|
||||||
char* result;
|
|
||||||
size_t size = (size_t)buflen;
|
|
||||||
|
|
||||||
// Don't pass buf to __cxa_demangle. In case of the 'buf' is too small,
|
|
||||||
// __cxa_demangle will call system "realloc" for additional memory, which
|
|
||||||
// may use different malloc/realloc mechanism that allocates 'buf'.
|
|
||||||
if ((result = abi::__cxa_demangle(symbol, NULL, NULL, &status)) != NULL) {
|
|
||||||
jio_snprintf(buf, buflen, "%s", result);
|
|
||||||
// call c library's free
|
|
||||||
::free(result);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
|
@ -23,11 +23,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "prims/jvm.h"
|
#include "prims/jvm.h"
|
||||||
#include "utilities/decoder.hpp"
|
#include "utilities/decoder_elf.hpp"
|
||||||
|
|
||||||
#include <cxxabi.h>
|
#include <cxxabi.h>
|
||||||
|
|
||||||
bool Decoder::demangle(const char* symbol, char *buf, int buflen) {
|
bool ElfDecoder::demangle(const char* symbol, char *buf, int buflen) {
|
||||||
int status;
|
int status;
|
||||||
char* result;
|
char* result;
|
||||||
size_t size = (size_t)buflen;
|
size_t size = (size_t)buflen;
|
||||||
|
@ -43,3 +43,4 @@ bool Decoder::demangle(const char* symbol, char *buf, int buflen) {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1732,7 +1732,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||||
return true;
|
return true;
|
||||||
} else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) {
|
} else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) {
|
||||||
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
|
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
|
||||||
dlinfo.dli_fname, buf, buflen, offset) == Decoder::no_error) {
|
buf, buflen, offset, dlinfo.dli_fname)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,11 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "utilities/decoder.hpp"
|
#include "utilities/decoder_elf.hpp"
|
||||||
|
|
||||||
#include <demangle.h>
|
#include <demangle.h>
|
||||||
|
|
||||||
bool Decoder::demangle(const char* symbol, char *buf, int buflen) {
|
bool ElfDecoder::demangle(const char* symbol, char *buf, int buflen) {
|
||||||
return !cplus_demangle(symbol, buf, (size_t)buflen);
|
return !cplus_demangle(symbol, buf, (size_t)buflen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1997,7 +1997,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||||
}
|
}
|
||||||
if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) {
|
if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) {
|
||||||
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
|
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
|
||||||
dlinfo.dli_fname, buf, buflen, offset) == Decoder::no_error) {
|
buf, buflen, offset, dlinfo.dli_fname)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2015,7 +2015,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||||
return true;
|
return true;
|
||||||
} else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) {
|
} else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) {
|
||||||
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
|
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
|
||||||
dlinfo.dli_fname, buf, buflen, offset) == Decoder::no_error) {
|
buf, buflen, offset, dlinfo.dli_fname)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -24,19 +24,21 @@
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "prims/jvm.h"
|
#include "prims/jvm.h"
|
||||||
#include "runtime/os.hpp"
|
#include "decoder_windows.hpp"
|
||||||
#include "utilities/decoder.hpp"
|
|
||||||
|
|
||||||
HMODULE Decoder::_dbghelp_handle = NULL;
|
WindowsDecoder::WindowsDecoder() {
|
||||||
bool Decoder::_can_decode_in_vm = false;
|
_dbghelp_handle = NULL;
|
||||||
pfn_SymGetSymFromAddr64 Decoder::_pfnSymGetSymFromAddr64 = NULL;
|
_can_decode_in_vm = false;
|
||||||
pfn_UndecorateSymbolName Decoder::_pfnUndecorateSymbolName = NULL;
|
_pfnSymGetSymFromAddr64 = NULL;
|
||||||
|
_pfnUndecorateSymbolName = NULL;
|
||||||
|
|
||||||
void Decoder::initialize() {
|
_decoder_status = no_error;
|
||||||
if (!_initialized) {
|
initialize();
|
||||||
_initialized = true;
|
}
|
||||||
|
|
||||||
HINSTANCE handle = os::win32::load_Windows_dll("dbghelp.dll", NULL, 0);
|
void WindowsDecoder::initialize() {
|
||||||
|
if (!has_error() && _dbghelp_handle == NULL) {
|
||||||
|
HMODULE handle = ::LoadLibrary("dbghelp.dll");
|
||||||
if (!handle) {
|
if (!handle) {
|
||||||
_decoder_status = helper_not_found;
|
_decoder_status = helper_not_found;
|
||||||
return;
|
return;
|
||||||
|
@ -70,32 +72,29 @@ void Decoder::initialize() {
|
||||||
|
|
||||||
// find out if jvm.dll contains private symbols, by decoding
|
// find out if jvm.dll contains private symbols, by decoding
|
||||||
// current function and comparing the result
|
// current function and comparing the result
|
||||||
address addr = (address)Decoder::initialize;
|
address addr = (address)Decoder::decode;
|
||||||
char buf[MAX_PATH];
|
char buf[MAX_PATH];
|
||||||
if (decode(addr, buf, sizeof(buf), NULL) == no_error) {
|
if (decode(addr, buf, sizeof(buf), NULL)) {
|
||||||
_can_decode_in_vm = !strcmp(buf, "Decoder::initialize");
|
_can_decode_in_vm = !strcmp(buf, "Decoder::decode");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Decoder::uninitialize() {
|
void WindowsDecoder::uninitialize() {
|
||||||
assert(_initialized, "Decoder not yet initialized");
|
|
||||||
_pfnSymGetSymFromAddr64 = NULL;
|
_pfnSymGetSymFromAddr64 = NULL;
|
||||||
_pfnUndecorateSymbolName = NULL;
|
_pfnUndecorateSymbolName = NULL;
|
||||||
if (_dbghelp_handle != NULL) {
|
if (_dbghelp_handle != NULL) {
|
||||||
::FreeLibrary(_dbghelp_handle);
|
::FreeLibrary(_dbghelp_handle);
|
||||||
}
|
}
|
||||||
_initialized = false;
|
_dbghelp_handle = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Decoder::can_decode_C_frame_in_vm() {
|
bool WindowsDecoder::can_decode_C_frame_in_vm() const {
|
||||||
initialize();
|
return (!has_error() && _can_decode_in_vm);
|
||||||
return _can_decode_in_vm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Decoder::decoder_status Decoder::decode(address addr, char *buf, int buflen, int *offset) {
|
bool WindowsDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* modulepath) {
|
||||||
assert(_initialized, "Decoder not yet initialized");
|
|
||||||
if (_pfnSymGetSymFromAddr64 != NULL) {
|
if (_pfnSymGetSymFromAddr64 != NULL) {
|
||||||
PIMAGEHLP_SYMBOL64 pSymbol;
|
PIMAGEHLP_SYMBOL64 pSymbol;
|
||||||
char symbolInfo[MAX_PATH + sizeof(IMAGEHLP_SYMBOL64)];
|
char symbolInfo[MAX_PATH + sizeof(IMAGEHLP_SYMBOL64)];
|
||||||
|
@ -105,19 +104,20 @@ Decoder::decoder_status Decoder::decode(address addr, char *buf, int buflen, int
|
||||||
DWORD64 displacement;
|
DWORD64 displacement;
|
||||||
if (_pfnSymGetSymFromAddr64(::GetCurrentProcess(), (DWORD64)addr, &displacement, pSymbol)) {
|
if (_pfnSymGetSymFromAddr64(::GetCurrentProcess(), (DWORD64)addr, &displacement, pSymbol)) {
|
||||||
if (buf != NULL) {
|
if (buf != NULL) {
|
||||||
if (!demangle(pSymbol->Name, buf, buflen)) {
|
if (demangle(pSymbol->Name, buf, buflen)) {
|
||||||
jio_snprintf(buf, buflen, "%s", pSymbol->Name);
|
jio_snprintf(buf, buflen, "%s", pSymbol->Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(offset != NULL) *offset = (int)displacement;
|
if(offset != NULL) *offset = (int)displacement;
|
||||||
return no_error;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return helper_not_found;
|
if (buf != NULL && buflen > 0) buf[0] = '\0';
|
||||||
|
if (offset != NULL) *offset = -1;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Decoder::demangle(const char* symbol, char *buf, int buflen) {
|
bool WindowsDecoder::demangle(const char* symbol, char *buf, int buflen) {
|
||||||
assert(_initialized, "Decoder not yet initialized");
|
|
||||||
return _pfnUndecorateSymbolName != NULL &&
|
return _pfnUndecorateSymbolName != NULL &&
|
||||||
_pfnUndecorateSymbolName(symbol, buf, buflen, UNDNAME_COMPLETE);
|
_pfnUndecorateSymbolName(symbol, buf, buflen, UNDNAME_COMPLETE);
|
||||||
}
|
}
|
||||||
|
|
61
hotspot/src/os/windows/vm/decoder_windows.hpp
Normal file
61
hotspot/src/os/windows/vm/decoder_windows.hpp
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OS_WINDOWS_VM_DECODER_WINDOWS_HPP
|
||||||
|
#define OS_WINDOWS_VM_DECIDER_WINDOWS_HPP
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <imagehlp.h>
|
||||||
|
|
||||||
|
#include "utilities/decoder.hpp"
|
||||||
|
|
||||||
|
// functions needed for decoding symbols
|
||||||
|
typedef DWORD (WINAPI *pfn_SymSetOptions)(DWORD);
|
||||||
|
typedef BOOL (WINAPI *pfn_SymInitialize)(HANDLE, PCTSTR, BOOL);
|
||||||
|
typedef BOOL (WINAPI *pfn_SymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64);
|
||||||
|
typedef DWORD (WINAPI *pfn_UndecorateSymbolName)(const char*, char*, DWORD, DWORD);
|
||||||
|
|
||||||
|
class WindowsDecoder: public NullDecoder {
|
||||||
|
|
||||||
|
public:
|
||||||
|
WindowsDecoder();
|
||||||
|
~WindowsDecoder() { uninitialize(); };
|
||||||
|
|
||||||
|
bool can_decode_C_frame_in_vm() const;
|
||||||
|
bool demangle(const char* symbol, char *buf, int buflen);
|
||||||
|
bool decode(address addr, char *buf, int buflen, int* offset, const char* modulepath = NULL);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initialize();
|
||||||
|
void uninitialize();
|
||||||
|
|
||||||
|
private:
|
||||||
|
HMODULE _dbghelp_handle;
|
||||||
|
bool _can_decode_in_vm;
|
||||||
|
pfn_SymGetSymFromAddr64 _pfnSymGetSymFromAddr64;
|
||||||
|
pfn_UndecorateSymbolName _pfnUndecorateSymbolName;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // OS_WINDOWS_VM_DECODER_WINDOWS_HPP
|
||||||
|
|
|
@ -1391,7 +1391,7 @@ bool os::dll_address_to_library_name(address addr, char* buf,
|
||||||
|
|
||||||
bool os::dll_address_to_function_name(address addr, char *buf,
|
bool os::dll_address_to_function_name(address addr, char *buf,
|
||||||
int buflen, int *offset) {
|
int buflen, int *offset) {
|
||||||
if (Decoder::decode(addr, buf, buflen, offset) == Decoder::no_error) {
|
if (Decoder::decode(addr, buf, buflen, offset)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (offset != NULL) *offset = -1;
|
if (offset != NULL) *offset = -1;
|
||||||
|
|
|
@ -24,80 +24,85 @@
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "prims/jvm.h"
|
#include "prims/jvm.h"
|
||||||
|
#include "runtime/mutexLocker.hpp"
|
||||||
#include "utilities/decoder.hpp"
|
#include "utilities/decoder.hpp"
|
||||||
|
|
||||||
Decoder::decoder_status Decoder::_decoder_status = Decoder::no_error;
|
#if defined(_WINDOWS)
|
||||||
bool Decoder::_initialized = false;
|
#include "decoder_windows.hpp"
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
#include "decoder_machO.hpp"
|
||||||
|
#else
|
||||||
|
#include "decoder_elf.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(_WINDOWS) && !defined(__APPLE__)
|
NullDecoder* Decoder::_decoder = NULL;
|
||||||
|
NullDecoder Decoder::_do_nothing_decoder;
|
||||||
|
Mutex* Decoder::_decoder_lock = new Mutex(Mutex::safepoint,
|
||||||
|
"DecoderLock");
|
||||||
|
|
||||||
// Implementation of common functionalities among Solaris and Linux
|
// _decoder_lock should already acquired before enter this method
|
||||||
#include "utilities/elfFile.hpp"
|
NullDecoder* Decoder::get_decoder() {
|
||||||
|
assert(_decoder_lock != NULL && _decoder_lock->owned_by_self(),
|
||||||
|
"Require DecoderLock to enter");
|
||||||
|
|
||||||
ElfFile* Decoder::_opened_elf_files = NULL;
|
if (_decoder != NULL) {
|
||||||
|
return _decoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decoder is a secondary service. Although, it is good to have,
|
||||||
|
// but we can live without it.
|
||||||
|
#if defined(_WINDOWS)
|
||||||
|
_decoder = new (std::nothrow) WindowsDecoder();
|
||||||
|
#elif defined (__APPLE__)
|
||||||
|
_decoder = new (std::nothrow)MachODecoder();
|
||||||
|
#else
|
||||||
|
_decoder = new (std::nothrow)ElfDecoder();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (_decoder == NULL || _decoder->has_error()) {
|
||||||
|
if (_decoder != NULL) {
|
||||||
|
delete _decoder;
|
||||||
|
}
|
||||||
|
_decoder = &_do_nothing_decoder;
|
||||||
|
}
|
||||||
|
return _decoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Decoder::decode(address addr, char* buf, int buflen, int* offset, const char* modulepath) {
|
||||||
|
assert(_decoder_lock != NULL, "Just check");
|
||||||
|
MutexLockerEx locker(_decoder_lock, true);
|
||||||
|
NullDecoder* decoder = get_decoder();
|
||||||
|
assert(decoder != NULL, "null decoder");
|
||||||
|
|
||||||
|
return decoder->decode(addr, buf, buflen, offset, modulepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Decoder::demangle(const char* symbol, char* buf, int buflen) {
|
||||||
|
assert(_decoder_lock != NULL, "Just check");
|
||||||
|
MutexLockerEx locker(_decoder_lock, true);
|
||||||
|
NullDecoder* decoder = get_decoder();
|
||||||
|
assert(decoder != NULL, "null decoder");
|
||||||
|
return decoder->demangle(symbol, buf, buflen);
|
||||||
|
}
|
||||||
|
|
||||||
bool Decoder::can_decode_C_frame_in_vm() {
|
bool Decoder::can_decode_C_frame_in_vm() {
|
||||||
return true;
|
assert(_decoder_lock != NULL, "Just check");
|
||||||
|
MutexLockerEx locker(_decoder_lock, true);
|
||||||
|
NullDecoder* decoder = get_decoder();
|
||||||
|
assert(decoder != NULL, "null decoder");
|
||||||
|
return decoder->can_decode_C_frame_in_vm();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Decoder::initialize() {
|
// shutdown real decoder and replace it with
|
||||||
_initialized = true;
|
// _do_nothing_decoder
|
||||||
|
void Decoder::shutdown() {
|
||||||
|
assert(_decoder_lock != NULL, "Just check");
|
||||||
|
MutexLockerEx locker(_decoder_lock, true);
|
||||||
|
|
||||||
|
if (_decoder != NULL && _decoder != &_do_nothing_decoder) {
|
||||||
|
delete _decoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Decoder::uninitialize() {
|
_decoder = &_do_nothing_decoder;
|
||||||
if (_opened_elf_files != NULL) {
|
|
||||||
delete _opened_elf_files;
|
|
||||||
_opened_elf_files = NULL;
|
|
||||||
}
|
|
||||||
_initialized = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Decoder::decoder_status Decoder::decode(address addr, const char* filepath, char *buf, int buflen, int *offset) {
|
|
||||||
if (_decoder_status != no_error) {
|
|
||||||
return _decoder_status;
|
|
||||||
}
|
|
||||||
|
|
||||||
ElfFile* file = get_elf_file(filepath);
|
|
||||||
if (_decoder_status != no_error) {
|
|
||||||
return _decoder_status;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* symbol = file->decode(addr, offset);
|
|
||||||
if (file->get_status() == out_of_memory) {
|
|
||||||
_decoder_status = out_of_memory;
|
|
||||||
return _decoder_status;
|
|
||||||
} else if (symbol != NULL) {
|
|
||||||
if (!demangle(symbol, buf, buflen)) {
|
|
||||||
jio_snprintf(buf, buflen, "%s", symbol);
|
|
||||||
}
|
|
||||||
return no_error;
|
|
||||||
} else {
|
|
||||||
return symbol_not_found;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ElfFile* Decoder::get_elf_file(const char* filepath) {
|
|
||||||
if (_decoder_status != no_error) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
ElfFile* file = _opened_elf_files;
|
|
||||||
while (file != NULL) {
|
|
||||||
if (file->same_elf_file(filepath)) {
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
file = file->m_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
file = new ElfFile(filepath);
|
|
||||||
if (file == NULL) {
|
|
||||||
_decoder_status = out_of_memory;
|
|
||||||
}
|
|
||||||
if (_opened_elf_files != NULL) {
|
|
||||||
file->m_next = _opened_elf_files;
|
|
||||||
}
|
|
||||||
|
|
||||||
_opened_elf_files = file;
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -23,83 +23,78 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef __DECODER_HPP
|
#ifndef SHARE_VM_UTILITIES_DECODER_HPP
|
||||||
#define __DECODER_HPP
|
#define SHARE_VM_UTILITIES_DECODER_HPP
|
||||||
|
|
||||||
#include "memory/allocation.hpp"
|
#include "memory/allocation.hpp"
|
||||||
|
#include "runtime/mutex.hpp"
|
||||||
|
|
||||||
#ifdef _WINDOWS
|
class NullDecoder: public CHeapObj {
|
||||||
#include <windows.h>
|
|
||||||
#include <imagehlp.h>
|
|
||||||
|
|
||||||
// functions needed for decoding symbols
|
|
||||||
typedef DWORD (WINAPI *pfn_SymSetOptions)(DWORD);
|
|
||||||
typedef BOOL (WINAPI *pfn_SymInitialize)(HANDLE, PCTSTR, BOOL);
|
|
||||||
typedef BOOL (WINAPI *pfn_SymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64);
|
|
||||||
typedef DWORD (WINAPI *pfn_UndecorateSymbolName)(const char*, char*, DWORD, DWORD);
|
|
||||||
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
class ElfFile;
|
|
||||||
|
|
||||||
#endif // _WINDOWS
|
|
||||||
|
|
||||||
|
|
||||||
class Decoder: public StackObj {
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// status code for decoding native C frame
|
// status code for decoding native C frame
|
||||||
enum decoder_status {
|
enum decoder_status {
|
||||||
no_error, // successfully decoded frames
|
not_available = -10, // real decoder is not available
|
||||||
|
no_error = 0, // successfully decoded frames
|
||||||
out_of_memory, // out of memory
|
out_of_memory, // out of memory
|
||||||
file_invalid, // invalid elf file
|
file_invalid, // invalid elf file
|
||||||
file_not_found, // could not found symbol file (on windows), such as jvm.pdb or jvm.map
|
file_not_found, // could not found symbol file (on windows), such as jvm.pdb or jvm.map
|
||||||
helper_not_found, // could not load dbghelp.dll (Windows only)
|
helper_not_found, // could not load dbghelp.dll (Windows only)
|
||||||
helper_func_error, // decoding functions not found (Windows only)
|
helper_func_error, // decoding functions not found (Windows only)
|
||||||
helper_init_error, // SymInitialize failed (Windows only)
|
helper_init_error // SymInitialize failed (Windows only)
|
||||||
symbol_not_found // could not find the symbol
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
NullDecoder() {
|
||||||
Decoder() { initialize(); };
|
_decoder_status = not_available;
|
||||||
~Decoder() { uninitialize(); };
|
}
|
||||||
|
|
||||||
|
~NullDecoder() {};
|
||||||
|
|
||||||
|
virtual bool decode(address pc, char* buf, int buflen, int* offset,
|
||||||
|
const char* modulepath = NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool demangle(const char* symbol, char* buf, int buflen) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool can_decode_C_frame_in_vm() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual decoder_status status() const {
|
||||||
|
return _decoder_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool has_error() const {
|
||||||
|
return is_error(_decoder_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_error(decoder_status status) {
|
||||||
|
return (status > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
decoder_status _decoder_status;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Decoder: AllStatic {
|
||||||
|
public:
|
||||||
|
static bool decode(address pc, char* buf, int buflen, int* offset, const char* modulepath = NULL);
|
||||||
|
static bool demangle(const char* symbol, char* buf, int buflen);
|
||||||
static bool can_decode_C_frame_in_vm();
|
static bool can_decode_C_frame_in_vm();
|
||||||
|
|
||||||
static void initialize();
|
static void shutdown();
|
||||||
static void uninitialize();
|
protected:
|
||||||
|
static NullDecoder* get_decoder();
|
||||||
#ifdef _WINDOWS
|
|
||||||
static decoder_status decode(address addr, char *buf, int buflen, int *offset);
|
|
||||||
#else
|
|
||||||
static decoder_status decode(address addr, const char* filepath, char *buf, int buflen, int *offset);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static bool demangle(const char* symbol, char *buf, int buflen);
|
|
||||||
|
|
||||||
static decoder_status get_status() { return _decoder_status; };
|
|
||||||
|
|
||||||
#if !defined(_WINDOWS) && !defined(__APPLE__)
|
|
||||||
private:
|
|
||||||
static ElfFile* get_elf_file(const char* filepath);
|
|
||||||
#endif // _WINDOWS
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static decoder_status _decoder_status;
|
static NullDecoder* _decoder;
|
||||||
static bool _initialized;
|
static NullDecoder _do_nothing_decoder;
|
||||||
|
|
||||||
#ifdef _WINDOWS
|
protected:
|
||||||
static HMODULE _dbghelp_handle;
|
static Mutex* _decoder_lock;
|
||||||
static bool _can_decode_in_vm;
|
|
||||||
static pfn_SymGetSymFromAddr64 _pfnSymGetSymFromAddr64;
|
|
||||||
static pfn_UndecorateSymbolName _pfnUndecorateSymbolName;
|
|
||||||
#elif __APPLE__
|
|
||||||
#else
|
|
||||||
static ElfFile* _opened_elf_files;
|
|
||||||
#endif // _WINDOWS
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __DECODER_HPP
|
#endif // SHARE_VM_UTILITIES_DECODER_HPP
|
||||||
|
|
76
hotspot/src/share/vm/utilities/decoder_elf.cpp
Normal file
76
hotspot/src/share/vm/utilities/decoder_elf.cpp
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.hpp"
|
||||||
|
|
||||||
|
#if !defined(_WINDOWS) && !defined(__APPLE__)
|
||||||
|
#include "decoder_elf.hpp"
|
||||||
|
|
||||||
|
ElfDecoder::~ElfDecoder() {
|
||||||
|
if (_opened_elf_files != NULL) {
|
||||||
|
delete _opened_elf_files;
|
||||||
|
_opened_elf_files = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ElfDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* filepath) {
|
||||||
|
assert(filepath, "null file path");
|
||||||
|
assert(buf != NULL && buflen > 0, "Invalid buffer");
|
||||||
|
if (has_error()) return false;
|
||||||
|
ElfFile* file = get_elf_file(filepath);
|
||||||
|
if (file == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file->decode(addr, buf, buflen, offset)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (buf[0] != '\0') {
|
||||||
|
demangle(buf, buf, buflen);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ElfFile* ElfDecoder::get_elf_file(const char* filepath) {
|
||||||
|
ElfFile* file;
|
||||||
|
|
||||||
|
file = _opened_elf_files;
|
||||||
|
while (file != NULL) {
|
||||||
|
if (file->same_elf_file(filepath)) {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
file = file->next();
|
||||||
|
}
|
||||||
|
|
||||||
|
file = new (std::nothrow)ElfFile(filepath);
|
||||||
|
if (file != NULL) {
|
||||||
|
if (_opened_elf_files != NULL) {
|
||||||
|
file->set_next(_opened_elf_files);
|
||||||
|
}
|
||||||
|
_opened_elf_files = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
#endif
|
55
hotspot/src/share/vm/utilities/decoder_elf.hpp
Normal file
55
hotspot/src/share/vm/utilities/decoder_elf.hpp
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHARE_VM_UTILITIES_DECODER_ELF_HPP
|
||||||
|
#define SHARE_VM_UTILITIES_DECODER_ELF_HPP
|
||||||
|
|
||||||
|
#if !defined(_WINDOWS) && !defined(__APPLE__)
|
||||||
|
|
||||||
|
#include "utilities/decoder.hpp"
|
||||||
|
#include "utilities/elfFile.hpp"
|
||||||
|
|
||||||
|
class ElfDecoder: public NullDecoder {
|
||||||
|
|
||||||
|
public:
|
||||||
|
ElfDecoder() {
|
||||||
|
_opened_elf_files = NULL;
|
||||||
|
_decoder_status = no_error;
|
||||||
|
}
|
||||||
|
~ElfDecoder();
|
||||||
|
|
||||||
|
bool can_decode_C_frame_in_vm() const { return true; }
|
||||||
|
|
||||||
|
bool demangle(const char* symbol, char *buf, int buflen);
|
||||||
|
bool decode(address addr, char *buf, int buflen, int* offset, const char* filepath = NULL);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ElfFile* get_elf_file(const char* filepath);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ElfFile* _opened_elf_files;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif // SHARE_VM_UTILITIES_DECODER_ELF_HPP
|
|
@ -44,7 +44,7 @@ ElfFile::ElfFile(const char* filepath) {
|
||||||
m_string_tables = NULL;
|
m_string_tables = NULL;
|
||||||
m_symbol_tables = NULL;
|
m_symbol_tables = NULL;
|
||||||
m_next = NULL;
|
m_next = NULL;
|
||||||
m_status = Decoder::no_error;
|
m_status = NullDecoder::no_error;
|
||||||
|
|
||||||
int len = strlen(filepath) + 1;
|
int len = strlen(filepath) + 1;
|
||||||
m_filepath = (const char*)os::malloc(len * sizeof(char));
|
m_filepath = (const char*)os::malloc(len * sizeof(char));
|
||||||
|
@ -54,10 +54,10 @@ ElfFile::ElfFile(const char* filepath) {
|
||||||
if (m_file != NULL) {
|
if (m_file != NULL) {
|
||||||
load_tables();
|
load_tables();
|
||||||
} else {
|
} else {
|
||||||
m_status = Decoder::file_not_found;
|
m_status = NullDecoder::file_not_found;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_status = Decoder::out_of_memory;
|
m_status = NullDecoder::out_of_memory;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,41 +96,41 @@ bool ElfFile::is_elf_file(Elf_Ehdr& hdr) {
|
||||||
|
|
||||||
bool ElfFile::load_tables() {
|
bool ElfFile::load_tables() {
|
||||||
assert(m_file, "file not open");
|
assert(m_file, "file not open");
|
||||||
assert(m_status == Decoder::no_error, "already in error");
|
assert(!NullDecoder::is_error(m_status), "already in error");
|
||||||
|
|
||||||
// read elf file header
|
// read elf file header
|
||||||
if (fread(&m_elfHdr, sizeof(m_elfHdr), 1, m_file) != 1) {
|
if (fread(&m_elfHdr, sizeof(m_elfHdr), 1, m_file) != 1) {
|
||||||
m_status = Decoder::file_invalid;
|
m_status = NullDecoder::file_invalid;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_elf_file(m_elfHdr)) {
|
if (!is_elf_file(m_elfHdr)) {
|
||||||
m_status = Decoder::file_invalid;
|
m_status = NullDecoder::file_invalid;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// walk elf file's section headers, and load string tables
|
// walk elf file's section headers, and load string tables
|
||||||
Elf_Shdr shdr;
|
Elf_Shdr shdr;
|
||||||
if (!fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) {
|
if (!fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) {
|
||||||
if (m_status != Decoder::no_error) return false;
|
if (NullDecoder::is_error(m_status)) return false;
|
||||||
|
|
||||||
for (int index = 0; index < m_elfHdr.e_shnum; index ++) {
|
for (int index = 0; index < m_elfHdr.e_shnum; index ++) {
|
||||||
if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) {
|
if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) {
|
||||||
m_status = Decoder::file_invalid;
|
m_status = NullDecoder::file_invalid;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// string table
|
// string table
|
||||||
if (shdr.sh_type == SHT_STRTAB) {
|
if (shdr.sh_type == SHT_STRTAB) {
|
||||||
ElfStringTable* table = new (std::nothrow) ElfStringTable(m_file, shdr, index);
|
ElfStringTable* table = new (std::nothrow) ElfStringTable(m_file, shdr, index);
|
||||||
if (table == NULL) {
|
if (table == NULL) {
|
||||||
m_status = Decoder::out_of_memory;
|
m_status = NullDecoder::out_of_memory;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
add_string_table(table);
|
add_string_table(table);
|
||||||
} else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
|
} else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
|
||||||
ElfSymbolTable* table = new (std::nothrow) ElfSymbolTable(m_file, shdr);
|
ElfSymbolTable* table = new (std::nothrow) ElfSymbolTable(m_file, shdr);
|
||||||
if (table == NULL) {
|
if (table == NULL) {
|
||||||
m_status = Decoder::out_of_memory;
|
m_status = NullDecoder::out_of_memory;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
add_symbol_table(table);
|
add_symbol_table(table);
|
||||||
|
@ -140,32 +140,33 @@ bool ElfFile::load_tables() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* ElfFile::decode(address addr, int* offset) {
|
bool ElfFile::decode(address addr, char* buf, int buflen, int* offset) {
|
||||||
// something already went wrong, just give up
|
// something already went wrong, just give up
|
||||||
if (m_status != Decoder::no_error) {
|
if (NullDecoder::is_error(m_status)) {
|
||||||
return NULL;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ElfSymbolTable* symbol_table = m_symbol_tables;
|
ElfSymbolTable* symbol_table = m_symbol_tables;
|
||||||
int string_table_index;
|
int string_table_index;
|
||||||
int pos_in_string_table;
|
int pos_in_string_table;
|
||||||
int off = INT_MAX;
|
int off = INT_MAX;
|
||||||
bool found_symbol = false;
|
bool found_symbol = false;
|
||||||
while (symbol_table != NULL) {
|
while (symbol_table != NULL) {
|
||||||
if (Decoder::no_error == symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off)) {
|
if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off)) {
|
||||||
found_symbol = true;
|
found_symbol = true;
|
||||||
}
|
}
|
||||||
symbol_table = symbol_table->m_next;
|
symbol_table = symbol_table->m_next;
|
||||||
}
|
}
|
||||||
if (!found_symbol) return NULL;
|
if (!found_symbol) return false;
|
||||||
|
|
||||||
ElfStringTable* string_table = get_string_table(string_table_index);
|
ElfStringTable* string_table = get_string_table(string_table_index);
|
||||||
|
|
||||||
if (string_table == NULL) {
|
if (string_table == NULL) {
|
||||||
m_status = Decoder::file_invalid;
|
m_status = NullDecoder::file_invalid;
|
||||||
return NULL;
|
return false;
|
||||||
}
|
}
|
||||||
if (offset) *offset = off;
|
if (offset) *offset = off;
|
||||||
return string_table->string_at(pos_in_string_table);
|
|
||||||
|
return string_table->string_at(pos_in_string_table, buf, buflen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -22,8 +22,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __ELF_FILE_HPP
|
#ifndef SHARE_VM_UTILITIES_ELF_FILE_HPP
|
||||||
#define __ELF_FILE_HPP
|
#define SHARE_VM_UTILITIES_ELF_FILE_HPP
|
||||||
|
|
||||||
#if !defined(_WINDOWS) && !defined(__APPLE__)
|
#if !defined(_WINDOWS) && !defined(__APPLE__)
|
||||||
|
|
||||||
|
@ -83,12 +83,12 @@ class ElfSymbolTable;
|
||||||
// part of code to be very defensive, and bait out if anything went wrong.
|
// part of code to be very defensive, and bait out if anything went wrong.
|
||||||
|
|
||||||
class ElfFile: public CHeapObj {
|
class ElfFile: public CHeapObj {
|
||||||
friend class Decoder;
|
friend class ElfDecoder;
|
||||||
public:
|
public:
|
||||||
ElfFile(const char* filepath);
|
ElfFile(const char* filepath);
|
||||||
~ElfFile();
|
~ElfFile();
|
||||||
|
|
||||||
const char* decode(address addr, int* offset);
|
bool decode(address addr, char* buf, int buflen, int* offset);
|
||||||
const char* filepath() {
|
const char* filepath() {
|
||||||
return m_filepath;
|
return m_filepath;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ class ElfFile: public CHeapObj {
|
||||||
return (m_filepath && !strcmp(filepath, m_filepath));
|
return (m_filepath && !strcmp(filepath, m_filepath));
|
||||||
}
|
}
|
||||||
|
|
||||||
Decoder::decoder_status get_status() {
|
NullDecoder::decoder_status get_status() {
|
||||||
return m_status;
|
return m_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,8 +119,9 @@ class ElfFile: public CHeapObj {
|
||||||
// return a string table at specified section index
|
// return a string table at specified section index
|
||||||
ElfStringTable* get_string_table(int index);
|
ElfStringTable* get_string_table(int index);
|
||||||
|
|
||||||
// look up an address and return the nearest symbol
|
protected:
|
||||||
const char* look_up(Elf_Shdr shdr, address addr, int* offset);
|
ElfFile* next() const { return m_next; }
|
||||||
|
void set_next(ElfFile* file) { m_next = file; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ElfFile* m_next;
|
ElfFile* m_next;
|
||||||
|
@ -139,9 +140,9 @@ class ElfFile: public CHeapObj {
|
||||||
// string tables
|
// string tables
|
||||||
ElfStringTable* m_string_tables;
|
ElfStringTable* m_string_tables;
|
||||||
|
|
||||||
Decoder::decoder_status m_status;
|
NullDecoder::decoder_status m_status;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _WINDOWS
|
#endif // _WINDOWS
|
||||||
|
|
||||||
#endif // __ELF_FILE_HPP
|
#endif // SHARE_VM_UTILITIES_ELF_FILE_HPP
|
||||||
|
|
|
@ -38,7 +38,7 @@ ElfStringTable::ElfStringTable(FILE* file, Elf_Shdr shdr, int index) {
|
||||||
m_index = index;
|
m_index = index;
|
||||||
m_next = NULL;
|
m_next = NULL;
|
||||||
m_file = file;
|
m_file = file;
|
||||||
m_status = Decoder::no_error;
|
m_status = NullDecoder::no_error;
|
||||||
|
|
||||||
// try to load the string table
|
// try to load the string table
|
||||||
long cur_offset = ftell(file);
|
long cur_offset = ftell(file);
|
||||||
|
@ -48,7 +48,7 @@ ElfStringTable::ElfStringTable(FILE* file, Elf_Shdr shdr, int index) {
|
||||||
if (fseek(file, shdr.sh_offset, SEEK_SET) ||
|
if (fseek(file, shdr.sh_offset, SEEK_SET) ||
|
||||||
fread((void*)m_table, shdr.sh_size, 1, file) != 1 ||
|
fread((void*)m_table, shdr.sh_size, 1, file) != 1 ||
|
||||||
fseek(file, cur_offset, SEEK_SET)) {
|
fseek(file, cur_offset, SEEK_SET)) {
|
||||||
m_status = Decoder::file_invalid;
|
m_status = NullDecoder::file_invalid;
|
||||||
os::free((void*)m_table);
|
os::free((void*)m_table);
|
||||||
m_table = NULL;
|
m_table = NULL;
|
||||||
}
|
}
|
||||||
|
@ -67,22 +67,23 @@ ElfStringTable::~ElfStringTable() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* ElfStringTable::string_at(int pos) {
|
bool ElfStringTable::string_at(int pos, char* buf, int buflen) {
|
||||||
if (m_status != Decoder::no_error) {
|
if (NullDecoder::is_error(m_status)) {
|
||||||
return NULL;
|
return false;
|
||||||
}
|
}
|
||||||
if (m_table != NULL) {
|
if (m_table != NULL) {
|
||||||
return (const char*)(m_table + pos);
|
jio_snprintf(buf, buflen, "%s", (const char*)(m_table + pos));
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
long cur_pos = ftell(m_file);
|
long cur_pos = ftell(m_file);
|
||||||
if (cur_pos == -1 ||
|
if (cur_pos == -1 ||
|
||||||
fseek(m_file, m_shdr.sh_offset + pos, SEEK_SET) ||
|
fseek(m_file, m_shdr.sh_offset + pos, SEEK_SET) ||
|
||||||
fread(m_symbol, 1, MAX_SYMBOL_LEN, m_file) <= 0 ||
|
fread(buf, 1, buflen, m_file) <= 0 ||
|
||||||
fseek(m_file, cur_pos, SEEK_SET)) {
|
fseek(m_file, cur_pos, SEEK_SET)) {
|
||||||
m_status = Decoder::file_invalid;
|
m_status = NullDecoder::file_invalid;
|
||||||
return NULL;
|
return false;
|
||||||
}
|
}
|
||||||
return (const char*)m_symbol;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -22,8 +22,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __ELF_STRING_TABLE_HPP
|
#ifndef SHARE_VM_UTILITIES_ELF_STRING_TABLE_HPP
|
||||||
#define __ELF_STRING_TABLE_HPP
|
#define SHARE_VM_UTILITIES_ELF_STRING_TABLE_HPP
|
||||||
|
|
||||||
#if !defined(_WINDOWS) && !defined(__APPLE__)
|
#if !defined(_WINDOWS) && !defined(__APPLE__)
|
||||||
|
|
||||||
|
@ -35,9 +35,6 @@
|
||||||
// The string table represents a string table section in an elf file.
|
// The string table represents a string table section in an elf file.
|
||||||
// Whenever there is enough memory, it will load whole string table as
|
// Whenever there is enough memory, it will load whole string table as
|
||||||
// one blob. Otherwise, it will load string from file when requested.
|
// one blob. Otherwise, it will load string from file when requested.
|
||||||
|
|
||||||
#define MAX_SYMBOL_LEN 256
|
|
||||||
|
|
||||||
class ElfStringTable: CHeapObj {
|
class ElfStringTable: CHeapObj {
|
||||||
friend class ElfFile;
|
friend class ElfFile;
|
||||||
public:
|
public:
|
||||||
|
@ -48,10 +45,10 @@ class ElfStringTable: CHeapObj {
|
||||||
int index() { return m_index; };
|
int index() { return m_index; };
|
||||||
|
|
||||||
// get string at specified offset
|
// get string at specified offset
|
||||||
const char* string_at(int offset);
|
bool string_at(int offset, char* buf, int buflen);
|
||||||
|
|
||||||
// get status code
|
// get status code
|
||||||
Decoder::decoder_status get_status() { return m_status; };
|
NullDecoder::decoder_status get_status() { return m_status; };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ElfStringTable* m_next;
|
ElfStringTable* m_next;
|
||||||
|
@ -69,13 +66,10 @@ class ElfStringTable: CHeapObj {
|
||||||
// section header
|
// section header
|
||||||
Elf_Shdr m_shdr;
|
Elf_Shdr m_shdr;
|
||||||
|
|
||||||
// buffer for reading individual string
|
|
||||||
char m_symbol[MAX_SYMBOL_LEN];
|
|
||||||
|
|
||||||
// error code
|
// error code
|
||||||
Decoder::decoder_status m_status;
|
NullDecoder::decoder_status m_status;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _WINDOWS
|
#endif // _WINDOWS and _APPLE
|
||||||
|
|
||||||
#endif // __ELF_STRING_TABLE_HPP
|
#endif // SHARE_VM_UTILITIES_ELF_STRING_TABLE_HPP
|
||||||
|
|
|
@ -34,7 +34,7 @@ ElfSymbolTable::ElfSymbolTable(FILE* file, Elf_Shdr shdr) {
|
||||||
m_symbols = NULL;
|
m_symbols = NULL;
|
||||||
m_next = NULL;
|
m_next = NULL;
|
||||||
m_file = file;
|
m_file = file;
|
||||||
m_status = Decoder::no_error;
|
m_status = NullDecoder::no_error;
|
||||||
|
|
||||||
// try to load the string table
|
// try to load the string table
|
||||||
long cur_offset = ftell(file);
|
long cur_offset = ftell(file);
|
||||||
|
@ -45,16 +45,16 @@ ElfSymbolTable::ElfSymbolTable(FILE* file, Elf_Shdr shdr) {
|
||||||
if (fseek(file, shdr.sh_offset, SEEK_SET) ||
|
if (fseek(file, shdr.sh_offset, SEEK_SET) ||
|
||||||
fread((void*)m_symbols, shdr.sh_size, 1, file) != 1 ||
|
fread((void*)m_symbols, shdr.sh_size, 1, file) != 1 ||
|
||||||
fseek(file, cur_offset, SEEK_SET)) {
|
fseek(file, cur_offset, SEEK_SET)) {
|
||||||
m_status = Decoder::file_invalid;
|
m_status = NullDecoder::file_invalid;
|
||||||
os::free(m_symbols);
|
os::free(m_symbols);
|
||||||
m_symbols = NULL;
|
m_symbols = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_status == Decoder::no_error) {
|
if (!NullDecoder::is_error(m_status)) {
|
||||||
memcpy(&m_shdr, &shdr, sizeof(Elf_Shdr));
|
memcpy(&m_shdr, &shdr, sizeof(Elf_Shdr));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_status = Decoder::file_invalid;
|
m_status = NullDecoder::file_invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,13 +68,13 @@ ElfSymbolTable::~ElfSymbolTable() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Decoder::decoder_status ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex, int* offset) {
|
bool ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex, int* offset) {
|
||||||
assert(stringtableIndex, "null string table index pointer");
|
assert(stringtableIndex, "null string table index pointer");
|
||||||
assert(posIndex, "null string table offset pointer");
|
assert(posIndex, "null string table offset pointer");
|
||||||
assert(offset, "null offset pointer");
|
assert(offset, "null offset pointer");
|
||||||
|
|
||||||
if (m_status != Decoder::no_error) {
|
if (NullDecoder::is_error(m_status)) {
|
||||||
return m_status;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
address pc = 0;
|
address pc = 0;
|
||||||
|
@ -97,8 +97,8 @@ Decoder::decoder_status ElfSymbolTable::lookup(address addr, int* stringtableInd
|
||||||
long cur_pos;
|
long cur_pos;
|
||||||
if ((cur_pos = ftell(m_file)) == -1 ||
|
if ((cur_pos = ftell(m_file)) == -1 ||
|
||||||
fseek(m_file, m_shdr.sh_offset, SEEK_SET)) {
|
fseek(m_file, m_shdr.sh_offset, SEEK_SET)) {
|
||||||
m_status = Decoder::file_invalid;
|
m_status = NullDecoder::file_invalid;
|
||||||
return m_status;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Elf_Sym sym;
|
Elf_Sym sym;
|
||||||
|
@ -114,13 +114,13 @@ Decoder::decoder_status ElfSymbolTable::lookup(address addr, int* stringtableInd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_status = Decoder::file_invalid;
|
m_status = NullDecoder::file_invalid;
|
||||||
return m_status;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fseek(m_file, cur_pos, SEEK_SET);
|
fseek(m_file, cur_pos, SEEK_SET);
|
||||||
}
|
}
|
||||||
return m_status;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // _WINDOWS
|
#endif // _WINDOWS
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -22,8 +22,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __ELF_SYMBOL_TABLE_HPP
|
#ifndef SHARE_VM_UTILITIES_ELF_SYMBOL_TABLE_HPP
|
||||||
#define __ELF_SYMBOL_TABLE_HPP
|
#define SHARE_VM_UTILITIES_ELF_SYMBOL_TABLE_HPP
|
||||||
|
|
||||||
#if !defined(_WINDOWS) && !defined(__APPLE__)
|
#if !defined(_WINDOWS) && !defined(__APPLE__)
|
||||||
|
|
||||||
|
@ -45,9 +45,9 @@ class ElfSymbolTable: public CHeapObj {
|
||||||
~ElfSymbolTable();
|
~ElfSymbolTable();
|
||||||
|
|
||||||
// search the symbol that is nearest to the specified address.
|
// search the symbol that is nearest to the specified address.
|
||||||
Decoder::decoder_status lookup(address addr, int* stringtableIndex, int* posIndex, int* offset);
|
bool lookup(address addr, int* stringtableIndex, int* posIndex, int* offset);
|
||||||
|
|
||||||
Decoder::decoder_status get_status() { return m_status; };
|
NullDecoder::decoder_status get_status() { return m_status; };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ElfSymbolTable* m_next;
|
ElfSymbolTable* m_next;
|
||||||
|
@ -62,9 +62,9 @@ class ElfSymbolTable: public CHeapObj {
|
||||||
// section header
|
// section header
|
||||||
Elf_Shdr m_shdr;
|
Elf_Shdr m_shdr;
|
||||||
|
|
||||||
Decoder::decoder_status m_status;
|
NullDecoder::decoder_status m_status;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _WINDOWS
|
#endif // _WINDOWS and _APPLE
|
||||||
|
|
||||||
#endif // __ELF_SYMBOL_TABLE_HPP
|
#endif // SHARE_VM_UTILITIES_ELF_SYMBOL_TABLE_HPP
|
||||||
|
|
|
@ -571,8 +571,6 @@ void VMError::report(outputStream* st) {
|
||||||
if (fr.pc()) {
|
if (fr.pc()) {
|
||||||
st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)");
|
st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)");
|
||||||
|
|
||||||
// initialize decoder to decode C frames
|
|
||||||
Decoder decoder;
|
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
while (count++ < StackPrintLimit) {
|
while (count++ < StackPrintLimit) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue