valgrind在Raspberry Pi上返回一条未处理的指令

时间:2013-07-02 16:21:44

标签: c++ valgrind raspberry-pi

我一直在尝试使用valgrind在我的树莓派Pi(模型b)上调试一个分段错误,运行Debian GNU / Linux7.0(wheezy)。每次我在编译的C ++程序上运行valgrind时,我会得到如下内容:

disInstr(arm): unhandled instruction: 0xF1010200
    cond=15(0xF) 27:20=16(0x10) 4:4=0 3:0=0(0x0)
valgrind: Unrecognized instruction at address 0x4843638.
at 0x4843638: ??? (in /usr/lib/arm-linux-gnueabihf/libconfi_rpi.so)

然后是正常的valgrind东西,导致SIGILL并终止我的程序。起初我假设我的程序中有一些内存泄漏导致它执行一条非指令内存作为指令,但后来我运行了以下的hello world代码,得到了相同的结果。

#include <iostream>
using namespace std;

int main() {
cout<<"Hello World"<<endl;

return 0;
}

不可能有内存泄漏/段错误,为什么它会给我这个错误? 我对valgrind很新,但我用最基本的valgrind ./a.out运行它。

4 个答案:

答案 0 :(得分:7)

从您的代码(一个简单的问候世界),它抱怨Unrecognized instruction at address 0x4843638。我的猜测是:

  • 由于valgrind需要拦截你的malloc系统调用函数(c标准库)。这允许valgrind检查您分配/释放的资源数量(用于内存泄漏检测)(例如)。如果valgrind无法识别您的标准库环境(或处理器的指令语言),它可能不会表现出预期,这可能是导致崩溃的原因。您应该检查valgrind版本并下载适合您平台的版本。

编辑:

http://valgrind.org/docs/manual/faq.html

  

3.3。我的程序死了,一路打印这样的消息:

     

vex x86-&gt; IR:未处理的指令字节:0x66 0xF 0x2E 0x5

     

一种可能性是您的程序有错误并且错误地跳转   到非代码地址,在这种情况下,您将获得SIGILL信号。   Memcheck可能会在此之前发出警告,但可能会发出警告   如果跳跃发生在可寻址的记忆中,那就不行了。

     

另一种可能性是Valgrind不处理该指令。   如果您使用较旧的Valgrind,则较新的版本可能会处理   但是,所有指令集都有一些模糊,很少   使用说明。此外,在amd64上有一个几乎无限的数字   冗余指令前缀的组合,其中许多   没有文档但被CPU接受。所以Valgrind仍然会有   不时解码失败。如果发生这种情况,请提交一份   错误报告。

EDIT2:

来自维基百科,Raspberry Pi CPU:

  • 700 MHz ARM1176JZF-S内核(ARM11系列,ARMv6指令集)[3]
  

2.11。限制

     

在ARM上,基本上支持整个ARMv7-A指令集,   在ARM和Thumb模式下。 ThumbEE和Jazelle不受支持。   NEON,VFPv3和 ARMv6媒体支持相当完整

你的程序/库恰好有一些不支持的指令。

答案 1 :(得分:5)

在Raspberry Pi 3上安装了Raspian的NOOBS,通过在终端窗口中执行以下操作来实现ayke的答案:

  1. cd / etc
  2. sudo nano ld.so.preload
  3. 删除包含“libarmmem.so”的行(/usr/lib/arm-linux-gnueabihf/libarmmem.so)<< li>
  4. 保存并退出ld.so.preload
  5. 运行valgrind
  6. 在valgrind测试完成后将行放回ld.so.preload
  7. 预加载的“libarmmem.so”包含“memcmp”函数中的“setend”指令,该指令导致未处理的指令错误。标准库(在未加载预加载的“libarmmem.so”库时使用)不包括“memcmp”中的“setend”指令。

答案 2 :(得分:4)

TL; DR:如果您使用的是Raspbian,请删除包raspi-copies-and-fills。它也可以用于其他一些Linux变体,如NOOBS。

正如Phong已经指出的那样,Valgrind不支持此指令。 有bug report解释了这个问题:

  

这种情况不断出现,例如最近的bug 366464。   也许我应该解释为什么不支持这一点。这是因为我们   没有可行的方法来做到这一点。 Valgrind的JIT仪器代码   首次访问时的块,以及当前的字节序   块被“烘焙”到仪器中。所以有两个   选项:

     

(1)当执行SETEND指令时,扔掉所有JITted   码       Valgrind已创建,JIT新代码块具有新的字节顺序。

     

(2)JIT代码以与字节无关的方式阻塞并具有运行时测试   对于每个内存访问,决定是否调用大或小   endian instrumentation helper function。

     

(1)对于不使用SETEND的代码,性能开销为零   但对于代码而言,这是一个巨大的(完全不可行的)命中。

     

(2)使endian更改自由,但会惩罚所有内存流量   无论是否实际使用SETEND。

     

所以我发现其中任何一个都不可接受。我想不出任何   其他实现方式。

换句话说,很难在valgrind中实现这个指令。 总结线程:这个指令最常见的原因是Raspberry Pi提供的一些更快的内存管理功能(memcmp,memset等)。

我通过(暂时)从我的Raspbian安装中删除raspi-copies-and-fills来解决它。

答案 3 :(得分:3)

Valgrind显然在Raspberry Pi上存在问题:

https://web.archive.org/web/20131003042418/http://www.raspberrypisoft.com/tag/valgrind/

我建议使用其他工具来查找seg错误。