#!/usr/bin/env python2 # Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) # To enable, put something like this in ~/.lldbinit: # # command script import $PYRO_ROOT/util/lldb_support.py # type summary add -F lldb_support.format_raw_object -p -x "python::Raw.*" import lldb def as_enum(target, name, value): """Given a name like LayoutId or ObjectFormat and an int, return the string name of the value. """ type = target.FindFirstType("python::" + name) data = lldb.SBData.CreateDataFromInt(value, size=type.size) enum = target.CreateValueFromData(name, data, type) return str(enum).split(" = ")[1] def format_heap_obj(val, raw): """Format a HeapObject's address and information from its header.""" address = raw - 1 header_type = val.target.FindFirstType("python::RawHeader") header = val.CreateValueFromAddress("header", address - 8, header_type) header_raw = header.GetChildMemberWithName("raw_").GetValueAsUnsigned() return "HeapObject @ 0x%x %s" % (address, format_header(val, header_raw)) def get_bits(raw, n): """Extract n bottom bits from raw, returning the value and raw with those bits shifted out. """ return (raw & ((1 << n) - 1), raw >> n) def format_header(val, raw): """Format all relevant information from a HeapObject's header.""" tag, raw = get_bits(raw, 3) format, raw = get_bits(raw, 3) layout_id, raw = get_bits(raw, 20) hash, raw = get_bits(raw, 30) count, raw = get_bits(raw, 8) return "Header<%s, %s, hash=%d, count=%d>" % ( as_enum(val.target, "ObjectFormat", format), as_enum(val.target, "LayoutId", layout_id), hash, count, ) def format_error_or_seq(raw): """Format an error or small sequence.""" tag = (raw >> 3) & 0x3 if tag == 2: return "Error" if tag == 3: return "" raw >>= 5 length = raw & 0x7 raw >>= 3 result = "" for _i in range(length): result += chr(raw & 0xFF) raw >>= 8 return "%s('%s')" % ("SmallStr" if tag == 1 else "SmallBytes", result) def format_imm(raw): """Format one of the singleton immediate values.""" tag = (raw >> 3) & 0x3 if tag == 0: return "True" if raw & 0x20 else "False" return ("NotImplemented", "Unbound", "None")[tag - 1] def format_raw_object(raw_object, internal_dict): """Format a RawObject.""" raw = raw_object.GetChildMemberWithName("raw_").GetValueAsUnsigned() # SmallInt if raw & 0x1 == 0: return str(raw_object.GetChildMemberWithName("raw_").GetValueAsSigned() >> 1) low_tag = (raw >> 1) & 0x3 if low_tag == 0: return format_heap_obj(raw_object, raw) if low_tag == 1: return format_header(raw_object, raw) if low_tag == 2: return format_error_or_seq(raw) return format_imm(raw)