OpenRakis / Cryogenic

An open-source reimplementation of Cryo's DUNE game (WIP)
Apache License 2.0
24 stars 1 forks source link

Ghidra Generated Code produces an Exception #13

Closed maximilien-noal closed 2 years ago

maximilien-noal commented 2 years ago

[21:00:36 ERR { SourceContext: "Spice86.UI.ViewModels.MainWindowViewModel" }] An error occurred during execution Spice86.Emulator.Errors.UnrecoverableException: Untested code reached, please tell us how to reach this state.Here is the message: Error: Function not registered at address 235C8 Here is the call stack: - entry_1000_0000_10000 expected to return to address at Cryogenic.Overrides.Overrides.spice86_generated_label_call_target_1000_C0AD_01C0AD(Int32 loadOffset) in /home/max/repos/Cryogenic/src/Cryogenic/Overrides/Generated/GeneratedCode7.cs:line 2550 at Spice86.Emulator.ReverseEngineer.CSharpOverrideHelper.<>cDisplayClass136_0.b__0() in /home/max/repos/Spice86/src/Spice86/Emulator/ReverseEngineer/CSharpOverrideHelper.cs:line 197 at Spice86.Emulator.ReverseEngineer.CSharpOverrideHelper.ExecuteEnsuringSameStack(UInt16 expectedReturnCs, UInt16 expectedReturnIp, Action action) in /home/max/repos/Spice86/src/Spice86/Emulator/ReverseEngineer/CSharpOverrideHelper.cs:line 246 at Spice86.Emulator.ReverseEngineer.CSharpOverrideHelper.NearCall(UInt16 expectedReturnCs, UInt16 expectedReturnIp, Func`2 function) in /home/max/repos/Spice86/src/Spice86/Emulator/ReverseEngineer/CSharpOverrideHelper.cs:line 195 at Cryogenic.Overrides.Overrides.spice86_generated_label_call_target_1000_E594_01E594(Int32 loadOffset) in /home/max/repos/Cryogenic/src/Cryogenic/Overrides/Generated/GeneratedCode9.cs:line 4514 at Spice86.Emulator.ReverseEngineer.CSharpOverrideHelper.<>cDisplayClass136_0.b__0() in /home/max/repos/Spice86/src/Spice86/Emulator/ReverseEngineer/CSharpOverrideHelper.cs:line 197 at Spice86.Emulator.ReverseEngineer.CSharpOverrideHelper.ExecuteEnsuringSameStack(UInt16 expectedReturnCs, UInt16 expectedReturnIp, Action action) in /home/max/repos/Spice86/src/Spice86/Emulator/ReverseEngineer/CSharpOverrideHelper.cs:line 246 at Spice86.Emulator.ReverseEngineer.CSharpOverrideHelper.NearCall(UInt16 expectedReturnCs, UInt16 expectedReturnIp, Func2 function) in /home/max/repos/Spice86/src/Spice86/Emulator/ReverseEngineer/CSharpOverrideHelper.cs:line 195 at Cryogenic.Overrides.Overrides.entry_1000_0000_10000(Int32 loadOffset) in /home/max/repos/Cryogenic/src/Cryogenic/Overrides/Generated/GeneratedCode.cs:line 1143 at Spice86.Emulator.Function.FunctionInformation.CallOverride() in /home/max/repos/Spice86/src/Spice86/Emulator/Function/FunctionInformation.cs:line 43 at Spice86.Emulator.Function.FunctionHandler.Call(CallType callType, UInt16 entrySegment, UInt16 entryOffset, Nullable1 expectedReturnSegment, Nullable`1 expectedReturnOffset, String name, Boolean recordReturn) in /home/max/repos/Spice86/src/Spice86/Emulator/Function/FunctionHandler.cs:line 52 at Spice86.Emulator.VM.Machine.Run() in /home/max/repos/Spice86/src/Spice86/Emulator/VM/Machine.cs:line 213 at Spice86.Emulator.ProgramExecutor.Run() in /home/max/repos/Spice86/src/Spice86/Emulator/ProgramExecutor.cs:line 51 at Spice86.UI.ViewModels.MainWindowViewModel.RunMachine() in /home/max/repos/Spice86/src/Spice86/UI/ViewModels/MainWindowViewModel.cs:line 291

Somewhere, the Java code that generated the fake ASM has a bug.

First step : Compare Spice86 + gdb and Cryogenic + gdb

A good GDB client for Linux : https://github.com/hugsy/gef

Or browser based: https://github.com/cs01/gdbgui/

Or inside VSCode: https://marketplace.visualstudio.com/items?itemName=webfreak.debug

Try to connect Ghidra to Spice86: https://wrongbaud.github.io/posts/ghidra-debugger/#debugging-the-rom

Also maybe use the -d option.

maximilien-noal commented 2 years ago

Code throwing the error :


public Action spice86_generated_label_call_target_1000_C0AD_01C0AD(int loadOffset) {
    entrydispatcher:
    if(loadOffset!=0){
      throw FailAsUntested("External goto not supported for this function.");
    }

    label_1000_C0AD_1C0AD:
    // MOV ES,word ptr [0xdbda] (1000_C0AD / 0x1C0AD)
    ES = UInt16[DS, 0xDBDA];
    // CALLF [0x38d5] (1000_C0B1 / 0x1C0B1)
    // Indirect call to [0x38d5], generating possible targets from emulator records
    uint targetAddress_1000_C0B1 = (uint)(UInt16[DS, 0x38D7] * 0x10 + UInt16[DS, 0x38D5] - cs1 * 0x10);
    switch(targetAddress_1000_C0B1) {
      default: throw FailAsUntested("Error: Function not registered at address " + ConvertUtils.ToHex32WithoutX(targetAddress_1000_C0B1));
        break;
    }
    // RET  (1000_C0B5 / 0x1C0B5)
    return NearRet();
  }
maximilien-noal commented 2 years ago

Fixed by @kevinferrare