LibELF: Treat STB_WEAK like STB_GLOBAL during global symbol lookup

This is what POSIX mandates and this also matches the behavior of modern
Linux.
This commit is contained in:
Dan Klishch 2024-04-20 15:10:31 -04:00 committed by Andrew Kaster
parent d8119c4b4a
commit bdfc77b725
Notes: sideshowbarker 2024-07-17 20:19:08 +09:00
5 changed files with 44 additions and 11 deletions

View file

@ -29,6 +29,7 @@ set(TEST_SOURCES
test-elf.cpp
TestDlOpen.cpp
TestTLS.cpp
TestWeakSymbolResolution.cpp
)
foreach(source IN LISTS TEST_SOURCES)
@ -42,3 +43,8 @@ target_link_libraries(TLSUse PRIVATE LibCore LibTest LibThreading TLSDef)
set_target_properties(TLSUse PROPERTIES INSTALL_RPATH "$ORIGIN")
target_link_libraries(TestTLS PRIVATE TLSUse)
set_target_properties(TestTLS PROPERTIES INSTALL_RPATH "$ORIGIN")
add_test_lib(TestWeakSymbolResolution1 TestWeakSymbolResolution1.cpp)
add_test_lib(TestWeakSymbolResolution2 TestWeakSymbolResolution2.cpp)
target_link_libraries(TestWeakSymbolResolution PRIVATE TestWeakSymbolResolution1 TestWeakSymbolResolution2)
set_target_properties(TestWeakSymbolResolution PROPERTIES INSTALL_RPATH "$ORIGIN")

View file

@ -0,0 +1,16 @@
/*
* Copyright (c) 2024, Dan Klishch <danilklishch@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibTest/TestCase.h>
int f();
[[gnu::weak]] int f() { return 1; }
int g();
TEST_CASE(weak_symbol_resolution)
{
EXPECT_EQ(g(), 1);
}

View file

@ -0,0 +1,10 @@
/*
* Copyright (c) 2024, Dan Klishch <danilklishch@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
[[gnu::weak]] int f();
int g();
int g() { return f(); }

View file

@ -0,0 +1,8 @@
/*
* Copyright (c) 2024, Dan Klishch <danilklishch@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
int f();
int f() { return 2; }

View file

@ -78,27 +78,20 @@ static HashMap<StringView, DynamicObject::SymbolLookupResult> s_magic_functions;
Optional<DynamicObject::SymbolLookupResult> DynamicLinker::lookup_global_symbol(StringView name)
{
Optional<DynamicObject::SymbolLookupResult> weak_result;
auto symbol = DynamicObject::HashSymbol { name };
for (auto& lib : s_global_objects) {
auto res = lib.value->lookup_symbol(symbol);
if (!res.has_value())
continue;
if (res.value().bind == STB_GLOBAL)
if (res.value().bind == STB_GLOBAL || res.value().bind == STB_WEAK)
return res;
if (res.value().bind == STB_WEAK && !weak_result.has_value())
weak_result = res;
// We don't want to allow local symbols to be pulled in to other modules
}
if (!weak_result.has_value()) {
if (auto magic_lookup = s_magic_functions.get(name); magic_lookup.has_value())
weak_result = *magic_lookup;
}
return weak_result;
if (auto magic_lookup = s_magic_functions.get(name); magic_lookup.has_value())
return *magic_lookup;
return {};
}
static Result<NonnullRefPtr<DynamicLoader>, DlErrorMessage> map_library(ByteString const& filepath, int fd)