linux下抓取C++ throw调用栈

本文介绍了一种使用API钩子技术抓取C++异常处理中throw调用的调用堆栈的方法。通过重定义__cxa_throw函数并利用backtrace和addr2line工具获取调用堆栈信息,此技术可以辅助开发者更好地理解和调试程序中的异常抛出流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值