# Pretty-printers for InterpreterRegs. import gdb import mozilla.prettyprinters as prettyprinters prettyprinters.clear_module_printers(__name__) from mozilla.prettyprinters import pretty_printer # Cache information about the Interpreter types for this objfile. class InterpreterTypeCache(object): def __init__(self): self.tValue = gdb.lookup_type('JS::Value') self.tJSOp = gdb.lookup_type('JSOp') self.tScriptFrameIterData = gdb.lookup_type('js::ScriptFrameIter::Data') self.tInterpreterFrame = gdb.lookup_type('js::InterpreterFrame') self.tBaselineFrame = gdb.lookup_type('js::jit::BaselineFrame') self.tRematerializedFrame = gdb.lookup_type('js::jit::RematerializedFrame') @pretty_printer('js::InterpreterRegs') class InterpreterRegs(object): def __init__(self, value, cache): self.value = value self.cache = cache if not cache.mod_Interpreter: cache.mod_Interpreter = InterpreterTypeCache() self.itc = cache.mod_Interpreter # There's basically no way to co-operate with 'set print pretty' (how would # you get the current level of indentation?), so we don't even bother # trying. No 'children', just 'to_string'. def to_string(self): fp_ = 'fp_ = {}'.format(self.value['fp_']) slots = (self.value['fp_'] + 1).cast(self.itc.tValue.pointer()) sp = 'sp = fp_.slots() + {}'.format(self.value['sp'] - slots) pc = self.value['pc'] try: opcode = pc.dereference().cast(self.itc.tJSOp) except: opcode = 'bad pc' pc = 'pc = {} ({})'.format(pc.cast(self.cache.void_ptr_t), opcode) return '{{ {}, {}, {} }}'.format(fp_, sp, pc) @pretty_printer('js::AbstractFramePtr') class AbstractFramePtr(object): Tag_ScriptFrameIterData = 0x0 Tag_InterpreterFrame = 0x1 Tag_BaselineFrame = 0x2 Tag_RematerializedFrame = 0x3 TagMask = 0x3 def __init__(self, value, cache): self.value = value self.cache = cache if not cache.mod_Interpreter: cache.mod_Interpreter = InterpreterTypeCache() self.itc = cache.mod_Interpreter def to_string(self): ptr = self.value['ptr_'] tag = ptr & AbstractFramePtr.TagMask ptr = ptr & ~AbstractFramePtr.TagMask if tag == AbstractFramePtr.Tag_ScriptFrameIterData: label = 'js::ScriptFrameIter::Data' ptr = ptr.cast(self.itc.tScriptFrameIterData.pointer()) if tag == AbstractFramePtr.Tag_InterpreterFrame: label = 'js::InterpreterFrame' ptr = ptr.cast(self.itc.tInterpreterFrame.pointer()) if tag == AbstractFramePtr.Tag_BaselineFrame: label = 'js::jit::BaselineFrame' ptr = ptr.cast(self.itc.tBaselineFrame.pointer()) if tag == AbstractFramePtr.Tag_RematerializedFrame: label = 'js::jit::RematerializedFrame' ptr = ptr.cast(self.itc.tRematerializedFrame.pointer()) return 'AbstractFramePtr (({} *) {})'.format(label, ptr) # Provide the ptr_ field as a child, so it prints after the pretty string # provided above. def children(self): yield ('ptr_', self.value['ptr_'])