Question

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?

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top