我们将在 print_backtrace 函数中完成所有的工作:
- void debugger::print_backtrace() {
我们已经年腋荷琐只能产生并附加到其他法度榜样的法度榜样走了很长的陆辜本系列的倒数第二篇文┞仿精晓过支撑读写变量来完成调试器的实现。在此之前,你可以在这里找到这个帖子的代码。
起重要决定的是应用什么格局打印出帧信息。我用了一个 lambda 来推出这个办法:
- auto output_frame = [frame_number = 0] (auto&& func) mutable {
- std::cout << "frame #" << frame_number++ << ": 0x" << dwarf::at_low_pc(func)
- << ' ' << dwarf::at_name(func) << std::endl;
- };
- auto frame_pointer = get_register_value(m_pid, reg::rbp);
- auto return_address = read_memory(frame_pointer+8);
打印输出的第一帧是当前正在履行的帧。我们可以经由过程查找 DWARF 中的当前法度榜样计数器来获取此帧的信息:
- void debugger::print_backtrace() {
- auto output_frame = [frame_number = 0] (auto&& func) mutable {
- std::cout << "frame #" << frame_number++ << ": 0x" << dwarf::at_low_pc(func)
- << ' ' << dwarf::at_name(func) << std::endl;
- };
- auto current_func = get_function_from_pc(get_pc());
- output_frame(current_func);
- auto frame_pointer = get_register_value(m_pid, reg::rbp);
- auto return_address = read_memory(frame_pointer+8);
- while (dwarf::at_name(current_func) != "main") {
- current_func = get_function_from_pc(return_address);
- output_frame(current_func);
- frame_pointer = read_memory(frame_pointer);
- return_address = read_memory(frame_pointer+8);
- }
- }
- auto current_func = get_function_from_pc(get_pc());
- output_frame(current_func);
接下来我们须要获取当前函数的帧指针和返回地址。帧指针存储在 rbp 存放器中,返回地址是大年夜帧指针客栈起的 8 字节。
如今我们拥有了展开客栈所需的所有信息。我只须要持续展开,直到调试器射中 main,然则当帧指针为 0x0 时,你也可以选择停止,这些是你在调用 main 函数之前调用的函数。我们将大年夜每帧抓取帧指针和返回地址,并打印出信息。
- while (dwarf::at_name(current_func) != "main") {
- current_func = get_function_from_pc(return_address);
- output_frame(current_func);
- frame_pointer = read_memory(frame_pointer);
推荐阅读
近日,人平易近日报评论快递业“虚胖的快递担保需瘦身”,让快递担保一向存在且愈演愈烈的“过度包装”,收受接收处理方法被提上日程受到广泛存眷。相干数据显示,2016年,我国快>>>详细阅读
本文标题:开发一个Linux调试器(八):堆栈展开
地址:http://www.17bianji.com/lsqh/37719.html
1/2 1