1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
27 #include <rtl/string.hxx>
28 #include <rtl/ustring.hxx>
32 #include "file_url.hxx"
34 static bool getModulePathFromAddress(void * address
, rtl_String
** path
)
40 result
= dladdr(address
, &dl_info
) != 0;
44 rtl_string_newFromStr(path
, dl_info
.dli_fname
);
53 #ifndef DISABLE_DYNLOADING
55 /*****************************************************************************/
57 /*****************************************************************************/
59 oslModule SAL_CALL
osl_loadModule(rtl_uString
*ustrModuleName
, sal_Int32 nRtldMode
)
61 oslModule pModule
=nullptr;
62 rtl_uString
* ustrTmp
= nullptr;
64 SAL_WARN_IF(ustrModuleName
== nullptr, "sal.osl", "string is not valid");
66 /* ensure ustrTmp hold valid string */
67 if (osl_getSystemPathFromFileURL(ustrModuleName
, &ustrTmp
) != osl_File_E_None
)
68 rtl_uString_assign(&ustrTmp
, ustrModuleName
);
72 char buffer
[PATH_MAX
];
74 if (UnicodeToText(buffer
, PATH_MAX
, ustrTmp
->buffer
, ustrTmp
->length
))
75 pModule
= osl_loadModuleAscii(buffer
, nRtldMode
);
76 rtl_uString_release(ustrTmp
);
82 /*****************************************************************************/
83 /* osl_loadModuleAscii */
84 /*****************************************************************************/
86 oslModule SAL_CALL
osl_loadModuleAscii(const char *pModuleName
, sal_Int32 nRtldMode
)
90 ((nRtldMode
& SAL_LOADMODULE_LAZY
) != 0
91 && (nRtldMode
& SAL_LOADMODULE_NOW
) != 0),
92 "sal.osl", "only either LAZY or NOW");
96 ((nRtldMode
& SAL_LOADMODULE_NOW
) ? RTLD_NOW
: RTLD_LAZY
) |
97 ((nRtldMode
& SAL_LOADMODULE_GLOBAL
) ? RTLD_GLOBAL
: RTLD_LOCAL
);
98 void* pLib
= dlopen(pModuleName
, rtld_mode
);
101 pLib
== nullptr, "sal.osl",
102 "dlopen(" << pModuleName
<< ", " << rtld_mode
<< "): "
113 oslModule
osl_loadModuleRelativeAscii(
114 oslGenericFunction baseModule
, char const * relativePath
, sal_Int32 mode
)
116 assert(relativePath
&& "illegal argument");
117 if (relativePath
[0] == '/') {
118 return osl_loadModuleAscii(relativePath
, mode
);
120 rtl_String
* path
= nullptr;
121 rtl_String
* suffix
= nullptr;
123 if (!getModulePathFromAddress(
124 reinterpret_cast< void * >(baseModule
), &path
))
128 rtl_string_newFromStr_WithLength(
130 (rtl_str_lastIndexOfChar_WithLength(path
->buffer
, path
->length
, '/')
132 /* cut off everything after the last slash; should the original path
133 contain no slash, the resulting path is the empty string */
134 rtl_string_newFromStr(&suffix
, relativePath
);
135 rtl_string_newConcat(&path
, path
, suffix
);
136 rtl_string_release(suffix
);
137 module
= osl_loadModuleAscii(path
->buffer
, mode
);
138 rtl_string_release(path
);
142 #endif // !DISABLE_DYNLOADING
144 /*****************************************************************************/
145 /* osl_getModuleHandle */
146 /*****************************************************************************/
149 osl_getModuleHandle(rtl_uString
*, oslModule
*pResult
)
152 *pResult
= static_cast<oslModule
>(RTLD_DEFAULT
);
160 /*****************************************************************************/
161 /* osl_unloadModule */
162 /*****************************************************************************/
163 void SAL_CALL
osl_unloadModule(oslModule hModule
)
165 #if !defined(DISABLE_DYNLOADING) && HAVE_UNIX_DLAPI
168 int nRet
= dlclose(hModule
);
170 nRet
!= 0, "sal.osl", "dlclose(" << hModule
<< "): " << dlerror());
179 void * getSymbol(oslModule module
, char const * symbol
)
181 assert(symbol
!= nullptr);
183 // We do want to use dlsym() also in the DISABLE_DYNLOADING case
184 // just to look up symbols in the static executable, I think:
185 void * p
= dlsym(module
, symbol
);
187 p
== nullptr, "sal.osl",
188 "dlsym(" << module
<< ", " << symbol
<< "): " << dlerror());
199 /*****************************************************************************/
201 /*****************************************************************************/
203 osl_getSymbol(oslModule Module
, rtl_uString
* pSymbolName
)
205 // Arbitrarily using UTF-8:
207 if (!OUString::unacquired(&pSymbolName
).convertToString(
208 &s
, RTL_TEXTENCODING_UTF8
,
209 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
|
210 RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
)))
213 "sal.osl", "cannot convert \"" << OUString::unacquired(&pSymbolName
)
217 if (s
.indexOf('\0') != -1) {
218 SAL_INFO("sal.osl", "\"" << s
<< "\" contains embedded NUL");
221 return getSymbol(Module
, s
.getStr());
224 /*****************************************************************************/
225 /* osl_getAsciiFunctionSymbol */
226 /*****************************************************************************/
227 oslGenericFunction SAL_CALL
228 osl_getAsciiFunctionSymbol(oslModule Module
, const char *pSymbol
)
230 return reinterpret_cast<oslGenericFunction
>(getSymbol(Module
, pSymbol
));
231 // requires conditionally-supported conversion from void * to function
235 /*****************************************************************************/
236 /* osl_getFunctionSymbol */
237 /*****************************************************************************/
238 oslGenericFunction SAL_CALL
239 osl_getFunctionSymbol(oslModule module
, rtl_uString
*puFunctionSymbolName
)
241 return reinterpret_cast<oslGenericFunction
>(
242 osl_getSymbol(module
, puFunctionSymbolName
));
243 // requires conditionally-supported conversion from void * to function
247 /*****************************************************************************/
248 /* osl_getModuleURLFromAddress */
249 /*****************************************************************************/
250 sal_Bool SAL_CALL
osl_getModuleURLFromAddress(void * addr
, rtl_uString
** ppLibraryUrl
)
253 rtl_String
* path
= nullptr;
254 if (getModulePathFromAddress(addr
, &path
))
256 rtl_string2UString(ppLibraryUrl
,
259 osl_getThreadTextEncoding(),
260 OSTRING_TO_OUSTRING_CVTFLAGS
);
263 *ppLibraryUrl
== nullptr, "sal.osl", "rtl_string2UString failed");
264 auto const e
= osl_getFileURLFromSystemPath(*ppLibraryUrl
, ppLibraryUrl
);
265 if (e
== osl_File_E_None
)
267 SAL_INFO("sal.osl", "osl_getModuleURLFromAddress(" << addr
<< ") => " << OUString(*ppLibraryUrl
));
275 "osl_getModuleURLFromAddress(" << addr
<< "), osl_getFileURLFromSystemPath("
276 << OUString::unacquired(ppLibraryUrl
) << ") failed with " << e
);
279 rtl_string_release(path
);
284 /*****************************************************************************/
285 /* osl_getModuleURLFromFunctionAddress */
286 /*****************************************************************************/
287 sal_Bool SAL_CALL
osl_getModuleURLFromFunctionAddress(oslGenericFunction addr
, rtl_uString
** ppLibraryUrl
)
289 return osl_getModuleURLFromAddress(
290 reinterpret_cast<void*>(addr
), ppLibraryUrl
);
291 // requires conditionally-supported conversion from function pointer to
295 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */