1# Pretty-printers for InterpreterRegs. 2 3import gdb 4import mozilla.prettyprinters as prettyprinters 5 6prettyprinters.clear_module_printers(__name__) 7 8from mozilla.prettyprinters import pretty_printer 9 10# Cache information about the Interpreter types for this objfile. 11class InterpreterTypeCache(object): 12 def __init__(self): 13 self.tValue = gdb.lookup_type('JS::Value') 14 self.tJSOp = gdb.lookup_type('JSOp') 15 self.tScriptFrameIterData = gdb.lookup_type('js::ScriptFrameIter::Data') 16 self.tInterpreterFrame = gdb.lookup_type('js::InterpreterFrame') 17 self.tBaselineFrame = gdb.lookup_type('js::jit::BaselineFrame') 18 self.tRematerializedFrame = gdb.lookup_type('js::jit::RematerializedFrame') 19 self.tDebugFrame = gdb.lookup_type('js::wasm::DebugFrame') 20 21@pretty_printer('js::InterpreterRegs') 22class InterpreterRegs(object): 23 def __init__(self, value, cache): 24 self.value = value 25 self.cache = cache 26 if not cache.mod_Interpreter: 27 cache.mod_Interpreter = InterpreterTypeCache() 28 self.itc = cache.mod_Interpreter 29 30 # There's basically no way to co-operate with 'set print pretty' (how would 31 # you get the current level of indentation?), so we don't even bother 32 # trying. No 'children', just 'to_string'. 33 def to_string(self): 34 fp_ = 'fp_ = {}'.format(self.value['fp_']) 35 slots = (self.value['fp_'] + 1).cast(self.itc.tValue.pointer()) 36 sp = 'sp = fp_.slots() + {}'.format(self.value['sp'] - slots) 37 pc = self.value['pc'] 38 try: 39 opcode = pc.dereference().cast(self.itc.tJSOp) 40 except: 41 opcode = 'bad pc' 42 pc = 'pc = {} ({})'.format(pc.cast(self.cache.void_ptr_t), opcode) 43 return '{{ {}, {}, {} }}'.format(fp_, sp, pc) 44 45@pretty_printer('js::AbstractFramePtr') 46class AbstractFramePtr(object): 47 Tag_ScriptFrameIterData = 0x0 48 Tag_InterpreterFrame = 0x1 49 Tag_BaselineFrame = 0x2 50 Tag_RematerializedFrame = 0x3 51 Tag_WasmDebugFrame = 0x4 52 TagMask = 0x7 53 54 def __init__(self, value, cache): 55 self.value = value 56 self.cache = cache 57 if not cache.mod_Interpreter: 58 cache.mod_Interpreter = InterpreterTypeCache() 59 self.itc = cache.mod_Interpreter 60 61 def to_string(self): 62 ptr = self.value['ptr_'] 63 tag = ptr & AbstractFramePtr.TagMask 64 ptr = ptr & ~AbstractFramePtr.TagMask 65 if tag == AbstractFramePtr.Tag_ScriptFrameIterData: 66 label = 'js::ScriptFrameIter::Data' 67 ptr = ptr.cast(self.itc.tScriptFrameIterData.pointer()) 68 if tag == AbstractFramePtr.Tag_InterpreterFrame: 69 label = 'js::InterpreterFrame' 70 ptr = ptr.cast(self.itc.tInterpreterFrame.pointer()) 71 if tag == AbstractFramePtr.Tag_BaselineFrame: 72 label = 'js::jit::BaselineFrame' 73 ptr = ptr.cast(self.itc.tBaselineFrame.pointer()) 74 if tag == AbstractFramePtr.Tag_RematerializedFrame: 75 label = 'js::jit::RematerializedFrame' 76 ptr = ptr.cast(self.itc.tRematerializedFrame.pointer()) 77 if tag == AbstractFramePtr.Tag_WasmDebugFrame: 78 label = 'js::wasm::DebugFrame' 79 ptr = ptr.cast(self.itc.tDebugFrame.pointer()) 80 return 'AbstractFramePtr (({} *) {})'.format(label, ptr) 81 82 # Provide the ptr_ field as a child, so it prints after the pretty string 83 # provided above. 84 def children(self): 85 yield ('ptr_', self.value['ptr_']) 86