diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..cff2ca5 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.1) + +project(backtracexx) + +add_library(${PROJECT_NAME} SHARED "backtracexx.cpp") +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(${PROJECT_NAME} ${CMAKE_DL_LIBS}) + +add_executable(${PROJECT_NAME}_example "example.cpp") +set_target_properties(${PROJECT_NAME} PROPERTIES ENABLE_EXPORTS 1) +target_link_libraries(${PROJECT_NAME}_example ${PROJECT_NAME}) + diff --git a/README.md b/README.md index 0240e7e..193cbd7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,75 @@ -This small library uses unwind information and produces backtrace -with optionally demangled symbols. +# backtracexx : cross-platform backtrace generation on Linux/MacOS/Windows + +This small library uses unwind information and produces backtrace with optionally demangled symbols. + +The [original sources](http://svn.pld-linux.org/cgi-bin/viewsvn/backtracexx/) are no longer available, but were imported to [GitHub](https://github.com/borneq/backtracexx) by Andrzej Borucki. + +## Building + +Note: currently, a GCC flavor of C++ compiler is required (that is, the code will not compile with e.g. Clang): + +``` +mkdir build +cmake -DCMAKE_CXX_COMPILER=g++-11 .. +make +``` + +## Usage + +The following example program produces the output below: + +```c++ +#include "backtracexx.hpp" + +#include +#include +#include + +jmp_buf context; + +void signalHandler( int signalNumber ) +{ + std::cerr << backtracexx::scan(); + longjmp( context, 1 ); +} + +void zoo() +{ + if ( setjmp( context ) == 0 ) + { + volatile int* p = 0; + *p = 0; + } +} + +void bar( void ( *f )() ) +{ + f(); +} + +void foo() +{ + bar( &zoo ); +} + +int main( int argc, char const* const* argv ) +{ + signal( SIGSEGV, signalHandler ); + foo(); + return 0; +} +``` + +``` +./backtracexx_example +=== backtrace ==== + 0x10c81c55c : backtracexx::scan[abi:cxx11](void*)+0x33 [/Users/dmikushin/backtracexx/build/libbacktracexx.dylib @ 0x10c81a000 ] + 0x10c811588 : signalHandler(int)+0x1d [/Users/dmikushin/backtracexx/build/./backtracexx_example @ 0x10c80f000 ] + 0x7fff6383b42d : _sigtramp+0x1d [/usr/lib/system/libsystem_platform.dylib @ 0x7fff63837000 ] + 0x10c811605 : zoo()+0x2d [/Users/dmikushin/backtracexx/build/./backtracexx_example @ 0x10c80f000 ] + 0x10c81161f : bar(void (*)())+0x12 [/Users/dmikushin/backtracexx/build/./backtracexx_example @ 0x10c80f000 ] + 0x10c811635 : foo()+0x13 [/Users/dmikushin/backtracexx/build/./backtracexx_example @ 0x10c80f000 ] + 0x10c811660 : main+0x28 [/Users/dmikushin/backtracexx/build/./backtracexx_example @ 0x10c80f000 ] +================== +``` -Sources available at: - (original) http://svn.pld-linux.org/cgi-bin/viewsvn/backtracexx/ - (imported to) https://github.com/borneq/backtracexx diff --git a/backtracexx.cpp b/backtracexx.cpp index 4ed7692..0a86c79 100644 --- a/backtracexx.cpp +++ b/backtracexx.cpp @@ -11,7 +11,7 @@ #if defined( __GNUC__ ) #include -#if defined( __linux__ ) +#if defined( __linux__ ) || defined( __APPLE__ ) #include #endif #include @@ -45,7 +45,7 @@ namespace backtracexx bool lookupSymbol( Frame& frame ) { -#if defined( __linux__ ) +#if defined( __linux__ ) || defined( __APPLE__ ) Dl_info info; if ( ::dladdr( frame.address, &info ) ) @@ -55,6 +55,7 @@ namespace backtracexx frame.moduleName = info.dli_fname; if ( info.dli_saddr ) { + frame.symbolMangled = info.dli_sname; frame.displacement = reinterpret_cast< ::ptrdiff_t >( frame.address ) - reinterpret_cast< ::ptrdiff_t >( info.dli_saddr ); int status; @@ -81,7 +82,7 @@ namespace backtracexx { struct TraceHelper { - _Unwind_Ptr prevIp; + _Unwind_Ptr prevIp = -1; unsigned recursionDepth; Trace trace; }; diff --git a/backtracexx.hpp b/backtracexx.hpp index 5bc1c34..84b1ce3 100644 --- a/backtracexx.hpp +++ b/backtracexx.hpp @@ -32,6 +32,7 @@ namespace backtracexx void const* address; std::string symbol; + std::string symbolMangled; long displacement; std::string moduleName; void const* moduleBaseAddress; diff --git a/makefile b/makefile deleted file mode 100644 index a2f3a33..0000000 --- a/makefile +++ /dev/null @@ -1,19 +0,0 @@ -# linux32 target -CXX32 := i486-gnu-linux-g++ - -# linux64 target -CXX64 := x86_64-gnu-linux-g++ - -CXXFLAGS := -Wall -Werror -pedantic -shared-libgcc -g2 - -all: example - -example: example.cpp backtracexx.hpp backtracexx.cpp - @mkdir -p bin-linux-{32,64} - $(CXX32) $(CXXFLAGS) -fpic backtracexx.cpp -o bin-linux-32/libbacktracexx.so -shared -ldl - $(CXX32) $(CXXFLAGS) example.cpp -o bin-linux-32/example -Lbin-linux-32 -lbacktracexx -Wl,--export-dynamic -Wl,-rpath,. - $(CXX64) $(CXXFLAGS) -fpic backtracexx.cpp -o bin-linux-64/libbacktracexx.so -shared -ldl - $(CXX64) $(CXXFLAGS) example.cpp -o bin-linux-64/example -Lbin-linux-64 -lbacktracexx -Wl,--export-dynamic -Wl,-rpath,. - -clean: - rm -rf bin-linux-{32,64} diff --git a/makefile.mingw b/makefile.mingw deleted file mode 100644 index 5ee20d5..0000000 --- a/makefile.mingw +++ /dev/null @@ -1,19 +0,0 @@ -# win32 target -CXX32 := i686-pc-mingw32-g++ - -# win64 target -CXX64 := x86_64-pc-mingw32-g++ - -CXXFLAGS := -Wall -Werror -pedantic -shared-libgcc -g2 - -all: example - -example: example.cpp backtracexx.hpp backtracexx.cpp - @mkdir -p bin-mingw-{32,64} - $(CXX32) $(CXXFLAGS) -DBACKTRACEXX_EXPORTS backtracexx.cpp -o bin-mingw-32/backtracexx.dll -shared - $(CXX32) $(CXXFLAGS) example.cpp -o bin-mingw-32/example.exe -Lbin-mingw-32 -lbacktracexx - $(CXX64) $(CXXFLAGS) -DBACKTRACEXX_EXPORTS backtracexx.cpp -o bin-mingw-64/backtracexx.dll -shared - $(CXX64) $(CXXFLAGS) example.cpp -o bin-mingw-64/example.exe -Lbin-mingw-64 -lbacktracexx - -clean: - rm -rf bin-mingw-{32,64} diff --git a/msvc/backtracexx/backtracexx.vcproj b/msvc/backtracexx/backtracexx.vcproj deleted file mode 100644 index eb4fb76..0000000 --- a/msvc/backtracexx/backtracexx.vcproj +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/msvc/example/example.vcproj b/msvc/example/example.vcproj deleted file mode 100644 index 0e82bab..0000000 --- a/msvc/example/example.vcproj +++ /dev/null @@ -1,183 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/msvc/msvc.sln b/msvc/msvc.sln deleted file mode 100644 index 7a4e39f..0000000 --- a/msvc/msvc.sln +++ /dev/null @@ -1,29 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual C++ Express 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "backtracexx", "backtracexx\backtracexx.vcproj", "{D58D1D6B-B8DB-43F7-836D-BF37AB591841}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example", "example\example.vcproj", "{A0C7A39E-B6D4-4E80-ACB3-E65809D582F2}" - ProjectSection(ProjectDependencies) = postProject - {D58D1D6B-B8DB-43F7-836D-BF37AB591841} = {D58D1D6B-B8DB-43F7-836D-BF37AB591841} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D58D1D6B-B8DB-43F7-836D-BF37AB591841}.Debug|Win32.ActiveCfg = Debug|Win32 - {D58D1D6B-B8DB-43F7-836D-BF37AB591841}.Debug|Win32.Build.0 = Debug|Win32 - {D58D1D6B-B8DB-43F7-836D-BF37AB591841}.Release|Win32.ActiveCfg = Release|Win32 - {D58D1D6B-B8DB-43F7-836D-BF37AB591841}.Release|Win32.Build.0 = Release|Win32 - {A0C7A39E-B6D4-4E80-ACB3-E65809D582F2}.Debug|Win32.ActiveCfg = Debug|Win32 - {A0C7A39E-B6D4-4E80-ACB3-E65809D582F2}.Debug|Win32.Build.0 = Debug|Win32 - {A0C7A39E-B6D4-4E80-ACB3-E65809D582F2}.Release|Win32.ActiveCfg = Release|Win32 - {A0C7A39E-B6D4-4E80-ACB3-E65809D582F2}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal