Mam podobny problem: chciałem sprawdzić syscall pod numerem ioctl
wykonanym przez vde_switch
(który tworzy wirtualny interfejs sieciowy TUN/TAP), aby wiedzieć, co robiłem źle w moim kodzie (który miał zrobić to samo, co vde_switch
, ale programowo)
Uruchamiając.
sudo strace vde_switch -tap tap0
udało mi się dowiedzieć, jak Terry Greentail, że syscall dokonywana była ioctl(5, TUNSETIFF, 0x7fffa99404e0)
i wskaźnik będzie odwołanie do struktury typu struct ifreq
. W moim kodzie miałem coś w rodzaju ioctl(tapfd, TUNSETIFF, &ifr_dev)
.
Początkowo starałem się zrobić przystanek gdb na syscall, ustawienie: catch syscall ioctl
(miałem uruchomić gdb jako gdb --args vde_switch -tap tap0
), ale ilekroć połów został uderzony, gdb wykazało żadnych informacji na temat parametrów ioctl
. Po zmaga się z tym przez chwilę, postanowiłem uruchomić strace wewnątrz gdb, jak:
gdb --args strace vde_witch -tap -tap0
Choć nie przerwania pracował w ten sposób wyjście pokazał których deskryptor był używany:
open("/dev/net/tun", O_RDWR) = 9
ioctl(9, TUNSETIFF, 0x7fffffffe350) = 0
Spróbowałem więc innym razem z: gdb --args strace vde_witch -tap -tap0
i ustawić punkt przerwania warunkowego:
b ioctl if $rdi==9
konwencja wywołujący (jestem na AMD64) wykorzystuje RDI
f lub pierwszy parametr, RSI
za drugim i RDX
za trzeci (patrz System V AMD64 ABI). Wreszcie, kiedy punkt przerwania został trafiony, udało mi się zbadać strukturę 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>}}
Czy to daje adres instrukcja? Jeśli tak, to w GDB jest naprawdę proste dodawanie punktu przerwania, a następnie spójrz na pamięć ... Jak określić rzeczywistą strukturę, której nie jestem pewien. – Matt
Mam na myśli to, że gdybym napisał to w moim programie, wyglądałoby to tak: 'ioctl (dev_node, IOCTL_CODE i &octl_struct)', gdzie trzeci argument jest strukturą typu Ioctl_Buf_Struct. Kiedy strace jest używane do programu binarnego, jak widzimy w powyższym przykładzie, chciałbym wiedzieć, co kryje się pod adresem 0x8f0eb18: jaka jest struktura, która jest tam wysyłana, lub przynajmniej jaka jest jego wartość. Czy gdb może tutaj pomóc? –
well ... Jeśli uruchomisz program, zatrzymaj się tuż przed tym poleceniem, wtedy możesz znaleźć wartości przez dereferencję wskaźnika. Użyj strace, aby znaleźć wszystkie wywołania malloc, dopóki nie znajdziesz tego, który zwróci ten wskaźnik. To powie ci rozmiar struktury.Następnie możesz spojrzeć na pamięć o znanym rozmiarze i odtworzyć strukturę w jej binarnej postaci. Możesz nigdy nie wiedzieć * czym * jest struktura, ale możesz znaleźć wartość. – Matt