了解并排除 SIGILL

问题描述

我为基于 armv7 的目标构建了一个用于 erlang (gitlab.com/Vagabond1/erlang-rocksdb@8708fe8) 的rocksdb 副本。这是一个 iMX6 SoloX 处理器,这里是 cpuinfo:

processor       : 0
model name      : ARMv7 Processor rev 10 (v7l)
BogoMIPS        : 7.54
Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
cpu implementer : 0x41
cpu architecture: 7
cpu variant     : 0x2
cpu part        : 0xc09
cpu revision    : 10

Hardware        : Freescale i.MX6 SoloX (Device Tree)
Revision        : 0500

我有一个加载编译后的 liberocksdb.so 的程序,但它因 SIGILL 崩溃,这是回溯:

#0  0xb1b2a7b0 in std::__detail::_Mod_range_hashing::operator()(unsigned int,unsigned int) const () from /opt/miner/lib/rocksdb-1.5.0/priv/liberocksdb.so
#1  0xb1b79b48 in std::__detail::_Hash_code_base<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::pair<std::__cxx11::basic_string<char,std::allocator<char> > const,rocksdb::OptionsSanityCheckLevel>,std::__detail::_Select1st,std::hash<std::__cxx11::basic_string<char,std::allocator<char> > >,std::__detail::_Mod_range_hashing,std::__detail::_Default_ranged_hash,true>::_M_bucket_index(std::__cxx11::basic_string<char,std::allocator<char> > const&,unsigned int,unsigned int) const () from /opt/miner/lib/rocksdb-1.5.0/priv/liberocksdb.so
#2  0xb1b751d4 in std::_Hashtable<std::__cxx11::basic_string<char,std::allocator<std::pair<std::__cxx11::basic_string<char,rocksdb::OptionsSanityCheckLevel> >,std::equal_to<std::__cxx11::basic_string<char,std::__detail::_Prime_rehash_policy,std::__detail::_Hashtable_traits<true,false,true> >::_M_bucket_index(std::__cxx11::basic_string<char,unsigned int) const ()
   from /opt/miner/lib/rocksdb-1.5.0/priv/liberocksdb.so
#3  0xb1b6e01c in std::pair<std::__detail::_Node_iterator<std::pair<std::__cxx11::basic_string<char,true>,bool> std::_Hashtable<std::__cxx11::basic_string<char,true> >::_M_insert<std::pair<std::__cxx11::basic_string<char,rocksdb::OptionsSanityCheckLevel> const&,std::__detail::_AllocNode<std::allocator<std::__detail::_Hash_node<std::pair<std::__cxx11::basic_string<char,true> > > >(std::pair<std::__cxx11::basic_string<char,true> > > const&,std::integral_constant<bool,true>) () from /opt/miner/lib/rocksdb-1.5.0/priv/liberocksdb.so
#4  0xb1b63edc in std::__detail::_Insert_base<std::__cxx11::basic_string<char,true> >::insert(std::pair<std::__cxx11::basic_string<char,rocksdb::OptionsSanityCheckLevel> const&) ()
   from /opt/miner/lib/rocksdb-1.5.0/priv/liberocksdb.so
#5  0xb1b568b8 in std::_Hashtable<std::__cxx11::basic_string<char,true> >::_Hashtable<std::pair<std::__cxx11::basic_string<char,rocksdb::OptionsSanityCheckLevel> const*>(std::pair<std::__cxx11::basic_string<char,rocksdb::OptionsSanityCheckLevel> const*,std::allocator<char> > > const&,std::__detail::_Mod_range_hashing const&,std::__detail::_Default_ranged_hash const&,std::__detail::_Select1st const&,rocksdb::OptionsSanityCheckLevel> > const&) () from /opt/miner/lib/rocksdb-1.5.0/priv/liberocksdb.so
#6  0xb1b489fc in std::_Hashtable<std::__cxx11::basic_string<char,true> >::_Hashtable(std::initializer_list<std::pair<std::__cxx11::basic_string<char,rocksdb::OptionsSanityCheckLevel> > const&) () from /opt/miner/lib/rocksdb-1.5.0/priv/liberocksdb.so
#7  0xb1b3c10c in std::unordered_map<std::__cxx11::basic_string<char,rocksdb::OptionsSanityCheckLevel,rocksdb::OptionsSanityCheckLevel> > >::unordered_map(std::initializer_list<std::pair<std::__cxx11::basic_string<char,rocksdb::OptionsSanityCheckLevel> > const&) () from /opt/miner/lib/rocksdb-1.5.0/priv/liberocksdb.so
#8  0xb1b28b04 in __static_initialization_and_destruction_0 () from /opt/miner/lib/rocksdb-1.5.0/priv/liberocksdb.so
#9  0xb1b29d30 in _GLOBAL__sub_I_db_impl.cc () from /opt/miner/lib/rocksdb-1.5.0/priv/liberocksdb.so
#10 0xb6fddff8 in ?? () from /lib/ld-linux-armhf.so.3
Backtrace stopped: prevIoUs frame identical to this frame (corrupt stack?)

拆解如下:

(gdb) disas /m
Dump of assembler code for function _ZNKSt8__detail18_Mod_range_hashingclEjj:
   0xb1b2a790 <+0>:     push    {r11}           ; (str r11,[sp,#-4]!)
   0xb1b2a794 <+4>:     add     r11,sp,#0
   0xb1b2a798 <+8>:     sub     sp,#20
   0xb1b2a79c <+12>:    str     r0,[r11,#-8]
   0xb1b2a7a0 <+16>:    str     r1,#-12]
   0xb1b2a7a4 <+20>:    str     r2,#-16]
   0xb1b2a7a8 <+24>:    ldr     r3,#-12]
   0xb1b2a7ac <+28>:    ldr     r2,#-16]
=> 0xb1b2a7b0 <+32>:    udiv    r2,r3,r2
   0xb1b2a7b4 <+36>:    ldr     r1,#-16]
   0xb1b2a7b8 <+40>:    mul     r2,r1,r2
   0xb1b2a7bc <+44>:    sub     r3,r2
   0xb1b2a7c0 <+48>:    mov     r0,r3
   0xb1b2a7c4 <+52>:    add     sp,r11,#0
   0xb1b2a7c8 <+56>:    pop     {r11}           ; (ldr r11,[sp],#4)
   0xb1b2a7cc <+60>:    bx      lr
End of assembler dump.

我不是这个领域的专家,但据我所知,程序崩溃是因为指令 udiv 对我的 cpu 是非法的。 我查看了 ARM 开发者网站,这是一个 Cortex M3 instruction,我相信我的 cpuCortex M4,所以我想它应该有这个指令?

也许我的分析是错误的,这是别的什么?

我的交叉编译是使用该 cpu 和 rootfs 的交叉工具链进行的,并包含诸如 -march=armv7-a -marm -mfpu=neon -mfloat-abi=hard 之类的参数,这些参数应该提供兼容的二进制文件

谢谢

解决方法

cmake 脚本强制使用与我的 CPU 不兼容的 -march=armv8-a+crc

https://gitlab.com/Vagabond1/erlang-rocksdb/-/commit/6bf4a440b8132ef643682ba87dee6de87dc47d58