使用API钩子技术,抓取throw调用的调用堆栈。
1. hook_cxa_throw-lys.hpp
#pragma once
#include <dlfcn.h>
#include <cstddef>
#include <exception>
#include <signal.h>
#include <execinfo.h>
#include <ucontext.h>
#include <thread>
#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);
/* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO)
would produce similar output to the following: */
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];
/* /usr/bin/addr2line */
sprintf(syscom,"addr2line %p -f -e %.*s", buffer[j], p, strings[j]);
//last parameter is the file name of the symbol
system(syscom);
printf("%s\n\n", 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 <iostream>
#include <stdexcept>
#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("\n");
mytest();
return 0;
}
3. 编译
g++ -g -std=c++0x -pthread -ldl -rdynamic main.cpp -o testThrow.out
4. 运行:
./testThrow.out
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)