lldb¶
Attach & Continue¶
sudo apt update && sudo apt install -y lldb
sudo lldb -o "continue" -p $(pgrep -x worker)
Breakpoints¶
Automatically perform an action on hit:
or via a one-lineer syntax:
Python scripting in lldb¶
Tutorial, Reference 1, Reference 2, Python enums.
List non-nullptr elements of an array¶
script
inner = lldb.frame.FindVariable("alienInner")
buckets = inner.GetChildMemberWithName("mBuckets")
count = inner.GetChildMemberWithName("mBucketCount")
for i in range(count.signed):
if buckets.GetChildAtIndex(i, lldb.eNoDynamicValues, True).unsigned != 0:
print(f'{buckets.GetChildAtIndex(i, lldb.eNoDynamicValues, True)}')
Use script from files¶
Create script:
parray.py
import lldb
import shlex
def parray(debugger, command, result, dict):
args = shlex.split(command)
va = lldb.frame.FindVariable(args[0])
for i in range(0, int(args[1])):
print va.GetChildAtIndex(i, 0, 1)
Define a command parray
in lldb:
(lldb) command script import /path/to/parray.py
(lldb) command script add --function parray.parray parray
Now you can use parray
variable length:
(lldb) parray a 5
(double) *a = 0
(double) [1] = 0
(double) [2] = 1.14468
(double) [3] = 2.28936
(double) [4] = 3.43404
Another example of scripting¶
script
def PackedRow_to_str(row: lldb.SBValue):
TAG_BIT = 1 << 0;
BUCKET_TAIL_PTR_BIT = 1 << 3;
BUCKET_HEAD_PTR_BIT = 1 << 4;
FINAL_BIT = 1 << 5;
END_OF_BUCKET_BIT = 1 << 6;
NEXT_ROW_PACKET_PTR_BIT = 1 << 7;
m_flags: int = row.GetChildMemberWithName("mFlags").unsigned
result: str = f'len: {row.GetChildMemberWithName("mLength").unsigned}'
if m_flags & BUCKET_TAIL_PTR_BIT:
result += " tail"
if m_flags & BUCKET_HEAD_PTR_BIT:
result += " head"
if m_flags & FINAL_BIT:
result += " final"
if m_flags & NEXT_ROW_PACKET_PTR_BIT:
result += " ptr"
return result
def print_ResizingHash_as(inner: lldb.SBValue, value_name: str = "PackedRow", max_count: int = None):
target = lldb.debugger.GetSelectedTarget()
packed_row_type = target.FindFirstType(value_name)
BLOOM_MASK = 0xFFFF000000000000
PTR_MASK = ~BLOOM_MASK
bucket_count: lldb.SBValue = inner.GetChildMemberWithName("mBucketCount")
for i in range(min(bucket_count.signed, max_count) if max_count else bucket_count.signed):
bucket = buckets.GetChildAtIndex(i, lldb.eNoDynamicValues, True)
if bucket.unsigned == 0:
continue
bloom_val = (bucket.GetValueAsUnsigned() & BLOOM_MASK) >> 48
ptr_val = bucket.GetValueAsUnsigned() & PTR_MASK
packed_row: lldb.SBValue = target.CreateValueFromAddress(f"i={i}", lldb.SBAddress(ptr_val, target), packed_row_type)
print(f'{packed_row.AddressOf()}, bloom: {bloom_val}, {value_name}: {PackedRow_to_str(packed_row)}')
inner = lldb.frame.FindVariable("srcInner")
print_ResizingHash_as(inner, "PackedRow", 100)
(PackedRow *) &i=61 = 0x00007fff9e13a164, bloom: 1125899906842624, PackedRow: len: 0
(PackedRow *) &i=62 = 0x00007fff9e1202c8, bloom: 281474976710656, PackedRow: len: 0
(PackedRow *) &i=986 = 0x00007fff9e120a48, bloom: 2, PackedRow: len: 2304
(PackedRow *) &i=991 = 0x00007fff9e125a4c, bloom: 2, PackedRow: len: 23056 tail head
(PackedRow *) &i=998 = 0x00007fff9e10c8ac, bloom: 4, PackedRow: len: 34304 tail head final ptr
(PackedRow *) &i=999 = 0x00007fff9e12d27c, bloom: 8, PackedRow: len: 48 tail