xref: /aosp_15_r20/external/llvm/lib/Support/Windows/DynamicLibrary.inc (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker//===- Win32/DynamicLibrary.cpp - Win32 DL Implementation -------*- C++ -*-===//
2*9880d681SAndroid Build Coastguard Worker//
3*9880d681SAndroid Build Coastguard Worker//                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker//
5*9880d681SAndroid Build Coastguard Worker// This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker// License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker//
8*9880d681SAndroid Build Coastguard Worker//===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker//
10*9880d681SAndroid Build Coastguard Worker// This file provides the Win32 specific implementation of DynamicLibrary.
11*9880d681SAndroid Build Coastguard Worker//
12*9880d681SAndroid Build Coastguard Worker//===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker
14*9880d681SAndroid Build Coastguard Worker#include "WindowsSupport.h"
15*9880d681SAndroid Build Coastguard Worker
16*9880d681SAndroid Build Coastguard Worker#ifdef __MINGW32__
17*9880d681SAndroid Build Coastguard Worker #include <imagehlp.h>
18*9880d681SAndroid Build Coastguard Worker#else
19*9880d681SAndroid Build Coastguard Worker #include <dbghelp.h>
20*9880d681SAndroid Build Coastguard Worker#endif
21*9880d681SAndroid Build Coastguard Worker
22*9880d681SAndroid Build Coastguard Worker#ifdef _MSC_VER
23*9880d681SAndroid Build Coastguard Worker #include <ntverp.h>
24*9880d681SAndroid Build Coastguard Worker#endif
25*9880d681SAndroid Build Coastguard Worker
26*9880d681SAndroid Build Coastguard Workernamespace llvm {
27*9880d681SAndroid Build Coastguard Workerusing namespace sys;
28*9880d681SAndroid Build Coastguard Worker
29*9880d681SAndroid Build Coastguard Worker//===----------------------------------------------------------------------===//
30*9880d681SAndroid Build Coastguard Worker//=== WARNING: Implementation here must contain only Win32 specific code
31*9880d681SAndroid Build Coastguard Worker//===          and must not be UNIX code.
32*9880d681SAndroid Build Coastguard Worker//===----------------------------------------------------------------------===//
33*9880d681SAndroid Build Coastguard Worker
34*9880d681SAndroid Build Coastguard Workertypedef BOOL (WINAPI *fpEnumerateLoadedModules)(HANDLE,PENUMLOADED_MODULES_CALLBACK64,PVOID);
35*9880d681SAndroid Build Coastguard Workerstatic fpEnumerateLoadedModules fEnumerateLoadedModules;
36*9880d681SAndroid Build Coastguard Workerstatic DenseSet<HMODULE> *OpenedHandles;
37*9880d681SAndroid Build Coastguard Worker
38*9880d681SAndroid Build Coastguard Workerstatic bool loadDebugHelp(void) {
39*9880d681SAndroid Build Coastguard Worker  HMODULE hLib = ::LoadLibraryW(L"Dbghelp.dll");
40*9880d681SAndroid Build Coastguard Worker  if (hLib) {
41*9880d681SAndroid Build Coastguard Worker    fEnumerateLoadedModules = (fpEnumerateLoadedModules)
42*9880d681SAndroid Build Coastguard Worker      ::GetProcAddress(hLib, "EnumerateLoadedModules64");
43*9880d681SAndroid Build Coastguard Worker  }
44*9880d681SAndroid Build Coastguard Worker  return fEnumerateLoadedModules != 0;
45*9880d681SAndroid Build Coastguard Worker}
46*9880d681SAndroid Build Coastguard Worker
47*9880d681SAndroid Build Coastguard Workerstatic BOOL CALLBACK
48*9880d681SAndroid Build Coastguard WorkerELM_Callback(PCSTR ModuleName, DWORD64 ModuleBase,
49*9880d681SAndroid Build Coastguard Worker             ULONG ModuleSize, PVOID UserContext) {
50*9880d681SAndroid Build Coastguard Worker  OpenedHandles->insert((HMODULE)ModuleBase);
51*9880d681SAndroid Build Coastguard Worker  return TRUE;
52*9880d681SAndroid Build Coastguard Worker}
53*9880d681SAndroid Build Coastguard Worker
54*9880d681SAndroid Build Coastguard WorkerDynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
55*9880d681SAndroid Build Coastguard Worker                                                   std::string *errMsg) {
56*9880d681SAndroid Build Coastguard Worker  SmartScopedLock<true> lock(*SymbolsMutex);
57*9880d681SAndroid Build Coastguard Worker
58*9880d681SAndroid Build Coastguard Worker  if (!filename) {
59*9880d681SAndroid Build Coastguard Worker    // When no file is specified, enumerate all DLLs and EXEs in the process.
60*9880d681SAndroid Build Coastguard Worker    if (OpenedHandles == 0)
61*9880d681SAndroid Build Coastguard Worker      OpenedHandles = new DenseSet<HMODULE>();
62*9880d681SAndroid Build Coastguard Worker
63*9880d681SAndroid Build Coastguard Worker    if (!fEnumerateLoadedModules) {
64*9880d681SAndroid Build Coastguard Worker      if (!loadDebugHelp()) {
65*9880d681SAndroid Build Coastguard Worker        assert(false && "These APIs should always be available");
66*9880d681SAndroid Build Coastguard Worker        return DynamicLibrary();
67*9880d681SAndroid Build Coastguard Worker      }
68*9880d681SAndroid Build Coastguard Worker    }
69*9880d681SAndroid Build Coastguard Worker
70*9880d681SAndroid Build Coastguard Worker    fEnumerateLoadedModules(GetCurrentProcess(), ELM_Callback, 0);
71*9880d681SAndroid Build Coastguard Worker    // Dummy library that represents "search all handles".
72*9880d681SAndroid Build Coastguard Worker    // This is mostly to ensure that the return value still shows up as "valid".
73*9880d681SAndroid Build Coastguard Worker    return DynamicLibrary(&OpenedHandles);
74*9880d681SAndroid Build Coastguard Worker  }
75*9880d681SAndroid Build Coastguard Worker
76*9880d681SAndroid Build Coastguard Worker  SmallVector<wchar_t, MAX_PATH> filenameUnicode;
77*9880d681SAndroid Build Coastguard Worker  if (std::error_code ec = windows::UTF8ToUTF16(filename, filenameUnicode)) {
78*9880d681SAndroid Build Coastguard Worker    SetLastError(ec.value());
79*9880d681SAndroid Build Coastguard Worker    MakeErrMsg(errMsg, std::string(filename) + ": Can't convert to UTF-16");
80*9880d681SAndroid Build Coastguard Worker    return DynamicLibrary();
81*9880d681SAndroid Build Coastguard Worker  }
82*9880d681SAndroid Build Coastguard Worker
83*9880d681SAndroid Build Coastguard Worker  HMODULE a_handle = LoadLibraryW(filenameUnicode.data());
84*9880d681SAndroid Build Coastguard Worker
85*9880d681SAndroid Build Coastguard Worker  if (a_handle == 0) {
86*9880d681SAndroid Build Coastguard Worker    MakeErrMsg(errMsg, std::string(filename) + ": Can't open");
87*9880d681SAndroid Build Coastguard Worker    return DynamicLibrary();
88*9880d681SAndroid Build Coastguard Worker  }
89*9880d681SAndroid Build Coastguard Worker
90*9880d681SAndroid Build Coastguard Worker  if (OpenedHandles == 0)
91*9880d681SAndroid Build Coastguard Worker    OpenedHandles = new DenseSet<HMODULE>();
92*9880d681SAndroid Build Coastguard Worker
93*9880d681SAndroid Build Coastguard Worker  // If we've already loaded this library, FreeLibrary() the handle in order to
94*9880d681SAndroid Build Coastguard Worker  // keep the internal refcount at +1.
95*9880d681SAndroid Build Coastguard Worker  if (!OpenedHandles->insert(a_handle).second)
96*9880d681SAndroid Build Coastguard Worker    FreeLibrary(a_handle);
97*9880d681SAndroid Build Coastguard Worker
98*9880d681SAndroid Build Coastguard Worker  return DynamicLibrary(a_handle);
99*9880d681SAndroid Build Coastguard Worker}
100*9880d681SAndroid Build Coastguard Worker
101*9880d681SAndroid Build Coastguard Worker// Stack probing routines are in the support library (e.g. libgcc), but we don't
102*9880d681SAndroid Build Coastguard Worker// have dynamic linking on windows. Provide a hook.
103*9880d681SAndroid Build Coastguard Worker#define EXPLICIT_SYMBOL(SYM)                    \
104*9880d681SAndroid Build Coastguard Worker  extern "C" { extern void *SYM; }
105*9880d681SAndroid Build Coastguard Worker#define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) EXPLICIT_SYMBOL(SYMTO)
106*9880d681SAndroid Build Coastguard Worker
107*9880d681SAndroid Build Coastguard Worker#ifdef _M_IX86
108*9880d681SAndroid Build Coastguard Worker// Win32 on x86 implements certain single-precision math functions as macros.
109*9880d681SAndroid Build Coastguard Worker// These functions are not exported by the DLL, but will still be needed
110*9880d681SAndroid Build Coastguard Worker// for symbol-resolution by the JIT loader. Therefore, this Support libray
111*9880d681SAndroid Build Coastguard Worker// provides helper functions with the same implementation.
112*9880d681SAndroid Build Coastguard Worker
113*9880d681SAndroid Build Coastguard Worker#define INLINE_DEF_SYMBOL1(TYP, SYM)                                           \
114*9880d681SAndroid Build Coastguard Worker  extern "C" TYP inline_##SYM(TYP _X) { return SYM(_X); }
115*9880d681SAndroid Build Coastguard Worker#define INLINE_DEF_SYMBOL2(TYP, SYM)                                           \
116*9880d681SAndroid Build Coastguard Worker  extern "C" TYP inline_##SYM(TYP _X, TYP _Y) { return SYM(_X, _Y); }
117*9880d681SAndroid Build Coastguard Worker#endif
118*9880d681SAndroid Build Coastguard Worker
119*9880d681SAndroid Build Coastguard Worker#include "explicit_symbols.inc"
120*9880d681SAndroid Build Coastguard Worker
121*9880d681SAndroid Build Coastguard Worker#undef EXPLICIT_SYMBOL
122*9880d681SAndroid Build Coastguard Worker#undef EXPLICIT_SYMBOL2
123*9880d681SAndroid Build Coastguard Worker#undef INLINE_DEF_SYMBOL1
124*9880d681SAndroid Build Coastguard Worker#undef INLINE_DEF_SYMBOL2
125*9880d681SAndroid Build Coastguard Worker
126*9880d681SAndroid Build Coastguard Workervoid* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) {
127*9880d681SAndroid Build Coastguard Worker  SmartScopedLock<true> Lock(*SymbolsMutex);
128*9880d681SAndroid Build Coastguard Worker
129*9880d681SAndroid Build Coastguard Worker  // First check symbols added via AddSymbol().
130*9880d681SAndroid Build Coastguard Worker  if (ExplicitSymbols.isConstructed()) {
131*9880d681SAndroid Build Coastguard Worker    StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName);
132*9880d681SAndroid Build Coastguard Worker
133*9880d681SAndroid Build Coastguard Worker    if (i != ExplicitSymbols->end())
134*9880d681SAndroid Build Coastguard Worker      return i->second;
135*9880d681SAndroid Build Coastguard Worker  }
136*9880d681SAndroid Build Coastguard Worker
137*9880d681SAndroid Build Coastguard Worker  // Now search the libraries.
138*9880d681SAndroid Build Coastguard Worker  if (OpenedHandles) {
139*9880d681SAndroid Build Coastguard Worker    for (DenseSet<HMODULE>::iterator I = OpenedHandles->begin(),
140*9880d681SAndroid Build Coastguard Worker         E = OpenedHandles->end(); I != E; ++I) {
141*9880d681SAndroid Build Coastguard Worker      FARPROC ptr = GetProcAddress((HMODULE)*I, symbolName);
142*9880d681SAndroid Build Coastguard Worker      if (ptr) {
143*9880d681SAndroid Build Coastguard Worker        return (void *)(intptr_t)ptr;
144*9880d681SAndroid Build Coastguard Worker      }
145*9880d681SAndroid Build Coastguard Worker    }
146*9880d681SAndroid Build Coastguard Worker  }
147*9880d681SAndroid Build Coastguard Worker
148*9880d681SAndroid Build Coastguard Worker#define EXPLICIT_SYMBOL(SYM)                                                   \
149*9880d681SAndroid Build Coastguard Worker  if (!strcmp(symbolName, #SYM))                                               \
150*9880d681SAndroid Build Coastguard Worker    return (void *)&SYM;
151*9880d681SAndroid Build Coastguard Worker#define EXPLICIT_SYMBOL2(SYMFROM, SYMTO)                                       \
152*9880d681SAndroid Build Coastguard Worker  if (!strcmp(symbolName, #SYMFROM))                                           \
153*9880d681SAndroid Build Coastguard Worker    return (void *)&SYMTO;
154*9880d681SAndroid Build Coastguard Worker
155*9880d681SAndroid Build Coastguard Worker#ifdef _M_IX86
156*9880d681SAndroid Build Coastguard Worker#define INLINE_DEF_SYMBOL1(TYP, SYM)                                           \
157*9880d681SAndroid Build Coastguard Worker  if (!strcmp(symbolName, #SYM))                                               \
158*9880d681SAndroid Build Coastguard Worker    return (void *)&inline_##SYM;
159*9880d681SAndroid Build Coastguard Worker#define INLINE_DEF_SYMBOL2(TYP, SYM) INLINE_DEF_SYMBOL1(TYP, SYM)
160*9880d681SAndroid Build Coastguard Worker#endif
161*9880d681SAndroid Build Coastguard Worker
162*9880d681SAndroid Build Coastguard Worker  {
163*9880d681SAndroid Build Coastguard Worker#include "explicit_symbols.inc"
164*9880d681SAndroid Build Coastguard Worker  }
165*9880d681SAndroid Build Coastguard Worker
166*9880d681SAndroid Build Coastguard Worker#undef EXPLICIT_SYMBOL
167*9880d681SAndroid Build Coastguard Worker#undef EXPLICIT_SYMBOL2
168*9880d681SAndroid Build Coastguard Worker#undef INLINE_DEF_SYMBOL1
169*9880d681SAndroid Build Coastguard Worker#undef INLINE_DEF_SYMBOL2
170*9880d681SAndroid Build Coastguard Worker
171*9880d681SAndroid Build Coastguard Worker  return 0;
172*9880d681SAndroid Build Coastguard Worker}
173*9880d681SAndroid Build Coastguard Worker
174*9880d681SAndroid Build Coastguard Workervoid *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
175*9880d681SAndroid Build Coastguard Worker  if (!isValid())
176*9880d681SAndroid Build Coastguard Worker    return NULL;
177*9880d681SAndroid Build Coastguard Worker  if (Data == &OpenedHandles)
178*9880d681SAndroid Build Coastguard Worker    return SearchForAddressOfSymbol(symbolName);
179*9880d681SAndroid Build Coastguard Worker  return (void *)(intptr_t)GetProcAddress((HMODULE)Data, symbolName);
180*9880d681SAndroid Build Coastguard Worker}
181*9880d681SAndroid Build Coastguard Worker
182*9880d681SAndroid Build Coastguard Worker}
183