Процессы сопоставления провайдера pid, которые приходят и уходят в dtrace

Я хотел бы отследить все вызовы функций для определенной библиотеки в процессе, но процесс будет регулярно выходить и повторно открываться, и я хочу продолжать трассировку.

Я делаю это сейчас:

oneshot$target:LIBRARY::entry
{
    printf("%s\n", probefunc);
}

Тем не менее, это позволяет мне предоставлять только один пид за раз. Могу ли я продолжать это?

Я хочу что-то вроде:

*:LIBRARY::entry
/execname == "foo"/

но это * не работает там.

Спасибо!

1 ответ

Я не думаю, что вы можете сделать это с помощью одного сценария dtrace. Вам нужно два (по крайней мере...). И вам нужно иметь способность запускать разрушительные system() действие, которое скорее всего означает root доступ.

Предположим, вы хотите запустить этот скрипт на любом новом ls процесс:

#!/usr/sbin/dtrace -s

pid$1:libc::entry
{
    printf( "func: %s\n", probefunc );
}

Предполагая, что путь к этому сценарию /root/dtrace/tracelibc.d, следующий скрипт запустится dtrace на любой новый ls процесс, который начинается. Обратите внимание, что вам нужно #pragma D option destructive быть в состоянии начать dtrace на новый процесс:

#!/usr/sbin/dtrace -s

#pragma D option destructive
#pragma D option quiet

proc:::exec-success
/ "ls" == basename( execname ) /
{
    printf( "tracing process %d\n", pid );
    system( "/root/dtrace/tracelibc.d %d", pid );
}

Это должно работать, но в этом случае ls такой недолговечный процесс, что нечто подобное происходит довольно часто:

dtrace: failed to compile script /root/dtrace/tracelibc.d: line 10:
    failed to grab process 12289

Процесс ушел к тому времени dtrace начинается Если вы отслеживаете долгоживущие процессы и не заботитесь о том, что вы можете пропустить первые несколько проб, потому что dtrace требуется время, чтобы присоединиться, все готово.

Но если вы хотите отследить недолговечные процессы, вам нужно остановить процесс сразу после его запуска, а затем перезапустить после dtrace присоединяет:

#!/usr/sbin/dtrace -s

#pragma D option destructive
#pragma D option quiet

proc:::exec-success
/ "ls" == basename( execname ) /
{
    printf( "stopping process %d\n", pid );
    system( "/root/dtrace/tracelibc.d %d", pid );
    stop();
}

и начать его обратно в tracelibc.d:

#!/usr/sbin/dtrace -s

#pragma D option destructive

BEGIN
{
    system( "prun %d", $1 );
}

pid$1:libc::entry
{
    printf( "func: %s\n", probefunc );
}

Обратите внимание, что я использую Solaris prun перезапустить остановленный процесс. Вы бы посмотрели на Mac dtrace документация для stop() позвоните, чтобы получить Mac эквивалент Solaris prun,

Но... упс. Два приведенных выше сценария объединяются для создания:

stopping process 12274
dtrace: failed to compile script /root/dtrace/tracelibc.d: line 10:
    probe description pid12274:libc::entry does not match any probes

Почему это говорит pid12274:libc::entry не соответствует ни одного зонда? О да - когда exec возвращается, libc.so общий объект еще не загружен в память. Нам нужен зонд, который гарантированно существует в целевом процессе и который вызывается после libc.so загружен, но перед обработкой. main должно хватить. Так что основным скриптом для запуска всего этого становится:

#!/usr/sbin/dtrace -s

#pragma D option destructive
#pragma D option quiet

proc:::exec-success
/ "ls" == basename( execname ) /
{
    printf( "stopping process %d\n", pid );
    system( "/root/dtrace/tracemain.d %d", pid );
    stop();
}

Это начинает tracemain.d скрипт, который перезапускает процесс, загружает tracelibc.d сценарий и снова останавливает процесс:

#!/usr/sbin/dtrace -s

#pragma D option destructive
#pragma D option quiet

BEGIN
{
    system( "prun %d", $1 );
}

pid$1::main:entry
{
    system( "/root/dtrace/tracelibc.d %d", $1 );
    stop();
    /* this instance of dtrace is now done */
    exit( 0 );
}

А также tracelibc.d добавляет свой собственный system( "prun %d", $1 ); в BEGIN зонд, и это выглядит так:

#!/usr/sbin/dtrace -s

#pragma D option destructive

BEGIN
{
    system( "prun %d", $1 );
}

pid$1:libc::entry
{
    printf( "func: %s\n", probefunc );
}

Эти три действительно замедляют ls процесс, но они производят ожидаемый результат - и есть много, как и ожидалось.

Другие вопросы по тегам