使用API钩子技术,抓取throw调用的调用堆栈。
1. hook_cxa_throw-lys.hpp
#pragma once #include#include #include #include #include #include #include #ifdef __GNUC__ typedef void __attribute__((__noreturn__)) (*cxa_throw_type)(void*, void*, void(*)(void*)); #elif defined(__clang__) typedef void __attribute__((__noreturn__)) (*cxa_throw_type)(void*, std::type_info*, void (_GLIBCXX_CDTOR_CALLABI*) (void*)); #endif cxa_throw_type orig_cxa_throw = nullptr; void load_orig_throw_code() { orig_cxa_throw = (cxa_throw_type) dlsym(RTLD_NEXT, "__cxa_throw"); } extern "C" #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #ifdef __clang__ void __cxa_throw(void* thrown_exception, std::type_info* typeifo, void (_GLIBCXX_CDTOR_CALLABI* dest)(void*)) #elif defined(__GNUC__) void __cxa_throw(void* thrown_exception, void* pvtinfo, void (*dest)(void *)) #endif { if (orig_cxa_throw == nullptr) load_orig_throw_code(); int nptrs; void *buffer[32]; char **strings; nptrs = backtrace(buffer, 32); strings = backtrace_symbols(buffer, nptrs); if (strings != NULL) { for (int j = 0; j < nptrs; j++) { size_t p = 0; while(strings[j][p] != '(' && strings[j][p] != ' ' && strings[j][p] != 0) ++p; char syscom[256]; sprintf(syscom,"addr2line %p -e %.*s", buffer[j], p, strings[j]); //last parameter is the file name of the symbol system(syscom); printf("%sn", strings[j]); } free(strings); } #ifdef __clang__ orig_cxa_throw(thrown_exception, typeifo, dest); #elif defined(__GNUC__) orig_cxa_throw(thrown_exception, pvtinfo, dest); #endif }
2. main.cpp
#include#include #include "hook_cxa_throw-lys.hpp" int mytest() { try { throw "mythrow char strings"; } catch(const char* sz) { std::cout << sz << "n"; } return 0; } int main(int argc, char* argv[]) { printf("hello, worldn"); mytest(); return 0; }
3. 编译
g++ -g -std=c++0x -pthread -ldl -rdynamic main.cpp -o testThrow.out
4. 运行:
./testThrow.out



