This commit is contained in:
Valdis Bogdāns 2026-04-06 22:58:47 +02:00 committed by GitHub
commit b2e5d587c7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 640 additions and 160 deletions

View File

@ -582,6 +582,9 @@ set(FIBER_LIB src/core/libraries/fiber/fiber_context.s
)
set_source_files_properties(src/core/libraries/fiber/fiber_context.s PROPERTIES COMPILE_OPTIONS -Wno-unused-command-line-argument)
if(APPLE)
set_source_files_properties(src/core/libraries/fiber/fiber.cpp PROPERTIES COMPILE_OPTIONS -fno-lto)
endif()
set(VDEC_LIB src/core/libraries/videodec/videodec2_impl.cpp
src/core/libraries/videodec/videodec2_impl.h

View File

@ -141,6 +141,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
SUB(Lib, Vdec2) \
SUB(Lib, Videodec) \
SUB(Lib, RazorCpu) \
SUB(Lib, Ulobjmgr) \
SUB(Lib, Mouse) \
SUB(Lib, WebBrowserDialog) \
SUB(Lib, NpParty) \

View File

@ -108,6 +108,7 @@ enum class Class : u8 {
Lib_Videodec, ///< The LibSceVideodec implementation.
Lib_Voice, ///< The LibSceVoice implementation.
Lib_RazorCpu, ///< The LibRazorCpu implementation.
Lib_Ulobjmgr, ///< The ulobjmgr implementation.
Lib_Mouse, ///< The LibSceMouse implementation
Lib_WebBrowserDialog, ///< The LibSceWebBrowserDialog implementation
Lib_NpParty, ///< The LibSceNpParty implementation

View File

@ -6,18 +6,285 @@
#include "common/elf_info.h"
#include "common/logging/log.h"
#include "core/libraries/fiber/fiber_error.h"
#include "core/libraries/kernel/memory.h"
#include "core/libraries/kernel/threads/pthread.h"
#include "core/libraries/libs.h"
#include "core/libraries/razor_cpu/razor_cpu.h"
#include "core/libraries/system/sysmodule.h"
#include "core/libraries/ulobjmgr/ulobjmgr.h"
#include "core/tls.h"
#include <cstddef>
#include <cstdint>
#include <cstring>
#if defined(_MSC_VER)
#include <intrin.h>
#endif
namespace Libraries::Fiber {
static constexpr u32 kFiberSignature0 = 0xdef1649c;
static constexpr u32 kFiberSignature1 = 0xb37592a0;
static constexpr u32 kFiberOptSignature = 0xbb40e64d;
static constexpr u64 kFiberEntryXor = 0xca953a6953c56aa5;
static constexpr u64 kFiberArgInitXor = 0xa356a3569c95ca5a;
static constexpr u32 kFiberRazorIdXor = 0x5a4c69a5;
static constexpr u64 kFiberSwitchCookieInit = 0xa5a569695c5c5a5a;
static constexpr u64 kFiberStackSignature = 0x7149f2ca7149f2ca;
static constexpr u64 kFiberStackSizeCheck = 0xdeadbeefdeadbeef;
static constexpr u64 kFiberNameSeedInit = 0x1234567812345678;
static constexpr u64 kFiberNameSeedMul = 0xfedcba89fedcba89;
static constexpr u64 kFiberNameSeedAdd = 0x9182736591827365;
static constexpr u8 kFiberNameXorTable[ORBIS_FIBER_MAX_NAME_LENGTH + 1] = {
0x5a, 0x5a, 0x66, 0x66, 0x99, 0x99, 0x66, 0x96, 0x99, 0x66, 0x99, 0x96, 0x33, 0x33, 0xcc, 0xcc,
0x33, 0xc3, 0xcc, 0x33, 0xcc, 0xc3, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0xa5, 0xaa, 0x55, 0xaa, 0xa5,
};
static std::atomic<u32> context_size_check = false;
static std::atomic<u64> name_seed = kFiberNameSeedInit;
static std::atomic<u32> fiber_globals_init = false;
static std::atomic<u32> razor_enabled = false;
static std::atomic<u32> asan_enabled = false;
static std::atomic<u64> switch_cookie_counter = 0;
static u64 PthreadSelf() {
auto* thread = ::Libraries::Kernel::posix_pthread_self();
return reinterpret_cast<u64>(thread);
}
static void GetThreadStack(void** stack_addr, size_t* stack_size) {
if (!stack_addr || !stack_size) {
return;
}
auto* thread = ::Libraries::Kernel::g_curthread;
if (!thread) {
*stack_addr = nullptr;
*stack_size = 0;
return;
}
*stack_addr = thread->attr.stackaddr_attr;
*stack_size = thread->attr.stacksize_attr;
}
static void RazorCpuFiberSwitch(u32 from_id, u32 to_id, u32 reason) {
(void)from_id;
(void)to_id;
(void)reason;
::Libraries::RazorCpu::sceRazorCpuFiberSwitch();
}
static void RazorCpuFiberLogNameChange(OrbisFiber* fiber, const char* name) {
(void)fiber;
(void)name;
::Libraries::RazorCpu::sceRazorCpuFiberLogNameChange();
}
static s32 UlobjmgrRegister(u64 arg0, s32 arg1, u32* arg2) {
return ::Libraries::Ulobjmgr::Func_046DBA8411A2365C(arg0, arg1, arg2);
}
static s32 UlobjmgrUnregister(u32 arg0) {
return ::Libraries::Ulobjmgr::Func_4A67FE7D435B94F7(arg0);
}
extern "C" {
void PS4_SYSV_ABI __sanitizer_start_switch_fiber(void** fake_stack_save, const void* stack_addr,
size_t stack_size);
void PS4_SYSV_ABI __sanitizer_finish_switch_fiber(void* fake_stack_save,
const void** old_stack_addr,
size_t* old_stack_size);
void PS4_SYSV_ABI __asan_destroy_fake_stack();
} // extern "C"
extern "C" void PS4_SYSV_ABI __sanitizer_start_switch_fiber(void** fake_stack_save,
const void* stack_addr,
size_t stack_size) {
(void)fake_stack_save;
(void)stack_addr;
(void)stack_size;
}
extern "C" void PS4_SYSV_ABI __sanitizer_finish_switch_fiber(void* fake_stack_save,
const void** old_stack_addr,
size_t* old_stack_size) {
(void)fake_stack_save;
(void)old_stack_addr;
(void)old_stack_size;
}
extern "C" void PS4_SYSV_ABI __asan_destroy_fake_stack() {}
#if defined(__APPLE__)
extern "C" void PS4_SYSV_ABI __sanitizer_start_switch_fiber_macho(void** fake_stack_save,
const void* stack_addr,
size_t stack_size)
__attribute__((used, externally_visible,
visibility("default"))) asm("__sanitizer_start_switch_fiber");
extern "C" void PS4_SYSV_ABI __sanitizer_finish_switch_fiber_macho(void* fake_stack_save,
const void** old_stack_addr,
size_t* old_stack_size)
__attribute__((used, externally_visible,
visibility("default"))) asm("__sanitizer_finish_switch_fiber");
extern "C" void PS4_SYSV_ABI __asan_destroy_fake_stack_macho(void)
__attribute__((used, externally_visible,
visibility("default"))) asm("__asan_destroy_fake_stack");
extern "C" void PS4_SYSV_ABI __sanitizer_start_switch_fiber_macho(void** fake_stack_save,
const void* stack_addr,
size_t stack_size) {
__sanitizer_start_switch_fiber(fake_stack_save, stack_addr, stack_size);
}
extern "C" void PS4_SYSV_ABI __sanitizer_finish_switch_fiber_macho(void* fake_stack_save,
const void** old_stack_addr,
size_t* old_stack_size) {
__sanitizer_finish_switch_fiber(fake_stack_save, old_stack_addr, old_stack_size);
}
extern "C" void PS4_SYSV_ABI __asan_destroy_fake_stack_macho(void) {
__asan_destroy_fake_stack();
}
#endif
static void EnsureFiberGlobalsInitialized() {
u32 expected = 0;
if (fiber_globals_init.compare_exchange_strong(expected, 1u, std::memory_order_relaxed)) {
const auto razor_loaded = ::Libraries::SysModule::sceSysmoduleIsLoadedInternal(
::Libraries::SysModule::OrbisSysModuleInternal::ORBIS_SYSMODULE_INTERNAL_RAZOR_CPU);
razor_enabled.store(razor_loaded == 0 ? 1u : 0u, std::memory_order_relaxed);
asan_enabled.store(::Libraries::Kernel::sceKernelIsAddressSanitizerEnabled() != 0 ? 1u : 0u,
std::memory_order_relaxed);
}
}
static bool RazorEnabled() {
EnsureFiberGlobalsInitialized();
return razor_enabled.load(std::memory_order_relaxed) != 0;
}
static bool AsanEnabled() {
EnsureFiberGlobalsInitialized();
return asan_enabled.load(std::memory_order_relaxed) != 0;
}
static void UpdateSwitchCookie(OrbisFiber* fiber) {
const u64 value = switch_cookie_counter.fetch_add(1, std::memory_order_relaxed) + 1;
fiber->switch_cookie = value ^ kFiberSwitchCookieInit;
}
static u64 ComputeContextSizeMargin(const OrbisFiber* fiber) {
if (!fiber || !fiber->context_start || !fiber->context_end) {
return 0;
}
u64* stack_start = reinterpret_cast<u64*>(fiber->context_start);
u64* stack_end = reinterpret_cast<u64*>(fiber->context_end);
if (stack_start >= stack_end) {
return 0;
}
u64* stack_ptr = stack_start + 1;
while (stack_ptr < stack_end && *stack_ptr == kFiberStackSizeCheck) {
++stack_ptr;
}
return reinterpret_cast<u64>(stack_ptr) - reinterpret_cast<u64>(stack_start + 1);
}
static u64 NextNameSeed() {
u64 seed = name_seed.load(std::memory_order_relaxed);
u64 next = 0;
do {
next = seed * kFiberNameSeedMul + kFiberNameSeedAdd;
} while (!name_seed.compare_exchange_weak(seed, next, std::memory_order_relaxed));
return next;
}
static void FillFiberRandomPad(OrbisFiber* fiber) {
if (!fiber) {
return;
}
constexpr size_t kRandomPadWords = 0x78 / sizeof(u64);
u64 values[kRandomPadWords]{};
for (size_t i = 0; i < kRandomPadWords; ++i) {
values[i] = NextNameSeed();
}
std::memcpy(fiber->random_pad, values, sizeof(values));
}
static void EncodeFiberName(OrbisFiber* fiber, const char* name) {
if (!fiber) {
return;
}
u64 seed_values[4] = {NextNameSeed(), NextNameSeed(), NextNameSeed(), NextNameSeed()};
std::memcpy(fiber->name_xor, seed_values, sizeof(seed_values));
if (!name) {
fiber->name_xor[0] = kFiberNameXorTable[0];
return;
}
for (u32 i = 0; i < ORBIS_FIBER_MAX_NAME_LENGTH; ++i) {
const u8 value = static_cast<u8>(name[i]);
if (value == 0) {
fiber->name_xor[i] = kFiberNameXorTable[i];
return;
}
fiber->name_xor[i] = value ^ kFiberNameXorTable[i];
}
fiber->name_xor[ORBIS_FIBER_MAX_NAME_LENGTH] = 0xa5;
}
static void DecodeFiberName(const OrbisFiber* fiber, char* out, size_t out_size) {
if (!fiber || !out || out_size < ORBIS_FIBER_MAX_NAME_LENGTH + 1) {
return;
}
for (u32 i = 0; i < ORBIS_FIBER_MAX_NAME_LENGTH; ++i) {
const u8 value = fiber->name_xor[i] ^ kFiberNameXorTable[i];
out[i] = static_cast<char>(value);
if (value == 0) {
std::memset(out + i + 1, 0, ORBIS_FIBER_MAX_NAME_LENGTH - i);
return;
}
}
out[ORBIS_FIBER_MAX_NAME_LENGTH] = '\0';
}
static OrbisFiberEntry DecodeEntry(const OrbisFiber* fiber) {
return reinterpret_cast<OrbisFiberEntry>(fiber->entry_xor ^ kFiberEntryXor);
}
static void EncodeEntry(OrbisFiber* fiber, OrbisFiberEntry entry) {
fiber->entry_xor = reinterpret_cast<u64>(entry) ^ kFiberEntryXor;
}
static u64 DecodeArgOnInitialize(const OrbisFiber* fiber) {
return fiber->arg_on_initialize_xor ^ kFiberArgInitXor;
}
static void EncodeArgOnInitialize(OrbisFiber* fiber, u64 arg_on_initialize) {
fiber->arg_on_initialize_xor = arg_on_initialize ^ kFiberArgInitXor;
}
static bool TryTransitionFiberState(OrbisFiber* fiber, FiberState expected, FiberState desired) {
std::atomic_ref<u32> state_ref(fiber->state);
u32 expected_value = static_cast<u32>(expected);
return state_ref.compare_exchange_strong(expected_value, static_cast<u32>(desired),
std::memory_order_seq_cst);
}
static void StoreFiberState(OrbisFiber* fiber, FiberState value) {
std::atomic_ref<u32> state_ref(fiber->state);
state_ref.store(static_cast<u32>(value), std::memory_order_seq_cst);
}
OrbisFiberContext* GetFiberContext() {
return Core::GetTcbBase()->tcb_fiber;
@ -36,9 +303,26 @@ extern "C" void PS4_SYSV_ABI _sceFiberForceQuit(u64 ret) {
}
void PS4_SYSV_ABI _sceFiberCheckStackOverflow(OrbisFiberContext* ctx) {
u64* stack_base = reinterpret_cast<u64*>(ctx->current_fiber->addr_context);
u64 stack_size = ctx->current_fiber->size_context;
OrbisFiber* fiber = ctx->current_fiber;
u64* stack_base = reinterpret_cast<u64*>(fiber->addr_context);
u64 stack_size = fiber->size_context;
if (stack_base && *stack_base != kFiberStackSignature) {
char name[ORBIS_FIBER_MAX_NAME_LENGTH + 1]{};
DecodeFiberName(fiber, name, sizeof(name));
const uintptr_t stack_base_addr = reinterpret_cast<uintptr_t>(stack_base);
const uintptr_t stack_top_addr = stack_base_addr + static_cast<uintptr_t>(stack_size);
LOG_CRITICAL(
Lib_Fiber,
"Fiber stack overflow: name='{}' fiber={:#x} ctx={:#x} stack_base={:#x} "
"stack_top={:#x} size=0x{:x} sig={:#x} expected={:#x} context_start={:#x} "
"context_end={:#x} flags=0x{:x} state=0x{:x} switch_cookie={:#x} magic_start=0x{:x} "
"magic_end=0x{:x}",
name, reinterpret_cast<uintptr_t>(fiber), reinterpret_cast<uintptr_t>(ctx),
stack_base_addr, stack_top_addr, stack_size, *stack_base, kFiberStackSignature,
reinterpret_cast<uintptr_t>(fiber->context_start),
reinterpret_cast<uintptr_t>(fiber->context_end), fiber->flags, fiber->state,
fiber->switch_cookie, fiber->magic_start, fiber->magic_end);
UNREACHABLE_MSG("Stack overflow detected in fiber with size = 0x{:x}", stack_size);
}
}
@ -64,6 +348,11 @@ s32 PS4_SYSV_ABI _sceFiberAttachContext(OrbisFiber* fiber, void* addr_context, u
/* Apply signature to start of stack */
*(u64*)addr_context = kFiberStackSignature;
LOG_INFO(
Lib_Fiber,
"Fiber attach context: fiber={:#x} addr_context={:#x} size=0x{:x} sig={:#x} flags=0x{:x}",
reinterpret_cast<uintptr_t>(fiber), reinterpret_cast<uintptr_t>(addr_context), size_context,
*(u64*)addr_context, fiber->flags);
if (fiber->flags & FiberFlags::ContextSizeCheck) {
u64* stack_start = reinterpret_cast<u64*>(fiber->context_start);
@ -79,7 +368,7 @@ s32 PS4_SYSV_ABI _sceFiberAttachContext(OrbisFiber* fiber, void* addr_context, u
}
void PS4_SYSV_ABI _sceFiberSwitchToFiber(OrbisFiber* fiber, u64 arg_on_run_to,
OrbisFiberContext* ctx) {
OrbisFiberContext* ctx, u64 asan_cookie) {
OrbisFiberContext* fiber_ctx = fiber->context;
if (fiber_ctx) {
ctx->arg_on_run_to = arg_on_run_to;
@ -96,52 +385,53 @@ void PS4_SYSV_ABI _sceFiberSwitchToFiber(OrbisFiber* fiber, u64 arg_on_run_to,
data.state = nullptr;
}
data.entry = fiber->entry;
data.arg_on_initialize = fiber->arg_on_initialize;
data.entry = DecodeEntry(fiber);
data.arg_on_initialize = DecodeArgOnInitialize(fiber);
data.arg_on_run_to = arg_on_run_to;
data.stack_addr = reinterpret_cast<u8*>(fiber->addr_context) + fiber->size_context;
if (fiber->flags & FiberFlags::SetFpuRegs) {
data.fpucw = 0x037f;
data.mxcsr = 0x9fc0;
_sceFiberSwitchEntry(&data, true);
} else {
_sceFiberSwitchEntry(&data, false);
}
data.asan_fake_stack = reinterpret_cast<void*>(asan_cookie);
_sceFiberSwitchEntry(&data, (fiber->flags & FiberFlags::SetFpuRegs) != 0);
__builtin_trap();
}
void PS4_SYSV_ABI _sceFiberSwitch(OrbisFiber* cur_fiber, OrbisFiber* fiber, u64 arg_on_run_to,
OrbisFiberContext* ctx) {
OrbisFiberContext* ctx, u64 asan_cookie) {
UpdateSwitchCookie(cur_fiber);
ctx->prev_fiber = cur_fiber;
ctx->current_fiber = fiber;
if (RazorEnabled()) {
RazorCpuFiberSwitch(static_cast<u32>(reinterpret_cast<uintptr_t>(cur_fiber)),
static_cast<u32>(reinterpret_cast<uintptr_t>(fiber)), 1);
}
if (fiber->addr_context == nullptr) {
ctx->prev_fiber = nullptr;
OrbisFiberData data{};
data.entry = fiber->entry;
data.arg_on_initialize = fiber->arg_on_initialize;
data.entry = DecodeEntry(fiber);
data.arg_on_initialize = DecodeArgOnInitialize(fiber);
data.arg_on_run_to = arg_on_run_to;
data.stack_addr = reinterpret_cast<void*>(ctx->rsp & ~15);
data.stack_addr = reinterpret_cast<void*>(ctx->jmp.rsp & ~15);
data.state = reinterpret_cast<u32*>(&cur_fiber->state);
if (fiber->flags & FiberFlags::SetFpuRegs) {
data.fpucw = 0x037f;
data.mxcsr = 0x9fc0;
_sceFiberSwitchEntry(&data, true);
if (asan_cookie != 0) {
data.asan_fake_stack =
reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(fiber->asan_fake_stack) + 1);
} else {
_sceFiberSwitchEntry(&data, false);
data.asan_fake_stack = nullptr;
}
_sceFiberSwitchEntry(&data, (fiber->flags & FiberFlags::SetFpuRegs) != 0);
__builtin_trap();
}
_sceFiberSwitchToFiber(fiber, arg_on_run_to, ctx);
_sceFiberSwitchToFiber(fiber, arg_on_run_to, ctx, asan_cookie);
__builtin_trap();
}
void PS4_SYSV_ABI _sceFiberTerminate(OrbisFiber* fiber, u64 arg_on_return, OrbisFiberContext* ctx) {
UpdateSwitchCookie(fiber);
ctx->arg_on_return = arg_on_return;
_sceFiberLongJmp(ctx);
__builtin_trap();
@ -151,6 +441,7 @@ s32 PS4_SYSV_ABI sceFiberInitializeImpl(OrbisFiber* fiber, const char* name, Orb
u64 arg_on_initialize, void* addr_context, u64 size_context,
const OrbisFiberOptParam* opt_param, u32 flags,
u32 build_ver) {
EnsureFiberGlobalsInitialized();
if (!fiber || !name || !entry) {
return ORBIS_FIBER_ERROR_NULL;
}
@ -172,6 +463,9 @@ s32 PS4_SYSV_ABI sceFiberInitializeImpl(OrbisFiber* fiber, const char* name, Orb
if (addr_context && !size_context) {
return ORBIS_FIBER_ERROR_INVALID;
}
if (size_context && size_context <= 4096) {
LOG_WARNING(Lib_Fiber, "Fiber initialized with small stack area.");
}
if (opt_param && opt_param->magic != kFiberOptSignature) {
return ORBIS_FIBER_ERROR_INVALID;
}
@ -180,26 +474,25 @@ s32 PS4_SYSV_ABI sceFiberInitializeImpl(OrbisFiber* fiber, const char* name, Orb
if (build_ver >= Common::ElfInfo::FW_35) {
user_flags |= FiberFlags::SetFpuRegs;
}
if (context_size_check) {
if (context_size_check.load(std::memory_order_relaxed) != 0) {
user_flags |= FiberFlags::ContextSizeCheck;
}
strncpy(fiber->name, name, ORBIS_FIBER_MAX_NAME_LENGTH);
fiber->entry = entry;
fiber->arg_on_initialize = arg_on_initialize;
FillFiberRandomPad(fiber);
EncodeFiberName(fiber, name);
EncodeEntry(fiber, entry);
EncodeArgOnInitialize(fiber, arg_on_initialize);
fiber->addr_context = addr_context;
fiber->size_context = size_context;
fiber->context = nullptr;
fiber->owner_thread = 0;
fiber->flags = user_flags;
/*
A low stack area is problematic, as we can easily
cause a stack overflow with our HLE.
*/
if (size_context && size_context <= 4096) {
LOG_WARNING(Lib_Fiber, "Fiber initialized with small stack area.");
}
fiber->razor_id_xor = 0;
fiber->switch_cookie = kFiberSwitchCookieInit;
fiber->asan_fake_stack = nullptr;
fiber->context_start = nullptr;
fiber->context_end = nullptr;
fiber->reserved = 0;
fiber->magic_start = kFiberSignature0;
fiber->magic_end = kFiberSignature1;
@ -210,8 +503,14 @@ s32 PS4_SYSV_ABI sceFiberInitializeImpl(OrbisFiber* fiber, const char* name, Orb
/* Apply signature to start of stack */
*(u64*)addr_context = kFiberStackSignature;
LOG_INFO(Lib_Fiber,
"Fiber init context: fiber={:#x} name='{}' addr_context={:#x} size=0x{:x} "
"sig={:#x} flags=0x{:x}",
reinterpret_cast<uintptr_t>(fiber), name,
reinterpret_cast<uintptr_t>(addr_context), size_context, *(u64*)addr_context,
fiber->flags);
if (flags & FiberFlags::ContextSizeCheck) {
if (fiber->flags & FiberFlags::ContextSizeCheck) {
u64* stack_start = reinterpret_cast<u64*>(fiber->context_start);
u64* stack_end = reinterpret_cast<u64*>(fiber->context_end);
@ -222,7 +521,17 @@ s32 PS4_SYSV_ABI sceFiberInitializeImpl(OrbisFiber* fiber, const char* name, Orb
}
}
fiber->state = FiberState::Idle;
StoreFiberState(fiber, FiberState::Idle);
if ((fiber->flags & FiberFlags::NoUlobjmgr) == 0) {
LOG_DEBUG(Lib_Fiber, "Ulobjmgr register: fiber={:#x} flags=0x{:x}",
reinterpret_cast<uintptr_t>(fiber), fiber->flags);
u32 razor_id = 0;
UlobjmgrRegister(reinterpret_cast<u64>(fiber), 1, &razor_id);
fiber->razor_id_xor = razor_id ^ kFiberRazorIdXor;
} else {
LOG_DEBUG(Lib_Fiber, "Ulobjmgr register skipped (NoUlobjmgr): fiber={:#x} flags=0x{:x}",
reinterpret_cast<uintptr_t>(fiber), fiber->flags);
}
return ORBIS_OK;
}
@ -234,11 +543,13 @@ s32 PS4_SYSV_ABI sceFiberOptParamInitialize(OrbisFiberOptParam* opt_param) {
return ORBIS_FIBER_ERROR_ALIGNMENT;
}
std::memset(opt_param, 0, sizeof(*opt_param));
opt_param->magic = kFiberOptSignature;
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceFiberFinalize(OrbisFiber* fiber) {
EnsureFiberGlobalsInitialized();
if (!fiber) {
return ORBIS_FIBER_ERROR_NULL;
}
@ -249,16 +560,33 @@ s32 PS4_SYSV_ABI sceFiberFinalize(OrbisFiber* fiber) {
return ORBIS_FIBER_ERROR_INVALID;
}
FiberState expected = FiberState::Idle;
if (!fiber->state.compare_exchange_strong(expected, FiberState::Terminated)) {
if (!TryTransitionFiberState(fiber, FiberState::Idle, FiberState::Terminated)) {
return ORBIS_FIBER_ERROR_STATE;
}
if (RazorEnabled()) {
char name[ORBIS_FIBER_MAX_NAME_LENGTH + 1]{};
DecodeFiberName(fiber, name, sizeof(name));
RazorCpuFiberLogNameChange(fiber, name);
}
if ((fiber->flags & FiberFlags::NoUlobjmgr) == 0) {
LOG_DEBUG(Lib_Fiber, "Ulobjmgr unregister: fiber={:#x} flags=0x{:x}",
reinterpret_cast<uintptr_t>(fiber), fiber->flags);
UlobjmgrUnregister(fiber->razor_id_xor ^ kFiberRazorIdXor);
} else {
LOG_DEBUG(Lib_Fiber, "Ulobjmgr unregister skipped (NoUlobjmgr): fiber={:#x} flags=0x{:x}",
reinterpret_cast<uintptr_t>(fiber), fiber->flags);
}
if (AsanEnabled() && fiber->asan_fake_stack != nullptr && fiber->addr_context != nullptr) {
__asan_destroy_fake_stack();
fiber->asan_fake_stack = nullptr;
}
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceFiberRunImpl(OrbisFiber* fiber, void* addr_context, u64 size_context,
u64 arg_on_run_to, u64* arg_on_return) {
EnsureFiberGlobalsInitialized();
if (!fiber) {
return ORBIS_FIBER_ERROR_NULL;
}
@ -274,51 +602,87 @@ s32 PS4_SYSV_ABI sceFiberRunImpl(OrbisFiber* fiber, void* addr_context, u64 size
return ORBIS_FIBER_ERROR_PERMISSION;
}
const bool attach_context = (addr_context != nullptr || size_context != 0);
if (attach_context) {
if (size_context != 0 && size_context < ORBIS_FIBER_CONTEXT_MINIMUM_SIZE) {
return ORBIS_FIBER_ERROR_RANGE;
}
if (!addr_context || size_context == 0 || (size_context & 15)) {
return ORBIS_FIBER_ERROR_INVALID;
}
if (fiber->addr_context != nullptr) {
return ORBIS_FIBER_ERROR_INVALID;
}
}
if (!TryTransitionFiberState(fiber, FiberState::Idle, FiberState::Run)) {
return ORBIS_FIBER_ERROR_STATE;
}
/* Caller wants to attach context and run. */
if (addr_context != nullptr || size_context != 0) {
if (attach_context) {
s32 res = _sceFiberAttachContext(fiber, addr_context, size_context);
if (res < 0) {
return res;
}
}
FiberState expected = FiberState::Idle;
if (!fiber->state.compare_exchange_strong(expected, FiberState::Run)) {
return ORBIS_FIBER_ERROR_STATE;
}
fiber->owner_thread = PthreadSelf();
OrbisFiberContext ctx{};
ctx.current_fiber = fiber;
ctx.prev_fiber = nullptr;
ctx.arg_on_run_to = 0;
ctx.arg_on_return = 0;
ctx.return_val = 0;
ctx.owner_thread = fiber->owner_thread;
ctx.asan_fake_stack = nullptr;
ctx.reserved0 = 0;
ctx.reserved1 = 0;
ctx.reserved2 = 0xffffffffu;
ctx.reserved3 = 0xffffffffu;
tcb->tcb_fiber = &ctx;
if (RazorEnabled()) {
RazorCpuFiberSwitch(0, static_cast<u32>(reinterpret_cast<uintptr_t>(fiber)), 2);
}
bool asan_switch = false;
if (AsanEnabled() && fiber->addr_context != nullptr) {
__sanitizer_start_switch_fiber(&ctx.asan_fake_stack, fiber->addr_context,
fiber->size_context);
asan_switch = true;
}
s32 jmp = _sceFiberSetJmp(&ctx);
if (!jmp) {
if (fiber->addr_context) {
_sceFiberSwitchToFiber(fiber, arg_on_run_to, &ctx);
_sceFiberSwitchToFiber(fiber, arg_on_run_to, &ctx, asan_switch ? 1 : 0);
__builtin_trap();
}
OrbisFiberData data{};
data.entry = fiber->entry;
data.arg_on_initialize = fiber->arg_on_initialize;
data.entry = DecodeEntry(fiber);
data.arg_on_initialize = DecodeArgOnInitialize(fiber);
data.arg_on_run_to = arg_on_run_to;
data.stack_addr = reinterpret_cast<void*>(ctx.rsp & ~15);
data.stack_addr = reinterpret_cast<void*>(ctx.jmp.rsp & ~15);
data.state = nullptr;
if (fiber->flags & FiberFlags::SetFpuRegs) {
data.fpucw = 0x037f;
data.mxcsr = 0x9fc0;
_sceFiberSwitchEntry(&data, true);
} else {
_sceFiberSwitchEntry(&data, false);
}
data.asan_fake_stack = nullptr;
_sceFiberSwitchEntry(&data, (fiber->flags & FiberFlags::SetFpuRegs) != 0);
}
if (asan_switch) {
__sanitizer_finish_switch_fiber(ctx.asan_fake_stack, nullptr, nullptr);
}
OrbisFiber* cur_fiber = ctx.current_fiber;
ctx.current_fiber = nullptr;
cur_fiber->state = FiberState::Idle;
if (RazorEnabled()) {
RazorCpuFiberSwitch(static_cast<u32>(reinterpret_cast<uintptr_t>(cur_fiber)), 0, 3);
}
StoreFiberState(cur_fiber, FiberState::Idle);
if (ctx.return_val != 0) {
/* Fiber entry returned! This should never happen. */
@ -335,6 +699,7 @@ s32 PS4_SYSV_ABI sceFiberRunImpl(OrbisFiber* fiber, void* addr_context, u64 size
s32 PS4_SYSV_ABI sceFiberSwitchImpl(OrbisFiber* fiber, void* addr_context, u64 size_context,
u64 arg_on_run_to, u64* arg_on_run) {
EnsureFiberGlobalsInitialized();
if (!fiber) {
return ORBIS_FIBER_ERROR_NULL;
}
@ -350,37 +715,73 @@ s32 PS4_SYSV_ABI sceFiberSwitchImpl(OrbisFiber* fiber, void* addr_context, u64 s
return ORBIS_FIBER_ERROR_PERMISSION;
}
const bool attach_context = (addr_context != nullptr || size_context != 0);
if (attach_context) {
if (size_context != 0 && size_context < ORBIS_FIBER_CONTEXT_MINIMUM_SIZE) {
return ORBIS_FIBER_ERROR_RANGE;
}
if (!addr_context || size_context == 0 || (size_context & 15)) {
return ORBIS_FIBER_ERROR_INVALID;
}
if (fiber->addr_context != nullptr) {
return ORBIS_FIBER_ERROR_INVALID;
}
}
if (!TryTransitionFiberState(fiber, FiberState::Idle, FiberState::Run)) {
return ORBIS_FIBER_ERROR_STATE;
}
/* Caller wants to attach context and switch. */
if (addr_context != nullptr || size_context != 0) {
if (attach_context) {
s32 res = _sceFiberAttachContext(fiber, addr_context, size_context);
if (res < 0) {
return res;
}
}
FiberState expected = FiberState::Idle;
if (!fiber->state.compare_exchange_strong(expected, FiberState::Run)) {
return ORBIS_FIBER_ERROR_STATE;
}
fiber->owner_thread = g_ctx->owner_thread;
OrbisFiber* cur_fiber = g_ctx->current_fiber;
if (cur_fiber->addr_context == nullptr) {
_sceFiberSwitch(cur_fiber, fiber, arg_on_run_to, g_ctx);
u64 asan_cookie = 0;
if (AsanEnabled() && fiber->addr_context != nullptr) {
__sanitizer_start_switch_fiber(&cur_fiber->asan_fake_stack, fiber->addr_context,
fiber->size_context);
asan_cookie = 1;
}
_sceFiberSwitch(cur_fiber, fiber, arg_on_run_to, g_ctx, asan_cookie);
__builtin_trap();
}
if (AsanEnabled()) {
void* stack_addr = nullptr;
size_t stack_size = 0;
if (fiber->addr_context == nullptr) {
GetThreadStack(&stack_addr, &stack_size);
} else {
stack_addr = fiber->addr_context;
stack_size = fiber->size_context;
}
__sanitizer_start_switch_fiber(&cur_fiber->asan_fake_stack, stack_addr, stack_size);
}
OrbisFiberContext ctx{};
s32 jmp = _sceFiberSetJmp(&ctx);
if (!jmp) {
cur_fiber->context = &ctx;
_sceFiberCheckStackOverflow(g_ctx);
_sceFiberSwitch(cur_fiber, fiber, arg_on_run_to, g_ctx);
_sceFiberSwitch(cur_fiber, fiber, arg_on_run_to, g_ctx, AsanEnabled() ? 1 : 0);
__builtin_trap();
}
if (AsanEnabled()) {
__sanitizer_finish_switch_fiber(cur_fiber->asan_fake_stack, nullptr, nullptr);
}
g_ctx = GetFiberContext();
if (g_ctx->prev_fiber) {
g_ctx->prev_fiber->state = FiberState::Idle;
StoreFiberState(g_ctx->prev_fiber, FiberState::Idle);
g_ctx->prev_fiber = nullptr;
}
@ -413,12 +814,22 @@ s32 PS4_SYSV_ABI sceFiberReturnToThread(u64 arg_on_return, u64* arg_on_run) {
OrbisFiber* cur_fiber = g_ctx->current_fiber;
if (cur_fiber->addr_context) {
if (AsanEnabled()) {
void* stack_addr = nullptr;
size_t stack_size = 0;
GetThreadStack(&stack_addr, &stack_size);
__sanitizer_start_switch_fiber(&cur_fiber->asan_fake_stack, stack_addr, stack_size);
}
OrbisFiberContext ctx{};
s32 jmp = _sceFiberSetJmp(&ctx);
if (jmp) {
if (AsanEnabled()) {
__sanitizer_finish_switch_fiber(cur_fiber->asan_fake_stack, nullptr, nullptr);
}
g_ctx = GetFiberContext();
if (g_ctx->prev_fiber) {
g_ctx->prev_fiber->state = FiberState::Idle;
StoreFiberState(g_ctx->prev_fiber, FiberState::Idle);
g_ctx->prev_fiber = nullptr;
}
if (arg_on_run) {
@ -449,11 +860,11 @@ s32 PS4_SYSV_ABI sceFiberGetInfo(OrbisFiber* fiber, OrbisFiberInfo* fiber_info)
return ORBIS_FIBER_ERROR_INVALID;
}
fiber_info->entry = fiber->entry;
fiber_info->arg_on_initialize = fiber->arg_on_initialize;
fiber_info->entry = DecodeEntry(fiber);
fiber_info->arg_on_initialize = DecodeArgOnInitialize(fiber);
fiber_info->addr_context = fiber->addr_context;
fiber_info->size_context = fiber->size_context;
strncpy(fiber_info->name, fiber->name, ORBIS_FIBER_MAX_NAME_LENGTH);
DecodeFiberName(fiber, fiber_info->name, sizeof(fiber_info->name));
fiber_info->size_context_margin = -1;
if (fiber->flags & FiberFlags::ContextSizeCheck && fiber->addr_context != nullptr) {
@ -463,10 +874,8 @@ s32 PS4_SYSV_ABI sceFiberGetInfo(OrbisFiber* fiber, OrbisFiberInfo* fiber_info)
if (*stack_start == kFiberStackSignature) {
u64* stack_ptr = stack_start + 1;
while (stack_ptr < stack_end) {
if (*stack_ptr == kFiberStackSizeCheck) {
stack_ptr++;
}
while (stack_ptr < stack_end && *stack_ptr == kFiberStackSizeCheck) {
stack_ptr++;
}
stack_margin =
@ -502,6 +911,7 @@ s32 PS4_SYSV_ABI sceFiberStopContextSizeCheck() {
}
s32 PS4_SYSV_ABI sceFiberRename(OrbisFiber* fiber, const char* name) {
EnsureFiberGlobalsInitialized();
if (!fiber || !name) {
return ORBIS_FIBER_ERROR_NULL;
}
@ -512,7 +922,13 @@ s32 PS4_SYSV_ABI sceFiberRename(OrbisFiber* fiber, const char* name) {
return ORBIS_FIBER_ERROR_INVALID;
}
strncpy(fiber->name, name, ORBIS_FIBER_MAX_NAME_LENGTH);
if (RazorEnabled()) {
char old_name[ORBIS_FIBER_MAX_NAME_LENGTH + 1]{};
DecodeFiberName(fiber, old_name, sizeof(old_name));
RazorCpuFiberLogNameChange(fiber, old_name);
}
EncodeFiberName(fiber, name);
return ORBIS_OK;
}
@ -526,7 +942,7 @@ s32 PS4_SYSV_ABI sceFiberGetThreadFramePointerAddress(u64* addr_frame_pointer) {
return ORBIS_FIBER_ERROR_PERMISSION;
}
*addr_frame_pointer = g_ctx->rbp;
*addr_frame_pointer = g_ctx->jmp.rbp;
return ORBIS_OK;
}

View File

@ -7,6 +7,7 @@
#include "common/types.h"
#include <atomic>
#include <cstddef>
namespace Core::Loader {
class SymbolsResolver;
@ -33,18 +34,40 @@ enum FiberFlags : u32 {
struct OrbisFiber;
struct OrbisFiberContext {
struct {
u64 rax, rcx, rdx, rbx, rsp, rbp, r8, r9, r10, r11, r12, r13, r14, r15;
u16 fpucw;
u32 mxcsr;
};
OrbisFiber* current_fiber;
OrbisFiber* prev_fiber;
u64 arg_on_run_to;
u64 arg_on_return;
u64 return_val;
struct OrbisFiberJmpBuf {
u64 rsp; // 0x00
u64 rbp; // 0x08
u64 ret_addr; // 0x10
u64 rbx; // 0x18
u64 r12; // 0x20
u64 r13; // 0x28
u64 r14; // 0x30
u64 r15; // 0x38
u16 fpucw; // 0x40
u16 pad0; // 0x42
u32 mxcsr; // 0x44
};
static_assert(sizeof(OrbisFiberJmpBuf) == 0x48);
struct OrbisFiberContext {
OrbisFiberJmpBuf jmp; // 0x00
OrbisFiber* current_fiber; // 0x48
OrbisFiber* prev_fiber; // 0x50
u64 arg_on_run_to; // 0x58
u64 arg_on_return; // 0x60
u64 return_val; // 0x68
u64 owner_thread; // 0x70
void* asan_fake_stack; // 0x78
u32 reserved0; // 0x80
u32 reserved1; // 0x84
u32 reserved2; // 0x88
u32 reserved3; // 0x8c
};
static_assert(sizeof(OrbisFiberContext) == 0x90);
static_assert(offsetof(OrbisFiberContext, current_fiber) == 0x48);
static_assert(offsetof(OrbisFiberContext, arg_on_run_to) == 0x58);
static_assert(offsetof(OrbisFiberContext, owner_thread) == 0x70);
static_assert(offsetof(OrbisFiberContext, asan_fake_stack) == 0x78);
struct OrbisFiberData {
OrbisFiberEntry entry;
@ -52,28 +75,36 @@ struct OrbisFiberData {
u64 arg_on_run_to;
void* stack_addr;
u32* state;
u16 fpucw;
s8 pad[2];
u32 mxcsr;
void* asan_fake_stack;
};
static_assert(sizeof(OrbisFiberData) == 0x30);
struct OrbisFiber {
u32 magic_start;
std::atomic<FiberState> state;
OrbisFiberEntry entry;
u64 arg_on_initialize;
void* addr_context;
u64 size_context;
char name[ORBIS_FIBER_MAX_NAME_LENGTH + 1];
OrbisFiberContext* context;
u32 flags;
void* context_start;
void* context_end;
u32 magic_end;
struct alignas(8) OrbisFiber {
u32 magic_start; // 0x00
u32 state; // 0x04
u64 entry_xor; // 0x08
u64 arg_on_initialize_xor; // 0x10
void* addr_context; // 0x18
u64 size_context; // 0x20
u8 name_xor[ORBIS_FIBER_MAX_NAME_LENGTH + 1]; // 0x28
OrbisFiberContext* context; // 0x48
u64 owner_thread; // 0x50
u32 flags; // 0x58
u32 razor_id_xor; // 0x5c
u64 switch_cookie; // 0x60
void* asan_fake_stack; // 0x68
u8 random_pad[0x78]; // 0x70
void* context_start; // 0xe8
void* context_end; // 0xf0
u32 reserved; // 0xf8
u32 magic_end; // 0xfc
};
static_assert(sizeof(OrbisFiber) <= 256);
static_assert(sizeof(OrbisFiber) == 0x100);
static_assert(offsetof(OrbisFiber, context_start) == 0xe8);
static_assert(offsetof(OrbisFiber, context_end) == 0xf0);
static_assert(offsetof(OrbisFiber, magic_end) == 0xfc);
struct OrbisFiberInfo {
struct alignas(8) OrbisFiberInfo {
u64 size;
OrbisFiberEntry entry;
u64 arg_on_initialize;
@ -85,10 +116,12 @@ struct OrbisFiberInfo {
};
static_assert(sizeof(OrbisFiberInfo) == 128);
struct OrbisFiberOptParam {
struct alignas(8) OrbisFiberOptParam {
u32 magic;
u32 option_flags;
u8 reserved[0x80 - 8];
};
static_assert(sizeof(OrbisFiberOptParam) <= 128);
static_assert(sizeof(OrbisFiberOptParam) == 0x80);
s32 PS4_SYSV_ABI sceFiberInitialize(OrbisFiber* fiber, const char* name, OrbisFiberEntry entry,
u64 arg_on_initialize, void* addr_context, u64 size_context,
@ -117,4 +150,4 @@ s32 PS4_SYSV_ABI sceFiberRename(OrbisFiber* fiber, const char* name);
s32 PS4_SYSV_ABI sceFiberGetThreadFramePointerAddress(u64* addr_frame_pointer);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Fiber
} // namespace Libraries::Fiber

View File

@ -3,75 +3,77 @@
.global _sceFiberSetJmp
_sceFiberSetJmp:
movq %rax, 0x0(%rdi)
movq %rsp, 0x00(%rdi)
movq %rbp, 0x08(%rdi)
movq (%rsp), %rdx
movq %rdx, 0x10(%rdi)
movq (%rsp), %rax
movq %rax, 0x10(%rdi)
movq %rcx, 0x08(%rdi)
movq %rbx, 0x18(%rdi)
movq %rsp, 0x20(%rdi)
movq %rbp, 0x28(%rdi)
movq %r12, 0x20(%rdi)
movq %r13, 0x28(%rdi)
movq %r14, 0x30(%rdi)
movq %r15, 0x38(%rdi)
movq %r8, 0x30(%rdi)
movq %r9, 0x38(%rdi)
movq %r10, 0x40(%rdi)
movq %r11, 0x48(%rdi)
movq %r12, 0x50(%rdi)
movq %r13, 0x58(%rdi)
movq %r14, 0x60(%rdi)
movq %r15, 0x68(%rdi)
fnstcw 0x70(%rdi)
stmxcsr 0x72(%rdi)
fnstcw 0x40(%rdi)
stmxcsr 0x44(%rdi)
xor %eax, %eax
ret
.global _sceFiberLongJmp
_sceFiberLongJmp:
# MXCSR = (MXCSR & 0x3f) ^ (ctx->mxcsr & ~0x3f)
stmxcsr -0x4(%rsp)
movl 0x72(%rdi), %eax
andl $0xffffffc0, %eax
movl -0x4(%rsp), %ecx
andl $0x3f, %ecx
xorl %eax, %ecx
movl %ecx, -0x4(%rsp)
ldmxcsr -0x4(%rsp)
mov %rdi, %r11
stmxcsr -4(%rsp)
mov 0x44(%r11), %eax
and $0xffffffc0, %eax
mov -4(%rsp), %ecx
and $0x3f, %ecx
xor %ecx, %eax
mov %eax, -4(%rsp)
ldmxcsr -4(%rsp)
movq 0x00(%rdi), %rax
movq 0x08(%rdi), %rcx
movq 0x10(%rdi), %rdx
movq 0x18(%rdi), %rbx
movq 0x20(%rdi), %rsp
movq 0x28(%rdi), %rbp
movq 0x00(%r11), %rsp
movq 0x08(%r11), %rbp
movq 0x10(%r11), %rcx
movq 0x18(%r11), %rbx
movq 0x20(%r11), %r12
movq 0x28(%r11), %r13
movq 0x30(%r11), %r14
movq 0x38(%r11), %r15
movq 0x30(%rdi), %r8
movq 0x38(%rdi), %r9
movq 0x40(%rdi), %r10
movq 0x48(%rdi), %r11
movq 0x50(%rdi), %r12
movq 0x58(%rdi), %r13
movq 0x60(%rdi), %r14
movq 0x68(%rdi), %r15
fldcw 0x40(%r11)
fldcw 0x70(%rdi)
# Make the jump and return 1
movq %rdx, 0x00(%rsp)
movq %rcx, 0x00(%rsp)
movl $0x1, %eax
ret
.global _sceFiberSwitchEntry
_sceFiberSwitchEntry:
mov %rdi, %r11
mov %esi, %r8d
# Set stack address to provided stack
movq 0x18(%r11), %rsp
xorl %ebp, %ebp
movq 0x28(%r11), %rdi # data->asan_fake_stack
test %rdi, %rdi
jz .skip_asan_finish
dec %rdi
xor %rsi, %rsi
xor %rdx, %rdx
push %r11
push %r11
call __sanitizer_finish_switch_fiber
pop %r11
pop %r11
.skip_asan_finish:
movq 0x08(%r11), %rdi # data->arg_on_initialize
movq 0x10(%r11), %rsi # data->arg_on_run_to
movq 0x20(%r11), %r10 # data->state
movq 0x00(%r11), %r11 # data->entry
# Set previous fiber state to Idle
test %r10, %r10
@ -79,17 +81,13 @@ _sceFiberSwitchEntry:
movl $2, (%r10)
.clear_regs:
test %esi, %esi
test %r8d, %r8d
jz .skip_fpu_regs
ldmxcsr 0x2c(%r11)
fldcw 0x28(%r11)
ldmxcsr kFiberMxcsrDefault(%rip)
fldcw kFiberFpucwDefault(%rip)
.skip_fpu_regs:
movq 0x08(%r11), %rdi # data->arg_on_initialize
movq 0x10(%r11), %rsi # data->arg_on_run_to
movq 0x00(%r11), %r11 # data->entry
xorl %eax, %eax
xorl %ebx, %ebx
xorl %ecx, %ecx
@ -119,3 +117,10 @@ _sceFiberSwitchEntry:
movl $1, %edi
call _sceFiberForceQuit
ret
.align 4
kFiberMxcsrDefault:
.long 0x00009fc0
.align 2
kFiberFpucwDefault:
.short 0x037f

View File

@ -186,6 +186,8 @@ s32 PS4_SYSV_ABI sceKernelMemoryPoolGetBlockStats(OrbisKernelMemoryPoolBlockStat
s32 PS4_SYSV_ABI sceKernelMunmap(void* addr, u64 len);
u32 PS4_SYSV_ABI sceKernelIsAddressSanitizerEnabled();
void RegisterMemory(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Kernel

View File

@ -352,6 +352,8 @@ using PthreadT = Pthread*;
extern thread_local Pthread* g_curthread;
PthreadT PS4_SYSV_ABI posix_pthread_self();
void RegisterMutex(Core::Loader::SymbolsResolver* sym);
void RegisterCond(Core::Loader::SymbolsResolver* sym);
void RegisterRwlock(Core::Loader::SymbolsResolver* sym);

View File

@ -13,5 +13,8 @@ class SymbolsResolver;
}
namespace Libraries::RazorCpu {
void PS4_SYSV_ABI sceRazorCpuDisableFiberUserMarkers();
s32 PS4_SYSV_ABI sceRazorCpuFiberLogNameChange();
s32 PS4_SYSV_ABI sceRazorCpuFiberSwitch();
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::RazorCpu
} // namespace Libraries::RazorCpu

View File

@ -10,6 +10,8 @@
namespace Libraries::Ulobjmgr {
s32 PS4_SYSV_ABI Func_046DBA8411A2365C(u64 arg0, s32 arg1, u32* arg2) {
LOG_DEBUG(Lib_Ulobjmgr, "(STUBBED) called arg0={:#x} arg1={} arg2={:#x}", arg0, arg1,
reinterpret_cast<uintptr_t>(arg2));
if (arg0 == 0 || arg1 == 0 || arg2 == nullptr) {
return POSIX_EINVAL;
}
@ -18,10 +20,12 @@ s32 PS4_SYSV_ABI Func_046DBA8411A2365C(u64 arg0, s32 arg1, u32* arg2) {
}
s32 PS4_SYSV_ABI Func_1D9F50D9CFB8054E() {
LOG_DEBUG(Lib_Ulobjmgr, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI Func_4A67FE7D435B94F7(u32 arg0) {
LOG_DEBUG(Lib_Ulobjmgr, "(STUBBED) called arg0={:#x}", arg0);
if (arg0 >= 0x4000) {
return POSIX_EINVAL;
}
@ -29,6 +33,7 @@ s32 PS4_SYSV_ABI Func_4A67FE7D435B94F7(u32 arg0) {
}
s32 PS4_SYSV_ABI Func_4B07893BBB77A649(u64 arg0) {
LOG_DEBUG(Lib_Ulobjmgr, "(STUBBED) called arg0={:#x}", arg0);
if (arg0 == 0) {
return POSIX_EINVAL;
}

View File

@ -10,5 +10,14 @@ class SymbolsResolver;
}
namespace Libraries::Ulobjmgr {
// NID: BG26hBGiNlw
s32 PS4_SYSV_ABI Func_046DBA8411A2365C(u64 arg0, s32 arg1, u32* arg2);
// NID: HZ9Q2c+4BU4
s32 PS4_SYSV_ABI Func_1D9F50D9CFB8054E();
// NID: Smf+fUNblPc
s32 PS4_SYSV_ABI Func_4A67FE7D435B94F7(u32 arg0);
// NID: SweJO7t3pkk
s32 PS4_SYSV_ABI Func_4B07893BBB77A649(u64 arg0);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Ulobjmgr
} // namespace Libraries::Ulobjmgr