Интерпретация вывода strace

С strace можно увидеть вызов ioctl для определенного файлового дескриптора и с определенной командой. Третий аргумент - это структура, но strace показывает его как необработанный указатель на память. Пример вывода strace:

open("/dev/node", O_RDWR) = 3
ioctl(3, 0x108, 0x8f0eb18) = 0
close(3)  

Есть ли способ (опции strace или другие инструменты), чтобы увидеть, что представляет собой структура, или, по крайней мере, значение, стоящее за исходным указателем?

Ответ 1

В gdb, если вы остановите его прямо перед вызовом ioctl, вы можете ввести:

(gdb) p *(ioctl_struct *) 0x8f0eb18

Это покажет вам, как содержимое этого расположения памяти сопоставляется с ioctl_struct.

Ответ 2

У меня возникла аналогичная проблема: я хотел проверить syscall на ioctl, сделанный vde_switch (который создает виртуальный сетевой интерфейс TUN/TAP), чтобы узнать, что я делал неправильно в своем коде (который должен был делать то же самое, что и vde_switch, но программно.)

Запустив:

sudo strace vde_switch -tap tap0

Я смог узнать, как Терри Greentail, что сделанный syscall был ioctl(5, TUNSETIFF, 0x7fffa99404e0), и указатель был бы ссылкой на структуру типа struct ifreq. В моем коде у меня было что-то вроде ioctl(tapfd, TUNSETIFF, &ifr_dev).

Сначала я попытался сделать gdb stop в syscall, установив: catch syscall ioctl (у меня был запуск gdb как gdb --args vde_switch -tap tap0), но всякий раз, когда улавливался, gdb не показывал информацию о параметрах ioctl. После того, как я боролся с этим некоторое время, я решил запустить strace внутри gdb, поскольку:

gdb --args strace vde_witch -tap -tap0

Хотя точка останова не работала таким образом, на выходе было показано, какой файловый дескриптор используется:

open("/dev/net/tun", O_RDWR)            = 9
ioctl(9, TUNSETIFF, 0x7fffffffe350)     = 0

Итак, я попробовал еще раз: gdb --args strace vde_witch -tap -tap0 и установить условную точку останова:

b ioctl if $rdi==9

Вызывающее соглашение (я на AMD64) использует RDI для первого параметра, RSI для второго и RDX для третьего (см. System V AMD64 ABI.) Наконец, когда ударила точка останова, мне удалось проверить структуру ifreq:

Breakpoint 6, ioctl () at ../sysdeps/unix/syscall-template.S:81
81      ../sysdeps/unix/syscall-template.S: File or directory not found.

(gdb) p (struct ifreq) *$rdx
$5 = {ifr_ifrn = {ifrn_name = "tap0", '\000' <repete 11 vezes>}, ifr_ifru = {ifru_addr = {sa_family = 4098, sa_data = '\000' <repete 13 vezes>}, ifru_dstaddr = {sa_family = 4098, sa_data = '\000' <repete 13 vezes>}, ifru_broadaddr = {sa_family = 4098, sa_data = '\000' <repete 13 vezes>}, ifru_netmask = {sa_family = 4098, sa_data = '\000' <repete 13 vezes>}, ifru_hwaddr = {sa_family = 4098, sa_data = '\000' <repete 13 vezes>}, ifru_flags = 4098, ifru_ivalue = 4098, ifru_mtu = 4098, ifru_map = {mem_start = 4098, mem_end = 0, base_addr = 0, irq = 0 '\000', dma = 0 '\000', port = 0 '\000'}, ifru_slave = "\002\020", '\000' <repete 13 vezes>, ifru_newname = "\002\020", '\000' <repete 13 vezes>, ifru_data = 0x1002 <Address 0x1002 out of bounds>}}