singrdk/base/Kernel/Native/PEImage.cpp

199 lines
5.4 KiB
C++
Raw Permalink Normal View History

2008-03-05 09:52:00 -05:00
////////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: PEImage.cpp
//
2008-11-17 18:29:00 -05:00
// Note: Kernel Only
2008-03-05 09:52:00 -05:00
//
#include "hal.h"
//////////////////////////////////////////////////////////////// Image Loader.
//
#if PAGING
extern int syscallEntryTable[];
struct AbiStackHead
{
uintptr prevBegin;
uintptr prevLimit;
uintptr esp;
};
int FakeSyscallBegin(int abiIndex)
{
// TODO: validate abiIndex, set fs, etc.
return syscallEntryTable[abiIndex];
}
// TODO: these cannot be functions; we cannot trust the user stack
uintptr PushAbiStack(uintptr esp)
{
2008-11-17 18:29:00 -05:00
Struct_Microsoft_Singularity_ThreadContext * context =
2008-03-05 09:52:00 -05:00
Class_Microsoft_Singularity_Processor::g_GetCurrentThreadContext();
AbiStackHead *head = (AbiStackHead *)(context->abiStackHead);
head->prevBegin = context->stackBegin;
head->prevLimit = context->stackLimit;
head->esp = esp;
context->stackBegin = context->abiStackBegin;
context->stackLimit = context->abiStackLimit;
return uintptr(head);
}
uintptr PopAbiStack(AbiStackHead *head)
{
2008-11-17 18:29:00 -05:00
Struct_Microsoft_Singularity_ThreadContext * context =
2008-03-05 09:52:00 -05:00
Class_Microsoft_Singularity_Processor::g_GetCurrentThreadContext();
// HACK: if the ABI call changed stackBegin/stackLimit, keep the changes
// (otherwise, switch back to original stack)
if (context->stackBegin == context->abiStackBegin) {
context->stackBegin = head->prevBegin;
context->stackLimit = head->prevLimit;
}
return head->esp;
}
2008-11-17 18:29:00 -05:00
//#define SEGMENT_SELECTOR(s) \
// (uint16)(offsetof(Struct_Microsoft_Singularity_CpuInfo,s) \
// - offsetof(Struct_Microsoft_Singularity_CpuInfo,GdtNull))
//const uint16 ourFs = SEGMENT_SELECTOR(GdtPF);
2008-03-05 09:52:00 -05:00
__declspec(naked) void FakeSyscall()
{
__asm
{
#if 0
push ecx
push edx
call AbiStackSegment
pop edx
pop ecx
mov esp, eax // TODO: must set stackBase, stackLimit
push edx
call FakeSyscallBegin
mov edx, eax
mov eax, [esp] // eax = pointer to arg1
call edx
pop ecx // ecx = pointer to arg1
sub ecx, 4 // ecx = pointer to return address
mov esp, ecx
ret 8
#else
// user stack = ret arg1 arg2 ret arg3 ... argn ...
// ecx = ABI index
// edx = pointer to arg1
push ecx
push edx
mov ecx, edx
sub ecx, 4 // 1 word for return address
call PushAbiStack
pop edx
pop ecx
mov esp, eax
/// mov eax, edx
/// sub eax, 4 // 1 word for return address
/// mov esp, eax
sti
mov ax, ss
mov ds, ax // Copy stack segment selector to DS so we can access memory!
mov es, ax // Copy stack segment selector to ES so we can access memory!
// push (offsetof(Struct_Microsoft_Singularity_CpuInfo,GdtPF) - offsetof(Struct_Microsoft_Singularity_CpuInfo,GdtNull))
// push ourFs
// pop fs
mov ax, 0x38 // TODO: no more hexadecimal constants
mov fs, ax
// push fs;
// pop fs; // refresh fs (TODO: don't trust user's fs)
push edx
call FakeSyscallBegin
mov edx, eax
pop eax // pointer to arg1
// user stack = ret arg1 arg2 ret arg3 ... argn ...
call edx
2008-11-17 18:29:00 -05:00
call Class_Microsoft_Singularity_Isal_Isa::g_EnterUserMode
2008-03-05 09:52:00 -05:00
// Any changes here must be reflected in EnterRing0
mov ecx, esp
push eax
push edx
call PopAbiStack
mov ecx, eax
pop edx
pop eax
mov esp, ecx
ret 8
#endif
}
}
__declspec(naked) void EnterRing0()
{
__asm
{
add esp, 4 // discard return address (pointing to FakeSyscall)
// Copied from FakeSyscall epilog:
mov ecx, esp
push eax
push edx
call PopAbiStack
mov ecx, eax
pop edx
pop eax
mov esp, ecx
ret 8
}
}
#endif // PAGING
int32 Class_Microsoft_Singularity_Loader_PEImage::
g_HalCallEntryPoint(UIntPtr entry, int threadIndex, bool runAtRing3)
{
if (entry == 0) {
2008-11-17 18:29:00 -05:00
__debugbreak();
2008-03-05 09:52:00 -05:00
return -1;
}
#if PAGING
if (runAtRing3) {
2008-11-17 18:29:00 -05:00
Class_Microsoft_Singularity_Isal_Isa::g_EnterUserMode();
2008-03-05 09:52:00 -05:00
}
#else
Assert(!runAtRing3);
#endif
int32 retval = (( int32 (__fastcall *)(int32))entry)(threadIndex);
#if PAGING
if (runAtRing3) {
// We should still be running at ring-3 when the process unwinds
2008-11-17 18:29:00 -05:00
Assert(Class_Microsoft_Singularity_Isal_Isa::g_IsInUserMode());
2008-03-05 09:52:00 -05:00
// Call ABI zero, which drops us to ring-0. Why is this not
// a gaping security hole? The kernel should verify that this
// request only ever comes from its own (trusted) code (i.e.,
// right here).
__asm {
mov ecx, 0
push ecx
push ecx
mov edx, esp
push done
_emit 0x0f
_emit 0x34 //sysenter
done:
}
}
#endif
return retval;
}
//
///////////////////////////////////////////////////////////////// End of File.