Difference between revisions of "Development:Debugging FEX with Signals"

From FEX-Emu Wiki
Jump to navigation Jump to search
m
 
(2 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 +
[[Category:Development]]
 
= Signals and you =
 
= Signals and you =
  
Line 19: Line 20:
 
Read more here [[Development:Debugging_Crash]]
 
Read more here [[Development:Debugging_Crash]]
  
First thing you'll want to do is enable building FEX with JITSymbols. `-DENABLE_JITSYMBOLS=True` added to cmake.
+
= Profiling FEX code =
 +
You'll want to enable a style of JIT code mark-up for perf to annotate with
 +
* FEX currently has three options for this
 +
* Depending on what you're trying to profile you will want to enable one of these options
 +
** FEX_GLOBALJITNAMING
 +
*** Useful if you want to throw all of FEX JIT space in to a global-ish namespace
 +
** FEX_LIBRARYJITNAMING
 +
*** Useful if you want to clump FEX JIT space in to library specific code segments
 +
*** Can be nice for finding libraries to thunk
 +
** FEX_BLOCKJITNAMING
 +
*** This is likely the one you want if you're profiling your application's code
 +
*** This will give you hot blocks in `perf top`
  
This will give you some symbols when capturing FEX with `perf top`
+
Enabling one of these will give you some symbols when capturing FEX with `perf top`. The block naming is useful for seeing hot blocks in program space so if something ends up being particularly slow in FEX, it can get more isolated.
 
+
* We don't currently have an option to relate JIT code directly to function symbols in the ELF at this point.
Next is when debugging FEX under GDB is to ignore the signals that FEX will be generating.
 
With gdb this is as follows
 
* handle SIGBUS SIGILL SIG63 noprint
 
 
 
If you're debugging under lldb then the syntax is a bit more hurtful and you must first run the application before passing these.
 
* pro hand -s no -n no SIGBUS SIGILL SIGRTMAX-1
 
 
 
At this point it becomes the typical problem of debugging JIT based applications, which is painful and usually involves throwing `printf` everywhere
 
  
 
= Debugging the guest application =
 
= Debugging the guest application =

Latest revision as of 13:41, 22 June 2022

Signals and you

FEX uses signals in quite a few ways that may cause debugging to be a bit of a pain. This is necessary for correct operation so it is an evil we must live with.

Signals that FEX uses

  • SIGBUS - The AArch64 JIT generates unaligned loadstore instructions then captures and backpatches these when they fault
    • This is necessary for emulating x86-TSO on AArch64 and can't be dropped without massive performance loses
  • SIGILL - All of the CPU backends generate this fault and is necessary for the emulator to return from a guest signal
    • Going in to a signal happens frequently, gdb will usually ignore the entry when it is SIGALRM or SIGUSR*
    • We could choose a different signal, but this one can be generated in one instruction which makes it nice to use
    • Using a signal to punch back through to the guest return path is necessary since we need to save and restore guest registers when guest signals occur.
  • SIG63 - We use this for various ancillary functions
    • This signal currently tells a thread that it should stop running, to pause its execution, or to resume from its paused frame
    • This is another necessary signal since if we want to safely shutdown the emulator and a thread is in a syscall, there is no way for it to leave without a signal.
    • The stop signal specifically will have the CPU backend long jump from the signal handler to the exit stage of the ASM dispatcher for safe shutdown
    • This slightly increases performance because then there aren't atomic checks per iteration of the execution loop for if we should stop executing

Debugging FEX

Read more here Development:Debugging_Crash

Profiling FEX code

You'll want to enable a style of JIT code mark-up for perf to annotate with

  • FEX currently has three options for this
  • Depending on what you're trying to profile you will want to enable one of these options
    • FEX_GLOBALJITNAMING
      • Useful if you want to throw all of FEX JIT space in to a global-ish namespace
    • FEX_LIBRARYJITNAMING
      • Useful if you want to clump FEX JIT space in to library specific code segments
      • Can be nice for finding libraries to thunk
    • FEX_BLOCKJITNAMING
      • This is likely the one you want if you're profiling your application's code
      • This will give you hot blocks in `perf top`

Enabling one of these will give you some symbols when capturing FEX with `perf top`. The block naming is useful for seeing hot blocks in program space so if something ends up being particularly slow in FEX, it can get more isolated.

  • We don't currently have an option to relate JIT code directly to function symbols in the ELF at this point.

Debugging the guest application

When FEX is started with the -G argument it will open a gdbstub socket listening on port 8086. This can be connected to with gdbserver, ida, ghidra, or binary ninja.

This is currently only useful for inspection, gdbstub doesn't yet send guest signals over through gdbstub!