office-gobmx/sal/osl/unx/module.cxx
Jan-Marek Glogowski b5b1eae538 Add HAVE_(UNIX_)DLAPI config header define
..., add the configure test flags and rename DLOPEN_LIBS to
UNIX_DLAPI_LIBS.

Initinally convert two dlsym callers to use HAVE_DLAPI and
osl_getAsciiFunctionSymbol.

There are a lot of places, which still use -ldl and even more
direct dlsym calls; good opportunity for many simple EasyHacks.

Change-Id: I4f2d2f7cb079a075af8f9d01eb5ee45de40c7f03
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128523
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2022-01-18 13:44:53 +01:00

344 lines
10 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <sal/config.h>
#include <sal/log.hxx>
#include <sal/types.h>
#include <osl/module.h>
#include <osl/thread.h>
#include <osl/process.h>
#include <osl/file.h>
#include <rtl/string.hxx>
#include <rtl/ustring.hxx>
#include <assert.h>
#include "system.hxx"
#include "file_url.hxx"
#ifdef AIX
#include <sys/ldr.h>
#endif
static bool getModulePathFromAddress(void * address, rtl_String ** path)
{
bool result = false;
#if defined(AIX)
int size = 4 * 1024;
char *buf, *filename=NULL;
struct ld_info *lp;
if ((buf = (char*)malloc(size)) == NULL)
return false;
//figure out how big a buffer we need
while (loadquery(L_GETINFO, buf, size) == -1 && errno == ENOMEM)
{
size += 4 * 1024;
free(buf);
if ((buf = (char*)malloc(size)) == NULL)
return false;
}
lp = (struct ld_info*) buf;
while (lp)
{
unsigned long start = (unsigned long)lp->ldinfo_dataorg;
unsigned long end = start + lp->ldinfo_datasize;
if (start <= (unsigned long)address && end > (unsigned long)address)
{
filename = lp->ldinfo_filename;
break;
}
if (!lp->ldinfo_next)
break;
lp = (struct ld_info*) ((char *) lp + lp->ldinfo_next);
}
if (filename)
{
rtl_string_newFromStr(path, filename);
result = sal_True;
}
else
{
result = sal_False;
}
free(buf);
#else
#if HAVE_UNIX_DLAPI
Dl_info dl_info;
result = dladdr(address, &dl_info) != 0;
if (result)
{
rtl_string_newFromStr(path, dl_info.dli_fname);
}
#else
(void) address;
(void) path;
#endif
#endif
return result;
}
#ifndef DISABLE_DYNLOADING
/*****************************************************************************/
/* osl_loadModule */
/*****************************************************************************/
oslModule SAL_CALL osl_loadModule(rtl_uString *ustrModuleName, sal_Int32 nRtldMode)
{
oslModule pModule=nullptr;
rtl_uString* ustrTmp = nullptr;
SAL_WARN_IF(ustrModuleName == nullptr, "sal.osl", "string is not valid");
/* ensure ustrTmp hold valid string */
if (osl_getSystemPathFromFileURL(ustrModuleName, &ustrTmp) != osl_File_E_None)
rtl_uString_assign(&ustrTmp, ustrModuleName);
if (ustrTmp)
{
char buffer[PATH_MAX];
if (UnicodeToText(buffer, PATH_MAX, ustrTmp->buffer, ustrTmp->length))
pModule = osl_loadModuleAscii(buffer, nRtldMode);
rtl_uString_release(ustrTmp);
}
return pModule;
}
/*****************************************************************************/
/* osl_loadModuleAscii */
/*****************************************************************************/
oslModule SAL_CALL osl_loadModuleAscii(const char *pModuleName, sal_Int32 nRtldMode)
{
#if HAVE_UNIX_DLAPI
SAL_WARN_IF(
((nRtldMode & SAL_LOADMODULE_LAZY) != 0
&& (nRtldMode & SAL_LOADMODULE_NOW) != 0),
"sal.osl", "only either LAZY or NOW");
if (pModuleName)
{
int rtld_mode =
((nRtldMode & SAL_LOADMODULE_NOW) ? RTLD_NOW : RTLD_LAZY) |
((nRtldMode & SAL_LOADMODULE_GLOBAL) ? RTLD_GLOBAL : RTLD_LOCAL);
void* pLib = dlopen(pModuleName, rtld_mode);
SAL_WARN_IF(
pLib == nullptr, "sal.osl",
"dlopen(" << pModuleName << ", " << rtld_mode << "): "
<< dlerror());
return pLib;
}
#else
(void) pModuleName;
(void) nRtldMode;
#endif
return nullptr;
}
oslModule osl_loadModuleRelativeAscii(
oslGenericFunction baseModule, char const * relativePath, sal_Int32 mode)
{
assert(relativePath && "illegal argument");
if (relativePath[0] == '/') {
return osl_loadModuleAscii(relativePath, mode);
}
rtl_String * path = nullptr;
rtl_String * suffix = nullptr;
oslModule module;
if (!getModulePathFromAddress(
reinterpret_cast< void * >(baseModule), &path))
{
return nullptr;
}
rtl_string_newFromStr_WithLength(
&path, path->buffer,
(rtl_str_lastIndexOfChar_WithLength(path->buffer, path->length, '/')
+ 1));
/* cut off everything after the last slash; should the original path
contain no slash, the resulting path is the empty string */
rtl_string_newFromStr(&suffix, relativePath);
rtl_string_newConcat(&path, path, suffix);
rtl_string_release(suffix);
module = osl_loadModuleAscii(path->buffer, mode);
rtl_string_release(path);
return module;
}
#endif // !DISABLE_DYNLOADING
/*****************************************************************************/
/* osl_getModuleHandle */
/*****************************************************************************/
sal_Bool SAL_CALL
osl_getModuleHandle(rtl_uString *, oslModule *pResult)
{
#if HAVE_UNIX_DLAPI
*pResult = static_cast<oslModule>(RTLD_DEFAULT);
return true;
#else
*pResult = nullptr;
return false;
#endif
}
/*****************************************************************************/
/* osl_unloadModule */
/*****************************************************************************/
void SAL_CALL osl_unloadModule(oslModule hModule)
{
#if !defined(DISABLE_DYNLOADING) && HAVE_UNIX_DLAPI
if (hModule)
{
int nRet = dlclose(hModule);
SAL_INFO_IF(
nRet != 0, "sal.osl", "dlclose(" << hModule << "): " << dlerror());
}
#else
(void) hModule;
#endif
}
namespace {
void * getSymbol(oslModule module, char const * symbol)
{
assert(symbol != nullptr);
#if HAVE_UNIX_DLAPI
// We do want to use dlsym() also in the DISABLE_DYNLOADING case
// just to look up symbols in the static executable, I think:
void * p = dlsym(module, symbol);
SAL_INFO_IF(
p == nullptr, "sal.osl",
"dlsym(" << module << ", " << symbol << "): " << dlerror());
#else
(void) module;
(void) symbol;
void *p = nullptr;
#endif
return p;
}
}
/*****************************************************************************/
/* osl_getSymbol */
/*****************************************************************************/
void* SAL_CALL
osl_getSymbol(oslModule Module, rtl_uString* pSymbolName)
{
// Arbitrarily using UTF-8:
OString s;
if (!OUString::unacquired(&pSymbolName).convertToString(
&s, RTL_TEXTENCODING_UTF8,
(RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
{
SAL_INFO(
"sal.osl", "cannot convert \"" << OUString::unacquired(&pSymbolName)
<< "\" to UTF-8");
return nullptr;
}
if (s.indexOf('\0') != -1) {
SAL_INFO("sal.osl", "\"" << s << "\" contains embedded NUL");
return nullptr;
}
return getSymbol(Module, s.getStr());
}
/*****************************************************************************/
/* osl_getAsciiFunctionSymbol */
/*****************************************************************************/
oslGenericFunction SAL_CALL
osl_getAsciiFunctionSymbol(oslModule Module, const char *pSymbol)
{
return reinterpret_cast<oslGenericFunction>(getSymbol(Module, pSymbol));
// requires conditionally-supported conversion from void * to function
// pointer
}
/*****************************************************************************/
/* osl_getFunctionSymbol */
/*****************************************************************************/
oslGenericFunction SAL_CALL
osl_getFunctionSymbol(oslModule module, rtl_uString *puFunctionSymbolName)
{
return reinterpret_cast<oslGenericFunction>(
osl_getSymbol(module, puFunctionSymbolName));
// requires conditionally-supported conversion from void * to function
// pointer
}
/*****************************************************************************/
/* osl_getModuleURLFromAddress */
/*****************************************************************************/
sal_Bool SAL_CALL osl_getModuleURLFromAddress(void * addr, rtl_uString ** ppLibraryUrl)
{
bool result = false;
rtl_String * path = nullptr;
if (getModulePathFromAddress(addr, &path))
{
rtl_string2UString(ppLibraryUrl,
path->buffer,
path->length,
osl_getThreadTextEncoding(),
OSTRING_TO_OUSTRING_CVTFLAGS);
SAL_WARN_IF(
*ppLibraryUrl == nullptr, "sal.osl", "rtl_string2UString failed");
auto const e = osl_getFileURLFromSystemPath(*ppLibraryUrl, ppLibraryUrl);
if (e == osl_File_E_None)
{
SAL_INFO("sal.osl", "osl_getModuleURLFromAddress(" << addr << ") => " << OUString(*ppLibraryUrl));
result = true;
}
else
{
SAL_WARN(
"sal.osl",
"osl_getModuleURLFromAddress(" << addr << "), osl_getFileURLFromSystemPath("
<< OUString::unacquired(ppLibraryUrl) << ") failed with " << e);
result = false;
}
rtl_string_release(path);
}
return result;
}
/*****************************************************************************/
/* osl_getModuleURLFromFunctionAddress */
/*****************************************************************************/
sal_Bool SAL_CALL osl_getModuleURLFromFunctionAddress(oslGenericFunction addr, rtl_uString ** ppLibraryUrl)
{
return osl_getModuleURLFromAddress(
reinterpret_cast<void*>(addr), ppLibraryUrl);
// requires conditionally-supported conversion from function pointer to
// void *
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */