15.2. 使用 Dyninst
15.2.1. 在 SystemTap 中使用 Dyninst 复制链接链接已复制到粘贴板!
要将 Dyninst 与 SystemTap 一起使用,以允许非root 用户检测用户空间可执行文件,请使用-- dyninst (or- )命令行选项运行 runtime=dyninststap 命令。这会告知 stap 将 SystemTap 脚本转换为使用 Dyninst 库的 C 代码,将这个 C 代码编译到共享库,然后加载共享库并运行脚本。请注意,执行此操作时,stap 命令还需要指定 -c or -x 命令行选项。
使用 Dyninst 运行时检测可执行文件:
scl enable devtoolset-9 "stap --dyninst -c 'command' option... argument..."
$ scl enable devtoolset-9 "stap --dyninst -c 'command' option... argument..."
同样,使用 Dyninst 运行时检测用户的进程:
scl enable devtoolset-9 "stap --dyninst -x process_id option... argument..."
$ scl enable devtoolset-9 "stap --dyninst -x process_id option... argument..."
有关 Red Hat Developer Toolset 版本 SystemTap 的更多信息,请参阅 第 12 章 SystemTap。有关 SystemTap 及其用法的一般介绍,请参阅 Red Hat Enterprise Linux 7 的 SystemTap Beginners 指南。
例 15.1. 在 SystemTap 中使用 Dyninst
考虑一个名为 exercise.C 的源文件,其内容如下:
此程序提示用户输入起始号,然后计算为 1,对每个迭代调用 print_iteration () 函数,以便将数字打印到标准输出。在命令行中使用 Red Hat Developer Toolset 中的 g++ 编译器编译该程序:
scl enable devtoolset-9 'g++ -g -o exercise exercise.C'
$ scl enable devtoolset-9 'g++ -g -o exercise exercise.C'
现在考虑另一个名为 count.stp 的源文件,其内容如下:
此 SystemTap 脚本打印在执行进程期间调用 print_iteration () 函数的次数。在 练习 二进制文件中运行这个脚本:
15.2.2. 使用 Dyninst 作为独立库 复制链接链接已复制到粘贴板!
在将 Dyninst 库用作应用程序的一部分前,请将 DYNINSTAPI_RT_LIB 环境变量的值设置为运行时库文件的路径:
export DYNINSTAPI_RT_LIB=/opt/rh/devtoolset-9/root/usr/lib64/dyninst/libdyninstAPI_RT.so
$ export DYNINSTAPI_RT_LIB=/opt/rh/devtoolset-9/root/usr/lib64/dyninst/libdyninstAPI_RT.so
这会在当前 shell 会话中设置 DYNINSTAPI_RT_LIB 环境变量。
例 15.2 “使用 Dyninst 作为独立应用程序” 演示了如何编写和构建程序来监控用户空间进程的执行。有关如何使用 Dyninst 的详细信息,请查看 第 15.3 节 “其它资源” 中列出的资源。
例 15.2. 使用 Dyninst 作为独立应用程序
考虑 exercise.C 源文件 例 15.1 “在 SystemTap 中使用 Dyninst” :该程序提示用户输入起始号,然后计数为 1,为每个迭代调用 print_iteration () 函数,以便打印到标准输出的数字。
现在考虑另一个名为 count.C 的源文件,其内容如下:
请注意,在调用任何 Dyninst 库解结构器之前,客户端应用程序应该销毁所有 Bpatch 对象。否则,变异程序可能会意外终止并出现分段错误。要临时解决这个问题,请将 mutator 的 BPatch 对象设置为 main () 函数中的本地变量。或者,如果您需要使用 BPatch 作为全局变量,请在 mutator 退出前手动分离所有 mutatee 进程。
该程序接受进程 ID 和函数名称作为命令行参数,然后打印执行过程中调用函数的次数。您可以使用以下 Makefile 来构建这两个文件:
要在命令行中使用 Red Hat Developer Toolset 的 g++ 编译器编译两个程序,请运行 make 工具:
scl enable devtoolset-9 make
$ scl enable devtoolset-9 make
g++ -g -I/opt/rh/devtoolset-9/root/usr/include/dyninst count.C -c
g++ -g -I/opt/rh/devtoolset-9/root/usr/include/dyninst count.o -L /opt/rh/devtoolset-9/root/usr/lib64/dyninst -ldyninstAPI -o count
g++ -g -I/opt/rh/devtoolset-9/root/usr/include/dyninst exercise.C -o exercise
这会创建一个名为 exercise 的新二进制文件,并在当前工作目录中 计数。
在一个 shell 会话中,按如下所示执行 练习 二进制文件,并等待它提示您输入起始号:
./exercise
$ ./exercise
Enter the starting number:
不要输入这个数字。相反,启动另一个 shell 会话,并在提示符下键入以下内容来设置 DYNINSTAPI_RT_LIB 环境变量,并执行 计数 二进制文件:
export DYNINSTAPI_RT_LIB=/opt/rh/devtoolset-9/root/usr/lib64/dyninst/libdyninstAPI_RT.so ./count `pidof exercise` print_iteration
$ export DYNINSTAPI_RT_LIB=/opt/rh/devtoolset-9/root/usr/lib64/dyninst/libdyninstAPI_RT.so
$ ./count `pidof exercise` print_iteration
Finding function print_iteration(): OK
Instrumenting function print_iteration(): OK
Waiting for process 8607 to exit...
现在,切换回第一个 shell 会话,并根据 练习 程序的要求输入起始号。例如:
当 练习 程序终止时,计数 程序会显示 print_iteration () 函数执行的次数:
Function executed 5 times.
Function executed 5 times.