[PATCH] x86emu: Fix more mis-decoding of the data prefix

Julien Cristau jcristau at debian.org
Mon Dec 20 15:50:19 PST 2010


On Mon, Dec 20, 2010 at 16:55:18 -0500, Adam Jackson wrote:

> On Mon, 2010-12-20 at 19:41 +0100, Julien Cristau wrote:
> > On Fri, Dec 10, 2010 at 14:47:20 -0500, Adam Jackson wrote:
> > > @@ -7084,8 +7089,12 @@ static void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
> > >      TRACE_AND_STEP();
> > >      push_word(M.x86.R_CS);
> > >      M.x86.R_CS = farseg;
> > > -    push_word(M.x86.R_IP);
> > > -    M.x86.R_IP = faroff;
> > > +    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
> > > +	push_long(M.x86.R_EIP);
> > > +    } else {
> > > +	push_word(M.x86.R_IP);
> > > +    }
> > > +    M.x86.R_EIP = faroff & 0xffff;
> > >      DECODE_CLEAR_SEGOVR();
> > >      END_OF_INSTR();
> > >  }
> > 
> > The intel doc says (for far calls in virtual-8086 mode):
> > 
> > IF OperandSize = 32
> >   THEN
> >     ...
> >     EIP ← DEST[31:0]; (* DEST is ptr16:32 or [m16:32] *)
> >   ELSE
> >     ...
> >     EIP ← DEST[15:0]; (* DEST is ptr16:16 or [m16:16]; clear upper 16 bits *)
> > FI;
> > 
> > which suggests that you don't need the & 0xffff in the last assignment?
> 
> Bit of artistic license on my part.  The relevant excerpt is:
> 
> IF OperandSize = 32
> THEN
> 	IF stack not large enough for a 6-byte return address
> 	THEN #SS(0); FI;
> @	IF DEST[31:16] is not zero THEN #GP(0); FI;
> 	Push(CS); (* Padded with 16 high-order bits *)
> 	Push(EIP);
> 	CS <- DEST[47:32]; (* DEST is ptr16:32 or [m16:32] *)
> 	EIP <- DEST[31:0]; (* DEST is ptr16:32 or [m16:32] *)
> ELSE (* OperandSize = 16 *)
> 	IF stack not large enough for a 4-byte return address
> 	THEN #SS(0); FI;
> 	Push(CS);
> 	Push(IP);
> 	CS <- DEST[31:16]; (* DEST is ptr16:16 or [m16:16] *)
> 	EIP <- DEST[15:0]; (* DEST is ptr16:16 or [m16:16]; clear upper 16 bits *)
> FI;
> 
> The @'d line is where I'm taking a small liberty, as x86emu doesn't
> emulate faults.  We'll assume (since x86emu tends to work) that the
> number of BIOSes that need fault handling is very low.  So by the time
> you hit the EIP load, either:
> 
> - operand size is 16, high word of EIP explicitly 0
> - operand size is 32 but you'd have faulted if the high word wasn't 0
> 
> Practically I think this matters only if the later code looks at the
> high word of EIP, instruction fetch is only going to look at cs:ip not
> cs:eip.  But, might as well be screechingly correct.
> 
Thanks for the explanation.  Feel free to add my
Reviewed-by: Julien Cristau <jcristau at debian.org>

Cheers,
Julien


More information about the xorg-devel mailing list