GCC在64位模式下崩溃

时间:2015-08-24 20:46:03

标签: c++ gcc compiler-optimization

在Windows64上使用MinGW GCC 4.8.2编译7-zip源代码我发现了崩溃。

以下是7-zip 9.20,Sha1.cpp:

的代码片段
const unsigned kBlockSize = 64;

...

void CContext::UpdateRar(Byte *data, size_t size, bool rar350Mode) {
   ...
   for (int i = 0; i < kBlockSizeInWords; i++) {
       UInt32 d = _buffer[i];
       data[i * 4 + 0 - kBlockSize] = (Byte)(d);      // <<= DISASSEMBLED
       data[i * 4 + 1 - kBlockSize] = (Byte)(d >>  8);
       data[i * 4 + 2 - kBlockSize] = (Byte)(d >> 16);
       data[i * 4 + 3 - kBlockSize] = (Byte)(d >> 24);
   }
}

使用MinGW GCC 4.8.2(在Windows上)进行编译得到:

0x0000000045b65f75 <+149>:   mov    eax,0xffffffc0
0x0000000045b65f7a <+154>:   nop    WORD PTR [rax+rax*1+0x0]
0x0000000045b65f80 <+160>:   mov    r10d,DWORD PTR [r11+0x24]
0x0000000045b65f84 <+164>:   mov    edx,eax
0x0000000045b65f86 <+166>:   add    r11,0x4
0x0000000045b65f8a <+170>:   mov    ecx,r10d
0x0000000045b65f8d <+173>:   mov    BYTE PTR [rbx+rdx*1],r10b

在最后一行rbx中,应从此地址中减去data64。这是通过添加-64来完成的。在汇编代码段0xffffffc0-64(Int32))的第一行中保存到eax,然后移至edx。但在最后一行

0x0000000045b65f8d <+173>:   mov    BYTE PTR [rbx+rdx*1],r10b

rdx寄存器而不是edx寄存器。此时rdx的顶部为0,因此+64可以正常工作。但添加-64要求rdx寄存器的顶部部分保留0xFFFFFFFF。在64位模式下添加&data+0xffffffc0会产生无效的地址并崩溃。

通过更改分配(添加(int)强制转换)来解决问题:

       data[i * 4 + 0 - (int)kBlockSize] = (Byte)(d);
       data[i * 4 + 1 - (int)kBlockSize] = (Byte)(d >>  8);
       data[i * 4 + 2 - (int)kBlockSize] = (Byte)(d >> 16);
       data[i * 4 + 3 - (int)kBlockSize] = (Byte)(d >> 24);

我的问题是:

  • 是错误还是功能?
  • 是否有一些GCC标志可以防止这种行为?
  • 我怎样才能确定我的整个7-zip二进制文件没有这样的错误?

更新 事实证明,这种行为不依赖于优化标志,只能在Windows上观察

0 个答案:

没有答案