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 跟踪程序函数动态执行流程相关推荐

  1. 动态执行流程分析和性能瓶颈分析的利器——gperftools的Cpu Profiler

    在<动态执行流程分析和性能瓶颈分析的利器--valgrind的callgrind>中,我们领略了valgrind对流程和性能瓶颈分析的强大能力.本文将介绍拥有相似能力的gperftools ...

  2. 动态执行流程分析和性能瓶颈分析的利器——valgrind的callgrind

    在<内存.性能问题分析的利器--valgrind>一文中我们简单介绍了下valgrind工具集,本文将使用callgrind工具进行动态执行流程分析和性能瓶颈分析.(转载请指明出于brea ...

  3. Python 函数的执行流程-函数递归-匿名函数-生成器

    1 函数的执行流程 函数的执行需要对函数进行压栈的,什么是压栈呢,简而言之就是在函数执行时在栈中创建栈帧存放需要变量以及指针的意思.具体涉及的知识非常多,这里就已一个Python脚本简单进行分析. 当 ...

  4. 梆梆加固函数抽取执行流程

    梆梆加固函数抽取执行流程:函数的第一条指令是goto,然后中间是一系列的nop(预留空间),第一条指令goto到末尾,跳过预留空间,跳转到的位置是一条invoke指令,调用壳中的还原函数,还原函数会将 ...

  5. mysql函数 动态语句_自定义函数动态执行SQL语句

    Oracle 动态SQL有两种写法:用 DBMS_SQL 或 execute immediate,建议使用后者. DDL 和 DML Sql代码 收藏代码 /*** DDL ***/ begin EX ...

  6. java 毕向东 内部类_Java基础毕向东day05 对象与对象的区别,匿名内部类,函数的执行流程。...

    1.Car c = new Car(); Car c2 = new Car(); 1> c 和 c2之间的区别? public static void main(String[] args) { ...

  7. mysql8.0源代码解析_MySQL8.0.11源码分析之mysql关键函数和执行流程

    mysql是命令行客户端程序 ,交互式输入SQL语句或从文件以批处理模式执行它们的命令行工具. 入口函数 int main(int argc, char *argv[]) { if (get_opti ...

  8. pip包管理工具-install执行流程简单查看

    pip概述 pip是python提供的包管理工具,该工具提供了对python包的查找.下载.安装与卸载等功能的工具,当前是python中比较主流的管理工具. pip下载安装包的概述 pip工具的本质通 ...

  9. 一文弄懂printf函数从用户态到内核态的执行流程

    目录 1.简介 2.示例代码 3.程序执行初探 4.用户态处理流程 5.内核态处理流程 5.1. 软中断处理 5.2 系统调用返回 5.3 系统调用处理 5.4 stdout重定向到console 5 ...

最新文章

  1. [Android]转-Android 中的拿来主义(编译,反编译,AXMLPrinter2,smali,baksmali)!
  2. live的domain服务
  3. 强力推荐!飞桨产业级PaddleNLP最新全景图发布
  4. XML--使用XML来将字符串分隔成行数据
  5. Digit sum【暴力+打表】
  6. 【微信小程序】带你做一个公众号留言系统(附源码)
  7. 深度好文,如何培养真正的数据分析思维?附实践案例
  8. 搜狗浏览器连接海康摄像头,无法显示画面
  9. java远程执行bat命令
  10. 【Pytorch神经网络理论篇】 40 Transformers中的词表工具Tokenizer
  11. VB连接数据库SQL sever
  12. 参数显著性检验的p值小于显著性水平不等于其具有经济学意义
  13. 树莓派基于motion的usb摄像头监控
  14. 用迅雷或者IDM下载下载百度网盘文件方法
  15. 2022-2027年中国民办高校行业市场全景评估及发展战略规划报告
  16. java飞翔的小鸟游戏实验报告,BirdGame 飞翔的小鸟游戏源码,仿照 编写的java版本 ,所有的 功能完整。 s 249万源代码下载- www.pudn.com...
  17. CentOS yum方式升级内核kernel
  18. 【图神经网络】异构时间图卷积网络HTGCN——用于社区检测
  19. 高德定位,只能定位一次,导航图标就消失
  20. 中国六大最忙和六大最懒城市

热门文章

  1. Android 高仿新浪微博底部导航栏,实现双击首页Tab,页面的ListView滚动、刷新
  2. 关于spring事务管理
  3. 【分块答案】【最小割】bzoj1532 [POI2005]Kos-Dicing
  4. error LNK2019: 无法解析的外部符号 __imp__inet_ntoa@4
  5. VC中BSTR和CString的使用
  6. 防止IE6出现BUG的十种常见解决方法
  7. xadmin引入样式无效
  8. MyEcplise安装Freemarker插件(支持.ftl文件)
  9. 2015-10-11 Sunday 晴 ARM学习
  10. 如何确定一个IAR工程所使用的IAR版本