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 <rtl/string.hxx>
29 : #include <rtl/ustring.hxx>
30 : #include <assert.h>
31 : #include "system.hxx"
32 : #include "file_url.hxx"
33 :
34 : #ifdef AIX
35 : #include <sys/ldr.h>
36 : #endif
37 :
38 : #ifdef ANDROID
39 : #include <osl/detail/android-bootstrap.h>
40 : #endif
41 :
42 46563 : static bool getModulePathFromAddress(void * address, rtl_String ** path) {
43 46563 : 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;
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) != 0;
94 : #else
95 46563 : result = dladdr(address, &dl_info) != 0;
96 : #endif
97 :
98 46563 : if (result)
99 : {
100 46563 : 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 : }
105 : #endif
106 46563 : return result;
107 : }
108 :
109 : #ifndef DISABLE_DYNLOADING
110 :
111 : /*****************************************************************************/
112 : /* osl_loadModule */
113 : /*****************************************************************************/
114 :
115 62634 : oslModule SAL_CALL osl_loadModule(rtl_uString *ustrModuleName, sal_Int32 nRtldMode)
116 : {
117 62634 : oslModule pModule=0;
118 62634 : rtl_uString* ustrTmp = NULL;
119 :
120 : SAL_WARN_IF(ustrModuleName == 0, "sal.osl", "string is not valid");
121 :
122 : /* ensure ustrTmp hold valid string */
123 62634 : if (osl_File_E_None != osl_getSystemPathFromFileURL(ustrModuleName, &ustrTmp))
124 388 : rtl_uString_assign(&ustrTmp, ustrModuleName);
125 :
126 62634 : if (ustrTmp)
127 : {
128 : char buffer[PATH_MAX];
129 :
130 62634 : if (UnicodeToText(buffer, PATH_MAX, ustrTmp->buffer, ustrTmp->length))
131 62634 : pModule = osl_loadModuleAscii(buffer, nRtldMode);
132 62634 : rtl_uString_release(ustrTmp);
133 : }
134 :
135 62634 : return pModule;
136 : }
137 :
138 : /*****************************************************************************/
139 : /* osl_loadModuleAscii */
140 : /*****************************************************************************/
141 :
142 62765 : oslModule SAL_CALL osl_loadModuleAscii(const sal_Char *pModuleName, sal_Int32 nRtldMode)
143 : {
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 62765 : if (pModuleName)
149 : {
150 : #ifdef ANDROID
151 : (void) nRtldMode;
152 : void *pLib = lo_dlopen(pModuleName);
153 : #else
154 : int rtld_mode =
155 62765 : ((nRtldMode & SAL_LOADMODULE_NOW) ? RTLD_NOW : RTLD_LAZY) |
156 62765 : ((nRtldMode & SAL_LOADMODULE_GLOBAL) ? RTLD_GLOBAL : RTLD_LOCAL);
157 62765 : void* pLib = dlopen(pModuleName, rtld_mode);
158 :
159 : SAL_INFO_IF(
160 : pLib == 0, "sal.osl",
161 : "dlopen(" << pModuleName << ", " << rtld_mode << "): "
162 : << dlerror());
163 : #endif
164 62765 : return pLib;
165 : }
166 0 : return NULL;
167 : }
168 :
169 131 : oslModule osl_loadModuleRelativeAscii(
170 : oslGenericFunction baseModule, char const * relativePath, sal_Int32 mode)
171 : {
172 : assert(relativePath && "illegal argument");
173 131 : if (relativePath[0] == '/') {
174 0 : return osl_loadModuleAscii(relativePath, mode);
175 : } else {
176 131 : rtl_String * path = NULL;
177 131 : rtl_String * suffix = NULL;
178 : oslModule module;
179 131 : if (!getModulePathFromAddress(
180 131 : reinterpret_cast< void * >(baseModule), &path))
181 : {
182 0 : return NULL;
183 : }
184 : rtl_string_newFromStr_WithLength(
185 : &path, path->buffer,
186 131 : (rtl_str_lastIndexOfChar_WithLength(path->buffer, path->length, '/')
187 131 : + 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 131 : rtl_string_newFromStr(&suffix, relativePath);
191 131 : rtl_string_newConcat(&path, path, suffix);
192 131 : rtl_string_release(suffix);
193 131 : module = osl_loadModuleAscii(path->buffer, mode);
194 131 : rtl_string_release(path);
195 131 : return module;
196 : }
197 : }
198 :
199 : #endif // !DISABLE_DYNLOADING
200 :
201 : /*****************************************************************************/
202 : /* osl_getModuleHandle */
203 : /*****************************************************************************/
204 :
205 : sal_Bool SAL_CALL
206 0 : osl_getModuleHandle(rtl_uString *, oslModule *pResult)
207 : {
208 : #if !defined(DISABLE_DYNLOADING) || defined(IOS)
209 0 : *pResult = static_cast<oslModule>(RTLD_DEFAULT);
210 : #else
211 : *pResult = NULL;
212 : #endif
213 0 : return sal_True;
214 : }
215 :
216 : #ifndef DISABLE_DYNLOADING
217 :
218 : /*****************************************************************************/
219 : /* osl_unloadModule */
220 : /*****************************************************************************/
221 61313 : void SAL_CALL osl_unloadModule(oslModule hModule)
222 : {
223 61313 : if (hModule)
224 : {
225 : #ifdef ANDROID
226 : int nRet = lo_dlclose(hModule);
227 : #else
228 30186 : int nRet = dlclose(hModule);
229 : #endif
230 : SAL_INFO_IF(
231 : nRet != 0, "sal.osl", "dlclose(" << hModule << "): " << dlerror());
232 : }
233 61313 : }
234 :
235 : #endif // !DISABLE_DYNLOADING
236 :
237 : namespace {
238 :
239 85639689 : void * getSymbol(oslModule module, char const * symbol) {
240 : assert(symbol != nullptr);
241 : // We do want to use dlsym() also in the DISABLE_DYNLOADING case
242 : // just to look up symbols in the static executable, I think:
243 85639689 : void * p = dlsym(module, symbol);
244 : SAL_INFO_IF(
245 : p == nullptr, "sal.osl",
246 : "dlsym(" << module << ", " << symbol << "): " << dlerror());
247 85639689 : return p;
248 : }
249 :
250 : }
251 :
252 : /*****************************************************************************/
253 : /* osl_getSymbol */
254 : /*****************************************************************************/
255 : void* SAL_CALL
256 85639356 : osl_getSymbol(oslModule Module, rtl_uString* pSymbolName)
257 : {
258 : // Arbitrarily using UTF-8:
259 85639356 : OString s;
260 171278712 : if (!OUString::unacquired(&pSymbolName).convertToString(
261 : &s, RTL_TEXTENCODING_UTF8,
262 : (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
263 85639356 : RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
264 : {
265 : SAL_INFO(
266 : "sal.osl", "cannot convert \"" << OUString::unacquired(&pSymbolName)
267 : << "\" to UTF-8");
268 0 : return nullptr;
269 : }
270 85639356 : if (s.indexOf('\0') != -1) {
271 : SAL_INFO("sal.osl", "\"" << s << "\" contains embedded NUL");
272 0 : return nullptr;
273 : }
274 85639356 : return getSymbol(Module, s.getStr());
275 : }
276 :
277 : /*****************************************************************************/
278 : /* osl_getAsciiFunctionSymbol */
279 : /*****************************************************************************/
280 : oslGenericFunction SAL_CALL
281 333 : osl_getAsciiFunctionSymbol(oslModule Module, const sal_Char *pSymbol)
282 : {
283 333 : return reinterpret_cast<oslGenericFunction>(getSymbol(Module, pSymbol));
284 : // requires conditionally-supported conversion from void * to function
285 : // pointer
286 : }
287 :
288 : /*****************************************************************************/
289 : /* osl_getFunctionSymbol */
290 : /*****************************************************************************/
291 : oslGenericFunction SAL_CALL
292 85625352 : osl_getFunctionSymbol(oslModule module, rtl_uString *puFunctionSymbolName)
293 : {
294 : return reinterpret_cast<oslGenericFunction>(
295 85625352 : osl_getSymbol(module, puFunctionSymbolName));
296 : // requires conditionally-supported conversion from void * to function
297 : // pointer
298 : }
299 :
300 : /*****************************************************************************/
301 : /* osl_getModuleURLFromAddress */
302 : /*****************************************************************************/
303 46432 : sal_Bool SAL_CALL osl_getModuleURLFromAddress(void * addr, rtl_uString ** ppLibraryUrl)
304 : {
305 46432 : bool result = false;
306 46432 : rtl_String * path = NULL;
307 46432 : if (getModulePathFromAddress(addr, &path))
308 : {
309 46432 : rtl_uString * workDir = NULL;
310 46432 : osl_getProcessWorkingDir(&workDir);
311 46432 : if (workDir)
312 : {
313 : SAL_INFO(
314 : "sal.osl", "osl_getModuleURLFromAddress: " << path->buffer);
315 : rtl_string2UString(ppLibraryUrl,
316 : path->buffer,
317 : path->length,
318 46432 : osl_getThreadTextEncoding(),
319 46432 : OSTRING_TO_OUSTRING_CVTFLAGS);
320 :
321 : SAL_WARN_IF(
322 : *ppLibraryUrl == 0, "sal.osl", "rtl_string2UString failed");
323 46432 : osl_getFileURLFromSystemPath(*ppLibraryUrl, ppLibraryUrl);
324 46432 : osl_getAbsoluteFileURL(workDir, *ppLibraryUrl, ppLibraryUrl);
325 :
326 46432 : rtl_uString_release(workDir);
327 46432 : result = true;
328 : }
329 : else
330 : {
331 0 : result = false;
332 : }
333 46432 : rtl_string_release(path);
334 : }
335 46432 : return result;
336 : }
337 :
338 : /*****************************************************************************/
339 : /* osl_getModuleURLFromFunctionAddress */
340 : /*****************************************************************************/
341 46268 : sal_Bool SAL_CALL osl_getModuleURLFromFunctionAddress(oslGenericFunction addr, rtl_uString ** ppLibraryUrl)
342 : {
343 : return osl_getModuleURLFromAddress(
344 46268 : reinterpret_cast<void*>(addr), ppLibraryUrl);
345 : // requires conditionally-supported conversion from function pointer to
346 : // void *
347 : }
348 :
349 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|