arm-wrs-linux-gnueabi可能出现的GCC错误

时间:2019-06-11 11:16:22

标签: gcc compiler-errors

我相信在构建大型项目时会遇到编译器错误。仅当使用-O1(而不是-O0或-O2)编译代码时,才观察到有问题的代码生成。

问题在于函数调用,该函数调用是find_if的包装。此函数将一个空向量作为输入,该向量应使find_if立即返回。

代码看起来像这样:

void LookUpEvalResultFun(some arguments) {
  empty vector declaration
  some simple code handling the arguments
  call the function that is wrapper to find_if
}

如果代码的行为不符合预期,则汇编器如下所示:

0x00eab0dc <+0>:   strd r4, [sp, #-36]! ; 0xffffffdc
0x00eab0e0 <+4>:   strd r6, [sp, #8]
0x00eab0e4 <+8>:   strd r8, [sp, #16]
0x00eab0e8 <+12>:  strd r10, [sp, #24]
0x00eab0ec <+16>:  str  lr, [sp, #32]
0x00eab0f0 <+20>:  add  r11, sp, #32
0x00eab0f4 <+24>:  sub  sp, sp, #132    ; 0x84
0x00eab0f8 <+28>:  ldr  r3, [r0]
0x00eab0fc <+32>:  ldr  r3, [r3, #24]
0x00eab100 <+36>:  blx  r3
0x00eab104 <+40>:  movw r4, #21700 ; 0x54c4
0x00eab108 <+44>:  movt r4, #373   ; 0x175
0x00eab10c <+48>:  mov  r3, #0
0x00eab110 <+52>:  strb r3, [sp]
0x00eab114 <+56>:  ldr  r2, [r4, #52]   ; 0x34
0x00eab118 <+60>:  ldr  r0, [r4, #48]   ; 0x30
0x00eab11c <+64>:  bl   0xd9c4a0 <mangled name for find_if>

mangled name for find_if:
0x00d9c4a0 <+0>:   strd r4, [sp, #-32]! ; 0xffffffe0
0x00d9c4a4 <+4>:   strd r6, [sp, #8]
0x00d9c4a8 <+8>:   strd r8, [sp, #16]
0x00d9c4ac <+12>:  str  r11, [sp, #24]
0x00d9c4b0 <+16>:  str  lr, [sp, #28]
0x00d9c4b4 <+20>:  add  r11, sp, #28
0x00d9c4b8 <+24>:  mov  r9, r1
0x00d9c4bc <+28>:  mov  r7, r0
0x00d9c4c0 <+32>:  rsb  r8, r0, r1
0x00d9c4c4 <+36>:  asr  r8, r8, #6
0x00d9c4c8 <+40>:  movw r3, #43691 ; 0xaaab
0x00d9c4cc <+44>:  movt r3, #43690 ; 0xaaaa
0x00d9c4d0 <+48>:  mul  r8, r3, r8
0x00d9c4d4 <+52>:  asr  r8, r8, #2
0x00d9c4d8 <+56>:  cmp  r8, #0
0x00d9c4dc <+60>:  ble  0xd9c558 <_ZSt9__find_ifIN9__gnu_cxx17__normal_iterator...>

以下说明:

0x00eab114 <+56>:  ldr  r2, [r4, #52]   ; 0x34
0x00eab118 <+60>:  ldr  r0, [r4, #48]   ; 0x30

vs。

0x00d9c4b8 <+24>:  mov  r9, r1
0x00d9c4bc <+28>:  mov  r7, r0

表明在包装函数中R2加载了vector.end(),而find_if希望在R1中找到vector.end()。

以下是更有趣的事情,无论有关优化级别的代码如何编译(当使用-c分别编译每个文件时)。

1244:   e3a00000    mov r0, #0
template<typename _Iterator, typename _Predicate>
inline _Iterator
__find_if(_Iterator __first, _Iterator __last, _Predicate __pred)
{
  return __find_if(__first, __last, __pred,                std::__iterator_category(__first));
1248:   e3a03000    mov r3, #0
124c:   e5cd3000    strb    r3, [sp]
1250:   e1a02000    mov r2, r0
1254:   ebfffffe    bl  0 <mangled name>
        1254: R_ARM_CALL    _ZSt9__find_ifIN9__gnu_cxx17__normal_iterator 

00000000 <mangled name>:
0:  e16d42f0    strd    r4, [sp, #-32]! ; 0xffffffe0
4:  e1cd60f8    strd    r6, [sp, #8]
8:  e1cd81f0    strd    r8, [sp, #16]
c:  e58db018    str fp, [sp, #24]
10: e58de01c    str lr, [sp, #28]
14: e28db01c    add fp, sp, #28
18: e1a09002    mov r9, r2
1c: e1a07000    mov r7, r0
20: e0608002    rsb r8, r0, r2
24: e1a08348    asr r8, r8, #6
28: e30a3aab    movw    r3, #43691  ; 0xaaab
2c: e34a3aaa    movt    r3, #43690  ; 0xaaaa

这表明正确使用了R2!

我的理论是这样的:

  1. 编译器正确地编译了每个文件,并且在接下来的阶段中发生了某些事情。
  2. 实际上存在一个编译器错误,包含包装函数的特定文件上的objdump输出未显示该错误。

即使addr2line也会显示以下内容:

0x00001254: _ZSt9__find_ifIN9__gnu_cxx17__normal_iteratorIPKN2ue7VariantINS2_12_...
(inlined by) _ZSt7find_ifIN9__gnu_cxx17__normal_iteratorIPKN2ue7VariantINS2_12_...
(inlined by) find_if wrapper
(inlined by) LookUpEvalResultFun at ...

表明objdump没有说谎;某种程度上支持了第一种理论。

您有什么想法吗?

谢谢。

0 个答案:

没有答案