Author: pluto Date: Thu Jul 12 14:22:23 2007 New Revision: 8671 Modified: backtracexx/LICENSE backtracexx/backtracexx.cpp backtracexx/backtracexx.hpp backtracexx/example.cpp backtracexx/makefile Log: - use ::StackWalk64 on winnt instead of primitive assembly. - add operator << for std::ostream. - tweak makefile and example. - detailed note about license version.
Modified: backtracexx/LICENSE ============================================================================== --- backtracexx/LICENSE (original) +++ backtracexx/LICENSE Thu Jul 12 14:22:23 2007 @@ -1 +1,2 @@ +the backtracexx library is licensed under LGPL v2.1. http://www.opensource.org/licenses/lgpl-license.php Modified: backtracexx/backtracexx.cpp ============================================================================== --- backtracexx/backtracexx.cpp (original) +++ backtracexx/backtracexx.cpp Thu Jul 12 14:22:23 2007 @@ -1,4 +1,6 @@ #include "backtracexx.hpp" +#include <iomanip> +#include <iostream> #if defined( __GNUC__ ) #include <cxxabi.h> @@ -155,37 +157,56 @@ #elif defined( _MSC_VER ) && defined( WIN32 ) - ::SymInitialize( ::GetCurrentProcess(), 0, FALSE ); + ::HANDLE process = ::GetCurrentProcess(); + ::SymInitialize( process, 0, FALSE ); ::SymSetOptions( ::SymGetOptions() | SYMOPT_UNDNAME ); - struct StackFrame - { - StackFrame* previousFrame; - unsigned long returnAddress; - }; - StackFrame const* stackFrame; - __asm mov stackFrame, ebp; - // - // the deepest frame pointer and return address of the process - // call chain are zeroed by kernel32.dll during process startup: - // - // BaseProcessStartThunk: - // xor ebp,ebp - // push eax - // push 0x0 - // jmp KERNEL32!BaseProcessStart - // - while ( stackFrame->returnAddress ) + ::CONTEXT context = { 0 }; + ::STACKFRAME64 stackFrame = { 0 }; + stackFrame.AddrPC.Mode = stackFrame.AddrFrame.Mode = stackFrame.AddrStack.Mode = AddrModeFlat; + __asm + { + call $ + 5; + pop eax; + mov context.Eip, eax; + mov context.Esp, esp; + mov context.Ebp, ebp; + mov stackFrame.AddrPC, eax; + mov stackFrame.AddrStack, esp; + mov stackFrame.AddrFrame, ebp; + } + while ( ::StackWalk64( IMAGE_FILE_MACHINE_I386, process, ::GetCurrentThread(), + &stackFrame, &context, 0, ::SymFunctionTableAccess64, ::SymGetModuleBase64, 0 ) ) { Frame frame; - frame.address = caller( stackFrame->returnAddress ); + frame.address = static_cast< unsigned long >( stackFrame.AddrReturn.Offset ); + // + // the deepest frame pointer and return address of the process + // call chain are zeroed by kernel32.dll during process startup, + // so exclude such frame from trace and exit from loop. + // + if ( !frame.address ) + break; lookupSymbol( frame ); trace.push_back( frame ); - stackFrame = stackFrame->previousFrame; } - ::SymCleanup( ::GetCurrentProcess() ); + ::SymCleanup( process ); #endif return trace; } + + std::ostream& operator << ( std::ostream& os, Trace const& t ) + { + os << "=== backtrace ====" << std::endl; + for ( backtracexx::Trace::const_iterator i = t.begin(); i != t.end(); ++i ) + { + backtracexx::Frame const& f = *i; + os << std::showbase << std::showpoint << std::hex << std::setw( 16 ) << f.address + << " : " << ( f.symbol.empty() ? "<unresolved symbol>" : f.symbol ) + << "+" << f.displacement << " [" << f.module << "]" << std::endl; + } + os << "==================" << std::endl; + return os; + } } Modified: backtracexx/backtracexx.hpp ============================================================================== --- backtracexx/backtracexx.hpp (original) +++ backtracexx/backtracexx.hpp Thu Jul 12 14:22:23 2007 @@ -1,12 +1,23 @@ #ifndef backtracexx_hpp #define backtracexx_hpp +#include <iosfwd> #include <string> #include <vector> +#if defined( WIN32 ) || defined( WIN64 ) +#ifdef BACKTRACEXX_EXPORTS +#define DEBUGTOOLS_EXPORT __declspec( dllexport ) +#else +#define DEBUGTOOLS_EXPORT __declspec( dllimport ) +#endif +#else +#define DEBUGTOOLS_EXPORT __attribute__(( visibility( "default" ) )) +#endif + namespace backtracexx { - struct Frame + struct DEBUGTOOLS_EXPORT Frame { Frame(); @@ -19,7 +30,8 @@ typedef std::vector< Frame > Trace; - Trace scan(); + DEBUGTOOLS_EXPORT Trace scan(); + DEBUGTOOLS_EXPORT std::ostream& operator << ( std::ostream&, Trace const& ); } #endif Modified: backtracexx/example.cpp ============================================================================== --- backtracexx/example.cpp (original) +++ backtracexx/example.cpp Thu Jul 12 14:22:23 2007 @@ -10,14 +10,7 @@ void signalHandler( int signalNumber ) { - backtracexx::Trace t = backtracexx::scan(); - for ( backtracexx::Trace::const_iterator i = t.begin(); i != t.end(); ++i ) - { - backtracexx::Frame const& f = *i; - std::printf( "0x%016lx : %s+0x%lx [%s]\n", f.address, - ( f.symbol.empty() ? "<unresolved symbol>" : f.symbol.c_str() ), - f.displacement, f.module.c_str() ); - } + std::cerr << backtracexx::scan(); longjmp( context, 1 ); } Modified: backtracexx/makefile ============================================================================== --- backtracexx/makefile (original) +++ backtracexx/makefile Thu Jul 12 14:22:23 2007 @@ -1,13 +1,11 @@ CXX := g++ CXXFLAGS := -O1 -Wall -Werror -pedantic -LDXXFLAGS := -Wl,-export-dynamic -s -ldl -static-libgcc all: example example: example.cpp backtracexx.hpp backtracexx.cpp - $(CXX) $(CXXFLAGS) backtracexx.cpp -c - $(CXX) $(CXXFLAGS) example.cpp -c - $(CXX) example.o backtracexx.o -o example $(LDXXFLAGS) + $(CXX) $(CXXFLAGS) -fpic backtracexx.cpp -o libbacktracexx.so -shared -s -ldl -static-libgcc + $(CXX) $(CXXFLAGS) example.cpp -o example ./libbacktracexx.so -s -Wl,--export-dynamic clean: - rm -f *.o *.s *.ii example + rm -f *.o *.s *.ii example libbacktracexx.so _______________________________________________ pld-cvs-commit mailing list [email protected] http://lists.pld-linux.org/mailman/listinfo/pld-cvs-commit
