strace/ltrace выводит противоречивую информацию

strace pwd:

getcwd("/root"..., 4096)                = 6

ltrace pwd:

getcwd(NULL, 0)                                     = "/root"

Почему 1-й параметр NULL в ltrace?

ОБНОВИТЬ

кажется, strace/ltrace оба использует ptrace syscall, но почему они получают различную информацию?

3 ответа

Хорошо, они оба используют ptrace, а также они получают различную информацию. Это потому что они используют ptrace по-другому.

Если вы заглянете на справочную страницу ptrace, то увидите, что существует несколько значений 'request', которые определяют поведение ptrace.

Конкретнее, если вы используете ptrace предварительно установить опцию PTRACE_O_TRACESYSGOOD у вас есть способ различить ловушки, ведущие к системным вызовам, и ловушки, не ведущие к системным вызовам.

ltrace показывает вызов библиотеки. В этом случае он показывает функцию из libc что исходный код вызывает.

Если ты видишь pwdВы увидите исходный код (coreutils-8.13, файл lib/xgetcwd.c):

char *cwd = getcwd (NULL, 0);

Так, ltraceвывод правильный: pwd исполняет getcwd(NULL, 0), Согласно справочной странице по Linux getcwd(3):

getcwd () распределяет буфер динамически, используя malloc(3), если buf равен NULL.

Тем не менее, системный вызов getcwd(2) всегда нужен первый аргумент, отличный от NULL, чтобы скопировать туда путь. Вы можете увидеть, как это делается в исходном коде libc (eglibc-3.13, файл sysdeps/unix/sysv/linux/getcwd.c).

Вызов библиотеки getcwd(NULL, 0) выполняет системный вызов getcwd(path, alloc_size), где path является результатом предыдущего malloc(), и alloc_size размер страницы (4096).

Чтобы подтвердить это, если вы запустите ltrace -S pwd вы увидите как библиотечные вызовы, так и системные вызовы: вы увидите что-то вроде:

getcwd(NULL, 0 <unfinished ...>
SYS_getcwd("/root", 4096)                        = 6
<... getcwd resumed> )                           = "/root"

Потому что системный вызов и вызов библиотеки разные. Прочтите man-страницу для функции getcwd, и вы увидите, что она имеет следующий прототип:

long getcwd(char *buf, unsigned long size);
Другие вопросы по тегам