Leaked source code of windows server 2003
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.

392 lines
7.6 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. entrypt.c
  5. Abstract:
  6. This module stores the Entry Point structures, and retrieves them
  7. given either an intel address or a native address.
  8. Author:
  9. 16-Jun-1995 t-orig
  10. Revision History:
  11. 24-Aug-1999 [askhalid] copied from 32-bit wx86 directory and make work for 64bit.
  12. --*/
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <windows.h>
  17. #include "cpuassrt.h"
  18. #include "entrypt.h"
  19. #include "wx86.h"
  20. #include "redblack.h"
  21. #include "mrsw.h"
  22. ASSERTNAME;
  23. //
  24. // Count of modifications made to the ENTRYPOINT tree. Useful for code
  25. // which unlocks the Entrypoint MRSW object and needs to see if another thread
  26. // has invalidated the ENTRYPOINT tree or not.
  27. //
  28. DWORD EntrypointTimestamp;
  29. EPNODE _NIL;
  30. PEPNODE NIL=&_NIL;
  31. PEPNODE intelRoot=&_NIL;
  32. #if DBG_DUAL_TREES
  33. PEPNODE dualRoot=&_NIL;
  34. #endif
  35. #if DBG_DUAL_TREES
  36. VOID
  37. VerifySubTree(
  38. PEPNODE intelEP,
  39. PEPNODE dualEP
  40. )
  41. {
  42. CPUASSERT(intelEP != NILL || dualEP == NIL);
  43. CPUASSERT(intelEP->dual == dualEP);
  44. CPUASSERT(dualEP->dual == intelEP);
  45. CPUASSERT(intelEP->ep.intelStart == dualEP->ep.intelStart);
  46. CPUASSERT(intelEP->ep.intelEnd == dualEP->ep.intelEnd);
  47. CPUASSERT(intelEP->ep.nativeStart == dualEP->ep.nativeStart);
  48. CPUASSERT(intelEP->intelColor == dualEP->intelColor);
  49. VerifySubTree(intelEP->intelLeft, dualEP->intelLeft);
  50. VerifySubTree(intelEP->intelRight, dualEP->intelRight);
  51. }
  52. VOID
  53. VerifyTrees(
  54. VOID
  55. )
  56. {
  57. VerifySubTree(intelRoot, dualRoot);
  58. }
  59. #endif
  60. #ifdef PROFILE
  61. void StartCAP(void);
  62. #endif
  63. INT
  64. initializeEntryPointModule(
  65. void
  66. )
  67. /*++
  68. Routine Description:
  69. Initializes the entry point module by allocating initial dll tables.
  70. Should be called once for each process (thus this need not be called
  71. by each thread).
  72. Arguments:
  73. none
  74. Return Value:
  75. return-value - 1 for success, 0 for failure
  76. --*/
  77. {
  78. NIL->intelLeft = NIL->intelRight = NIL->intelParent = NIL;
  79. NIL->intelColor = BLACK;
  80. #ifdef PROFILE
  81. StartCAP();
  82. #endif
  83. return 1;
  84. }
  85. INT
  86. insertEntryPoint(
  87. PEPNODE pNewEntryPoint
  88. )
  89. /*++
  90. Routine Description:
  91. Inserts the entry point structure into the correct red/black trees
  92. (both intel and native)
  93. Arguments:
  94. pNewEntryPoint - A pointer to the entry point structure to be inserted
  95. into the trees
  96. Return Value:
  97. return-value - 1 - Success
  98. 0 - No entry for that region of memory
  99. -1 -- There's a problem with the entry point table
  100. --*/
  101. {
  102. #if DBG_DUAL_TREES
  103. PEPNODE pdualNewEntryPoint = malloc(sizeof(EPNODE));
  104. memcpy(pdualNewEntryPoint, pNewEntryPoint, sizeof(EPNODE));
  105. #endif
  106. intelRoot = insertNodeIntoIntelTree (intelRoot,
  107. pNewEntryPoint,
  108. NIL);
  109. #if DBG_DUAL_TREES
  110. dualRoot = insertNodeIntoIntelTree (dualRoot,
  111. pdualNewEntryPoint,
  112. NIL);
  113. pdualNewEntryPoint->dual = pNewEntryPoint;
  114. pNewEntryPoint->dual = pdualNewEntryPoint;
  115. VerifyTrees();
  116. #endif
  117. //
  118. // Bump the timestamp
  119. //
  120. EntrypointTimestamp++;
  121. return 1;
  122. }
  123. #if 0 // dead code, but keep it around in case we decide we want it later.
  124. INT
  125. removeEntryPoint(
  126. PEPNODE pEP
  127. )
  128. /*++
  129. Routine Description:
  130. Removes an entry point structure from both the intel and native
  131. red/black trees
  132. Arguments:
  133. pEP - A pointer to the entry point structure to be removed
  134. Return Value:
  135. return-value - 1 - Success
  136. 0 - No entry for that region of memory
  137. -1 -- There's a problem with the entry point table
  138. --*/
  139. {
  140. intelRoot = intelRBDelete (intelRoot,
  141. pEP,
  142. NIL);
  143. #if DBG_DUAL_TREES
  144. CPUASSERT(pEP->dual->dual == pEP);
  145. dualRoot = intelRBDelete(dualRoot,
  146. pEP->dual,
  147. NIL);
  148. free(pEP->dual);
  149. pEP->dual = NULL;
  150. VerifyTrees();
  151. #endif
  152. EntrypointTimestamp++;
  153. return 1;
  154. }
  155. #endif // 0
  156. PENTRYPOINT
  157. EPFromIntelAddr(
  158. PVOID intelAddr
  159. )
  160. /*++
  161. Routine Description:
  162. Retrieves an entry point structure containing the given intel address
  163. Arguments:
  164. intelAddr - The intel address contained within the code corresponding to
  165. the entry point structure
  166. Return Value:
  167. return-value - The entry point structure if found, NULL otherwise.
  168. --*/
  169. {
  170. PENTRYPOINT EP;
  171. PEPNODE pEPNode;
  172. pEPNode = findIntel(intelRoot, intelAddr, NIL);
  173. if (!pEPNode) {
  174. //
  175. // No EPNODE contains the address
  176. //
  177. return NULL;
  178. }
  179. //
  180. // The ENTRYPOINT inside the EPNODE contains the address. Search
  181. // for an ENTRYPOINT which matches that address exactly.
  182. //
  183. EP = &pEPNode->ep;
  184. do {
  185. if (EP->intelStart == intelAddr) {
  186. //
  187. // Found a sub-Entrypoint whose Intel address exactly matches
  188. // the one we were looking for.
  189. //
  190. return EP;
  191. }
  192. EP=EP->SubEP;
  193. } while (EP);
  194. //
  195. // The EPNODE in the Red-black tree contains the Intel address, but
  196. // no sub-Entrypoint exactly describes the Intel address.
  197. //
  198. return &pEPNode->ep;
  199. }
  200. PENTRYPOINT
  201. GetNextEPFromIntelAddr(
  202. PVOID intelAddr
  203. )
  204. /*++
  205. Routine Description:
  206. Retrieves the entry point following
  207. Arguments:
  208. intelAddr - The intel address contained within the code corresponding to
  209. the entry point structure
  210. Return Value:
  211. A pointer to the first EntryPoint which follows a particular Intel Address.
  212. --*/
  213. {
  214. PEPNODE pEP;
  215. #if DBG_DUAL_TREES
  216. PEPNODE pDual;
  217. #endif
  218. pEP = findIntelNext (intelRoot, intelAddr, NIL);
  219. #if DBG_DUAL_TREES
  220. pDual = findIntelNext(dualRoot, intelAddr, NIL);
  221. CPUASSERT((pDual==NULL && pEP==NULL) ||
  222. (pDual->dual == pEP));
  223. VerifyTrees();
  224. #endif
  225. return &pEP->ep;
  226. }
  227. BOOLEAN
  228. IsIntelRangeInCache(
  229. PVOID Addr,
  230. DWORD Length
  231. )
  232. /*++
  233. Routine Description:
  234. Determines if any entrypoints are contained within a range of memory.
  235. Used to determine if the Translation Cache must be flushed.
  236. Must be called with either EP write or read lock.
  237. Arguments:
  238. None
  239. Return Value:
  240. None
  241. --*/
  242. {
  243. BOOLEAN fContains;
  244. if (intelRoot == NIL) {
  245. //
  246. // Empty tree - no need to flush
  247. //
  248. return FALSE;
  249. }
  250. fContains = intelContainsRange(intelRoot,
  251. NIL,
  252. Addr,
  253. (PVOID)((ULONGLONG)Addr + Length)
  254. );
  255. return fContains;
  256. }
  257. VOID
  258. FlushEntrypoints(
  259. VOID
  260. )
  261. /*++
  262. Routine Description:
  263. Quickly deletes all entrypoints. Called by the Translation Cache when
  264. the cache is flushed.
  265. Arguments:
  266. None
  267. Return Value:
  268. None
  269. --*/
  270. {
  271. if (intelRoot != NIL) {
  272. //
  273. // Delete the heap containing all entrypoints in the tree
  274. //
  275. EPFree();
  276. //
  277. // Reset the root of the tree
  278. //
  279. intelRoot = NIL;
  280. #if DBG_DUAL_TREES
  281. dualRoot = NIL;
  282. #endif
  283. //
  284. // Bump the timestamp
  285. //
  286. EntrypointTimestamp++;
  287. }
  288. }