From: <ibr...@us...> - 2010-02-25 13:24:35
|
Revision: 3443 http://tora.svn.sourceforge.net/tora/?rev=3443&view=rev Author: ibre5041 Date: 2010-02-25 13:24:12 +0000 (Thu, 25 Feb 2010) Log Message: ----------- widows compile fix Modified Paths: -------------- branches/tora-trotl/src/CMakeLists.txt branches/tora-trotl/src/trotl/src/CMakeLists.txt Added Paths: ----------- branches/tora-trotl/src/trotl/src/stack/ branches/tora-trotl/src/trotl/src/stack/CMakeLists.txt branches/tora-trotl/src/trotl/src/stack/LICENSE_1_0.txt branches/tora-trotl/src/trotl/src/stack/stack.cpp branches/tora-trotl/src/trotl/src/stack/stack.hpp Removed Paths: ------------- branches/tora-trotl/src/stack/ branches/tora-trotl/src/trotl/src/stack/CMakeLists.txt branches/tora-trotl/src/trotl/src/stack/LICENSE_1_0.txt branches/tora-trotl/src/trotl/src/stack/stack.cpp branches/tora-trotl/src/trotl/src/stack/stack.hpp Modified: branches/tora-trotl/src/CMakeLists.txt =================================================================== --- branches/tora-trotl/src/CMakeLists.txt 2010-02-25 13:22:06 UTC (rev 3442) +++ branches/tora-trotl/src/CMakeLists.txt 2010-02-25 13:24:12 UTC (rev 3443) @@ -459,14 +459,6 @@ SET (WINDOWS_LIB "windows_lib") ENDIF (WIN32) -# include the stack library in dubug builds only -IF(CMAKE_BUILD_TYPE STREQUAL "Debug") - SET (STACK_LIB "stack_lib") - ADD_SUBDIRECTORY(stack) - INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/stack) - LINK_DIRECTORIES(./stack) -ENDIF(CMAKE_BUILD_TYPE STREQUAL "Debug") - SET (TROTL_LIB "trotl") SET (TORA_MOC_LIB "tora_moc_lib") @@ -556,10 +548,6 @@ LIST(APPEND TORA_LIBS ${TROTL_LIB}) -IF(CMAKE_BUILD_TYPE STREQUAL "Debug") - LIST(APPEND TORA_LIBS ${STACK_LIB}) -ENDIF(CMAKE_BUILD_TYPE STREQUAL "Debug") - ADD_EXECUTABLE(${EXE_NAME} ${GUI_TYPE} # ${TORA_I18N_QM} # ${TORA_MOC_SOURCES} Modified: branches/tora-trotl/src/trotl/src/CMakeLists.txt =================================================================== --- branches/tora-trotl/src/trotl/src/CMakeLists.txt 2010-02-25 13:22:06 UTC (rev 3442) +++ branches/tora-trotl/src/trotl/src/CMakeLists.txt 2010-02-25 13:24:12 UTC (rev 3443) @@ -1,13 +1,17 @@ SET(TROTL_DLL_DEFINES "-DLOKI_STATIC -DEXPLICIT_EXPORT -DTROTL_MAKE_DLL") SET(TROTL_CLIENT_DEFINES "-DLOKI_STATIC -DEXPLICIT_EXPORT -DTROTL_DLL") -ADD_DEFINITIONS(-DORACLE_CS=DEVEL) - INCLUDE_DIRECTORIES( - ${ORACLE_INCLUDES} - ${CMAKE_SOURCE_DIR}/src + ${ORACLE_INCLUDES} ) +# include the stack library in dubug builds only +IF(CMAKE_BUILD_TYPE STREQUAL "Debug") + SET (STACK_LIB "stack_lib") + ADD_SUBDIRECTORY(stack) + INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/stack) + LINK_DIRECTORIES(./stack) +ENDIF(CMAKE_BUILD_TYPE STREQUAL "Debug") SET(TROTL_SOURCES trotl_aq.cpp Deleted: branches/tora-trotl/src/trotl/src/stack/CMakeLists.txt =================================================================== --- branches/tora-trotl/src/trotl/src/stack/CMakeLists.txt 2010-02-25 09:54:47 UTC (rev 3439) +++ branches/tora-trotl/src/trotl/src/stack/CMakeLists.txt 2010-02-25 13:24:12 UTC (rev 3443) @@ -1,18 +0,0 @@ -INCLUDE_DIRECTORIES( -${CMAKE_SOURCE_DIR}/src/stack/ -) - -SET(STACK_LIB_SOURCES -stack.hpp -stack.cpp -) - -SET(STACK_LIB "stack_lib") - -ADD_LIBRARY(${STACK_LIB} STATIC ${STACK_LIB_SOURCES}) - -IF("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64") - SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fPIC" ) - SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fPIC" ) - SET_TARGET_PROPERTIES( stack_lib PROPERTIES COMPILE_FLAGS -fPIC) -ENDIF("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64") Copied: branches/tora-trotl/src/trotl/src/stack/CMakeLists.txt (from rev 3439, branches/tora-trotl/src/trotl/src/stack/CMakeLists.txt) =================================================================== --- branches/tora-trotl/src/trotl/src/stack/CMakeLists.txt (rev 0) +++ branches/tora-trotl/src/trotl/src/stack/CMakeLists.txt 2010-02-25 13:24:12 UTC (rev 3443) @@ -0,0 +1,18 @@ +INCLUDE_DIRECTORIES( +${CMAKE_SOURCE_DIR}/src/stack/ +) + +SET(STACK_LIB_SOURCES +stack.hpp +stack.cpp +) + +SET(STACK_LIB "stack_lib") + +ADD_LIBRARY(${STACK_LIB} STATIC ${STACK_LIB_SOURCES}) + +IF("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64") + SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fPIC" ) + SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fPIC" ) + SET_TARGET_PROPERTIES( stack_lib PROPERTIES COMPILE_FLAGS -fPIC) +ENDIF("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64") Deleted: branches/tora-trotl/src/trotl/src/stack/LICENSE_1_0.txt =================================================================== --- branches/tora-trotl/src/trotl/src/stack/LICENSE_1_0.txt 2010-02-25 09:54:47 UTC (rev 3439) +++ branches/tora-trotl/src/trotl/src/stack/LICENSE_1_0.txt 2010-02-25 13:24:12 UTC (rev 3443) @@ -1,23 +0,0 @@ -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. Copied: branches/tora-trotl/src/trotl/src/stack/LICENSE_1_0.txt (from rev 3439, branches/tora-trotl/src/trotl/src/stack/LICENSE_1_0.txt) =================================================================== --- branches/tora-trotl/src/trotl/src/stack/LICENSE_1_0.txt (rev 0) +++ branches/tora-trotl/src/trotl/src/stack/LICENSE_1_0.txt 2010-02-25 13:24:12 UTC (rev 3443) @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. Deleted: branches/tora-trotl/src/trotl/src/stack/stack.cpp =================================================================== --- branches/tora-trotl/src/trotl/src/stack/stack.cpp 2010-02-25 09:54:47 UTC (rev 3439) +++ branches/tora-trotl/src/trotl/src/stack/stack.cpp 2010-02-25 13:24:12 UTC (rev 3443) @@ -1,433 +0,0 @@ -// Copyright 2007 Edd Dawson. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include <iomanip> -#include <sstream> -#include <ostream> -#include <iostream> -#include <cassert> -#include <cstdlib> - -#include "stack.hpp" - -#if defined(_WIN32) - #include <windows.h> - #include <imagehlp.h> - - #if defined(__MINGW32__) - #include <bfd.h> // link against libbfd and libiberty - #include <psapi.h> // link against psapi - #include <cxxabi.h> - #endif - -#elif defined(__GNUC__) - #include <string.h> - #include <dlfcn.h> - #include <cxxabi.h> -#endif - -namespace -{ - -#if defined(__GNUC__) - std::string demangle(const char *name) - { - //this just does not work - some QT's private symbols cannot be resolved - //if (!name) throws dbg::stack_error then "use -rdynamic"; - if(!name) return "uknown symbol"; - int status = 0; - char *d = 0; - std::string ret = name; - try { if ((d = abi::__cxa_demangle(name, 0, 0, &status))) ret = d; } - catch(...) { } - std::free(d); - return ret; - } -#endif - -#if defined(_WIN32) - - class uncopyable - { - public: - uncopyable() { } - - private: - uncopyable(const uncopyable &); // remains undefined - uncopyable &operator= (const uncopyable &); // remains undefined - }; - - #if defined(__MINGW32__) - - class bfd_context : uncopyable - { - private: - struct find_data - { - std::string func; - asymbol **symbol_table; - bfd_vma counter; - }; - - public: - bfd_context() : - abfd_(0), - sec_(0), - symbol_table_(0) - { - char procname[MAX_PATH]; - GetModuleFileNameEx(GetCurrentProcess(), NULL, procname, sizeof procname); - - bfd_init(); - abfd_ = bfd_openr(procname, 0); - if (!abfd_) - throw dbg::stack_error("Failed to parse object data for the executable"); - - char **formats = 0; - bool b1 = bfd_check_format(abfd_, bfd_object); - bool b2 = bfd_check_format_matches(abfd_, bfd_object, &formats); - bool b3 = bfd_get_file_flags(abfd_) & HAS_SYMS; - - if (!(b1 && b2 && b3)) - { - bfd_close(abfd_); - free(formats); - throw dbg::stack_error("Failed to parse object data for the executable"); - } - free(formats); - - // Load symbol table - unsigned dummy = 0; - if (bfd_read_minisymbols(abfd_, FALSE, (void **)&symbol_table_, &dummy) == 0 && - bfd_read_minisymbols(abfd_, TRUE, (void **)&symbol_table_, &dummy) < 0) - { - free(symbol_table_); - bfd_close(abfd_); - throw dbg::stack_error("Failed to parse object data for the executable"); - } - } - - ~bfd_context() - { - free(symbol_table_); - bfd_close(abfd_); - } - - std::string get_function_name(DWORD offset) - { - find_data data; - data.symbol_table = symbol_table_; - data.counter = offset; - - bfd_map_over_sections(abfd_, &find_function_name_in_section, &data); - - return data.func; - } - - private: - static void find_function_name_in_section(bfd *abfd, asection *sec, void *opaque_data) - { - assert(sec); - assert(opaque_data); - find_data &data = *static_cast<find_data *>(opaque_data); - - if (!data.func.empty()) return; // already found it - - if (!(bfd_get_section_flags(abfd, sec) & SEC_ALLOC)) return; - - bfd_vma vma = bfd_get_section_vma(abfd, sec); - if (data.counter < vma || vma + bfd_get_section_size(sec) <= data.counter) return; - - const char *func = 0; - const char *file = 0; - unsigned line = 0; - - if (bfd_find_nearest_line(abfd, sec, data.symbol_table, data.counter - vma, &file, &func, &line) && func) - data.func = demangle(func); - } - - private: - bfd *abfd_; - asection *sec_; - asymbol **symbol_table_; - }; - - #endif // __MINGW32__ - - class auto_cast_function_ptr - { - public: - template<typename FuncPtr> - explicit auto_cast_function_ptr(FuncPtr f) : fptr_(reinterpret_cast<void (*)(void)>(f)) { } - - template<typename FuncPtr> - operator FuncPtr() const { return reinterpret_cast<FuncPtr>(fptr_); } - - private: - void (*fptr_)(void); - }; - - class windows_dll : uncopyable - { - public: - explicit windows_dll(const std::string &libname) : - name_(libname), - lib_(LoadLibrary(name_.c_str())) - { - if (!lib_) throw dbg::stack_error("Failed to load dll " + name_); - } - - ~windows_dll() { FreeLibrary(lib_); } - - const std::string &name() const { return name_; } - - auto_cast_function_ptr function(const std::string &func_name) const - { - FARPROC proc = GetProcAddress(lib_, func_name.c_str()); - if (!proc) throw dbg::stack_error("failed to load function " + func_name + " from library " + name_); - - return auto_cast_function_ptr(proc); - } - - private: - std::string name_; - HMODULE lib_; - }; - - class symbol_context : uncopyable - { - public: - symbol_context() { SymInitialize(GetCurrentProcess(), 0, true); } - ~symbol_context() { SymCleanup(GetCurrentProcess()); } - }; - - - class mutex : uncopyable - { - public: - mutex() { InitializeCriticalSection(&cs_); } - ~mutex() { DeleteCriticalSection(&cs_); } - void lock() { EnterCriticalSection(&cs_); } - void unlock() { LeaveCriticalSection(&cs_); } - - private: - CRITICAL_SECTION cs_; - }; - - class scoped_lock : uncopyable - { - public: - scoped_lock(mutex &m) : m_(m) { m_.lock(); } - ~scoped_lock() { m_.unlock(); } - private: - mutex &m_; - }; - - mutex fill_frames_mtx_; - - - void fill_frames(std::list<dbg::stack_frame> &frames, dbg::stack::depth_type limit) - { - scoped_lock lk(fill_frames_mtx_); - - #if defined(__MINGW32__) - static bfd_context bfdc; - #endif - - symbol_context sc; - - STACKFRAME frame; std::memset(&frame, 0, sizeof frame); - CONTEXT context; std::memset(&context, 0, sizeof(CONTEXT)); - context.ContextFlags = CONTEXT_FULL; - - windows_dll kernel32("kernel32.dll"); - - void (WINAPI *RtlCaptureContext_) (CONTEXT*) = kernel32.function("RtlCaptureContext"); - - RtlCaptureContext_(&context); - - frame.AddrPC.Offset = context.Eip; - frame.AddrPC.Mode = AddrModeFlat; - frame.AddrStack.Offset = context.Esp; - frame.AddrStack.Mode = AddrModeFlat; - frame.AddrFrame.Offset = context.Ebp; - frame.AddrFrame.Mode = AddrModeFlat; - - HANDLE process = GetCurrentProcess(); - HANDLE thread = GetCurrentThread(); - - dbg::stack::depth_type skip = 0; - bool has_limit = limit != 0; - char symbol_buffer[sizeof(IMAGEHLP_SYMBOL) + 255]; - char module_name_raw[MAX_PATH]; - - while(StackWalk(IMAGE_FILE_MACHINE_I386, process, thread, - &frame, &context, 0, SymFunctionTableAccess, SymGetModuleBase, 0 )) - { - if (skip < 1) - { - ++skip; - continue; - } - - if (has_limit && limit-- == 0) break; - - IMAGEHLP_SYMBOL *symbol = reinterpret_cast<IMAGEHLP_SYMBOL *>(symbol_buffer); - symbol->SizeOfStruct = (sizeof *symbol) + 255; - symbol->MaxNameLength = 254; - - DWORD module_base = SymGetModuleBase(process, frame.AddrPC.Offset); - std::string module_name = "[unknown module]"; - if( module_base && GetModuleFileName(reinterpret_cast<HINSTANCE>(module_base), module_name_raw, MAX_PATH)) - module_name = module_name_raw; - - #if defined(__MINGW32__) - std::string func = bfdc.get_function_name(frame.AddrPC.Offset); - - if (func.empty()) - { - DWORD displacement = 0; // dummy variable - BOOL got_symbol = SymGetSymFromAddr(process, frame.AddrPC.Offset, &displacement, symbol); - func = got_symbol ? symbol->Name : "[unknown function]"; - } - #else - DWORD displacement = 0; // dummy variable - BOOL got_symbol = SymGetSymFromAddr(process, frame.AddrPC.Offset, &displacement, symbol); - std::string func = got_symbol ? symbol->Name : "[unknown function]"; - #endif - - dbg::stack_frame f(reinterpret_cast<const void *>(frame.AddrPC.Offset), func + " in " + module_name); - frames.push_back(f); - } - } -#pragma comment(lib, "DBGHELP") -#elif defined(__GNUC__) - #if defined(__i386__) || defined( __x86_64__ ) - void fill_frames(std::list<dbg::stack_frame> &frames, dbg::stack::depth_type limit) - { - // Based on code found at: - // http://www.tlug.org.za/wiki/index.php/Obtaining_a_stack_trace_in_C_upon_SIGSEGV - - Dl_info info; - void **frame = static_cast<void **>(__builtin_frame_address(0)); - void **bp = static_cast<void **>(*frame); - void *ip = frame[1]; - - bool has_limit = limit != 0; - dbg::stack::depth_type skip = 0; - - while(bp && ip && dladdr(ip, &info)) - { - if (skip < 1) - ++skip; - else - { - if (has_limit && limit-- == 0) break; - frames.push_back(dbg::stack_frame(ip, demangle(info.dli_sname) + " in " + info.dli_fname)); - - if(info.dli_sname && !strcmp(info.dli_sname, "main")) break; - } - - ip = bp[1]; - bp = static_cast<void**>(bp[0]); - } - } - - #elif defined(__ppc__) - - void fill_frames(std::list<dbg::stack_frame> &frames, dbg::stack::depth_type limit) - { - // Based on code found at: - // http://www.informit.com/articles/article.aspx?p=606582&seqNum=4&rl=1 - - void *ip = __builtin_return_address(0); - void **frame = static_cast<void **>(__builtin_frame_address(1)); - bool has_limit = limit != 0; - Dl_info info; - - do - { - if (has_limit && limit-- == 0) break; - - if (dladdr(ip, &info)) - frames.push_back(dbg::stack_frame(ip, demangle(info.dli_sname) + " in " + info.dli_fname)); - - if (frame && (frame = static_cast<void**>(*frame))) ip = *(frame + 2); - } - while (frame && ip); - } - - #else - // GNU, but neither x86 or PPC - #error "Sorry but dbg::stack is not supported on this architecture" - #endif -#else - // Unsupported compiler - #error "Sorry but dbg::stack is not supported on this compiler" -#endif -} - - - -namespace dbg -{ - stack_error::stack_error(const std::string &what) : - what_(what) - { - } - - stack_error::~stack_error() throw() - { - } - - const char *stack_error::what() const throw() - { - return what_.c_str(); - } - - - stack_frame::stack_frame(const void *instruction, const std::string &function) : - instruction_(instruction), - function_(function) - { - } - - const void *stack_frame::instruction() const - { - return instruction_; - } - - const std::string &stack_frame::function() const - { - return function_; - } - - std::ostream &operator<< (std::ostream &out, const stack_frame &frame) - { - return out << frame.instruction() << ": " << frame.function(); - } - - stack::stack(depth_type limit) - { - fill_frames(frames_, limit); - } - - stack::const_iterator stack::begin() const - { - return frames_.begin(); - } - - stack::const_iterator stack::end() const - { - return frames_.end(); - } - - stack::depth_type stack::depth() const - { - return frames_.size(); - } - -} // close namespace dbg - Copied: branches/tora-trotl/src/trotl/src/stack/stack.cpp (from rev 3439, branches/tora-trotl/src/trotl/src/stack/stack.cpp) =================================================================== --- branches/tora-trotl/src/trotl/src/stack/stack.cpp (rev 0) +++ branches/tora-trotl/src/trotl/src/stack/stack.cpp 2010-02-25 13:24:12 UTC (rev 3443) @@ -0,0 +1,433 @@ +// Copyright 2007 Edd Dawson. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include <iomanip> +#include <sstream> +#include <ostream> +#include <iostream> +#include <cassert> +#include <cstdlib> + +#include "stack.hpp" + +#if defined(_WIN32) + #include <windows.h> + #include <imagehlp.h> + + #if defined(__MINGW32__) + #include <bfd.h> // link against libbfd and libiberty + #include <psapi.h> // link against psapi + #include <cxxabi.h> + #endif + +#elif defined(__GNUC__) + #include <string.h> + #include <dlfcn.h> + #include <cxxabi.h> +#endif + +namespace +{ + +#if defined(__GNUC__) + std::string demangle(const char *name) + { + //this just does not work - some QT's private symbols cannot be resolved + //if (!name) throws dbg::stack_error then "use -rdynamic"; + if(!name) return "uknown symbol"; + int status = 0; + char *d = 0; + std::string ret = name; + try { if ((d = abi::__cxa_demangle(name, 0, 0, &status))) ret = d; } + catch(...) { } + std::free(d); + return ret; + } +#endif + +#if defined(_WIN32) + + class uncopyable + { + public: + uncopyable() { } + + private: + uncopyable(const uncopyable &); // remains undefined + uncopyable &operator= (const uncopyable &); // remains undefined + }; + + #if defined(__MINGW32__) + + class bfd_context : uncopyable + { + private: + struct find_data + { + std::string func; + asymbol **symbol_table; + bfd_vma counter; + }; + + public: + bfd_context() : + abfd_(0), + sec_(0), + symbol_table_(0) + { + char procname[MAX_PATH]; + GetModuleFileNameEx(GetCurrentProcess(), NULL, procname, sizeof procname); + + bfd_init(); + abfd_ = bfd_openr(procname, 0); + if (!abfd_) + throw dbg::stack_error("Failed to parse object data for the executable"); + + char **formats = 0; + bool b1 = bfd_check_format(abfd_, bfd_object); + bool b2 = bfd_check_format_matches(abfd_, bfd_object, &formats); + bool b3 = bfd_get_file_flags(abfd_) & HAS_SYMS; + + if (!(b1 && b2 && b3)) + { + bfd_close(abfd_); + free(formats); + throw dbg::stack_error("Failed to parse object data for the executable"); + } + free(formats); + + // Load symbol table + unsigned dummy = 0; + if (bfd_read_minisymbols(abfd_, FALSE, (void **)&symbol_table_, &dummy) == 0 && + bfd_read_minisymbols(abfd_, TRUE, (void **)&symbol_table_, &dummy) < 0) + { + free(symbol_table_); + bfd_close(abfd_); + throw dbg::stack_error("Failed to parse object data for the executable"); + } + } + + ~bfd_context() + { + free(symbol_table_); + bfd_close(abfd_); + } + + std::string get_function_name(DWORD offset) + { + find_data data; + data.symbol_table = symbol_table_; + data.counter = offset; + + bfd_map_over_sections(abfd_, &find_function_name_in_section, &data); + + return data.func; + } + + private: + static void find_function_name_in_section(bfd *abfd, asection *sec, void *opaque_data) + { + assert(sec); + assert(opaque_data); + find_data &data = *static_cast<find_data *>(opaque_data); + + if (!data.func.empty()) return; // already found it + + if (!(bfd_get_section_flags(abfd, sec) & SEC_ALLOC)) return; + + bfd_vma vma = bfd_get_section_vma(abfd, sec); + if (data.counter < vma || vma + bfd_get_section_size(sec) <= data.counter) return; + + const char *func = 0; + const char *file = 0; + unsigned line = 0; + + if (bfd_find_nearest_line(abfd, sec, data.symbol_table, data.counter - vma, &file, &func, &line) && func) + data.func = demangle(func); + } + + private: + bfd *abfd_; + asection *sec_; + asymbol **symbol_table_; + }; + + #endif // __MINGW32__ + + class auto_cast_function_ptr + { + public: + template<typename FuncPtr> + explicit auto_cast_function_ptr(FuncPtr f) : fptr_(reinterpret_cast<void (*)(void)>(f)) { } + + template<typename FuncPtr> + operator FuncPtr() const { return reinterpret_cast<FuncPtr>(fptr_); } + + private: + void (*fptr_)(void); + }; + + class windows_dll : uncopyable + { + public: + explicit windows_dll(const std::string &libname) : + name_(libname), + lib_(LoadLibrary(name_.c_str())) + { + if (!lib_) throw dbg::stack_error("Failed to load dll " + name_); + } + + ~windows_dll() { FreeLibrary(lib_); } + + const std::string &name() const { return name_; } + + auto_cast_function_ptr function(const std::string &func_name) const + { + FARPROC proc = GetProcAddress(lib_, func_name.c_str()); + if (!proc) throw dbg::stack_error("failed to load function " + func_name + " from library " + name_); + + return auto_cast_function_ptr(proc); + } + + private: + std::string name_; + HMODULE lib_; + }; + + class symbol_context : uncopyable + { + public: + symbol_context() { SymInitialize(GetCurrentProcess(), 0, true); } + ~symbol_context() { SymCleanup(GetCurrentProcess()); } + }; + + + class mutex : uncopyable + { + public: + mutex() { InitializeCriticalSection(&cs_); } + ~mutex() { DeleteCriticalSection(&cs_); } + void lock() { EnterCriticalSection(&cs_); } + void unlock() { LeaveCriticalSection(&cs_); } + + private: + CRITICAL_SECTION cs_; + }; + + class scoped_lock : uncopyable + { + public: + scoped_lock(mutex &m) : m_(m) { m_.lock(); } + ~scoped_lock() { m_.unlock(); } + private: + mutex &m_; + }; + + mutex fill_frames_mtx_; + + + void fill_frames(std::list<dbg::stack_frame> &frames, dbg::stack::depth_type limit) + { + scoped_lock lk(fill_frames_mtx_); + + #if defined(__MINGW32__) + static bfd_context bfdc; + #endif + + symbol_context sc; + + STACKFRAME frame; std::memset(&frame, 0, sizeof frame); + CONTEXT context; std::memset(&context, 0, sizeof(CONTEXT)); + context.ContextFlags = CONTEXT_FULL; + + windows_dll kernel32("kernel32.dll"); + + void (WINAPI *RtlCaptureContext_) (CONTEXT*) = kernel32.function("RtlCaptureContext"); + + RtlCaptureContext_(&context); + + frame.AddrPC.Offset = context.Eip; + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrStack.Offset = context.Esp; + frame.AddrStack.Mode = AddrModeFlat; + frame.AddrFrame.Offset = context.Ebp; + frame.AddrFrame.Mode = AddrModeFlat; + + HANDLE process = GetCurrentProcess(); + HANDLE thread = GetCurrentThread(); + + dbg::stack::depth_type skip = 0; + bool has_limit = limit != 0; + char symbol_buffer[sizeof(IMAGEHLP_SYMBOL) + 255]; + char module_name_raw[MAX_PATH]; + + while(StackWalk(IMAGE_FILE_MACHINE_I386, process, thread, + &frame, &context, 0, SymFunctionTableAccess, SymGetModuleBase, 0 )) + { + if (skip < 1) + { + ++skip; + continue; + } + + if (has_limit && limit-- == 0) break; + + IMAGEHLP_SYMBOL *symbol = reinterpret_cast<IMAGEHLP_SYMBOL *>(symbol_buffer); + symbol->SizeOfStruct = (sizeof *symbol) + 255; + symbol->MaxNameLength = 254; + + DWORD module_base = SymGetModuleBase(process, frame.AddrPC.Offset); + std::string module_name = "[unknown module]"; + if( module_base && GetModuleFileName(reinterpret_cast<HINSTANCE>(module_base), module_name_raw, MAX_PATH)) + module_name = module_name_raw; + + #if defined(__MINGW32__) + std::string func = bfdc.get_function_name(frame.AddrPC.Offset); + + if (func.empty()) + { + DWORD displacement = 0; // dummy variable + BOOL got_symbol = SymGetSymFromAddr(process, frame.AddrPC.Offset, &displacement, symbol); + func = got_symbol ? symbol->Name : "[unknown function]"; + } + #else + DWORD displacement = 0; // dummy variable + BOOL got_symbol = SymGetSymFromAddr(process, frame.AddrPC.Offset, &displacement, symbol); + std::string func = got_symbol ? symbol->Name : "[unknown function]"; + #endif + + dbg::stack_frame f(reinterpret_cast<const void *>(frame.AddrPC.Offset), func + " in " + module_name); + frames.push_back(f); + } + } +#pragma comment(lib, "DBGHELP") +#elif defined(__GNUC__) + #if defined(__i386__) || defined( __x86_64__ ) + void fill_frames(std::list<dbg::stack_frame> &frames, dbg::stack::depth_type limit) + { + // Based on code found at: + // http://www.tlug.org.za/wiki/index.php/Obtaining_a_stack_trace_in_C_upon_SIGSEGV + + Dl_info info; + void **frame = static_cast<void **>(__builtin_frame_address(0)); + void **bp = static_cast<void **>(*frame); + void *ip = frame[1]; + + bool has_limit = limit != 0; + dbg::stack::depth_type skip = 0; + + while(bp && ip && dladdr(ip, &info)) + { + if (skip < 1) + ++skip; + else + { + if (has_limit && limit-- == 0) break; + frames.push_back(dbg::stack_frame(ip, demangle(info.dli_sname) + " in " + info.dli_fname)); + + if(info.dli_sname && !strcmp(info.dli_sname, "main")) break; + } + + ip = bp[1]; + bp = static_cast<void**>(bp[0]); + } + } + + #elif defined(__ppc__) + + void fill_frames(std::list<dbg::stack_frame> &frames, dbg::stack::depth_type limit) + { + // Based on code found at: + // http://www.informit.com/articles/article.aspx?p=606582&seqNum=4&rl=1 + + void *ip = __builtin_return_address(0); + void **frame = static_cast<void **>(__builtin_frame_address(1)); + bool has_limit = limit != 0; + Dl_info info; + + do + { + if (has_limit && limit-- == 0) break; + + if (dladdr(ip, &info)) + frames.push_back(dbg::stack_frame(ip, demangle(info.dli_sname) + " in " + info.dli_fname)); + + if (frame && (frame = static_cast<void**>(*frame))) ip = *(frame + 2); + } + while (frame && ip); + } + + #else + // GNU, but neither x86 or PPC + #error "Sorry but dbg::stack is not supported on this architecture" + #endif +#else + // Unsupported compiler + #error "Sorry but dbg::stack is not supported on this compiler" +#endif +} + + + +namespace dbg +{ + stack_error::stack_error(const std::string &what) : + what_(what) + { + } + + stack_error::~stack_error() throw() + { + } + + const char *stack_error::what() const throw() + { + return what_.c_str(); + } + + + stack_frame::stack_frame(const void *instruction, const std::string &function) : + instruction_(instruction), + function_(function) + { + } + + const void *stack_frame::instruction() const + { + return instruction_; + } + + const std::string &stack_frame::function() const + { + return function_; + } + + std::ostream &operator<< (std::ostream &out, const stack_frame &frame) + { + return out << frame.instruction() << ": " << frame.function(); + } + + stack::stack(depth_type limit) + { + fill_frames(frames_, limit); + } + + stack::const_iterator stack::begin() const + { + return frames_.begin(); + } + + stack::const_iterator stack::end() const + { + return frames_.end(); + } + + stack::depth_type stack::depth() const + { + return frames_.size(); + } + +} // close namespace dbg + Deleted: branches/tora-trotl/src/trotl/src/stack/stack.hpp =================================================================== --- branches/tora-trotl/src/trotl/src/stack/stack.hpp 2010-02-25 09:54:47 UTC (rev 3439) +++ branches/tora-trotl/src/trotl/src/stack/stack.hpp 2010-02-25 13:24:12 UTC (rev 3443) @@ -1,64 +0,0 @@ -// Copyright 2007 Edd Dawson. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef STACK_HPP_0022_01092007 -#define STACK_HPP_0022_01092007 - -#include <string> -#include <list> -#include <stdexcept> -#include <iosfwd> - - -namespace dbg -{ - class stack_error : public std::exception - { - public: - stack_error(const std::string &what); - ~stack_error() throw(); - - const char *what() const throw(); - - private: - std::string what_; - }; - - class stack_frame - { - public: - stack_frame(const void *instruction, const std::string &function); - - const void *instruction() const; - const std::string &function() const; - - private: - const void *instruction_; - const std::string function_; - }; - - std::ostream &operator<< (std::ostream &out, const stack_frame &frame); - - class stack - { - public: - typedef std::list<stack_frame>::size_type depth_type; - typedef std::list<stack_frame>::const_iterator const_iterator; - - stack(depth_type limit = 0); - - const_iterator begin() const; - const_iterator end() const; - - depth_type depth() const; - - private: - std::list<stack_frame> frames_; - }; - - -} // close namespace dbg - -#endif // STACK_HPP_0022_01092007 Copied: branches/tora-trotl/src/trotl/src/stack/stack.hpp (from rev 3439, branches/tora-trotl/src/trotl/src/stack/stack.hpp) =================================================================== --- branches/tora-trotl/src/trotl/src/stack/stack.hpp (rev 0) +++ branches/tora-trotl/src/trotl/src/stack/stack.hpp 2010-02-25 13:24:12 UTC (rev 3443) @@ -0,0 +1,64 @@ +// Copyright 2007 Edd Dawson. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef STACK_HPP_0022_01092007 +#define STACK_HPP_0022_01092007 + +#include <string> +#include <list> +#include <stdexcept> +#include <iosfwd> + + +namespace dbg +{ + class stack_error : public std::exception + { + public: + stack_error(const std::string &what); + ~stack_error() throw(); + + const char *what() const throw(); + + private: + std::string what_; + }; + + class stack_frame + { + public: + stack_frame(const void *instruction, const std::string &function); + + const void *instruction() const; + const std::string &function() const; + + private: + const void *instruction_; + const std::string function_; + }; + + std::ostream &operator<< (std::ostream &out, const stack_frame &frame); + + class stack + { + public: + typedef std::list<stack_frame>::size_type depth_type; + typedef std::list<stack_frame>::const_iterator const_iterator; + + stack(depth_type limit = 0); + + const_iterator begin() const; + const_iterator end() const; + + depth_type depth() const; + + private: + std::list<stack_frame> frames_; + }; + + +} // close namespace dbg + +#endif // STACK_HPP_0022_01092007 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |