diff --git a/misc/lldb_cruby.py b/misc/lldb_cruby.py index e0cf53760f..748d8aacf6 100755 --- a/misc/lldb_cruby.py +++ b/misc/lldb_cruby.py @@ -527,6 +527,31 @@ def dump_bits(target, result, page, object_address, end = "\n"): check_bits(page, "wb_unprotected_bits", bitmap_index, bitmap_bit, "U"), ), end=end, file=result) +class HeapPageIter: + def __init__(self, page, target): + self.page = page + self.target = target + self.start = page.GetChildMemberWithName('start').GetValueAsUnsigned(); + self.num_slots = page.GetChildMemberWithName('total_slots').unsigned + self.counter = 0 + self.tRBasic = target.FindFirstType("struct RBasic") + self.tRValue = target.FindFirstType("struct RVALUE") + + def __iter__(self): + return self + + def __next__(self): + if self.counter < self.num_slots: + obj_addr_i = self.start + (self.counter * self.tRValue.GetByteSize()) + obj_addr = lldb.SBAddress(obj_addr_i, self.target) + slot_info = (self.counter, obj_addr_i, self.target.CreateValueFromAddress("object", obj_addr, self.tRBasic)) + self.counter += 1 + + return slot_info + else: + raise StopIteration + + def dump_page(debugger, command, result, internal_dict): if not ('RUBY_Qfalse' in globals()): lldb_init(debugger) @@ -540,21 +565,33 @@ def dump_page(debugger, command, result, internal_dict): page = frame.EvaluateExpression(command) page = page.Cast(tHeapPageP) - tRBasic = target.FindFirstType("struct RBasic") - tRValue = target.FindFirstType("struct RVALUE") - - obj_address = page.GetChildMemberWithName('start').GetValueAsUnsigned(); - num_slots = page.GetChildMemberWithName('total_slots').unsigned - ruby_type_map = ruby_types(debugger) - for j in range(0, num_slots): - offset = obj_address + (j * tRValue.GetByteSize()) - obj_addr = lldb.SBAddress(offset, target) - p = target.CreateValueFromAddress("object", obj_addr, tRBasic) - dump_bits(target, result, page, offset, end = " ") - flags = p.GetChildMemberWithName('flags').GetValueAsUnsigned() - print("%s [%3d]: Addr: %0#x (flags: %0#x)" % (rb_type(flags, ruby_type_map), j, offset, flags), file=result) + freelist = [] + fl_start = page.GetChildMemberWithName('freelist').GetValueAsUnsigned() + tRVALUE = target.FindFirstType("struct RVALUE") + + while fl_start > 0: + freelist.append(fl_start) + obj_addr = lldb.SBAddress(fl_start, target) + obj = target.CreateValueFromAddress("object", obj_addr, tRVALUE) + fl_start = obj.GetChildMemberWithName("as").GetChildMemberWithName("free").GetChildMemberWithName("next").GetValueAsUnsigned() + + for (page_index, obj_addr, obj) in HeapPageIter(page, target): + dump_bits(target, result, page, obj_addr, end= " ") + flags = obj.GetChildMemberWithName('flags').GetValueAsUnsigned() + flType = flags & RUBY_T_MASK + + flidx = ' ' + if flType == RUBY_T_NONE: + try: + flidx = "%3d" % freelist.index(obj_addr) + except ValueError: + flidx = ' ' + + result_str = "%s idx: [%3d] freelist_idx: {%s} Addr: %0#x (flags: %0#x)" % (rb_type(flags, ruby_type_map), page_index, flidx, obj_addr, flags) + print(result_str, file=result) + def rb_type(flags, ruby_types): flType = flags & RUBY_T_MASK