我可能无法立即回到这个问题,但我想既然遇到了这个问题,我就会记下来:
首先,我不确定调用它的正确方法是什么;我在标题中尝试过“descend”和“resolve”,但我想知道是否有更合适的术语。从本质上讲,我想要的是获得像我从内核系统调用 - ar.linux.it获得的这张图片所示的东西:
这是一个更具体的示例 - 考虑以下小型且不工作(它只会导致“断言失败”),但可编译的 ALSA 代码:
// atest.c
#include <alsa/asoundlib.h>
static snd_pcm_t *playbck_pcm_handle;
static char wrsrcbuf[256] = {[0 ... 255] = 5}; // initialization gcc specific
static snd_pcm_uframes_t period_frames = 32;
static int ret;
int main() {
ret = snd_pcm_writei(playbck_pcm_handle, wrsrcbuf, period_frames);
return 0;
}
我可以用:
gcc -Wall -g atest.c -lasound -o atest
...然后,我可以观察装配objdump
:
$ objdump -d -M intel -S atest
...
int main() {
...
ret = snd_pcm_writei(playbck_pcm_handle, wrsrcbuf, period_frames);
804842d: 8b 15 40 a1 04 08 mov edx,DWORD PTR ds:0x804a140
...
8048447: e8 0c ff ff ff call 8048358 <snd_pcm_writei@plt>
...
return 0;
8048451: b8 00 00 00 00 mov eax,0x0
}
...
...这仅告诉我<snd_pcm_writei@plt>
将调用一个子例程-但它没有告诉我,例如,哪个库目标文件(旁注:给定编译通过,这是否意味着gcc
将知道库的位置为当前系统上的目标文件?)
然后,我原则上可以运行程序(虽然不是这个),并通过使用中内置的 Linux 跟踪(ftrace
)功能/sys/kernel/debug/tracing/trace
,获取运行时内核日志。由于内核的抢占性质和调度,我们不能真正指望执行顺序的任何恒定性,但原则上,我们可以得到这样的东西(虽然不是来自上面的例子,因为它没有做任何适当的设备初始化):
sys_ioctl() {
...
do_vfs_ioctl() {
snd_pcm_playback_ioctl() {
snd_pcm_playback_ioctl1() {
_cond_resched();
copy_from_user() {
...
}
snd_pcm_lib_write() {
snd_pcm_lib_write1() {
_raw_read_lock_irq();
_raw_spin_lock();
snd_pcm_update_hw_ptr() {
snd_pcm_update_hw_ptr0() {
azx_pcm_pointer() {
...
所以,这告诉我响应snd_pcm_writei
命令 - 最终sys_ioctl
-> snd_pcm_playback_ioctl
->snd_pcm_lib_write
将被调用,这将是内核中内置的 ALSA 函数;但是,也会调用类似的函数azx_pcm_pointer()
,它们是设备驱动程序azx_pcm_pointer
的一部分(是hda-intel
驱动程序的一部分)。
所以我的问题是 - 是否有一个应用程序可以将程序的函数“下降”树从用户空间输出到内核空间 - 无论是在编译时(这将是gcc
它本身,但如果它们为此目的存在一些特殊开关) ,或后编译(如使用时objdump
,但不是“运行时”,因为分析的程序本身没有运行)?例如,对于这个例子,我希望输出如下:
int main() { # atest
...
ret = snd_pcm_writei(playbck_pcm_handle, wrsrcbuf, period_frames); # atest
...
<snd_pcm_writei@plt> # libasound.so ??
...
sys_ioctl() { # ???.(k)o?
...
snd_pcm_playback_ioctl() { # ???.(k)o?
...
azx_pcm_pointer() { # /lib/modules/.../sound/pci/hda/snd-hda-intel.ko
...
...
我知道代码可以采用许多代码路径 - 所以希望这个工具能够全部解决它们 - 或者允许设置变量,以限制代码路径的数量;但一般来说,输出将是一棵树(然后可以用,比如说,来可视化graphviz
)。
我也明白,如果不进入运行时解析驱动程序可能是不可能的(因为设备 - 及其驱动程序 - 可以在运行时由用户空间程序的命令行参数指定);但我希望至少有一个通知告诉我“这里将调用一个未指定的驱动程序函数”。