From 92213e719a6c4c83b47ec25928f3edf751d05fcc Mon Sep 17 00:00:00 2001 From: Bertrand Bellenot Date: Wed, 29 Nov 2017 14:17:01 +0100 Subject: [PATCH] Switch object format from ELF to COFF and fix symbols lookup - Switch object format from ELF (Linux) to COFF (Windows) - Fix mangled symbols lookup on Windows: remove leading '_' and use malloc to simulate __imp_ variables (that are indirection pointers) --- lib/Interpreter/CIFactory.cpp | 2 +- lib/Interpreter/IncrementalJIT.cpp | 4 ++-- lib/Utils/PlatformWin.cpp | 30 ++++++++++++++++++++++++++---- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/lib/Interpreter/CIFactory.cpp b/lib/Interpreter/CIFactory.cpp index 15e466cc..2a410ce1 100644 --- a/lib/Interpreter/CIFactory.cpp +++ b/lib/Interpreter/CIFactory.cpp @@ -894,7 +894,7 @@ static void stringifyPreprocSetting(PreprocessorOptions& PPOpts, llvm::Triple TheTriple(llvm::sys::getProcessTriple()); #ifdef LLVM_ON_WIN32 // COFF format currently needs a few changes in LLVM to function properly. - TheTriple.setObjectFormat(llvm::Triple::ELF); + TheTriple.setObjectFormat(llvm::Triple::COFF); #endif clang::driver::Driver Drvr(argv[0], TheTriple.getTriple(), *Diags); //Drvr.setWarnMissingInput(false); diff --git a/lib/Interpreter/IncrementalJIT.cpp b/lib/Interpreter/IncrementalJIT.cpp index 963bbeb4..d6135ad0 100644 --- a/lib/Interpreter/IncrementalJIT.cpp +++ b/lib/Interpreter/IncrementalJIT.cpp @@ -16,8 +16,8 @@ #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/Support/DynamicLibrary.h" -#ifdef __APPLE__ -// Apple adds an extra '_' +#if defined(__APPLE__) || defined (_MSC_VER) +// Apple and Windows add an extra '_' # define MANGLE_PREFIX "_" #endif diff --git a/lib/Utils/PlatformWin.cpp b/lib/Utils/PlatformWin.cpp index bec1f3c2..adbf48ec 100644 --- a/lib/Utils/PlatformWin.cpp +++ b/lib/Utils/PlatformWin.cpp @@ -533,6 +533,16 @@ const void* DLOpen(const std::string& Path, std::string* Err) { return reinterpret_cast(dyLibHandle); } +const void *CheckImp(void *addr, bool dllimp) { + // __imp_ variables are indirection pointers, so use malloc to simulate that + if (dllimp) { + void **imp_addr = (void**)malloc(sizeof(void*)); + *imp_addr = addr; + addr = (void*)imp_addr; + } + return (const void *)addr; +} + const void* DLSym(const std::string& Name, std::string* Err) { #ifdef _WIN64 const DWORD Flags = LIST_MODULES_64BIT; @@ -540,6 +550,18 @@ const void* DLSym(const std::string& Name, std::string* Err) { const DWORD Flags = LIST_MODULES_32BIT; #endif + bool dllimp = false; + std::string s = Name; + // remove the leading '__imp_' from the symbol (will be replaced by an + // indirection pointer later on) + if (s.compare(0, 6, "__imp_") == 0) { + dllimp = true; + s.replace(0, 6, ""); + } + // remove the leading '_' from the symbol + if (s.compare(0, 1, "_") == 0) + s.replace(0, 1, ""); + DWORD Bytes; std::string ErrStr; llvm::SmallVector Modules; @@ -554,8 +576,8 @@ const void* DLSym(const std::string& Name, std::string* Err) { // In reverse so user loaded modules are searched first for (auto It = Modules.rbegin(), End = Modules.rend(); It < End; ++It) { - if (const void* Addr = ::GetProcAddress(*It, Name.c_str())) - return Addr; + if (void* Addr = ::GetProcAddress(*It, s.c_str())) + return CheckImp(Addr, dllimp); } if (NumNeeded > NumFirst) { // The number of modules was too small to get them all, so call again @@ -563,8 +585,8 @@ const void* DLSym(const std::string& Name, std::string* Err) { if (::EnumProcessModulesEx(::GetCurrentProcess(), &Modules[0], Modules.capacity_in_bytes(), &Bytes, Flags) != 0) { for (DWORD i = NumNeeded-1; i > NumFirst; --i) { - if (const void* Addr = ::GetProcAddress(Modules[i], Name.c_str())) - return Addr; + if (void* Addr = ::GetProcAddress(Modules[i], s.c_str())) + return CheckImp(Addr, dllimp); } } else if (Err) GetLastErrorAsString(*Err, "EnumProcessModulesEx");