当前位置: 代码迷 >> 综合 >> LLVM JIT finalizeObject失败或getFunctionAddress失败探究
  详细解决方案

LLVM JIT finalizeObject失败或getFunctionAddress失败探究

热度:42   发布时间:2023-12-16 05:42:00.0

环境:windows llvm5.0.1

代码:

#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/ExecutionEngine/Interpreter.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include <llvm/IRReader/IRReader.h>
#include <llvm/Support/SourceMgr.h>
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/TargetSelect.h"
#include <llvm/Support/MemoryBuffer.h>
#include "llvm/Support/raw_ostream.h"
#include <llvm/Support/DynamicLibrary.h>
#include "llvm/Support/Debug.h"#include <cctype>
#include <cstdio>
#include <map>
#include <string>
#include <vector>
#include <stdlib.h>
#include <iostream>
using namespace llvm;
using namespace std;
static LLVMContext *context;
typedef void(*func_type)(...);int main(int argc, char* argv[]) {InitializeNativeTarget();InitializeNativeTargetAsmPrinter();InitializeNativeTargetAsmParser();RTDyldMemoryManager* RTDyldMM = NULL;context = new LLVMContext();SMDiagnostic *smd = new SMDiagnostic();static unique_ptr<Module> Owner = llvm::parseIRFile("external.bc", *smd, *context);//std::unique_ptr<Module> Owner = llvm::make_unique<Module>("test", *context);Module *module = Owner.get();std::string ErrStr;RTDyldMM = new SectionMemoryManager();ExecutionEngine *executionEngine = EngineBuilder(std::move(Owner)).setEngineKind(EngineKind::JIT).setErrorStr(&ErrStr).setVerifyModules(true).setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager>(RTDyldMM)).setOptLevel(CodeGenOpt::Default).create();if (!executionEngine) {exit(1);}executionEngine->finalizeObject();void *func = executionEngine->getPointerToFunction(module->getFunction("sayhello"));
//	uint64_t func = executionEngine->getFunctionAddress("islower");func_type f = (func_type)func;f();system("pause");return 0;
}

遇到的问题:

finalizeObject失败,尝试使用getFunctionAddress也失败,调用getFunctionAddress方法时会默认调用finalizeObject方法。

当注释掉finalizeObject方法时,出现如下错误:

 即调用external.bc中的sayhello函数失败,可能是函数地址获取不正确。

注:这里是finalizeObject的文档解释:

finalizeObject - ensure the module is fully processed and is usable.

It is the user-level function for completing the process of making the object usable for execution. It should be called after sections within an object have been relocated using mapSectionAddress. When this method is called the MCJIT execution engine will reapply relocations for a loaded object. This method has no effect for the interpeter.

解决方法: 

去掉external.cpp某些方法。

例如会导致问题的external.cpp如下:

#include <math.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <setjmp.h>
#include <math.h>
#include <ctype.h>
#include <windows.h>
#include <process.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h> 
#include <sys/types.h>
#include <errno.h>
#include <signal.h>
#include <windows.h>
#include <intrin.h>
#include <io.h>
#include <intrin.h>
#include <string.h>
#pragma comment(lib,"Winmm.lib")
using namespace std;
void ex()
{_beginthreadex(NULL, 1, NULL, NULL, 1, NULL);_endthreadex(1);strncmp("asdf", "afd", 13);_ReadWriteBarrier();int * px = (int*)malloc(2 * sizeof(int));realloc(px, 1);memset(px, 2, 1);memmove(px, px, 1);free(px);char c[10] = "a";char b[10] = "a";int x = strlen(c);x = strcmp(b, c);strcpy(c, b);strcat(b, c);strncat(b, c, 1);sprintf(b, "a", x);system("IRResult.exe");isdigit(c[1]); isupper(c[1]); tolower(c[1]); islower(c[1]); toupper(c[1]); isspace(c[1]);isatty(0);isalpha(0);long *lp = NULL;strrchr("xxx", 38);strcspn("x", "x");strspn("x", "x");atoi(c); atof(c);floor(1.0);sqrt(5.0); pow(1.0, 1.0); exp(2.0);sin(1.0); asin(1.0); tan(1.0); atan(1.0); atan2(1.0, 1.0);cos(1.0); acos(1.0); abs(1); fabs(1.0); fmod(1.0, 1.0); log(1.0);calloc(1, 1);clock(); time(NULL); srand(0); rand();getenv(c);FILE * fp;fp = fopen("1.txt", "r");fread(c, 1, 1, fp);fprintf(fp, "%d", x);fprintf(stdin, "%d", x);fprintf(stdout, "%d", x);fprintf(stderr, "%d", x);fileno(fp);fscanf(fp, "%d", &x); sscanf(c, "%s", c);fwrite(c, 1, 1, fp);fseek(fp, 1, SEEK_SET);feof(fp);strtok(NULL, "sdfs");itoa(1, c, 10);rewind(fp);  fflush(fp); rename(c, c); _unlink(c);read(0, (void*)NULL, 0);tmpnam((char*)NULL);write(0, NULL, 0);memcmp(NULL, NULL, 10);if (c[0] != EOF)fputs(c, fp);fputc(c[1], fp); fgetc(fp); fgets(c, 10, fp); tmpfile();getchar(); putchar('a');fclose(fp);_close(1); perror(c); strerror(errno); remove(c); _read(1, (void*)c, 1);Sleep(1);setbuf(fp, c);//windows数据类型HANDLE  Handle;HANDLE OSSemaphore;CRITICAL_SECTION cs;TIMECAPS Timecaps;va_list OS_Printf_marker;//windows API函数//temptime_t timeaaa;localtime(&timeaaa);CRITICAL_SECTION  a;DeleteCriticalSection(&a);LPLONG aaa;unsigned char xxxx;_byteswap_ushort(xxxx);_ReadWriteBarrier();int x1;_byteswap_ulong(x1);_beginthreadex(NULL, 0, NULL, NULL, 0, NULL);_endthreadex(0);strncmp("", "", 1);AreFileApisANSI();CloseHandle(NULL);CreateFileA(NULL, 0, 0, NULL, 0, 0, NULL);CreateFileW(NULL, 0, 0, NULL, 0, 0, NULL);CreateFileMappingA(NULL, NULL, 0, 0, 0, NULL);CreateFileMappingW(NULL, NULL, 0, 0, 0, NULL);CreateMutexW(NULL, NULL, NULL);DeleteFileA(NULL);DeleteFileW(NULL);FlushFileBuffers(NULL);FormatMessageA(0, NULL, 0, 0, NULL, 0, NULL);FormatMessageW(0, NULL, 0, 0, NULL, 0, NULL);FreeLibrary(NULL);GetCurrentProcessId();GetDiskFreeSpaceA(NULL, NULL, NULL, NULL, NULL);GetDiskFreeSpaceW(NULL, NULL, NULL, NULL, NULL);GetFileAttributesA(NULL);GetFileAttributesW(NULL);GET_FILEEX_INFO_LEVELS x2;GetFileAttributesExW(NULL, x2, NULL);GetFileSize(NULL, NULL);GetFullPathNameA(NULL, 0, NULL, NULL);GetFullPathNameW(NULL, 0, NULL, NULL);GetLastError();GetProcAddress(NULL, NULL);GetSystemInfo(NULL);GetSystemTime(NULL);GetSystemTimeAsFileTime(NULL);GetTempPathA(0, NULL);GetTempPathW(0, NULL);GetTickCount();GetVersionExA(NULL);GetVersionExW(NULL);HeapAlloc(NULL, 0, 0);HeapCreate(0, 0, 0);HeapDestroy(0);HeapFree(NULL, 0, NULL);HeapReAlloc(NULL, 0, NULL, 0);HeapSize(NULL, 0, NULL);HeapValidate(NULL, 0, NULL);HeapCompact(NULL, 0);LoadLibraryA(NULL);LoadLibraryW(NULL);LocalFree(NULL);LockFile(NULL, 0, 0, 0, 0);LockFileEx(NULL, 0, 0, 0, 0, 0);MapViewOfFile(NULL, 0, 0, 0, 0);MultiByteToWideChar(0, 0, 0, 0, NULL, 0);QueryPerformanceCounter(NULL);ReadFile(NULL, NULL, 0, NULL, NULL);SetEndOfFile(NULL);SetFilePointer(NULL, 0, NULL, 0);Sleep(0);SystemTimeToFileTime(NULL, 0);UnlockFile(NULL, 0, 0, 0, 0);UnlockFileEx(NULL, 0, 0, 0, NULL);UnmapViewOfFile(NULL);WideCharToMultiByte(0, 0, NULL, 0, NULL, 0, NULL, NULL);WriteFile(NULL, NULL, 0, NULL, NULL);WaitForSingleObject(NULL, 0);WaitForSingleObjectEx(NULL, 0, 0);OutputDebugStringA(NULL);OutputDebugStringW(NULL);GetProcessHeap();FlushViewOfFile(NULL, 0);EnterCriticalSection(&cs);LeaveCriticalSection(&cs);InitializeCriticalSection(&cs);WaitForSingleObject(OSSemaphore, 1);ReleaseSemaphore(OSSemaphore, 1, NULL);SetThreadAffinityMask(Handle, 1);GetCurrentThreadId();SuspendThread(Handle);ResumeThread(Handle);SetThreadPriorityBoost(Handle, true);CloseHandle(Handle);ResetEvent(Handle);timeSetEvent(10, 1, 0, 1, 1);timeKillEvent(0);timeEndPeriod(0);timeGetDevCaps(&Timecaps, 0);timeBeginPeriod(0);GetTickCount();vprintf(c, OS_Printf_marker);exit(0);
}void *memcpy(void *dest, const void *src, size_t count){//assert(dest != NULL && src != NULL && count>0);char *tmp_dest = (char*)dest;char *tmp_src = (char*)src;while (count--)//不对是否存在重叠区域进行判断*tmp_dest++ = *tmp_src++;return dest;
}void * memmove(void *dest, const void *src, int num)
{//assert(dest != NULL && src != NULL && num>0);char *tmp_dest = (char*)dest;char *tmp_src = (char*)src;//判断des和src是否存在重叠if (tmp_dest + num < tmp_src || tmp_src + num < tmp_dest){while (num--)*tmp_dest++ = *tmp_src++;}else//存在重叠,防止信息丢失,从后向前赋值{tmp_dest = tmp_dest + num - 1;tmp_src = tmp_src + num - 1;while (num--)*tmp_dest-- = *tmp_src--;}return dest;
}
void* memset(void* s, int c, size_t n)
{printf("hello");unsigned char* p = (unsigned char*)s;while (n > 0) {*p++ = (unsigned char)c;--n;printf("%d ", &n);}return s;
}extern "C" {void sayhello(){printf("hello\n");}
}

其中isatty 以及 itoa 等会引发上诉问题。

修改后的external.cpp 如下:

#include <math.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <setjmp.h>
#include <math.h>
#include <ctype.h>
#include <windows.h>
#include <process.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h> 
#include <sys/types.h>
#include <errno.h>
#include <signal.h>
#include <windows.h>
#include <intrin.h>
#include <io.h>
#include <intrin.h>
#include <string.h>
#pragma comment(lib,"Winmm.lib")
using namespace std;
void ex()
{strncmp("asdf", "afd", 13);int * px = (int*)malloc(2 * sizeof(int));realloc(px, 1);memset(px, 2, 1);memmove(px, px, 1);memcmp(NULL, NULL, 10);memcpy(NULL, NULL, 10);free(px);char c[10] = "a";char b[10] = "a";int x = strlen(c);x = strcmp(b, c);strcpy(c, b);strcat(b, c);strncat(b, c, 1);sprintf(b, "a", x);isdigit(c[1]); isupper(c[1]); tolower(c[1]); islower(c[1]); toupper(c[1]); isspace(c[1]);isalpha(0);long *lp = NULL;strrchr("xxx", 38);strcspn("x", "x");strspn("x", "x");atoi(c); atof(c);floor(1.0);sqrt(5.0); pow(1.0, 1.0); exp(2.0);sin(1.0); asin(1.0); tan(1.0); atan(1.0); atan2(1.0, 1.0);cos(1.0); acos(1.0); abs(1); fabs(1.0); fmod(1.0, 1.0); log(1.0);FILE * fp;fp = fopen("1.txt", "r");fread(c, 1, 1, fp);fprintf(fp, "%d", x);fprintf(stdin, "%d", x);fprintf(stdout, "%d", x);fprintf(stderr, "%d", x);fscanf(fp, "%d", &x); sscanf(c, "%s", c);fwrite(c, 1, 1, fp);strtok(NULL, "sdfs");if (c[0] != EOF)fputs(c, fp);fputc(c[1], fp); fgetc(fp); fgets(c, 10, fp);getchar(); putchar('a');fclose(fp);
}void *memcpy(void *dest, const void *src, size_t count){//assert(dest != NULL && src != NULL && count>0);char *tmp_dest = (char*)dest;char *tmp_src = (char*)src;while( count--)//不对是否存在重叠区域进行判断*tmp_dest++ = *tmp_src++;return dest;
}void* memmove(void *dest, const void *src, size_t num)
{//assert(dest != NULL && src != NULL && num>0);char *tmp_dest = (char*)dest;char *tmp_src = (char*)src;//判断des和src是否存在重叠if (tmp_dest + num < tmp_src || tmp_src + num < tmp_dest){while (num--)*tmp_dest++ = *tmp_src++;}else//存在重叠,防止信息丢失,从后向前赋值{tmp_dest = tmp_dest + num - 1;tmp_src = tmp_src + num - 1;while (num--)*tmp_dest-- = *tmp_src--;}return dest;
}
void* memset(void* s, int c, size_t n)
{unsigned char* p = (unsigned char*) s;while (n > 0) {*p++ = (unsigned char) c;--n;}return s;
}extern "C" {void sayhello(){printf("hello\n");}
}

补充:

如果需要保证c++ 与 IR 的自定义函数名不发生变化,需要使用

extern "C"{ 方法... }