如何解决RISC管道对设置断点的影响?
在 RISC Pipelining 指令中坚持 5 个步骤。
我有一个关于流水线是否会影响设置断点的问题。
示例:
假设下面的二进制文件正在运行并且 $pc
在 line 1
line1: lwz r11 8(r31) <= PC @ here
line2: lwz r0,0(r31)
line3: cmpwi cr7,r10,0
line4: lwz r9,4(r31)
line5: stw r11,0xA0(r1)
管道状态(我的猜测):
据我所知,PPC 指令有 5 种状态:获取、解码、执行、内存访问、回写
在这一刻,我猜流水线会像下面这样。正确吗?
line1: lwz r11 8(r31) <= execution (because PC is at here)
line2: lwz r0,0(r31) <= decode
line3: cmpwi cr7,0 <= fetch
line4: lwz r9,0xA0(r1)
问题
- 我写的状态正确吗?
- 此时,是否不允许调试器在运行时更改
line 3
中的指令?
(例如在line 3
处设置断点?)
解决方法
在真正的微处理器上,这取决于您是否...
-
...使用 JTAG 调试器
(这意味着某些外部硬件在断点处停止 CPU 到达)在这种情况下,当 CPU 在断点处停止时,如果更改行“2”或“3”会发生什么取决于 CPU。可能有从断点处继续后再次读取内存的 CPU 和不这样做的其他 CPU。
我不知道 PowerPC 微控制器(如 MPC57xx)的行为。
但是,我猜想在大多数微控制器中,硬件的设计方式(有意)使流水线在断点的情况下无法“正常”工作:到达断点后,“第 1 行”到“第 3 行” " 从内存中重新读取。
-
... 或者如果您正在执行片上调试
(这意味着调试软件与被调试软件在同一个 CPU 上运行)在这种情况下,进入断点时会出现一些异常。
对于 PowerPC,异常返回使用
rfdi
或(对于较旧的控制器)rfci
指令。这意味着调试器使用
rfdi
指令继续被调试的程序。rfdi
、rfi
、rfci
是跳转/分支指令。无论如何,在跳转/分支之后,CPU 必须重新读取管道。这意味着CPU肯定会再次从内存中读取“第1行”,因此您甚至可以在断点处修改“第1行”。
如果您想查看流经 POWER 处理器管道的指令的多种状态,您可以进行指令跟踪,使用 Power Performance Simulator 来模拟流经各个管道的指令(通常有很多) ,并使用与 Power Performance Simulator 关联的查看器之一逐周期查看状态更改。我写了一篇文章 (https://developer.ibm.com/technologies/linux/tutorials/l-porting-tuning-tools/),其中简要介绍了如何执行此操作。
话虽如此,像 gdb 这样的用户级调试器将指令视为粗略的原子。一条指令执行前的状态就好像之前的所有指令都完成了,而当前指令没有改变任何状态。
,流水线阶段不是架构性的(例如,高性能 PowerPC CPU 可以拥有更长的流水线,而无需更改任何软件可见的内容)。这不会是单步执行的一部分,除非您使用软件模拟器来查看指令通过模拟 CPU。
如果您在设置另一个断点或单步执行时在断点处停止,则正在调试的代码中的任何指令都不会在管道中运行。 CPU 将处于休眠状态或运行调试器的代码。
此外,PowerPC 没有一致的指令缓存,因此运行 stw
指令的自修改代码在其自身之后修改了几条指令不一定会导致该新指令被获取,即使它是超过 5 条指令之后。为了可靠地发生这种情况,您需要一堆指令,例如 dcbf
和 msync
将 D-cache 刷新到更高级别,然后 icbi
到使 I-cache 的那一行无效,然后 msync
和 isync
以确保在指令获取之前发生。 https://www.nxp.com/docs/en/application-note/AN3441.pdf 例如记录了您应该在第 2.2 节指令缓存一致性中做什么,至少对于 PowerPC 的特定实现。 (我认为飞思卡尔的 PowerQUICC™ III 是一款 PowerPC;这个文档是谷歌找到的。)
奇怪的是 GNU C __builtin___clear_cache(start,end)
对 GCC 没有任何作用。 https://godbolt.org/z/nbre7Y 可能是因为推荐的过程涉及将页面标记为不可执行,如果没有系统调用,您无法从用户空间执行此操作?
调试器本身在进程未运行时修改其内存会更容易;操作系统已经必须确保页面加载到内存中或使用 ptrace
修改的页面可以安全地执行代码。所以它可以将大部分刷新留给操作系统。
当内核在被调试的进程中返回用户空间时,如果第一条或任何后面的指令是调试陷阱/软件断点指令,它就会陷入陷阱。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。