def try_unwinder_init(): """Try to register the custom unwinder if it hasn't been already, and return whether the unwinder has been successfully registered.""" global _did_init if _did_init: return True # If we can't successfully call is_jitted(), then gdb startup hasn't # proceeded to a point where it's safe to set up our unwinder yet, so just # bail out. try: frame.is_jitted(0, 0) except: return False register_unwinder(None, HHVMUnwinder()) _did_init = True return True
# GDB wants a FrameId to be a pair of (stack pointer, starting PC) for # a given function frame. Unfortunately, we can't restore the stack # pointer correctly in the TC, and we don't know our starting IP. # # Instead, we just use the stack pointer value for our most recent call # into native code, along with the current PC. It turns out that this # is good enough. # # GDB expects stack pointers to be monotonically nondecreasing as we # unwind, so we can't use, e.g., the frame pointer as part of the ID. unwind_info = pending_frame.create_unwind_info(FrameId(sp, ip)) # Restore the saved frame pointer and instruction pointer. fp = fp.cast(T('uintptr_t').pointer()) unwind_info.add_saved_register('rbp', fp[0]) unwind_info.add_saved_register('rip', fp[1]) if frame.is_jitted(fp[0], fp[1]): # Our parent frame is jitted. Again, we are unable to track %rsp # properly in the TC, so just preserve its value (just as we do in # the TC's custom .eh_frame section). unwind_info.add_saved_register('rsp', sp) else: # Our parent frame is not jitted, so we're in enterTCHelper, and we # can restore our parent's %rsp as usual. unwind_info.add_saved_register('rsp', fp + 16) return unwind_info register_unwinder(None, HHVMUnwinder())
# a given function frame. Unfortunately, we can't restore the stack # pointer correctly in the TC, and we don't know our starting IP. # # Instead, we just use the stack pointer value for our most recent call # into native code, along with the current PC. It turns out that this # is good enough. # # GDB expects stack pointers to be monotonically nondecreasing as we # unwind, so we can't use, e.g., the frame pointer as part of the ID. unwind_info = pending_frame.create_unwind_info(FrameId(sp, ip)) # Restore the saved frame pointer and instruction pointer. fp = fp.cast(T('uintptr_t').pointer()) unwind_info.add_saved_register('rbp', fp[0]) unwind_info.add_saved_register('rip', fp[1]) if frame.is_jitted(fp[0], fp[1]): # Our parent frame is jitted. Again, we are unable to track %rsp # properly in the TC, so just preserve its value (just as we do in # the TC's custom .eh_frame section). unwind_info.add_saved_register('rsp', sp) else: # Our parent frame is not jitted, so we're in enterTCHelper, and we # can restore our parent's %rsp as usual. unwind_info.add_saved_register('rsp', fp + 16) return unwind_info register_unwinder(None, HHVMUnwinder())