1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
import lldb
from lldb_rb.lldb_interface import LLDBInterface
from lldb_rb.constants import *
class HeapPage(LLDBInterface):
def __init__(self, debugger, val):
self.build_environment(debugger)
self.page_type = self.target.FindFirstType("struct heap_page").GetPointerType()
self.val = val
def heap_page_body(self, command, ctx, result, internal_dict):
process = self.target.GetProcess()
thread = process.GetSelectedThread()
frame = thread.GetSelectedFrame()
val = frame.EvaluateExpression(command)
page = self.get_page_body(val)
print("Page body address: ", page.GetAddress(), file=result)
print(page, file=result)
def get_page_body(self, val):
tHeapPageBody = self.target.FindFirstType("struct heap_page_body")
addr = val.GetValueAsUnsigned()
page_addr = addr & ~(HEAP_PAGE_ALIGN_MASK)
address = lldb.SBAddress(page_addr, self.target)
return self.target.CreateValueFromAddress("page", address, tHeapPageBody)
def get_page_raw(self, val):
body = self.get_page_body(val)
return body.GetValueForExpressionPath("->header.page")
def to_heap_page_struct(self):
pagePtr = self.get_page_raw(self.val)
return pagePtr.Cast(self.page_type)
class RbObject(LLDBInterface):
def __init__(self, ptr, debugger, ruby_globals):
self.build_environment(debugger)
self.ruby_globals = ruby_globals
self.flUser1 = self.ruby_globals["RUBY_FL_USER1"]
self.flUser2 = self.ruby_globals["RUBY_FL_USER2"]
self.flUser3 = self.ruby_globals["RUBY_FL_USER3"]
self.flUser4 = self.ruby_globals["RUBY_FL_USER4"]
self.flUser5 = self.ruby_globals["RUBY_FL_USER5"]
self.flUser6 = self.ruby_globals["RUBY_FL_USER6"]
self.flUser7 = self.ruby_globals["RUBY_FL_USER7"]
self.flUser8 = self.ruby_globals["RUBY_FL_USER8"]
self.flUser9 = self.ruby_globals["RUBY_FL_USER9"]
self.flUshift = self.ruby_globals["RUBY_FL_USHIFT"]
self.tRBasic = self.target.FindFirstType("struct RBasic").GetPointerType()
self.tRValue = self.target.FindFirstType("struct RVALUE")
self.val = ptr.Cast(self.tRBasic)
self.page = HeapPage(self.debugger, self.val)
self.flags = self.val.GetValueForExpressionPath("->flags").GetValueAsUnsigned()
self.type = None
self.type_name = ""
def check_bits(self, bitmap_name, bitmap_index, bitmap_bit, v):
page = self.page.to_heap_page_struct()
bits = page.GetChildMemberWithName(bitmap_name)
plane = bits.GetChildAtIndex(bitmap_index).GetValueAsUnsigned()
if (plane & bitmap_bit) != 0:
return v
else:
return ' '
def dump_bits(self, result, end = "\n"):
tRValue = self.target.FindFirstType("struct RVALUE")
tUintPtr = self.target.FindFirstType("uintptr_t") # bits_t
num_in_page = (self.val.GetValueAsUnsigned() & HEAP_PAGE_ALIGN_MASK) // tRValue.GetByteSize();
bits_bitlength = tUintPtr.GetByteSize() * 8
bitmap_index = num_in_page // bits_bitlength
bitmap_offset = num_in_page & (bits_bitlength - 1)
bitmap_bit = 1 << bitmap_offset
page = self.page.to_heap_page_struct()
print("bits: [%s%s%s%s%s]" % (
self.check_bits("uncollectible_bits", bitmap_index, bitmap_bit, "L"),
self.check_bits("mark_bits", bitmap_index, bitmap_bit, "M"),
self.check_bits("pinned_bits", bitmap_index, bitmap_bit, "P"),
self.check_bits("marking_bits", bitmap_index, bitmap_bit, "R"),
self.check_bits("wb_unprotected_bits", bitmap_index, bitmap_bit, "U"),
), end=end, file=result)
def promoted_p(self):
rbFlPromoted = self.ruby_globals["RUBY_FL_PROMOTED"]
return (self.flags & rbFlPromoted) == rbFlPromoted
def frozen_p(self):
rbFlFreeze = self.ruby_globals["RUBY_FL_FREEZE"]
return (self.flags & rbFlFreeze) == rbFlFreeze
def is_type(self, type_name):
if self.type is None:
flTMask = self.ruby_globals["RUBY_T_MASK"]
flType = self.flags & flTMask
self.type = flType
if self.type == self.ruby_globals[type_name]:
self.type_name = type_name
return True
else:
return False
def as_type(self, type_name):
return self.val.Cast(self.tRValue.GetPointerType()).GetValueForExpressionPath("->as."+type_name)
def ary_ptr(self):
rval = self.as_type("array")
if self.flags & self.ruby_globals["RUBY_FL_USER1"]:
ptr = rval.GetValueForExpressionPath("->as.ary")
else:
ptr = rval.GetValueForExpressionPath("->as.heap.ptr")
return ptr
def ary_len(self):
if self.flags & self.flUser1:
len = ((self.flags &
(self.flUser3 | self.flUser4 | self.flUser5 | self.flUser6 |
self.flUser7 | self.flUser8 | self.flUser9)
) >> (self.flUshift + 3))
else:
rval = self.as_type("array")
len = rval.GetValueForExpressionPath("->as.heap.len").GetValueAsSigned()
return len
def bignum_len(self):
if self.flags & self.flUser2:
len = ((self.flags &
(self.flUser3 | self.flUser4 | self.flUser5)
) >> (self.flUshift + 3))
else:
len = (self.as_type("bignum").GetValueForExpressionPath("->as.heap.len").
GetValueAsUnsigned())
return len
|