// Copyright (C) 2003, Matt Conover (mconover@gmail.com) #include "cpu.h" #include // 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; }