250 lines
4.9 KiB
C
250 lines
4.9 KiB
C
/*++
|
|
|
|
Copyright (c) 1995-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ctrltrns.c
|
|
|
|
Abstract:
|
|
|
|
Control Transfer Fragments.
|
|
|
|
Author:
|
|
|
|
10-July-1995 t-orig (Ori Gershony)
|
|
|
|
Revision History:
|
|
|
|
24-Aug-1999 [askhalid] copied from 32-bit wx86 directory and make work for 64bit.
|
|
20-Sept-1999[barrybo] added FRAG2REF(LockCmpXchg8bFrag32, ULONGLONG)
|
|
|
|
--*/
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
|
|
#define _WX86CPUAPI_
|
|
|
|
#include "wx86nt.h"
|
|
#include "wx86cpu.h"
|
|
#include "instr.h"
|
|
#include "config.h"
|
|
#include "cpuassrt.h"
|
|
#include "fragp.h"
|
|
#include "entrypt.h"
|
|
#include "compiler.h"
|
|
#include "ctrltrns.h"
|
|
#include "threadst.h"
|
|
#include "tc.h"
|
|
#include "cpunotif.h"
|
|
#include "atomic.h"
|
|
|
|
ASSERTNAME;
|
|
|
|
VOID
|
|
FlushCallstack(
|
|
PTHREADSTATE cpu
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Flush the callstack - the Translation Cache is flushing, which
|
|
invalidates the callstack.
|
|
|
|
Arguments:
|
|
|
|
cpu - per-thread info
|
|
|
|
Return Value:
|
|
|
|
.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Mark the callstack as valid.
|
|
//
|
|
cpu->CSTimestamp = TranslationCacheTimestamp;
|
|
|
|
memset(cpu->callStack, 0, CSSIZE*sizeof(CALLSTACK));
|
|
//
|
|
// No need to reset cpu->CSIndex as the stack is actually implemented
|
|
// within a circular buffer. It can start at any offset
|
|
//
|
|
}
|
|
|
|
// Call
|
|
ULONG
|
|
CTRL_CallFrag(
|
|
PTHREADSTATE cpu, // cpu state pointer
|
|
ULONG inteldest,
|
|
ULONG intelnext,
|
|
ULONG nativenext
|
|
)
|
|
{
|
|
PUSH_LONG(intelnext);
|
|
PUSH_CALLSTACK(intelnext, nativenext);
|
|
ASSERTPtrInTCOrZero((PVOID)nativenext);
|
|
|
|
eip = inteldest;
|
|
|
|
return inteldest;
|
|
}
|
|
|
|
// Call FAR
|
|
ULONG
|
|
CTRL_CallfFrag(
|
|
PTHREADSTATE cpu, // cpu state pointer
|
|
PUSHORT pinteldest,
|
|
ULONG intelnext,
|
|
ULONG nativenext
|
|
)
|
|
{
|
|
USHORT sel;
|
|
DWORD offset;
|
|
|
|
offset = *(UNALIGNED PULONG)(pinteldest);
|
|
sel = *(UNALIGNED PUSHORT)(pinteldest+2);
|
|
|
|
PUSH_LONG(CS);
|
|
PUSH_LONG(intelnext);
|
|
PUSH_CALLSTACK(intelnext, nativenext);
|
|
ASSERTPtrInTCOrZero((PVOID)nativenext);
|
|
|
|
eip = offset;
|
|
CS = sel;
|
|
|
|
return (ULONG)(ULONGLONG)pinteldest;
|
|
}
|
|
|
|
// IRet
|
|
ULONG CTRL_INDIR_IRetFrag(PTHREADSTATE cpu)
|
|
{
|
|
ULONG intelAddr, nativeAddr;
|
|
DWORD CSTemp;
|
|
|
|
POP_LONG(intelAddr);
|
|
POP_LONG(CSTemp);
|
|
PopfFrag32(cpu);
|
|
|
|
eip = intelAddr;
|
|
CS = (USHORT)CSTemp;
|
|
POP_CALLSTACK(intelAddr,nativeAddr);
|
|
ASSERTPtrInTCOrZero((PVOID)nativeAddr);
|
|
|
|
return nativeAddr;
|
|
}
|
|
|
|
// Now the ret fragments
|
|
ULONG CTRL_INDIR_RetnFrag32(PTHREADSTATE cpu)
|
|
{
|
|
ULONG intelAddr, nativeAddr;
|
|
|
|
POP_LONG(intelAddr);
|
|
eip = intelAddr;
|
|
POP_CALLSTACK(intelAddr,nativeAddr);
|
|
ASSERTPtrInTCOrZero((PVOID)nativeAddr);
|
|
|
|
return nativeAddr;
|
|
}
|
|
ULONG CTRL_INDIR_RetnFrag16(PTHREADSTATE cpu)
|
|
{
|
|
ULONG intelAddr, nativeAddr;
|
|
|
|
POP_SHORT(intelAddr);
|
|
intelAddr &= 0x0000ffff;
|
|
eip = intelAddr;
|
|
POP_CALLSTACK(intelAddr,nativeAddr);
|
|
ASSERTPtrInTCOrZero((PVOID)nativeAddr);
|
|
|
|
return nativeAddr;
|
|
}
|
|
ULONG CTRL_INDIR_RetfFrag32(PTHREADSTATE cpu)
|
|
{
|
|
ULONG intelAddr, nativeAddr;
|
|
ULONG CSTemp;
|
|
|
|
POP_LONG(intelAddr);
|
|
POP_LONG(CSTemp);
|
|
|
|
eip = intelAddr;
|
|
CS = (USHORT)CSTemp;
|
|
POP_CALLSTACK(intelAddr,nativeAddr);
|
|
ASSERTPtrInTCOrZero((PVOID)nativeAddr);
|
|
|
|
return nativeAddr;
|
|
}
|
|
ULONG CTRL_INDIR_RetfFrag16(PTHREADSTATE cpu)
|
|
{
|
|
ULONG intelAddr, nativeAddr;
|
|
ULONG CSTemp;
|
|
|
|
POP_SHORT(intelAddr);
|
|
POP_SHORT(CSTemp);
|
|
intelAddr &= 0x0000ffff;
|
|
eip = intelAddr;
|
|
CS = (USHORT)CSTemp;
|
|
POP_CALLSTACK(intelAddr,nativeAddr);
|
|
ASSERTPtrInTCOrZero((PVOID)nativeAddr);
|
|
|
|
return nativeAddr;
|
|
}
|
|
ULONG CTRL_INDIR_Retn_iFrag32(PTHREADSTATE cpu, ULONG numBytes)
|
|
{
|
|
ULONG intelAddr, nativeAddr;
|
|
|
|
intelAddr = *(DWORD *)esp;
|
|
eip = intelAddr;
|
|
esp += numBytes+4;
|
|
POP_CALLSTACK(intelAddr,nativeAddr);
|
|
ASSERTPtrInTCOrZero((PVOID)nativeAddr);
|
|
|
|
return nativeAddr;
|
|
}
|
|
ULONG CTRL_INDIR_Retn_iFrag16(PTHREADSTATE cpu, ULONG numBytes)
|
|
{
|
|
ULONG intelAddr, nativeAddr;
|
|
|
|
intelAddr = *(USHORT *)esp;
|
|
eip = intelAddr;
|
|
esp += numBytes+2;
|
|
POP_CALLSTACK(intelAddr,nativeAddr);
|
|
ASSERTPtrInTCOrZero((PVOID)nativeAddr);
|
|
|
|
return nativeAddr;
|
|
}
|
|
ULONG CTRL_INDIR_Retf_iFrag32(PTHREADSTATE cpu, ULONG numBytes)
|
|
{
|
|
ULONG intelAddr, nativeAddr;
|
|
USHORT CSTemp;
|
|
|
|
intelAddr = *(DWORD *)esp;
|
|
CSTemp = *(USHORT *)(esp+sizeof(ULONG));
|
|
eip = intelAddr;
|
|
CS = CSTemp;
|
|
esp += numBytes+sizeof(ULONG)+sizeof(ULONG);
|
|
POP_CALLSTACK(intelAddr,nativeAddr);
|
|
ASSERTPtrInTCOrZero((PVOID)nativeAddr);
|
|
|
|
return nativeAddr;
|
|
}
|
|
ULONG CTRL_INDIR_Retf_iFrag16(PTHREADSTATE cpu, ULONG numBytes)
|
|
{
|
|
ULONG intelAddr, nativeAddr;
|
|
USHORT CSTemp;
|
|
|
|
intelAddr = *(USHORT *)esp;
|
|
CSTemp = *(USHORT *)(esp+sizeof(USHORT));
|
|
eip = intelAddr;
|
|
CS = CSTemp;
|
|
esp += numBytes+sizeof(USHORT)+sizeof(USHORT);
|
|
POP_CALLSTACK(intelAddr,nativeAddr);
|
|
ASSERTPtrInTCOrZero((PVOID)nativeAddr);
|
|
|
|
return nativeAddr;
|
|
}
|