Write access violation on read instruction
Asked Answered
A

1

2

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?

Alkalosis answered 21/1, 2014 at 11:26 Comment(2)
An access violation on read occurs when you attempt to read a location in a guard page. Most likely it's an index out of bound issue. I would suggest you debug the exception and see what is at the location that the exception says the violation occurred.Sarina
The accessed address is pointer table in the generated code and the address is correct and readable. I even verified that in debugger and post-mortem dumps. The problem is that the exception is write access violation, but the instruction should read. The address is not writable, btw.Alkalosis
C
3

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.

Conde answered 4/2, 2014 at 22:5 Comment(1)
I looked at the processor manuals before and I was pretty much convinced that the instruction is SSE and not SSE2, which should be supported on the Athlon XP processors. However now that you pointed out that the XMM version is SSE2 it makes complete sense.Alkalosis

© 2022 - 2024 — McMap. All rights reserved.