在线精品99_中国九九盗摄偷拍偷看_91免费版在线观看_91.app_91高清视频在线_99热最新网站

Linux中堆栈的示例分析

148次阅读
没有评论

共计 2827 个字符,预计需要花费 8 分钟才能阅读完成。

这篇文章给大家分享的是有关 Linux 中堆栈的示例分析的内容。丸趣 TV 小编觉得挺实用的,因此分享给大家做个参考,一起跟随丸趣 TV 小编过来看看吧。

用下面的程序作为例子:

void a() { //stopped here } void b() { a(); } void c() { a(); } int main() { b(); c(); }

如果调试器停在 //stopped here   这行,那么有两种方法可以达到:main- b- a 或 main- c- a`。如果我们用 LLDB   设置一个断点,继续执行并请求一个回溯,那么我们将得到以下内容:

* frame #0: 0x00000000004004da a.out`a() + 4 at bt.cpp:3 frame #1: 0x00000000004004e6 a.out`b() + 9 at bt.cpp:6 frame #2: 0x00000000004004fe a.out`main + 9 at bt.cpp:14 frame #3: 0x00007ffff7a2e830 libc.so.6`__libc_start_main + 240 at libc-start.c:291 frame #4: 0x0000000000400409 a.out`_start + 41

这说明我们目前在函数 a 中,a 从函数 b 中跳转,b 从 main 中跳转等等。*** 两个帧是编译器如何引导 main 函数的。

现在的问题是我们如何在 x86_64 上实现。最稳健的方法是解析 ELF 文件的 .eh_frame   部分,并解决如何从那里展开堆栈,但这会很痛苦。你可以使用 libunwind   或类似的来做,但这很无聊。相反,我们假设编译器以某种方式设置了堆栈,我们将手动遍历它。为了做到这一点,我们首先需要了解堆栈的布局。

 High | ... | +---------+ | Arg 1 | +---------+ | Arg 2 | +---------+ | Return | +---------+ |Saved EBP| +---------+ | Var 1 | +---------+ | Var 2 | +---------+ | ... | Low

如你所见,*** 一个堆栈帧的帧指针存储在当前堆栈帧的开始处,创建一个链接的指针列表。堆栈依据这个链表解开。我们可以通过查找 DWARF   信息中的返回地址来找出列表中下一帧的函数。一些编译器将忽略跟踪 EBP 的帧基址,因为这可以表示为 ESP   的偏移量,并可以释放一个额外的寄存器。即使启用了优化,传递 -fno-omit-frame-pointer 到 GCC 或 Clang   会强制它遵循我们依赖的约定。

我们将在 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; };

打印输出的 *** 帧是当前正在执行的帧。我们可以通过查找 DWARF 中的当前程序计数器来获取此帧的信息:

auto current_func = get_function_from_pc(get_pc()); output_frame(current_func);

接下来我们需要获取当前函数的帧指针和返回地址。帧指针存储在 rbp 寄存器中,返回地址是从帧指针堆栈起的 8 字节。

auto frame_pointer = get_register_value(m_pid, reg::rbp); auto return_address = read_memory(frame_pointer+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); return_address = read_memory(frame_pointer+8); } }

就是这样! 以下是整个函数:

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); } }

添加命令

当然,我们必须向用户公开这个命令。

else if(is_prefix(command,  backtrace)) { print_backtrace(); }

感谢各位的阅读!关于“Linux 中堆栈的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-25发表,共计2827字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)
主站蜘蛛池模板: 一本久道中文无码字幕av | 久草在线这里只有精品 | 亚洲日韩欧美一区二区三区在线 | 人妻丰满熟妇av无码区乱 | 久久久亚洲精品蜜桃臀 | 亚洲精品久久久久久婷婷 | 国产乱人伦精品一区二区 | 国产欧美日韩高清专区ho | 亚洲国产精品成人精品小说 | 免费看片a级毛片免费看 | 欧美乱码伦视频免费 | 日本怡春院一区二区三区 | 亚洲人成电影网站色 | 美女张开腿让男人捅 | 亚洲国内自拍愉拍 | 手机黄丨片免费看 | 国产精品亚洲专区在线播放 | 国产高清在线精品一区a | 一级免费a | 一级毛片在线免费视频 | 欧美一级视频在线高清观看 | 国产成人精品免费视频大全办公室 | 成人观看天堂在线影片 | 免费看a级黄色片 | 国产在线无码视频一区 | 中文字幕不卡视频 | 欧美激情综合亚洲一二区 | 在线资源天堂 | 欧美伊人久久久久久久久影院 | 黄色大片在线观看 | 色吊丝中文字幕 | 久久久国产精品免费a片3d | 美女隐私视频网站 | 在线播放国产色视频在线 | 亚洲欧美不卡视频在线播放 | 妇女网站爱嘿嘿视频免费观看 | 国产 字幕 制服 中文 在线 | 九九热爱视频精品视频高清 | 国精产品自偷自偷综合下载 | 亚洲国产精品久久一线不卡 | 思思久久96热在精品国产免费 |