dtruss
— это элегантный пример сценария, написанного для DTrace, и демонстрация возможностей DTrace. Однако, хотя его сходство с truss
или strace
очень приветствуется в относительно бесплодной OS X, я подозреваю, что dtruss
никогда не предназначался для полной замены ни того, ни другого.
В любом случае, ваш вопрос немного двусмыслен: я не уверен, обеспокоены ли вы тем, что строки, которые вы видите, усечены или что вы вообще не видите никаких строк для sendto()
или recvfrom()
(базовые интерфейсы, обнаруженные DTrace ). Я обращусь к обоим.
Во-первых, DTrace собирает данные в ядре; пользовательские буферы получаются с помощью copyin()
или copyinstr()
языка D перед записью и передачей обратно потребителю — обычно это команда dtrace(1)
. DTrace требует, чтобы размер буфера ядра был известен во время компиляции, и поэтому налагает ограничение на непредсказуемую длину строки. По умолчанию это ограничение составляет 256 байт; если вы видите усечение, вы можете изменить ограничение, добавив, например,
#pragma D option strsize=512
ниже существующего pragma
dtruss
.
Во-вторых, dtruss
жестко закодировано, чтобы знать о требованиях к форматированию различных системных вызовов. Вы не видите какой-либо интерпретации буфера для sendto()
или recvfrom()
в его выводе, потому что они не обрабатываются явно в исходном коде. Ничто не мешает вам найти подходящее место для их добавления, но вместо этого вы можете написать свой собственный скрипт:
bash-3.2# cat sr.d
#pragma D option rawbytes
syscall::sendto:entry,
syscall::recvfrom:entry
/pid == $target/
{
self->bufp = arg1;
self->size = arg2;
}
syscall::sendto:return,
syscall::recvfrom:return
/pid == $target && self->bufp && self->size/
{
printf("%s():\n", probefunc);
tracemem(copyin(self->bufp, self->size), 64);
printf("\n");
self->bufp = self->size = NULL;
}
bash-3.2# dtrace -qs ./sr.d -p 16988
sendto():
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
0: 68 65 6c 6c 6f 00 00 00 00 00 00 00 00 00 00 00 hello...........
10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
^C
bash-3.2#
Обратите внимание, что, что касается строк, мы обязаны установить жесткое ограничение на использование tracemem()
буфера записи данных DTrace. Если предел редко приближается, то это приводит к раздражающему результату, который может быть подавляющим и в основном избыточным. Если вы знаете, что ищете строки, вы можете просто использовать вместо них copyinstr()
; если у вас более современная реализация DTrace, чем моя OS X 10.6.8, вы можете обнаружить, что можете написать
tracemem(copyin(self->bufp, self->size), 64, self->size);
где второй аргумент по-прежнему жестко ограничивает количество записываемых байтов, но количество отображаемых байтов ограничено необязательным третьим аргументом.
Наконец, обратите внимание, что адрес пользователя записывается при входе в системный вызов, но используется только при выходе. Это распространенная идиома, которая позволяет системному вызову при необходимости вводить данные с ошибкой --- DTrace не будет делать этого сам и выдаст ошибку во время выполнения, если его попросят отследить нерезидентный адрес.
person
Robert Harris
schedule
10.11.2013