Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "sal/config.h"
21 :
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 :
29 : #include "system.h"
30 :
31 : #ifdef AIX
32 : #include <sys/ldr.h>
33 : #endif
34 :
35 : #ifdef ANDROID
36 : #include <osl/detail/android-bootstrap.h>
37 : #endif
38 :
39 : /* implemented in file.c */
40 : extern "C" int UnicodeToText(char *, size_t, const sal_Unicode *, sal_Int32);
41 :
42 14999 : static sal_Bool getModulePathFromAddress(void * address, rtl_String ** path) {
43 14999 : 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;
50 :
51 : if ((buf = malloc(size)) == NULL)
52 : return result;
53 :
54 : while(loadquery(L_GETINFO, buf, size) == -1 && errno == ENOMEM)
55 : {
56 : size += 4 * 1024;
57 : if ((buf = malloc(size)) == NULL)
58 : break;
59 : }
60 :
61 : lp = (struct ld_info*) buf;
62 : while (lp)
63 : {
64 : unsigned long start = (unsigned long)lp->ldinfo_dataorg;
65 : unsigned long end = start + lp->ldinfo_datasize;
66 : if (start <= (unsigned long)address && end > (unsigned long)address)
67 : {
68 : filename = lp->ldinfo_filename;
69 : break;
70 : }
71 : if (!lp->ldinfo_next)
72 : break;
73 : lp = (struct ld_info*) ((char *) lp + lp->ldinfo_next);
74 : }
75 :
76 : if (filename)
77 : {
78 : rtl_string_newFromStr(path, filename);
79 : result = sal_True;
80 : }
81 : else
82 : {
83 : result = sal_False;
84 : }
85 :
86 : free(buf);
87 : #else
88 : Dl_info dl_info;
89 :
90 : #if defined(ANDROID) && !defined(DISABLE_DYNLOADING)
91 : result = lo_dladdr(address, &dl_info);
92 : #else
93 14999 : result = dladdr(address, &dl_info);
94 : #endif
95 :
96 14999 : if (result != 0)
97 : {
98 14999 : rtl_string_newFromStr(path, dl_info.dli_fname);
99 : #if defined(ANDROID) && !defined(DISABLE_DYNLOADING)
100 : free((void *) dl_info.dli_fname);
101 : #endif
102 14999 : result = sal_True;
103 : }
104 : else
105 : {
106 0 : result = sal_False;
107 : }
108 : #endif
109 14999 : return result;
110 : }
111 :
112 :
113 : #ifndef DISABLE_DYNLOADING
114 :
115 : /*****************************************************************************/
116 : /* osl_loadModule */
117 : /*****************************************************************************/
118 :
119 20619 : oslModule SAL_CALL osl_loadModule(rtl_uString *ustrModuleName, sal_Int32 nRtldMode)
120 : {
121 20619 : oslModule pModule=0;
122 20619 : rtl_uString* ustrTmp = NULL;
123 :
124 : SAL_WARN_IF(ustrModuleName == 0, "sal.osl", "string is not valid");
125 :
126 : /* ensure ustrTmp hold valid string */
127 20619 : if (osl_File_E_None != osl_getSystemPathFromFileURL(ustrModuleName, &ustrTmp))
128 0 : rtl_uString_assign(&ustrTmp, ustrModuleName);
129 :
130 20619 : if (ustrTmp)
131 : {
132 : char buffer[PATH_MAX];
133 :
134 20619 : if (UnicodeToText(buffer, PATH_MAX, ustrTmp->buffer, ustrTmp->length))
135 20619 : pModule = osl_loadModuleAscii(buffer, nRtldMode);
136 20619 : rtl_uString_release(ustrTmp);
137 : }
138 :
139 20619 : return pModule;
140 : }
141 :
142 : /*****************************************************************************/
143 : /* osl_loadModuleAscii */
144 : /*****************************************************************************/
145 :
146 20661 : oslModule SAL_CALL osl_loadModuleAscii(const sal_Char *pModuleName, sal_Int32 nRtldMode)
147 : {
148 : SAL_WARN_IF(
149 : ((nRtldMode & SAL_LOADMODULE_LAZY) != 0
150 : && (nRtldMode & SAL_LOADMODULE_NOW) != 0),
151 : "sal.osl", "only either LAZY or NOW");
152 20661 : if (pModuleName)
153 : {
154 : #ifdef ANDROID
155 : (void) nRtldMode;
156 : void *pLib = lo_dlopen(pModuleName);
157 : #else
158 : int rtld_mode =
159 : ((nRtldMode & SAL_LOADMODULE_NOW) ? RTLD_NOW : RTLD_LAZY) |
160 20661 : ((nRtldMode & SAL_LOADMODULE_GLOBAL) ? RTLD_GLOBAL : RTLD_LOCAL);
161 20661 : void* pLib = dlopen(pModuleName, rtld_mode);
162 :
163 : SAL_INFO_IF(
164 : pLib == 0, "sal.osl",
165 : "dlopen(" << pModuleName << ", " << rtld_mode << "): "
166 : << dlerror());
167 : #endif
168 20661 : return ((oslModule)(pLib));
169 : }
170 0 : return NULL;
171 : }
172 :
173 42 : oslModule osl_loadModuleRelativeAscii(
174 : oslGenericFunction baseModule, char const * relativePath, sal_Int32 mode)
175 : {
176 : SAL_WARN_IF(relativePath == 0, "sal.osl", "illegal argument");
177 42 : if (relativePath[0] == '/') {
178 0 : return osl_loadModuleAscii(relativePath, mode);
179 : } else {
180 42 : rtl_String * path = NULL;
181 42 : rtl_String * suffix = NULL;
182 : oslModule module;
183 42 : if (!getModulePathFromAddress(
184 42 : reinterpret_cast< void * >(baseModule), &path))
185 : {
186 0 : return NULL;
187 : }
188 : rtl_string_newFromStr_WithLength(
189 : &path, path->buffer,
190 42 : (rtl_str_lastIndexOfChar_WithLength(path->buffer, path->length, '/')
191 42 : + 1));
192 : /* cut off everything after the last slash; should the original path
193 : contain no slash, the resulting path is the empty string */
194 42 : rtl_string_newFromStr(&suffix, relativePath);
195 42 : rtl_string_newConcat(&path, path, suffix);
196 42 : rtl_string_release(suffix);
197 42 : module = osl_loadModuleAscii(path->buffer, mode);
198 42 : rtl_string_release(path);
199 42 : return module;
200 : }
201 : }
202 :
203 : #endif // !DISABLE_DYNLOADING
204 :
205 : /*****************************************************************************/
206 : /* osl_getModuleHandle */
207 : /*****************************************************************************/
208 :
209 : sal_Bool SAL_CALL
210 0 : osl_getModuleHandle(rtl_uString *, oslModule *pResult)
211 : {
212 : #if !defined(DISABLE_DYNLOADING) || defined(IOS)
213 0 : *pResult = (oslModule) RTLD_DEFAULT;
214 : #else
215 : *pResult = NULL;
216 : #endif
217 0 : return sal_True;
218 : }
219 :
220 : #ifndef DISABLE_DYNLOADING
221 :
222 : /*****************************************************************************/
223 : /* osl_unloadModule */
224 : /*****************************************************************************/
225 6514 : void SAL_CALL osl_unloadModule(oslModule hModule)
226 : {
227 6514 : if (hModule)
228 : {
229 : #ifdef ANDROID
230 : int nRet = lo_dlclose(hModule);
231 : #else
232 5700 : int nRet = dlclose(hModule);
233 : #endif
234 : SAL_INFO_IF(
235 : nRet != 0, "sal.osl", "dlclose(" << hModule << "): " << dlerror());
236 : }
237 6514 : }
238 :
239 : #endif // !DISABLE_DYNLOADING
240 :
241 : /*****************************************************************************/
242 : /* osl_getSymbol */
243 : /*****************************************************************************/
244 : void* SAL_CALL
245 6 : osl_getSymbol(oslModule Module, rtl_uString* pSymbolName)
246 : {
247 6 : return (void *) osl_getFunctionSymbol(Module, pSymbolName);
248 : }
249 :
250 :
251 : /*****************************************************************************/
252 : /* osl_getAsciiFunctionSymbol */
253 : /*****************************************************************************/
254 : oslGenericFunction SAL_CALL
255 145724 : osl_getAsciiFunctionSymbol(oslModule Module, const sal_Char *pSymbol)
256 : {
257 145724 : void *fcnAddr = NULL;
258 :
259 : // We do want to use dlsym() also in the DISABLE_DYNLOADING case
260 : // just to look up symbols in the static executable, I think.
261 145724 : if (pSymbol)
262 : {
263 145724 : fcnAddr = dlsym(Module, pSymbol);
264 : SAL_INFO_IF(
265 : fcnAddr == 0, "sal.osl",
266 : "dlsym(" << Module << ", " << pSymbol << "): " << dlerror());
267 : }
268 :
269 145724 : return (oslGenericFunction) fcnAddr;
270 : }
271 :
272 : /*****************************************************************************/
273 : /* osl_getFunctionSymbol */
274 : /*****************************************************************************/
275 : oslGenericFunction SAL_CALL
276 145526 : osl_getFunctionSymbol(oslModule module, rtl_uString *puFunctionSymbolName)
277 : {
278 145526 : oslGenericFunction pSymbol = NULL;
279 :
280 145526 : if( puFunctionSymbolName )
281 : {
282 145526 : rtl_String* pSymbolName = NULL;
283 :
284 : rtl_uString2String( &pSymbolName,
285 145526 : rtl_uString_getStr(puFunctionSymbolName),
286 : rtl_uString_getLength(puFunctionSymbolName),
287 : RTL_TEXTENCODING_UTF8,
288 291052 : OUSTRING_TO_OSTRING_CVTFLAGS );
289 :
290 145526 : if( pSymbolName != NULL )
291 : {
292 145526 : pSymbol = osl_getAsciiFunctionSymbol(module, rtl_string_getStr(pSymbolName));
293 145526 : rtl_string_release(pSymbolName);
294 : }
295 : }
296 :
297 145526 : return pSymbol;
298 : }
299 :
300 : /*****************************************************************************/
301 : /* osl_getModuleURLFromAddress */
302 : /*****************************************************************************/
303 14957 : sal_Bool SAL_CALL osl_getModuleURLFromAddress(void * addr, rtl_uString ** ppLibraryUrl)
304 : {
305 14957 : sal_Bool result = sal_False;
306 14957 : rtl_String * path = NULL;
307 14957 : if (getModulePathFromAddress(addr, &path))
308 : {
309 14957 : rtl_uString * workDir = NULL;
310 14957 : osl_getProcessWorkingDir(&workDir);
311 14957 : if (workDir)
312 : {
313 : SAL_INFO(
314 : "sal.osl", "osl_getModuleURLFromAddress: " << path->buffer);
315 : rtl_string2UString(ppLibraryUrl,
316 : path->buffer,
317 : path->length,
318 14957 : osl_getThreadTextEncoding(),
319 14957 : OSTRING_TO_OUSTRING_CVTFLAGS);
320 :
321 : SAL_WARN_IF(
322 : *ppLibraryUrl == 0, "sal.osl", "rtl_string2UString failed");
323 14957 : osl_getFileURLFromSystemPath(*ppLibraryUrl, ppLibraryUrl);
324 14957 : osl_getAbsoluteFileURL(workDir, *ppLibraryUrl, ppLibraryUrl);
325 :
326 14957 : rtl_uString_release(workDir);
327 14957 : result = sal_True;
328 : }
329 : else
330 : {
331 0 : result = sal_False;
332 : }
333 14957 : rtl_string_release(path);
334 : }
335 14957 : return result;
336 : }
337 :
338 : /*****************************************************************************/
339 : /* osl_getModuleURLFromFunctionAddress */
340 : /*****************************************************************************/
341 14143 : sal_Bool SAL_CALL osl_getModuleURLFromFunctionAddress(oslGenericFunction addr, rtl_uString ** ppLibraryUrl)
342 : {
343 14143 : return osl_getModuleURLFromAddress((void*)addr, ppLibraryUrl);
344 : }
345 :
346 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|