valgrind 无法识别树莓派中的 memcmp 指令

Posted

技术标签:

【中文标题】valgrind 无法识别树莓派中的 memcmp 指令【英文标题】:valgrind unrecognizes memcmp instruction in raspberry Pi 【发布时间】:2013-12-02 16:35:04 【问题描述】:

我正在 Valgrind 中测试我的应用程序,但我不明白为什么它会在此处对无法识别的指令抛出错误:

unsigned char *temp=SearchStartPtr;
unsigned char *NrStartPos=NULL;
unsigned char *Param=(unsigned char*)ParamName; //this is originally *char with "PAR#" inside

if(0==memcmp(temp,Param,4)) 
        
        NrStartPos=temp;
        break;
               

Valgrind 抛出这个并退出我的应用程序。

disInstr(arm): unhandled instruction: 0xF1010200
cond=15(0xF) 27:20=16(0x10) 4:4=0 3:0=0(0x0)
==7679== valgrind: Unrecognised instruction at address 0x4843588.
==7679==    at 0x4843588: ??? (in /usr/lib/arm-linux-gnueabihf/libcofi_rpi.so)
Your program just tried to execute an instruction that Valgrind
==7679== did not recognise.  There are two possible reasons for this.
==7679== 1. Your program has a bug and erroneously jumped to a non-code
==7679==    location.  If you are running Memcheck and you just saw a
==7679==    warning about a bad jump, it's probably your program's fault.
==7679== 2. The instruction is legitimate but Valgrind doesn't handle it,
==7679==    i.e. it's Valgrind's fault.  If you think this is the case or
==7679==    you are not sure, please let us know and we'll try to fix it.
==7679== Either way, Valgrind will now raise a SIGILL signal which will
==7679== probably kill your program.
==7679== 
==7679== Process terminating with default action of signal 4 (SIGILL)
==7679==  Illegal opcode at address 0x4843588
==7679==    at 0x4843588: ??? (in /usr/lib/arm-linux-gnueabihf/libcofi_rpi.so)

通常代码工作正常(但我不知道它是否没有一些内存泄漏)。

我确定问题出在 memcmp 指令上,但我不明白哪里出了问题。

在代码的前面,我有另一条指令做了同样的事情,但我可以在检查之前将其注释掉:

  memcmp(ReadPtr,ToWritePtr,sizeof(struct termios)

【问题讨论】:

如果您仔细阅读该消息,它会说它发现了一条非法指令(如汇编指令)。 memcmp 是函数而不是指令。此外,Valgrind 表示在 /usr/lib/arm-linux-gnueabihf/libcofi_rpi.so 中发现了这条非法指令,这几乎不是你创建的文件,我会冒险。 【参考方案1】:

这似乎是 Pi 上带有 Valgrind 的 known issue。

总结 Raspbian 中的 memcmp 库存版本使用当前 Valgrind 根本无法处理的汇编指令。不幸的是,这个特定的指令显然很难 Valgrind 支持,所以它不太可能发生 - 在 Valgrind 跟踪器中提出了 bug,但已作为 WONTFIX 关闭。

我认为解决此问题的唯一方法是替换您自己的 memcmp 版本,并希望它不会编译为包含有问题的指令。

【讨论】:

优秀的答案。作为解决此问题的可能方法,请尝试使用 strcmp [如果您查看发布的错误链接下的 valgrind 跟踪,用 strcmp 替换似乎没问题] /usr/lib/arm-linux-gnueabihf/libcofi_rpi.so 中的函数是用汇编编码的,C 版本不太可能编译成 SETEND 汇编指令 - 所以可以创建一个它的 C 版本并使用 LD_PRELOAD 来覆盖麻烦的 memcmp 好吧,比这更容易。 /usr/lib/arm-linux-gnueabihf/libcofi_rpi.so 本身是预加载的。因此,只需在树莓上编辑 /etc/ld.so.preload 并注释掉该行,这应该会为您提供 glibc 中的 memcmp 奈杰尔,您应该在答案中添加 nos last comment,因为它提供了一个非常简单的解决方法 我通过简单地删除 raspi-copies-and-fills 包解决了这个问题。【参考方案2】:

我和你有同样的问题。

我检查了 arm-mem 存储库,它似乎被 libc 中的 memcmp 替换了。所以我使用 valgrind 的解决方案是 remove arm-mem 暂时然后使用 libc 中的原始实现。

试试这个:

$ sudo mv /usr/lib/arm-linux-gnueabihf/libarmmem.so /usr/lib/arm-linux-gnueabihf/libarmmem.so.orig
$ sudo ln -s  /lib/arm-linux-gnueabihf/libc.so.6  /usr/lib/arm-linux-gnueabihf/libarmmem.so
$ sudo ldconfig

现在尝试重新运行 valgrind...

稍后,将其移回:

$ sudo rm /usr/lib/arm-linux-gnueabihf/libarmmem.so
$ sudo mv /usr/lib/arm-linux-gnueabihf/libarmmem.so.orig /usr/lib/arm-linux-gnueabihf/libarmmem.so
$ sudo ldconfig

【讨论】:

【参考方案3】:

您需要修补 libarmmem.so 才能仅在 little-endian-mode 下运行。为了以@nigelharper 的回答为基础,Valgrind 不支持反向操作,因此会在 SETEND 指令上陷入陷阱。但是,memcmp() 可以在没有 SETEND 的情况下实现,如下所示:https://github.com/rsaxvc/arm-mem/commit/b836e465c2fd0bb006b428abce99e31607072834

@user167752 也是正确的,禁用 libarmmem 也可以,但这会改变所有的 libarmmem,而不仅仅是 memcmp()

【讨论】:

以上是关于valgrind 无法识别树莓派中的 memcmp 指令的主要内容,如果未能解决你的问题,请参考以下文章

在树莓派中为 python 3 安装 mysql 连接器

树莓派中QT实现PWM

语音识别后控制

树莓派中GPIO针角定义图

树莓派中编译OpenCV3.4.1和OpenCvSharp

在树莓派中开启激动人心的 Perl 之旅