Я сразу приведу список статей на которые опирался, при проведении дальнейших экпериментов:
Список макроопределений systemtap:
Название | Описание |
---|---|
$$vars | Expands to a character string that is equivalent to sprintf("parm1=%x ... parmN=%x var1=%x ... varN=%x", parm1, ..., parmN, var1, ..., varN) for each variable in scope at the probe point. Some values may be printed as “=?” if their run-time location cannot be found. |
$$locals | Expands to a subset of $$vars containing only the local variables. |
$$parms | Expands to a subset of $$vars containing only the function parameters. |
$$return | Is available in return probes only. It expands to a string that is equivalent to sprintf("return=%x", $return) if the probed function has a return value, or else an empty string |
Продолжу...
И так мы имеем программу memory, давайте отследим, сколько раз в ней вызывается malloc функция:
- Найдем сведения о фнукции malloc, необходимы для systemtap
1.1 Анализируем бинарник утилитой nm
[probes]# nm ./memory | grep malloc U malloc@@GLIBC_2.2.5
Это нам говорит, что символ не определен U, значит он из библиотеки. 1.2 Проверим список библиотек утилитой ldd:
[probes]# ldd ./memory linux-vdso.so.1 => (0x00007fff1fde4000) libc.so.6 => /lib64/libc.so.6 (0x00007f900d6d4000) /lib64/ld-linux-x86-64.so.2 (0x00007f900daaf000)
Функция скорее всего в
/lib64/libc.so.6
1.3 проверим это утилитой nm опять, но уже на файл библиотеки:[probes]# nm /lib64/libc.so.6 | grep malloc ... 000000000007ff70 T __libc_malloc 000000000007ff70 T malloc 000000000007ff70 t __malloc
Теперь то что нужно, T или t
- Значит дочтавляем debuginfo для glibc
yum install glibc-debuginfo
. И прогоняем вот такую команду:[probes]# stap -L 'process("/lib64/libc.so.6").statement("*malloc*")' process("/usr/lib64/libc-2.17.so").statement("__libc_malloc@/usr/src/debug/glibc-2.17-c758a686/malloc/malloc.c:2881") $bytes:size_t
Вот первая попавшаяса функция, та что нам нужна, и информация о параметре - имя и размерность
$bytes:size_t
. Допишем наш проб, чтоб он выводил, что-нибудь при вызове функции malloc и выдавал, что она возвращает и самое интересное, где именно.
Немного покопавшись с кодом malloc.c, и поэкспериментировав с process("/lib64/libc.so.6").function("__libc_malloc")
, я обнаружил, что она вызывается дважды. Поэтому в результирующем пробе, я поставил точку проверки на _int_malloc
и на free
:
#! /usr/bin/env stap
probe process("./memory").begin {
printf("Test process started %d\n", pid())
}
probe process("./memory").end {
printf("Test process ended %d\n", pid())
}
probe process("/lib64/libc.so.6").function("_int_malloc"){
printf("%s:%s malloc called with param %d\n", pp(), ppfunc(), $bytes)
}
probe process("/lib64/libc.so.6").function("_int_malloc").return{
printf("malloc returned %p\n", $return)
}
probe process("/lib64/libc.so.6").function("free"){
printf("free called with param %p\n", $mem)
}
probe begin {
printf("Waiting for even or Ctrl+C\n")
}
И работа программы:
[probes]# stap malloc.stp -c "./memory"
Waiting for even or Ctrl+C
Test process started 6231
process("/usr/lib64/libc-2.17.so").function("_int_malloc@/usr/src/debug/glibc-2.17-c758a686/malloc/malloc.c:3308"):_int_malloc malloc called with param 1024
malloc returned 0x767010
free called with param 0x767010
Test process ended 6231
А теперь промоделируем ситуация, когда malloc
возвращает NULL:
#! /usr/bin/env stap
probe process("./memory").begin {
printf("Test process started %d\n", pid())
}
probe process("./memory").end {
printf("Test process ended %d\n", pid())
}
probe process("/lib64/libc.so.6").function("_int_malloc"){
printf("%s:%s malloc called with param %d\n", pp(), ppfunc(), $bytes)
}
probe process("/lib64/libc.so.6").function("_int_malloc").return{
$return = 0
}
probe process("/lib64/libc.so.6").function("free"){
printf("free called with param %p\n", $mem)
}
probe begin {
printf("Waiting for even or Ctrl+C\n")
}
В пробе probe process("/lib64/libc.so.6").function("_int_malloc").return
я перезаписал возвращаемое значение в 0 функцией $return = 0
и вот результат:
[probes]# stap -g malloc.stp -c "./memory"
Ooops
WARNING: Child process exited with status 1
Waiting for even or Ctrl+C
Test process started 6512
process("/usr/lib64/libc-2.17.so").function("_int_malloc@/usr/src/debug/glibc-2.17-c758a686/malloc/malloc.c:3308"):_int_malloc malloc called with param 1024
process("/usr/lib64/libc-2.17.so").function("_int_malloc@/usr/src/debug/glibc-2.17-c758a686/malloc/malloc.c:3308"):_int_malloc malloc called with param 1024
Test process ended 6512
WARNING: /usr/bin/staprun exited with status: 1
Pass 5: run failed. [man error::pass5]
Программу я запускал в guru-mode иначе stap не позволит переписать $return. По выводу видим, что дважды программа пыталась выделить память и в результате прекратила работу сообщив Ooops
.