Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BS-Hooks 4] Paper switch and format #147

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ extern/
qpm.shared.json
*.backup
extern.cmake
qpm_defines.cmake
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is no longer ignored, where is the corresponding file committed to this repo? Shouldn't this still be ignored?

build/
*.log

Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ add_compile_options(-frtti -fPIE -fPIC -fexceptions -flto)
add_compile_options(-Wall -Wextra -Werror -Wno-unused-function)
# compile definitions used
add_compile_definitions(VERSION=\"${MOD_VERSION}\")
add_compile_definitions(ID=\"${MOD_ID}\")
add_compile_definitions(MOD_ID=\"${MOD_ID}\")
add_compile_definitions(UNITY_2019)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
Expand Down
13 changes: 9 additions & 4 deletions qpm.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
"version": "1.2.3",
"url": "https://github.com/sc2ad/beatsaber-hook",
"additionalData": {
"branchName": "master",
"soLink": "https://github.com/sc2ad/beatsaber-hook/releases/download/v0.5.8/libbeatsaber-hook.so",
"debugSoLink": "https://github.com/sc2ad/beatsaber-hook/releases/download/v0.5.8/debug_libbeatsaber-hook.so"
"debugSoLink": "https://github.com/sc2ad/beatsaber-hook/releases/download/v0.5.8/debug_libbeatsaber-hook.so",
"branchName": "master"
}
},
"dependencies": [
Expand All @@ -20,7 +20,7 @@
},
{
"id": "libil2cpp",
"versionRange": ">=0.1.2<0.3.0",
"versionRange": ">=0.1.2, <0.3.0",
"additionalData": {}
},
{
Expand All @@ -29,7 +29,12 @@
"additionalData": {
"private": true
}
},
{
"id": "paper",
"versionRange": "^1.2.14",
"additionalData": {}
}
],
"additionalData": {}
"workspace": null
}
107 changes: 107 additions & 0 deletions qpm.shared.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
{
"config": {
"sharedDir": "shared",
"dependenciesDir": "extern",
"info": {
"name": "beatsaber-hook",
"id": "beatsaber-hook",
"version": "1.2.3",
"url": "https://github.com/sc2ad/beatsaber-hook",
"additionalData": {
"soLink": "https://github.com/sc2ad/beatsaber-hook/releases/download/v0.5.8/libbeatsaber-hook.so",
"debugSoLink": "https://github.com/sc2ad/beatsaber-hook/releases/download/v0.5.8/debug_libbeatsaber-hook.so",
"branchName": "master"
}
},
"dependencies": [
{
"id": "modloader",
"versionRange": "^1.2.0",
"additionalData": {}
},
{
"id": "libil2cpp",
"versionRange": ">=0.1.2, <0.3.0",
"additionalData": {}
},
{
"id": "capstone",
"versionRange": "^0.1.0",
"additionalData": {
"private": true
}
},
{
"id": "paper",
"versionRange": "^1.2.14",
"additionalData": {}
}
],
"workspace": null
},
"restoredDependencies": [
{
"dependency": {
"id": "paper",
"versionRange": "=1.2.14",
"additionalData": {
"overrideSoName": "libpaperlog.so"
}
},
"version": "1.2.14"
},
{
"dependency": {
"id": "libil2cpp",
"versionRange": "=0.2.3",
"additionalData": {
"headersOnly": true
}
},
"version": "0.2.3"
},
{
"dependency": {
"id": "modloader",
"versionRange": "=1.2.3",
"additionalData": {
"soLink": "https://github.com/sc2ad/QuestLoader/releases/download/v1.2.3/libmodloader64.so",
"overrideSoName": "libmodloader.so",
"branchName": "version-v1.2.3"
}
},
"version": "1.2.3"
},
{
"dependency": {
"id": "fmt",
"versionRange": "=10.0.0",
"additionalData": {
"headersOnly": true,
"branchName": "version/v10_0_0",
"compileOptions": {
"systemIncludes": [
"fmt/include/"
],
"cppFlags": [
"-DFMT_HEADER_ONLY"
]
}
}
},
"version": "10.0.0"
},
{
"dependency": {
"id": "capstone",
"versionRange": "=0.1.0",
"additionalData": {
"staticLinking": true,
"soLink": "https://github.com/sc2ad/capstone-qpm/releases/download/v0.1.0/libcapstone.a",
"overrideSoName": "libcapstone.a"
}
},
"version": "0.1.0"
}
]
}
30 changes: 15 additions & 15 deletions shared/utils/capstone-utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ struct AddrSearchPair {

auto find_through_hooks(void const* hook, uint32_t initialSearchSize, auto&& func) {
// First, check to see if we are hooked.
Logger::get().debug("Finding through potential hook: %p and size: %u", hook, initialSearchSize);
il2cpp_utils::getLogger().fmtLog<Paper::LogLevel::DBG>("Finding through potential hook: {} and size: {}", fmt::ptr(hook), initialSearchSize);
auto hooks = HookTracker::GetHooks(hook);
if (!hooks.empty()) {
uint32_t const* addr = hooks.front().original_data.data();
uint32_t size = hooks.front().original_data.size() * sizeof(uint32_t);
Logger::get().debug("Hook found (%s)! Original data: %p with size: %u", hooks.front().name.c_str(), addr, size);
il2cpp_utils::getLogger().fmtLog<Paper::LogLevel::DBG>("Hook found ({})! Original data: {} with size: {}", hooks.front().name.c_str(), fmt::ptr(addr), size);
return func(cs::AddrSearchPair(addr, size), cs::AddrSearchPair(reinterpret_cast<uint32_t const*>(hook), initialSearchSize));
}
Logger::get().debug("No hook found! Searching: %p, %u", hook, initialSearchSize);
il2cpp_utils::getLogger().fmtLog<Paper::LogLevel::DBG>("No hook found! Searching: {}, {}", fmt::ptr(hook), initialSearchSize);
return func(cs::AddrSearchPair(reinterpret_cast<uint32_t const*>(hook), initialSearchSize));
}

Expand All @@ -46,14 +46,14 @@ decltype(auto) findNth(std::array<AddrSearchPair, sz>& addrs, uint32_t nToRetOn,
while (addrs[searchIdx].remSearchSize > 0) {
auto ptr = reinterpret_cast<uint64_t>(addrs[searchIdx].addr);
bool res = cs_disasm_iter(getHandle(), reinterpret_cast<const uint8_t**>(&addrs[searchIdx].addr), &addrs[searchIdx].remSearchSize, &ptr, insn);
Logger::get().debug("%p diassemb: %s (rCount: %i, nToRetOn: %u, sz: %zu)", (void*)ptr, insn->mnemonic, retCount, nToRetOn, addrs[searchIdx].remSearchSize);
il2cpp_utils::getLogger().fmtLog<Paper::LogLevel::DBG>("{} diassemb: {} (rCount: {}, nToRetOn: {}, sz: {})", fmt::ptr((void*)ptr), insn->mnemonic, retCount, nToRetOn, addrs[searchIdx].remSearchSize);
if (res) {
// Valid decode, so lets check to see if it is a match or we need to break.
if (insn->id == ARM64_INS_RET) {
if (retCount == 0) {
// Early termination!
cs_free(insn, 1);
Logger::get().warning("Could not find: %u call at: %p within: %i rets! Found all of the rets first!", nToRetOn, addrs[searchIdx].addr, retCount);
il2cpp_utils::getLogger().fmtLog<Paper::LogLevel::WRN>("Could not find: {} call at: {} within: {} rets! Found all of the rets first!", nToRetOn, fmt::ptr(addrs[searchIdx].addr), retCount);
return (decltype(match(insn)))std::nullopt;
}
retCount--;
Expand All @@ -70,7 +70,7 @@ decltype(auto) findNth(std::array<AddrSearchPair, sz>& addrs, uint32_t nToRetOn,
if (nToRetOn == 1) {
std::string name(insn->mnemonic);
cs_free(insn, 1);
Logger::get().warning("Found: %u match, at: %p within: %i rets, but the result was a %s! Cannot compute destination address!", nToRetOn, addrs[searchIdx].addr, retCount, name.c_str());
il2cpp_utils::getLogger().fmtLog<Paper::LogLevel::WRN>("Found: {} match, at: {} within: {} rets, but the result was a {}! Cannot compute destination address!", nToRetOn, fmt::ptr(addrs[searchIdx].addr), retCount, name.c_str());
return (decltype(match(insn)))std::nullopt;
} else {
nToRetOn--;
Expand All @@ -87,7 +87,7 @@ decltype(auto) findNth(std::array<AddrSearchPair, sz>& addrs, uint32_t nToRetOn,
}
}
// We didn't find it. Let's instead look at the next address/size pair for a match.
Logger::get().debug("Could not find: %u call at: %p within: %i rets at idx: %zu!", nToRetOn, addrs[searchIdx].addr, retCount, searchIdx);
il2cpp_utils::getLogger().fmtLog<Paper::LogLevel::DBG>("Could not find: {} call at: {} within: {} rets at idx: {}!", nToRetOn, fmt::ptr(addrs[searchIdx].addr), retCount, searchIdx);
}
// If we run out of bytes to parse, we fail
cs_free(insn, 1);
Expand All @@ -106,14 +106,14 @@ auto findNth(const uint32_t* addr, F1&& match, F2&& skip) {
size_t sz = szBytes;
while (sz > 0) {
bool res = cs_disasm_iter(getHandle(), &instructions, &sz, &ptr, insn);
Logger::get().debug("%p diassemb: %s (rCount: %i, nCalls: %u, sz: %zu)", (void*)ptr, insn->mnemonic, rCount, nCalls, sz);
il2cpp_utils::getLogger().fmtLog<Paper::LogLevel::DBG>("{} diassemb: {} (rCount: {}, nCalls: {}, sz: {})", fmt::ptr((void*)ptr), insn->mnemonic, rCount, nCalls, sz);
if (res) {
// Valid decode, so lets check to see if it is a match or we need to break.
if (insn->id == ARM64_INS_RET) {
if (rCount == 0) {
// Early termination!
cs_free(insn, 1);
Logger::get().warning("Could not find: %u call at: %p within: %i rets! Found all of the rets first!", nToRetOn, (void*)ptr, retCount);
il2cpp_utils::getLogger().fmtLog<Paper::LogLevel::WRN>("Could not find: {} call at: {} within: {} rets! Found all of the rets first!", nToRetOn, fmt::ptr((void*)ptr), retCount);
return (decltype(match(insn)))std::nullopt;
}
rCount--;
Expand All @@ -130,7 +130,7 @@ auto findNth(const uint32_t* addr, F1&& match, F2&& skip) {
if (nCalls == 1) {
std::string name(insn->mnemonic);
cs_free(insn, 1);
Logger::get().warning("Found: %u match, at: %p within: %i rets, but the result was a %s! Cannot compute destination address!", nToRetOn, (void*)ptr, retCount, name.c_str());
il2cpp_utils::getLogger().fmtLog<Paper::LogLevel::WRN>("Found: {} match, at: {} within: {} rets, but the result was a {}! Cannot compute destination address!", nToRetOn, fmt::ptr((void*)ptr), retCount, name.c_str());
return (decltype(match(insn)))std::nullopt;
} else {
nCalls--;
Expand All @@ -149,7 +149,7 @@ auto findNth(const uint32_t* addr, F1&& match, F2&& skip) {
}
// If we run out of bytes to parse, we fail
cs_free(insn, 1);
Logger::get().warning("Could not find: %u call at: %p within: %i rets, within size: %zu!", nToRetOn, addr, retCount, szBytes);
il2cpp_utils::getLogger().fmtLog<Paper::LogLevel::WRN>("Could not find: {} call at: {} within: {} rets, within size: {}!", nToRetOn, fmt::ptr(addr), retCount, szBytes);
return (decltype(match(insn)))std::nullopt;
}

Expand All @@ -165,14 +165,14 @@ auto findNth(const uint32_t* addr) {
size_t sz = szBytes;
while (sz > 0) {
bool res = cs_disasm_iter(getHandle(), &instructions, &sz, &ptr, insn);
Logger::get().debug("%p diassemb: %s (rCount: %i, nCalls: %u, sz: %zu)", (void*)ptr, insn->mnemonic, rCount, nCalls, sz);
il2cpp_utils::getLogger().fmtLog<Paper::LogLevel::DBG>("{} diassemb: {} (rCount: {}, nCalls: {}, sz: {})", fmt::ptr((void*)ptr), insn->mnemonic, rCount, nCalls, sz);
if (res) {
// Valid decode, so lets check to see if it is a match or we need to break.
if (insn->id == ARM64_INS_RET) {
if (rCount == 0) {
// Early termination!
cs_free(insn, 1);
Logger::get().warning("Could not find: %u call at: %p within: %i rets! Found all of the rets first!", nToRetOn, (void*)ptr, retCount);
il2cpp_utils::getLogger().fmtLog<Paper::LogLevel::WRN>("Could not find: {} call at: {} within: {} rets! Found all of the rets first!", nToRetOn, fmt::ptr((void*)ptr), retCount);
return (decltype(match(insn)))std::nullopt;
}
rCount--;
Expand All @@ -189,7 +189,7 @@ auto findNth(const uint32_t* addr) {
if (nCalls == 1) {
std::string name(insn->mnemonic);
cs_free(insn, 1);
Logger::get().warning("Found: %u match, at: %p within: %i rets, but the result was a %s! Cannot compute destination address!", nToRetOn, (void*)ptr, retCount, name.c_str());
il2cpp_utils::getLogger().fmtLog<Paper::LogLevel::WRN>("Found: {} match, at: {} within: {} rets, but the result was a {}! Cannot compute destination address!", nToRetOn, fmt::ptr((void*)ptr), retCount, name.c_str());
return (decltype(match(insn)))std::nullopt;
} else {
nCalls--;
Expand All @@ -201,7 +201,7 @@ auto findNth(const uint32_t* addr) {
else {
// Invalid instructions are ignored silently.
// In order to skip these properly, we must increment our instructions, ptr, and size accordingly.
Logger::get().warning("FAILED PARSE: %p diassemb: 0x%x", (void*)ptr, *(uint32_t*)ptr);
il2cpp_utils::getLogger().fmtLog<Paper::LogLevel::WRN>("FAILED PARSE: {} diassemb: 0x{:x}", fmt::ptr((void*)ptr), *(uint32_t*)ptr);
sz -= 4;
ptr += 4;
instructions += 4;
Expand Down
8 changes: 4 additions & 4 deletions shared/utils/hooking.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ retval Hook_##name_::hook_##name_(__VA_ARGS__)
template<typename T, typename L, bool track = true>
inline void __InstallHook(L& logger, void* addr) {
#ifndef SUPPRESS_MACRO_LOGS
logger.info("Installing hook: %s to offset: %p", T::name(), addr);
logger.fmtLog<Paper::LogLevel::INF>("Installing hook: {} to offset: {}", T::name(), fmt::ptr(addr));
#endif
#ifdef __aarch64__
if constexpr (track) {
Expand Down Expand Up @@ -631,7 +631,7 @@ void InstallHook(L& logger) {
auto info = T::getInfo();
if (!info) {
#ifndef SUPPRESS_MACRO_LOGS
logger.critical("Attempting to install hook: %s, but method could not be found!", T::name());
logger.fmtLog<Paper::LogLevel::CRIT>("Attempting to install hook: {}, but method could not be found!", T::name());
#endif
SAFE_ABORT();
}
Expand All @@ -645,7 +645,7 @@ void InstallOrigHook(L& logger) {
auto info = T::getInfo();
if (!info) {
#ifndef SUPPRESS_MACRO_LOGS
logger.critical("Attempting to install hook: %s, but method could not be found!", T::name());
logger.fmtLog<Paper::LogLevel::INF>("Attempting to install hook: {}, but method could not be found!", T::name());
#endif
SAFE_ABORT();
}
Expand All @@ -666,7 +666,7 @@ void InstallHookDirect(L& logger, void* dst) {
// Install T into the specified address. Null checks dst.
if (!dst) {
#ifndef SUPPRESS_MACRO_LOGS
logger.critical("Attempting to install direct hook: %s, but was installing to an invalid destination!", T::name());
logger.fmtLog<Paper::LogLevel::CRIT>("Attempting to install direct hook: {}, but was installing to an invalid destination!", T::name());
#endif
SAFE_ABORT();
}
Expand Down
19 changes: 9 additions & 10 deletions shared/utils/il2cpp-functions.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// ifguard because pragma once doesn't work as intended
#ifndef IL2CPP_FUNCTIONS_H
#define IL2CPP_FUNCTIONS_H

#pragma pack(push)

#include <cstddef>
#include <stdio.h>
#include <stdlib.h>
Expand Down Expand Up @@ -118,6 +118,7 @@ static rt name(TArgs&&... args) { \
return il2cpp_##name(args...); \
} \
}

// A class which contains all available il2cpp functions
// Created by zoller27osu
class il2cpp_functions {
Expand Down Expand Up @@ -434,16 +435,16 @@ class il2cpp_functions {
// must be done on-demand because the pointers aren't necessarily correct at the time of il2cpp_functions::Init
static void CheckS_GlobalMetadata() {
if (!s_GlobalMetadataHeader) {
static auto& logger = getFuncLogger();
auto& logger = ::il2cpp_utils::getLogger();
s_GlobalMetadata = *CRASH_UNLESS(il2cpp_functions::s_GlobalMetadataPtr);
s_GlobalMetadataHeader = *CRASH_UNLESS(il2cpp_functions::s_GlobalMetadataHeaderPtr);
s_Il2CppMetadataRegistration = *CRASH_UNLESS(il2cpp_functions::s_Il2CppMetadataRegistrationPtr);
logger.debug("sanity: %X (should be 0xFAB11BAF)", s_GlobalMetadataHeader->sanity);
logger.debug("version: %i", s_GlobalMetadataHeader->version);
logger.fmtLog<Paper::LogLevel::DBG>("sanity: {:X} (should be 0xFAB11BAF)", s_GlobalMetadataHeader->sanity);
logger.fmtLog<Paper::LogLevel::DBG>("version: {}", s_GlobalMetadataHeader->version);
CRASH_UNLESS((uint32_t)s_GlobalMetadataHeader->sanity == 0xFAB11BAF);
logger.debug("typeDefinitionsOffset: %i", s_GlobalMetadataHeader->typeDefinitionsOffset);
logger.debug("exportedTypeDefinitionsOffset: %i", s_GlobalMetadataHeader->exportedTypeDefinitionsOffset);
logger.debug("nestedTypesOffset: %i", s_GlobalMetadataHeader->nestedTypesOffset);
logger.fmtLog<Paper::LogLevel::DBG>("typeDefinitionsOffset: {}", s_GlobalMetadataHeader->typeDefinitionsOffset);
logger.fmtLog<Paper::LogLevel::DBG>("exportedTypeDefinitionsOffset: {}", s_GlobalMetadataHeader->exportedTypeDefinitionsOffset);
logger.fmtLog<Paper::LogLevel::DBG>("nestedTypesOffset: {}", s_GlobalMetadataHeader->nestedTypesOffset);
// TODO: use il2cpp_functions::defaults to define the il2cpp_defaults variable mentioned in il2cpp-class-internals.h
}
}
Expand All @@ -461,12 +462,10 @@ class il2cpp_functions {
static bool initialized;
// Initializes all of the IL2CPP functions via dlopen and dlsym for use.
static void Init();

static LoggerContextObject& getFuncLogger();
};

#undef API_FUNC

#pragma pack(pop)

#endif /* IL2CPP_FUNCTIONS_H */
#endif
Loading