mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-05-28 17:16:29 +03:00
Improvements in SyntaxTokenizer TextMate compatability. Fixed debugging types definition scripts.
156 lines
5.1 KiB
Python
156 lines
5.1 KiB
Python
import lldb
|
|
|
|
|
|
class EESmallVectorSyntheticProvider:
|
|
def __init__(self, valobj, internal_dict):
|
|
self.valobj = valobj
|
|
self.update()
|
|
|
|
def _get_m_data(self):
|
|
# 1. Try direct access
|
|
m_data = self.valobj.GetChildMemberWithName("m_data")
|
|
if m_data and m_data.IsValid():
|
|
return m_data
|
|
|
|
# 2. Try looking inside the base class (ankerl::svector)
|
|
for i in range(self.valobj.GetNumChildren()):
|
|
child = self.valobj.GetChildAtIndex(i)
|
|
if child.GetName() and "svector" in child.GetName():
|
|
m_data = child.GetChildMemberWithName("m_data")
|
|
if m_data and m_data.IsValid():
|
|
return m_data
|
|
return None
|
|
|
|
def update(self):
|
|
self.size = 0
|
|
self.capacity = 0
|
|
self.is_direct = True
|
|
self.data_addr = lldb.LLDB_INVALID_ADDRESS
|
|
|
|
self.type_t = self.valobj.GetType().GetTemplateArgumentType(0)
|
|
self.m_data = self._get_m_data()
|
|
|
|
if not self.m_data or not self.m_data.IsValid():
|
|
return
|
|
|
|
# Use SBData instead of direct memory reading to support variables in registers
|
|
sb_data = self.m_data.GetData()
|
|
error = lldb.SBError()
|
|
if sb_data.GetByteSize() == 0:
|
|
return
|
|
|
|
first_byte = sb_data.GetUnsignedInt8(error, 0)
|
|
if error.Fail():
|
|
return
|
|
|
|
self.is_direct = (first_byte & 1) != 0
|
|
|
|
target = self.valobj.GetTarget()
|
|
ptr_size = target.GetAddressByteSize()
|
|
|
|
# Safely get alignment
|
|
align_t = 0
|
|
if hasattr(self.type_t, "GetByteAlign"):
|
|
align_t = self.type_t.GetByteAlign()
|
|
if align_t == 0:
|
|
align_t = self.type_t.GetByteSize()
|
|
if align_t == 0:
|
|
align_t = ptr_size
|
|
|
|
if self.is_direct:
|
|
self.size = first_byte >> 1
|
|
self.capacity = 0
|
|
|
|
# Data starts at offset equal to the alignment of T
|
|
addr = self.m_data.GetLoadAddress()
|
|
if addr != lldb.LLDB_INVALID_ADDRESS:
|
|
self.data_addr = addr + align_t
|
|
else:
|
|
# Indirect Mode: read the pointer to the heap storage
|
|
void_ptr = sb_data.GetAddress(error, 0)
|
|
process = self.valobj.GetProcess()
|
|
|
|
if error.Fail() or void_ptr == 0 or not process.IsValid():
|
|
return
|
|
|
|
self.size = process.ReadUnsignedIntegerFromMemory(void_ptr, ptr_size, error)
|
|
self.capacity = process.ReadUnsignedIntegerFromMemory(
|
|
void_ptr + ptr_size, ptr_size, error
|
|
)
|
|
|
|
# Calculate offset_to_data: round_up(sizeof(header), alignment_of_t)
|
|
header_size = 2 * ptr_size
|
|
offset = ((header_size + (align_t - 1)) // align_t) * align_t
|
|
self.data_addr = void_ptr + offset
|
|
|
|
def num_children(self):
|
|
return self.size
|
|
|
|
def get_child_index(self, name):
|
|
try:
|
|
return int(name.lstrip("[").rstrip("]"))
|
|
except:
|
|
return -1
|
|
|
|
def get_child_at_index(self, index):
|
|
if index < 0 or index >= self.size:
|
|
return None
|
|
item_addr = self.data_addr + index * self.type_t.GetByteSize()
|
|
return self.valobj.CreateValueFromAddress(f"[{index}]", item_addr, self.type_t)
|
|
|
|
def has_children(self):
|
|
return self.size > 0
|
|
|
|
|
|
def EESmallVectorSummaryProvider(valobj, internal_dict):
|
|
"""
|
|
Standalone summary provider. It's an LLDB anti-pattern to initialize the
|
|
SyntheticProvider class inside here, so we duplicate the tiny bit of logic
|
|
needed to read the state efficiently.
|
|
"""
|
|
# Find m_data, handling base classes
|
|
m_data = valobj.GetChildMemberWithName("m_data")
|
|
if not m_data or not m_data.IsValid():
|
|
for i in range(valobj.GetNumChildren()):
|
|
child = valobj.GetChildAtIndex(i)
|
|
if child.GetName() and "svector" in child.GetName():
|
|
m_data = child.GetChildMemberWithName("m_data")
|
|
break
|
|
|
|
if not m_data or not m_data.IsValid():
|
|
return f"size={valobj.GetNumChildren()}"
|
|
|
|
sb_data = m_data.GetData()
|
|
error = lldb.SBError()
|
|
first_byte = sb_data.GetUnsignedInt8(error, 0)
|
|
|
|
if error.Fail():
|
|
return f"size={valobj.GetNumChildren()}"
|
|
|
|
is_direct = (first_byte & 1) != 0
|
|
|
|
if is_direct:
|
|
size = first_byte >> 1
|
|
return f"[Direct] size={size}"
|
|
else:
|
|
target = valobj.GetTarget()
|
|
ptr_size = target.GetAddressByteSize()
|
|
void_ptr = sb_data.GetAddress(error, 0)
|
|
process = valobj.GetProcess()
|
|
|
|
if process.IsValid() and void_ptr != 0:
|
|
size = process.ReadUnsignedIntegerFromMemory(void_ptr, ptr_size, error)
|
|
capacity = process.ReadUnsignedIntegerFromMemory(void_ptr + ptr_size, ptr_size, error)
|
|
return f"[Indirect] size={size}, capacity={capacity}"
|
|
|
|
return "[Indirect]"
|
|
|
|
|
|
def __lldb_init_module(debugger, internal_dict):
|
|
debugger.HandleCommand(
|
|
'type summary add -x "^EE::SmallVector<.+>$" -F eepp_lldb.EESmallVectorSummaryProvider'
|
|
)
|
|
debugger.HandleCommand(
|
|
'type synthetic add -x "^EE::SmallVector<.+>$" -l eepp_lldb.EESmallVectorSyntheticProvider'
|
|
)
|