linux的用户态程序栈的跟踪方法
来源:互联网 发布:sound软件 编辑:程序博客网 时间:2024/06/09 14:16
linux的用户态程序栈的跟踪方法
- GNU C中的libc相关函数介绍
- 实例分析
GNU C中的libc相关函数介绍
这一部分文章来源于GNU C的在线帮助文档
实例分析
将下面的代码保存为main.c文件,然后用gcc编译
#include <execinfo.h>#include <stdio.h>#include <stdlib.h>/* Obtain a backtrace and print it to stdout. */voidprint_trace (void){ void *array[10]; size_t size; char **strings; size_t i; size = backtrace (array, 10); strings = backtrace_symbols (array, size); printf ("Obtained %zd stack frames.\n", size); for (i = 0; i < size; i++) printf ("%s\n", strings[i]); free (strings);}/* A dummy function to make the backtrace more interesting. */voiddummy_function (void){ print_trace ();}intmain (void){ dummy_function (); return 0;}
然后编译并运行:
[ycwang@ycwang-desktop:backtrace-test]$ gcc -g main.c
[ycwang@ycwang-desktop:backtrace-test]$ ./a.out
Obtained 5 stack frames.
./a.out() [0x4006fe]
./a.out() [0x400795]
./a.out() [0x4007a1]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7f06a6ef2ac0]
./a.out() [0x400609]
可以看到,程序运行之后,把stack frames完全打印出来了。
我们可以定位各个栈了。
然后用objdump来把反汇编文件导出到一个文件中
[ycwang@ycwang-desktop:backtrace-test]$ objdump -D a.out > dump
然后打开dump文件,查找函数在内存中的虚拟地址。
450 00000000004006d6 <print_trace>: 451 4006d6: 55 push %rbp 452 4006d7: 48 89 e5 mov %rsp,%rbp 453 4006da: 48 83 c4 80 add $0xffffffffffffff80,%rsp 454 4006de: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax 455 4006e5: 00 00 456 4006e7: 48 89 45 f8 mov %rax,-0x8(%rbp) 457 4006eb: 31 c0 xor %eax,%eax 458 4006ed: 48 8d 45 a0 lea -0x60(%rbp),%rax 459 4006f1: be 0a 00 00 00 mov $0xa,%esi 460 4006f6: 48 89 c7 mov %rax,%rdi 461 4006f9: e8 92 fe ff ff callq 400590 <backtrace@plt> 462 4006fe: 48 98 cltq 463 400700: 48 89 45 90 mov %rax,-0x70(%rbp) 464 400704: 48 8b 45 90 mov -0x70(%rbp),%rax
可以看出:0x4006fe在print_trace函数里面,这也是函数栈的栈顶。
接下来查找另外几个地址。得到:
地址0x400795:
503 000000000040078c <dummy_function>: 504 40078c: 55 push %rbp 505 40078d: 48 89 e5 mov %rsp,%rbp 506 400790: e8 41 ff ff ff callq 4006d6 <print_trace> 507 400795: 90 nop 508 400796: 5d pop %rbp 509 400797: c3 retq
地址0x4007a1:
511 0000000000400798 <main>: 512 400798: 55 push %rbp 513 400799: 48 89 e5 mov %rsp,%rbp 514 40079c: e8 eb ff ff ff callq 40078c <dummy_function> 515 4007a1: b8 00 00 00 00 mov $0x0,%eax 516 4007a6: 5d pop %rbp 517 4007a7: c3 retq 518 4007a8: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1) 519 4007af: 00
接下来的两个栈对于我们的程序分析没有意义,暂时不讨论。
然后我们可以得到栈的层次为
print_trace()dummy_function()main()
跟我们写出的函数的栈完全相同。
这种调试方法适用于不能打断点的一些程序的调试。
0 0
- linux的用户态程序栈的跟踪方法
- 跟踪用户的SQL
- 用户空间程序的函数跟踪器 (Function Tracer)
- 一个简单的跟踪用户访问路径的方法
- linux下清空连接跟踪表的方法
- 跟踪程序在Linux下的执行的函数调用
- 跟踪代码的方法
- Linux 用户退出后,用户程序后台运行的方法介绍
- 注销linux用户的方法
- 程序的测试与跟踪
- 内核与用户态程序共享内存的方法
- 小程序获取用户unionid的方法
- 嵌入式Linux 下用户程序实现多任务的方法:多线程的实现
- 跟踪用户的更改/删除历史
- 免费的用户行为跟踪采集
- biee的用户跟踪 user tracking
- 免费的用户行为跟踪采集
- 流行的视觉跟踪方法
- AndroidStudio导入项目一直卡在Building gradle project info最快速解决方案
- myBatis学习笔记
- 在树莓派基础下的Web服务器的建设(ACM)二
- java中如何将字符数组转换成字符串,以逗号分割
- 从外部的js文件中获取ASPX页面的控件ClientID
- linux的用户态程序栈的跟踪方法
- HTML5之Canvas绘图——使用Canvas绘制图形
- Parcelable和Serializable
- Git笔记
- 高效办公工具
- Python的安装和环境配置
- JDK,JRE,JVM区别与联系 Java为什么跨平台 ?为什么一次编写,到处运行?
- linux下强制修改mysql密码
- java多线程详解