我正在调试一个仅在我的程序的 PPC64 端口中出现的问题。
我有一个测试用例,其中 C 库qsort
被赋予一个 libffi 生成的闭包作为字符串比较回调。字符串被正确地传递给回调,返回值被精确地存储到 libffi 传递给闭包函数的返回值缓冲区中。
但是,该数组未正确排序qsort
。此外,Valgrind 报告 C 库 qsort 代码正在访问未初始化的内存,并--track-orgins=yes
显示该内存是由 Libffi 堆栈分配的。我强烈怀疑这是返回值,因此由于垃圾比较,排序不正确。
即 Libffi 为返回值分配了缓冲区,并将该值传播给回调调用者;但是我的闭包调度函数被赋予了错误的指针,因此没有将返回值放在正确的位置。
由于某些奇怪的原因,Valgrind 不报告 未初始化内存的地址,只报告代码中发生使用的位置和分配的位置。
我只是想将该位置的地址与传递给闭包函数的指针进行比较:它们甚至是远程关闭的吗?
有没有办法从 Valgrind 中获取这些信息?
更新:我正在使用没有 root 权限的 GCC Compile Farm 机器;安装的 libffi 没有调试信息。它是 3.0.13 版本。
libffi
但是,我刚刚构建的 git head重现了该问题。
我已经确认它是未初始化的返回值区域。
我在闭包调度汇编代码中添加了一条指令,用于在闭包调度堆栈帧的部分ffi_closure_LINUX64
底部初始化一个双字大小的区域。RETVAL
这使得 Valgrind 错误消失了;但当然返回值是垃圾。它还证实了一个基本的理智:调用闭包调度助手之前的代码和之后的代码引用相同的返回值区域。(堆栈指针没有意外移动,并且帧引用是正确的。)用户代码最终获得的任何地址都没有指向该返回值。
接下来,我将返回区域的初始化向下移动到名为 的 C 函数ffi_closure_helper_LINUX64
中,靠近函数的入口。这也仍然使未初始化的错误消失,确认助手正在通过%r6
(参数 4)获取正确的返回值区域地址。