lok: vcl: fix multiple floatwin removal case more robustly.
[LibreOffice.git] / sal / osl / unx / module.cxx
blob571770248c1c4399e4bb17a554bf4c9cfa79f240
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <sal/log.hxx>
23 #include <sal/types.h>
24 #include <osl/module.h>
25 #include <osl/thread.h>
26 #include <osl/process.h>
27 #include <osl/file.h>
28 #include <rtl/string.hxx>
29 #include <rtl/ustring.hxx>
30 #include <assert.h>
31 #include "system.hxx"
32 #include "file_url.hxx"
34 #ifdef AIX
35 #include <sys/ldr.h>
36 #endif
38 #ifdef ANDROID
39 #include <osl/detail/android-bootstrap.h>
40 #endif
42 static bool getModulePathFromAddress(void * address, rtl_String ** path) {
43 bool result = false;
44 // We do want to have this functionality also in the
45 // DISABLE_DYNLOADING case, I think?
46 #if defined(AIX)
47 int size = 4 * 1024;
48 char *buf, *filename=NULL;
49 struct ld_info *lp;
51 if ((buf = (char*)malloc(size)) == NULL)
52 return false;
54 //figure out how big a buffer we need
55 while (loadquery(L_GETINFO, buf, size) == -1 && errno == ENOMEM)
57 size += 4 * 1024;
58 free(buf);
59 if ((buf = (char*)malloc(size)) == NULL)
60 return false;
63 lp = (struct ld_info*) buf;
64 while (lp)
66 unsigned long start = (unsigned long)lp->ldinfo_dataorg;
67 unsigned long end = start + lp->ldinfo_datasize;
68 if (start <= (unsigned long)address && end > (unsigned long)address)
70 filename = lp->ldinfo_filename;
71 break;
73 if (!lp->ldinfo_next)
74 break;
75 lp = (struct ld_info*) ((char *) lp + lp->ldinfo_next);
78 if (filename)
80 rtl_string_newFromStr(path, filename);
81 result = sal_True;
83 else
85 result = sal_False;
88 free(buf);
89 #else
90 Dl_info dl_info;
92 #if defined(ANDROID) && !defined(DISABLE_DYNLOADING)
93 result = lo_dladdr(address, &dl_info) != 0;
94 #else
95 result = dladdr(address, &dl_info) != 0;
96 #endif
98 if (result)
100 rtl_string_newFromStr(path, dl_info.dli_fname);
101 #if defined(ANDROID) && !defined(DISABLE_DYNLOADING)
102 free((void *) dl_info.dli_fname);
103 #endif
105 #endif
106 return result;
109 #ifndef DISABLE_DYNLOADING
111 /*****************************************************************************/
112 /* osl_loadModule */
113 /*****************************************************************************/
115 oslModule SAL_CALL osl_loadModule(rtl_uString *ustrModuleName, sal_Int32 nRtldMode)
117 oslModule pModule=nullptr;
118 rtl_uString* ustrTmp = nullptr;
120 SAL_WARN_IF(ustrModuleName == nullptr, "sal.osl", "string is not valid");
122 /* ensure ustrTmp hold valid string */
123 if (osl_getSystemPathFromFileURL(ustrModuleName, &ustrTmp) != osl_File_E_None)
124 rtl_uString_assign(&ustrTmp, ustrModuleName);
126 if (ustrTmp)
128 char buffer[PATH_MAX];
130 if (UnicodeToText(buffer, PATH_MAX, ustrTmp->buffer, ustrTmp->length))
131 pModule = osl_loadModuleAscii(buffer, nRtldMode);
132 rtl_uString_release(ustrTmp);
135 return pModule;
138 /*****************************************************************************/
139 /* osl_loadModuleAscii */
140 /*****************************************************************************/
142 oslModule SAL_CALL osl_loadModuleAscii(const sal_Char *pModuleName, sal_Int32 nRtldMode)
144 SAL_WARN_IF(
145 ((nRtldMode & SAL_LOADMODULE_LAZY) != 0
146 && (nRtldMode & SAL_LOADMODULE_NOW) != 0),
147 "sal.osl", "only either LAZY or NOW");
148 if (pModuleName)
150 #ifdef ANDROID
151 (void) nRtldMode;
152 void *pLib = lo_dlopen(pModuleName);
153 #else
154 int rtld_mode =
155 ((nRtldMode & SAL_LOADMODULE_NOW) ? RTLD_NOW : RTLD_LAZY) |
156 ((nRtldMode & SAL_LOADMODULE_GLOBAL) ? RTLD_GLOBAL : RTLD_LOCAL);
157 void* pLib = dlopen(pModuleName, rtld_mode);
159 SAL_INFO_IF(
160 pLib == nullptr, "sal.osl",
161 "dlopen(" << pModuleName << ", " << rtld_mode << "): "
162 << dlerror());
163 #endif
164 return pLib;
166 return nullptr;
169 oslModule osl_loadModuleRelativeAscii(
170 oslGenericFunction baseModule, char const * relativePath, sal_Int32 mode)
172 assert(relativePath && "illegal argument");
173 if (relativePath[0] == '/') {
174 return osl_loadModuleAscii(relativePath, mode);
176 rtl_String * path = nullptr;
177 rtl_String * suffix = nullptr;
178 oslModule module;
179 if (!getModulePathFromAddress(
180 reinterpret_cast< void * >(baseModule), &path))
182 return nullptr;
184 rtl_string_newFromStr_WithLength(
185 &path, path->buffer,
186 (rtl_str_lastIndexOfChar_WithLength(path->buffer, path->length, '/')
187 + 1));
188 /* cut off everything after the last slash; should the original path
189 contain no slash, the resulting path is the empty string */
190 rtl_string_newFromStr(&suffix, relativePath);
191 rtl_string_newConcat(&path, path, suffix);
192 rtl_string_release(suffix);
193 module = osl_loadModuleAscii(path->buffer, mode);
194 rtl_string_release(path);
195 return module;
198 #endif // !DISABLE_DYNLOADING
200 /*****************************************************************************/
201 /* osl_getModuleHandle */
202 /*****************************************************************************/
204 sal_Bool SAL_CALL
205 osl_getModuleHandle(rtl_uString *, oslModule *pResult)
207 #if !defined(DISABLE_DYNLOADING) || defined(IOS)
208 *pResult = static_cast<oslModule>(RTLD_DEFAULT);
209 #else
210 *pResult = nullptr;
211 #endif
212 return true;
215 #ifndef DISABLE_DYNLOADING
217 /*****************************************************************************/
218 /* osl_unloadModule */
219 /*****************************************************************************/
220 void SAL_CALL osl_unloadModule(oslModule hModule)
222 if (hModule)
224 #ifdef ANDROID
225 int nRet = lo_dlclose(hModule);
226 #else
227 int nRet = dlclose(hModule);
228 #endif
229 SAL_INFO_IF(
230 nRet != 0, "sal.osl", "dlclose(" << hModule << "): " << dlerror());
234 #endif // !DISABLE_DYNLOADING
236 namespace {
238 void * getSymbol(oslModule module, char const * symbol) {
239 assert(symbol != nullptr);
240 // We do want to use dlsym() also in the DISABLE_DYNLOADING case
241 // just to look up symbols in the static executable, I think:
242 void * p = dlsym(module, symbol);
243 SAL_INFO_IF(
244 p == nullptr, "sal.osl",
245 "dlsym(" << module << ", " << symbol << "): " << dlerror());
246 return p;
251 /*****************************************************************************/
252 /* osl_getSymbol */
253 /*****************************************************************************/
254 void* SAL_CALL
255 osl_getSymbol(oslModule Module, rtl_uString* pSymbolName)
257 // Arbitrarily using UTF-8:
258 OString s;
259 if (!OUString::unacquired(&pSymbolName).convertToString(
260 &s, RTL_TEXTENCODING_UTF8,
261 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
262 RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
264 SAL_INFO(
265 "sal.osl", "cannot convert \"" << OUString::unacquired(&pSymbolName)
266 << "\" to UTF-8");
267 return nullptr;
269 if (s.indexOf('\0') != -1) {
270 SAL_INFO("sal.osl", "\"" << s << "\" contains embedded NUL");
271 return nullptr;
273 return getSymbol(Module, s.getStr());
276 /*****************************************************************************/
277 /* osl_getAsciiFunctionSymbol */
278 /*****************************************************************************/
279 oslGenericFunction SAL_CALL
280 osl_getAsciiFunctionSymbol(oslModule Module, const sal_Char *pSymbol)
282 return reinterpret_cast<oslGenericFunction>(getSymbol(Module, pSymbol));
283 // requires conditionally-supported conversion from void * to function
284 // pointer
287 /*****************************************************************************/
288 /* osl_getFunctionSymbol */
289 /*****************************************************************************/
290 oslGenericFunction SAL_CALL
291 osl_getFunctionSymbol(oslModule module, rtl_uString *puFunctionSymbolName)
293 return reinterpret_cast<oslGenericFunction>(
294 osl_getSymbol(module, puFunctionSymbolName));
295 // requires conditionally-supported conversion from void * to function
296 // pointer
299 /*****************************************************************************/
300 /* osl_getModuleURLFromAddress */
301 /*****************************************************************************/
302 sal_Bool SAL_CALL osl_getModuleURLFromAddress(void * addr, rtl_uString ** ppLibraryUrl)
304 bool result = false;
305 rtl_String * path = nullptr;
306 if (getModulePathFromAddress(addr, &path))
308 rtl_uString * workDir = nullptr;
309 osl_getProcessWorkingDir(&workDir);
310 if (workDir)
312 rtl_string2UString(ppLibraryUrl,
313 path->buffer,
314 path->length,
315 osl_getThreadTextEncoding(),
316 OSTRING_TO_OUSTRING_CVTFLAGS);
318 SAL_WARN_IF(
319 *ppLibraryUrl == nullptr, "sal.osl", "rtl_string2UString failed");
320 osl_getFileURLFromSystemPath(*ppLibraryUrl, ppLibraryUrl);
321 osl_getAbsoluteFileURL(workDir, *ppLibraryUrl, ppLibraryUrl);
322 SAL_INFO("sal.osl", "osl_getModuleURLFromAddress(" << addr << ") => " << OUString(*ppLibraryUrl));
324 rtl_uString_release(workDir);
325 result = true;
327 else
329 result = false;
331 rtl_string_release(path);
333 return result;
336 /*****************************************************************************/
337 /* osl_getModuleURLFromFunctionAddress */
338 /*****************************************************************************/
339 sal_Bool SAL_CALL osl_getModuleURLFromFunctionAddress(oslGenericFunction addr, rtl_uString ** ppLibraryUrl)
341 return osl_getModuleURLFromAddress(
342 reinterpret_cast<void*>(addr), ppLibraryUrl);
343 // requires conditionally-supported conversion from function pointer to
344 // void *
347 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */