SVN: backtracexx: LICENSE backtracexx.cpp backtracexx.hpp example.cpp makefile
pluto
pluto at pld-linux.org
Thu Jul 12 14:22:23 CEST 2007
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
More information about the pld-cvs-commit
mailing list