OK,所以这并没有变成是微不足道的 - 首先,我莫名其妙地结束了在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
的systemtap
的configure
,其然后将configure
和生成elfutils
以及。
- 即使在非系统/私有(本地)目录中,您也必须执行
make install
的systemtap
! - 否则,会出现一些错误(不幸的是,没有记录他们)
建成后,stap
报告版本:
$ ./stap --version
Systemtap translator/driver (version 3.2/0.170, commit release-3.1-331-g0efba6fc74c8 + changes) ...
好了,我发现了用于分析的基本斐波纳契C++例子,这是我略作修改,并呼吁/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;
}
开始我尝试编译它是这样的:
cd /tmp
g++ -g fibo.cpp -o fibo.exe
现在,我们要做的第一件事是找出可用于我们可执行文件中探测的函数;为此,我们可以使用stap -L
(注意,我在这里仍然使用旧的,Ubuntu 14.04系统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("[email protected]/tmp/fibo.cpp:13").call $this:class Fibonacci* const $istep:int
process("/tmp/fibo.exe").function("[email protected]/tmp/fibo.cpp:20").call $this:class Fibonacci* const $n:int
process("/tmp/fibo.exe").function("[email protected]/tmp/fibo.cpp:28").call
尼斯 - 所以我想探测/追踪doFibonacciStep
和它的输入参数, 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]
哎哟,这样的错误 - 不好。文章"__tracepoint_sched_process_fork undefined" when run systemstap script解释说,基本上stap
版本对于我拥有的内核来说太旧了 - 这要求从源代码开始构建(上图)。让我们看看现在怎么新stap -L
作品:
$ /path/to/src/systemtap_git/stap -L 'process("/tmp/fibo.exe").function("*").call'
process("/tmp/fibo.exe").function("[email protected]/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("[email protected]/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("[email protected]/tmp/fibo.cpp:13").call $this:class Fibonacci* const $istep:int
process("/tmp/fibo.exe").function("frame_dummy").call
process("/tmp/fibo.exe").function("[email protected]/tmp/fibo.cpp:20").call $this:class Fibonacci* const $n:int
process("/tmp/fibo.exe").function("[email protected]/tmp/fibo.cpp:28").call
process("/tmp/fibo.exe").function("register_tm_clones").call
尼斯,这已经比老版更详细一点。无论如何,我想探讨doFibonacciStep
函数及其输入参数,这里是$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::[email protected]/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]
哎哟 - 一个讨厌的错误,并没有真正告诉我什么 - 只有很少的错误报告这个错误(和大部分来自2010)。因此,当我因为某些原因而被困在这里时,我记得那天我编了一些程序-gdwarf-2
(因为我现在已经忘记了)。所以我想我会尝试它 - 并且whaddayaknow,它现在开始工作:
不错!请注意,在程序结束后(即它们不与实际出现的程序输出交错),stap
打印实际上是打印。
,而不是直接在命令行上指定探测点和行为,我们可以写一个脚本,而不是 - 所以这里是check-do-step.stp
- 这里有一些额外的东西:
#!/usr/bin/env stap
global stringone = "Testing String One"
global stringtwo = "Testing String Two"
probe begin {
printf("begin: %s\n", stringone)
#exit() # must have; else probe end runs only upon Ctrl-C if we only have `begin` and `end` probes!
}
probe process(
"/tmp/fibo.exe"
).function(
"Fibonacci::doFibonacciStep"
).call {
printf("stap do step: %d\n", $istep)
}
probe end {
newstr = "We Are " . stringtwo . " And We're Done" # string concat
printf("%s\n", newstr)
}
...以及与此脚本,我们的电话,结果是这样的:再次
$ sudo /path/to/src/systemtap_git/stap check-do-step.stp -c /tmp/fibo.exe
Hello world! Fibonacci series
Enter number of items you need in the series: begin: Testing String One
6
Start: a 0 b 1
istep: 1 c: 1
istep: 2 c: 2
istep: 3 c: 3
istep: 4 c: 5
stap do step: 1
stap do step: 2
stap do step: 3
stap do step: 4
We Are Testing String Two And We're Done
声明 - begin: Testing ...
串不会在打一开始我们很想否则预期,但只有程序后,已经开始产生输出。
嗯,我想这就是它 - 对我来说当然是够好的,一个简单的例子...
对不起DWARF相关的错误。现代GCC非常擅长优化函数参数,并且在debuginfo中只留下复杂的线索,指出在哪里可以找到它们。 Systemtap尚未完全掌握所有技巧。 -gdwarf2将省略这些复杂的线索(但作为交换,受影响的参数甚至不会被stap看到)。 – fche