Я столкнулся с аналогичной проблемой: хотел проверить системный столбец на 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>}}
это даст вам адрес инструкции ли? Если это так, то в GDB очень просто добавить точку останова, а затем посмотреть на память ... Как бы вы определили фактическую структуру, я не настолько уверен. – Matt
Я имею в виду, что если бы я написал его в своей программе, это выглядело бы так: 'ioctl (dev_node, IOCTL_CODE, & ioctl_struct)', где третий аргумент представляет собой структуру типа Ioctl_Buf_Struct. Когда strace используется для двоичной программы, как мы видим в приведенном выше примере, мне было бы интересно узнать, что находится за адресом 0x8f0eb18: какова структура, которая отправляется туда, или, по крайней мере, то, что является ее значением. Может ли gdb помочь здесь? –
... Если вы запустите программу, остановитесь, если перед этой командой вы можете найти значения, разыменовывая указатель. Используйте strace, чтобы найти все вызовы malloc, пока не найдете тот, который возвращает этот указатель. Это скажет вам размер структуры.Затем вы можете посмотреть на память с известным размером и размножить структуру в бинарной форме. Вы можете никогда не знать, что такое * структура, но вы можете найти значение. – Matt