[prev in list] [next in list] [prev in thread] [next in thread]
List: wine-devel
Subject: Re: Thunking problem is partially solved
From: Ulrich Weigand <weigand () immd1 ! informatik ! uni-erlangen ! de>
Date: 2000-08-31 1:48:30
[Download RAW message or body]
Dmitry Timoshkov wrote:
> Examining the disassembled text of pm65.exe, I noted, that PM pushes
> different number of bytes in different places in the code before call
> to QT_Thunk. I assume, that it is an exact number of bytes, that 16-bit
> callee will get as arguments and should pop from the stack with pascal16
> function return type.
Right. The problem is that we implement thunks differently than Win95
does, with the most important difference being that we actually have two
seperate stacks per app, a 16-bit one and a 32-bit one, where Win95 has
only *one* stack: 16-bit apps have their 16-bit stack, and when thunking
to 32-bit, ESP is simply set to the appropriate 32-bit flat pointer pointing
to the current 16-bit stack location; 32-bit apps have their 32-bit stack,
and when thunking to 16-bit, a temporary SS selector is allocated that
covers the current 'window' on the 32-bit stack.
This means that Win95 does not in fact copy *any* arguments in QT_Thunk
and the other thunking routines; they simply stay on the stack.
Similarly, all modifications made to SP by the called routine are
preserved, so if the 16-bit routine pops N argument bytes, those
arguments will also be popped on the 32-bit stack after return of
QT_Thunk.
We, on the other hand, have to copy arguments to the 16-bit stack.
Unfortunately, we don't know how *many* arguments to copy, thus we
copy in fact the largest possible size (i.e. from ESP to EBP-0x40.
EBP-0x40 is because the region EBP-0x40..EBP is a parameter block
for use by QT_Thunk that has to be set up by the caller). As we
don't know the actual argument size, we don't know how much to
pop off the 32-bit stack either.
This works fine if the caller of QT_Thunk is one of the thunk stubs
generated by the MS thunk compiler (which is supposed to be the *only*
code that ever calls QT_Thunk), because these stubs don't have any
other local variables on the stack, and return to their caller
immediately after QT_Thunk returned.
Apparently, your app calls QT_Thunk manually, from within a routine
that does in fact care about the proper ESP value after return of
QT_Thunk. This unfortunately doesn't work with the current Wine
code. To fix this, we'd need to find out how many bytes the
16-bit routine popped off the stack, which is currently not possible.
> I made some addtional traces to find out the way to properly calculate
> number of bytes popped by 16-bit function from the 16-bit stack, but failed.
The problem is that the return path in CallTo16 restores proper
32-bit register values, without taking care of saving the values
left in the registers by the 16-bit function (except for the
return value in AX/DX). Thus, the caller has no way of finding
out these values.
One option to fix this problem might be to update the context
structure on return. This is unfortunately a little tricky
because of the peculiar way we perform the 16->32 bit transition.
Furthermore it might have probably an adverse impact on
performance ...
Another way might be to change the arg_size parameter from a
pure input parameter to in/out, and update this with the
actual argument size (as popped by the called routine).
I'll have to think about this ...
Bye,
Ulrich
--
Dr. Ulrich Weigand
weigand@informatik.uni-erlangen.de
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic