melonDS-emu / melonDS

DS emulator, sorta
https://melonds.kuribo64.net
GNU General Public License v3.0
2.98k stars 493 forks source link

TESTING NEEDED: allow build with ENABLE_JIT=ON on OpenBSD Targets #2050

Open Izder456 opened 1 month ago

Izder456 commented 1 month ago

I take MAINTAINER for the melonDS port on OpenBSD, and I am trying to get JIT to work on melonDS 0.9.5 on amd64 openbsd targets.

I was able to find the needed context register for JIT to work on OpenBSD. It seems to pass compile stages, but I came across a runtime crash error.

with JIT on, max JIT block size to 32, both Branch & Literal Optimizations, as well as Fast memory OFF, I get the following crash:

melonDS 0.9.5
https://melonds.kuribo64.net/
IPC sharedmem doesn't exist. creating
IPC: instance ID 0
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-izder456'
Audio output frequency: 48000 Hz
Created a OpenGL context
GL_VENDOR: Intel
GL_RENDERER: Mesa Intel(R) HD Graphics 5500 (BDW GT2)
GL_VERSION: 4.6 (Core Profile) Mesa 23.3.6
GL_SHADING_LANGUAGE_VERSION: 4.60
MP sharedmem doesn't exist. creating
MP comm init OK, instance ID 0
ARM9 BIOS loaded
ARM7 BIOS loaded
Resetting JIT block cache...
done resetting jit mem
done resetting jit mem
MAC: 00:19:FD:B2:79:76
FW: WIFI CRC16 = GOOD
FW: AP1 CRC16 = GOOD
FW: AP2 CRC16 = GOOD
FW: AP3 CRC16 = GOOD
FW: USER0 CRC16 = GOOD
FW: USER1 CRC16 = GOOD
Game code: ADME
ROM entry: 02000000 00000005
Cart ID: 00001FC2
Re-encrypting cart secure area
this is a JIT bug �]$������THx
zsh: abort      melonDS

Testing with a REAL dump of Animal Crossing: Wild World

with sha256 checksum: SHA256 (ACWW.nds) = 9788570e90bbbb226c47e1f52c8882559129003695f8d91279c2158649cb7f06

Low level stuff like this is a bit over my head, so any pointers would be appreciated.

Thanks.

RSDuck commented 1 month ago

It looks like the JIT segfaults unintentionally. Are there maybe differences in the calling convention?

Also %sx seems to be a typo from me, so it ends up displaying the pc as a string.

RSDuck commented 1 month ago

Can you run a debugger and print out the JIT code where the fault happens? With gdb it would be something like

break abort

wait for the abort to happen

backtrace
frame (the frame named CodeMemory seen in backtrace)
x/50i $pc-30

The pc offset and instruction is to be experimented.

Izder456 commented 1 month ago

Can you run a debugger and print out the JIT code where the fault happens? With gdb it would be something like

[yadda yadda]

I am new to debugging as a whole. I built this with Clang version 16.0.6 (default compiler on -CURRENT). I have the binary with debugging symbols built. But- I don't think gdb is what I need here. would lldb suffice? If so, how would I set the breakpoint with lldb?

Figured it out: b abort is what i needed

The pc offset and instruction is to be experimented.

output from lldb when running ACWW.nds (the same ROM as before)

ARM9 BIOS loaded
ARM7 BIOS loaded
Resetting JIT block cache...
done resetting jit mem
done resetting jit mem
MAC: 00:19:FD:B6:89:B6
FW: WIFI CRC16 = GOOD
FW: AP1 CRC16 = GOOD
FW: AP2 CRC16 = GOOD
FW: AP3 CRC16 = GOOD
FW: USER0 CRC16 = GOOD
FW: USER1 CRC16 = GOOD
Game code: ADME
ROM entry: 02000000 00000005
Cart ID: 00001FC2
Re-encrypting cart secure area
Process 34455 stopped
* thread #1, stop reason = signal SIGSEGV
    frame #0: 0x00000096361bc854 libQt5Widgets.so.4.1
->  0x96361bc854: jmpq   *0x3b866(%rip)
    0x96361bc85a: nopw   (%rax,%rax)
    0x96361bc860: endbr64
    0x96361bc864: jmpq   *0x3b85e(%rip)
RSDuck commented 1 month ago

did you go to the frame of the JIT code?

Izder456 commented 1 month ago

did you go to the frame of the JIT code?

I am going to be honest here. I have no idea what I am doing.

Izder456 commented 1 month ago

well this is how i got to it:

~ lldb melonDS
(lldb) target create "melonDS"
Current executable set to '/usr/local/bin/melonDS' (x86_64).
(lldb) b abort
Breakpoint 1: 16 locations.
(lldb) r
Process 77596 launched: '/usr/local/bin/melonDS' (x86_64)
2 locations added to breakpoint 1
melonDS 0.9.5
https://melonds.kuribo64.net/
IPC sharedmem doesn't exist. creating
IPC: instance ID 0
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-izder456'
Audio output frequency: 48000 Hz
Created a OpenGL context
GL_VENDOR: Intel
GL_RENDERER: Mesa Intel(R) HD Graphics 5500 (BDW GT2)
GL_VERSION: 4.6 (Core Profile) Mesa 23.3.6
GL_SHADING_LANGUAGE_VERSION: 4.60
MP sharedmem doesn't exist. creating
MP comm init OK, instance ID 0
Process 77596 stopped
* thread #1, stop reason = breakpoint 1.1
    frame #0: 0x000004bda0a39e70 libQt5Widgets.so.4.1`QWidgetAnimator::abort(QWidget*)
libQt5Widgets.so.4.1`QWidgetAnimator::abort:
->  0x4bda0a39e70 <+0>:  endbr64
    0x4bda0a39e74 <+4>:  movq   0x464c1d(%rip), %r11      ; __retguard_1208
    0x4bda0a39e7b <+11>: xorq   (%rsp), %r11
    0x4bda0a39e7f <+15>: pushq  %rbp
(lldb) c
Process 77596 resuming
Process 77596 stopped
* thread #1, stop reason = breakpoint 1.1
    frame #0: 0x000004bda0a39e70 libQt5Widgets.so.4.1`QWidgetAnimator::abort(QWidget*)
libQt5Widgets.so.4.1`QWidgetAnimator::abort:
->  0x4bda0a39e70 <+0>:  endbr64
    0x4bda0a39e74 <+4>:  movq   0x464c1d(%rip), %r11      ; __retguard_1208
    0x4bda0a39e7b <+11>: xorq   (%rsp), %r11
    0x4bda0a39e7f <+15>: pushq  %rbp
(lldb) c
Process 77596 resuming
Process 77596 stopped
* thread #1, stop reason = breakpoint 1.1
    frame #0: 0x000004bda0a39e70 libQt5Widgets.so.4.1`QWidgetAnimator::abort(QWidget*)
libQt5Widgets.so.4.1`QWidgetAnimator::abort:
->  0x4bda0a39e70 <+0>:  endbr64
    0x4bda0a39e74 <+4>:  movq   0x464c1d(%rip), %r11      ; __retguard_1208
    0x4bda0a39e7b <+11>: xorq   (%rsp), %r11
    0x4bda0a39e7f <+15>: pushq  %rbp
(lldb) c
Process 77596 resuming
ARM9 BIOS loaded
ARM7 BIOS loaded
Resetting JIT block cache...
done resetting jit mem
done resetting jit mem
MAC: 00:19:FD:B2:79:76
FW: WIFI CRC16 = GOOD
FW: AP1 CRC16 = GOOD
FW: AP2 CRC16 = GOOD
FW: AP3 CRC16 = GOOD
FW: USER0 CRC16 = GOOD
FW: USER1 CRC16 = GOOD
Game code: ADME
ROM entry: 02000000 00000005
Cart ID: 00001FC2
Re-encrypting cart secure area
Process 77596 stopped
* thread #1, stop reason = signal SIGSEGV
    frame #0: 0x000004be1a5d3bab libc.so.100.1`_thread_sys_poll at -:2
warning: This version of LLDB has no plugin for the language "assembler". Inspection of frame variables will be limited.
(lldb) frame select
frame #0: 0x000004be1a5d3bab libc.so.100.1`_thread_sys_poll at -:2
(lldb) n
Process 77596 stopped
* thread #1, stop reason = signal SIGSEGV
    frame #0: 0x000004be1a5d3bab libc.so.100.1`_thread_sys_poll at -:2
(lldb) n
Process 77596 stopped
* thread #1, stop reason = signal SIGSEGV
    frame #0: 0x000004be1a5d3bab libc.so.100.1`_thread_sys_poll at -:2
(lldb) bt
* thread #1, stop reason = signal SIGSEGV
  * frame #0: 0x000004be1a5d3bab libc.so.100.1`_thread_sys_poll at -:2
    frame #1: 0x000004be1a58b9d2 libc.so.100.1`_libc_poll_cancel(fds=0x000004bdfb7c81d0, nfds=2, timeout=737) at w_poll.c:27:8
    frame #2: 0x000004be4a88142e libglib-2.0.so.4201.12`g_main_context_iterate_unlocked + 510
    frame #3: 0x000004be4a88153b libglib-2.0.so.4201.12`g_main_context_iteration + 123
    frame #4: 0x000004be250c6a74 libQt5Core.so.6.0`QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 228
    frame #5: 0x000004bdd9028448 libQt5XcbQpa.so.1.0`QXcbGlibEventDispatcher::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 56
    frame #6: 0x000004be24fe74c7 libQt5Core.so.6.0`QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 119
    frame #7: 0x000004be24fe770e libQt5Core.so.6.0`QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) + 542
    frame #8: 0x000004be24fecce0 libQt5Core.so.6.0`QCoreApplication::exec() + 400
    frame #9: 0x000004be07cfca58 libQt5Gui.so.4.2`QGuiApplication::exec() + 40
    frame #10: 0x000004bda08b960b libQt5Widgets.so.4.1`QApplication::exec() + 27
    frame #11: 0x000004bb4f47db6e melonDS`main at main.cpp:3380:15
    frame #12: 0x000004bb4f46199b melonDS`__start + 299

seems my lldb version is limited in frame debugging.

hopefully this is helpful.

RSDuck commented 1 month ago

looks like it also set a breakpoint to member functions called abort. Also the backtrace in the end is the wrong thread?

Izder456 commented 1 month ago

looks like it also set a breakpoint to member functions called abort.

sorry, here:

~ lldb melonDS
(lldb) target create "melonDS"
Current executable set to '/usr/local/bin/melonDS' (x86_64).
(lldb) process handle --stop true --pass true --notify true SIGSEGV
NAME         PASS     STOP     NOTIFY
===========  =======  =======  =======
SIGSEGV      true     true     true
(lldb) process handle --stop true --pass false --notify true SIGSEGV
NAME         PASS     STOP     NOTIFY
===========  =======  =======  =======
SIGSEGV      false    true     true
(lldb) r
Process 49945 launched: '/usr/local/bin/melonDS' (x86_64)
melonDS 0.9.5
https://melonds.kuribo64.net/
IPC: instance ID 1
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-izder456'
Audio output frequency: 48000 Hz
Created a OpenGL context
GL_VENDOR: Intel
GL_RENDERER: Mesa Intel(R) HD Graphics 5500 (BDW GT2)
GL_VERSION: 4.6 (Core Profile) Mesa 23.3.6
GL_SHADING_LANGUAGE_VERSION: 4.60
MP comm init OK, instance ID 1
ARM9 BIOS loaded
ARM7 BIOS loaded
Resetting JIT block cache...
done resetting jit mem
done resetting jit mem
MAC: 00:19:FD:B3:BD:86
FW: WIFI CRC16 = GOOD
FW: AP1 CRC16 = GOOD
FW: AP2 CRC16 = GOOD
FW: AP3 CRC16 = GOOD
FW: USER0 CRC16 = GOOD
FW: USER1 CRC16 = GOOD
Game code: ADME
ROM entry: 02000000 00000005
Cart ID: 00001FC2
Re-encrypting cart secure area
Process 49945 stopped
* thread #1, stop reason = signal SIGSEGV
    frame #0: 0x000008e126bf16eb libc.so.100.1`_thread_sys_poll at -:2
warning: This version of LLDB has no plugin for the language "assembler". Inspection of frame variables will be limited.
(lldb) frame info
frame #0: 0x000008e126bf16eb libc.so.100.1`_thread_sys_poll at -:2
(lldb) frame variable
(lldb)

Also the backtrace in the end is the wrong thread?

What do you mean?

Izder456 commented 1 week ago

@RSDuck

got learning a bit more about debugging.

heres the output of:

gdb $(which melonDS) melonDS.core

GNU gdb (GDB) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-unknown-openbsd7.5".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /usr/local/bin/melonDS...
Reading symbols from /usr/local/bin/.debug/melonDS.dbg...
[New process 479009]
[New process 261453]
[New process 500121]
[New process 293878]
[New process 597546]
[New process 355356]
[New process 281441]
[New process 291377]
[New process 305011]
[New process 369700]
[New process 115130]
[New process 351819]
[New process 126874]
[New process 510707]
[New process 268684]
Core was generated by `melonDS'.
Program terminated with signal SIGABRT, Aborted.
#0  thrkill () at /tmp/-:2
[Current thread is 1 (process 479009)]
(gdb) bt
#0  thrkill () at /tmp/-:2
#1  0xd4d7220244d44784 in ?? ()
#2  0x000005d7a785185b in _libc_abort () at /usr/src/lib/libc/stdlib/abort.c:51
#3  0x000005d58d8fffd9 in ARMJIT::Compiler::RewriteMemAccess (this=<optimized out>, pc=0x5d592dadf8f <ARMJIT::CodeMemory+15375> "\213]$\203\353\001\017\220\300\017\223\301\215TH")
    at /usr/obj/melonds-0.9.5/melonDS-0.9.5/src/ARMJIT_x64/ARMJIT_LoadStore.cpp:55
#4  0x000005d58d8ee6a6 in ARMJIT_Memory::FaultHandler (faultDesc=...) at /usr/obj/melonds-0.9.5/melonDS-0.9.5/src/ARMJIT_Memory.cpp:691
#5  SigsegvHandler (sig=<optimized out>, info=<optimized out>, rawContext=0x5d85d309f40) at /usr/obj/melonds-0.9.5/melonDS-0.9.5/src/ARMJIT_Memory.cpp:210
#6  <signal handler called>
#7  0x000005d592dadf8f in ARMJIT::CodeMemory ()
#8  0x00000000000003e6 in ?? ()
#9  0x000005d85d30a510 in ?? ()
#10 0x000005d58db98f46 in ?? ()
#11 0x000005d885bf9000 in ?? ()
#12 0x00000000ffff07ce in ?? ()
#13 0x000000000000013e in ?? ()
#14 0x00000000000003e6 in ?? ()
#15 0x000005d58d8508fe in ARMv5::ExecuteJIT (this=0x5d885bf9000) at /usr/obj/melonds-0.9.5/melonDS-0.9.5/src/ARM.cpp:689
#16 0x0000000000000000 in ?? ()
(gdb) quit

seems gnu's debugger seems to be fine with .core dumps, but not the literal binary.

I should mention i have built melonDS with debug symbols ON.

Hopefully this helps, sorry for the wait.