http://bugs.winehq.org/show_bug.cgi?id=31308
--- Comment #4 from Anastasius Focht focht@gmx.net 2012-07-25 16:21:56 CDT --- Hello André,
I think I figured out what TPIDRURW value means. The routine that accesses it looks like some inlined alloca() implementation for ARM.
I added some comments what I think it does
--- snip --- ... .text:00419D3C SUBS.W R12, SP, R4,LSL#2 ; get end addr of req. buffer .text:00419D40 MRC p15, 0, R4,c13,c0, 2 ; get TEB .text:00419D44 LDR R4, [R4,#8] ; teb->Tib.StackLimit .text:00419D48 CMP R12, R4 .text:00419D4A BCC loc_419D58 ; doesn't fit, grow active stack .text:00419D4C SUB.W R4, SP, R12 ; fits, new buffer start .text:00419D50 BX LR .text:00419D52 MOVS.W R12, #0 .text:00419D56 B loc_419D48 ; grow the stack .text:00419D58 PUSH {R5,R6} .text:00419D5A MOV R6, R12 .text:00419D5C BFC.W R6, #0, #0xC ; align .text:00419D60 SUB.W R4, R4, #0x1000 ; move down by PAGE_SIZE .text:00419D64 LDR R5, [R4] ; touch the page ; touching page below teb->Tib.StackLimit should update the field to new limit ; until DeallocationStack is reached (exhausted) .text:00419D66 CMP R4, R6 .text:00419D68 BNE loc_419D60 .text:00419D6A POP {R5,R6} .text:00419D6C SUB.W R4, SP, R12 ; new buffer start .text:00419D70 BX LR --- snip ---
I patched Wine to set TPIDRURW to the TEB value for each newly created thread in signal_init_thread(). This should work but unfortunately my kernel doesn't preserve the value of TPIDRURW (gets overwritten).
The crash you're seeing is because another thread context, where TPIDRURW has been zeroed out again.
For each newly created thread you have to set TPIDRURW to the appropriate TEB and the kernel must be modified to save/restore TPIDRURW value for each thread on context switch (hence this bug is actually upstream).
Regards