Skip to content

Commit c7862c6

Browse files
[ci skip] Move rp helper to new LLDB format
For now, the old function still exists as `old_rp`, in order to debug issues with this command.
1 parent cc68d69 commit c7862c6

File tree

7 files changed

+455
-16
lines changed

7 files changed

+455
-16
lines changed

misc/lldb_cruby.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -727,13 +727,13 @@ def __lldb_init_module(debugger, internal_dict):
727727
# Register all classes that subclass RbBaseCommand
728728

729729
for memname, mem in inspect.getmembers(sys.modules["lldb_rb.rb_base_command"]):
730-
if inspect.isclass(mem):
730+
if memname == "RbBaseCommand":
731731
for sclass in mem.__subclasses__():
732732
sclass.register_lldb_command(debugger, f"{__name__}.{sclass.__module__}")
733733

734734

735735
## FUNCTION INITS - These should be removed when converted to class commands
736-
debugger.HandleCommand("command script add -f lldb_cruby.lldb_rp rp")
736+
debugger.HandleCommand("command script add -f lldb_cruby.lldb_rp old_rp")
737737
debugger.HandleCommand("command script add -f lldb_cruby.count_objects rb_count_objects")
738738
debugger.HandleCommand("command script add -f lldb_cruby.stack_dump_raw SDR")
739739
debugger.HandleCommand("command script add -f lldb_cruby.dump_node dump_node")

misc/lldb_rb/commands/rp_command.py

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import lldb
2+
3+
from lldb_rb.constants import *
4+
from lldb_rb.utils import *
5+
from lldb_rb.rb_base_command import RbBaseCommand
6+
7+
class RbID2StrCommand(RbBaseCommand):
8+
program = "rp"
9+
10+
help_string = "convert and print a Ruby ID to a C string and print it to the LLDB console"
11+
12+
def call(self, debugger, command, exe_ctx, result):
13+
val = self.frame.EvaluateExpression(command)
14+
inspector = RbInspector(debugger, result, self.ruby_globals)
15+
inspector.inspect(val)
16+

misc/lldb_rb/constants.py

+2
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@
22
HEAP_PAGE_ALIGN_MASK = (~(~0 << HEAP_PAGE_ALIGN_LOG))
33
HEAP_PAGE_ALIGN = (1 << HEAP_PAGE_ALIGN_LOG)
44
HEAP_PAGE_SIZE = HEAP_PAGE_ALIGN
5+
6+
IMEMO_MASK = 0x0F

misc/lldb_rb/lldb_interface.py

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class LLDBInterface:
2+
def build_environment(self, debugger):
3+
self.debugger = debugger
4+
self.target = debugger.GetSelectedTarget()
5+
self.process = self.target.GetProcess()
6+
self.thread = self.process.GetSelectedThread()
7+
self.frame = self.thread.GetSelectedFrame()
8+

misc/lldb_rb/rb_base_command.py

+3-14
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import lldb
22
from pydoc import locate
3+
from lldb_rb.constants import *
4+
from lldb_rb.utils import *
35

4-
class RbBaseCommand:
6+
class RbBaseCommand(LLDBInterface):
57
@classmethod
68
def register_lldb_command(cls, debugger, module_name):
79
# Add any commands contained in this module to LLDB
@@ -53,16 +55,3 @@ def get_short_help(self):
5355
def get_long_help(self):
5456
return self.__class__.help_string
5557

56-
def build_environment(self, debugger):
57-
self.target = debugger.GetSelectedTarget()
58-
self.process = self.target.GetProcess()
59-
self.thread = self.process.GetSelectedThread()
60-
self.frame = self.thread.GetSelectedFrame()
61-
62-
def _append_command_output(self, debugger, command, result):
63-
output1 = result.GetOutput()
64-
debugger.GetCommandInterpreter().HandleCommand(command, result)
65-
output2 = result.GetOutput()
66-
result.Clear()
67-
result.write(output1)
68-
result.write(output2)

misc/lldb_rb/rb_heap_structs.py

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

0 commit comments

Comments
 (0)