процессы сопоставления провайдера pid, которые приходят и уходят в dtrace - PullRequest
0 голосов
/ 29 апреля 2018

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

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

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

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

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

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

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

Спасибо!

1 Ответ

0 голосов
/ 30 апреля 2018

Я не думаю, что вы можете сделать это с помощью одного скрипта 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, но они дают ожидаемый результат - и его, как и ожидалось, много.

...