1*da0073e9SAndroid Build Coastguard Worker #include <c10/util/Exception.h>
2*da0073e9SAndroid Build Coastguard Worker #include <c10/util/Unicode.h>
3*da0073e9SAndroid Build Coastguard Worker #include <ATen/DynamicLibrary.h>
4*da0073e9SAndroid Build Coastguard Worker #include <ATen/Utils.h>
5*da0073e9SAndroid Build Coastguard Worker
6*da0073e9SAndroid Build Coastguard Worker #ifndef _WIN32
7*da0073e9SAndroid Build Coastguard Worker #include <dlfcn.h>
8*da0073e9SAndroid Build Coastguard Worker #include <libgen.h>
9*da0073e9SAndroid Build Coastguard Worker #else
10*da0073e9SAndroid Build Coastguard Worker #include <c10/util/win32-headers.h>
11*da0073e9SAndroid Build Coastguard Worker #endif
12*da0073e9SAndroid Build Coastguard Worker
13*da0073e9SAndroid Build Coastguard Worker namespace at {
14*da0073e9SAndroid Build Coastguard Worker
15*da0073e9SAndroid Build Coastguard Worker
16*da0073e9SAndroid Build Coastguard Worker #ifndef C10_MOBILE
17*da0073e9SAndroid Build Coastguard Worker #ifndef _WIN32
18*da0073e9SAndroid Build Coastguard Worker
19*da0073e9SAndroid Build Coastguard Worker // Unix
20*da0073e9SAndroid Build Coastguard Worker
checkDL(void * x)21*da0073e9SAndroid Build Coastguard Worker static void* checkDL(void* x) {
22*da0073e9SAndroid Build Coastguard Worker if (!x) {
23*da0073e9SAndroid Build Coastguard Worker TORCH_CHECK_WITH(DynamicLibraryError, false, "Error in dlopen or dlsym: ", dlerror());
24*da0073e9SAndroid Build Coastguard Worker }
25*da0073e9SAndroid Build Coastguard Worker
26*da0073e9SAndroid Build Coastguard Worker return x;
27*da0073e9SAndroid Build Coastguard Worker }
DynamicLibrary(const char * name,const char * alt_name,bool leak_handle_)28*da0073e9SAndroid Build Coastguard Worker DynamicLibrary::DynamicLibrary(const char* name, const char* alt_name, bool leak_handle_): leak_handle(leak_handle_), handle(dlopen(name, RTLD_LOCAL | RTLD_NOW)) {
29*da0073e9SAndroid Build Coastguard Worker if (!handle) {
30*da0073e9SAndroid Build Coastguard Worker if (alt_name) {
31*da0073e9SAndroid Build Coastguard Worker handle = dlopen(alt_name, RTLD_LOCAL | RTLD_NOW);
32*da0073e9SAndroid Build Coastguard Worker if (!handle) {
33*da0073e9SAndroid Build Coastguard Worker TORCH_CHECK_WITH(DynamicLibraryError, false, "Error in dlopen for library ", name, "and ", alt_name);
34*da0073e9SAndroid Build Coastguard Worker }
35*da0073e9SAndroid Build Coastguard Worker } else {
36*da0073e9SAndroid Build Coastguard Worker TORCH_CHECK_WITH(DynamicLibraryError, false, "Error in dlopen: ", dlerror());
37*da0073e9SAndroid Build Coastguard Worker }
38*da0073e9SAndroid Build Coastguard Worker }
39*da0073e9SAndroid Build Coastguard Worker }
40*da0073e9SAndroid Build Coastguard Worker
sym(const char * name)41*da0073e9SAndroid Build Coastguard Worker void* DynamicLibrary::sym(const char* name) {
42*da0073e9SAndroid Build Coastguard Worker AT_ASSERT(handle);
43*da0073e9SAndroid Build Coastguard Worker return checkDL(dlsym(handle, name));
44*da0073e9SAndroid Build Coastguard Worker }
45*da0073e9SAndroid Build Coastguard Worker
~DynamicLibrary()46*da0073e9SAndroid Build Coastguard Worker DynamicLibrary::~DynamicLibrary() {
47*da0073e9SAndroid Build Coastguard Worker if (!handle || leak_handle) {
48*da0073e9SAndroid Build Coastguard Worker return;
49*da0073e9SAndroid Build Coastguard Worker }
50*da0073e9SAndroid Build Coastguard Worker dlclose(handle);
51*da0073e9SAndroid Build Coastguard Worker }
52*da0073e9SAndroid Build Coastguard Worker
53*da0073e9SAndroid Build Coastguard Worker #else
54*da0073e9SAndroid Build Coastguard Worker
55*da0073e9SAndroid Build Coastguard Worker // Windows
56*da0073e9SAndroid Build Coastguard Worker
57*da0073e9SAndroid Build Coastguard Worker DynamicLibrary::DynamicLibrary(const char* name, const char* alt_name, bool leak_handle_): leak_handle(leak_handle_) {
58*da0073e9SAndroid Build Coastguard Worker // NOLINTNEXTLINE(hicpp-signed-bitwise)
59*da0073e9SAndroid Build Coastguard Worker HMODULE theModule;
60*da0073e9SAndroid Build Coastguard Worker bool reload = true;
61*da0073e9SAndroid Build Coastguard Worker auto wname = c10::u8u16(name);
62*da0073e9SAndroid Build Coastguard Worker // Check if LOAD_LIBRARY_SEARCH_DEFAULT_DIRS is supported
63*da0073e9SAndroid Build Coastguard Worker if (GetProcAddress(GetModuleHandleW(L"KERNEL32.DLL"), "AddDllDirectory") != NULL) {
64*da0073e9SAndroid Build Coastguard Worker theModule = LoadLibraryExW(
65*da0073e9SAndroid Build Coastguard Worker wname.c_str(),
66*da0073e9SAndroid Build Coastguard Worker NULL,
67*da0073e9SAndroid Build Coastguard Worker LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
68*da0073e9SAndroid Build Coastguard Worker if (theModule != NULL || (GetLastError() != ERROR_MOD_NOT_FOUND)) {
69*da0073e9SAndroid Build Coastguard Worker reload = false;
70*da0073e9SAndroid Build Coastguard Worker }
71*da0073e9SAndroid Build Coastguard Worker }
72*da0073e9SAndroid Build Coastguard Worker
73*da0073e9SAndroid Build Coastguard Worker if (reload) {
74*da0073e9SAndroid Build Coastguard Worker theModule = LoadLibraryW(wname.c_str());
75*da0073e9SAndroid Build Coastguard Worker }
76*da0073e9SAndroid Build Coastguard Worker
77*da0073e9SAndroid Build Coastguard Worker if (theModule) {
78*da0073e9SAndroid Build Coastguard Worker handle = theModule;
79*da0073e9SAndroid Build Coastguard Worker } else {
80*da0073e9SAndroid Build Coastguard Worker char buf[256];
81*da0073e9SAndroid Build Coastguard Worker DWORD dw = GetLastError();
82*da0073e9SAndroid Build Coastguard Worker FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
83*da0073e9SAndroid Build Coastguard Worker NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
84*da0073e9SAndroid Build Coastguard Worker buf, (sizeof(buf) / sizeof(char)), NULL);
85*da0073e9SAndroid Build Coastguard Worker TORCH_CHECK_WITH(DynamicLibraryError, false, "error in LoadLibrary for ", name, ". WinError ", dw, ": ", buf);
86*da0073e9SAndroid Build Coastguard Worker }
87*da0073e9SAndroid Build Coastguard Worker }
88*da0073e9SAndroid Build Coastguard Worker
89*da0073e9SAndroid Build Coastguard Worker void* DynamicLibrary::sym(const char* name) {
90*da0073e9SAndroid Build Coastguard Worker AT_ASSERT(handle);
91*da0073e9SAndroid Build Coastguard Worker FARPROC procAddress = GetProcAddress((HMODULE)handle, name);
92*da0073e9SAndroid Build Coastguard Worker if (!procAddress) {
93*da0073e9SAndroid Build Coastguard Worker TORCH_CHECK_WITH(DynamicLibraryError, false, "error in GetProcAddress");
94*da0073e9SAndroid Build Coastguard Worker }
95*da0073e9SAndroid Build Coastguard Worker return (void*)procAddress;
96*da0073e9SAndroid Build Coastguard Worker }
97*da0073e9SAndroid Build Coastguard Worker
98*da0073e9SAndroid Build Coastguard Worker DynamicLibrary::~DynamicLibrary() {
99*da0073e9SAndroid Build Coastguard Worker if (!handle || leak_handle) {
100*da0073e9SAndroid Build Coastguard Worker return;
101*da0073e9SAndroid Build Coastguard Worker }
102*da0073e9SAndroid Build Coastguard Worker FreeLibrary((HMODULE)handle);
103*da0073e9SAndroid Build Coastguard Worker }
104*da0073e9SAndroid Build Coastguard Worker
105*da0073e9SAndroid Build Coastguard Worker #endif
106*da0073e9SAndroid Build Coastguard Worker #endif
107*da0073e9SAndroid Build Coastguard Worker
108*da0073e9SAndroid Build Coastguard Worker } // namespace at
109