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 : #include <assert.h>
29 : #include "system.h"
30 : #include "file_url.h"
31 :
32 : #ifdef AIX
33 : #include <sys/ldr.h>
34 : #endif
35 :
36 : #ifdef ANDROID
37 : #include <osl/detail/android-bootstrap.h>
38 : #endif
39 :
40 75285 : static bool getModulePathFromAddress(void * address, rtl_String ** path) {
41 75285 : bool result = false;
42 : // We do want to have this functionality also in the
43 : // DISABLE_DYNLOADING case, I think?
44 : #if defined(AIX)
45 : int size = 4 * 1024;
46 : char *buf, *filename=NULL;
47 : struct ld_info *lp;
48 :
49 : if ((buf = (char*)malloc(size)) == NULL)
50 : return false;
51 :
52 : //figure out how big a buffer we need
53 : while (loadquery(L_GETINFO, buf, size) == -1 && errno == ENOMEM)
54 : {
55 : size += 4 * 1024;
56 : free(buf);
57 : if ((buf = (char*)malloc(size)) == NULL)
58 : return false;
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) != 0;
92 : #else
93 75285 : result = dladdr(address, &dl_info) != 0;
94 : #endif
95 :
96 75285 : if (result)
97 : {
98 75285 : 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 : }
103 : #endif
104 75285 : return result;
105 : }
106 :
107 : #ifndef DISABLE_DYNLOADING
108 :
109 : /*****************************************************************************/
110 : /* osl_loadModule */
111 : /*****************************************************************************/
112 :
113 98099 : oslModule SAL_CALL osl_loadModule(rtl_uString *ustrModuleName, sal_Int32 nRtldMode)
114 : {
115 98099 : oslModule pModule=0;
116 98099 : rtl_uString* ustrTmp = NULL;
117 :
118 : SAL_WARN_IF(ustrModuleName == 0, "sal.osl", "string is not valid");
119 :
120 : /* ensure ustrTmp hold valid string */
121 98099 : if (osl_File_E_None != osl_getSystemPathFromFileURL(ustrModuleName, &ustrTmp))
122 666 : rtl_uString_assign(&ustrTmp, ustrModuleName);
123 :
124 98099 : if (ustrTmp)
125 : {
126 : char buffer[PATH_MAX];
127 :
128 98099 : if (UnicodeToText(buffer, PATH_MAX, ustrTmp->buffer, ustrTmp->length))
129 98099 : pModule = osl_loadModuleAscii(buffer, nRtldMode);
130 98099 : rtl_uString_release(ustrTmp);
131 : }
132 :
133 98099 : return pModule;
134 : }
135 :
136 : /*****************************************************************************/
137 : /* osl_loadModuleAscii */
138 : /*****************************************************************************/
139 :
140 98286 : oslModule SAL_CALL osl_loadModuleAscii(const sal_Char *pModuleName, sal_Int32 nRtldMode)
141 : {
142 : SAL_WARN_IF(
143 : ((nRtldMode & SAL_LOADMODULE_LAZY) != 0
144 : && (nRtldMode & SAL_LOADMODULE_NOW) != 0),
145 : "sal.osl", "only either LAZY or NOW");
146 98286 : if (pModuleName)
147 : {
148 : #ifdef ANDROID
149 : (void) nRtldMode;
150 : void *pLib = lo_dlopen(pModuleName);
151 : #else
152 : int rtld_mode =
153 98286 : ((nRtldMode & SAL_LOADMODULE_NOW) ? RTLD_NOW : RTLD_LAZY) |
154 98286 : ((nRtldMode & SAL_LOADMODULE_GLOBAL) ? RTLD_GLOBAL : RTLD_LOCAL);
155 98286 : void* pLib = dlopen(pModuleName, rtld_mode);
156 :
157 : SAL_INFO_IF(
158 : pLib == 0, "sal.osl",
159 : "dlopen(" << pModuleName << ", " << rtld_mode << "): "
160 : << dlerror());
161 : #endif
162 98286 : return ((oslModule)(pLib));
163 : }
164 0 : return NULL;
165 : }
166 :
167 187 : oslModule osl_loadModuleRelativeAscii(
168 : oslGenericFunction baseModule, char const * relativePath, sal_Int32 mode)
169 : {
170 : assert(relativePath && "illegal argument");
171 187 : if (relativePath[0] == '/') {
172 0 : return osl_loadModuleAscii(relativePath, mode);
173 : } else {
174 187 : rtl_String * path = NULL;
175 187 : rtl_String * suffix = NULL;
176 : oslModule module;
177 187 : if (!getModulePathFromAddress(
178 187 : reinterpret_cast< void * >(baseModule), &path))
179 : {
180 0 : return NULL;
181 : }
182 : rtl_string_newFromStr_WithLength(
183 : &path, path->buffer,
184 187 : (rtl_str_lastIndexOfChar_WithLength(path->buffer, path->length, '/')
185 187 : + 1));
186 : /* cut off everything after the last slash; should the original path
187 : contain no slash, the resulting path is the empty string */
188 187 : rtl_string_newFromStr(&suffix, relativePath);
189 187 : rtl_string_newConcat(&path, path, suffix);
190 187 : rtl_string_release(suffix);
191 187 : module = osl_loadModuleAscii(path->buffer, mode);
192 187 : rtl_string_release(path);
193 187 : return module;
194 : }
195 : }
196 :
197 : #endif // !DISABLE_DYNLOADING
198 :
199 : /*****************************************************************************/
200 : /* osl_getModuleHandle */
201 : /*****************************************************************************/
202 :
203 : sal_Bool SAL_CALL
204 0 : osl_getModuleHandle(rtl_uString *, oslModule *pResult)
205 : {
206 : #if !defined(DISABLE_DYNLOADING) || defined(IOS)
207 0 : *pResult = (oslModule) RTLD_DEFAULT;
208 : #else
209 : *pResult = NULL;
210 : #endif
211 0 : return sal_True;
212 : }
213 :
214 : #ifndef DISABLE_DYNLOADING
215 :
216 : /*****************************************************************************/
217 : /* osl_unloadModule */
218 : /*****************************************************************************/
219 78474 : void SAL_CALL osl_unloadModule(oslModule hModule)
220 : {
221 78474 : if (hModule)
222 : {
223 : #ifdef ANDROID
224 : int nRet = lo_dlclose(hModule);
225 : #else
226 54203 : int nRet = dlclose(hModule);
227 : #endif
228 : SAL_INFO_IF(
229 : nRet != 0, "sal.osl", "dlclose(" << hModule << "): " << dlerror());
230 : }
231 78474 : }
232 :
233 : #endif // !DISABLE_DYNLOADING
234 :
235 : /*****************************************************************************/
236 : /* osl_getSymbol */
237 : /*****************************************************************************/
238 : void* SAL_CALL
239 6 : osl_getSymbol(oslModule Module, rtl_uString* pSymbolName)
240 : {
241 6 : return (void *) osl_getFunctionSymbol(Module, pSymbolName);
242 : }
243 :
244 : /*****************************************************************************/
245 : /* osl_getAsciiFunctionSymbol */
246 : /*****************************************************************************/
247 : oslGenericFunction SAL_CALL
248 477955 : osl_getAsciiFunctionSymbol(oslModule Module, const sal_Char *pSymbol)
249 : {
250 477955 : void *fcnAddr = NULL;
251 :
252 : // We do want to use dlsym() also in the DISABLE_DYNLOADING case
253 : // just to look up symbols in the static executable, I think.
254 477955 : if (pSymbol)
255 : {
256 477955 : fcnAddr = dlsym(Module, pSymbol);
257 : SAL_INFO_IF(
258 : fcnAddr == 0, "sal.osl",
259 : "dlsym(" << Module << ", " << pSymbol << "): " << dlerror());
260 : }
261 :
262 477955 : return (oslGenericFunction) fcnAddr;
263 : }
264 :
265 : /*****************************************************************************/
266 : /* osl_getFunctionSymbol */
267 : /*****************************************************************************/
268 : oslGenericFunction SAL_CALL
269 477077 : osl_getFunctionSymbol(oslModule module, rtl_uString *puFunctionSymbolName)
270 : {
271 477077 : oslGenericFunction pSymbol = NULL;
272 :
273 477077 : if( puFunctionSymbolName )
274 : {
275 477077 : rtl_String* pSymbolName = NULL;
276 :
277 : rtl_uString2String( &pSymbolName,
278 477077 : rtl_uString_getStr(puFunctionSymbolName),
279 : rtl_uString_getLength(puFunctionSymbolName),
280 : RTL_TEXTENCODING_UTF8,
281 954154 : OUSTRING_TO_OSTRING_CVTFLAGS );
282 :
283 477077 : if( pSymbolName != NULL )
284 : {
285 477077 : pSymbol = osl_getAsciiFunctionSymbol(module, rtl_string_getStr(pSymbolName));
286 477077 : rtl_string_release(pSymbolName);
287 : }
288 : }
289 :
290 477077 : return pSymbol;
291 : }
292 :
293 : /*****************************************************************************/
294 : /* osl_getModuleURLFromAddress */
295 : /*****************************************************************************/
296 75098 : sal_Bool SAL_CALL osl_getModuleURLFromAddress(void * addr, rtl_uString ** ppLibraryUrl)
297 : {
298 75098 : bool result = false;
299 75098 : rtl_String * path = NULL;
300 75098 : if (getModulePathFromAddress(addr, &path))
301 : {
302 75098 : rtl_uString * workDir = NULL;
303 75098 : osl_getProcessWorkingDir(&workDir);
304 75098 : if (workDir)
305 : {
306 : SAL_INFO(
307 : "sal.osl", "osl_getModuleURLFromAddress: " << path->buffer);
308 : rtl_string2UString(ppLibraryUrl,
309 : path->buffer,
310 : path->length,
311 75098 : osl_getThreadTextEncoding(),
312 75098 : OSTRING_TO_OUSTRING_CVTFLAGS);
313 :
314 : SAL_WARN_IF(
315 : *ppLibraryUrl == 0, "sal.osl", "rtl_string2UString failed");
316 75098 : osl_getFileURLFromSystemPath(*ppLibraryUrl, ppLibraryUrl);
317 75098 : osl_getAbsoluteFileURL(workDir, *ppLibraryUrl, ppLibraryUrl);
318 :
319 75098 : rtl_uString_release(workDir);
320 75098 : result = true;
321 : }
322 : else
323 : {
324 0 : result = false;
325 : }
326 75098 : rtl_string_release(path);
327 : }
328 75098 : return result;
329 : }
330 :
331 : /*****************************************************************************/
332 : /* osl_getModuleURLFromFunctionAddress */
333 : /*****************************************************************************/
334 74814 : sal_Bool SAL_CALL osl_getModuleURLFromFunctionAddress(oslGenericFunction addr, rtl_uString ** ppLibraryUrl)
335 : {
336 74814 : return osl_getModuleURLFromAddress((void*)addr, ppLibraryUrl);
337 : }
338 :
339 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|