ThreadContextInfo.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Copyright (c) ChakraCore Project Contributors. All rights reserved.
  4. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  5. //-------------------------------------------------------------------------------------------------------
  6. #include "RuntimeBasePch.h"
  7. // Originally defined in ntstatus.h, define here because including windows.h (via PCH
  8. // above) with ntstatus.h causes macro redefinition errors for the common errors defined
  9. // in both header files.
  10. #define STATUS_PROCESS_IS_TERMINATING ((NTSTATUS)0xC000010AL)
  11. #if ENABLE_NATIVE_CODEGEN
  12. #include "CodeGenAllocators.h"
  13. #include "ServerThreadContext.h"
  14. #endif
  15. #if defined(_UCRT) && _CONTROL_FLOW_GUARD
  16. # if _MSC_VER >= 1913
  17. # include <cfguard.h>
  18. # else
  19. extern "C" void __fastcall _guard_check_icall(_In_ uintptr_t _Target);
  20. # endif
  21. # ifndef _GUARD_CHECK_ICALL
  22. # define _GUARD_CHECK_ICALL _guard_check_icall
  23. # endif
  24. #endif
  25. ThreadContextInfo::ThreadContextInfo() :
  26. m_isAllJITCodeInPreReservedRegion(true),
  27. m_isClosed(false)
  28. {
  29. for (int i = 0; i <= WellKnownHostType_Last; ++i)
  30. {
  31. wellKnownHostTypeIds[i] = Js::TypeIds_Undefined;
  32. }
  33. }
  34. #if ENABLE_NATIVE_CODEGEN
  35. intptr_t
  36. ThreadContextInfo::GetNullFrameDisplayAddr() const
  37. {
  38. return ShiftAddr(this, &Js::NullFrameDisplay);
  39. }
  40. intptr_t
  41. ThreadContextInfo::GetStrictNullFrameDisplayAddr() const
  42. {
  43. return ShiftAddr(this, &Js::StrictNullFrameDisplay);
  44. }
  45. intptr_t
  46. ThreadContextInfo::GetAbsDoubleCstAddr() const
  47. {
  48. return ShiftAddr(this, &Js::JavascriptNumber::AbsDoubleCst);
  49. }
  50. intptr_t
  51. ThreadContextInfo::GetAbsFloatCstAddr() const
  52. {
  53. return ShiftAddr(this, &Js::JavascriptNumber::AbsFloatCst);
  54. }
  55. intptr_t ThreadContextInfo::GetSgnFloatBitCst() const
  56. {
  57. return ShiftAddr(this, &Js::JavascriptNumber::SgnFloatBitCst);
  58. }
  59. intptr_t ThreadContextInfo::GetSgnDoubleBitCst() const
  60. {
  61. return ShiftAddr(this, &Js::JavascriptNumber::SgnDoubleBitCst);
  62. }
  63. intptr_t
  64. ThreadContextInfo::GetMaskNegFloatAddr() const
  65. {
  66. return ShiftAddr(this, &Js::JavascriptNumber::MaskNegFloat);
  67. }
  68. intptr_t
  69. ThreadContextInfo::GetMaskNegDoubleAddr() const
  70. {
  71. return ShiftAddr(this, &Js::JavascriptNumber::MaskNegDouble);
  72. }
  73. intptr_t
  74. ThreadContextInfo::GetUIntConvertConstAddr() const
  75. {
  76. return ShiftAddr(this, &Js::JavascriptNumber::UIntConvertConst);
  77. }
  78. intptr_t
  79. ThreadContextInfo::GetUint8ClampedArraySetItemAddr() const
  80. {
  81. return ShiftAddr(this, (BOOL(*)(Js::Uint8ClampedArray * arr, uint32 index, Js::Var value))&Js::Uint8ClampedArray::DirectSetItem);
  82. }
  83. intptr_t
  84. ThreadContextInfo::GetConstructorCacheDefaultInstanceAddr() const
  85. {
  86. return ShiftAddr(this, &Js::ConstructorCache::DefaultInstance);
  87. }
  88. intptr_t
  89. ThreadContextInfo::GetJavascriptObjectNewInstanceAddr() const
  90. {
  91. return ShiftAddr(this, &Js::JavascriptObject::EntryInfo::NewInstance);
  92. }
  93. intptr_t
  94. ThreadContextInfo::GetJavascriptArrayNewInstanceAddr() const
  95. {
  96. return ShiftAddr(this, &Js::JavascriptArray::EntryInfo::NewInstance);
  97. }
  98. intptr_t
  99. ThreadContextInfo::GetDoubleOnePointZeroAddr() const
  100. {
  101. return ShiftAddr(this, &Js::JavascriptNumber::ONE_POINT_ZERO);
  102. }
  103. intptr_t
  104. ThreadContextInfo::GetDoublePointFiveAddr() const
  105. {
  106. return ShiftAddr(this, &Js::JavascriptNumber::k_PointFive);
  107. }
  108. intptr_t
  109. ThreadContextInfo::GetFloatPointFiveAddr() const
  110. {
  111. return ShiftAddr(this, &Js::JavascriptNumber::k_Float32PointFive);
  112. }
  113. intptr_t
  114. ThreadContextInfo::GetDoubleNegPointFiveAddr() const
  115. {
  116. return ShiftAddr(this, &Js::JavascriptNumber::k_NegPointFive);
  117. }
  118. intptr_t
  119. ThreadContextInfo::GetFloatNegPointFiveAddr() const
  120. {
  121. return ShiftAddr(this, &Js::JavascriptNumber::k_Float32NegPointFive);
  122. }
  123. intptr_t
  124. ThreadContextInfo::GetDoubleNegOneAddr() const
  125. {
  126. return ShiftAddr(this, &Js::JavascriptNumber::k_NegOne);
  127. }
  128. intptr_t
  129. ThreadContextInfo::GetDoubleTwoToFractionAddr() const
  130. {
  131. return ShiftAddr(this, &Js::JavascriptNumber::k_TwoToFraction);
  132. }
  133. intptr_t
  134. ThreadContextInfo::GetFloatTwoToFractionAddr() const
  135. {
  136. return ShiftAddr(this, &Js::JavascriptNumber::k_Float32TwoToFraction);
  137. }
  138. intptr_t
  139. ThreadContextInfo::GetDoubleNegTwoToFractionAddr() const
  140. {
  141. return ShiftAddr(this, &Js::JavascriptNumber::k_NegTwoToFraction);
  142. }
  143. intptr_t
  144. ThreadContextInfo::GetDoubleNaNAddr() const
  145. {
  146. return ShiftAddr(this, &Js::JavascriptNumber::k_Nan);
  147. }
  148. intptr_t
  149. ThreadContextInfo::GetDoubleUintMaxPlusOneAddr() const
  150. {
  151. return ShiftAddr(this, &Js::JavascriptNumber::k_UintMaxPlusOne);
  152. }
  153. intptr_t
  154. ThreadContextInfo::GetDoubleIntMaxPlusOneAddr() const
  155. {
  156. return ShiftAddr(this, &Js::JavascriptNumber::k_IntMaxPlusOne);
  157. }
  158. intptr_t
  159. ThreadContextInfo::GetDoubleIntMinMinusOneAddr() const
  160. {
  161. return ShiftAddr(this, &Js::JavascriptNumber::k_MinIntMinusOne);
  162. }
  163. intptr_t
  164. ThreadContextInfo::GetFloatNaNAddr() const
  165. {
  166. return ShiftAddr(this, &Js::JavascriptNumber::k_Nan32);
  167. }
  168. intptr_t
  169. ThreadContextInfo::GetFloatNegTwoToFractionAddr() const
  170. {
  171. return ShiftAddr(this, &Js::JavascriptNumber::k_Float32NegTwoToFraction);
  172. }
  173. intptr_t
  174. ThreadContextInfo::GetDoubleZeroAddr() const
  175. {
  176. return ShiftAddr(this, &Js::JavascriptNumber::k_Zero);
  177. }
  178. intptr_t
  179. ThreadContextInfo::GetFloatZeroAddr() const
  180. {
  181. return ShiftAddr(this, &Js::JavascriptNumber::k_Float32Zero);
  182. }
  183. intptr_t
  184. ThreadContextInfo::GetNativeFloatArrayMissingItemAddr() const
  185. {
  186. return ShiftAddr(this, &Js::JavascriptNativeFloatArray::MissingItem);
  187. }
  188. intptr_t
  189. ThreadContextInfo::GetExponentMaskAddr() const
  190. {
  191. return ShiftAddr(this, &Js::Constants::ExponentMask);
  192. }
  193. intptr_t
  194. ThreadContextInfo::GetMantissaMaskAddr() const
  195. {
  196. return ShiftAddr(this, &Js::Constants::MantissaMask);
  197. }
  198. #if _M_IX86 || _M_AMD64
  199. intptr_t
  200. ThreadContextInfo::GetX86AbsMaskF4Addr() const
  201. {
  202. return ShiftAddr(this, &X86_ABS_MASK_F4);
  203. }
  204. intptr_t
  205. ThreadContextInfo::GetX86AbsMaskD2Addr() const
  206. {
  207. return ShiftAddr(this, &X86_ABS_MASK_D2);
  208. }
  209. intptr_t
  210. ThreadContextInfo::GetX86NegMaskF4Addr() const
  211. {
  212. return ShiftAddr(this, &X86_NEG_MASK_F4);
  213. }
  214. intptr_t
  215. ThreadContextInfo::GetX86NegMaskD2Addr() const
  216. {
  217. return ShiftAddr(this, &X86_NEG_MASK_D2);
  218. }
  219. intptr_t
  220. ThreadContextInfo::GetX86AllNegOnesAddr() const
  221. {
  222. return ShiftAddr(this, &X86_ALL_NEG_ONES);
  223. }
  224. intptr_t
  225. ThreadContextInfo::GetX86AllNegOnesF4Addr() const
  226. {
  227. return ShiftAddr(this, &X86_ALL_NEG_ONES_F4);
  228. }
  229. intptr_t
  230. ThreadContextInfo::GetX86AllZerosAddr() const
  231. {
  232. return ShiftAddr(this, &X86_ALL_ZEROS);
  233. }
  234. intptr_t
  235. ThreadContextInfo::GetX86AllOnesF4Addr() const
  236. {
  237. return ShiftAddr(this, &X86_ALL_ONES_F4);
  238. }
  239. intptr_t
  240. ThreadContextInfo::GetX86AllOnesI4Addr() const
  241. {
  242. return ShiftAddr(this, &X86_ALL_ONES_I4);
  243. }
  244. intptr_t
  245. ThreadContextInfo::GetX86AllOnesI8Addr() const
  246. {
  247. return ShiftAddr(this, &X86_ALL_ONES_I8);
  248. }
  249. intptr_t
  250. ThreadContextInfo::GetX86AllOnesI16Addr() const
  251. {
  252. return ShiftAddr(this, &X86_ALL_ONES_I16);
  253. }
  254. intptr_t
  255. ThreadContextInfo::GetX86LowBytesMaskAddr() const
  256. {
  257. return ShiftAddr(this, &X86_LOWBYTES_MASK);
  258. }
  259. intptr_t
  260. ThreadContextInfo::GetX86HighBytesMaskAddr() const
  261. {
  262. return ShiftAddr(this, &X86_HIGHBYTES_MASK);
  263. }
  264. intptr_t
  265. ThreadContextInfo::GetX86DoubleWordSignBitsAddr() const
  266. {
  267. return ShiftAddr(this, &X86_DWORD_SIGNBITS);
  268. }
  269. intptr_t
  270. ThreadContextInfo::GetX86WordSignBitsAddr() const
  271. {
  272. return ShiftAddr(this, &X86_WORD_SIGNBITS);
  273. }
  274. intptr_t
  275. ThreadContextInfo::GetX86ByteSignBitsAddr() const
  276. {
  277. return ShiftAddr(this, &X86_BYTE_SIGNBITS);
  278. }
  279. intptr_t
  280. ThreadContextInfo::GetX86TwoPower32F4Addr() const
  281. {
  282. return ShiftAddr(this, &X86_TWO_32_F4);
  283. }
  284. intptr_t
  285. ThreadContextInfo::GetX86TwoPower31F4Addr() const
  286. {
  287. return ShiftAddr(this, &X86_TWO_31_F4);
  288. }
  289. intptr_t
  290. ThreadContextInfo::GetX86TwoPower31I4Addr() const
  291. {
  292. return ShiftAddr(this, &X86_TWO_31_I4);
  293. }
  294. intptr_t
  295. ThreadContextInfo::GetX86NegTwoPower31F4Addr() const
  296. {
  297. return ShiftAddr(this, &X86_NEG_TWO_31_F4);
  298. }
  299. intptr_t
  300. ThreadContextInfo::GetX86FourLanesMaskAddr(uint8 minorityLane) const
  301. {
  302. return ShiftAddr(this, &X86_4LANES_MASKS[minorityLane]);
  303. }
  304. intptr_t
  305. ThreadContextInfo::GetDoubleIntMinAddr() const
  306. {
  307. return ShiftAddr(this, &Js::JavascriptNumber::DOUBLE_INT_MIN);
  308. }
  309. intptr_t
  310. ThreadContextInfo::GetDoubleTwoTo31Addr() const
  311. {
  312. return ShiftAddr(this, &Js::JavascriptNumber::DOUBLE_TWO_TO_31);
  313. }
  314. #endif
  315. intptr_t
  316. ThreadContextInfo::GetStringReplaceNameAddr() const
  317. {
  318. return ShiftAddr(this, Js::Constants::StringReplace);
  319. }
  320. intptr_t
  321. ThreadContextInfo::GetStringMatchNameAddr() const
  322. {
  323. return ShiftAddr(this, Js::Constants::StringMatch);
  324. }
  325. #endif
  326. bool
  327. ThreadContextInfo::IsAllJITCodeInPreReservedRegion() const
  328. {
  329. return m_isAllJITCodeInPreReservedRegion;
  330. }
  331. void
  332. ThreadContextInfo::ResetIsAllJITCodeInPreReservedRegion()
  333. {
  334. m_isAllJITCodeInPreReservedRegion = false;
  335. }
  336. #ifdef ENABLE_GLOBALIZATION
  337. # if defined(_CONTROL_FLOW_GUARD)
  338. Js::DelayLoadWinCoreProcessThreads *
  339. ThreadContextInfo::GetWinCoreProcessThreads()
  340. {
  341. m_delayLoadWinCoreProcessThreads.EnsureFromSystemDirOnly();
  342. return &m_delayLoadWinCoreProcessThreads;
  343. }
  344. # endif
  345. #endif
  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 (GlobalSecurityPolicy::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 = GlobalSecurityPolicy::SetProcessValidCallTargets(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
  435. #if ENABLE_OOP_NATIVE_CODEGEN
  436. && !JITManager::GetJITManager()->IsOOPJITEnabled()
  437. #endif
  438. )
  439. {
  440. _GUARD_CHECK_ICALL((uintptr_t)callTargetAddress);
  441. }
  442. if (PHASE_TRACE1(Js::CFGPhase))
  443. {
  444. if (!isSetValid)
  445. {
  446. Output::Print(_u("DEREGISTER:"));
  447. }
  448. 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));
  449. Output::Flush();
  450. }
  451. #endif
  452. }
  453. #endif // _CONTROL_FLOW_GUARD
  454. }
  455. void
  456. ThreadContextInfo::SetValidCallTargetFile(PVOID callTargetAddress, HANDLE fileHandle, PVOID viewBase, bool isSetValid)
  457. {
  458. ThreadContextInfo::SetValidCallTargetInternal<true>(callTargetAddress, fileHandle, viewBase, isSetValid);
  459. }
  460. void
  461. ThreadContextInfo::SetValidCallTargetForCFG(PVOID callTargetAddress, bool isSetValid)
  462. {
  463. ThreadContextInfo::SetValidCallTargetInternal<false>(callTargetAddress, nullptr, nullptr, isSetValid);
  464. }
  465. bool
  466. ThreadContextInfo::IsClosed()
  467. {
  468. return m_isClosed;
  469. }
  470. uintptr_t ShiftAddr(const ThreadContextInfo * const context, uintptr_t address)
  471. {
  472. #if ENABLE_OOP_NATIVE_CODEGEN
  473. ptrdiff_t diff = 0;
  474. if (AutoSystemInfo::Data.IsJscriptModulePointer((void*)address))
  475. {
  476. diff = context->GetChakraBaseAddressDifference();
  477. }
  478. else if(AutoSystemInfo::Data.IsCRTModulePointer(address))
  479. {
  480. diff = context->GetCRTBaseAddressDifference();
  481. }
  482. else
  483. {
  484. AssertOrFailFast(UNREACHED);
  485. }
  486. return (intptr_t)address + diff;
  487. #else
  488. return address;
  489. #endif
  490. }