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

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

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

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


person Terry Greentail    schedule 21.06.2012    source источник
comment
Он дает вам адрес инструкции? Если это так, то в GDB действительно просто добавить точку останова, а затем посмотреть на память... Как бы вы определили фактическую структуру, я не уверен.   -  person Matt    schedule 21.06.2012
comment
Я имею в виду, что если бы я написал это в своей программе, то это выглядело бы так: ioctl( dev_node, IOCTL_CODE, &ioctl_struct ), где третий аргумент — это структура типа Ioctl_Buf_Struct. Когда strace используется для бинарной программы, как мы видим в приведенном выше примере, мне было бы любопытно узнать, что стоит за адресом 0x8f0eb18: какая структура отправляется туда или, по крайней мере, каково ее значение. Может ли gdb помочь здесь?   -  person Terry Greentail    schedule 21.06.2012
comment
хорошо... Если вы запустите программу, остановитесь, если только перед этой командой, тогда вы можете найти значения, разыменовав указатель. Используйте strace, чтобы найти все вызовы malloc, пока не найдете тот, который возвращает этот указатель. Это скажет вам размер структуры. Затем вы можете просмотреть память с известным размером и таким образом воспроизвести структуру в ее двоичной форме. Возможно, вы никогда не узнаете, что такое структура, но вы можете найти ее значение.   -  person Matt    schedule 21.06.2012


Ответы (2)


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

(gdb) p *(ioctl_struct *) 0x8f0eb18

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

person koral    schedule 21.06.2012

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

Запустив:

sudo strace vde_switch -tap tap0

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

Первоначально я пытался остановить gdb при системном вызове, установив: 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>}}
person Tarc    schedule 30.07.2013