ZEVORN.blog

May 22, 2024

LLVM3.0 JIT 处理代码块重定向阶段对外部符号解析的 Bug

article2.0 min to read

LLVM3.0 的 JIT 在 MinGW64 / MSCV64 上,进行代码块重定向阶段,处理超过32位地址范围(前后跳转2GB地址空间)的外部符号地址时,会将其强转为32位:

// lib\Target\X86\X86JITInfo.cpp:543void X86JITInfo::relocate(void *Function, MachineRelocation *MR,                          unsigned NumRelocs, unsigned char* GOTBase) {  for (unsigned i = 0; i != NumRelocs; ++i, ++MR) {    void *RelocPos = (char*)Function + MR->getMachineCodeOffset();    intptr_t ResultPtr = (intptr_t)MR->getResultPointer();    switch ((X86::RelocationType)MR->getRelocationType()) {    case X86::reloc_pcrel_word: {      ResultPtr = ResultPtr -(intptr_t)RelocPos - 4 - MR->getConstantVal();      *((unsigned*)RelocPos) += (unsigned)ResultPtr; // 这里默认都是强转成32位的      break;    }}

这会导致生成的指令,在执行时崩溃,一般表现为段错误。

解决办法:

From bdc19fc6fa1a87a375e5f77e83bc6e712185676a Mon Sep 17 00:00:00 2001From: zevorn <zevorn@yeah.net>Date: Wed, 22 May 2024 18:31:30 +0800Subject: [PATCH 1/4] <fix>(JIT) Fixed a Bug in JITFixed a Bug in JIT processing code block redirection phase for external symbol parsing--- lib/ExecutionEngine/JIT/JITEmitter.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cppindex 24020ee..0050b75 100644--- a/lib/ExecutionEngine/JIT/JITEmitter.cpp+++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp@@ -849,7 +849,11 @@ bool JITEmitter::finishFunction(MachineFunction &F) {                        << ResultPtr << "]\n");            // If the target REALLY wants a stub for this function, emit it now.-          if (MR.mayNeedFarStub()) {+          uintptr_t CurrPtr = getCurrentPCValue();+          const uintptr_t rang = 2ull * 1024 * 1024 * 1024; // 2GB+          if (MR.mayNeedFarStub()+            || ((CurrPtr + rang) < (uintptr_t)ResultPtr)+            || ((CurrPtr - rang) > (uintptr_t)ResultPtr)) {             ResultPtr = Resolver.getExternalFunctionStub(ResultPtr);           }         } else if (MR.isGlobalValue()) {-- 2.44.0.windows.1

PS:这个问题似乎在 LLVM 3.1 上面也存在。