etrace 跟踪程序函数动态执行流程
https://github.com/elcritch/etrace 窗口1: 监控窗口,执行监控程序,显示监控结果[root@monitor example]# pwd /root/etrace-master/example[root@monitor example]# ll total 28 -rwxr-xr-x 1 root root 16687 Jun 9 08:49 crumble -rw-r--r-- 1 root root 1644 Aug 7 2015 crumble.c -rw-r--r-- 1 root root 242 Aug 7 2015 Makefile[root@monitor example]# ../src/etrace crumble[root@monitor example]# ll total 28 -rwxr-xr-x 1 root root 16687 Jun 9 08:49 crumble -rw-r--r-- 1 root root 1644 Aug 7 2015 crumble.c -rw-r--r-- 1 root root 242 Aug 7 2015 Makefile prw-r--r-- 1 root root 0 Jun 9 08:59 TRACE
窗口2:执行程序[root@monitor example]# ./crumblebuy 125 grams of sugarbuy 125 grams of butterbuy 200 grams of wheatbuy 1 pinch of saltbuy 5 pieces of appleskin apples and make little dicesmix butter with sugar, wheat and saltput apples belowput crumble on topput apple crumble in ovencook apple crumble at 220 degrees for 45 minutes
窗口1:显示程序监控结果 //etrace跟据 TRACE 这个文件中的 记录的函数调用地址 查找对应 crumble中的函数符号名,并生调用图[root@monitor example]# ../src/etrace crumble \--main | \--Crumble_make_apple_crumble | | \--Crumble_buy_stuff | | | \--Crumble_buy | | | \--Crumble_buy (total: 5 times) | | \--Crumble_prepare_apples | | | \--Crumble_skin_and_dice | | \--Crumble_mix | | \--Crumble_finalize | | | \--Crumble_put | | | \--Crumble_put (total: 2 times) | | \--Crumble_cook | | | \--Crumble_put | | | \--Crumble_bake
原理:[root@monitor example]# cat Makefile CC = gccCFLAGS = -g -finstrument-functions --std=gnu99 crumble: crumble.c ../src/ptrace.c $(CC) $(CFLAGS) -o crumble crumble.c ../src/ptrace.c run: touch TRACE ; ./crumble ../src/etrace crumble rm -f TRACE clean: rm -f crumble TRACE [root@monitor example]# make //执行原理gcc -g -finstrument-functions --std=gnu99 -o crumble crumble.c ../src/ptrace.c
单窗口也可以显示跟踪结果[root@monitor example]# make run touch TRACE ; ./crumble buy 125 grams of sugar buy 125 grams of butter buy 200 grams of wheat buy 1 pinch of salt buy 5 pieces of apple skin apples and make little dices mix butter with sugar, wheat and salt put apples below put crumble on top put apple crumble in oven cook apple crumble at 220 degrees for 45 minutes ../src/etrace crumble\--main | \--Crumble_make_apple_crumble | | \--Crumble_buy_stuff | | | \--Crumble_buy | | | \--Crumble_buy (total: 5 times) | | \--Crumble_prepare_apples | | | \--Crumble_skin_and_dice | | \--Crumble_mix | | \--Crumble_finalize | | | \--Crumble_put | | | \--Crumble_put (total: 2 times) | | \--Crumble_cook | | | \--Crumble_put | | | \--Crumble_bake rm -f TRACE
执行原理: [root@monitor example]# touch TRACE [root@monitor example]# ./crumble buy 125 grams of sugar buy 125 grams of butter buy 200 grams of wheat buy 1 pinch of salt buy 5 pieces of apple skin apples and make little dices mix butter with sugar, wheat and salt put apples below put crumble on top put apple crumble in oven cook apple crumble at 220 degrees for 45 minutes [root@monitor example]# ll total 32 -rwxr-xr-x 1 root root 16687 Jun 9 09:17 crumble -rw-r--r-- 1 root root 1650 Jun 9 09:17 crumble.c -rw-r--r-- 1 root root 244 Jun 9 09:05 Makefile -rw-r--r-- 1 root root 563 Jun 9 09:17 TRACE [root@monitor example]# cat TRACE enter 0x400beb enter 0x400b88 enter 0x400904 enter 0x4008a4 enter 0x400ba1 enter 0x400b3e enter 0x4008ba enter 0x400864 exit 0x400864 enter 0x400864 exit 0x400864 enter 0x400864 exit 0x400864 enter 0x400864 exit 0x400864 enter 0x400864 exit 0x400864 exit 0x4008ba enter 0x40096c enter 0x400940 exit 0x400940 exit 0x40096c enter 0x4009a4 exit 0x4009a4 enter 0x400a5a enter 0x400a0f exit 0x400a0f enter 0x400a0f exit 0x400a0f exit 0x400a5a enter 0x400af9 enter 0x400a0f exit 0x400a0f enter 0x400aa4 exit 0x400aa4 exit 0x400af9 exit 0x400b3e exit 0x400ba1 EXIT 6847
0000000000400ba1 <main>:400ba1: 55 push %rbp400ba2: 48 89 e5 mov %rsp,%rbp400ba5: 53 push %rbx400ba6: 48 83 ec 18 sub $0x18,%rsp400baa: 89 7d ec mov %edi,-0x14(%rbp)400bad: 48 89 75 e0 mov %rsi,-0x20(%rbp)400bb1: 48 8b 75 08 mov 0x8(%rbp),%rsi400bb5: bf a1 0b 40 00 mov $0x400ba1,%edi 400bba: e8 8e 01 00 00 callq 400d4d <__cyg_profile_func_enter>400bbf: e8 7a ff ff ff callq 400b3e <Crumble_make_apple_crumble>400bc4: bb 00 00 00 00 mov $0x0,%ebx400bc9: 48 8b 75 08 mov 0x8(%rbp),%rsi400bcd: bf a1 0b 40 00 mov $0x400ba1,%edi400bd2: e8 99 01 00 00 callq 400d70 <__cyg_profile_func_exit>400bd7: 89 d8 mov %ebx,%eax400bd9: 48 83 c4 18 add $0x18,%rsp400bdd: 5b pop %rbx400bde: c9 leaveq 400bdf: c3 retq
[root@monitor src]# cat ptrace.c //程序连接时加的额外代码/*-------------------------------------------------------------------------*/ /**@file ptrace.c@author N. Devillard, V. Chudnovsky@date March 2004@version $Revision: 1.1.1.1 $@brief Add tracing capability to any program compiled with gcc.This module is only compiled when using gcc and tracing has beenactivated. It allows the compiled program to output messages whenevera function is entered or exited.To activate this feature, your version of gcc must supportthe -finstrument-functions flag.When using ptrace on a dynamic library, you must set thePTRACE_REFERENCE_FUNCTION macro to be the name of a function in thelibrary. The address of this function when loaded will be the firstline output to the trace file and will permit the translation of theother entry and exit pointers to their symbolic names. You may setthe macro PTRACE_INCLUDE with any #include directives needed forthat function to be accesible to this source file.The printed messages yield function addresses, not human-readablenames. To link both, you need to get a list of symbols from theprogram. There are many (unportable) ways of doing that, see the'etrace' project on freshmeat for more information about how to digthe information. */ /*--------------------------------------------------------------------------*//*$Id: ptrace.c,v 1.1.1.1 2004-03-16 20:00:07 ndevilla Exp $$Author: ndevilla $$Date: 2004-03-16 20:00:07 $$Revision: 1.1.1.1 $ */#if (__GNUC__>2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ > 95))/*---------------------------------------------------------------------------Includes---------------------------------------------------------------------------*/#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <string.h> #include <sys/errno.h>/*---------------------------------------------------------------------------User Macros---------------------------------------------------------------------------*/ #define PTRACE_PIPENAME "TRACE"/* When using ptrace on a dynamic library, the following must be defined:#include "any files needed for PTRACE_REFERENCE_FUNCTION" #define PTRACE_REFERENCE_FUNCTION functionName`*//*---------------------------------------------------------------------------Defines---------------------------------------------------------------------------*/#define REFERENCE_OFFSET "REFERENCE:" #define FUNCTION_ENTRY "enter" #define FUNCTION_EXIT "exit" #define END_TRACE "EXIT" #define __NON_INSTRUMENT_FUNCTION__ __attribute__((__no_instrument_function__)) #define PTRACE_OFF __NON_INSTRUMENT_FUNCTION__ #define STR(_x) #_x #define DEF(_x) _x #define GET(_x,_y) _x(_y) #define TRACE __GNU_PTRACE_FILE__ /*---------------------------------------------------------------------------Function codes---------------------------------------------------------------------------*//** Initial trace open */ static FILE *__GNU_PTRACE_FILE__;/** Final trace close */ static void __NON_INSTRUMENT_FUNCTION__ gnu_ptrace_close(void) {fprintf(TRACE, END_TRACE " %ld\n", (long)getpid());if (TRACE != NULL)fclose(TRACE);return ; }/** Trace initialization */ static int __NON_INSTRUMENT_FUNCTION__ gnu_ptrace_init(void) {struct stat sta;__GNU_PTRACE_FILE__ = NULL;/* See if a trace file exists */if (stat(PTRACE_PIPENAME, &sta) != 0) {/* No trace file: do not trace at all */return 0;}else {/* trace file: open up trace file */if ((TRACE = fopen(PTRACE_PIPENAME, "a")) == NULL){char *msg = strerror(errno);perror(msg);printf("[gnu_ptrace error]\n");return 0;}#ifdef PTRACE_REFERENCE_FUNCTIONfprintf(TRACE,"%s %s %p\n",REFERENCE_OFFSET,GET(STR,PTRACE_REFERENCE_FUNCTION),(void *)GET(DEF,PTRACE_REFERENCE_FUNCTION));#endif/* Tracing requested: a trace file was found */atexit(gnu_ptrace_close);return 1;} }/** Function called by every function event */ void __NON_INSTRUMENT_FUNCTION__ gnu_ptrace(char * what, void * p) {static int first=1;static int active=1;if (active == 0)return;if (first){active = gnu_ptrace_init();first = 0;if (active == 0)return;}fprintf(TRACE, "%s %p\n", what, p);fflush(TRACE);return; }/** According to gcc documentation: called upon function entry */ void __NON_INSTRUMENT_FUNCTION__ __cyg_profile_func_enter(void *this_fn, void *call_site) {gnu_ptrace(FUNCTION_ENTRY, this_fn);(void)call_site; }/** According to gcc documentation: called upon function exit */ void __NON_INSTRUMENT_FUNCTION__ __cyg_profile_func_exit(void *this_fn, void *call_site) {gnu_ptrace(FUNCTION_EXIT, this_fn);(void)call_site; }#endif /* vim: set ts=4 et sw=4 tw=75 */
执行原理: test.c#include <stdio.h>fun(){printf("this is test\n");}main(){ fun(); } gcc test.c -g -otest00000000004004d4 <main>: 4004d4: 55 push %rbp 4004d5: 48 89 e5 mov %rsp,%rbp 4004d8: b8 00 00 00 00 mov $0x0,%eax 4004dd: e8 e2 ff ff ff callq 4004c4 <fun> 4004e2: c9 leaveq 4004e3: c3 retq 4004e4: 90 nop 4004e5: 90 nop 4004e6: 90 nop 4004e7: 90 nop 4004e8: 90 nop 4004e9: 90 nop 4004ea: 90 nop 4004eb: 90 nop 4004ec: 90 nop 4004ed: 90 nop 4004ee: 90 nop 4004ef: 90 nop gcc test.c -g -finstrument-functions -otest 00000000004005a0 <main>: 4005a0: 55 push %rbp 4005a1: 48 89 e5 mov %rsp,%rbp 4005a4: 48 8b 75 08 mov 0x8(%rbp),%rsi 4005a8: bf a0 05 40 00 mov $0x4005a0,%edi 4005ad: e8 be fe ff ff callq 400470 <__cyg_profile_func_enter@plt> 4005b2: b8 00 00 00 00 mov $0x0,%eax 4005b7: e8 b8 ff ff ff callq 400574 <fun> 4005bc: 48 8b 75 08 mov 0x8(%rbp),%rsi 4005c0: bf a0 05 40 00 mov $0x4005a0,%edi 4005c5: e8 b6 fe ff ff callq 400480 <__cyg_profile_func_exit@plt> 4005ca: c9 leaveq 4005cb: c3 retq 4005cc: 90 nop 4005cd: 90 nop 4005ce: 90 nop 4005cf: 90 nop gcc -g -finstrument-functions --std=gnu99 -otest test.c ../src/ptrace.c //ptrace.c 写函数进入或退去点到TRACE文件中(如果存在的话)//函数的首地址 0000000000400840 <main>: 400840: 55 push %rbp 400841: 48 89 e5 mov %rsp,%rbp 400844: 53 push %rbx 400845: 48 83 ec 08 sub $0x8,%rsp 400849: 48 8b 75 08 mov 0x8(%rbp),%rsi 40084d: bf 40 08 40 00 mov $0x400840,%edi 400852: e8 96 01 00 00 callq 4009ed <__cyg_profile_func_enter> 400857: b8 00 00 00 00 mov $0x0,%eax 40085c: e8 b3 ff ff ff callq 400814 <fun> 400861: bb 00 00 00 00 mov $0x0,%ebx 400866: 48 8b 75 08 mov 0x8(%rbp),%rsi 40086a: bf 40 08 40 00 mov $0x400840,%edi 40086f: e8 9c 01 00 00 callq 400a10 <__cyg_profile_func_exit> 400874: 89 d8 mov %ebx,%eax 400876: 48 83 c4 08 add $0x8,%rsp 40087a: 5b pop %rbx 40087b: c9 leaveq 40087c: c3 retq 40087d: 90 nop 40087e: 90 nop 40087f: 90 nop 00000000004009ed <__cyg_profile_func_enter>: 4009ed: 55 push %rbp 4009ee: 48 89 e5 mov %rsp,%rbp 4009f1: 48 83 ec 10 sub $0x10,%rsp 4009f5: 48 89 7d f8 mov %rdi,-0x8(%rbp) 4009f9: 48 89 75 f0 mov %rsi,-0x10(%rbp) 4009fd: 48 8b 45 f8 mov -0x8(%rbp),%rax 400a01: 48 89 c6 mov %rax,%rsi 400a04: bf a1 0b 40 00 mov $0x400ba1,%edi 400a09: e8 5a ff ff ff callq 400968 <gnu_ptrace> 400a0e: c9 leaveq 400a0f: c3 retq 0000000000400968 <gnu_ptrace>: 400968: 55 push %rbp 400969: 48 89 e5 mov %rsp,%rbp 40096c: 53 push %rbx 40096d: 48 83 ec 18 sub $0x18,%rsp 400971: 48 89 7d e8 mov %rdi,-0x18(%rbp) 400975: 48 89 75 e0 mov %rsi,-0x20(%rbp) 400979: 8b 05 4d 06 20 00 mov 0x20064d(%rip),%eax # 600fcc <active.3459> 40097f: 85 c0 test %eax,%eax 400981: 74 5f je 4009e2 <gnu_ptrace+0x7a> 400983: 8b 05 47 06 20 00 mov 0x200647(%rip),%eax # 600fd0 <first.3458> 400989: 85 c0 test %eax,%eax 40098b: 74 1f je 4009ac <gnu_ptrace+0x44> 40098d: e8 36 ff ff ff callq 4008c8 <gnu_ptrace_init> 400992: 89 05 34 06 20 00 mov %eax,0x200634(%rip) # 600fcc <active.3459> 400998: c7 05 2e 06 20 00 00 movl $0x0,0x20062e(%rip) # 600fd0 <first.3458> 40099f: 00 00 00 4009a2: 8b 05 24 06 20 00 mov 0x200624(%rip),%eax # 600fcc <active.3459> 4009a8: 85 c0 test %eax,%eax 4009aa: 74 39 je 4009e5 <gnu_ptrace+0x7d> 4009ac: bb 9a 0b 40 00 mov $0x400b9a,%ebx 4009b1: 48 8b 05 30 06 20 00 mov 0x200630(%rip),%rax # 600fe8 <__GNU_PTRACE_FILE__> 4009b8: 48 8b 4d e0 mov -0x20(%rbp),%rcx 4009bc: 48 8b 55 e8 mov -0x18(%rbp),%rdx 4009c0: 48 89 de mov %rbx,%rsi 4009c3: 48 89 c7 mov %rax,%rdi 4009c6: b8 00 00 00 00 mov $0x0,%eax 4009cb: e8 40 fd ff ff callq 400710 <fprintf@plt> 4009d0: 48 8b 05 11 06 20 00 mov 0x200611(%rip),%rax # 600fe8 <__GNU_PTRACE_FILE__> 4009d7: 48 89 c7 mov %rax,%rdi 4009da: e8 41 fd ff ff callq 400720 <fflush@plt> 4009df: 90 nop 4009e0: eb 04 jmp 4009e6 <gnu_ptrace+0x7e> 4009e2: 90 nop 4009e3: eb 01 jmp 4009e6 <gnu_ptrace+0x7e> 4009e5: 90 nop 4009e6: 48 83 c4 18 add $0x18,%rsp 4009ea: 5b pop %rbx 4009eb: c9 leaveq 4009ec: c3 retq [root@monitor example]# touch TRACE[root@monitor example]# ./testthis is test[root@monitor example]# lltotal 52-rwxr-xr-x 1 root root 16687 Jun 9 09:39 crumble-rw-r--r-- 1 root root 1651 Jun 9 09:28 crumble.c-rw-r--r-- 1 root root 244 Jun 9 09:05 Makefile-rwxr-xr-x 1 root root 13627 Jun 9 09:47 test-rw-r--r-- 1 root root 75 Jun 9 09:34 test.c-rw-r--r-- 1 root root 68 Jun 9 09:52 TRACE[root@monitor example]# cat TRACEenter 0x400840 // main进入enter 0x400814 // fun进入exit 0x400814 // fun退去exit 0x400840 // main退去EXIT 6993
转载于:https://www.cnblogs.com/zengkefu/p/5571961.html
etrace 跟踪程序函数动态执行流程相关推荐
- 动态执行流程分析和性能瓶颈分析的利器——gperftools的Cpu Profiler
在<动态执行流程分析和性能瓶颈分析的利器--valgrind的callgrind>中,我们领略了valgrind对流程和性能瓶颈分析的强大能力.本文将介绍拥有相似能力的gperftools ...
- 动态执行流程分析和性能瓶颈分析的利器——valgrind的callgrind
在<内存.性能问题分析的利器--valgrind>一文中我们简单介绍了下valgrind工具集,本文将使用callgrind工具进行动态执行流程分析和性能瓶颈分析.(转载请指明出于brea ...
- Python 函数的执行流程-函数递归-匿名函数-生成器
1 函数的执行流程 函数的执行需要对函数进行压栈的,什么是压栈呢,简而言之就是在函数执行时在栈中创建栈帧存放需要变量以及指针的意思.具体涉及的知识非常多,这里就已一个Python脚本简单进行分析. 当 ...
- 梆梆加固函数抽取执行流程
梆梆加固函数抽取执行流程:函数的第一条指令是goto,然后中间是一系列的nop(预留空间),第一条指令goto到末尾,跳过预留空间,跳转到的位置是一条invoke指令,调用壳中的还原函数,还原函数会将 ...
- mysql函数 动态语句_自定义函数动态执行SQL语句
Oracle 动态SQL有两种写法:用 DBMS_SQL 或 execute immediate,建议使用后者. DDL 和 DML Sql代码 收藏代码 /*** DDL ***/ begin EX ...
- java 毕向东 内部类_Java基础毕向东day05 对象与对象的区别,匿名内部类,函数的执行流程。...
1.Car c = new Car(); Car c2 = new Car(); 1> c 和 c2之间的区别? public static void main(String[] args) { ...
- mysql8.0源代码解析_MySQL8.0.11源码分析之mysql关键函数和执行流程
mysql是命令行客户端程序 ,交互式输入SQL语句或从文件以批处理模式执行它们的命令行工具. 入口函数 int main(int argc, char *argv[]) { if (get_opti ...
- pip包管理工具-install执行流程简单查看
pip概述 pip是python提供的包管理工具,该工具提供了对python包的查找.下载.安装与卸载等功能的工具,当前是python中比较主流的管理工具. pip下载安装包的概述 pip工具的本质通 ...
- 一文弄懂printf函数从用户态到内核态的执行流程
目录 1.简介 2.示例代码 3.程序执行初探 4.用户态处理流程 5.内核态处理流程 5.1. 软中断处理 5.2 系统调用返回 5.3 系统调用处理 5.4 stdout重定向到console 5 ...
最新文章
- [Android]转-Android 中的拿来主义(编译,反编译,AXMLPrinter2,smali,baksmali)!
- live的domain服务
- 强力推荐!飞桨产业级PaddleNLP最新全景图发布
- XML--使用XML来将字符串分隔成行数据
- Digit sum【暴力+打表】
- 【微信小程序】带你做一个公众号留言系统(附源码)
- 深度好文,如何培养真正的数据分析思维?附实践案例
- 搜狗浏览器连接海康摄像头,无法显示画面
- java远程执行bat命令
- 【Pytorch神经网络理论篇】 40 Transformers中的词表工具Tokenizer
- VB连接数据库SQL sever
- 参数显著性检验的p值小于显著性水平不等于其具有经济学意义
- 树莓派基于motion的usb摄像头监控
- 用迅雷或者IDM下载下载百度网盘文件方法
- 2022-2027年中国民办高校行业市场全景评估及发展战略规划报告
- java飞翔的小鸟游戏实验报告,BirdGame 飞翔的小鸟游戏源码,仿照 编写的java版本 ,所有的 功能完整。 s 249万源代码下载- www.pudn.com...
- CentOS yum方式升级内核kernel
- 【图神经网络】异构时间图卷积网络HTGCN——用于社区检测
- 高德定位,只能定位一次,导航图标就消失
- 中国六大最忙和六大最懒城市
热门文章
- Android 高仿新浪微博底部导航栏,实现双击首页Tab,页面的ListView滚动、刷新
- 关于spring事务管理
- 【分块答案】【最小割】bzoj1532 [POI2005]Kos-Dicing
- error LNK2019: 无法解析的外部符号 __imp__inet_ntoa@4
- VC中BSTR和CString的使用
- 防止IE6出现BUG的十种常见解决方法
- xadmin引入样式无效
- MyEcplise安装Freemarker插件(支持.ftl文件)
- 2015-10-11 Sunday 晴 ARM学习
- 如何确定一个IAR工程所使用的IAR版本