--- old/src/os/linux/vm/decoder_linux.cpp Fri Oct 21 11:12:02 2011 +++ new/src/os/linux/vm/decoder_linux.cpp Fri Oct 21 11:12:01 2011 @@ -23,11 +23,11 @@ */ #include "prims/jvm.h" -#include "utilities/decoder.hpp" +#include "utilities/decoder_elf.hpp" #include -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; } + --- old/src/os/linux/vm/os_linux.cpp Fri Oct 21 11:12:04 2011 +++ new/src/os/linux/vm/os_linux.cpp Fri Oct 21 11:12:04 2011 @@ -1733,7 +1733,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; } } --- old/src/os/solaris/vm/decoder_solaris.cpp Fri Oct 21 11:12:08 2011 +++ new/src/os/solaris/vm/decoder_solaris.cpp Fri Oct 21 11:12:07 2011 @@ -22,10 +22,11 @@ * */ -#include "utilities/decoder.hpp" +#include "utilities/decoder_elf.hpp" #include -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); } + --- old/src/os/solaris/vm/os_solaris.cpp Fri Oct 21 11:12:10 2011 +++ new/src/os/solaris/vm/os_solaris.cpp Fri Oct 21 11:12:10 2011 @@ -1993,7 +1993,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; } } @@ -2011,7 +2011,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; } } --- old/src/os/windows/vm/decoder_windows.cpp Fri Oct 21 11:12:14 2011 +++ new/src/os/windows/vm/decoder_windows.cpp Fri Oct 21 11:12:14 2011 @@ -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" -HMODULE Decoder::_dbghelp_handle = NULL; -bool Decoder::_can_decode_in_vm = false; -pfn_SymGetSymFromAddr64 Decoder::_pfnSymGetSymFromAddr64 = NULL; -pfn_UndecorateSymbolName Decoder::_pfnUndecorateSymbolName = NULL; +WindowsDecoder::WindowsDecoder() { + _dbghelp_handle = NULL; + _can_decode_in_vm = false; + _pfnSymGetSymFromAddr64 = NULL; + _pfnUndecorateSymbolName = NULL; -void Decoder::initialize() { - if (!_initialized) { - _initialized = true; + _decoder_status = no_error; + initialize(); +} - 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::get_decoder; 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::get_decoder"); } } } -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); } --- old/src/os/windows/vm/os_windows.cpp Fri Oct 21 11:12:17 2011 +++ new/src/os/windows/vm/os_windows.cpp Fri Oct 21 11:12:17 2011 @@ -1389,7 +1389,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; --- old/src/share/vm/utilities/decoder.cpp Fri Oct 21 11:12:21 2011 +++ new/src/share/vm/utilities/decoder.cpp Fri Oct 21 11:12:20 2011 @@ -24,80 +24,93 @@ #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) + #include "decoder_windows.hpp" +#elif defined(__APPLE__) + #include "decoder_machO.hpp" +#else + #include "decoder_elf.hpp" +#endif -#if !defined(_WINDOWS) && !defined(__APPLE__) +Decoder* Decoder::_decoder = NULL; +Decoder Decoder::_do_nothing_decoder; +Mutex* Decoder::_decoder_lock = new Mutex(Mutex::safepoint, + "DecoderLock"); -// Implementation of common functionalities among Solaris and Linux -#include "utilities/elfFile.hpp" +// _decoder_lock should already acquired before enter this method +Decoder* 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; + } -bool Decoder::can_decode_C_frame_in_vm() { - return true; + // 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; } -void Decoder::initialize() { - _initialized = true; +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); + Decoder* decoder = get_decoder(); + assert(decoder != NULL, "null decoder"); + + return decoder->_decode(addr, buf, buflen, offset, modulepath); } -void Decoder::uninitialize() { - if (_opened_elf_files != NULL) { - delete _opened_elf_files; - _opened_elf_files = NULL; - } - _initialized = false; +bool Decoder::demangle(const char* symbol, char* buf, int buflen) { + assert(_decoder_lock != NULL, "Just check"); + MutexLockerEx locker(_decoder_lock, true); + Decoder* decoder = get_decoder(); + assert(decoder != NULL, "null decoder"); + return decoder->_demangle(symbol, buf, buflen); } -Decoder::decoder_status Decoder::decode(address addr, const char* filepath, char *buf, int buflen, int *offset) { - if (_decoder_status != no_error) { - return _decoder_status; - } +bool Decoder::can_decode_C_frame_in_vm() { + assert(_decoder_lock != NULL, "Just check"); + MutexLockerEx locker(_decoder_lock, true); + Decoder* decoder = get_decoder(); + assert(decoder != NULL, "null decoder"); + return decoder->_can_decode_C_frame_in_vm(); +} - 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; - } -} +Decoder::decoder_status Decoder::status() { + assert(_decoder_lock != NULL, "Just check"); + MutexLockerEx locker(_decoder_lock, true); + Decoder* decoder = get_decoder(); + assert(decoder != NULL, "null decoder"); + return _decoder->_status(); +}; -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; - } +// shutdown real decoder and replace it with +// _do_nothing_decoder +void Decoder::shutdown() { + assert(_decoder_lock != NULL, "Just check"); + MutexLockerEx locker(_decoder_lock, true); - file = new ElfFile(filepath); - if (file == NULL) { - _decoder_status = out_of_memory; + if (_decoder != NULL && _decoder != &_do_nothing_decoder) { + delete _decoder; } - if (_opened_elf_files != NULL) { - file->m_next = _opened_elf_files; - } - _opened_elf_files = file; - return file; + _decoder = &_do_nothing_decoder; } - -#endif --- old/src/share/vm/utilities/decoder.hpp Fri Oct 21 11:12:24 2011 +++ new/src/share/vm/utilities/decoder.hpp Fri Oct 21 11:12:23 2011 @@ -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,68 @@ */ -#ifndef __DECODER_HPP -#define __DECODER_HPP +#ifndef SHARE_VM_UTILITIES_DECODER_HPP +#define SHARE_VM_UTILITIES_DECODER_HPP #include "memory/allocation.hpp" +#include "runtime/mutex.hpp" -#ifdef _WINDOWS -#include -#include +class Decoder: public CHeapObj { -// 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 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(); }; + 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 bool is_error(decoder_status status) { return (status > 0); } + static decoder_status status(); - static void initialize(); - static void uninitialize(); + static void shutdown(); +protected: + Decoder() { + _decoder_status = not_available; + }; -#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 + ~Decoder() {}; - static bool demangle(const char* symbol, char *buf, int buflen); + static Decoder* get_decoder(); - static decoder_status get_status() { return _decoder_status; }; + virtual bool _decode(address pc, char* buf, int buflen, int* offset, + const char* modulepath = NULL) { + return false; + } -#if !defined(_WINDOWS) && !defined(__APPLE__) - private: - static ElfFile* get_elf_file(const char* filepath); -#endif // _WINDOWS + virtual bool _demangle(const char* symbol, char* buf, int buflen) { + return false; + } + virtual bool _can_decode_C_frame_in_vm() const { + return false; + } - private: - static decoder_status _decoder_status; - static bool _initialized; + virtual decoder_status _status() const { return _decoder_status; } + virtual bool has_error() const { return is_error(_decoder_status); } + +private: + static Decoder* _decoder; + static Decoder _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; + + decoder_status _decoder_status; }; -#endif // __DECODER_HPP +#endif // SHARE_VM_UTILITIES_DECODER_HPP --- old/src/share/vm/utilities/elfFile.cpp Fri Oct 21 11:12:26 2011 +++ new/src/share/vm/utilities/elfFile.cpp Fri Oct 21 11:12:26 2011 @@ -96,7 +96,7 @@ bool ElfFile::load_tables() { assert(m_file, "file not open"); - assert(m_status == Decoder::no_error, "already in error"); + assert(!Decoder::is_error(m_status), "already in error"); // read elf file header if (fread(&m_elfHdr, sizeof(m_elfHdr), 1, m_file) != 1) { @@ -112,7 +112,7 @@ // 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 (Decoder::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) { @@ -140,12 +140,11 @@ 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 (Decoder::is_error(m_status)) { + return false; } - ElfSymbolTable* symbol_table = m_symbol_tables; int string_table_index; int pos_in_string_table; @@ -152,20 +151,22 @@ 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; + 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); } --- old/src/share/vm/utilities/elfFile.hpp Fri Oct 21 11:12:29 2011 +++ new/src/share/vm/utilities/elfFile.hpp Fri Oct 21 11:12:28 2011 @@ -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; } @@ -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; @@ -144,4 +145,4 @@ #endif // _WINDOWS -#endif // __ELF_FILE_HPP +#endif // SHARE_VM_UTILITIES_ELF_FILE_HPP --- old/src/share/vm/utilities/elfStringTable.cpp Fri Oct 21 11:12:31 2011 +++ new/src/share/vm/utilities/elfStringTable.cpp Fri Oct 21 11:12:31 2011 @@ -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 (Decoder::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; + return false; } - return (const char*)m_symbol; + return true; } } --- old/src/share/vm/utilities/elfStringTable.hpp Fri Oct 21 11:12:34 2011 +++ new/src/share/vm/utilities/elfStringTable.hpp Fri Oct 21 11:12:33 2011 @@ -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,7 +45,7 @@ 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; }; @@ -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; }; -#endif // _WINDOWS +#endif // _WINDOWS and _APPLE -#endif // __ELF_STRING_TABLE_HPP +#endif // SHARE_VM_UTILITIES_ELF_STRING_TABLE_HPP --- old/src/share/vm/utilities/elfSymbolTable.cpp Fri Oct 21 11:12:36 2011 +++ new/src/share/vm/utilities/elfSymbolTable.cpp Fri Oct 21 11:12:36 2011 @@ -50,7 +50,7 @@ m_symbols = NULL; } } - if (m_status == Decoder::no_error) { + if (!Decoder::is_error(m_status)) { memcpy(&m_shdr, &shdr, sizeof(Elf_Shdr)); } } else { @@ -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 (Decoder::is_error(m_status)) { + return false; } address pc = 0; @@ -98,7 +98,7 @@ if ((cur_pos = ftell(m_file)) == -1 || fseek(m_file, m_shdr.sh_offset, SEEK_SET)) { m_status = Decoder::file_invalid; - return m_status; + return false; } Elf_Sym sym; @@ -115,12 +115,12 @@ } } else { m_status = Decoder::file_invalid; - return m_status; + return false; } } fseek(m_file, cur_pos, SEEK_SET); } - return m_status; + return true; } #endif // _WINDOWS --- old/src/share/vm/utilities/elfSymbolTable.hpp Fri Oct 21 11:12:39 2011 +++ new/src/share/vm/utilities/elfSymbolTable.hpp Fri Oct 21 11:12:38 2011 @@ -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,7 +45,7 @@ ~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; }; @@ -65,6 +65,6 @@ Decoder::decoder_status m_status; }; -#endif // _WINDOWS +#endif // _WINDOWS and _APPLE -#endif // __ELF_SYMBOL_TABLE_HPP +#endif // SHARE_VM_UTILITIES_ELF_SYMBOL_TABLE_HPP --- old/src/share/vm/utilities/vmError.cpp Fri Oct 21 11:12:41 2011 +++ new/src/share/vm/utilities/vmError.cpp Fri Oct 21 11:12:41 2011 @@ -571,9 +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) { fr.print_on_error(st, buf, sizeof(buf)); --- /dev/null Fri Oct 21 11:12:44 2011 +++ new/src/os/bsd/vm/decoder_machO.cpp Fri Oct 21 11:12:44 2011 @@ -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 Fri Oct 21 11:12:46 2011 +++ new/src/os/bsd/vm/decoder_machO.hpp Fri Oct 21 11:12:46 2011 @@ -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 Decoder { +public: + MachODecoder() { } + ~MachODecoder() { } +}; + +#endif + +#endif // OS_BSD_VM_DECODER_MACHO_HPP + --- /dev/null Fri Oct 21 11:12:48 2011 +++ new/src/os/windows/vm/decoder_windows.hpp Fri Oct 21 11:12:47 2011 @@ -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 +#include + +#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 Decoder { + +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 + --- /dev/null Fri Oct 21 11:12:49 2011 +++ new/src/share/vm/utilities/decoder_elf.cpp Fri Oct 21 11:12:49 2011 @@ -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 Fri Oct 21 11:12:51 2011 +++ new/src/share/vm/utilities/decoder_elf.hpp Fri Oct 21 11:12:50 2011 @@ -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 "elfFile.hpp" + +class ElfDecoder: public Decoder { + +public: + ElfDecoder() { + _opened_elf_files = NULL; + _decoder_status = Decoder::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 --- old/src/os/bsd/vm/decoder_bsd.cpp Fri Oct 21 11:12:52 2011 +++ /dev/null Fri Oct 21 11:12:52 2011 @@ -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 - -#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; -}