Move konan_lldb.py with from the KMM plugin
This version of the konan_lldb.py has scripted breakpoints to avoid stepping into <compiler-generated> routines. ^KT-63598
This commit is contained in:
committed by
Space Team
parent
fd1641ef35
commit
22b2c1a587
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
##
|
||||
# Copyright 2010-2017 JetBrains s.r.o.
|
||||
# Copyright 2010-2023 JetBrains s.r.o.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -32,7 +32,7 @@ import traceback
|
||||
|
||||
NULL = 'null'
|
||||
logging=False
|
||||
exe_logging=False
|
||||
exe_logging=True if (os.getenv('GLOG_log_dir') != None) else False # Same as in LLDBFrontend
|
||||
bench_logging=False
|
||||
|
||||
def log(msg):
|
||||
@@ -43,7 +43,7 @@ def log(msg):
|
||||
|
||||
def exelog(stmt):
|
||||
if exe_logging:
|
||||
f = open(os.getenv('HOME', '') + "/lldbexelog.txt", "a")
|
||||
f = open(os.getenv('GLOG_log_dir', '') + "/konan_lldb.log", "a")
|
||||
f.write(stmt())
|
||||
f.write("\n")
|
||||
f.close()
|
||||
@@ -84,6 +84,8 @@ def _symbol_loaded_address(name, debugger = lldb.debugger):
|
||||
log(lambda: "_symbol_loaded_address:{} {:#x}".format(name, address))
|
||||
return address
|
||||
|
||||
return 0
|
||||
|
||||
def _type_info_by_address(address, debugger = lldb.debugger):
|
||||
target = debugger.GetSelectedTarget()
|
||||
process = target.GetProcess()
|
||||
@@ -123,6 +125,7 @@ __FACTORY = {}
|
||||
SYNTHETIC_OBJECT_LAYOUT_CACHE = {}
|
||||
TO_STRING_DEPTH = 2
|
||||
ARRAY_TO_STRING_LIMIT = 10
|
||||
TOTAL_MEMBERS_LIMIT = 50
|
||||
|
||||
_TYPE_CONVERSION = [
|
||||
lambda obj, value, address, name: value.CreateValueFromExpression(name, "(void *){:#x}".format(address)),
|
||||
@@ -192,11 +195,12 @@ def select_provider(lldb_val, tip, internal_dict):
|
||||
return ret
|
||||
|
||||
class KonanHelperProvider(lldb.SBSyntheticValueProvider):
|
||||
def __init__(self, valobj, amString, internal_dict = {}):
|
||||
def __init__(self, valobj, amString, type_name, internal_dict = {}):
|
||||
self._target = lldb.debugger.GetSelectedTarget()
|
||||
self._process = self._target.GetProcess()
|
||||
self._valobj = valobj
|
||||
self._internal_dict = internal_dict.copy()
|
||||
self._type_name = type_name
|
||||
if amString:
|
||||
return
|
||||
if self._children_count == 0:
|
||||
@@ -250,7 +254,7 @@ class KonanStringSyntheticProvider(KonanHelperProvider):
|
||||
def __init__(self, valobj):
|
||||
log(lambda: "KonanStringSyntheticProvider:{:#x} name:{}".format(valobj.unsigned, valobj.name))
|
||||
self._children_count = 0
|
||||
super(KonanStringSyntheticProvider, self).__init__(valobj, True)
|
||||
super(KonanStringSyntheticProvider, self).__init__(valobj, True, "StringProvider")
|
||||
fallback = valobj.GetValue()
|
||||
buff_addr = evaluate("(void *)Konan_DebugBuffer()").unsigned
|
||||
buff_len = evaluate(
|
||||
@@ -296,7 +300,7 @@ class KonanObjectSyntheticProvider(KonanHelperProvider):
|
||||
# Save an extra call into the process
|
||||
log(lambda: "KonanObjectSyntheticProvider({:#x})".format(valobj.unsigned))
|
||||
self._children_count = 0
|
||||
super(KonanObjectSyntheticProvider, self).__init__(valobj, False, internal_dict)
|
||||
super(KonanObjectSyntheticProvider, self).__init__(valobj, False, "ObjectProvider", internal_dict)
|
||||
self._children = [self._field_name(i) for i in range(self._children_count)]
|
||||
log(lambda: "KonanObjectSyntheticProvider::__init__({:#x}) _children:{}".format(self._valobj.unsigned,
|
||||
self._children))
|
||||
@@ -346,7 +350,7 @@ class KonanObjectSyntheticProvider(KonanHelperProvider):
|
||||
class KonanArraySyntheticProvider(KonanHelperProvider):
|
||||
def __init__(self, valobj, internal_dict):
|
||||
self._children_count = 0
|
||||
super(KonanArraySyntheticProvider, self).__init__(valobj, False, internal_dict)
|
||||
super(KonanArraySyntheticProvider, self).__init__(valobj, False, "ArrayProvider", internal_dict)
|
||||
log(lambda: "KonanArraySyntheticProvider: valobj:{:#x}".format(valobj.unsigned))
|
||||
if self._valobj is None:
|
||||
return
|
||||
@@ -452,9 +456,38 @@ class KonanProxyTypeProvider:
|
||||
def __getattr__(self, item):
|
||||
return getattr(self._proxy, item)
|
||||
|
||||
def strip_quotes(name):
|
||||
return "" if (name == None) else name.strip('"')
|
||||
|
||||
def type_name_command(debugger, command, result, internal_dict):
|
||||
result.AppendMessage(evaluate('(char *)Konan_DebugGetTypeName({})'.format(command)).summary)
|
||||
def get_runtime_type(variable):
|
||||
return strip_quotes(evaluate("(char *)Konan_DebugGetTypeName({:#x})".format(variable.unsigned)).summary)
|
||||
|
||||
def field_type_command(debugger, field_address, exe_ctx, result, internal_dict):
|
||||
"""
|
||||
Returns runtime type of foo.bar.baz field in the form "(foo.bar.baz <TYPE_NAME>)".
|
||||
If requested field could not be traced, then "<NO_FIELD_FOUND>" plug is used for type name.
|
||||
"""
|
||||
fields = field_address.split('.')
|
||||
|
||||
variable = exe_ctx.GetFrame().FindVariable(fields[0])
|
||||
provider = None
|
||||
|
||||
for field_name in fields[1:]:
|
||||
if (variable != None):
|
||||
provider = KonanProxyTypeProvider(variable, internal_dict)
|
||||
field_index = provider.get_child_index(field_name)
|
||||
variable = provider.get_child_at_index(field_index)
|
||||
else:
|
||||
break
|
||||
|
||||
desc = "<NO_FIELD_FOUND>"
|
||||
|
||||
if (variable != None):
|
||||
rt = get_runtime_type(variable)
|
||||
if (len(rt) > 0):
|
||||
desc = rt
|
||||
|
||||
result.write("{}".format(desc))
|
||||
|
||||
|
||||
__KONAN_VARIABLE = re.compile('kvar:(.*)#internal')
|
||||
@@ -536,6 +569,64 @@ def konan_globals_command(debugger, command, result, internal_dict):
|
||||
result.AppendMessage('{} {}: {}'.format(type, name, str_value))
|
||||
|
||||
|
||||
class KonanStep(object):
|
||||
def __init__(self, thread_plan):
|
||||
self.thread_plan = thread_plan
|
||||
self.step_thread_plan = self.queue_thread_plan()
|
||||
|
||||
debugger = thread_plan.GetThread().GetProcess().GetTarget().GetDebugger()
|
||||
self.avoid_no_debug = debugger.GetInternalVariableValue('target.process.thread.step-in-avoid-nodebug',
|
||||
debugger.GetInstanceName()).GetStringAtIndex(0)
|
||||
|
||||
def explains_stop(self, event):
|
||||
return True
|
||||
|
||||
def should_stop(self, event):
|
||||
frame = self.thread_plan.GetThread().GetFrameAtIndex(0)
|
||||
source_file = frame.GetLineEntry().GetFileSpec().GetFilename()
|
||||
|
||||
if self.avoid_no_debug == 'true' and source_file in [None, '<compiler-generated>']:
|
||||
self.step_thread_plan = self.queue_thread_plan()
|
||||
return False
|
||||
|
||||
self.thread_plan.SetPlanComplete(True)
|
||||
return True
|
||||
|
||||
def should_step(self):
|
||||
return True
|
||||
|
||||
def queue_thread_plan(self):
|
||||
address = self.thread_plan.GetThread().GetFrameAtIndex(0).GetPCAddress()
|
||||
line_entry = self.thread_plan.GetThread().GetFrameAtIndex(0).GetLineEntry()
|
||||
begin_address = line_entry.GetStartAddress().GetFileAddress()
|
||||
end_address = line_entry.GetEndAddress().GetFileAddress()
|
||||
return self.do_queue_thread_plan(address, end_address - begin_address)
|
||||
|
||||
|
||||
class KonanStepIn(KonanStep):
|
||||
def __init__(self, thread_plan, dict, *args):
|
||||
KonanStep.__init__(self, thread_plan)
|
||||
|
||||
def do_queue_thread_plan(self, address, offset):
|
||||
return self.thread_plan.QueueThreadPlanForStepInRange(address, offset)
|
||||
|
||||
|
||||
class KonanStepOver(KonanStep):
|
||||
def __init__(self, thread_plan, dict, *args):
|
||||
KonanStep.__init__(self, thread_plan)
|
||||
|
||||
def do_queue_thread_plan(self, address, offset):
|
||||
return self.thread_plan.QueueThreadPlanForStepOverRange(address, offset)
|
||||
|
||||
|
||||
class KonanStepOut(KonanStep):
|
||||
def __init__(self, thread_plan, dict, *args):
|
||||
KonanStep.__init__(self, thread_plan)
|
||||
|
||||
def do_queue_thread_plan(self, address, offset):
|
||||
return self.thread_plan.QueueThreadPlanForStepOut(0)
|
||||
|
||||
|
||||
def __lldb_init_module(debugger, _):
|
||||
log(lambda: "init start")
|
||||
__FACTORY['object'] = lambda x, y, z: KonanObjectSyntheticProvider(x, y, z)
|
||||
@@ -556,7 +647,9 @@ def __lldb_init_module(debugger, _):
|
||||
--category Kotlin\
|
||||
')
|
||||
debugger.HandleCommand('type category enable Kotlin')
|
||||
debugger.HandleCommand('command script add -f {}.type_name_command type_name'.format(__name__))
|
||||
debugger.HandleCommand('command script add -f {}.field_type_command field_type'.format(__name__))
|
||||
debugger.HandleCommand('command script add -f {}.type_by_address_command type_by_address'.format(__name__))
|
||||
debugger.HandleCommand('command script add -f {}.symbol_by_name_command symbol_by_name'.format(__name__))
|
||||
# Avoid Kotlin/Native runtime
|
||||
debugger.HandleCommand('settings set target.process.thread.step-avoid-regexp ^::Kotlin_')
|
||||
log(lambda: "init end")
|
||||
|
||||
Reference in New Issue
Block a user