├── test ├── main.cpp ├── CMakeLists.txt └── test.vcxproj ├── README.md ├── LICENSE └── traceback.h /test/main.cpp: -------------------------------------------------------------------------------- 1 | #include "../traceback.h" 2 | 3 | void func(int a) 4 | { 5 | std::cout << zsummer::traceback(); 6 | } 7 | int main(int argc, char *argv[]) 8 | { 9 | func(1); 10 | 11 | return 0; 12 | } 13 | 14 | /* 15 | g++ stack.cpp -g -O0 16 | gdb info line * 0x40000000 17 | google coredumper 18 | */ -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(test) 3 | 4 | include_directories(../) 5 | aux_source_directory(./ source) 6 | set(EXECUTABLE_OUTPUT_PATH ./) 7 | 8 | 9 | if (CMAKE_BUILD_TYPE STREQUAL "Debug") 10 | add_definitions(-Wall -g -ggdb -O0 -D_GLIBCXX_USE_NANOSLEEP) 11 | else() 12 | add_definitions(-Wall -O2 -DNDEBUG -D_GLIBCXX_USE_NANOSLEEP) 13 | endif() 14 | 15 | set(CMAKE_CXX_FLAGS -std=c++11) 16 | 17 | add_executable(test ${source} ) 18 | 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # traceback简述 2 | C++ traceback library cross-plat win & linux. 3 | C++运行时堆栈信息获取, 支持win,linux,mac 4 | 5 | # 使用方法 6 | 使用方法为在需要获取堆栈信息的位置如下调用即可: 7 | ``` C++ 8 | std::string tb = traceback(); 9 | ``` 10 | 11 | # 部分说明 12 | 在gcc下traceback在动态符号库中获取符号名, 如果是静态链接 可能获取不到符号名, 但依然可以获取到堆栈的地址信息. 13 | 通过gdb或者addr2line 或者nm 可以从外部正确获取实际的符号信息. 该函数的返回已经自动排版好地址的格式可以直接复制通过shell命令获取符号信息.   14 | 命令和使用方法如下,具体man手册: 15 | ```shell 16 | gdb info line * 0x40000000 17 | addr2line -f -C -e ./test 0x400fce 0x401027 0x7f2bfb401b45 0x400ee9 18 | ``` 19 | # 备忘 20 | gcc调试hook   21 | ``` 22 | gcc -finstrument-functions 23 | void __attribute__((no_instrument_function)) 24 | __cyg_profile_func_enter(void *this_func, void *call_site); 25 | void __attribute__((no_instrument_function))   26 | __cyg_profile_func_exit(void *this_func, void *call_site); 27 | ``` 28 | vs调试hook 29 | ``` 30 | /Gh (Enable _penter Hook Function) 31 | /GH (Enable _pexit Hook Function) 32 | ``` 33 | # About The Author     34 | **Author**: YaweiZhang 35 | **Mail**: yawei.zhang@foxmail.com 36 | **GitHub**: https://github.com/zsummer/traceback 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | /* 2 | * traceback License 3 | * ----------- 4 | * 5 | * traceback is licensed under the terms of the MIT license reproduced below. 6 | * This means that Log4z is free software and can be used for both academic 7 | * and commercial purposes at absolutely no cost. 8 | * 9 | * 10 | * =============================================================================== 11 | * 12 | * Copyright (C) 2015 YaweiZhang . 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining a copy 15 | * of this software and associated documentation files (the "Software"), to deal 16 | * in the Software without restriction, including without limitation the rights 17 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | * copies of the Software, and to permit persons to whom the Software is 19 | * furnished to do so, subject to the following conditions: 20 | * 21 | * The above copyright notice and this permission notice shall be included in 22 | * all copies or substantial portions of the Software. 23 | * 24 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 30 | * THE SOFTWARE. 31 | * 32 | * =============================================================================== 33 | * 34 | * (end of COPYRIGHT) 35 | */ 36 | -------------------------------------------------------------------------------- /traceback.h: -------------------------------------------------------------------------------- 1 | /* 2 | * traceback License 3 | * ----------- 4 | * 5 | * traceback is licensed under the terms of the MIT license reproduced below. 6 | * This means that Log4z is free software and can be used for both academic 7 | * and commercial purposes at absolutely no cost. 8 | * 9 | * 10 | * =============================================================================== 11 | * 12 | * Copyright (C) 2015 YaweiZhang . 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining a copy 15 | * of this software and associated documentation files (the "Software"), to deal 16 | * in the Software without restriction, including without limitation the rights 17 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | * copies of the Software, and to permit persons to whom the Software is 19 | * furnished to do so, subject to the following conditions: 20 | * 21 | * The above copyright notice and this permission notice shall be included in 22 | * all copies or substantial portions of the Software. 23 | * 24 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 30 | * THE SOFTWARE. 31 | * 32 | * =============================================================================== 33 | * 34 | * (end of COPYRIGHT) 35 | */ 36 | 37 | 38 | #ifdef WIN32 39 | #ifndef _CRT_SECURE_NO_WARNINGS 40 | #define _CRT_SECURE_NO_WARNINGS 41 | #endif 42 | #include 43 | #include 44 | #include 45 | #include 46 | #pragma comment(lib, "Dbghelp") 47 | #else 48 | #include 49 | #include 50 | #endif 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | using namespace std; 58 | 59 | namespace zsummer 60 | { 61 | 62 | inline std::string traceback() 63 | { 64 | std::stringstream ss; 65 | #ifdef WIN32 66 | 67 | SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); 68 | if (!SymInitialize(GetCurrentProcess(), NULL, TRUE)) 69 | { 70 | ss << "SymInitialize returned error " << GetLastError(); 71 | return ss.str(); 72 | } 73 | 74 | // typedef USHORT(WINAPI *CaptureStackBackTraceType)(__in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG); 75 | // CaptureStackBackTraceType capture = (CaptureStackBackTraceType)(GetProcAddress(LoadLibraryA("kernel32.dll"), "RtlCaptureStackBackTrace")); 76 | // if (capture == NULL) return; 77 | const int stackMax = 128; 78 | void* trace[stackMax]; 79 | // int count = (capture)(0, stackMax, trace, NULL); 80 | int count = (CaptureStackBackTrace)(0, stackMax, trace, NULL); 81 | for (int i = 1; i < count; i++) 82 | { 83 | ULONG64 buffer[(sizeof(SYMBOL_INFO)+MAX_SYM_NAME*sizeof(TCHAR)+sizeof(ULONG64)-1) / sizeof(ULONG64)]; 84 | PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; 85 | pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); 86 | pSymbol->MaxNameLen = MAX_SYM_NAME; 87 | DWORD64 dwDisplacement = 0; 88 | if (SymFromAddr(GetCurrentProcess(), (DWORD64)trace[i], &dwDisplacement, pSymbol)) 89 | { 90 | ss << "bt[" << i - 1 << "] --[ " << pSymbol->Name << " ]-- from "; 91 | } 92 | else 93 | { 94 | ss << "bt[" << i - 1 << "] " << "error[" << GetLastError() << "] from "; 95 | } 96 | 97 | IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE64) }; 98 | DWORD dwLineDisplacement; 99 | if (SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)trace[i], &dwLineDisplacement, &lineInfo)) 100 | { 101 | std::string pathfile = lineInfo.FileName; 102 | if (pathfile.empty()) 103 | { 104 | ss << "\r\n"; 105 | continue; 106 | } 107 | std::for_each(pathfile.begin(), pathfile.end(), [](char &ch){ if (ch == '/') ch = '\\'; }); 108 | auto pos = pathfile.find_last_of('\\'); 109 | if (pos != std::string::npos) pathfile[pos] = '/'; 110 | pos = pathfile.find_last_of('\\'); 111 | if (pos != std::string::npos) pathfile[pos] = '/'; else pos = -1; 112 | ss << pathfile.substr(pos + 1) << ":" << lineInfo.LineNumber; 113 | } 114 | else 115 | { 116 | ss << "------:0"; 117 | } 118 | ss << "\r\n"; 119 | if (strcmp(pSymbol->Name, "main") == 0) break; 120 | } 121 | #else 122 | void *stack[200]; 123 | size_t size = backtrace(stack, 200); 124 | char **stackSymbol = backtrace_symbols(stack, size); 125 | ss << "backtrace: "; 126 | for (size_t i = 1; i < size; i++ ) 127 | { 128 | ss << stack[i] << " "; 129 | } 130 | ss << "\r\n"; 131 | for (size_t i = 1; i < size && stackSymbol != NULL; i++) 132 | { 133 | ss << "bt[" << i - 1 << "] " << stackSymbol[i] << "\r\n"; 134 | } 135 | free(stackSymbol); 136 | #endif 137 | return std::move(ss.str()); 138 | } 139 | } 140 | 141 | 142 | 143 | /* 144 | gdb info line * 0x40000000 145 | addr2line -f -C -e ./test 0x400fce 0x401027 0x7f2bfb401b45 0x400ee9 146 | */ 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /test/test.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {6B98CAD6-9E8E-42E8-A5CF-120CCF6AE293} 23 | Win32Proj 24 | ConsoleApplication1 25 | 26 | 27 | 28 | Application 29 | true 30 | v120 31 | Unicode 32 | 33 | 34 | Application 35 | true 36 | v120 37 | Unicode 38 | 39 | 40 | Application 41 | false 42 | v120 43 | true 44 | Unicode 45 | 46 | 47 | Application 48 | false 49 | v120 50 | true 51 | Unicode 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | true 71 | 72 | 73 | true 74 | 75 | 76 | false 77 | 78 | 79 | false 80 | 81 | 82 | 83 | 84 | 85 | Level3 86 | Disabled 87 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 88 | true 89 | 90 | 91 | Console 92 | true 93 | 94 | 95 | 96 | 97 | 98 | 99 | Level3 100 | Disabled 101 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 102 | true 103 | 104 | 105 | Console 106 | true 107 | 108 | 109 | 110 | 111 | Level3 112 | 113 | 114 | MaxSpeed 115 | true 116 | true 117 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 118 | true 119 | 120 | 121 | Console 122 | true 123 | true 124 | true 125 | 126 | 127 | 128 | 129 | Level3 130 | 131 | 132 | MaxSpeed 133 | true 134 | true 135 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 136 | true 137 | 138 | 139 | Console 140 | true 141 | true 142 | true 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | --------------------------------------------------------------------------------