使用uftrace来debug应用程序
谈uftrace之前,先谈谈ftrace。
ftrace是一个用于调试linux内核的工具,它可以用于调试内核的调用栈,performance等。
ftrace的核心是在编译内核代码时,通过制定-pg标志,在函数的调用入口插入桩mcount函数,这样,就可以在桩函数里收集函数调用的信息。至于mcount函数怎么来的,我们可以后续再谈。
uftrace应用了类似的机制,只不过它是针对user space的应用程序。使用uftrace的前提是要通过 “-pg”或者“-finstrument-functions”这个编译标志对应用程序代码进行编译。
"-pg"指定编译器在函数入口插入对mcount()桩函数的调用,而“-finstrument-functions”会指定编译器在函数入口插入对__cyg_profile_func_enter()函数的调用,在函数返回时插入对__cyg_profile_func_exit()函数的调用。 uftrace对这2种情况都能支持。正常情况下,c库提供了对这些桩函数的定义,所以我们链接程序时,是可以链接到c库里面的桩函数定义。
同时呢,我们可以重新定义这些函数,让编译器链接到自定义的函数了。那么这里来了个问题,既然c库里面已经有同名的函数定义,链接器怎么知道该链接c库里面的定义还是自定义的函数?这里就用到了__attribute__((weak))这样一种属性,c库里面在定义桩函数时,在函数前面加了这个weak属性。链接器在链接这个函数符号时,如果只在c库里面找到了,那就链接到c库里面去。但是如果找到另外一个自定义的同名函数,且不是weak的,那么链接器就会优先链接到这个自定义的同名函数。
我们可以验证一把:
$ ldd test
linux-vdso.so.1 => (0x00007ffc379b7000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fbd6d5fb000)
/lib64/ld-linux-x86-64.so.2 (0x00007fbd6d9c5000)
$ readelf -s /lib/x86_64-linux-gnu/libc.so.6 |grep mcount
113: 000000000010a350 91 FUNC GLOBAL DEFAULT 13 _mcount@@GLIBC_2.2.5
419: 0000000000143530 50 FUNC GLOBAL DEFAULT 13 _dl_mcount_wrapper_check@@GLIBC_2.2.5
1616: 0000000000143510 23 FUNC GLOBAL DEFAULT 13 _dl_mcount_wrapper@@GLIBC_2.2.5
2012: 000000000010a350 91 FUNC WEAK DEFAULT 13 mcount@@GLIBC_2.2.5
可以看到mcount()在libc.so.6里被定义为WEAK类型,这个验证了我们的猜想。
利用这个机制,我们可以玩很多花样,我们可以自己定义桩函数,然后链接到应用程序中,至于在桩函数里面干什么,那就海阔任鱼游了。
uftrace也利用了这点。
我们看看uftrace使用效果如何。
我们有下面这个小程序
void func_a(){
}
void func_b(){
func_a();
}
int main(){
func_a();
func_b();
}
然后我们这样编译
$ gcc -pg -g test.c
$ ls
a.out test.c
运行
$ uftrace a.out
# DURATION TID FUNCTION
0.602 us [ 3211] | __monstartup();
0.604 us [ 3211] | __cxa_atexit();
[ 3211] | main() {
0.131 us [ 3211] | func_a();
[ 3211] | func_b() {
0.101 us [ 3211] | func_a();
0.406 us [ 3211] | } /* func_b */
1.113 us [ 3211] | } /* main */ $
这里面打印了函数调用栈和每个函数运行时间,这些信息对于我们的运行时分析是非常有用的,特别是有回调函数之类的代码。
当然uftrace还有更多有用的功能。这个后续再谈。
使用uftrace来debug应用程序的更多相关文章
- Python 【Debug排除程序故障】
debug #排除程序故障 print()函数常和#号注释结合在一起用来debug 多行注释有两种快捷操作:1.在需要注释的多行代码块前后加一组三引号''' 2.选中代码后使用快捷键操作:Window ...
- eclipse远程debug Java程序
使用Eclipse JPDA远程调试Java程序 本文将介绍使用Eclipse JPDA,在Eclipse的开发环境下对远程运行的Java程序进行调试操作. 请按以下步骤进行(本人已经在Eclipse ...
- debug PHP程序(xdebug、IntelliJ IDEA)
之前写PHP程序的都是echo调试,今天感觉太麻烦了就想起研究一下IntelliJ IDEA如何调试PHP程序. 从网上查找了很多资料,大部分都提到在IDE里开启服务,一下就懵了,怎么启这么多服务呢. ...
- [VS2008] Debug版本程序发布后 由于应用程序的配置不正确,应用程序未能启动,重新安装应用程序可能会纠正这个问题
转自VC错误:http://www.vcerror.com/?p=59 问题描述: [VS2008] 版本程序发布后,运行程序弹出错误框: 由于应用程序的配置不正确,应用程序未能启动,重新安装应用程序 ...
- debug : 应用程序无法正常启动(0xc000007b)
- 使用Dev C++调试(debug)程序
在 "Tools" -> "Compiler Options" -> "Add following commands when calli ...
- 如何在其他电脑上运行VS2005编译的DEBUG版应用程序
做项目的过程中,遇到这样的问题:在自己的电脑上用VS2005编译好的DEBUG版程序在其它的没有安装VS2005的电脑上没有办法运行,郁闷至极啊. 直 接拷贝文件后,错误信息如下:"This ...
- Debug程序无法运行解决
说明:文章内容部分参考网络上的解决思路. 在没有安装Microsoft Visual Studio的系统上,Debug版本无法正常运行.这是由于缺少vs运行时库引起的. 以vs2005为例.开发机用v ...
- Python程序高效地调试
现在我在debug python程序就只是简单在有可能错误的地方print出来看一下,不知道python有没像c++的一些IDE一样有单步调试这类的工具?或者说各位python大神一般是怎么debug ...
随机推荐
- 事件总线 EventBus
661. .net中事件模型很优雅的实现了观察者模式,同时被大量的使用在各种框架中. [2016-04-30 10:52:42]662. Prism框架中实现了一个典型的EventAggregator ...
- 使用Route Prefix 使用属性路由 精通ASP-NET-MVC-5-弗瑞曼
- windows RabbitMQ安装与配置
windows RabbitMQ安装与配置 1.安装Erlang 下载地址: http://www.erlang.org/downloads 注意: 右键以管理员身份进行安装,否则将导致后续无法启动 ...
- springboot整合elasticJob实战(纯代码开发三种任务类型用法)以及分片系统,事件追踪详解
一 springboot整合 介绍就不多说了,只有这个框架是当当网开源的,支持分布式调度,分布式系统中非常合适(两个服务同时跑不会重复,并且可灵活配置分开分批处理数据,贼方便)! 这里主要还是用到zo ...
- 通过 SCF Component 轻松构建 REST API,再也不用熬夜加班了
本教程将分享如何通过 Serverless SCF Component .云函数 SCF 及 API 网关组件,快速构建一个 REST API 并实现 GET/PUT 操作. 当一个应用需要对第三方提 ...
- 迭代器中set的使用
今天对迭代器中的set方法进行了一下简单的使用,由于之前使用过list方法,所以将他与list进行了一下对比. list中加入对象时不会进行查重,也就是只要是一个符合的对象就可以加到list中,而对于 ...
- 《快乐编程大本营》java语言训练班 3课:java的运算符
第1节. 算术运算符 第2节. 递增和递减运算符 第3节. 比较运算符 第4节. 逻辑运算符 第5节. 运算符优先级 第6节. 字符串运算 http://code6g.com/pxphp/px/ban ...
- python中的变量和字符串
一.变量 1.python变量 *变量用于存储某个或某些特定的值,它与一个特定标识符相关联,该标识符称为变量名称.变量名指向存储在内存中的值.在创建变量时会在内存中开辟一个空间.基于变量的数据类型,解 ...
- c++引用深入探讨
(偶然翻起自己的旧博,忽然发现大三的时候写的这篇文章,仔细看看觉得写的还是那么回事,所以赶紧搭救出来) 引用的声明: 基本格式:引用类型 &引用名=被引用对象 &运算符:声明运算符 ...
- 《剑指Offer》第二章(一)题 9 -12
第二章 面试题9:用两个栈实现队列 题目:如面试题,给你两个栈, 实现队列的先进先出,即在队列头删除一个元素以及在队列的尾部添加一个元素 思路:这个题的分析感觉很巧妙,从一个具体的例子入手,找出其中的 ...