@@ -571,6 +571,43 @@ def usage(self):
571571 print (" rb-stack-trace # Show backtrace for current fiber/thread" )
572572 print (" rb-stack-trace --values # Show backtrace with stack VALUEs" )
573573
574+ def _get_current_execution_context (self ):
575+ """Get the current execution context from the running thread.
576+
577+ Tries multiple approaches in order of preference:
578+ 1. ruby_current_ec - TLS variable (works in GDB, some LLDB)
579+ 2. rb_current_ec_noinline() - function call (works in most cases)
580+ 3. rb_current_ec() - macOS-specific function
581+
582+ Returns:
583+ Execution context value, or None if not available
584+ """
585+ # Try ruby_current_ec variable first
586+ try :
587+ ec = debugger .parse_and_eval ('ruby_current_ec' )
588+ if ec is not None and int (ec ) != 0 :
589+ return ec
590+ except debugger .Error :
591+ pass
592+
593+ # Fallback to rb_current_ec_noinline() function
594+ try :
595+ ec = debugger .parse_and_eval ('rb_current_ec_noinline()' )
596+ if ec is not None and int (ec ) != 0 :
597+ return ec
598+ except debugger .Error :
599+ pass
600+
601+ # Last resort: rb_current_ec() (macOS-specific)
602+ try :
603+ ec = debugger .parse_and_eval ('rb_current_ec()' )
604+ if ec is not None and int (ec ) != 0 :
605+ return ec
606+ except debugger .Error :
607+ pass
608+
609+ return None
610+
574611 def invoke (self , arg , from_tty ):
575612 """Execute the stack trace command."""
576613 try :
@@ -602,38 +639,13 @@ def invoke(self, arg, from_tty):
602639 print ()
603640
604641 try :
605- # Get current execution context from the running thread
606- # The approach depends on the debugger:
607- # - GDB can access thread-local variable ruby_current_ec directly
608- # - LLDB cannot access TLS variables, must use rb_current_ec_noinline()
609- ec = None
610-
611- if debugger .DEBUGGER_NAME == 'gdb' :
612- # GDB: Try direct TLS variable access first (faster)
613- try :
614- ec = debugger .parse_and_eval ('ruby_current_ec' )
615- except debugger .Error :
616- # Fallback to function call
617- try :
618- ec = debugger .parse_and_eval ('rb_current_ec_noinline()' )
619- except debugger .Error :
620- pass
621- else :
622- # LLDB: Must use function call (cannot access TLS variables)
623- try :
624- ec = debugger .parse_and_eval ('rb_current_ec_noinline()' )
625- except debugger .Error :
626- # Fallback attempts for macOS or other platforms
627- try :
628- ec = debugger .parse_and_eval ('rb_current_ec()' )
629- except debugger .Error :
630- pass
642+ ec = self ._get_current_execution_context ()
631643
632- if ec is None or int ( ec ) == 0 :
644+ if ec is None :
633645 print ("Error: No execution context available" )
634646 print ("Either select a fiber with 'rb-fiber-switch' or ensure Ruby is running" )
635647 print ("\n Troubleshooting:" )
636- print (" - Check if Ruby symbols are loaded: image lookup -n rb_current_ec_noinline " )
648+ print (" - Check if Ruby symbols are loaded" )
637649 print (" - Ensure the process is stopped at a Ruby frame" )
638650 return
639651
0 commit comments