From 6b14c31437d57b7267512d1f39b5de74a6ad4033 Mon Sep 17 00:00:00 2001 From: Zinebyte <197974009+Zinebyte@users.noreply.github.com> Date: Fri, 16 Oct 2026 13:30:33 -0400 Subject: [PATCH 1/2] fix(relinker): infer guest dependencies from referenced imports --- core/relinker/CMakeLists.txt | 4 + .../relinker/src/guest/GuestModuleBuilder.cpp | 9 +- .../test_guest_unused_import_dependencies.py | 119 ++++++++++++++++++ 3 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 core/relinker/relinker/tests/test_guest_unused_import_dependencies.py diff --git a/core/relinker/CMakeLists.txt b/core/relinker/CMakeLists.txt index d227fc017d2c..75484ae9622c 100644 --- a/core/relinker/CMakeLists.txt +++ b/core/relinker/CMakeLists.txt @@ -517,6 +517,10 @@ if(BUILD_TESTING) add_test(NAME guest_deferred_dependencies COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_guest_deferred_dependencies.py $ $) + add_test(NAME guest_unused_import_dependencies COMMAND ${Python3_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_guest_unused_import_dependencies.py + $ $) + set_property(TEST guest_unused_import_dependencies APPEND PROPERTY LABELS relinker) add_test(NAME guest_absolute_symbols COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_guest_absolute_symbols.py $) add_test(NAME guest_module_identity COMMAND ${Python3_EXECUTABLE} diff --git a/core/relinker/relinker/src/guest/GuestModuleBuilder.cpp b/core/relinker/relinker/src/guest/GuestModuleBuilder.cpp index 33cc5bdfc220..ab8ff81d0fc6 100644 --- a/core/relinker/relinker/src/guest/GuestModuleBuilder.cpp +++ b/core/relinker/relinker/src/guest/GuestModuleBuilder.cpp @@ -219,6 +219,13 @@ std::vector GuestModuleBuilder::Build(const std::filesystem::path const auto found = findGuest(name); if (found != guestNames.end() && found->second != index) dependencies[index].insert(found->second); } + std::set referencedSymbols; + for (const auto* table : {&images[index].Dynamic.RelaData, &images[index].Dynamic.RelaPltData}) { + for (std::size_t offset = 0; offset < table->size(); offset += 24) { + const auto info = Io::ReadU64(*table, offset + 8); + if ((info & 0xffffffffu) != 0) referencedSymbols.insert(info >> 32); + } + } for (std::size_t symbolIndex = 0; symbolIndex < images[index].Symbols.size(); ++symbolIndex) { const auto& symbol = images[index].Symbols[symbolIndex]; if (symbol.Section != 0 || symbol.Name.empty()) continue; @@ -241,7 +248,7 @@ std::vector GuestModuleBuilder::Build(const std::filesystem::path } if (provider != nullptr) { if ((symbol.Info & 15) != 0 && (symbol.Info & 15) != provider->Type) throw Domain::RelinkerException("Guest import/export type mismatch: " + symbol.Name); - if (provider->Provider != index) dependencies[index].insert(provider->Provider); + if (provider->Provider != index && referencedSymbols.contains(symbolIndex)) dependencies[index].insert(provider->Provider); } else if (windows && (symbol.Info & 15) == 6) throw Domain::RelinkerException("Windows guest TLS import requires a guest TLS export: " + symbol.Name); if (provider == nullptr) systemImports[index].insert(symbolIndex); } diff --git a/core/relinker/relinker/tests/test_guest_unused_import_dependencies.py b/core/relinker/relinker/tests/test_guest_unused_import_dependencies.py new file mode 100644 index 000000000000..f3054ee7bdf4 --- /dev/null +++ b/core/relinker/relinker/tests/test_guest_unused_import_dependencies.py @@ -0,0 +1,119 @@ +from pathlib import Path +import os +import shutil +import struct +import subprocess +import sys +import tempfile + +from guest_import_fixtures import dynamic +from test_guest_deferred_dependencies import page_aligned +from test_guest_intel_trampolines import main_fixture +from test_guest_module_args import args_module +from test_guest_module_directories import module_with_symbol, needed_libraries +from test_guest_module_dir import pe_export_names +from test_guest_needed_modules import module_with_needed +from test_guest_symbol_names import dynamic_tags +from test_macos_output import MachO + + +def consumer(kind): + image = module_with_symbol(False) + tags = dynamic_tags(image) + if kind in ('unreferenced', 'weak-unreferenced', 'needed'): + tags[8] = 0 + elif kind == 'noop': + struct.pack_into(' Date: Fri, 16 Oct 2026 14:53:45 -0400 Subject: [PATCH 2/2] test(relinker): avoid preinit registration overlap --- core/relinker/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/relinker/CMakeLists.txt b/core/relinker/CMakeLists.txt index 75484ae9622c..a941d625a9a2 100644 --- a/core/relinker/CMakeLists.txt +++ b/core/relinker/CMakeLists.txt @@ -517,14 +517,14 @@ if(BUILD_TESTING) add_test(NAME guest_deferred_dependencies COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_guest_deferred_dependencies.py $ $) - add_test(NAME guest_unused_import_dependencies COMMAND ${Python3_EXECUTABLE} - ${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_guest_unused_import_dependencies.py - $ $) - set_property(TEST guest_unused_import_dependencies APPEND PROPERTY LABELS relinker) add_test(NAME guest_absolute_symbols COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_guest_absolute_symbols.py $) add_test(NAME guest_module_identity COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_guest_module_identity.py $) + add_test(NAME guest_unused_import_dependencies COMMAND ${Python3_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_guest_unused_import_dependencies.py + $ $) + set_property(TEST guest_unused_import_dependencies APPEND PROPERTY LABELS relinker) add_test(NAME guest_export_lookup COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_guest_export_lookup.py $) set_tests_properties(guest_export_lookup PROPERTIES TIMEOUT 30)