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

问题描述 投票:0回答:3

我正在 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)
c valgrind raspberry-pi raspbian
3个回答
16
投票

看来这是 Pi 上 Valgrind 的一个已知问题

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

关于我能看到解决这个问题的唯一方法是替换你自己的 memcmp 版本,并希望它不会编译下来包含有问题的指令。


3
投票

我和你有同样的问题

我检查了 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

1
投票

libarmmem.so 的 memcmp() 使用多字节加载指令,同时使用称为 SWAR 的技术搜索缓冲区中的差异。但是,它使用'setend be'指令将处理器置于大端模式,以便一旦寄存器不匹配更容易定位差异,然后在找到差异后,'setend le'恢复之前的字节序模式返回。这在 ARM11 上运行良好,但是......

Valgrind 没有为 Arm 处理器实现 setend 仿真(可能是因为它会使本机端访问的正常情况变慢),因此它触发了“无法识别的指令”。

SWAR-vectorized memcmp() 可以在没有 SETEND 的情况下实现,我也是这样做的,并且合并到上游。额外的 rev 指令对性能的影响在相关内核的大型足够比较中大致可以忽略不计。

@user167752 也是正确的,禁用 libarmmem 也可以,但这会改变所有 libarmmem,而不仅仅是 memcmp()。为此,请卸载 raspi-copies-and-fills 包。

© www.soinside.com 2019 - 2024. All rights reserved.