Source code of Windows XP (NT5)
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.

214 lines
5.5 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. selector.c
  5. Abstract:
  6. This module allows the host side of the kernel debugger to look up
  7. selector values in the GDT and LDT of the target machine.
  8. Author:
  9. John Vert (jvert) 10-Jun-1991
  10. Revision History:
  11. Wesley Witt (wesw) 26-Aug-1993 (ported to WinDbg)
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. #include "i386.h"
  16. #define SELECTOR_CACHE_LENGTH 6
  17. typedef struct _sc {
  18. struct _sc *nextYoungest;
  19. struct _sc *nextOldest;
  20. USHORT processor;
  21. DESCRIPTOR_TABLE_ENTRY_X86 desc;
  22. } SELCACHEENTRY;
  23. SELCACHEENTRY SelectorCache[SELECTOR_CACHE_LENGTH], *selYoungest, *selOldest;
  24. BOOL fInitialized = FALSE;
  25. void
  26. InitSelCache(void)
  27. {
  28. int i;
  29. for(i=0;i<SELECTOR_CACHE_LENGTH;i++){
  30. SelectorCache[i].nextYoungest = &SelectorCache[i+1];
  31. SelectorCache[i].nextOldest = &SelectorCache[i-1];
  32. SelectorCache[i].processor = (USHORT)-1;
  33. SelectorCache[i].desc.Selector = 0;
  34. }
  35. SelectorCache[--i].nextYoungest = NULL;
  36. SelectorCache[0].nextOldest = NULL;
  37. selYoungest = &SelectorCache[i];
  38. selOldest = &SelectorCache[0];
  39. }
  40. BOOLEAN
  41. FindSelector(USHORT Processor, PDESCRIPTOR_TABLE_ENTRY_X86 pdesc)
  42. {
  43. int i;
  44. for(i=0;i<SELECTOR_CACHE_LENGTH;i++) {
  45. if (SelectorCache[i].desc.Selector == pdesc->Selector &&
  46. SelectorCache[i].processor == Processor) {
  47. *pdesc = SelectorCache[i].desc;
  48. return TRUE;
  49. }
  50. }
  51. return FALSE;
  52. }
  53. void
  54. PutSelector(USHORT Processor, PDESCRIPTOR_TABLE_ENTRY_X86 pdesc)
  55. {
  56. selOldest->desc = *pdesc;
  57. selOldest->processor = Processor;
  58. (selOldest->nextYoungest)->nextOldest = NULL;
  59. selOldest->nextOldest = selYoungest;
  60. selYoungest->nextYoungest= selOldest;
  61. selYoungest = selOldest;
  62. selOldest = selOldest->nextYoungest;
  63. }
  64. NTSTATUS
  65. LookupSelector(
  66. IN USHORT Processor,
  67. IN OUT PDESCRIPTOR_TABLE_ENTRY_X86 pDescriptorTableEntry
  68. )
  69. /*++
  70. Routine Description:
  71. Looks up a selector in the GDT or LDT on the host machine.
  72. Arguments:
  73. Processor - Supplies the processor whose selector is desired.
  74. pDescriptorTableEntry->Selector - Supplies value of the selector to
  75. be looked up.
  76. pDescriptorTableEntry->Descriptor - Returns descriptor
  77. Return Value:
  78. STATUS_SUCCESS - The selector was found in the GDT or LDT, and the
  79. Descriptor field pointed to by pDescriptorTableEntry
  80. has been filled in with valid data.
  81. STATUS_UNSUCCESSFUL - The selector's descriptor could not be read from
  82. virtual memory. (Page is invalid or not present)
  83. STATUS_INVALID_PARAMETER - The selector was not in the GDT or LDT,
  84. and the Descriptor field is invalid.
  85. --*/
  86. {
  87. ULONG64 Address;
  88. ULONG TableBase=0;
  89. USHORT TableLimit=0;
  90. ULONG Result;
  91. ULONG Index;
  92. ULONG Off;
  93. LDT_ENTRY_X86 Descriptor;
  94. if (!fInitialized) {
  95. fInitialized = TRUE;
  96. InitSelCache();
  97. }
  98. if (FindSelector(Processor, pDescriptorTableEntry)) {
  99. return(STATUS_SUCCESS);
  100. }
  101. //
  102. // Fetch the address and limit of the GDT
  103. //
  104. if (GetFieldOffset("KPROCESSOR_STATE", "SpecialRegisters.Gdtr.Base", &Off)) {
  105. dprintf("Cannot find KPROCESSOR_STATE type\n");
  106. return(STATUS_INVALID_PARAMETER);
  107. }
  108. Address = Off;
  109. ReadControlSpace64((USHORT)Processor, Address,
  110. &TableBase, sizeof(TableBase));
  111. if (!TableBase) {
  112. return STATUS_INVALID_PARAMETER;
  113. }
  114. GetFieldOffset("KPROCESSOR_STATE", "SpecialRegisters.Gdtr.Limit", &Off);
  115. Address = Off;
  116. ReadControlSpace64((USHORT)Processor, Address,
  117. &TableLimit, sizeof(TableLimit));
  118. //
  119. // Find out whether this is a GDT or LDT selector
  120. //
  121. if (pDescriptorTableEntry->Selector & 0x4) {
  122. //
  123. // This is an LDT selector, so we reload the TableBase and TableLimit
  124. // with the LDT's Base & Limit by loading the descriptor for the
  125. // LDT selector.
  126. //
  127. ReadMemory((ULONG64) (LONG64) (LONG) (TableBase)+KGDT_LDT_I386,&Descriptor,
  128. sizeof(Descriptor),&Result);
  129. TableBase = ((ULONG)Descriptor.BaseLow +
  130. ((ULONG)Descriptor.HighWord.Bits.BaseMid << 16) +
  131. ((ULONG)Descriptor.HighWord.Bytes.BaseHi << 24));
  132. TableLimit = Descriptor.LimitLow; // LDT can't be > 64k
  133. if(Descriptor.HighWord.Bits.Granularity == GRAN_PAGE) {
  134. //
  135. // I suppose it's possible, although strange to have an
  136. // LDT with page granularity.
  137. //
  138. TableLimit <<= PAGE_SHIFT_X86;
  139. }
  140. }
  141. Index = (USHORT)(pDescriptorTableEntry->Selector) & ~0x7;
  142. // Irrelevant bits
  143. //
  144. // Check to make sure that the selector is within the table bounds
  145. //
  146. if (Index >= TableLimit) {
  147. //
  148. // Selector is out of table's bounds
  149. //
  150. return(STATUS_INVALID_PARAMETER);
  151. }
  152. ReadMemory((ULONG64) (LONG64) (LONG) TableBase+Index,
  153. &(pDescriptorTableEntry->Descriptor),
  154. sizeof(pDescriptorTableEntry->Descriptor),
  155. &Result);
  156. if(Result != sizeof(pDescriptorTableEntry->Descriptor)) {
  157. return(STATUS_UNSUCCESSFUL);
  158. }
  159. PutSelector(Processor, pDescriptorTableEntry);
  160. return(STATUS_SUCCESS);
  161. }