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

strace pwd:

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

ltrace pwd:

getcwd(NULL, 0)                                     = "/root"

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

ОБНОВЛЕНИЕ

похоже, что strace/ltrace используют системный вызов ptrace, но почему они получают разную информацию?


person Je Rog    schedule 23.06.2011    source источник


Ответы (3)


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

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

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

person kosklain    schedule 10.11.2012

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 (например, libc-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"
person Juan Cespedes    schedule 13.08.2014

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

long getcwd(char *buf, unsigned long size);
person zvrba    schedule 23.06.2011
comment
@zvrba, как ты думаешь, почему это отвечает на мой вопрос? - person Je Rog; 23.06.2011
comment
Потому что на странице руководства также объясняется, что передача NULL является расширением Linux. И это также может быть ошибка в ltrace. Невозможно узнать, не видя кода. - person zvrba; 23.06.2011
comment
ptrace() абсолютно ничего не знает о параметрах. Аргументы функции/системного вызова и то, как их следует интерпретировать, жестко закодированы в strace и ltrace. - person zvrba; 23.06.2011
comment
@zvrba, какой самый важный элемент управления кодом, который делает strace / ltrace другой функцией? - person Je Rog; 27.06.2011
comment
Я не понимаю, что вы там спрашиваете. Какая функция? strace подключается к механизму системных вызовов, ltrace модифицирует точки входа функций динамической библиотеки. - person zvrba; 27.06.2011
comment
@zvrba, не могли бы вы вкратце объяснить, как это делается с ptrace, скажем, hooks into the system call mechanism и modifies entry points of dynamic library functions? - person Je Rog; 28.06.2011
comment
Это невозможно объяснить кратко. Прочтите справочную страницу ptrace, документацию по ELF, документацию по Linux ABI и исходный код для strace и ltrace. - person zvrba; 29.06.2011