blob: 1d47f0848a6dfac5e0b295b5fa344264dcd1a81a [file] [log] [blame]
Reid Spencer4befbf32004-12-24 06:03:31 +00001//===- Win32/DynamicLibrary.cpp - Win32 DL Implementation -------*- C++ -*-===//
Michael J. Spencer447762d2010-11-29 18:16:10 +00002//
Reid Spencer4befbf32004-12-24 06:03:31 +00003// The LLVM Compiler Infrastructure
4//
Chris Lattnerf3ebc3f2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Michael J. Spencer447762d2010-11-29 18:16:10 +00007//
Reid Spencer4befbf32004-12-24 06:03:31 +00008//===----------------------------------------------------------------------===//
9//
Jeff Cohenf365c332004-12-25 04:50:17 +000010// This file provides the Win32 specific implementation of DynamicLibrary.
Reid Spencer4befbf32004-12-24 06:03:31 +000011//
12//===----------------------------------------------------------------------===//
13
Reid Klecknerd59e2fa2014-02-12 21:26:20 +000014#include "WindowsSupport.h"
Zachary Turnerb44d7a02018-06-01 22:23:46 +000015#include "llvm/Support/ConvertUTF.h"
Frederich Munchc1db8cf2017-04-27 16:55:24 +000016#include "llvm/Support/raw_ostream.h"
Jeff Cohenf365c332004-12-25 04:50:17 +000017
Frederich Munchc1db8cf2017-04-27 16:55:24 +000018#include <psapi.h>
Frederich Munchb8c236a2017-04-24 03:33:30 +000019
Reid Spencer4befbf32004-12-24 06:03:31 +000020//===----------------------------------------------------------------------===//
Michael J. Spencer447762d2010-11-29 18:16:10 +000021//=== WARNING: Implementation here must contain only Win32 specific code
Jeff Cohen039b4ab2004-12-24 07:57:09 +000022//=== and must not be UNIX code.
Reid Spencer4befbf32004-12-24 06:03:31 +000023//===----------------------------------------------------------------------===//
24
Jeff Cohen039b4ab2004-12-24 07:57:09 +000025
Frederich Munchc1db8cf2017-04-27 16:55:24 +000026DynamicLibrary::HandleSet::~HandleSet() {
Frederich Munchad125802017-06-05 16:26:58 +000027 for (void *Handle : llvm::reverse(Handles))
Frederich Munchc1db8cf2017-04-27 16:55:24 +000028 FreeLibrary(HMODULE(Handle));
29
30 // 'Process' should not be released on Windows.
31 assert((!Process || Process==this) && "Bad Handle");
Frederich Munch5fdd2cb2017-07-12 21:22:45 +000032 // llvm_shutdown called, Return to default
33 DynamicLibrary::SearchOrder = DynamicLibrary::SO_Linker;
Frederich Munch9f404572017-04-24 02:30:12 +000034}
35
Frederich Munchc1db8cf2017-04-27 16:55:24 +000036void *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
37 // Create the instance and return it to be the *Process* handle
38 // simillar to dlopen(NULL, RTLD_LAZY|RTLD_GLOBAL)
39 if (!File)
40 return &(*OpenedHandles);
Frederich Munch9f404572017-04-24 02:30:12 +000041
Frederich Munchc1db8cf2017-04-27 16:55:24 +000042 SmallVector<wchar_t, MAX_PATH> FileUnicode;
43 if (std::error_code ec = windows::UTF8ToUTF16(File, FileUnicode)) {
Frederich Munchfd96d5e2017-04-24 20:16:01 +000044 SetLastError(ec.value());
Frederich Munchc1db8cf2017-04-27 16:55:24 +000045 MakeErrMsg(Err, std::string(File) + ": Can't convert to UTF-16");
46 return &DynamicLibrary::Invalid;
Frederich Munchfd96d5e2017-04-24 20:16:01 +000047 }
48
Frederich Munchc1db8cf2017-04-27 16:55:24 +000049 HMODULE Handle = LoadLibraryW(FileUnicode.data());
50 if (Handle == NULL) {
51 MakeErrMsg(Err, std::string(File) + ": Can't open");
52 return &DynamicLibrary::Invalid;
Frederich Munchfd96d5e2017-04-24 20:16:01 +000053 }
54
Frederich Munchc1db8cf2017-04-27 16:55:24 +000055 return reinterpret_cast<void*>(Handle);
Frederich Munch70c377a2017-04-24 19:55:16 +000056}
57
Frederich Munchc1db8cf2017-04-27 16:55:24 +000058static DynamicLibrary::HandleSet *IsOpenedHandlesInstance(void *Handle) {
59 if (!OpenedHandles.isConstructed())
60 return nullptr;
61 DynamicLibrary::HandleSet &Inst = *OpenedHandles;
62 return Handle == &Inst ? &Inst : nullptr;
Frederich Munchfd96d5e2017-04-24 20:16:01 +000063}
Frederich Munch70c377a2017-04-24 19:55:16 +000064
Frederich Munchc1db8cf2017-04-27 16:55:24 +000065void DynamicLibrary::HandleSet::DLClose(void *Handle) {
66 if (HandleSet* HS = IsOpenedHandlesInstance(Handle))
67 HS->Process = nullptr; // Just drop the *Process* handle.
68 else
69 FreeLibrary((HMODULE)Handle);
70}
71
72static bool GetProcessModules(HANDLE H, DWORD &Bytes, HMODULE *Data = nullptr) {
73 // EnumProcessModules will fail on Windows 64 while some versions of
74 // MingW-32 don't have EnumProcessModulesEx.
75 if (
76#ifdef _WIN64
77 !EnumProcessModulesEx(H, Data, Bytes, &Bytes, LIST_MODULES_64BIT)
78#else
79 !EnumProcessModules(H, Data, Bytes, &Bytes)
80#endif
81 ) {
82 std::string Err;
83 if (MakeErrMsg(&Err, "EnumProcessModules failure"))
84 llvm::errs() << Err << "\n";
85 return false;
86 }
87 return true;
88}
89
90void *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) {
91 HandleSet* HS = IsOpenedHandlesInstance(Handle);
92 if (!HS)
93 return (void *)uintptr_t(GetProcAddress((HMODULE)Handle, Symbol));
94
95 // Could have done a dlclose on the *Process* handle
96 if (!HS->Process)
97 return nullptr;
98
99 // Trials indicate EnumProcessModulesEx is consistantly faster than using
100 // EnumerateLoadedModules64 or CreateToolhelp32Snapshot.
101 //
102 // | Handles | DbgHelp.dll | CreateSnapshot | EnumProcessModulesEx
103 // |=========|=============|========================================
104 // | 37 | 0.0000585 * | 0.0003031 | 0.0000152
105 // | 1020 | 0.0026310 * | 0.0121598 | 0.0002683
106 // | 2084 | 0.0149418 * | 0.0369936 | 0.0005610
107 //
108 // * Not including the load time of Dbghelp.dll (~.005 sec)
109 //
110 // There's still a case to somehow cache the result of EnumProcessModulesEx
111 // across invocations, but the complication of doing that properly...
112 // Possibly using LdrRegisterDllNotification to invalidate the cache?
113
114 DWORD Bytes = 0;
115 HMODULE Self = HMODULE(GetCurrentProcess());
116 if (!GetProcessModules(Self, Bytes))
117 return nullptr;
118
119 // Get the most recent list in case any modules added/removed between calls
120 // to EnumProcessModulesEx that gets the amount of, then copies the HMODULES.
121 // MSDN is pretty clear that if the module list changes during the call to
122 // EnumProcessModulesEx the results should not be used.
123 std::vector<HMODULE> Handles;
124 do {
125 assert(Bytes && ((Bytes % sizeof(HMODULE)) == 0) &&
126 "Should have at least one module and be aligned");
127 Handles.resize(Bytes / sizeof(HMODULE));
128 if (!GetProcessModules(Self, Bytes, Handles.data()))
129 return nullptr;
130 } while (Bytes != (Handles.size() * sizeof(HMODULE)));
131
132 // Try EXE first, mirroring what dlsym(dlopen(NULL)) does.
133 if (FARPROC Ptr = GetProcAddress(HMODULE(Handles.front()), Symbol))
134 return (void *) uintptr_t(Ptr);
135
136 if (Handles.size() > 1) {
137 // This is different behaviour than what Posix dlsym(dlopen(NULL)) does.
138 // Doing that here is causing real problems for the JIT where msvc.dll
139 // and ucrt.dll can define the same symbols. The runtime linker will choose
140 // symbols from ucrt.dll first, but iterating NOT in reverse here would
141 // mean that the msvc.dll versions would be returned.
142
143 for (auto I = Handles.rbegin(), E = Handles.rend()-1; I != E; ++I) {
144 if (FARPROC Ptr = GetProcAddress(HMODULE(*I), Symbol))
145 return (void *) uintptr_t(Ptr);
146 }
147 }
148 return nullptr;
149}
150
151
Anton Korobeynikov66362102008-02-22 10:08:31 +0000152// Stack probing routines are in the support library (e.g. libgcc), but we don't
153// have dynamic linking on windows. Provide a hook.
NAKAMURA Takumi03a541f2011-02-05 15:11:53 +0000154#define EXPLICIT_SYMBOL(SYM) \
155 extern "C" { extern void *SYM; }
156#define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) EXPLICIT_SYMBOL(SYMTO)
Anton Korobeynikov66362102008-02-22 10:08:31 +0000157
Reid Kleckner9aeb0472014-11-13 23:32:52 +0000158#ifdef _M_IX86
159// Win32 on x86 implements certain single-precision math functions as macros.
160// These functions are not exported by the DLL, but will still be needed
161// for symbol-resolution by the JIT loader. Therefore, this Support libray
162// provides helper functions with the same implementation.
163
164#define INLINE_DEF_SYMBOL1(TYP, SYM) \
165 extern "C" TYP inline_##SYM(TYP _X) { return SYM(_X); }
166#define INLINE_DEF_SYMBOL2(TYP, SYM) \
167 extern "C" TYP inline_##SYM(TYP _X, TYP _Y) { return SYM(_X, _Y); }
168#endif
169
NAKAMURA Takumi03a541f2011-02-05 15:11:53 +0000170#include "explicit_symbols.inc"
171
172#undef EXPLICIT_SYMBOL
173#undef EXPLICIT_SYMBOL2
Reid Kleckner9aeb0472014-11-13 23:32:52 +0000174#undef INLINE_DEF_SYMBOL1
175#undef INLINE_DEF_SYMBOL2
Anton Korobeynikov66362102008-02-22 10:08:31 +0000176
Frederich Munchc1db8cf2017-04-27 16:55:24 +0000177static void *DoSearch(const char *SymbolName) {
Jeff Cohen039b4ab2004-12-24 07:57:09 +0000178
Reid Kleckner9aeb0472014-11-13 23:32:52 +0000179#define EXPLICIT_SYMBOL(SYM) \
Frederich Munchc1db8cf2017-04-27 16:55:24 +0000180 if (!strcmp(SymbolName, #SYM)) \
Reid Kleckner9aeb0472014-11-13 23:32:52 +0000181 return (void *)&SYM;
182#define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) \
Frederich Munchc1db8cf2017-04-27 16:55:24 +0000183 if (!strcmp(SymbolName, #SYMFROM)) \
Reid Kleckner9aeb0472014-11-13 23:32:52 +0000184 return (void *)&SYMTO;
185
186#ifdef _M_IX86
187#define INLINE_DEF_SYMBOL1(TYP, SYM) \
Frederich Munchc1db8cf2017-04-27 16:55:24 +0000188 if (!strcmp(SymbolName, #SYM)) \
Reid Kleckner9aeb0472014-11-13 23:32:52 +0000189 return (void *)&inline_##SYM;
190#define INLINE_DEF_SYMBOL2(TYP, SYM) INLINE_DEF_SYMBOL1(TYP, SYM)
191#endif
Anton Korobeynikov66362102008-02-22 10:08:31 +0000192
Anton Korobeynikovec9038bc2007-06-25 07:12:14 +0000193 {
Reid Kleckner9aeb0472014-11-13 23:32:52 +0000194#include "explicit_symbols.inc"
Anton Korobeynikov105682d2010-01-14 20:19:51 +0000195 }
NAKAMURA Takumi03a541f2011-02-05 15:11:53 +0000196
Reid Kleckner9aeb0472014-11-13 23:32:52 +0000197#undef EXPLICIT_SYMBOL
198#undef EXPLICIT_SYMBOL2
199#undef INLINE_DEF_SYMBOL1
200#undef INLINE_DEF_SYMBOL2
Anton Korobeynikoveef04ba2006-12-19 15:24:18 +0000201
Frederich Munchc1db8cf2017-04-27 16:55:24 +0000202 return nullptr;
Reid Spencer4befbf32004-12-24 06:03:31 +0000203}