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 22326 : static sal_Bool getModulePathFromAddress(void * address, rtl_String ** path) {
43 22326 : 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 = (char*)malloc(size)) == NULL)
52 : return false;
53 :
54 : //figure out how big a buffer we need
55 : while (loadquery(L_GETINFO, buf, size) == -1 && errno == ENOMEM)
56 : {
57 : size += 4 * 1024;
58 : free(buf);
59 : if ((buf = (char*)malloc(size)) == NULL)
60 : return false;
61 : }
62 :
63 : lp = (struct ld_info*) buf;
64 : while (lp)
65 : {
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)
69 : {
70 : filename = lp->ldinfo_filename;
71 : break;
72 : }
73 : if (!lp->ldinfo_next)
74 : break;
75 : lp = (struct ld_info*) ((char *) lp + lp->ldinfo_next);
76 : }
77 :
78 : if (filename)
79 : {
80 : rtl_string_newFromStr(path, filename);
81 : result = sal_True;
82 : }
83 : else
84 : {
85 : result = sal_False;
86 : }
87 :
88 : free(buf);
89 : #else
90 : Dl_info dl_info;
91 :
92 : #if defined(ANDROID) && !defined(DISABLE_DYNLOADING)
93 : result = lo_dladdr(address, &dl_info);
94 : #else
95 22326 : result = dladdr(address, &dl_info);
96 : #endif
97 :
98 22326 : if (result != 0)
99 : {
100 22326 : 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 22326 : result = sal_True;
105 : }
106 : else
107 : {
108 0 : result = sal_False;
109 : }
110 : #endif
111 22326 : return result;
112 : }
113 :
114 :
115 : #ifndef DISABLE_DYNLOADING
116 :
117 : /*****************************************************************************/
118 : /* osl_loadModule */
119 : /*****************************************************************************/
120 :
121 31219 : oslModule SAL_CALL osl_loadModule(rtl_uString *ustrModuleName, sal_Int32 nRtldMode)
122 : {
123 31219 : oslModule pModule=0;
124 31219 : rtl_uString* ustrTmp = NULL;
125 :
126 : SAL_WARN_IF(ustrModuleName == 0, "sal.osl", "string is not valid");
127 :
128 : /* ensure ustrTmp hold valid string */
129 31219 : if (osl_File_E_None != osl_getSystemPathFromFileURL(ustrModuleName, &ustrTmp))
130 0 : rtl_uString_assign(&ustrTmp, ustrModuleName);
131 :
132 31219 : if (ustrTmp)
133 : {
134 : char buffer[PATH_MAX];
135 :
136 31219 : if (UnicodeToText(buffer, PATH_MAX, ustrTmp->buffer, ustrTmp->length))
137 31219 : pModule = osl_loadModuleAscii(buffer, nRtldMode);
138 31219 : rtl_uString_release(ustrTmp);
139 : }
140 :
141 31219 : return pModule;
142 : }
143 :
144 : /*****************************************************************************/
145 : /* osl_loadModuleAscii */
146 : /*****************************************************************************/
147 :
148 31254 : oslModule SAL_CALL osl_loadModuleAscii(const sal_Char *pModuleName, sal_Int32 nRtldMode)
149 : {
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 31254 : if (pModuleName)
155 : {
156 : #ifdef ANDROID
157 : (void) nRtldMode;
158 : void *pLib = lo_dlopen(pModuleName);
159 : #else
160 : int rtld_mode =
161 31254 : ((nRtldMode & SAL_LOADMODULE_NOW) ? RTLD_NOW : RTLD_LAZY) |
162 31254 : ((nRtldMode & SAL_LOADMODULE_GLOBAL) ? RTLD_GLOBAL : RTLD_LOCAL);
163 31254 : void* pLib = dlopen(pModuleName, rtld_mode);
164 :
165 : SAL_INFO_IF(
166 : pLib == 0, "sal.osl",
167 : "dlopen(" << pModuleName << ", " << rtld_mode << "): "
168 : << dlerror());
169 : #endif
170 31254 : return ((oslModule)(pLib));
171 : }
172 0 : return NULL;
173 : }
174 :
175 30 : oslModule osl_loadModuleRelativeAscii(
176 : oslGenericFunction baseModule, char const * relativePath, sal_Int32 mode)
177 : {
178 : SAL_WARN_IF(relativePath == 0, "sal.osl", "illegal argument");
179 30 : if (relativePath[0] == '/') {
180 0 : return osl_loadModuleAscii(relativePath, mode);
181 : } else {
182 30 : rtl_String * path = NULL;
183 30 : rtl_String * suffix = NULL;
184 : oslModule module;
185 30 : if (!getModulePathFromAddress(
186 30 : reinterpret_cast< void * >(baseModule), &path))
187 : {
188 0 : return NULL;
189 : }
190 : rtl_string_newFromStr_WithLength(
191 : &path, path->buffer,
192 30 : (rtl_str_lastIndexOfChar_WithLength(path->buffer, path->length, '/')
193 30 : + 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 30 : rtl_string_newFromStr(&suffix, relativePath);
197 30 : rtl_string_newConcat(&path, path, suffix);
198 30 : rtl_string_release(suffix);
199 30 : module = osl_loadModuleAscii(path->buffer, mode);
200 30 : rtl_string_release(path);
201 30 : return module;
202 : }
203 : }
204 :
205 : #endif // !DISABLE_DYNLOADING
206 :
207 : /*****************************************************************************/
208 : /* osl_getModuleHandle */
209 : /*****************************************************************************/
210 :
211 : sal_Bool SAL_CALL
212 0 : osl_getModuleHandle(rtl_uString *, oslModule *pResult)
213 : {
214 : #if !defined(DISABLE_DYNLOADING) || defined(IOS)
215 0 : *pResult = (oslModule) RTLD_DEFAULT;
216 : #else
217 : *pResult = NULL;
218 : #endif
219 0 : return sal_True;
220 : }
221 :
222 : #ifndef DISABLE_DYNLOADING
223 :
224 : /*****************************************************************************/
225 : /* osl_unloadModule */
226 : /*****************************************************************************/
227 11616 : void SAL_CALL osl_unloadModule(oslModule hModule)
228 : {
229 11616 : if (hModule)
230 : {
231 : #ifdef ANDROID
232 : int nRet = lo_dlclose(hModule);
233 : #else
234 11156 : int nRet = dlclose(hModule);
235 : #endif
236 : SAL_INFO_IF(
237 : nRet != 0, "sal.osl", "dlclose(" << hModule << "): " << dlerror());
238 : }
239 11616 : }
240 :
241 : #endif // !DISABLE_DYNLOADING
242 :
243 : /*****************************************************************************/
244 : /* osl_getSymbol */
245 : /*****************************************************************************/
246 : void* SAL_CALL
247 3 : osl_getSymbol(oslModule Module, rtl_uString* pSymbolName)
248 : {
249 3 : return (void *) osl_getFunctionSymbol(Module, pSymbolName);
250 : }
251 :
252 :
253 : /*****************************************************************************/
254 : /* osl_getAsciiFunctionSymbol */
255 : /*****************************************************************************/
256 : oslGenericFunction SAL_CALL
257 196272 : osl_getAsciiFunctionSymbol(oslModule Module, const sal_Char *pSymbol)
258 : {
259 196272 : void *fcnAddr = NULL;
260 :
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 196272 : if (pSymbol)
264 : {
265 196272 : fcnAddr = dlsym(Module, pSymbol);
266 : SAL_INFO_IF(
267 : fcnAddr == 0, "sal.osl",
268 : "dlsym(" << Module << ", " << pSymbol << "): " << dlerror());
269 : }
270 :
271 196272 : return (oslGenericFunction) fcnAddr;
272 : }
273 :
274 : /*****************************************************************************/
275 : /* osl_getFunctionSymbol */
276 : /*****************************************************************************/
277 : oslGenericFunction SAL_CALL
278 195967 : osl_getFunctionSymbol(oslModule module, rtl_uString *puFunctionSymbolName)
279 : {
280 195967 : oslGenericFunction pSymbol = NULL;
281 :
282 195967 : if( puFunctionSymbolName )
283 : {
284 195967 : rtl_String* pSymbolName = NULL;
285 :
286 : rtl_uString2String( &pSymbolName,
287 195967 : rtl_uString_getStr(puFunctionSymbolName),
288 : rtl_uString_getLength(puFunctionSymbolName),
289 : RTL_TEXTENCODING_UTF8,
290 391934 : OUSTRING_TO_OSTRING_CVTFLAGS );
291 :
292 195967 : if( pSymbolName != NULL )
293 : {
294 195967 : pSymbol = osl_getAsciiFunctionSymbol(module, rtl_string_getStr(pSymbolName));
295 195967 : rtl_string_release(pSymbolName);
296 : }
297 : }
298 :
299 195967 : return pSymbol;
300 : }
301 :
302 : /*****************************************************************************/
303 : /* osl_getModuleURLFromAddress */
304 : /*****************************************************************************/
305 22296 : sal_Bool SAL_CALL osl_getModuleURLFromAddress(void * addr, rtl_uString ** ppLibraryUrl)
306 : {
307 22296 : sal_Bool result = sal_False;
308 22296 : rtl_String * path = NULL;
309 22296 : if (getModulePathFromAddress(addr, &path))
310 : {
311 22296 : rtl_uString * workDir = NULL;
312 22296 : osl_getProcessWorkingDir(&workDir);
313 22296 : if (workDir)
314 : {
315 : SAL_INFO(
316 : "sal.osl", "osl_getModuleURLFromAddress: " << path->buffer);
317 : rtl_string2UString(ppLibraryUrl,
318 : path->buffer,
319 : path->length,
320 22296 : osl_getThreadTextEncoding(),
321 22296 : OSTRING_TO_OUSTRING_CVTFLAGS);
322 :
323 : SAL_WARN_IF(
324 : *ppLibraryUrl == 0, "sal.osl", "rtl_string2UString failed");
325 22296 : osl_getFileURLFromSystemPath(*ppLibraryUrl, ppLibraryUrl);
326 22296 : osl_getAbsoluteFileURL(workDir, *ppLibraryUrl, ppLibraryUrl);
327 :
328 22296 : rtl_uString_release(workDir);
329 22296 : result = sal_True;
330 : }
331 : else
332 : {
333 0 : result = sal_False;
334 : }
335 22296 : rtl_string_release(path);
336 : }
337 22296 : return result;
338 : }
339 :
340 : /*****************************************************************************/
341 : /* osl_getModuleURLFromFunctionAddress */
342 : /*****************************************************************************/
343 21966 : sal_Bool SAL_CALL osl_getModuleURLFromFunctionAddress(oslGenericFunction addr, rtl_uString ** ppLibraryUrl)
344 : {
345 21966 : return osl_getModuleURLFromAddress((void*)addr, ppLibraryUrl);
346 : }
347 :
348 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|