非常感謝@fche for pointing me in the right direction。正如他所說,systemtap
的symdata()
函數可用於檢索包含大小的給定地址處的符號信息。因此,我們可以寫我們自己的sizeof()
功能解析它以提取尺寸爲:
function sizeof(address:long) {
tokenize(symdata(address), "/");
return strtol(tokenize("",""),16);
}
如果我們看那個symdata()
函數的定義,我們可以看到,它本身就是一個systemtap
功能,它利用了_stp_snprint_addr()
的C函數,它自己調用_stp_kallsyms_lookup()
來檢索數據。這意味着我們也可以直接使用stp_kallsyms_lookup()
定義我們自己sizeof()
:
function sizeof:long (addr:long) %{ /* pure */ /* pragma:symbols */
STAP_RETVALUE = -1;
_stp_kallsyms_lookup(STAP_ARG_addr, (unsigned long*)&(STAP_RETVALUE), NULL, NULL, NULL);
%}
(注意,我們需要-g
(大師)這裏我們使用嵌入式C)。
現在,要獲得數組大小,我們需要數組元素的大小。一種方法可以是使用數組的2個元素之間的地址偏移量。因此,我們可以定義我們array_size()
功能:
function array_size(first:long, second:long) {
return sizeof(first)/(second - first);
}
(其中sizeof()
是一個或另一個的上面定義的函數)。
,並調用它爲:
probe begin {
printf("%d\n", array_size(
&@var("[email protected]/unix/af_unix.c")[0],
&@var("[email protected]/unix/af_unix.c")[1]));
exit();
}
這讓我們512
預期。
對於sizeof()
,另一種方法可以是使用C sizeof()
操作者:
$ sudo stap -ge '
%{ #include <net/af_unix.h> %}
probe begin {
printf("%d\n", %{ sizeof(unix_socket_table)/sizeof(unix_socket_table[0]) %});
exit();
}'
512
(也需要-g
),但是然後被從內核源代碼(頭文件)檢索到的信息,而不是調試信息,所以雖然這對於在頭文件中定義的內核數組來說很有效,但這種方法對於所有數組都不是必需的。