读指令上的写访问冲突 [英] Write access violation on read instruction

查看:300
本文介绍了读指令上的写访问冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们在我们的产品中使用SQLite库,并且在用不同的编译器版本(Visual C ++)重新编译之后突然在客户计算机上崩溃。



崩溃是

  ExceptionAddress:0710eadd(sqlite3!sqlite3_transfer_bindings + 0x0004e5bd)
ExceptionCode:c0000005(访问冲突)
ExceptionFlags:00000000
NumberParameters:2
参数[0]:00000001
参数[1]:07148688
尝试写入地址07148688

,导致崩溃的代码如下(sqlite3MutexInit的一部分):

  0710ead0 b804811407 mov eax,0x07148104 
0710ead5 b97c861407 mov ecx,0x0714867c
0710eada 0f44c8 cmove ecx,eax
0710eadd f30f7e410c movq xmm0,mmword ptr [ecx + 0Ch]

相应的C代码:

  if(sqlite3GlobalConfig.bCoreMutex){
pFrom = sqlite3DefaultMutex();
} else {
pFrom = sqlite3NoopMutex();
}
memcpy(pTo,pFrom,offsetof(sqlite3_mutex_methods,xMutexAlloc));

这不是特别重要,但在我们的例子中sqlite3GlobalConfig.bCoreMutex设置为1。 >

问题是,在这种特殊情况下,地址07148688的内存是可读的,并且指令应该读取,而不是写入。



我们有两台机器的内存转储,这两种情况都发生在Athlon XP处理器(家庭/型号/步进:6/10/0,6/8/1)。



使用多个Visual C ++版本(2012,2013和2013 Update 1)重新编译会产生略微不同的代码(错误地址处的movq vs movdqu指令),但崩溃。



是否可能是由于处理器或编译器错误而导致的?

解决方案

早期的AMD Athlon(和Pentium III)处理器显然不支持使用SSE2指令引入的这种形式的movq。我引用Anders Carlsson在 GCC讨论中:


查看英特尔参考文档,可从 ftp://download.intel.com/design/Pentium4/manuals/25366614.pdf MOVQ有以下操作码:

  0F 6F / r MOVQ mm,mm / m64将四字从mm / m64移动到mm。 
0F 7F / r MOVQ mm / m64,mm将四字从mm移动到mm / m64。
F3 0F 7E MOVQ xmm1,xmm2 / m64将四字从xmm2 / mem64移动到xmm1。
66 0F D6 MOVQ xmm2 / m64,xmm1将四字从xmm1移动到xmm2 / mem64。

并且由于后两条指令在AMD和Pentium III上不受支持,因此您需要一些其他方法来移动xmm寄存器和存储器之间的数据。


英特尔参考文档不再可用; movq指令的另一个引用位于 http://x86.renejeschke.de/html/file_module_x86_id_201.html 。我没有AMD Athlon XP来测试这个。



关闭SSE2优化应该可以解决问题。 SSE2指令集是VS2012及更高版本中的默认值,并且/ arch编译器标志控制要使用的指令集;请参见 http://msdn.microsoft.com/ en-us / library / 7t5yh4fd%28v = vs.110%29.aspx


We use SQLite library in our product and suddenly after recompilation with different compiler version (Visual C++) it started crashing on customer computers.

The crash is

ExceptionAddress: 0710eadd (sqlite3!sqlite3_transfer_bindings+0x0004e5bd)
   ExceptionCode: c0000005 (Access violation)
  ExceptionFlags: 00000000
NumberParameters: 2
   Parameter[0]: 00000001
   Parameter[1]: 07148688
Attempt to write to address 07148688

and the code causing the crash is the following (part of sqlite3MutexInit):

0710ead0 b804811407      mov     eax, 0x07148104
0710ead5 b97c861407      mov     ecx, 0x0714867c
0710eada 0f44c8          cmove   ecx, eax
0710eadd f30f7e410c      movq    xmm0, mmword ptr [ecx+0Ch]

The corresponding C code:

if( sqlite3GlobalConfig.bCoreMutex ){
  pFrom = sqlite3DefaultMutex();
}else{
  pFrom = sqlite3NoopMutex();
}
memcpy(pTo, pFrom, offsetof(sqlite3_mutex_methods, xMutexAlloc));

It is not particularly important, but in our case sqlite3GlobalConfig.bCoreMutex is set to 1.

The problem is that in this particular case the memory at address 07148688 is readable and the instruction is supposed to read it, not write it.

We have memory dumps from two machines and in both cases it happened on Athlon XP processors (Family/Model/Stepping: 6/10/0, 6/8/1).

Recompilation with several Visual C++ versions (2012, 2013 and 2013 Update 1) yeilds slightly different code (movq vs movdqu instruction at the faulting address), but the crash happens consistently.

Could it be caused by processor or compiler bug we are hitting?

解决方案

The older AMD Athlon (and Pentium III) processors apparently do not support this form of movq which was introduced with SSE2 instructions. I quote Anders Carlsson in a GCC discussion:

Looking at the Intel reference documentation available from ftp://download.intel.com/design/Pentium4/manuals/25366614.pdf MOVQ has the following opcodes:

0F 6F /r MOVQ mm, mm/m64      Move quadword from mm/m64 to mm. 
0F 7F /r MOVQ mm/m64, mm      Move quadword from mm to mm/m64. 
F3 0F 7E MOVQ xmm1, xmm2/m64  Move quadword from xmm2/mem64 to xmm1.
66 0F D6 MOVQ xmm2/m64, xmm1  Move quadword from xmm1 to xmm2/mem64.

and since the two latter instructions are unsupported on AMD and Pentium III you would need some other way to move data between the xmm registers and memory.

That Intel reference documentation is no longer available; another reference for the movq instruction is at http://x86.renejeschke.de/html/file_module_x86_id_201.html. I don't have an AMD Athlon XP to test this against, though.

Turning off SSE2 optimizations should resolve the problem. SSE2 instruction set is the default in VS2012 and later, and the /arch compiler flag controls which instruction set to use; see http://msdn.microsoft.com/en-us/library/7t5yh4fd%28v=vs.110%29.aspx.

这篇关于读指令上的写访问冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆