我遇到了类似的问题:想检查由vde_switch(创建 TUN/TAP 虚拟网络接口)对ioctl 的系统调用,以便了解我在代码中做错了什么(它必须与vde_switch 做同样的事情,但以编程方式。)
通过运行:
sudo strace vde_switch -tap tap0
作为 Terry Greentail,我能够知道正在进行的系统调用是 ioctl(5, TUNSETIFF, 0x7fffa99404e0),并且指针将是对 struct ifreq 类型结构的引用。在我的代码中,我有类似 ioctl(tapfd, TUNSETIFF, &ifr_dev) 的内容。
最初我试图让 gdb 在系统调用上停止,设置为:catch syscall ioctl(我曾以 gdb --args vde_switch -tap tap0 运行 gdb),但每当遇到问题时,gdb 都不会显示有关 ioctl 参数的信息。在为此苦苦挣扎了一段时间后,我决定在 gdb 中运行 strace,如下所示:
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>}}