You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Returnal (PPSA01285) on Windows: intermittent fault in a frame-pointer stack walk at app.exe+0x337aa9d (UE4 Main Thread, read of 0x8) #4239
Returnal (PPSA01285, Unreal Engine) on Windows, maind0ca839 and a672688, relinked from PPSA01285_elf, 0 absent imports: in 2 of 3 runs the title faults within the first seconds (the log has about 57 lines):
FATAL: unhandled exception 0xc0000005 on thread 'UE4 Main Thread'
rip app.exe+0x337aa9d read of 0x8 (rcx = 0)
The third run (60 s) did not fault.
What the instruction is (static, from the relinked image):app.exe+0x337aa40 is a stack-walk function. After clearing a 0x320-byte buffer it loads the return address [rbp+8], and then loops: store the address in a local array, rcx = [rcx] (next saved frame pointer), rax = [rcx+8] (that frame's return address), continue while the return address is non-zero, at most 100 entries. There is no check of rcx itself, so the loop only ends cleanly if the last frame in the chain has a zero return address and a valid frame pointer. If the chain ends in a null frame pointer, [rcx+8] reads address 8, which is the fault here (rcx = 0).
Hypothesis, not tested: on the console the bottom of a thread's frame chain is a valid frame with a zero return address; on this host the chain of the main thread continues into host start-up code or ends in 0, depending on the run. That would also explain why it is intermittent. I have not looked at how our thread start-up sets rbp, and I have not seen who calls the walker (the crash dump's chain shows frames up to app.exe+0x3339012).
Correction: the stack walk is the symptom, not the cause. Following the crash dump's frame chain in the relinked image (static, objdump; strings read from the image):
The message format right before that call is the UTF-16 string PS5 Out of Memory: with AvailablePhysical: %lld and UsedPhysical: %lld, filled by a statistics function (+0x33351e0). So in the runs that fault, Returnal's PS5 allocator ran into its out-of-memory path, raised LowLevelFatalError, and the title's attempt to dump the call stack then faulted in its own frame walk (null frame pointer). In the runs that did not fault, no out-of-memory error was raised.
What I have not established: which allocation fails and what our side returned for it. Our direct-memory pool is 13824 MiB (DIRECT_MEMORY_SIZE) and the flexible-memory budget is 448 MiB (FLEXIBLE_MEMORY_SIZE, Export.cpp; it prints [memory] flexible memory exhausted when it runs out, which none of my logs contain). I ran Returnal three more times with APS5_TRACE_MEMORY=1 (45 s each) and did not hit the fault again, so I have no trace of the failing call. The intermittence suggests the failure depends on timing or on the address-space layout of that run (not shown to be a race). Next step for whoever continues: keep running with APS5_TRACE_MEMORY=1 until the fault appears and read the last sceKernelAllocateDirectMemory/sceKernelMap* calls and their return codes before it.
The same class may explain other UE title stops that were attributed to the title's libc fatal path (libc.prx.guest.prx+0x141b0): Demon Slayer on #4238 shows LowLevelFatalError [File:Unknown]; I have not looked at whether it is an out-of-memory message.
Update from a 240 s run: Returnal (PPSA01285) faulted at the same place again (app.exe+0x337aa9d, UE4 Main Thread, read of 0x8) within the first seconds (57 log lines), so by now 3 of 5 plain runs on current main hit it; the other two ran without it. Nothing new on the cause; the out-of-memory reading above stands.
Does this still happen with the PlayGo chunk check from before #3238 (your one-line change on #3209)? The PS5 Out of Memory path is the one PPSA03001 and PPSA03490 reach since that merge.
@oneandonlydean Answer with numbers. I did not run the exact pre-#3238 one-line revert on Returnal; I ran the bound I propose in https://github.com/xXPBSXx/AnyPS5/tree/fix/playgo-bound-no-chunk-table (ids below 256 accepted without a chunk table, larger ids BAD_CHUNK_ID), 3 runs of 240 s each on mainffa198407 versus the same main plus that change (libraries hash-checked against the work directory's copy):
Plain main: 3 of 3 runs print PS5 Out of Memory (UsedPhysical about 9.28 GB, AvailablePhysical about 5.0 GB) and fault on UE4 Main Thread at app.exe+0x337aa9d (read of 0x8), after 57, 60 and 77 s of runtime.
With the change: 0 of 3 runs print that message or fault there. One run was still alive at 240 s; two ended after 136 and 146 s with abort() from compute shader ...: AGC graphics: storage image access to depth/stencil surface ... is not implemented (runtime_error, a different, later stop).
So for this title the stack-walk fault is reached only through the out-of-memory path on current main, and the bound removes that path in these runs. The Returnal dump has no sce_sys/playgo-chunk.dat (an observation; I have not shown that this is why the loop runs). Sifu's measurements are in #3209 (comment) (the 6 of 6 clean runs with the change and the Demon Slayer comparison, 3 of 3 failing without and 0 of 3 with the OOM message, go into the PR text for that branch). Not tested: the exact pre-#3238 check on Returnal, Linux.
#4491 is on main: without a PlayGo file only chunk 0 is valid. Does Returnal still print PS5 Out of Memory and fault at app.exe+0x337aa9d on current main? If not, this can close.
A second title with this fault, on Linux, and a core dump that confirms the hypothesis above: the frame chain runs past the guest thread's first frame into AnyPS5's thread start-up, whose saved frame pointer is garbage.
Title: LEGO Batman: Legacy of the Dark Knight (PPSA16833 v01.010.000). Build:main5d9dcc42d + #6694 + #6699 + the sceWebBrowserDialogOpenForPredeterminedContent hunk of #6447, plus input-only changes. Linux, RTX 4090. Four runs segfaulted at the same instruction, each right after a large burst of shader-cache loads or compiles (a new area streaming in); other sessions, one of them 26 minutes long, ended normally. So it's intermittent here too, which fits a walk that only crashes when the chain's garbage value isn't readable memory.
The faulting function (app.elf+0x3383eee) is the same kind of walker as yours: it starts from its own rbp, loads rcx = [rax+8] (the return address), stops when that is zero, stores at most 100 entries, and follows rax = [rax]. It never checks the frame pointer itself.
The chain at the fault (from the core, frame pointer → saved frame pointer, return address):
Frame
Saved rbp
Return address
0–5
on the guest thread's stack
app.elf (the walker and its callers)
6
on the guest thread's stack
libkernel.prx+0x95582, i.e. StartNativeThread right after its call *%r12 into the guest entry
7
0x21
libc.so.6+0xac93f (glibc's thread start)
Frame 7 is StartNativeThread's own frame; its saved rbp is whatever glibc's thread start left in the register (glibc doesn't keep frame pointers), here 0x21. The walker follows it and reads 0x29: SIGSEGV. Your Windows case (rcx = 0, read of 0x8) is the same chain ending in a different garbage value.
A possible fix: before StartNativeThread calls the guest entry (Linux and Windows paths, and presumably wherever the guest main thread is entered), point rbp at a terminating frame record {saved rbp = 0, return address = 0} on the guest stack. Both walkers stop on a zero return address, so the chain would end there as it does on the console. I haven't written or tested that yet.
Tested and written by Claude (AI assistant) on a contributor's machine.
Two merged changes now cover the reported path on current main:
fix(libScePlayGo): answer chunk ids from the package layout #4491 makes the PlayGo chunk set follow the package layout. Its description specifically includes Returnal among titles whose packages have no PlayGo files, while qualifying that the title observation alone did not prove PlayGo caused Returnal’s loop.
Could you rerun Returnal on a fresh build of current main and report whether it still prints PS5 Out of Memory or faults at app.exe+0x337aa9d? If it proceeds, that would establish the reported stop is addressed; if it reaches another failure, the new log would define the next issue.
Two fixes for this are on main now: #4491 (18c438b) for the out-of-memory path and #7123 (cb1d6e5), which ends guest thread frame chains at a zero record so the frame walker stops cleanly (this is the Linux core dump Tamalero posted above). Could you or Tamalero retest on current main and say whether the fault at app.exe+0x337aa9d / "PS5 Out of Memory" still appears? If it is gone I'll close this.
No reply to the retest request, so closing this. The out-of-memory path (#4491, 18c438b) and the frame-chain terminator that stops the walker cleanly (#7123, cb1d6e5) are both on main. If the fault at app.exe+0x337aa9d or "PS5 Out of Memory" still shows on current main, please open a new issue with the log.
Activity
xXPBSXx commentedon Oct 12, 2026
Correction: the stack walk is the symptom, not the cause. Following the crash dump's frame chain in the relinked image (static,
objdump; strings read from the image):app.exe+0x337aa40is Unreal'sStackWalkAndDump: it walks the frame chain and calls a symbolizer (+0x337a550) to fill a text buffer. It is reached from a fatal-error function (+0x3374dd0, frames fix(build): register relinker tests with CTest #2 and Expand native PS5 homebrew compatibility and regression coverage #3 of the dump), whose caller formats a message and then calls it. The fatal path contains the file name stringUnknown(the sameLowLevelFatalError [File:Unknown]as in the Demon Slayer dump on Demon Slayer (PPSA03490) on Windows: Unreal LowLevelFatalError into the title's libc fatal path (libc.prx.guest.prx+0x141b0) #4238).PS5 Out of Memory:withAvailablePhysical: %lldandUsedPhysical: %lld, filled by a statistics function (+0x33351e0). So in the runs that fault, Returnal's PS5 allocator ran into its out-of-memory path, raisedLowLevelFatalError, and the title's attempt to dump the call stack then faulted in its own frame walk (null frame pointer). In the runs that did not fault, no out-of-memory error was raised.What I have not established: which allocation fails and what our side returned for it. Our direct-memory pool is 13824 MiB (
DIRECT_MEMORY_SIZE) and the flexible-memory budget is 448 MiB (FLEXIBLE_MEMORY_SIZE,Export.cpp; it prints[memory] flexible memory exhaustedwhen it runs out, which none of my logs contain). I ran Returnal three more times withAPS5_TRACE_MEMORY=1(45 s each) and did not hit the fault again, so I have no trace of the failing call. The intermittence suggests the failure depends on timing or on the address-space layout of that run (not shown to be a race). Next step for whoever continues: keep running withAPS5_TRACE_MEMORY=1until the fault appears and read the lastsceKernelAllocateDirectMemory/sceKernelMap*calls and their return codes before it.The same class may explain other UE title stops that were attributed to the title's libc fatal path (
libc.prx.guest.prx+0x141b0): Demon Slayer on #4238 showsLowLevelFatalError [File:Unknown]; I have not looked at whether it is an out-of-memory message.AI-assisted (Claude Code).
xXPBSXx commentedon Oct 12, 2026
Update from a 240 s run: Returnal (PPSA01285) faulted at the same place again (
app.exe+0x337aa9d,UE4 Main Thread, read of 0x8) within the first seconds (57 log lines), so by now 3 of 5 plain runs on currentmainhit it; the other two ran without it. Nothing new on the cause; the out-of-memory reading above stands.AI-assisted (Claude Code).
oneandonlydean commentedon Oct 12, 2026
Does this still happen with the PlayGo chunk check from before #3238 (your one-line change on #3209)? The
PS5 Out of Memorypath is the one PPSA03001 and PPSA03490 reach since that merge.xXPBSXx commentedon Oct 12, 2026
@oneandonlydean Answer with numbers. I did not run the exact pre-#3238 one-line revert on Returnal; I ran the bound I propose in https://github.com/xXPBSXx/AnyPS5/tree/fix/playgo-bound-no-chunk-table (ids below 256 accepted without a chunk table, larger ids
BAD_CHUNK_ID), 3 runs of 240 s each onmainffa198407versus the samemainplus that change (libraries hash-checked against the work directory's copy):main: 3 of 3 runs printPS5 Out of Memory(UsedPhysicalabout 9.28 GB,AvailablePhysicalabout 5.0 GB) and fault onUE4 Main Threadatapp.exe+0x337aa9d(read of0x8), after 57, 60 and 77 s of runtime.abort()fromcompute shader ...: AGC graphics: storage image access to depth/stencil surface ... is not implemented(runtime_error, a different, later stop).So for this title the stack-walk fault is reached only through the out-of-memory path on current
main, and the bound removes that path in these runs. The Returnal dump has nosce_sys/playgo-chunk.dat(an observation; I have not shown that this is why the loop runs). Sifu's measurements are in #3209 (comment) (the 6 of 6 clean runs with the change and the Demon Slayer comparison, 3 of 3 failing without and 0 of 3 with the OOM message, go into the PR text for that branch). Not tested: the exact pre-#3238 check on Returnal, Linux.AI-assisted (Claude Code).
oneandonlydean commentedon Oct 14, 2026
#4491 is on main: without a PlayGo file only chunk 0 is valid. Does Returnal still print
PS5 Out of Memoryand fault atapp.exe+0x337aa9don current main? If not, this can close.Tamalero commentedon Oct 17, 2026
A second title with this fault, on Linux, and a core dump that confirms the hypothesis above: the frame chain runs past the guest thread's first frame into AnyPS5's thread start-up, whose saved frame pointer is garbage.
Title: LEGO Batman: Legacy of the Dark Knight (PPSA16833 v01.010.000). Build:
main5d9dcc42d+ #6694 + #6699 + thesceWebBrowserDialogOpenForPredeterminedContenthunk of #6447, plus input-only changes. Linux, RTX 4090. Four runs segfaulted at the same instruction, each right after a large burst of shader-cache loads or compiles (a new area streaming in); other sessions, one of them 26 minutes long, ended normally. So it's intermittent here too, which fits a walk that only crashes when the chain's garbage value isn't readable memory.The faulting function (
app.elf+0x3383eee) is the same kind of walker as yours: it starts from its ownrbp, loadsrcx = [rax+8](the return address), stops when that is zero, stores at most 100 entries, and followsrax = [rax]. It never checks the frame pointer itself.The chain at the fault (from the core, frame pointer → saved frame pointer, return address):
rbpapp.elf(the walker and its callers)libkernel.prx+0x95582, i.e.StartNativeThreadright after itscall *%r12into the guest entry0x21libc.so.6+0xac93f(glibc's thread start)Frame 7 is
StartNativeThread's own frame; its savedrbpis whatever glibc's thread start left in the register (glibc doesn't keep frame pointers), here0x21. The walker follows it and reads0x29: SIGSEGV. Your Windows case (rcx = 0, read of0x8) is the same chain ending in a different garbage value.A possible fix: before
StartNativeThreadcalls the guest entry (Linux and Windows paths, and presumably wherever the guest main thread is entered), pointrbpat a terminating frame record{saved rbp = 0, return address = 0}on the guest stack. Both walkers stop on a zero return address, so the chain would end there as it does on the console. I haven't written or tested that yet.Tested and written by Claude (AI assistant) on a contributor's machine.
MarcZX10 commentedon Oct 23, 2026
Two merged changes now cover the reported path on current
main:Could you rerun Returnal on a fresh build of current
mainand report whether it still printsPS5 Out of Memoryor faults atapp.exe+0x337aa9d? If it proceeds, that would establish the reported stop is addressed; if it reaches another failure, the new log would define the next issue.oneandonlydean commentedon Oct 26, 2026
Two fixes for this are on main now: #4491 (18c438b) for the out-of-memory path and #7123 (cb1d6e5), which ends guest thread frame chains at a zero record so the frame walker stops cleanly (this is the Linux core dump Tamalero posted above). Could you or Tamalero retest on current main and say whether the fault at app.exe+0x337aa9d / "PS5 Out of Memory" still appears? If it is gone I'll close this.
oneandonlydean commentedon Oct 29, 2026
No reply to the retest request, so closing this. The out-of-memory path (#4491, 18c438b) and the frame-chain terminator that stops the walker cleanly (#7123, cb1d6e5) are both on main. If the fault at app.exe+0x337aa9d or "PS5 Out of Memory" still shows on current main, please open a new issue with the log.