2.15 GDB断点后处理commands中finish/until/tb带来的问题 https://scz.617.cn/unix/200901071528.txt Q: 我现在拦截recvmsg(),有几个目的: 1) 获取UDP报文的源IP、源PORT 2) 观察接收到的数据 由于recvmsg()被频繁调用,我需要设置条件断点,比如当源IP、源PORT、接收到的 数据满足一定条件时再命中断点。对于recvmsg()来说,这些信息都是函数返回之后 才能获取的,因此我设想了这样一种断点设置方式: -------------------------------------------------------------------------- b recvmsg commands silent set $x=(struct msghdr *)(*(unsigned int *)($esp+8)) finish if ($x->msg_name!=0&&$x->msg_namelen==16) set $y=(struct sockaddr_in *)$x->msg_name if ( ntohl( $y->sin_addr.s_addr )==<...>) else c end else c end end -------------------------------------------------------------------------- 但这个断点不能达到预期效果,commands中finish之后的脚本未被执行,可能是BUG, 也可能是GDB就是这样实现的。将finish换成until *(*(unsigned int *)$esp),情 况依旧。后来我试图将finish换成tb *(*(unsigned int *)$esp),并针对tb设置后 处理commands,但GDB不允许这样做: Can't use the "commands" command among a breakpoint's commands. 用define也无法绕过上述限制。 D: scz 2021-04-22 现在GDB允许在commands中tb并再次使用commands,后面的技巧过时了。 A: qfp 2009-01-07 14:20 用如下办法变通满足原始需求: -------------------------------------------------------------------------- define finish_recvmsg finish if ($x->msg_name!=0&&$x->msg_namelen==16) set $y=(struct sockaddr_in *)$x->msg_name if ( ntohl( $y->sin_addr.s_addr )==<...>) else c end else c end end -------------------------------------------------------------------------- b recvmsg commands silent set $x=(struct msghdr *)(*(unsigned int *)($esp+8)) finish_recvmsg end -------------------------------------------------------------------------- A: emacsen@SMTH 2009-01-07 12:33:14 emacsen建议用hook试试,用Google搜"gdb hook"找到类似资料: -------------------------------------------------------------------------- define hook-echo // 定义echo命令的"前处理" echo [ end define hookpost-echo // 定义echo命令的"后处理" echo ]\n end (gdb) echo Hello World [Hello World] -------------------------------------------------------------------------- 据此测试了hookpost-finish,也能满足原始需求: -------------------------------------------------------------------------- define hookpost-finish if ($x->msg_name!=0&&$x->msg_namelen==16) set $y=(struct sockaddr_in *)$x->msg_name if ( ntohl( $y->sin_addr.s_addr )==<...>) else c end else c end end -------------------------------------------------------------------------- b recvmsg commands silent set $x=(struct msghdr *)(*(unsigned int *)($esp+8)) finish end --------------------------------------------------------------------------