You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.4 KiB
94 lines
2.4 KiB
10 months ago
|
// Copyright (C) 2003, Matt Conover (mconover@gmail.com)
|
||
|
#include "cpu.h"
|
||
|
#include <assert.h>
|
||
|
|
||
|
// NOTE: this assumes default scenarios (i.e., we assume CS/DS/ES/SS and flat
|
||
|
// and all have a base of 0 and limit of 0xffffffff, we don't try to verify
|
||
|
// that in the GDT)
|
||
|
//
|
||
|
// TODO: use inline assembly to get selector for segment
|
||
|
// Segment = x86 segment register (SEG_ES = 0, SEG_CS = 1, ...)
|
||
|
BYTE *GetAbsoluteAddressFromSegment(BYTE Segment, DWORD Offset)
|
||
|
{
|
||
|
switch (Segment)
|
||
|
{
|
||
|
// Windows uses a flat address space (except FS for x86 and GS for x64)
|
||
|
case 0: // SEG_ES
|
||
|
case 1: // SEG_CS
|
||
|
case 2: // SEG_SS
|
||
|
case 3: // SEG_DS
|
||
|
return (BYTE *)(DWORD_PTR)Offset;
|
||
|
case 4: // SEG_FS
|
||
|
case 5: // SEG_GS
|
||
|
return (BYTE *)(DWORD_PTR)Offset;
|
||
|
// Note: we're really supposed to do this, but get_teb is not implemented
|
||
|
// in this bastardized version of the disassembler.
|
||
|
// return (BYTE *)get_teb() + Offset;
|
||
|
default:
|
||
|
assert(0);
|
||
|
return (BYTE *)(DWORD_PTR)Offset;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// This is an GDT/LDT selector (pGDT+Selector)
|
||
|
BYTE *GetAbsoluteAddressFromSelector(WORD Selector, DWORD Offset)
|
||
|
{
|
||
|
DESCRIPTOR_ENTRY Entry;
|
||
|
GATE_ENTRY *Gate;
|
||
|
ULONG_PTR Base;
|
||
|
|
||
|
assert(Selector < 0x10000);
|
||
|
if (!GetThreadSelectorEntry(GetCurrentThread(), Selector, (LDT_ENTRY *)&Entry)) return NULL;
|
||
|
if (!Entry.Present) return NULL;
|
||
|
if (Entry.System)
|
||
|
{
|
||
|
Base = 0;
|
||
|
#ifdef _WIN64
|
||
|
Base |= (ULONG_PTR)Entry.HighOffset64 << 32;
|
||
|
#endif
|
||
|
Base |= Entry.BaseHi << 24;
|
||
|
Base |= Entry.BaseMid << 16;
|
||
|
Base |= Entry.BaseLow;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
switch (Entry.Type)
|
||
|
{
|
||
|
case 1: // 16-bit TSS (available)
|
||
|
case 2: // LDT
|
||
|
case 3: // 16-bit TSS (busy)
|
||
|
case 9: // 32-bit TSS (available)
|
||
|
case 11: // 32-bit TSS (busy)
|
||
|
Base = 0;
|
||
|
#ifdef _WIN64
|
||
|
Base |= (ULONG_PTR)Entry.HighOffset64 << 32;
|
||
|
#endif
|
||
|
Base |= Entry.BaseHi << 24;
|
||
|
Base |= Entry.BaseMid << 16;
|
||
|
Base |= Entry.BaseLow;
|
||
|
break;
|
||
|
|
||
|
case 4: // 16-bit call gate
|
||
|
case 5: // task gate
|
||
|
case 6: // 16-bit interrupt gate
|
||
|
case 7: // 16-bit task gate
|
||
|
case 12: // 32-bit call gate
|
||
|
case 14: // 32-bit interrupt gate
|
||
|
case 15: // 32-bit trap gate
|
||
|
Gate = (GATE_ENTRY *)&Entry;
|
||
|
#ifdef _WIN64
|
||
|
Base = ((ULONG_PTR)Gate->HighOffset64 << 32) | (Gate->HighOffset << 16) | Gate->LowOffset;
|
||
|
#else
|
||
|
Base = (Gate->HighOffset << 16) | Gate->LowOffset;
|
||
|
#endif
|
||
|
assert(!Offset); Offset = 0;
|
||
|
break;
|
||
|
default:
|
||
|
assert(0);
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
return (BYTE *)Base + Offset;
|
||
|
}
|
||
|
|