7071311: Decoder enhancement
Summary: Made decoder thread-safe
Reviewed-by: coleenp, kamg
--- a/hotspot/src/os/bsd/vm/decoder_bsd.cpp Wed Jan 11 17:58:26 2012 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 1997, 2010, 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 "prims/jvm.h"
-#include "utilities/decoder.hpp"
-
-#include <cxxabi.h>
-
-#ifdef __APPLE__
-
-void Decoder::initialize() {
- _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;
-}
-
-
-#endif
-
-bool Decoder::demangle(const char* symbol, char *buf, int buflen) {
- 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;
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/os/bsd/vm/decoder_machO.cpp Tue Jan 17 13:08:52 2012 -0500
@@ -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
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/os/bsd/vm/decoder_machO.hpp Tue Jan 17 13:08:52 2012 -0500
@@ -0,0 +1,42 @@
+/*
+ * 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_BSD_VM_DECODER_MACHO_HPP
+#define OS_BSD_VM_DECODER_MACHO_HPP
+
+#ifdef __APPLE__
+
+#include "utilities/decoder.hpp"
+
+// Just a placehold for now
+class MachODecoder: public NullDecoder {
+public:
+ MachODecoder() { }
+ ~MachODecoder() { }
+};
+
+#endif
+
+#endif // OS_BSD_VM_DECODER_MACHO_HPP
+
--- a/hotspot/src/os/linux/vm/decoder_linux.cpp Wed Jan 11 17:58:26 2012 -0500
+++ b/hotspot/src/os/linux/vm/decoder_linux.cpp Tue Jan 17 13:08:52 2012 -0500
@@ -23,11 +23,11 @@
*/
#include "prims/jvm.h"
-#include "utilities/decoder.hpp"
+#include "utilities/decoder_elf.hpp"
#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;
char* result;
size_t size = (size_t)buflen;
@@ -43,3 +43,4 @@
}
return false;
}
+
--- a/hotspot/src/os/linux/vm/os_linux.cpp Wed Jan 11 17:58:26 2012 -0500
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Tue Jan 17 13:08:52 2012 -0500
@@ -1732,7 +1732,7 @@
return true;
} else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) {
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;
}
}
--- a/hotspot/src/os/solaris/vm/decoder_solaris.cpp Wed Jan 11 17:58:26 2012 -0500
+++ b/hotspot/src/os/solaris/vm/decoder_solaris.cpp Tue Jan 17 13:08:52 2012 -0500
@@ -22,10 +22,11 @@
*
*/
-#include "utilities/decoder.hpp"
+#include "utilities/decoder_elf.hpp"
#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);
}
+
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Wed Jan 11 17:58:26 2012 -0500
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Tue Jan 17 13:08:52 2012 -0500
@@ -1997,7 +1997,7 @@
}
if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) {
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;
}
}
@@ -2015,7 +2015,7 @@
return true;
} else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) {
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;
}
}
--- a/hotspot/src/os/windows/vm/decoder_windows.cpp Wed Jan 11 17:58:26 2012 -0500
+++ b/hotspot/src/os/windows/vm/decoder_windows.cpp Tue Jan 17 13:08:52 2012 -0500
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,22 +24,24 @@
#include "precompiled.hpp"
#include "prims/jvm.h"
-#include "runtime/os.hpp"
-#include "utilities/decoder.hpp"
+#include "decoder_windows.hpp"
+
+WindowsDecoder::WindowsDecoder() {
+ _dbghelp_handle = NULL;
+ _can_decode_in_vm = false;
+ _pfnSymGetSymFromAddr64 = NULL;
+ _pfnUndecorateSymbolName = NULL;
-HMODULE Decoder::_dbghelp_handle = NULL;
-bool Decoder::_can_decode_in_vm = false;
-pfn_SymGetSymFromAddr64 Decoder::_pfnSymGetSymFromAddr64 = NULL;
-pfn_UndecorateSymbolName Decoder::_pfnUndecorateSymbolName = NULL;
+ _decoder_status = no_error;
+ initialize();
+}
-void Decoder::initialize() {
- if (!_initialized) {
- _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) {
_decoder_status = helper_not_found;
- return;
+ return;
}
_dbghelp_handle = handle;
@@ -70,32 +72,29 @@
// find out if jvm.dll contains private symbols, by decoding
// current function and comparing the result
- address addr = (address)Decoder::initialize;
+ address addr = (address)Decoder::decode;
char buf[MAX_PATH];
- if (decode(addr, buf, sizeof(buf), NULL) == no_error) {
- _can_decode_in_vm = !strcmp(buf, "Decoder::initialize");
+ if (decode(addr, buf, sizeof(buf), NULL)) {
+ _can_decode_in_vm = !strcmp(buf, "Decoder::decode");
}
}
}
-void Decoder::uninitialize() {
- assert(_initialized, "Decoder not yet initialized");
+void WindowsDecoder::uninitialize() {
_pfnSymGetSymFromAddr64 = NULL;
_pfnUndecorateSymbolName = NULL;
if (_dbghelp_handle != NULL) {
::FreeLibrary(_dbghelp_handle);
}
- _initialized = false;
+ _dbghelp_handle = NULL;
}
-bool Decoder::can_decode_C_frame_in_vm() {
- initialize();
- return _can_decode_in_vm;
+bool WindowsDecoder::can_decode_C_frame_in_vm() const {
+ return (!has_error() && _can_decode_in_vm);
}
-Decoder::decoder_status Decoder::decode(address addr, char *buf, int buflen, int *offset) {
- assert(_initialized, "Decoder not yet initialized");
+bool WindowsDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* modulepath) {
if (_pfnSymGetSymFromAddr64 != NULL) {
PIMAGEHLP_SYMBOL64 pSymbol;
char symbolInfo[MAX_PATH + sizeof(IMAGEHLP_SYMBOL64)];
@@ -105,19 +104,20 @@
DWORD64 displacement;
if (_pfnSymGetSymFromAddr64(::GetCurrentProcess(), (DWORD64)addr, &displacement, pSymbol)) {
if (buf != NULL) {
- if (!demangle(pSymbol->Name, buf, buflen)) {
+ if (demangle(pSymbol->Name, buf, buflen)) {
jio_snprintf(buf, buflen, "%s", pSymbol->Name);
}
}
- if (offset != NULL) *offset = (int)displacement;
- return no_error;
+ if(offset != NULL) *offset = (int)displacement;
+ 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) {
- assert(_initialized, "Decoder not yet initialized");
+bool WindowsDecoder::demangle(const char* symbol, char *buf, int buflen) {
return _pfnUndecorateSymbolName != NULL &&
_pfnUndecorateSymbolName(symbol, buf, buflen, UNDNAME_COMPLETE);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/os/windows/vm/decoder_windows.hpp Tue Jan 17 13:08:52 2012 -0500
@@ -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
+
--- a/hotspot/src/os/windows/vm/os_windows.cpp Wed Jan 11 17:58:26 2012 -0500
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Tue Jan 17 13:08:52 2012 -0500
@@ -1391,7 +1391,7 @@
bool os::dll_address_to_function_name(address addr, char *buf,
int buflen, int *offset) {
- if (Decoder::decode(addr, buf, buflen, offset) == Decoder::no_error) {
+ if (Decoder::decode(addr, buf, buflen, offset)) {
return true;
}
if (offset != NULL) *offset = -1;
--- a/hotspot/src/share/vm/utilities/decoder.cpp Wed Jan 11 17:58:26 2012 -0500
+++ b/hotspot/src/share/vm/utilities/decoder.cpp Tue Jan 17 13:08:52 2012 -0500
@@ -24,80 +24,85 @@
#include "precompiled.hpp"
#include "prims/jvm.h"
+#include "runtime/mutexLocker.hpp"
#include "utilities/decoder.hpp"
-Decoder::decoder_status Decoder::_decoder_status = Decoder::no_error;
-bool Decoder::_initialized = false;
-
-#if !defined(_WINDOWS) && !defined(__APPLE__)
-
-// Implementation of common functionalities among Solaris and Linux
-#include "utilities/elfFile.hpp"
-
-ElfFile* Decoder::_opened_elf_files = NULL;
-
-bool Decoder::can_decode_C_frame_in_vm() {
- return true;
-}
+#if defined(_WINDOWS)
+ #include "decoder_windows.hpp"
+#elif defined(__APPLE__)
+ #include "decoder_machO.hpp"
+#else
+ #include "decoder_elf.hpp"
+#endif
-void Decoder::initialize() {
- _initialized = true;
-}
+NullDecoder* Decoder::_decoder = NULL;
+NullDecoder Decoder::_do_nothing_decoder;
+Mutex* Decoder::_decoder_lock = new Mutex(Mutex::safepoint,
+ "DecoderLock");
-void Decoder::uninitialize() {
- if (_opened_elf_files != NULL) {
- delete _opened_elf_files;
- _opened_elf_files = NULL;
- }
- _initialized = false;
-}
+// _decoder_lock should already acquired before enter this method
+NullDecoder* Decoder::get_decoder() {
+ assert(_decoder_lock != NULL && _decoder_lock->owned_by_self(),
+ "Require DecoderLock to enter");
-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;
+ if (_decoder != NULL) {
+ return _decoder;
}
- 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);
+ // 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;
}
- return no_error;
- } else {
- return symbol_not_found;
+ _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);
}
-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;
+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() {
+ 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();
+}
+
+// shutdown real decoder and replace it with
+// _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;
}
- 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;
+ _decoder = &_do_nothing_decoder;
}
-#endif
--- a/hotspot/src/share/vm/utilities/decoder.hpp Wed Jan 11 17:58:26 2012 -0500
+++ b/hotspot/src/share/vm/utilities/decoder.hpp Tue Jan 17 13:08:52 2012 -0500
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,83 +23,78 @@
*/
-#ifndef __DECODER_HPP
-#define __DECODER_HPP
+#ifndef SHARE_VM_UTILITIES_DECODER_HPP
+#define SHARE_VM_UTILITIES_DECODER_HPP
#include "memory/allocation.hpp"
-
-#ifdef _WINDOWS
-#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);
+#include "runtime/mutex.hpp"
-#elif defined(__APPLE__)
-
-#else
-
-class ElfFile;
-
-#endif // _WINDOWS
-
-
-class Decoder: public StackObj {
-
- public:
+class NullDecoder: public CHeapObj {
+public:
// status code for decoding native C frame
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
file_invalid, // invalid elf file
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_func_error, // decoding functions not found (Windows only)
- helper_init_error, // SymInitialize failed (Windows only)
- symbol_not_found // could not find the symbol
+ helper_init_error // SymInitialize failed (Windows only)
};
- public:
- Decoder() { initialize(); };
- ~Decoder() { uninitialize(); };
+ NullDecoder() {
+ _decoder_status = not_available;
+ }
+
+ ~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 void initialize();
- static void uninitialize();
-
-#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; };
+ static void shutdown();
+protected:
+ static NullDecoder* get_decoder();
-#if !defined(_WINDOWS) && !defined(__APPLE__)
- private:
- static ElfFile* get_elf_file(const char* filepath);
-#endif // _WINDOWS
-
-
- private:
- static decoder_status _decoder_status;
- static bool _initialized;
+private:
+ static NullDecoder* _decoder;
+ static NullDecoder _do_nothing_decoder;
-#ifdef _WINDOWS
- static HMODULE _dbghelp_handle;
- static bool _can_decode_in_vm;
- static pfn_SymGetSymFromAddr64 _pfnSymGetSymFromAddr64;
- static pfn_UndecorateSymbolName _pfnUndecorateSymbolName;
-#elif __APPLE__
-#else
- static ElfFile* _opened_elf_files;
-#endif // _WINDOWS
+protected:
+ static Mutex* _decoder_lock;
};
-#endif // __DECODER_HPP
+#endif // SHARE_VM_UTILITIES_DECODER_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/utilities/decoder_elf.cpp Tue Jan 17 13:08:52 2012 -0500
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/utilities/decoder_elf.hpp Tue Jan 17 13:08:52 2012 -0500
@@ -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
--- a/hotspot/src/share/vm/utilities/elfFile.cpp Wed Jan 11 17:58:26 2012 -0500
+++ b/hotspot/src/share/vm/utilities/elfFile.cpp Tue Jan 17 13:08:52 2012 -0500
@@ -44,7 +44,7 @@
m_string_tables = NULL;
m_symbol_tables = NULL;
m_next = NULL;
- m_status = Decoder::no_error;
+ m_status = NullDecoder::no_error;
int len = strlen(filepath) + 1;
m_filepath = (const char*)os::malloc(len * sizeof(char));
@@ -54,10 +54,10 @@
if (m_file != NULL) {
load_tables();
} else {
- m_status = Decoder::file_not_found;
+ m_status = NullDecoder::file_not_found;
}
} else {
- m_status = Decoder::out_of_memory;
+ m_status = NullDecoder::out_of_memory;
}
}
@@ -96,41 +96,41 @@
bool ElfFile::load_tables() {
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
if (fread(&m_elfHdr, sizeof(m_elfHdr), 1, m_file) != 1) {
- m_status = Decoder::file_invalid;
+ m_status = NullDecoder::file_invalid;
return false;
}
if (!is_elf_file(m_elfHdr)) {
- m_status = Decoder::file_invalid;
+ m_status = NullDecoder::file_invalid;
return false;
}
// walk elf file's section headers, and load string tables
Elf_Shdr shdr;
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 ++) {
if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) {
- m_status = Decoder::file_invalid;
+ m_status = NullDecoder::file_invalid;
return false;
}
// string table
if (shdr.sh_type == SHT_STRTAB) {
ElfStringTable* table = new (std::nothrow) ElfStringTable(m_file, shdr, index);
if (table == NULL) {
- m_status = Decoder::out_of_memory;
+ m_status = NullDecoder::out_of_memory;
return false;
}
add_string_table(table);
} else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
ElfSymbolTable* table = new (std::nothrow) ElfSymbolTable(m_file, shdr);
if (table == NULL) {
- m_status = Decoder::out_of_memory;
+ m_status = NullDecoder::out_of_memory;
return false;
}
add_symbol_table(table);
@@ -140,32 +140,33 @@
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
- if (m_status != Decoder::no_error) {
- return NULL;
+ if (NullDecoder::is_error(m_status)) {
+ return false;
}
-
ElfSymbolTable* symbol_table = m_symbol_tables;
int string_table_index;
int pos_in_string_table;
int off = INT_MAX;
bool found_symbol = false;
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;
}
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);
+
if (string_table == NULL) {
- m_status = Decoder::file_invalid;
- return NULL;
+ m_status = NullDecoder::file_invalid;
+ return false;
}
if (offset) *offset = off;
- return string_table->string_at(pos_in_string_table);
+
+ return string_table->string_at(pos_in_string_table, buf, buflen);
}
--- a/hotspot/src/share/vm/utilities/elfFile.hpp Wed Jan 11 17:58:26 2012 -0500
+++ b/hotspot/src/share/vm/utilities/elfFile.hpp Tue Jan 17 13:08:52 2012 -0500
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,8 @@
*
*/
-#ifndef __ELF_FILE_HPP
-#define __ELF_FILE_HPP
+#ifndef SHARE_VM_UTILITIES_ELF_FILE_HPP
+#define SHARE_VM_UTILITIES_ELF_FILE_HPP
#if !defined(_WINDOWS) && !defined(__APPLE__)
@@ -83,12 +83,12 @@
// part of code to be very defensive, and bait out if anything went wrong.
class ElfFile: public CHeapObj {
- friend class Decoder;
+ friend class ElfDecoder;
public:
ElfFile(const char* filepath);
~ElfFile();
- const char* decode(address addr, int* offset);
+ bool decode(address addr, char* buf, int buflen, int* offset);
const char* filepath() {
return m_filepath;
}
@@ -99,7 +99,7 @@
return (m_filepath && !strcmp(filepath, m_filepath));
}
- Decoder::decoder_status get_status() {
+ NullDecoder::decoder_status get_status() {
return m_status;
}
@@ -119,8 +119,9 @@
// return a string table at specified section index
ElfStringTable* get_string_table(int index);
- // look up an address and return the nearest symbol
- const char* look_up(Elf_Shdr shdr, address addr, int* offset);
+protected:
+ ElfFile* next() const { return m_next; }
+ void set_next(ElfFile* file) { m_next = file; }
protected:
ElfFile* m_next;
@@ -131,17 +132,17 @@
FILE* m_file;
// Elf header
- Elf_Ehdr m_elfHdr;
+ Elf_Ehdr m_elfHdr;
// symbol tables
- ElfSymbolTable* m_symbol_tables;
+ ElfSymbolTable* m_symbol_tables;
// string tables
- ElfStringTable* m_string_tables;
+ ElfStringTable* m_string_tables;
- Decoder::decoder_status m_status;
+ NullDecoder::decoder_status m_status;
};
#endif // _WINDOWS
-#endif // __ELF_FILE_HPP
+#endif // SHARE_VM_UTILITIES_ELF_FILE_HPP
--- a/hotspot/src/share/vm/utilities/elfStringTable.cpp Wed Jan 11 17:58:26 2012 -0500
+++ b/hotspot/src/share/vm/utilities/elfStringTable.cpp Tue Jan 17 13:08:52 2012 -0500
@@ -38,7 +38,7 @@
m_index = index;
m_next = NULL;
m_file = file;
- m_status = Decoder::no_error;
+ m_status = NullDecoder::no_error;
// try to load the string table
long cur_offset = ftell(file);
@@ -48,7 +48,7 @@
if (fseek(file, shdr.sh_offset, SEEK_SET) ||
fread((void*)m_table, shdr.sh_size, 1, file) != 1 ||
fseek(file, cur_offset, SEEK_SET)) {
- m_status = Decoder::file_invalid;
+ m_status = NullDecoder::file_invalid;
os::free((void*)m_table);
m_table = NULL;
}
@@ -67,22 +67,23 @@
}
}
-const char* ElfStringTable::string_at(int pos) {
- if (m_status != Decoder::no_error) {
- return NULL;
+bool ElfStringTable::string_at(int pos, char* buf, int buflen) {
+ if (NullDecoder::is_error(m_status)) {
+ return false;
}
if (m_table != NULL) {
- return (const char*)(m_table + pos);
+ jio_snprintf(buf, buflen, "%s", (const char*)(m_table + pos));
+ return true;
} else {
long cur_pos = ftell(m_file);
if (cur_pos == -1 ||
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)) {
- m_status = Decoder::file_invalid;
- return NULL;
+ m_status = NullDecoder::file_invalid;
+ return false;
}
- return (const char*)m_symbol;
+ return true;
}
}
--- a/hotspot/src/share/vm/utilities/elfStringTable.hpp Wed Jan 11 17:58:26 2012 -0500
+++ b/hotspot/src/share/vm/utilities/elfStringTable.hpp Tue Jan 17 13:08:52 2012 -0500
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,8 @@
*
*/
-#ifndef __ELF_STRING_TABLE_HPP
-#define __ELF_STRING_TABLE_HPP
+#ifndef SHARE_VM_UTILITIES_ELF_STRING_TABLE_HPP
+#define SHARE_VM_UTILITIES_ELF_STRING_TABLE_HPP
#if !defined(_WINDOWS) && !defined(__APPLE__)
@@ -35,9 +35,6 @@
// The string table represents a string table section in an elf file.
// Whenever there is enough memory, it will load whole string table as
// one blob. Otherwise, it will load string from file when requested.
-
-#define MAX_SYMBOL_LEN 256
-
class ElfStringTable: CHeapObj {
friend class ElfFile;
public:
@@ -48,10 +45,10 @@
int index() { return m_index; };
// get string at specified offset
- const char* string_at(int offset);
+ bool string_at(int offset, char* buf, int buflen);
// get status code
- Decoder::decoder_status get_status() { return m_status; };
+ NullDecoder::decoder_status get_status() { return m_status; };
protected:
ElfStringTable* m_next;
@@ -69,13 +66,10 @@
// section header
Elf_Shdr m_shdr;
- // buffer for reading individual string
- char m_symbol[MAX_SYMBOL_LEN];
-
// 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
--- a/hotspot/src/share/vm/utilities/elfSymbolTable.cpp Wed Jan 11 17:58:26 2012 -0500
+++ b/hotspot/src/share/vm/utilities/elfSymbolTable.cpp Tue Jan 17 13:08:52 2012 -0500
@@ -34,7 +34,7 @@
m_symbols = NULL;
m_next = NULL;
m_file = file;
- m_status = Decoder::no_error;
+ m_status = NullDecoder::no_error;
// try to load the string table
long cur_offset = ftell(file);
@@ -45,16 +45,16 @@
if (fseek(file, shdr.sh_offset, SEEK_SET) ||
fread((void*)m_symbols, shdr.sh_size, 1, file) != 1 ||
fseek(file, cur_offset, SEEK_SET)) {
- m_status = Decoder::file_invalid;
+ m_status = NullDecoder::file_invalid;
os::free(m_symbols);
m_symbols = NULL;
}
}
- if (m_status == Decoder::no_error) {
+ if (!NullDecoder::is_error(m_status)) {
memcpy(&m_shdr, &shdr, sizeof(Elf_Shdr));
}
} else {
- m_status = Decoder::file_invalid;
+ m_status = NullDecoder::file_invalid;
}
}
@@ -68,13 +68,13 @@
}
}
-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(posIndex, "null string table offset pointer");
assert(offset, "null offset pointer");
- if (m_status != Decoder::no_error) {
- return m_status;
+ if (NullDecoder::is_error(m_status)) {
+ return false;
}
address pc = 0;
@@ -97,8 +97,8 @@
long cur_pos;
if ((cur_pos = ftell(m_file)) == -1 ||
fseek(m_file, m_shdr.sh_offset, SEEK_SET)) {
- m_status = Decoder::file_invalid;
- return m_status;
+ m_status = NullDecoder::file_invalid;
+ return false;
}
Elf_Sym sym;
@@ -114,13 +114,13 @@
}
}
} else {
- m_status = Decoder::file_invalid;
- return m_status;
+ m_status = NullDecoder::file_invalid;
+ return false;
}
}
fseek(m_file, cur_pos, SEEK_SET);
}
- return m_status;
+ return true;
}
#endif // _WINDOWS
--- a/hotspot/src/share/vm/utilities/elfSymbolTable.hpp Wed Jan 11 17:58:26 2012 -0500
+++ b/hotspot/src/share/vm/utilities/elfSymbolTable.hpp Tue Jan 17 13:08:52 2012 -0500
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,8 @@
*
*/
-#ifndef __ELF_SYMBOL_TABLE_HPP
-#define __ELF_SYMBOL_TABLE_HPP
+#ifndef SHARE_VM_UTILITIES_ELF_SYMBOL_TABLE_HPP
+#define SHARE_VM_UTILITIES_ELF_SYMBOL_TABLE_HPP
#if !defined(_WINDOWS) && !defined(__APPLE__)
@@ -45,9 +45,9 @@
~ElfSymbolTable();
// 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:
ElfSymbolTable* m_next;
@@ -62,9 +62,9 @@
// section header
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
--- a/hotspot/src/share/vm/utilities/vmError.cpp Wed Jan 11 17:58:26 2012 -0500
+++ b/hotspot/src/share/vm/utilities/vmError.cpp Tue Jan 17 13:08:52 2012 -0500
@@ -571,8 +571,6 @@
if (fr.pc()) {
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;
while (count++ < StackPrintLimit) {