在 Linux 中跟踪本地函数调用的工具 [英] Tool to trace local function calls in Linux

查看:35
本文介绍了在 Linux 中跟踪本地函数调用的工具的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找像 ltracestrace 可以跟踪可执行文件中本地定义的函数.ltrace 只跟踪动态库调用,strace 只跟踪系统调用.例如,给定以下 C 程序:

I am looking for a tool like ltrace or strace that can trace locally defined functions in an executable. ltrace only traces dynamic library calls and strace only traces system calls. For example, given the following C program:

#include <stdio.h>

int triple ( int x )
{
  return 3 * x;
}

int main (void)
{
  printf("%d
", triple(10));
  return 0;
}

使用 ltrace 运行程序将显示对 printf 的调用,因为这是一个标准库函数(它是我系统上的动态库)和 strace 将显示来自启动代码的所有系统调用、用于实现 printf 的系统调用和关闭代码,但我想要一些可以显示函数 triple 被调用的东西.假设本地函数没有被优化编译器内联并且二进制文件没有被剥离(删除符号),是否有工具可以做到这一点?

Running the program with ltrace will show the call to printf since that is a standard library function (which is a dynamic library on my system) and strace will show all the system calls from the startup code, the system calls used to implement printf, and the shutdown code, but I want something that will show me that the function triple was called. Assuming that the local functions have not been inlined by an optimizing compiler and that the binary has not been stripped (symbols removed), is there a tool that can do this?

编辑

几点说明:

  • 如果该工具还提供非本地函数的跟踪信息,那也没关系.
  • 我不想在支持特定工具的情况下重新编译程序,可执行文件中的符号信息就足够了.
  • 如果我能像使用 ltrace/strace 一样使用该工具附加到现有进程,我会非常高兴.

推荐答案

假设您只想收到特定功能的通知,您可以这样做:

Assuming you only want to be notified for specific functions, you can do it like this:

用调试信息编译(因为你已经有了符号信息,你可能也有足够的调试信息)

compile with debug informations (as you already have symbol informations, you probably also have enough debugs in)

给定

#include <iostream>

int fac(int n) {
    if(n == 0)
        return 1;
    return n * fac(n-1);
}

int main()
{
    for(int i=0;i<4;i++)
        std::cout << fac(i) << std::endl;
}

使用gdb进行跟踪:

[js@HOST2 cpp]$ g++ -g3 test.cpp
[js@HOST2 cpp]$ gdb ./a.out
(gdb) b fac
Breakpoint 1 at 0x804866a: file test.cpp, line 4.
(gdb) commands 1
Type commands for when breakpoint 1 is hit, one per line.
End with a line saying just "end".
>silent
>bt 1
>c
>end
(gdb) run
Starting program: /home/js/cpp/a.out
#0  fac (n=0) at test.cpp:4
1
#0  fac (n=1) at test.cpp:4
#0  fac (n=0) at test.cpp:4
1
#0  fac (n=2) at test.cpp:4
#0  fac (n=1) at test.cpp:4
#0  fac (n=0) at test.cpp:4
2
#0  fac (n=3) at test.cpp:4
#0  fac (n=2) at test.cpp:4
#0  fac (n=1) at test.cpp:4
#0  fac (n=0) at test.cpp:4
6

Program exited normally.
(gdb)

这是我收集所有函数地址的方法:

Here is what i do to collect all function's addresses:

tmp=$(mktemp)
readelf -s ./a.out | gawk '
{ 
  if($4 == "FUNC" && $2 != 0) { 
    print "# code for " $NF; 
    print "b *0x" $2; 
    print "commands"; 
    print "silent"; 
    print "bt 1"; 
    print "c"; 
    print "end"; 
    print ""; 
  } 
}' > $tmp; 
gdb --command=$tmp ./a.out; 
rm -f $tmp

请注意,不是只打印当前帧(bt 1),你可以做任何你喜欢的事情,打印一些全局的值,执行一些 shell 命令或者如果它碰到 fatal_bomb_exploded 函数 :) 可悲的是,gcc 在两者之间输出了一些当前语言已更改"的消息.但这很容易解决.没什么大不了的.

Note that instead of just printing the current frame(bt 1), you can do anything you like, printing the value of some global, executing some shell command or mailing something if it hits the fatal_bomb_exploded function :) Sadly, gcc outputs some "Current Language changed" messages in between. But that's easily grepped out. No big deal.

这篇关于在 Linux 中跟踪本地函数调用的工具的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆