diff --git a/core/libs/CMakeLists.txt b/core/libs/CMakeLists.txt index 510110335..0212df94a 100644 --- a/core/libs/CMakeLists.txt +++ b/core/libs/CMakeLists.txt @@ -51,6 +51,8 @@ set_target_properties(libc PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${UNPATCHED_DIR} LIBRARY_OUTPUT_DIRECTORY ${UNPATCHED_DIR} ARCHIVE_OUTPUT_DIRECTORY ${IMPLIB_DIR} + BUILD_WITH_INSTALL_RPATH ON + INSTALL_RPATH "$ORIGIN" ) set(LIBC_UNPATCHED ${UNPATCHED_DIR}/libc.prx) @@ -101,6 +103,8 @@ foreach(LIB_DIR ${LIBS_DIRS}) RUNTIME_OUTPUT_DIRECTORY ${UNPATCHED_DIR} LIBRARY_OUTPUT_DIRECTORY ${UNPATCHED_DIR} ARCHIVE_OUTPUT_DIRECTORY ${IMPLIB_DIR} + BUILD_WITH_INSTALL_RPATH ON + INSTALL_RPATH "$ORIGIN" ) set(UNPATCHED_FILE ${UNPATCHED_DIR}/${LIB_NAME}.prx) diff --git a/core/libs/nid/include/nid/ElfPatcher.hpp b/core/libs/nid/include/nid/ElfPatcher.hpp index dd70791c7..8dbc7d4bf 100644 --- a/core/libs/nid/include/nid/ElfPatcher.hpp +++ b/core/libs/nid/include/nid/ElfPatcher.hpp @@ -83,7 +83,13 @@ struct GnuHashLayout { constexpr std::int64_t kDtNeeded = 1; constexpr std::int64_t kDtSoname = 14; +constexpr std::int64_t kDtRpath = 15; +constexpr std::int64_t kDtRunpath = 29; constexpr std::int64_t kDtNull = 0; + +inline bool IsDynamicNameTag(std::int64_t tag) { + return tag == kDtNeeded || tag == kDtSoname || tag == kDtRpath || tag == kDtRunpath; +} constexpr std::uint32_t kShtDynamic = 6u; constexpr std::uint32_t kShtGnuVerneed = 0x6ffffffeu; constexpr std::uint32_t kShtDynsym = 11u; diff --git a/core/libs/nid/src/ElfNidPatcher.cpp b/core/libs/nid/src/ElfNidPatcher.cpp index aa9bd06c0..319cf1feb 100644 --- a/core/libs/nid/src/ElfNidPatcher.cpp +++ b/core/libs/nid/src/ElfNidPatcher.cpp @@ -190,7 +190,7 @@ void RemapDynamicNeededOffsets( for (std::size_t d = 0u; d < dynCount; ++d) { const std::size_t entryOffset = dynOffset + d * sizeof(Elf64_Dyn); const auto dyn = Read(elf, entryOffset); - if (dyn.d_tag != kDtNeeded && dyn.d_tag != kDtSoname) continue; + if (!IsDynamicNameTag(dyn.d_tag)) continue; const auto oldNameOffset = static_cast(dyn.d_val); const auto mapped = std::find_if( @@ -266,7 +266,7 @@ std::vector CollectDynamicNameOffsets(const std::vector(elf, dynOffset + d * sizeof(Elf64_Dyn)); if (dyn.d_tag == kDtNull) break; - if (dyn.d_tag != kDtNeeded && dyn.d_tag != kDtSoname) continue; + if (!IsDynamicNameTag(dyn.d_tag)) continue; offsets.push_back(static_cast(dyn.d_val)); } } diff --git a/core/libs/nid/tests/test_dynamic_strings.py b/core/libs/nid/tests/test_dynamic_strings.py new file mode 100644 index 000000000..1f9bbc847 --- /dev/null +++ b/core/libs/nid/tests/test_dynamic_strings.py @@ -0,0 +1,42 @@ +import re +import struct +import sys +from pathlib import Path + +DT_NULL = 0 +DT_NEEDED = 1 +DT_SONAME = 14 +DT_RPATH = 15 +DT_RUNPATH = 29 +SHT_DYNAMIC = 6 + + +def dynamic_strings(image): + shoff, = struct.unpack_from(" guest_module_fixture $ VERBATIM) add_dependencies(guest_module_fixture nid_patcher) + set_target_properties(guest_module_fixture PROPERTIES BUILD_WITH_INSTALL_RPATH ON INSTALL_RPATH "$ORIGIN") + find_package(Python3 QUIET COMPONENTS Interpreter) + if(Python3_Interpreter_FOUND AND NOT WIN32) + add_test(NAME nid_patcher_dynamic_strings COMMAND ${Python3_EXECUTABLE} + ${LIBS_INCLUDE_DIR}/nid/tests/test_dynamic_strings.py $) + endif() add_test_executable(guest_dynamic_loader_tests ${LIBS_INCLUDE_DIR}/tests/GuestDynamicLoader.cpp) target_include_directories(guest_dynamic_loader_tests PRIVATE ${LIBS_INCLUDE_DIR}) target_link_libraries(guest_dynamic_loader_tests PRIVATE libkernel libc)