refactor(fiber): keep the assembly entry points out of NID patching with _nid_no_patch

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
This commit is contained in:
Dean Galvin 2026-09-28 19:46:38 +13:00
parent ba9201874f
commit 41fb65761f
1 changed files with 26 additions and 28 deletions

View File

@ -92,14 +92,14 @@ static void CompletePendingSuspend() {
#ifdef _WIN32
extern "C" void Aps5FiberSwitchStack(void** save, void* load);
extern "C" void Aps5FiberTrampoline();
extern "C" void Aps5FiberSwitchStack_nid_no_patch(void** save, void* load);
extern "C" void Aps5FiberTrampoline_nid_no_patch();
asm(R"(
.text
.globl Aps5FiberSwitchStack
.def Aps5FiberSwitchStack; .scl 2; .type 32; .endef
Aps5FiberSwitchStack:
.globl Aps5FiberSwitchStack_nid_no_patch
.def Aps5FiberSwitchStack_nid_no_patch; .scl 2; .type 32; .endef
Aps5FiberSwitchStack_nid_no_patch:
push %rbp
push %rbx
push %rdi
@ -146,13 +146,13 @@ Aps5FiberSwitchStack:
pop %rbp
ret
.globl Aps5FiberTrampoline
.def Aps5FiberTrampoline; .scl 2; .type 32; .endef
Aps5FiberTrampoline:
.globl Aps5FiberTrampoline_nid_no_patch
.def Aps5FiberTrampoline_nid_no_patch; .scl 2; .type 32; .endef
Aps5FiberTrampoline_nid_no_patch:
mov %r12, %rcx
and $-16, %rsp
sub $32, %rsp
call Aps5FiberMain
call Aps5FiberMain_nid_no_patch
ud2
)");
@ -164,7 +164,7 @@ struct InitialFrame {
std::uint64_t r15, r14, r13, r12, rsi, rdi, rbx, rbp;
std::uint64_t returnAddress;
};
static_assert(sizeof(InitialFrame) == 0xa8 + 8 * 8 + 8, "initial fiber frame must match Aps5FiberSwitchStack");
static_assert(sizeof(InitialFrame) == 0xa8 + 8 * 8 + 8, "initial fiber frame must match Aps5FiberSwitchStack_nid_no_patch");
static StackBounds CurrentBounds() {
auto* tib = reinterpret_cast<NT_TIB*>(NtCurrentTeb());
@ -182,15 +182,14 @@ static void SetBounds(const StackBounds& bounds) {
#else
extern "C" __attribute__((visibility("hidden"))) void Aps5FiberSwitchStack(void** save, void* load);
extern "C" __attribute__((visibility("hidden"))) void Aps5FiberTrampoline();
extern "C" void Aps5FiberSwitchStack_nid_no_patch(void** save, void* load);
extern "C" void Aps5FiberTrampoline_nid_no_patch();
asm(R"(
.text
.globl Aps5FiberSwitchStack
.hidden Aps5FiberSwitchStack
.type Aps5FiberSwitchStack, @function
Aps5FiberSwitchStack:
.globl Aps5FiberSwitchStack_nid_no_patch
.type Aps5FiberSwitchStack_nid_no_patch, @function
Aps5FiberSwitchStack_nid_no_patch:
push %rbp
push %rbx
push %r12
@ -212,17 +211,16 @@ Aps5FiberSwitchStack:
pop %rbx
pop %rbp
ret
.size Aps5FiberSwitchStack, .-Aps5FiberSwitchStack
.size Aps5FiberSwitchStack_nid_no_patch, .-Aps5FiberSwitchStack_nid_no_patch
.globl Aps5FiberTrampoline
.hidden Aps5FiberTrampoline
.type Aps5FiberTrampoline, @function
Aps5FiberTrampoline:
.globl Aps5FiberTrampoline_nid_no_patch
.type Aps5FiberTrampoline_nid_no_patch, @function
Aps5FiberTrampoline_nid_no_patch:
mov %r12, %rdi
and $-16, %rsp
call Aps5FiberMain
call Aps5FiberMain_nid_no_patch
ud2
.size Aps5FiberTrampoline, .-Aps5FiberTrampoline
.size Aps5FiberTrampoline_nid_no_patch, .-Aps5FiberTrampoline_nid_no_patch
)");
struct InitialFrame {
@ -232,7 +230,7 @@ struct InitialFrame {
std::uint64_t r15, r14, r13, r12, rbx, rbp;
std::uint64_t returnAddress;
};
static_assert(sizeof(InitialFrame) == 8 + 6 * 8 + 8, "initial fiber frame must match Aps5FiberSwitchStack");
static_assert(sizeof(InitialFrame) == 8 + 6 * 8 + 8, "initial fiber frame must match Aps5FiberSwitchStack_nid_no_patch");
static StackBounds CurrentBounds() {
return {};
@ -251,7 +249,7 @@ static Fiber* AsFiber(FiberObject* object) {
return fiber && fiber->magic == FIBER_MAGIC ? fiber : nullptr;
}
extern "C" [[noreturn]] __attribute__((visibility("hidden"))) void Aps5FiberMain(Fiber* fiber) {
extern "C" [[noreturn]] void Aps5FiberMain_nid_no_patch(Fiber* fiber) {
CompletePendingSuspend();
fiber->entry(fiber->argOnInitialize, ThreadState().transfer);
throw std::runtime_error(std::string("sceFiber: entry function of fiber '") + fiber->name + "' returned");
@ -266,7 +264,7 @@ static void PrepareInitialStack(Fiber* fiber) {
asm volatile("fnstcw %0" : "=m"(control));
frame->fpuControl = control;
frame->r12 = reinterpret_cast<std::uint64_t>(fiber);
frame->returnAddress = reinterpret_cast<std::uint64_t>(&Aps5FiberTrampoline);
frame->returnAddress = reinterpret_cast<std::uint64_t>(&Aps5FiberTrampoline_nid_no_patch);
fiber->savedStack = frame;
}
@ -298,7 +296,7 @@ static void Resume(Fiber* target, void** save, std::uint64_t argOnRun) {
ThreadState().current = target;
ThreadState().transfer = argOnRun;
SetBounds(FiberBounds(target));
Aps5FiberSwitchStack(save, target->savedStack);
Aps5FiberSwitchStack_nid_no_patch(save, target->savedStack);
}
extern "C" {
@ -380,7 +378,7 @@ int32_t APS5_VABI sceFiberReturnToThread(uint64_t arg_on_return, uint64_t* arg_o
ThreadState().current = nullptr;
ThreadState().transfer = arg_on_return;
SetBounds(ThreadState().threadBounds);
Aps5FiberSwitchStack(&self->savedStack, ThreadState().threadStack);
Aps5FiberSwitchStack_nid_no_patch(&self->savedStack, ThreadState().threadStack);
CompletePendingSuspend();
if (arg_on_run) *arg_on_run = ThreadState().transfer;
return SCE_OK;