ThreadContextInfo.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "RuntimeBasePch.h"
  6. // Originally defined in ntstatus.h, define here because including windows.h (via PCH
  7. // above) with ntstatus.h causes macro redefinition errors for the common errors defined
  8. // in both header files.
  9. #define STATUS_PROCESS_IS_TERMINATING ((NTSTATUS)0xC000010AL)
  10. #if ENABLE_NATIVE_CODEGEN
  11. #include "CodeGenAllocators.h"
  12. #include "ServerThreadContext.h"
  13. #endif
  14. #if defined(_UCRT) && _CONTROL_FLOW_GUARD
  15. #include <cfguard.h>
  16. #endif
  17. ThreadContextInfo::ThreadContextInfo() :
  18. m_isAllJITCodeInPreReservedRegion(true),
  19. m_isClosed(false)
  20. {
  21. for (int i = 0; i <= WellKnownHostType_Last; ++i)
  22. {
  23. wellKnownHostTypeIds[i] = Js::TypeIds_Undefined;
  24. }
  25. }
  26. #if ENABLE_NATIVE_CODEGEN
  27. intptr_t
  28. ThreadContextInfo::GetNullFrameDisplayAddr() const
  29. {
  30. return ShiftAddr(this, &Js::NullFrameDisplay);
  31. }
  32. intptr_t
  33. ThreadContextInfo::GetStrictNullFrameDisplayAddr() const
  34. {
  35. return ShiftAddr(this, &Js::StrictNullFrameDisplay);
  36. }
  37. intptr_t
  38. ThreadContextInfo::GetAbsDoubleCstAddr() const
  39. {
  40. return ShiftAddr(this, &Js::JavascriptNumber::AbsDoubleCst);
  41. }
  42. intptr_t
  43. ThreadContextInfo::GetAbsFloatCstAddr() const
  44. {
  45. return ShiftAddr(this, &Js::JavascriptNumber::AbsFloatCst);
  46. }
  47. intptr_t ThreadContextInfo::GetSgnFloatBitCst() const
  48. {
  49. return ShiftAddr(this, &Js::JavascriptNumber::SgnFloatBitCst);
  50. }
  51. intptr_t ThreadContextInfo::GetSgnDoubleBitCst() const
  52. {
  53. return ShiftAddr(this, &Js::JavascriptNumber::SgnDoubleBitCst);
  54. }
  55. intptr_t
  56. ThreadContextInfo::GetMaskNegFloatAddr() const
  57. {
  58. return ShiftAddr(this, &Js::JavascriptNumber::MaskNegFloat);
  59. }
  60. intptr_t
  61. ThreadContextInfo::GetMaskNegDoubleAddr() const
  62. {
  63. return ShiftAddr(this, &Js::JavascriptNumber::MaskNegDouble);
  64. }
  65. intptr_t
  66. ThreadContextInfo::GetUIntConvertConstAddr() const
  67. {
  68. return ShiftAddr(this, &Js::JavascriptNumber::UIntConvertConst);
  69. }
  70. intptr_t
  71. ThreadContextInfo::GetUint8ClampedArraySetItemAddr() const
  72. {
  73. return ShiftAddr(this, (BOOL(*)(Js::Uint8ClampedArray * arr, uint32 index, Js::Var value))&Js::Uint8ClampedArray::DirectSetItem);
  74. }
  75. intptr_t
  76. ThreadContextInfo::GetConstructorCacheDefaultInstanceAddr() const
  77. {
  78. return ShiftAddr(this, &Js::ConstructorCache::DefaultInstance);
  79. }
  80. intptr_t
  81. ThreadContextInfo::GetJavascriptObjectNewInstanceAddr() const
  82. {
  83. return ShiftAddr(this, &Js::JavascriptObject::EntryInfo::NewInstance);
  84. }
  85. intptr_t
  86. ThreadContextInfo::GetJavascriptArrayNewInstanceAddr() const
  87. {
  88. return ShiftAddr(this, &Js::JavascriptArray::EntryInfo::NewInstance);
  89. }
  90. intptr_t
  91. ThreadContextInfo::GetDoubleOnePointZeroAddr() const
  92. {
  93. return ShiftAddr(this, &Js::JavascriptNumber::ONE_POINT_ZERO);
  94. }
  95. intptr_t
  96. ThreadContextInfo::GetDoublePointFiveAddr() const
  97. {
  98. return ShiftAddr(this, &Js::JavascriptNumber::k_PointFive);
  99. }
  100. intptr_t
  101. ThreadContextInfo::GetFloatPointFiveAddr() const
  102. {
  103. return ShiftAddr(this, &Js::JavascriptNumber::k_Float32PointFive);
  104. }
  105. intptr_t
  106. ThreadContextInfo::GetDoubleNegPointFiveAddr() const
  107. {
  108. return ShiftAddr(this, &Js::JavascriptNumber::k_NegPointFive);
  109. }
  110. intptr_t
  111. ThreadContextInfo::GetFloatNegPointFiveAddr() const
  112. {
  113. return ShiftAddr(this, &Js::JavascriptNumber::k_Float32NegPointFive);
  114. }
  115. intptr_t
  116. ThreadContextInfo::GetDoubleNegOneAddr() const
  117. {
  118. return ShiftAddr(this, &Js::JavascriptNumber::k_NegOne);
  119. }
  120. intptr_t
  121. ThreadContextInfo::GetDoubleTwoToFractionAddr() const
  122. {
  123. return ShiftAddr(this, &Js::JavascriptNumber::k_TwoToFraction);
  124. }
  125. intptr_t
  126. ThreadContextInfo::GetFloatTwoToFractionAddr() const
  127. {
  128. return ShiftAddr(this, &Js::JavascriptNumber::k_Float32TwoToFraction);
  129. }
  130. intptr_t
  131. ThreadContextInfo::GetDoubleNegTwoToFractionAddr() const
  132. {
  133. return ShiftAddr(this, &Js::JavascriptNumber::k_NegTwoToFraction);
  134. }
  135. intptr_t
  136. ThreadContextInfo::GetDoubleNaNAddr() const
  137. {
  138. return ShiftAddr(this, &Js::JavascriptNumber::k_Nan);
  139. }
  140. intptr_t
  141. ThreadContextInfo::GetDoubleUintMaxPlusOneAddr() const
  142. {
  143. return ShiftAddr(this, &Js::JavascriptNumber::k_UintMaxPlusOne);
  144. }
  145. intptr_t
  146. ThreadContextInfo::GetDoubleIntMaxPlusOneAddr() const
  147. {
  148. return ShiftAddr(this, &Js::JavascriptNumber::k_IntMaxPlusOne);
  149. }
  150. intptr_t
  151. ThreadContextInfo::GetDoubleIntMinMinusOneAddr() const
  152. {
  153. return ShiftAddr(this, &Js::JavascriptNumber::k_MinIntMinusOne);
  154. }
  155. intptr_t
  156. ThreadContextInfo::GetFloatNaNAddr() const
  157. {
  158. return ShiftAddr(this, &Js::JavascriptNumber::k_Nan32);
  159. }
  160. intptr_t
  161. ThreadContextInfo::GetFloatNegTwoToFractionAddr() const
  162. {
  163. return ShiftAddr(this, &Js::JavascriptNumber::k_Float32NegTwoToFraction);
  164. }
  165. intptr_t
  166. ThreadContextInfo::GetDoubleZeroAddr() const
  167. {
  168. return ShiftAddr(this, &Js::JavascriptNumber::k_Zero);
  169. }
  170. intptr_t
  171. ThreadContextInfo::GetFloatZeroAddr() const
  172. {
  173. return ShiftAddr(this, &Js::JavascriptNumber::k_Float32Zero);
  174. }
  175. intptr_t
  176. ThreadContextInfo::GetNativeFloatArrayMissingItemAddr() const
  177. {
  178. return ShiftAddr(this, &Js::JavascriptNativeFloatArray::MissingItem);
  179. }
  180. intptr_t
  181. ThreadContextInfo::GetExponentMaskAddr() const
  182. {
  183. return ShiftAddr(this, &Js::Constants::ExponentMask);
  184. }
  185. intptr_t
  186. ThreadContextInfo::GetMantissaMaskAddr() const
  187. {
  188. return ShiftAddr(this, &Js::Constants::MantissaMask);
  189. }
  190. #if _M_IX86 || _M_AMD64
  191. intptr_t
  192. ThreadContextInfo::GetX86AbsMaskF4Addr() const
  193. {
  194. return ShiftAddr(this, &X86_ABS_MASK_F4);
  195. }
  196. intptr_t
  197. ThreadContextInfo::GetX86AbsMaskD2Addr() const
  198. {
  199. return ShiftAddr(this, &X86_ABS_MASK_D2);
  200. }
  201. intptr_t
  202. ThreadContextInfo::GetX86NegMaskF4Addr() const
  203. {
  204. return ShiftAddr(this, &X86_NEG_MASK_F4);
  205. }
  206. intptr_t
  207. ThreadContextInfo::GetX86NegMaskD2Addr() const
  208. {
  209. return ShiftAddr(this, &X86_NEG_MASK_D2);
  210. }
  211. intptr_t
  212. ThreadContextInfo::GetX86AllNegOnesAddr() const
  213. {
  214. return ShiftAddr(this, &X86_ALL_NEG_ONES);
  215. }
  216. intptr_t
  217. ThreadContextInfo::GetX86AllNegOnesF4Addr() const
  218. {
  219. return ShiftAddr(this, &X86_ALL_NEG_ONES_F4);
  220. }
  221. intptr_t
  222. ThreadContextInfo::GetX86AllZerosAddr() const
  223. {
  224. return ShiftAddr(this, &X86_ALL_ZEROS);
  225. }
  226. intptr_t
  227. ThreadContextInfo::GetX86AllOnesF4Addr() const
  228. {
  229. return ShiftAddr(this, &X86_ALL_ONES_F4);
  230. }
  231. intptr_t
  232. ThreadContextInfo::GetX86LowBytesMaskAddr() const
  233. {
  234. return ShiftAddr(this, &X86_LOWBYTES_MASK);
  235. }
  236. intptr_t
  237. ThreadContextInfo::GetX86HighBytesMaskAddr() const
  238. {
  239. return ShiftAddr(this, &X86_HIGHBYTES_MASK);
  240. }
  241. intptr_t
  242. ThreadContextInfo::GetX86DoubleWordSignBitsAddr() const
  243. {
  244. return ShiftAddr(this, &X86_DWORD_SIGNBITS);
  245. }
  246. intptr_t
  247. ThreadContextInfo::GetX86WordSignBitsAddr() const
  248. {
  249. return ShiftAddr(this, &X86_WORD_SIGNBITS);
  250. }
  251. intptr_t
  252. ThreadContextInfo::GetX86ByteSignBitsAddr() const
  253. {
  254. return ShiftAddr(this, &X86_BYTE_SIGNBITS);
  255. }
  256. intptr_t
  257. ThreadContextInfo::GetX86TwoPower32F4Addr() const
  258. {
  259. return ShiftAddr(this, &X86_TWO_32_F4);
  260. }
  261. intptr_t
  262. ThreadContextInfo::GetX86TwoPower31F4Addr() const
  263. {
  264. return ShiftAddr(this, &X86_TWO_31_F4);
  265. }
  266. intptr_t
  267. ThreadContextInfo::GetX86TwoPower31I4Addr() const
  268. {
  269. return ShiftAddr(this, &X86_TWO_31_I4);
  270. }
  271. intptr_t
  272. ThreadContextInfo::GetX86NegTwoPower31F4Addr() const
  273. {
  274. return ShiftAddr(this, &X86_NEG_TWO_31_F4);
  275. }
  276. intptr_t
  277. ThreadContextInfo::GetX86FourLanesMaskAddr(uint8 minorityLane) const
  278. {
  279. return ShiftAddr(this, &X86_4LANES_MASKS[minorityLane]);
  280. }
  281. intptr_t
  282. ThreadContextInfo::GetDoubleIntMinAddr() const
  283. {
  284. return ShiftAddr(this, &Js::JavascriptNumber::DOUBLE_INT_MIN);
  285. }
  286. intptr_t
  287. ThreadContextInfo::GetDoubleTwoTo31Addr() const
  288. {
  289. return ShiftAddr(this, &Js::JavascriptNumber::DOUBLE_TWO_TO_31);
  290. }
  291. #endif
  292. intptr_t
  293. ThreadContextInfo::GetStringReplaceNameAddr() const
  294. {
  295. return ShiftAddr(this, Js::Constants::StringReplace);
  296. }
  297. intptr_t
  298. ThreadContextInfo::GetStringMatchNameAddr() const
  299. {
  300. return ShiftAddr(this, Js::Constants::StringMatch);
  301. }
  302. #endif
  303. bool
  304. ThreadContextInfo::IsAllJITCodeInPreReservedRegion() const
  305. {
  306. return m_isAllJITCodeInPreReservedRegion;
  307. }
  308. void
  309. ThreadContextInfo::ResetIsAllJITCodeInPreReservedRegion()
  310. {
  311. m_isAllJITCodeInPreReservedRegion = false;
  312. }
  313. #ifdef ENABLE_GLOBALIZATION
  314. #if defined(_CONTROL_FLOW_GUARD)
  315. Js::DelayLoadWinCoreProcessThreads *
  316. ThreadContextInfo::GetWinCoreProcessThreads()
  317. {
  318. m_delayLoadWinCoreProcessThreads.EnsureFromSystemDirOnly();
  319. return &m_delayLoadWinCoreProcessThreads;
  320. }
  321. Js::DelayLoadWinCoreMemory *
  322. ThreadContextInfo::GetWinCoreMemoryLibrary()
  323. {
  324. m_delayLoadWinCoreMemoryLibrary.EnsureFromSystemDirOnly();
  325. return &m_delayLoadWinCoreMemoryLibrary;
  326. }
  327. #endif
  328. bool
  329. ThreadContextInfo::IsCFGEnabled()
  330. {
  331. #if defined(_CONTROL_FLOW_GUARD)
  332. PROCESS_MITIGATION_CONTROL_FLOW_GUARD_POLICY CfgPolicy;
  333. m_delayLoadWinCoreProcessThreads.EnsureFromSystemDirOnly();
  334. BOOL isGetMitigationPolicySucceeded = m_delayLoadWinCoreProcessThreads.GetMitigationPolicyForProcess(
  335. GetCurrentProcess(),
  336. ProcessControlFlowGuardPolicy,
  337. &CfgPolicy,
  338. sizeof(CfgPolicy));
  339. Assert(isGetMitigationPolicySucceeded || !AutoSystemInfo::Data.IsCFGEnabled());
  340. return CfgPolicy.EnableControlFlowGuard && AutoSystemInfo::Data.IsCFGEnabled();
  341. #else
  342. return false;
  343. #endif // _CONTROL_FLOW_GUARD
  344. }
  345. #endif // ENABLE_GLOBALIZATION
  346. //Masking bits according to AutoSystemInfo::PageSize
  347. #define PAGE_START_ADDR(address) ((size_t)(address) & ~(size_t)(AutoSystemInfo::PageSize - 1))
  348. #define IS_16BYTE_ALIGNED(address) (((size_t)(address) & 0xF) == 0)
  349. #define OFFSET_ADDR_WITHIN_PAGE(address) ((size_t)(address) & (AutoSystemInfo::PageSize - 1))
  350. template <bool useFileAPI>
  351. void
  352. ThreadContextInfo::SetValidCallTargetInternal(
  353. _In_ PVOID callTargetAddress,
  354. _In_opt_ HANDLE fileHandle,
  355. _In_opt_ PVOID viewBase,
  356. bool isSetValid)
  357. {
  358. AnalysisAssert(!useFileAPI || fileHandle);
  359. AnalysisAssert(!useFileAPI || viewBase);
  360. #ifdef _CONTROL_FLOW_GUARD
  361. if (IsCFGEnabled())
  362. {
  363. #ifdef _M_ARM
  364. AssertMsg(((uintptr_t)callTargetAddress & 0x1) != 0, "on ARM we expect the thumb bit to be set on anything we use as a call target");
  365. AssertMsg(IS_16BYTE_ALIGNED((uintptr_t)callTargetAddress & ~0x1), "callTargetAddress is not 16-byte page aligned?");
  366. #else
  367. AssertMsg(IS_16BYTE_ALIGNED(callTargetAddress), "callTargetAddress is not 16-byte page aligned?");
  368. #endif
  369. // If SetProcessValidCallTargets is not allowed by global policy (e.g.
  370. // OOP JIT is in use in the client), then generate a fast fail
  371. // exception as state has been corrupted and attempt is being made to
  372. // illegally call SetProcessValidCallTargets.
  373. if (!GlobalSecurityPolicy::IsSetProcessValidCallTargetsAllowed())
  374. {
  375. RaiseFailFastException(nullptr, nullptr, FAIL_FAST_GENERATE_EXCEPTION_ADDRESS);
  376. }
  377. CFG_CALL_TARGET_INFO callTargetInfo[1];
  378. BOOL isCallTargetRegistrationSucceed;
  379. PVOID startAddr = nullptr;
  380. if (useFileAPI)
  381. {
  382. // Fall back to old CFG registration API, since new API seems broken
  383. SetValidCallTargetForCFG(callTargetAddress, isSetValid);
  384. return;
  385. #if 0
  386. Assert(JITManager::GetJITManager()->IsJITServer());
  387. size_t codeOffset = (uintptr_t)callTargetAddress - (uintptr_t)viewBase;
  388. size_t regionSize = codeOffset + 1;
  389. callTargetInfo[0].Offset = codeOffset;
  390. callTargetInfo[0].Flags = (isSetValid ? CFG_CALL_TARGET_VALID : 0);
  391. startAddr = viewBase;
  392. isCallTargetRegistrationSucceed = GetWinCoreMemoryLibrary()->SetProcessCallTargetsForMappedView(GetProcessHandle(), viewBase, regionSize, 1, callTargetInfo, fileHandle, 0);
  393. #if ENABLE_DEBUG_CONFIG_OPTIONS
  394. if (!isCallTargetRegistrationSucceed)
  395. {
  396. // Fall back to old CFG registration API for test builds, so that they can run on older OSes
  397. SetValidCallTargetForCFG(callTargetAddress, isSetValid);
  398. return;
  399. }
  400. #endif
  401. #endif
  402. }
  403. else
  404. {
  405. PVOID startAddressOfPage = (PVOID)(PAGE_START_ADDR(callTargetAddress));
  406. size_t codeOffset = OFFSET_ADDR_WITHIN_PAGE(callTargetAddress);
  407. callTargetInfo[0].Offset = codeOffset;
  408. callTargetInfo[0].Flags = (isSetValid ? CFG_CALL_TARGET_VALID : 0);
  409. startAddr = startAddressOfPage;
  410. AssertMsg((size_t)callTargetAddress - (size_t)startAddressOfPage <= AutoSystemInfo::PageSize - 1, "Only last bits corresponding to PageSize should be masked");
  411. AssertMsg((size_t)startAddressOfPage + (size_t)codeOffset == (size_t)callTargetAddress, "Wrong masking of address?");
  412. isCallTargetRegistrationSucceed = GetWinCoreMemoryLibrary()->SetProcessCallTargets(GetProcessHandle(), startAddressOfPage, AutoSystemInfo::PageSize, 1, callTargetInfo);
  413. }
  414. if (!isCallTargetRegistrationSucceed)
  415. {
  416. DWORD gle = GetLastError();
  417. if (gle == ERROR_COMMITMENT_LIMIT)
  418. {
  419. //Throw OOM, if there is not enough virtual memory for paging (required for CFG BitMap)
  420. Js::Throw::OutOfMemory();
  421. }
  422. else if (gle == ERROR_ACCESS_DENIED)
  423. {
  424. // When this error is set, the target process may be exiting and thus cannot proceed with
  425. // JIT output. Throw this exception to safely abort this call.
  426. throw Js::OperationAbortedException();
  427. }
  428. else
  429. {
  430. Js::Throw::InternalError();
  431. }
  432. }
  433. #if DBG
  434. if (isSetValid && !JITManager::GetJITManager()->IsOOPJITEnabled())
  435. {
  436. _GUARD_CHECK_ICALL((uintptr_t)callTargetAddress);
  437. }
  438. if (PHASE_TRACE1(Js::CFGPhase))
  439. {
  440. if (!isSetValid)
  441. {
  442. Output::Print(_u("DEREGISTER:"));
  443. }
  444. Output::Print(_u("CFGRegistration: StartAddr: 0x%p , Offset: 0x%x, TargetAddr: 0x%x \n"), (char*)startAddr, callTargetInfo[0].Offset, ((size_t)startAddr + (size_t)callTargetInfo[0].Offset));
  445. Output::Flush();
  446. }
  447. #endif
  448. }
  449. #endif // _CONTROL_FLOW_GUARD
  450. }
  451. void
  452. ThreadContextInfo::SetValidCallTargetFile(PVOID callTargetAddress, HANDLE fileHandle, PVOID viewBase, bool isSetValid)
  453. {
  454. ThreadContextInfo::SetValidCallTargetInternal<true>(callTargetAddress, fileHandle, viewBase, isSetValid);
  455. }
  456. void
  457. ThreadContextInfo::SetValidCallTargetForCFG(PVOID callTargetAddress, bool isSetValid)
  458. {
  459. ThreadContextInfo::SetValidCallTargetInternal<false>(callTargetAddress, nullptr, nullptr, isSetValid);
  460. }
  461. bool
  462. ThreadContextInfo::IsClosed()
  463. {
  464. return m_isClosed;
  465. }
  466. uintptr_t ShiftAddr(const ThreadContextInfo * const context, uintptr_t address)
  467. {
  468. #if ENABLE_OOP_NATIVE_CODEGEN
  469. ptrdiff_t diff = 0;
  470. if (AutoSystemInfo::Data.IsJscriptModulePointer((void*)address))
  471. {
  472. diff = context->GetChakraBaseAddressDifference();
  473. }
  474. else if(AutoSystemInfo::Data.IsCRTModulePointer(address))
  475. {
  476. diff = context->GetCRTBaseAddressDifference();
  477. }
  478. else
  479. {
  480. AssertOrFailFast(UNREACHED);
  481. }
  482. return (intptr_t)address + diff;
  483. #else
  484. return address;
  485. #endif
  486. }