xref: /aosp_15_r20/libnativehelper/DlHelp.c (revision 0797b24ee566c78eb48500180cb4bf71f81c8aab)
1*0797b24eSAndroid Build Coastguard Worker /*
2*0797b24eSAndroid Build Coastguard Worker  * Copyright (C) 2020 The Android Open Source Project
3*0797b24eSAndroid Build Coastguard Worker  *
4*0797b24eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*0797b24eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*0797b24eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*0797b24eSAndroid Build Coastguard Worker  *
8*0797b24eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*0797b24eSAndroid Build Coastguard Worker  *
10*0797b24eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*0797b24eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*0797b24eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*0797b24eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*0797b24eSAndroid Build Coastguard Worker  * limitations under the License.
15*0797b24eSAndroid Build Coastguard Worker  */
16*0797b24eSAndroid Build Coastguard Worker 
17*0797b24eSAndroid Build Coastguard Worker #include "DlHelp.h"
18*0797b24eSAndroid Build Coastguard Worker 
19*0797b24eSAndroid Build Coastguard Worker #include <stdbool.h>
20*0797b24eSAndroid Build Coastguard Worker 
21*0797b24eSAndroid Build Coastguard Worker #ifdef WIN32_LEAN_AND_MEAN
22*0797b24eSAndroid Build Coastguard Worker #include <stdio.h>
23*0797b24eSAndroid Build Coastguard Worker #include <windows.h>
24*0797b24eSAndroid Build Coastguard Worker #else
25*0797b24eSAndroid Build Coastguard Worker #include <dlfcn.h>
26*0797b24eSAndroid Build Coastguard Worker #endif
27*0797b24eSAndroid Build Coastguard Worker 
DlOpenLibrary(const char * filename)28*0797b24eSAndroid Build Coastguard Worker DlLibrary DlOpenLibrary(const char* filename) {
29*0797b24eSAndroid Build Coastguard Worker #ifdef _WIN32
30*0797b24eSAndroid Build Coastguard Worker   return LoadLibrary(filename);
31*0797b24eSAndroid Build Coastguard Worker #else
32*0797b24eSAndroid Build Coastguard Worker   // Load with RTLD_NODELETE in order to ensure that libart.so is not unmapped when it is closed.
33*0797b24eSAndroid Build Coastguard Worker   // This is due to the fact that it is possible that some threads might have yet to finish
34*0797b24eSAndroid Build Coastguard Worker   // exiting even after JNI_DeleteJavaVM returns, which can lead to segfaults if the library is
35*0797b24eSAndroid Build Coastguard Worker   // unloaded.
36*0797b24eSAndroid Build Coastguard Worker   return dlopen(filename, RTLD_NOW | RTLD_NODELETE);
37*0797b24eSAndroid Build Coastguard Worker #endif
38*0797b24eSAndroid Build Coastguard Worker }
39*0797b24eSAndroid Build Coastguard Worker 
DlCloseLibrary(DlLibrary library)40*0797b24eSAndroid Build Coastguard Worker bool DlCloseLibrary(DlLibrary library) {
41*0797b24eSAndroid Build Coastguard Worker #ifdef _WIN32
42*0797b24eSAndroid Build Coastguard Worker   return (FreeLibrary(library) == TRUE);
43*0797b24eSAndroid Build Coastguard Worker #else
44*0797b24eSAndroid Build Coastguard Worker   return (dlclose(library) == 0);
45*0797b24eSAndroid Build Coastguard Worker #endif
46*0797b24eSAndroid Build Coastguard Worker }
47*0797b24eSAndroid Build Coastguard Worker 
DlGetSymbol(DlLibrary handle,const char * symbol)48*0797b24eSAndroid Build Coastguard Worker DlSymbol DlGetSymbol(DlLibrary handle, const char* symbol) {
49*0797b24eSAndroid Build Coastguard Worker #ifdef _WIN32
50*0797b24eSAndroid Build Coastguard Worker   return (DlSymbol) GetProcAddress(handle, symbol);
51*0797b24eSAndroid Build Coastguard Worker #else
52*0797b24eSAndroid Build Coastguard Worker   return dlsym(handle, symbol);
53*0797b24eSAndroid Build Coastguard Worker #endif
54*0797b24eSAndroid Build Coastguard Worker }
55*0797b24eSAndroid Build Coastguard Worker 
DlGetError()56*0797b24eSAndroid Build Coastguard Worker const char* DlGetError() {
57*0797b24eSAndroid Build Coastguard Worker #ifdef _WIN32
58*0797b24eSAndroid Build Coastguard Worker   static char buffer[256];
59*0797b24eSAndroid Build Coastguard Worker 
60*0797b24eSAndroid Build Coastguard Worker   DWORD cause = GetLastError();
61*0797b24eSAndroid Build Coastguard Worker   DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
62*0797b24eSAndroid Build Coastguard Worker   DWORD length = FormatMessageA(flags, NULL, cause, 0, buffer, sizeof(buffer), NULL);
63*0797b24eSAndroid Build Coastguard Worker   if (length == 0) {
64*0797b24eSAndroid Build Coastguard Worker     snprintf(buffer, sizeof(buffer),
65*0797b24eSAndroid Build Coastguard Worker              "Error %lu while retrieving message for error %lu",
66*0797b24eSAndroid Build Coastguard Worker              GetLastError(), cause);
67*0797b24eSAndroid Build Coastguard Worker     length = strlen(buffer);
68*0797b24eSAndroid Build Coastguard Worker   }
69*0797b24eSAndroid Build Coastguard Worker 
70*0797b24eSAndroid Build Coastguard Worker   // Trim trailing whitespace.
71*0797b24eSAndroid Build Coastguard Worker   for (DWORD i = length - 1; i > 0; --i) {
72*0797b24eSAndroid Build Coastguard Worker     if (!isspace(buffer[i])) {
73*0797b24eSAndroid Build Coastguard Worker       break;
74*0797b24eSAndroid Build Coastguard Worker     }
75*0797b24eSAndroid Build Coastguard Worker     buffer[i] = '\0';
76*0797b24eSAndroid Build Coastguard Worker   }
77*0797b24eSAndroid Build Coastguard Worker 
78*0797b24eSAndroid Build Coastguard Worker   return buffer;
79*0797b24eSAndroid Build Coastguard Worker #else
80*0797b24eSAndroid Build Coastguard Worker   return dlerror();
81*0797b24eSAndroid Build Coastguard Worker #endif
82*0797b24eSAndroid Build Coastguard Worker }
83