Systemtap简单的用户空间示例(函数跟踪,Ubuntu)?

时间:2017-10-17 06:41:32

标签: c++ ubuntu systemtap

(我花了很长时间才开始工作,所以我想我会记录下来 - 首先,把它正式作为一个问题):

在用户空间应用程序中是否有一个简单的systemtap探测/跟踪函数示例,最好是在C ++中?我的系统是Ubuntu 14.04:

$ uname -a
Linux mypc 4.2.0-42-generic #49~14.04.1-Ubuntu SMP Wed Jun 29 20:22:11 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
$ g++ --version
g++ (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4 ...
$ stap --version
Systemtap translator/driver (version 2.3/0.158, Debian version 2.3-1ubuntu1.4 (trusty))

1 个答案:

答案 0 :(得分:4)

好的,所以这并不是微不足道的 - 首先,我最终在Ubuntu 14.04上得到了一个(更新的)内核4.2.0;显然,Ubuntu 14.04附带的systemtap对于该内核来说太旧了(见下文)。这意味着我必须从源代码构建systemtap - 这是我的程序:

cd /path/to/src
git clone git://sourceware.org/git/elfutils.git elfutils_git
git clone git://sourceware.org/git/systemtap.git systemtap_git
cd systemtap_git
./configure --with-elfutils=/path/to/src/elfutils_git --prefix=/path/to/src/systemtap_git/local --enable-docs=no
make
make install
# after this, there are `stap` executables in: 
#  /path/to/src/systemtap_git/stap
#  /path/to/src/systemtap_git/local/bin/stap

这就是事情:

  • 您不应单独构建elfutils,然后systemtap - 而应将elfutils源目录传递给--with-elfutils的{​​{1}} { {1}},然后systemtap并构建configure
  • 你必须configure elfutils,即使它在非系统/私人(本地)目录中! - 否则,会发生一些错误(遗憾的是,没有记录它们)

构建完成后,make install报告版本:

systemtap

好的,所以我找到了一个用于分析的基本Fibonacci C ++示例,我稍作修改,并调用了stap

$ ./stap --version
Systemtap translator/driver (version 3.2/0.170, commit release-3.1-331-g0efba6fc74c8 + changes) ...

首先我尝试这样编译:

/tmp/fibo.cpp

现在,我们要做的第一件事就是弄清楚哪些函数可以在我们的可执行文件中进行探测;为此,我们可以使用// based on: http://www.cplusplus.com/articles/LT75fSEw/ #include <iostream> using namespace std; class Fibonacci{ public: int a, b, c; void generate(int); void doFibonacciStep(int); }; void Fibonacci::doFibonacciStep(int istep){ c = a + b; cout << " istep: " << istep << " c: " << c << endl; a = b; b = c; } void Fibonacci::generate(int n){ a = 0; b = 1; cout << " Start: a "<< a << " b " << b << endl; for(int i=1; i<= n-2; i++){ doFibonacciStep(i); } } int main() { cout << "Hello world! Fibonacci series" << endl; cout << "Enter number of items you need in the series: "; int n; cin >> n; Fibonacci fibonacci; fibonacci.generate(n); return 0; } (注意,这里我仍在使用旧的,Ubuntu 14.04系统cd /tmp g++ -g fibo.cpp -o fibo.exe ):

stap -L

很好 - 所以我想探测/追踪stap及其输入参数$ stap -L 'process("/tmp/fibo.exe").function("*").call' process("/tmp/fibo.exe").function("_GLOBAL__sub_I__ZN9Fibonacci15doFibonacciStepEi").call process("/tmp/fibo.exe").function("__static_initialization_and_destruction_0").call $__initialize_p:int $__priority:int process("/tmp/fibo.exe").function("doFibonacciStep@/tmp/fibo.cpp:13").call $this:class Fibonacci* const $istep:int process("/tmp/fibo.exe").function("generate@/tmp/fibo.cpp:20").call $this:class Fibonacci* const $n:int process("/tmp/fibo.exe").function("main@/tmp/fibo.cpp:28").call 。所以我尝试从命令行:

doFibonacciStep

哎呀,像这样的错误 - 不好。帖子"__tracepoint_sched_process_fork undefined" when run systemstap script解释说,基本上istep版本对于我所拥有的内核来说太旧了 - 这需要从源代码构建(上图)。现在让我们看看新的$ sudo stap -e 'probe process("/tmp/fibo.exe").function("Fibonacci::doFibonacciStep").call { printf("stap do step: %d\n", $istep) }' -c /tmp/fibo.exe WARNING: "__tracepoint_sched_process_fork" [/tmp/stap51A5tV/stap_ab5b824c79b38b5207910696c49c4e22_1760.ko] undefined! WARNING: "__tracepoint_sys_exit" [/tmp/stap51A5tV/stap_ab5b824c79b38b5207910696c49c4e22_1760.ko] undefined! WARNING: "__tracepoint_sys_enter" [/tmp/stap51A5tV/stap_ab5b824c79b38b5207910696c49c4e22_1760.ko] undefined! WARNING: "__tracepoint_sched_process_exec" [/tmp/stap51A5tV/stap_ab5b824c79b38b5207910696c49c4e22_1760.ko] undefined! WARNING: "__tracepoint_sched_process_exit" [/tmp/stap51A5tV/stap_ab5b824c79b38b5207910696c49c4e22_1760.ko] undefined! ERROR: Couldn't insert module '/tmp/stap51A5tV/stap_ab5b824c79b38b5207910696c49c4e22_1760.ko': Unknown symbol in module WARNING: /usr/bin/staprun exited with status: 1 Pass 5: run failed. [man error::pass5] Tip: /usr/share/doc/systemtap/README.Debian should help you get started. $ sudo stap -e 'probe process("/tmp/fibo.exe").function("Fibonacci::doFibonacciStep").call { printf("stap do step: %d\n", $istep) }' -c /tmp/fibo.exe ERROR: Couldn't insert module '/tmp/stapmo60OW/stap_ab5b824c79b38b5207910696c49c4e22_1760.ko': Unknown symbol in module WARNING: /usr/bin/staprun exited with status: 1 Pass 5: run failed. [man error::pass5] 是如何工作的:

stap

很好,这已经比旧版本更冗长了。无论如何,我想调查stap -L函数及其输入参数$ /path/to/src/systemtap_git/stap -L 'process("/tmp/fibo.exe").function("*").call' process("/tmp/fibo.exe").function("_GLOBAL__sub_I__ZN9Fibonacci15doFibonacciStepEi@/tmp/fibo.cpp:37").call process("/tmp/fibo.exe").function("__do_global_dtors_aux").call process("/tmp/fibo.exe").function("__libc_csu_fini").call process("/tmp/fibo.exe").function("__libc_csu_init").call process("/tmp/fibo.exe").function("__static_initialization_and_destruction_0@/tmp/fibo.cpp:37").call $__initialize_p:int $__priority:int process("/tmp/fibo.exe").function("_fini").call process("/tmp/fibo.exe").function("_init").call process("/tmp/fibo.exe").function("_start").call process("/tmp/fibo.exe").function("deregister_tm_clones").call process("/tmp/fibo.exe").function("doFibonacciStep@/tmp/fibo.cpp:13").call $this:class Fibonacci* const $istep:int process("/tmp/fibo.exe").function("frame_dummy").call process("/tmp/fibo.exe").function("generate@/tmp/fibo.cpp:20").call $this:class Fibonacci* const $n:int process("/tmp/fibo.exe").function("main@/tmp/fibo.cpp:28").call process("/tmp/fibo.exe").function("register_tm_clones").call 。所以我在命令行上写这个:

doFibonacciStep

哎呀 - 一个令人讨厌的错误,并没有真正告诉我任何事情 - 关于这个错误的错误报告很少(主要来自2010年)。所以我就要被困在这里,出于某些原因,我记得前几天,我用$istep汇编了一些程序(原因我现在已经忘记了);所以我想我会尝试一下 - 而且,现在它真的开始工作了:

$ sudo /path/to/src/systemtap_git/stap -e 'probe process("/tmp/fibo.exe").function("Fibonacci::doFibonacciStep").call { printf("stap do step: %d\n", $istep) }' -c /tmp/fibo.exe 
semantic error: while processing probe process("/tmp/fibo.exe").function("Fibonacci::doFibonacciStep@/tmp/fibo.cpp:13").call from: process("/tmp/fibo.exe").function("Fibonacci::doFibonacciStep").call

semantic error: No cfa_ops supplied, but needed by DW_OP_call_frame_cfa: identifier '$istep' at <input>:1:107
        source: probe process("/tmp/fibo.exe").function("Fibonacci::doFibonacciStep").call { printf("stap do step: %d\n", $istep) }

Pass 2: analysis failed.  [man error::pass2]

尼斯!请注意,{/ 1}}打印实际上是在程序完成后打印的(也就是说,它们不会与它们发生的实际程序输出交错)。

我们可以直接在命令行上指定探测点和行为,而不是编写脚本 - 所以这里是-gdwarf-2 - 这里有一些额外的东西:

$ g++ -gdwarf-2 fibo.cpp -o fibo.exe
$ sudo /path/to/src/systemtap_git/stap -e 'probe process("/tmp/fibo.exe").function("Fibonacci::doFibonacciStep").call { printf("stap do step: %d\n", $istep) }' -c /tmp/fibo.exe 
Hello world! Fibonacci series
Enter number of items you need in the series: 5
 Start: a 0 b 1
  istep: 1 c: 1
  istep: 2 c: 2
  istep: 3 c: 3
stap do step: 1
stap do step: 2
stap do step: 3

...使用此脚本,我们的调用和结果如下所示:

stap

再次注意 - check-do-step.stp字符串在开始时没有像我们预期的那样点击,但只有在程序已经开始生成输出之后才会出现。

嗯,我想这就是它 - 对我来说当然足够好了,举个简单的例子......