update credits
[LibreOffice.git] / sal / osl / unx / module.cxx
blobcc615bff70898538d67985ed9c06ca71683daa39
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>
29 #include "system.h"
31 #ifdef AIX
32 #include <sys/ldr.h>
33 #endif
35 #ifdef ANDROID
36 #include <osl/detail/android-bootstrap.h>
37 #endif
39 /* implemented in file.c */
40 extern "C" int UnicodeToText(char *, size_t, const sal_Unicode *, sal_Int32);
42 static sal_Bool getModulePathFromAddress(void * address, rtl_String ** path) {
43 sal_Bool result = sal_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);
94 #else
95 result = dladdr(address, &dl_info);
96 #endif
98 if (result != 0)
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
104 result = sal_True;
106 else
108 result = sal_False;
110 #endif
111 return result;
115 #ifndef DISABLE_DYNLOADING
117 /*****************************************************************************/
118 /* osl_loadModule */
119 /*****************************************************************************/
121 oslModule SAL_CALL osl_loadModule(rtl_uString *ustrModuleName, sal_Int32 nRtldMode)
123 oslModule pModule=0;
124 rtl_uString* ustrTmp = NULL;
126 SAL_WARN_IF(ustrModuleName == 0, "sal.osl", "string is not valid");
128 /* ensure ustrTmp hold valid string */
129 if (osl_File_E_None != osl_getSystemPathFromFileURL(ustrModuleName, &ustrTmp))
130 rtl_uString_assign(&ustrTmp, ustrModuleName);
132 if (ustrTmp)
134 char buffer[PATH_MAX];
136 if (UnicodeToText(buffer, PATH_MAX, ustrTmp->buffer, ustrTmp->length))
137 pModule = osl_loadModuleAscii(buffer, nRtldMode);
138 rtl_uString_release(ustrTmp);
141 return pModule;
144 /*****************************************************************************/
145 /* osl_loadModuleAscii */
146 /*****************************************************************************/
148 oslModule SAL_CALL osl_loadModuleAscii(const sal_Char *pModuleName, sal_Int32 nRtldMode)
150 SAL_WARN_IF(
151 ((nRtldMode & SAL_LOADMODULE_LAZY) != 0
152 && (nRtldMode & SAL_LOADMODULE_NOW) != 0),
153 "sal.osl", "only either LAZY or NOW");
154 if (pModuleName)
156 #ifdef ANDROID
157 (void) nRtldMode;
158 void *pLib = lo_dlopen(pModuleName);
159 #else
160 int rtld_mode =
161 ((nRtldMode & SAL_LOADMODULE_NOW) ? RTLD_NOW : RTLD_LAZY) |
162 ((nRtldMode & SAL_LOADMODULE_GLOBAL) ? RTLD_GLOBAL : RTLD_LOCAL);
163 void* pLib = dlopen(pModuleName, rtld_mode);
165 SAL_INFO_IF(
166 pLib == 0, "sal.osl",
167 "dlopen(" << pModuleName << ", " << rtld_mode << "): "
168 << dlerror());
169 #endif
170 return ((oslModule)(pLib));
172 return NULL;
175 oslModule osl_loadModuleRelativeAscii(
176 oslGenericFunction baseModule, char const * relativePath, sal_Int32 mode)
178 SAL_WARN_IF(relativePath == 0, "sal.osl", "illegal argument");
179 if (relativePath[0] == '/') {
180 return osl_loadModuleAscii(relativePath, mode);
181 } else {
182 rtl_String * path = NULL;
183 rtl_String * suffix = NULL;
184 oslModule module;
185 if (!getModulePathFromAddress(
186 reinterpret_cast< void * >(baseModule), &path))
188 return NULL;
190 rtl_string_newFromStr_WithLength(
191 &path, path->buffer,
192 (rtl_str_lastIndexOfChar_WithLength(path->buffer, path->length, '/')
193 + 1));
194 /* cut off everything after the last slash; should the original path
195 contain no slash, the resulting path is the empty string */
196 rtl_string_newFromStr(&suffix, relativePath);
197 rtl_string_newConcat(&path, path, suffix);
198 rtl_string_release(suffix);
199 module = osl_loadModuleAscii(path->buffer, mode);
200 rtl_string_release(path);
201 return module;
205 #endif // !DISABLE_DYNLOADING
207 /*****************************************************************************/
208 /* osl_getModuleHandle */
209 /*****************************************************************************/
211 sal_Bool SAL_CALL
212 osl_getModuleHandle(rtl_uString *, oslModule *pResult)
214 #if !defined(DISABLE_DYNLOADING) || defined(IOS)
215 *pResult = (oslModule) RTLD_DEFAULT;
216 #else
217 *pResult = NULL;
218 #endif
219 return sal_True;
222 #ifndef DISABLE_DYNLOADING
224 /*****************************************************************************/
225 /* osl_unloadModule */
226 /*****************************************************************************/
227 void SAL_CALL osl_unloadModule(oslModule hModule)
229 if (hModule)
231 #ifdef ANDROID
232 int nRet = lo_dlclose(hModule);
233 #else
234 int nRet = dlclose(hModule);
235 #endif
236 SAL_INFO_IF(
237 nRet != 0, "sal.osl", "dlclose(" << hModule << "): " << dlerror());
241 #endif // !DISABLE_DYNLOADING
243 /*****************************************************************************/
244 /* osl_getSymbol */
245 /*****************************************************************************/
246 void* SAL_CALL
247 osl_getSymbol(oslModule Module, rtl_uString* pSymbolName)
249 return (void *) osl_getFunctionSymbol(Module, pSymbolName);
253 /*****************************************************************************/
254 /* osl_getAsciiFunctionSymbol */
255 /*****************************************************************************/
256 oslGenericFunction SAL_CALL
257 osl_getAsciiFunctionSymbol(oslModule Module, const sal_Char *pSymbol)
259 void *fcnAddr = NULL;
261 // We do want to use dlsym() also in the DISABLE_DYNLOADING case
262 // just to look up symbols in the static executable, I think.
263 if (pSymbol)
265 fcnAddr = dlsym(Module, pSymbol);
266 SAL_INFO_IF(
267 fcnAddr == 0, "sal.osl",
268 "dlsym(" << Module << ", " << pSymbol << "): " << dlerror());
271 return (oslGenericFunction) fcnAddr;
274 /*****************************************************************************/
275 /* osl_getFunctionSymbol */
276 /*****************************************************************************/
277 oslGenericFunction SAL_CALL
278 osl_getFunctionSymbol(oslModule module, rtl_uString *puFunctionSymbolName)
280 oslGenericFunction pSymbol = NULL;
282 if( puFunctionSymbolName )
284 rtl_String* pSymbolName = NULL;
286 rtl_uString2String( &pSymbolName,
287 rtl_uString_getStr(puFunctionSymbolName),
288 rtl_uString_getLength(puFunctionSymbolName),
289 RTL_TEXTENCODING_UTF8,
290 OUSTRING_TO_OSTRING_CVTFLAGS );
292 if( pSymbolName != NULL )
294 pSymbol = osl_getAsciiFunctionSymbol(module, rtl_string_getStr(pSymbolName));
295 rtl_string_release(pSymbolName);
299 return pSymbol;
302 /*****************************************************************************/
303 /* osl_getModuleURLFromAddress */
304 /*****************************************************************************/
305 sal_Bool SAL_CALL osl_getModuleURLFromAddress(void * addr, rtl_uString ** ppLibraryUrl)
307 sal_Bool result = sal_False;
308 rtl_String * path = NULL;
309 if (getModulePathFromAddress(addr, &path))
311 rtl_uString * workDir = NULL;
312 osl_getProcessWorkingDir(&workDir);
313 if (workDir)
315 SAL_INFO(
316 "sal.osl", "osl_getModuleURLFromAddress: " << path->buffer);
317 rtl_string2UString(ppLibraryUrl,
318 path->buffer,
319 path->length,
320 osl_getThreadTextEncoding(),
321 OSTRING_TO_OUSTRING_CVTFLAGS);
323 SAL_WARN_IF(
324 *ppLibraryUrl == 0, "sal.osl", "rtl_string2UString failed");
325 osl_getFileURLFromSystemPath(*ppLibraryUrl, ppLibraryUrl);
326 osl_getAbsoluteFileURL(workDir, *ppLibraryUrl, ppLibraryUrl);
328 rtl_uString_release(workDir);
329 result = sal_True;
331 else
333 result = sal_False;
335 rtl_string_release(path);
337 return result;
340 /*****************************************************************************/
341 /* osl_getModuleURLFromFunctionAddress */
342 /*****************************************************************************/
343 sal_Bool SAL_CALL osl_getModuleURLFromFunctionAddress(oslGenericFunction addr, rtl_uString ** ppLibraryUrl)
345 return osl_getModuleURLFromAddress((void*)addr, ppLibraryUrl);
348 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */