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)
This commit is contained in:
Bertrand Bellenot 2017-11-29 14:17:01 +01:00 committed by sftnight
parent 54dbb830b3
commit 92213e719a
3 changed files with 29 additions and 7 deletions

View File

@ -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);

View File

@ -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

View File

@ -533,6 +533,16 @@ const void* DLOpen(const std::string& Path, std::string* Err) {
return reinterpret_cast<void*>(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<HMODULE, 128> 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");