Ghidra Generated Code produces an Exception
Closed this issue · 2 comments
[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.<>c__DisplayClass136_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.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.<>c__DisplayClass136_0.<NearCall>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.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.
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();
}
Fixed by @kevinferrare