通过控制转移,我的意思是,在tracee执行一个函数并返回之后,生成哪个信号,以便GDB可以等待*()并再次获取控制权?虽然很多人声称......不是SIGTRAP。
答案 0 :(得分:2)
在tracee执行一个函数并返回后,生成哪个信号,以便GDB可以等待*()并再次获取控制权?
当一个“有趣”事件发生时,tracee被停止,控件被转移回GDB,仅。
有趣的事件是:
SIGSEGV
或SIGFPE
),SIGKILL
),[可能还有其他“有趣”事件,但我现在想不出任何其他事情。]
现在,对“GDB使用的信号......”的技术上正确答案是:完全没有。除非上述事件之一发生,否则控制不会转移。
也许你的问题是:在执行类似finish
命令(从当前函数中退出)之后,控制如何回到GDB?
答案是:GDB在使我们进入当前函数的CALL
指令之后立即在指令上设置临时断点。
最后,是什么原因导致内核停止跟踪并使GDB中的waitpid
在执行断点指令时返回?
在x86
上,GDB使用INT3
(操作码0xCC
)指令设置断点(使用调试寄存器有另一种机制,但它仅限于4个同时断点,并且通常保留用于硬件观察点)。当tracee执行INT3
指令时,SIGTRAP
确实是内核生成的信号(即您找到的其他答案都是正确的)。
如果不知道是什么导致你相信不是 SIGTRAP
,那么很难猜测你是如何说服自己不是。
<强>更新强>
我尝试手动向tracee发送SIGTRAP信号,试图导致GDB的虚假唤醒,但是失败了。
以什么方式失败?
我希望您观察到的是GDB以Program received signal SIGTRAP ...
停止。那是因为GDB 知道它放置断点的位置。
当GDB收到SIGTRAP
和时,tracee指令指针与其中一个断点匹配,然后GDB“知道”这是已触发的断点,并相应地采取行动。
但是当GDB收到SIGTRAP
且跟踪IP
没有匹配任何断点时,GDB会将其视为任何其他信号:打印消息并等待你告诉它接下来要做什么。
“GDB设置了一个临时断点......这意味着GDB必须修改tracee的代码区域,这可能是只读的。那么,GDB如何应对呢?
你是对的:GDB需要修改(通常是不可写的).text
部分以使用INT3
方法插入任何断点。幸运的是,这是内核通过ptrace(POKE_TEXT, ...)
授予它的“超级大国”之一。
P.S。这是一个有趣的练习,可以使校验和自己函数之一的代码字节的程序变白。然后,您可以在“要校验和”功能上放置断点之前和之后执行校验和,并观察断点存在时校验和是否不同。
P.P.S。如果您对GDB正在做的事情感到好奇,设置maintenance debug inferior
将提供很多线索。