Огромное спасибо @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()
для извлечения данных. Это означает, что мы можем определить наши собственные sizeof()
с помощью stp_kallsyms_lookup()
непосредственно:
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).
Теперь, чтобы получить размер массива, нам нужен размер элементов массивов. Одним из подходов может быть использование смещения адреса между двумя элементами массива. Таким образом, мы могли бы определить нашу 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
), но тогда информация извлекается из исходного кода ядра (файлы заголовков), не отладить информацию, поэтому, хотя это будет работать для массивов ядер, которые определены в файлах заголовков, этот подход не будет работать для всех массивов.