Repository navigation
fix(libkernel): report guest unwind tables in sceKernelGetModuleInfoForUnwind - #904
Conversation
|
Thanks, the Silksong trace makes the cause clear, and the happy path looks right to me: the header comes from One point on exactness. Once an image has
Images without Also, after the last batch this branch conflicts with main in |
adriadam10
left a comment
There was a problem hiding this comment.
Agree with Dean's points above (throw instead of the empty answer once .ehmeta exists, only absptr/pcrel in ReadEncoded, throw on the 64-bit length, rebase on main for libkernel/CMakeLists.txt). Two additions:
core/libs/tests/GuestUnwindModuleInfo.cpp: once those paths throw, each needs a case (version != 1, unsupportedeh_frame_ptrencoding, 64-bit length record); today only the happy path and the host image are covered.Module.cpp:58:eh_frame_sizestops before the zero terminator (16 in the test). Please say which reference the libunwind consumer follows for this (with or without the terminator), in the PR description.
|
Test report from a second machine, in case it helps review. Setup: Windows 11, Intel i9-10850K, NVIDIA RTX 3080, WinLibs GCC 15.2.0. PPSA12544 v1.0.30021, relinked with Stack: Result: the title boots past the Team Cherry logos to the main menu (Start Game / Options / Extras) and holds 60 FPS (vsync) there for several minutes, from a warm or a cold shader cache (cold: one dip while pipelines compile around 30 s). Small visual artifact at the menu: a white block covers the first letter of "Options". I have not looked into which draw produces it. AI-assisted (Claude Code) testing and write-up. |
|
Thanks both. Addressed in 732a8b5 and 6eed05c:
Non-GPU tests pass (239). |
…orUnwind On Windows the call returned no eh_frame_hdr for every address, so a title's own libc (its libunwind) found no frame information and terminated on the first C++ exception thrown in guest code. PPSA12544 died that way after its intro cinematic: IL2CPP raised an AmbiguousMatchException that Unity catches and logs, and the runtime called terminate instead. For an address in a relinked guest image the call now returns the PT_GNU_EH_FRAME segment named by .ehmeta, the eh_frame it points to and its size, and the image as seg0; host images keep the empty answer. AI-assisted: yes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…InfoForUnwind Once an image has .ehmeta, an eh_frame_hdr version other than 1, an eh_frame_ptr encoding other than absptr or pcrel, a 64-bit record length, an eh_frame_ptr outside the image or a missing terminator now throw instead of returning the empty answer. The test queries a fixture DLL whose .ehmeta it can break, since the unwinder reads the same section. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tensions Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6eed05c to
7f4f887
Compare
|
Rebased onto current |
adriadam10
left a comment
There was a problem hiding this comment.
Checked the diff against Dean's and my earlier requests: throws once .ehmeta exists, only absptr/pcrel in ReadEncoded, 64-bit length throws, fixture tests for each, rebased, terminator choice recorded in TechnicalDebt. CI is green on this head and the Windows job runs guest_unwind_module_info (Passed). Windows-only code, Linux unchanged; merging.
|
Follow-up as promised: PPSA12544 now gets past the intro cinematic into gameplay with this change on Setup: Windows 11, Intel i9-10850K, NVIDIA RTX 3080, DualSense over SDL. Result: the game was played from the menu through the cinematic into gameplay. The window-title counter read 59.92 FPS during gameplay (5847 frames at 135 s, including boot and loading), and it played smoothly. The log has no exceptions and no skipped draws. The gameplay was played by hand and only the counter was measured, with no profiling. Written with AI assistance. |
What
On Windows,
sceKernelGetModuleInfoForUnwindreported no unwind tables for any address (eh_frame_hdr_addr,eh_frame_addrandeh_frame_sizeall 0). A title that ships its ownlibc.prxunwinds C++ exceptions with that libc's libunwind, which asks this call where a frame's FDEs are. With the empty answer it finds nothing, and the first C++ exception thrown in guest code ends interminate.PPSA12544 (Hollow Knight: Silksong, Unity/IL2CPP) died that way right after its intro cinematic:
The exception is a
System.Reflection.AmbiguousMatchExceptionthat Unity's invoke wrapper in the executable normally catches and logs; the search phase just never reached it.For an address in a relinked guest image, the call now returns:
eh_frame_hdr_addr: thePT_GNU_EH_FRAMEsegment the relinker names in.ehmeta(the same section the emulator's own libc unwinder reads);eh_frame_addr: decoded from the header'seh_frame_ptr;eh_frame_size: found by walking the records to the zero terminator, not counting the terminator;seg0: the whole image.Once an image has
.ehmeta, every other outcome throws instead of giving the empty answer:eh_frame_hdrversion other than 1;eh_frame_ptrencoding other than absptr or pcrel (datarel, funcrel, aligned and indirect throw, as do the omit encoding and unknown value formats);0xffffffff);eh_frame_ptroutside the image, or no terminator inside it.A
MEM_IMAGEwithout DOS/NT signatures also throws. Host images, which have no.ehmeta, keep the empty answer. Linux is unchanged.eh_frame_sizeand the terminator: I followed LLVM libunwind, which Sony's libunwind derives from.CFI_Parser::findFDEscans from the start of.eh_frameuntil either the given length runs out or it reads a zero length. So a size with or without the terminator finds the same FDEs. For aPT_GNU_EH_FRAMEfound throughdl_iterate_phdr, LLVM passesSIZE_MAXand relies on the terminator alone. What the console's kernel reports is not public, so TechnicalDebt records the choice.The
guest_unwind_module_infotest (Windows) uses a small fixture DLL whose.ehmetapoints at aneh_frame_hdrwith one CIE. It checks:eh_frame_ptrencodings 0x3b (datarel), 0x9b (indirect), 0x0f (unknown format) and 0xff (omit), and for a 64-bit length record;kernel32.The fixture is a separate DLL because the emulator's unwinder reads the same
.ehmeta: with a broken table in the test executable itself, the thrown exception could not be caught there. The test fails without the change.Tested
Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt.mdfiles or images added to the repository (attach them to this PR)🤖 Generated with Claude Code