gdb如何在共享库函数中设置软件断点?

Mic*_*ael 6 debugging gdb breakpoints internals shared-libraries

我知道可执行文件中的软件断点可以通过用另一个替换所需位置的某些汇编指令来工作,这会导致中断.因此,调试器可以在此处完全停止执行,并将此指令替换为原始指令,并询问用户下一步操作或调用某些命令等.

但是这样的可执行文件的代码不被其他程序使用,并且在内存中只有一个副本.软件断点如何与共享库一起使用?例如,如果我在C库的某个内部函数中设置一个软件断点,它的工作原理(据我所知它只有一个副本用于所有应用程序,所以我们不能只替换它中的一些指令)?是否有为此目的的"软件断点"技术?

Iwi*_*ist 8

适用于Linux的答案是Linux内核实现COW(写入时复制):如果一个共享库的代码被写入,内核使得共享一个私有的副本第一,重新映射内部虚拟内存为刚进程到副本,并允许应用程序继续.这对用户态应用程序完全不可见,完全在内核中完成.

因此,在第一次将软件断点放入共享库之前,其代码确实是共享的 ; 但事后,不是.此后,该过程使用脏的私人副本进行操作.

这个内核魔术允许调试器不会导致其他所有应用程序突然停止.

但是,在VxWorks等操作系统上,这是不可能的.从个人的经验,当我实现了VxWorks的一个GDB远程调试服务器,我不得不从以往单步内禁止我的用户semTake()semGive()(操作系统信号函数),因为)GDB使用软件断点在源代码级的单步骤实现和b)VxWorks使用信号量来保护其断点列表...

令人不快的后果是一个中断风暴,其中一个断点会引起一个中断,并且在这个中断中会有另一个中断,另一个和另一个在一个不可避免的链中甚至阻止Ctrl-Z.唯一的出路是关闭机器电源.