Permalink
Browse files

Fix unwinders on aarch64

Summary:
With a new enough version of gdb, we have a gdb.unwind module on
aarch64, so fix our unwinder to do the right thing.

Reviewed By: mxw

Differential Revision: D7202225

fbshipit-source-id: cfee595e7950fefb12e04eb2f93dc0041eb4f79a
  • Loading branch information...
markw65 authored and hhvm-bot committed Mar 8, 2018
1 parent bacea82 commit 000059a4fd75e369c47ba80c1bd3df9728f70435
Showing with 29 additions and 14 deletions.
  1. +14 −7 hphp/tools/gdb/stack.py
  2. +15 −7 hphp/tools/gdb/unwind.py
@@ -74,9 +74,11 @@ def invoke(self, args, from_tty):
print('walkstk: Cannot find any frames: corrupt stack?')
return
arch = native_frame.architecture().name()
frame_reg = 'x29' if arch == 'aarch64' else 'rbp'
# Set fp = $rbp, rip = $rip.
fp_type = T('uintptr_t').pointer()
fp = native_frame.read_register('rbp').cast(fp_type)
fp = native_frame.read_register(frame_reg).cast(fp_type)
rip = native_frame.pc()
if len(argv) == 1:
@@ -193,14 +195,19 @@ def invoke(self, args, from_tty):
return
fp_type = T('uintptr_t').pointer()
fp = gdb.parse_and_eval('$rbp').cast(fp_type)
rip = gdb.parse_and_eval('$rip').cast(T('uintptr_t'))
if len(argv) >= 1:
fp = argv[0].cast(fp_type)
try:
arch = gdb.newest_frame().architecture().name()
except:
arch = 'i386:x86-64'
if len(argv) == 2:
rip = argv[1].cast(T('uintptr_t'))
frame_reg = '$x29' if arch == 'aarch64' else '$rbp'
pc_reg = '$pc' if arch == 'aarch64' else '$rip'
fp = (argv[0] if len(argv) >= 1 else
gdb.parse_and_eval(frame_reg)).cast(fp_type)
rip = (argv[1] if len(argv) == 2 else
gdb.parse_and_eval(pc_reg)).cast(T('uintptr_t'))
i = 0
fp = (fp, rip)
@@ -26,12 +26,20 @@ class HHVMUnwinder(Unwinder):
"""
def __init__(self):
try:
self.arch = gdb.newest_frame().architecture().name()
except:
self.arch = 'i386:x86-64'
self.frame_reg = 'x29' if self.arch == 'aarch64' else 'rbp'
self.stack_reg = 'sp' if self.arch == 'aarch64' else 'rsp'
self.pc_reg = 'pc' if self.arch == 'aarch64' else 'rip'
super(HHVMUnwinder, self).__init__('hhvm_unwinder')
def __call__(self, pending_frame):
fp = pending_frame.read_register('rbp')
sp = pending_frame.read_register('rsp')
ip = pending_frame.read_register('rip')
fp = pending_frame.read_register(self.frame_reg)
sp = pending_frame.read_register(self.stack_reg)
ip = pending_frame.read_register(self.pc_reg)
if not frame.is_jitted(fp, ip):
return None
@@ -50,18 +58,18 @@ def __call__(self, pending_frame):
# 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])
unwind_info.add_saved_register(self.frame_reg, fp[0])
unwind_info.add_saved_register(self.pc_reg, 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)
unwind_info.add_saved_register(self.stack_reg, 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)
unwind_info.add_saved_register(self.stack_reg, fp + 16)
return unwind_info

0 comments on commit 000059a

Please sign in to comment.