Advertisement
fig02

Rebaccus VC Crash Explanation

Dec 7th, 2023 (edited)
311
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.72 KB | None | 0 0
  1. Here's the Ocarina of Time VC JP decompile of the same CPU function for reference. MM's VC is very similar.
  2. https://github.com/zeldaret/oot-vc/blob/master/src/virtual_console/cpu.c#L5326C5-L5353C6
  3.  
  4. The proposed fix I have in MMR's VC: In cpuExecuteCall, have cpuExecuteUpdate run before FindExternalCall marks a JAL as repointered (to prevent cpuExecuteUpdate's code cleanup from discovering this JAL prematurely).
  5.  
  6.  
  7. Emulated JALs do a few things, they'll write to the emulated CPU some status stuff, and then there will be the branch it takes which can self-modify.
  8.  
  9. Normal dynarec jump assembly behaviour while a JAL is interpreter:
  10. lis r5, N64Address@h
  11. ori r5, r5, N64Address@l
  12. stw r5, N64regs[RA](CPU) (this gets overwritten with the real return address by cpuExecuteCall)
  13. bl cpuExecuteCallWrapper (backs up dedicated PPCtoN64 registers before going into cpuExecuteCall)
  14.  
  15. After running cpuExecuteCall, when it's pointing to recompiled code:
  16. lis r5, ThisCallersReturnAddr@h
  17. ori r5, r5, ThisCallersReturnAddr@l
  18. stw r5, N64regs[RA](CPU)
  19. bl RecompiledCodeTarget
  20.  
  21.  
  22. cpuExecuteCall will tag the JAL in a list of external calls, then change the lis/ori r5 instructions to the caller's PPC return address. Then it calls cpuExecuteUpdate so some maintenance can happen and to fetch the target recompiled code address, to update the bl instruction.
  23.  
  24. In the unlucky timing situation, if cpuExecuteUpdate:
  25. think's it's time for code cleanup, and
  26. - the code cleanup function finds existing recompiled code for the target N64 function, and
  27. - it's a candidate for deletion (is old enough and no running code is going to return to it),
  28. every repointered external call with this N64 address gets reverted back to interpreter instructions as this recomp code is deleted.
  29. ...including any unfinished building ones, like the lis/ori cpuExecuteCall just worked on.
  30. cpuExecuteUpdate continues on to cpuMakeFunction (which rebuilds the target N64 code and returns a pointer for the bl instruction).
  31.  
  32. Thus turning it into:
  33. lis r5, N64Address@h
  34. oris r5, r5, N64Adress@l
  35. stw r5, N64regs[RA](CPU)
  36. bl RecompiledCodeTarget
  37.  
  38. ...Effectively creating a sort of code landmine. Upon a second run on this now broken JAL, the PPC return address is set wrong. Instead of coming back to the caller, the program counter gets sent to the N64 address... in Wii space. Most of the time it crashes immediately by executing a invalid load/store or illegal instruction. Sometimes it can get caught in an infinite loop which won't hit an exeception.
  39.  
  40. ...There was one crash reported where the broken return address sent the program counter to begin an IOS file seek. A bit concerning.
  41. Here's one of the crash screens shared in the bug report channel with the random crash error present
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement