From f882b613bcc9ebcdc7ec5d0b53178b4371f4752c Mon Sep 17 00:00:00 2001 From: PixelyIon Date: Tue, 10 Jan 2023 22:49:19 +0530 Subject: [PATCH] Fix `.hook` section being allocated without any hooked symbols Due to the trampoline and save/load context functions, `GetHookSectionSize` returned a non-zero size for when there were no hooked symbols supplied to it. This is problematic as it isn't required and hooking is currently not stable so it can lead to crashes or freezes in certain titles. --- app/src/main/cpp/skyline/loader/loader.cpp | 73 ++++++++++++++-------- app/src/main/cpp/skyline/nce.cpp | 3 + 2 files changed, 49 insertions(+), 27 deletions(-) diff --git a/app/src/main/cpp/skyline/loader/loader.cpp b/app/src/main/cpp/skyline/loader/loader.cpp index 1afbd50f..beb1e3c8 100644 --- a/app/src/main/cpp/skyline/loader/loader.cpp +++ b/app/src/main/cpp/skyline/loader/loader.cpp @@ -34,39 +34,58 @@ namespace skyline::loader { std::vector executableSymbols; size_t hookSize{}; if (dynamicallyLinked) { - for (auto &symbol : dynsym) { - if (symbol.st_name == 0 || symbol.st_value == 0) - continue; + if constexpr (!hle::HookedSymbols.empty()) { + for (auto &symbol : dynsym) { + if (symbol.st_name == 0 || symbol.st_value == 0) + continue; - if (ELF64_ST_TYPE(symbol.st_info) != STT_FUNC || ELF64_ST_BIND(symbol.st_info) != STB_GLOBAL || symbol.st_shndx == SHN_UNDEF) - continue; + if (ELF64_ST_TYPE(symbol.st_info) != STT_FUNC || ELF64_ST_BIND(symbol.st_info) != STB_GLOBAL || symbol.st_shndx == SHN_UNDEF) + continue; - std::string_view symbolName{dynstr.data() + symbol.st_name}; + std::string_view symbolName{dynstr.data() + symbol.st_name}; - auto item{std::find_if(hle::HookedSymbols.begin(), hle::HookedSymbols.end(), [&symbolName](const auto &item) { - return item.name == symbolName; - })}; - if (item != hle::HookedSymbols.end()) { - executableSymbols.emplace_back(std::string{symbolName}, item->hook, &symbol.st_value); - continue; + auto item{std::find_if(hle::HookedSymbols.begin(), hle::HookedSymbols.end(), [&symbolName](const auto &item) { + return item.name == symbolName; + })}; + if (item != hle::HookedSymbols.end()) { + executableSymbols.emplace_back(std::string{symbolName}, item->hook, &symbol.st_value); + continue; + } + + #ifdef PRINT_HOOK_ALL + if (symbolName == "memcpy" || symbolName == "memcmp" || symbolName == "memset" || symbolName == "strcmp" || symbolName == "strlen") + // If symbol is from libc (such as memcpy, strcmp, strlen, etc), we don't need to hook it + continue; + + executableSymbols.emplace_back(std::string{symbolName}, hle::EntryExitHook{ + .entry = [](const DeviceState &, const hle::HookedSymbol &symbol) { + Logger::Error("Entering \"{}\" ({})", symbol.prettyName, symbol.name); + }, + .exit = [](const DeviceState &, const hle::HookedSymbol &symbol) { + Logger::Error("Exiting \"{}\"", symbol.prettyName); + }, + }, &symbol.st_value); + #endif } - - #ifdef PRINT_HOOK_ALL - if (symbolName == "memcpy" || symbolName == "memcmp" || symbolName == "memset" || symbolName == "strcmp" || symbolName == "strlen") - // If symbol is from libc (such as memcpy, strcmp, strlen, etc), we don't need to hook it - continue; - - executableSymbols.emplace_back(std::string{symbolName}, hle::EntryExitHook{ - .entry = [](const DeviceState &, const hle::HookedSymbol &symbol) { - Logger::Error("Entering \"{}\" ({})", symbol.prettyName, symbol.name); - }, - .exit = [](const DeviceState &, const hle::HookedSymbol &symbol) { - Logger::Error("Exiting \"{}\"", symbol.prettyName); - }, - }, &symbol.st_value); - #endif } + #ifdef PRINT_HOOK_ALL + for (auto &symbol : dynsym) { + if (symbolName == "memcpy" || symbolName == "memcmp" || symbolName == "memset" || symbolName == "strcmp" || symbolName == "strlen") + // If symbol is from libc (such as memcpy, strcmp, strlen, etc), we don't need to hook it + continue; + + executableSymbols.emplace_back(std::string{symbolName}, hle::EntryExitHook{ + .entry = [](const DeviceState &, const hle::HookedSymbol &symbol) { + Logger::Error("Entering \"{}\" ({})", symbol.prettyName, symbol.name); + }, + .exit = [](const DeviceState &, const hle::HookedSymbol &symbol) { + Logger::Error("Exiting \"{}\"", symbol.prettyName); + }, + }, &symbol.st_value); + } + #endif + hookSize = util::AlignUp(state.nce->GetHookSectionSize(executableSymbols), PAGE_SIZE); } diff --git a/app/src/main/cpp/skyline/nce.cpp b/app/src/main/cpp/skyline/nce.cpp index 00a0ee0a..08d9b35f 100644 --- a/app/src/main/cpp/skyline/nce.cpp +++ b/app/src/main/cpp/skyline/nce.cpp @@ -515,6 +515,9 @@ namespace skyline::nce { } size_t NCE::GetHookSectionSize(span entries) { + if (entries.empty()) + return 0; + size_t size{guest::SaveCtxSize + guest::LoadCtxSize + TrampolineSize}; for (const auto &entry : entries) { constexpr size_t EmitTrampolineSize{10};