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