怎么在 lldb 中命中设置的函数断点后自动输出返回值?原本设想的方式是在断点的 command 中加入 finish(thread step-out) 和 po 命令实现,然后在实际执行的时候触发 error: Aborting reading of commands after command #1: 'finish' continued the target.
错误。
finish
其实是thread step-out
的缩写,从 lldb 的帮助文档,可以看到这条指令的作用是
Finish executing the current stack frame and stop after returning
Defaults to current thread unless specified.
在 IDE 上触发断点,我们确实可以执行finish
去到函数返回的地方,然后通过po $x0
输出返回值。但是其实这已经是「另一个断点」了。这意味着,给上一个断点添加的 command 无法在这个断点上执行,所有会出现开篇提到的错误。
模仿finish
的行为——完成当前函数调用并停止在返回点。「完成当前函数调用」这个很简单,直接continue
让程序继续执行就 vans 了。「停止在返回点」这个需要在返回地址设置断点,根据「 bl/ble 指令调用时会将返回地址写到 link regiseter($lr
)中去」这点,可以尝试在触发函数断点 A 时,获取返回地址,再设置一个返回地址的断点 B。
(lldb) br set -n "-[ViewController switchAction:]" -K false
(lldb) br command add
Enter your debugger command(s). Type 'DONE' to end.
> br set -a $lr -o true -G true -C "po $x0"
> continue
> DONE
简单梳理下:第一行设置我们想观察的 breakpoint,注意这里添加了 -K false 的参数
-K
( –skip-prologue )
sKip the prologue if the breakpoint is at the beginning of a function. If not set the
target.skip-prologue setting is used.
使得触发断点的位置在这段子程序的最前面,不要跳过函数的 prologue 部分,因为跳过的话大概率已经把返回地址压入栈了,然后用 link register 装了其他奇奇怪怪的东西,那么定位返回地址的任务会比较复杂。触发断点 A 后执行的br set -a $lr -o true -G true -C "po $x0"
设置断点 B 以及附属指令。其中:
$lr
寄存器的值设置断点;权当抛砖引玉,不做更多的优化和定制,用处没有很大。
— Aug 5, 2020