Problem getting XMM registers from a CONTEXT structure

Started by donkey, April 26, 2011, 03:00:37 AM

Previous topic - Next topic

donkey

I have been trying to dump the processor state from a process and can't seem to get the values for XMM0-XMM5 in the CONTEXT structure. Not even the foggiest idea why not. Here's the test code:

DATA SECTION

xmm0Value DQ 0x1111111111111111
DQ 0x1111111111111111
xmm1Value DQ 0x2222222222222222
DQ 0x2222222222222222
xmm2Value DQ 0x3333333333333333
DQ 0x3333333333333333
xmm3Value DQ 0x4444444444444444
DQ 0x4444444444444444
xmm4Value DQ 0x5555555555555555
DQ 0x5555555555555555
xmm5Value DQ 0x6666666666666666
DQ 0x6666666666666666
xmm6Value DQ 0x7777777777777777
DQ 0x7777777777777777
xmm7Value DQ 0x8888888888888888
DQ 0x8888888888888888

hThreadHandle DD ?
idthread DD ?

ALIGN 16
cntxt CONTEXT <?>

CODE SECTION
// Load the xmm registers with easily identifiable data
movdqu xmm0,[xmm0Value]
movdqu xmm1,[xmm1Value]
movdqu xmm2,[xmm2Value]
movdqu xmm3,[xmm3Value]
movdqu xmm4,[xmm4Value]
movdqu xmm5,[xmm5Value]
movdqu xmm6,[xmm6Value]
movdqu xmm7,[xmm7Value]

// Get a real handle to this thread
invoke DuplicateHandle,-1,-2,-1,offset hThreadHandle,0,0,2
// Create a new thread to suspend this one
invoke CreateThread,NULL,0x10000,offset TestXMMThreadProc,[hThreadHandle],NULL,offset idthread
// We're done...
invoke CloseHandle,eax
invoke ExitProcess,0

TestXMMThreadProc FRAME hThread
LOCAL xmmsa:XMM_SAVE_AREA32

// Suspend the main thread
invoke SuspendThread,[hThread]

// Set the flags to get everything
mov D[cntxt.ContextFlags],CONTEXT_ALL
// Fill the context structure
invoke GetThreadContext,[hThread],offset cntxt

// Move the data - don't have to do this but it makes it clearer.
lea esi,cntxt.ExtendedRegisters
mov ecx,SIZEOF XMM_SAVE_AREA32
shr ecx,2
lea edi,xmmsa
rep movsd

// Dump the XMM register data to the output window
DumpMem(offset xmmsa.XmmRegisters,SIZEOF XMM_SAVE_AREA32.XmmRegisters)

// Restart the main thread
invoke ResumeThread,[hThread]

// Terminate this thread
invoke ExitThread,0
ret
endf


I have checked the values in the XMM registers prior to suspending the thread and they are fine. On exit from the thread XMM6 and XMM7 are valid however all the others have been set to zero. The output is:

----------------------------------------
Line 83 : Hex dump of 256 bytes at address 0x0217FE1C
----------------------------------------
0217FE1C:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00   ................
0217FE2C:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00   ................
0217FE3C:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00   ................
0217FE4C:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00   ................
0217FE5C:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00   ................
0217FE6C:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00   ................
0217FE7C:  77 77 77 77-77 77 77 77-77 77 77 77-77 77 77 77   wwwwwwwwwwwwwwww
0217FE8C:  88 88 88 88-88 88 88 88-88 88 88 88-88 88 88 88   ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ
0217FE9C:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00   ................
0217FEAC:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00   ................
0217FEBC:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00   ................
0217FECC:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00   ................
0217FEDC:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00   ................
0217FEEC:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00   ................
0217FEFC:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00   ................
0217FF0C:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00   ................
----------------------------------------
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

dedndave

hi Edgar
we don't see the labels for this code...
lea esi,cntxt.ExtendedRegisters
mov ecx,SIZEOF XMM_SAVE_AREA32
shr ecx,2
lea edi,xmmsa
rep movsd


now, i am the last guy you want to ask about xmm   :lol
but, it appears to me that the stuff isn't 16-aligned...
0217FE7C:  77 77 77 77-77 77 77 77-77 77 77 77-77 77 77 77   wwwwwwwwwwwwwwww
0217FE7C
mainly, we don't see what the CONTEXT structure looks like
and, we don't know where xmmsa is

donkey

Hi Dave,

The label for cntxt is aligned, its the last label in the data section. The label xmmsa does not have to be since its just a local buffer and is filled with movsd which does not require alignment.

Weird, it almost appears as if the API calls trash the XMM registers. For example if I load them then call DuplicateHandle without the thread XMM0-XMM5 are set to zero, the same goes for the CreateThread function. This may be an issue related to WoW64 in some way, I'll have to run this test on an XP32 box to see if its the problem. I did not use GetThreadContext but output the XMM registers directly to see their contents for these tests.

The X86-32 CONTEXT structure is defined in winnt.h as:

CONTEXT STRUCT
ContextFlags DD
Dr0 DD
Dr1 DD
Dr2 DD
Dr3 DD
Dr6 DD
Dr7 DD
FloatSave FLOATING_SAVE_AREA
SegGs DD
SegFs DD
SegEs DD
SegDs DD
Edi DD
Esi DD
Ebx DD
Edx DD
Ecx DD
Eax DD
Ebp DD
Eip DD
SegCs DD
EFlags DD
Esp DD
SegSs DD
ExtendedRegisters DB MAXIMUM_SUPPORTED_EXTENSION DUP
ENDS


The XMM_SAVE_AREA32 sturcture is defined as:

XMM_SAVE_AREA32 STRUCT
ControlWord DW
StatusWord DW
TagWord DB
Reserved1 DB
ErrorOpcode DW
ErrorOffset DD
ErrorSelector DW
Reserved2 DW
DataOffset DD
DataSelector DW
Reserved3 DW
MxCsr DD
MxCsr_Mask DD
FloatRegisters DB 16*8 DUP ; M128A
XmmRegisters DB 16*16 DUP ; M128A
Reserved4 DB 96 DUP
ENDS
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

dedndave

ah yes - Jochen has mentioned something about that in the past...
...that some API functions trash them

dedndave

QuoteIf you call GetThreadContext for the current thread, the function
returns successfully; however, the context returned is not valid.

sounds like someone is writing a debugger   :P

donkey

Hi Dave,

That's why its called in a separate thread and the one I'm examining is suspended. Just looking to expand on my inline debug tools for RadAsm3.

Well, now I know what the problem is the workaround is simple, just save the registers on entry and restore them on exit.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

drizz

Quote from: donkey on April 26, 2011, 03:29:52 AMWeird, it almost appears as if the API calls trash the XMM registers.
xmm0-xmm7 are volatile under 32bit windows
xmm0-xmm5 are volatile under 64bit windows, xmm6-xmm15 are not - this explains why xmm6 & xmm7 are preserved for WoW.

If you are in debuggers wait loop -> You get the exact CONTEXT of the debugee
If you are in exception handler -> You get the exact CONTEXT when the exception occured
If you need to store register state use FXSAVE
If you need to debug without debug api -> You insert exception raising instruction/code and .....hooooook... :lol............................  :naughty:

The truth cannot be learned ... it can only be recognized.

donkey

Thanks Drizz,

I think I have it pretty much licked, I had used the FXSAVE/FXRSTOR combination to preserve the XMM registers for the calls that needed it. In a debug loop or in an exception handler it wasn't an issue.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

baltoro

drizz,   
This is really useful intel: 

Quote from: DRIZZIf you are in debuggers wait loop -> You get the exact CONTEXT of the debugee
If you are in exception handler -> You get the exact CONTEXT when the exception occured
If you need to store register state use FXSAVE
If you need to debug without debug api -> You insert exception raising instruction/code and .....hooooook...

How did you figure that out ??? I always screw up any attempts to obtain register state data wihen invoking GetThreadContext. :eek
Baltoro

drizz

The truth cannot be learned ... it can only be recognized.

baltoro

:eek INCREDIBLE !!! :eek
Thanks, Drizz,..this is valuable information. If you run for President,...you've got my vote,... :eek
Baltoro