2012-06-21 2 views
11

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

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

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

+0

это даст вам адрес инструкции ли? Если это так, то в GDB очень просто добавить точку останова, а затем посмотреть на память ... Как бы вы определили фактическую структуру, я не настолько уверен. – Matt

+0

Я имею в виду, что если бы я написал его в своей программе, это выглядело бы так: 'ioctl (dev_node, IOCTL_CODE, & ioctl_struct)', где третий аргумент представляет собой структуру типа Ioctl_Buf_Struct. Когда strace используется для двоичной программы, как мы видим в приведенном выше примере, мне было бы интересно узнать, что находится за адресом 0x8f0eb18: какова структура, которая отправляется туда, или, по крайней мере, то, что является ее значением. Может ли gdb помочь здесь? –

+0

... Если вы запустите программу, остановитесь, если перед этой командой вы можете найти значения, разыменовывая указатель. Используйте strace, чтобы найти все вызовы malloc, пока не найдете тот, который возвращает этот указатель. Это скажет вам размер структуры.Затем вы можете посмотреть на память с известным размером и размножить структуру в бинарной форме. Вы можете никогда не знать, что такое * структура, но вы можете найти значение. – Matt

ответ

2

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

(gdb) p *(ioctl_struct *) 0x8f0eb18 

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

1

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

Выполнив:.

sudo strace vde_switch -tap tap0 

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

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

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 для F Параметр рвый, 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>}} 
Смежные вопросы