Skip to content

Commit

Permalink
QDir and QHash now read memory directly not relying on LLDB type info
Browse files Browse the repository at this point in the history
  • Loading branch information
winseros committed Jan 15, 2024
1 parent 91545fe commit 055b0cb
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 19 deletions.
6 changes: 3 additions & 3 deletions python/lldb/qt6renderer/qdir.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ class QDirPrivate(SyntheticStruct):
def __init__(self, pointer: SBValue):
super().__init__(pointer)
self.add_gap_field(self._get_offset())
self.add_synthetic_field('path', QFileSystemEntry(pointer))
self.add_synthetic_field('abs_path', QFileSystemEntry(pointer))
self.add_synthetic_field('path', lambda p: QFileSystemEntry(p))
self.add_synthetic_field('abs_path', lambda p: QFileSystemEntry(p))

def path(self) -> QFileSystemEntry:
pass
Expand Down Expand Up @@ -86,7 +86,7 @@ def _get_offset(self):
class QDir(SyntheticStruct):
def __init__(self, pointer: SBValue):
super().__init__(pointer)
self.add_synthetic_field('d_ptr', QSharedDataPointer(pointer, QDirPrivate))
self.add_synthetic_field('d_ptr', lambda p: QSharedDataPointer[QDirPrivate](p, lambda q: QDirPrivate(q)))

def d_ptr(self) -> QSharedDataPointer[QDirPrivate]:
pass
15 changes: 9 additions & 6 deletions python/lldb/qt6renderer/qhash.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def update(self) -> bool:
p_span = d.GetChildMemberWithName('spans')

[t_key, t_value] = TypeHelpers.get_template_types(self._valobj.type, 2, self._valobj.target)
entry_size = KeyValuePair(self._valobj, t_key, t_value, 0).get_sibling_aligned_size()
entry_size = KeyValuePair(self._valobj, t_key, t_value).get_sibling_aligned_size()

for b in range(nspans):
span = self._valobj.CreateValueFromAddress('span', p_span.load_addr + b * p_span.size,
Expand All @@ -47,7 +47,9 @@ def update(self) -> bool:
for i in range(128):
offset = offsets[i]
if offset != 255:
pair = KeyValuePair(entries, t_key, t_value, offset * entry_size)
pair = KeyValuePair(entries, t_key, t_value)
pair.offset_struct_addr_by(offset * entry_size)

self._values.append(pair.k())
self._values.append(pair.v())

Expand Down Expand Up @@ -92,15 +94,16 @@ def update(self) -> bool:
offsets = span.GetChildMemberWithName('offsets').data.uint8s
entries = span.GetChildMemberWithName('entries')

entry_size = KeyValuePair(entries, t_key, t_value, 0).get_sibling_aligned_size()
pair = KeyValuePair(entries, t_key, t_value, offsets[index_offset] * entry_size)
pair = KeyValuePair(entries, t_key, t_value)
entry_size = pair.get_sibling_aligned_size()
pair.offset_struct_addr_by(offsets[index_offset] * entry_size)

self._values = [pair.k(), pair.v()]


class KeyValuePair(SyntheticStruct):
def __init__(self, pointer: SBValue, t_key: SBType, t_value: SBType, address_byte_offset):
super().__init__(pointer, address_byte_offset)
def __init__(self, pointer: SBValue, t_key: SBType, t_value: SBType):
super().__init__(pointer)
self.add_sb_type_field('k', t_key)
self.add_sb_type_field('v', t_value)

Expand Down
15 changes: 15 additions & 0 deletions python/lldb/qt6renderer/qshareddatapointer.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from lldb import SBValue
from .abstractsynth import AbstractSynth
from .syntheticstruct import SyntheticStruct
from typing import TypeVar, Generic, Callable


def qshareddatapointer_summary(valobj: SBValue):
Expand Down Expand Up @@ -31,3 +33,16 @@ def update(self) -> bool:
self._valobj.CreateValueFromData(QSharedDataPointerSynth.PROP_VALUE, value.data, value.type))

return False


TPointee = TypeVar('TPointee', bound=SyntheticStruct)


class QSharedDataPointer(SyntheticStruct, Generic[TPointee]):
def __init__(self, pointer: SBValue, pointee_ctor: Callable[[SBValue], TPointee]):
super().__init__(pointer)

self.add_synthetic_field('d', pointee_ctor, pointer=True)

def d(self) -> TPointee:
pass
40 changes: 30 additions & 10 deletions python/lldb/qt6renderer/syntheticstruct.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
from lldb import SBValue, SBType
from lldb import SBValue, SBType, eBasicTypeInt
from math import ceil
from typing import Union
from typing import Union, Callable


class SyntheticStruct:
def __init__(self, pointer: SBValue, address_byte_offset=0):
def __init__(self, pointer: SBValue):
self._pointer = pointer
self._size = 0
self._address_byte_offset = address_byte_offset

def add_gap_field(self, gap_size: int):
self._size += gap_size
Expand All @@ -25,11 +24,22 @@ def add_named_type_field(self, name: str, type_name: str, getter_name: str = Non
def add_sb_type_field(self, name: str, sb_type: SBType, getter_name: str = None):
self._add_field(name, sb_type, getter_name)

def add_synthetic_field(self, name: str, synthetic_struct: 'SyntheticStruct'):
field_byte_offset = self._get_field_byte_offset(synthetic_struct)
synthetic_struct._address_byte_offset = field_byte_offset + self._address_byte_offset
def add_synthetic_field(self, name: str, synthetic_struct_ctor: Callable[[SBValue], 'SyntheticStruct'],
pointer=False):
if pointer:
sb_ptr_t = self._pointer.target.GetBasicType(eBasicTypeInt).GetPointerType()
field_byte_offset = self._get_field_byte_offset(sb_ptr_t)
self._size = field_byte_offset + sb_ptr_t.size
field_addr = self._get_struct_addr()
struct_ptr = self._pointer.CreateValueFromAddress(name, field_addr + field_byte_offset, sb_ptr_t)
synthetic_struct = synthetic_struct_ctor(struct_ptr)
else:
synthetic_struct = synthetic_struct_ctor(self._pointer)
field_byte_offset = self._get_field_byte_offset(synthetic_struct)
if field_byte_offset:
synthetic_struct.offset_struct_addr_by(field_byte_offset)
self._size = field_byte_offset + synthetic_struct.size

self._size = field_byte_offset + synthetic_struct.size
setattr(self, name, lambda: synthetic_struct)

def _add_field(self, name: str, type: SBType, getter_name: str):
Expand All @@ -41,8 +51,7 @@ def _add_field(self, name: str, type: SBType, getter_name: str):
setattr(self, getter_name, lambda: self._field_impl(name, byte_offset, type))

def _field_impl(self, name: str, byte_offset: int, type: SBType) -> SBValue:
struct_addr = self._pointer.GetValueAsUnsigned() if self._pointer.TypeIsPointerType() else self._pointer.load_addr
struct_addr += self._address_byte_offset
struct_addr = self._get_struct_addr()

field_addr = struct_addr + byte_offset

Expand All @@ -66,6 +75,17 @@ def _get_field_byte_alignment(self, type: Union[SBType, 'SyntheticStruct']) -> i

return alignment

def offset_struct_addr_by(self, offset_in_bytes: int):
struct_addr = self._get_struct_addr()
struct_addr += offset_in_bytes

sb_int = self._pointer.target.FindFirstType('int')
self._pointer = self._pointer.CreateValueFromAddress(self._pointer.name, struct_addr, sb_int)

def _get_struct_addr(self) -> int:
struct_addr = self._pointer.GetValueAsUnsigned() if self._pointer.TypeIsPointerType() else self._pointer.load_addr
return struct_addr

@property
def size(self):
return self._size
Expand Down

0 comments on commit 055b0cb

Please sign in to comment.