【发布时间】:2013-09-18 07:50:54
【问题描述】:
我可能无法立即回过头来回答这个问题,但我想既然遇到了这个问题,我就会记下来:
首先,我不确定正确的称呼方式是什么;我在标题中尝试过“descend”和“resolve”,但我想知道是否有更合适的术语。本质上,我想要的是获得像我从Kernel System Calls - 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会知道库的位置作为当前系统上的目标文件吗?)
然后,我原则上可以运行程序(虽然不是这个),并通过使用/sys/kernel/debug/tracing/trace中内置的Linux跟踪(ftrace)功能,获取运行时内核日志。由于内核的抢占性质和调度,我们不能真正指望执行顺序的任何恒定性,但原则上,我们可以得到这样的东西(虽然不是来自上面的例子,因为它没有任何适当的设备初始化):
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 来可视化)。
我也明白,如果不进入运行时解析驱动程序可能是不可能的(因为设备 - 及其驱动程序 - 可以在运行时由用户空间程序的命令行参数指定);但我希望至少有一个通知告诉我“这里将调用一个未指定的驱动程序函数”。
【问题讨论】: