mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-10-04 15:19:16 +00:00
Previously, the actual behavior of magic lookup and one described in its commit description have not matched. Instead of being weak definitions in a library that is always in the end of load order, the definitions were normal ones and thus were able to override other weak definitions in LibC. While this was consistent with how DynamicLoader resolves ambiguity between normal and weak relocations, this is not the behavior POSIX mandates -- we should always choose first available definition wrt load order. To fix this problem, the patch makes sure we don't define any of magic symbols in LibC. In addition to this, it makes all provided magic symbols functions (instead of objects), what renders MagicWeakSymbol class unnecessary.
85 lines
2.1 KiB
C++
85 lines
2.1 KiB
C++
/*
|
|
* Copyright (c) 2021, Gunnar Beutner <gunnar@beutner.name>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <AK/ByteString.h>
|
|
#include <AK/Result.h>
|
|
#include <AK/Types.h>
|
|
#include <bits/dlfcn_integration.h>
|
|
#include <dlfcn.h>
|
|
#include <string.h>
|
|
|
|
[[gnu::weak]] Result<void, DlErrorMessage> __dlclose(void*) asm("__dlclose");
|
|
[[gnu::weak]] Result<void*, DlErrorMessage> __dlopen(char const*, int) asm("__dlopen");
|
|
[[gnu::weak]] Result<void*, DlErrorMessage> __dlsym(void*, char const*) asm("__dlsym");
|
|
[[gnu::weak]] Result<void, DlErrorMessage> __dladdr(void const*, Dl_info*) asm("__dladdr");
|
|
|
|
// FIXME: use thread_local and a String once TLS works
|
|
#ifdef NO_TLS
|
|
char* s_dlerror_text = NULL;
|
|
bool s_dlerror_retrieved = false;
|
|
#else
|
|
__thread char* s_dlerror_text = NULL;
|
|
__thread bool s_dlerror_retrieved = false;
|
|
#endif
|
|
|
|
static void store_error(ByteString const& error)
|
|
{
|
|
free(s_dlerror_text);
|
|
s_dlerror_text = strdup(error.characters());
|
|
s_dlerror_retrieved = false;
|
|
}
|
|
|
|
int dlclose(void* handle)
|
|
{
|
|
auto result = __dlclose(handle);
|
|
if (result.is_error()) {
|
|
store_error(result.error().text);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
char* dlerror()
|
|
{
|
|
if (s_dlerror_retrieved) {
|
|
free(s_dlerror_text);
|
|
s_dlerror_text = nullptr;
|
|
}
|
|
s_dlerror_retrieved = true;
|
|
return const_cast<char*>(s_dlerror_text);
|
|
}
|
|
|
|
void* dlopen(char const* filename, int flags)
|
|
{
|
|
auto result = __dlopen(filename, flags);
|
|
if (result.is_error()) {
|
|
store_error(result.error().text);
|
|
return nullptr;
|
|
}
|
|
return result.value();
|
|
}
|
|
|
|
void* dlsym(void* handle, char const* symbol_name)
|
|
{
|
|
auto result = __dlsym(handle, symbol_name);
|
|
if (result.is_error()) {
|
|
store_error(result.error().text);
|
|
return nullptr;
|
|
}
|
|
return result.value();
|
|
}
|
|
|
|
int dladdr(void const* addr, Dl_info* info)
|
|
{
|
|
auto result = __dladdr(addr, info);
|
|
if (result.is_error()) {
|
|
// FIXME: According to the man page glibc does _not_ make the error
|
|
// available via dlerror(), however we do. Does this break anything?
|
|
store_error(result.error().text);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|