Skip to content

Commit 3e311d5

Browse files
committed
Updates for Xcode 10.2
1 parent b671aa1 commit 3e311d5

File tree

5 files changed

+905
-0
lines changed

5 files changed

+905
-0
lines changed

Kotlin.ideplugin/Contents/Info.plist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
<string>B395D63E-9166-4CD6-9287-6889D507AD6A</string>
3939
<string>26355AE5-C605-4A56-A79B-AD4207EA18DD</string>
4040
<string>D7881182-AD00-4C36-A94D-F45FC9B0CF85</string>
41+
<string>72F7D751-F810-43B8-A53F-1F1DFD74FC54</string>
4142
</array>
4243
<key>XCPluginHasUI</key>
4344
<false/>
Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
#!/usr/bin/python
2+
3+
##
4+
# Copyright 2010-2017 JetBrains s.r.o.
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#
18+
19+
#
20+
# (lldb) command script import llvmDebugInfoC/src/scripts/konan_lldb.py
21+
# (lldb) p kotlin_variable
22+
#
23+
24+
import lldb
25+
import struct
26+
27+
NULL = 'null'
28+
29+
30+
def lldb_val_to_ptr(lldb_val):
31+
addr = lldb_val.GetValueAsUnsigned()
32+
return '((struct ObjHeader *) {:#x})'.format(addr)
33+
34+
35+
def evaluate(expr):
36+
return lldb.debugger.GetSelectedTarget().EvaluateExpression(expr, lldb.SBExpressionOptions())
37+
38+
39+
def is_instance_of(addr, typeinfo):
40+
return evaluate("(bool)IsInstance({}, {})".format(addr, typeinfo)).GetValue() == "true"
41+
42+
43+
def is_string(value):
44+
return is_instance_of(lldb_val_to_ptr(value), "theStringTypeInfo")
45+
46+
47+
def is_array(value):
48+
return int(evaluate("(int)Konan_DebugIsArray({})".format(lldb_val_to_ptr(value))).GetValue()) == 1
49+
50+
51+
def check_type_info(value):
52+
"""This method checks self-referencing of pointer of first member of TypeInfo including case when object has an
53+
meta-object pointed by TypeInfo. Two lower bits are reserved for memory management needs see runtime/src/main/cpp/Memory.h."""
54+
if str(value.type) != "struct ObjHeader *":
55+
return False
56+
expr = "*(void **)((uintptr_t)(*(void**){0}) & ~0x3) == **(void***)((uintptr_t)(*(void**){0}) & ~0x3)".format(value.unsigned)
57+
result = evaluate(expr)
58+
return result.IsValid() and result.GetValue() == "true"
59+
60+
61+
#
62+
# Some kind of forward declaration.
63+
64+
65+
__FACTORY = {}
66+
67+
68+
def kotlin_object_type_summary(lldb_val, internal_dict):
69+
"""Hook that is run by lldb to display a Kotlin object."""
70+
fallback = lldb_val.GetValue()
71+
if str(lldb_val.type) != "struct ObjHeader *":
72+
return fallback
73+
74+
if not check_type_info(lldb_val):
75+
return NULL
76+
77+
ptr = lldb_val_to_ptr(lldb_val)
78+
if ptr is None:
79+
return fallback
80+
81+
return select_provider(lldb_val).to_string()
82+
83+
84+
def select_provider(lldb_val):
85+
return __FACTORY['string'](lldb_val) if is_string(lldb_val) else __FACTORY['array'](lldb_val) if is_array(
86+
lldb_val) else __FACTORY['object'](lldb_val)
87+
88+
89+
class KonanHelperProvider(lldb.SBSyntheticValueProvider):
90+
def __init__(self, valobj):
91+
self._target = lldb.debugger.GetSelectedTarget()
92+
self._process = self._target.GetProcess()
93+
self._valobj = valobj
94+
self._ptr = lldb_val_to_ptr(self._valobj)
95+
if is_string(valobj):
96+
return
97+
self._children_count = int(evaluate("(int)Konan_DebugGetFieldCount({})".format(self._ptr)).GetValue())
98+
self._children = []
99+
self._children_types = []
100+
self._children_type_names = []
101+
self._children_type_addresses = []
102+
self._type_conversion = [
103+
lambda address, name: self._valobj.CreateValueFromExpression(name, "(void *){:#x}".format(address)),
104+
lambda address, name: self._create_synthetic_child(address, name),
105+
lambda address, name: self._valobj.CreateValueFromExpression(name, "(int8_t *){:#x}".format(address)),
106+
lambda address, name: self._valobj.CreateValueFromExpression(name, "(int16_t *){:#x}".format(address)),
107+
lambda address, name: self._valobj.CreateValueFromExpression(name, "(int32_t *){:#x}".format(address)),
108+
lambda address, name: self._valobj.CreateValueFromExpression(name, "(int64_t *){:#x}".format(address)),
109+
lambda address, name: self._valobj.CreateValueFromExpression(name, "(float *){:#x}".format(address)),
110+
lambda address, name: self._valobj.CreateValueFromExpression(name, "(double *){:#x}".format(address)),
111+
lambda address, name: self._valobj.CreateValueFromExpression(name, "(void **){:#x}".format(address)),
112+
lambda address, name: self._valobj.CreateValueFromExpression(name, "(bool *){:#x}".format(address)),
113+
lambda address, name: None]
114+
115+
self._types = [
116+
valobj.GetType().GetBasicType(lldb.eBasicTypeVoid).GetPointerType(),
117+
valobj.GetType(),
118+
valobj.GetType().GetBasicType(lldb.eBasicTypeChar),
119+
valobj.GetType().GetBasicType(lldb.eBasicTypeShort),
120+
valobj.GetType().GetBasicType(lldb.eBasicTypeInt),
121+
valobj.GetType().GetBasicType(lldb.eBasicTypeLongLong),
122+
valobj.GetType().GetBasicType(lldb.eBasicTypeFloat),
123+
valobj.GetType().GetBasicType(lldb.eBasicTypeDouble),
124+
valobj.GetType().GetBasicType(lldb.eBasicTypeVoid).GetPointerType(),
125+
valobj.GetType().GetBasicType(lldb.eBasicTypeBool)
126+
]
127+
self._children_types = [
128+
evaluate("(int)Konan_DebugGetFieldType({}, {})".format(self._ptr, child)).GetValueAsUnsigned()
129+
for child in range(self._children_count)]
130+
self._children_type_addresses = [
131+
int(evaluate("(void *)Konan_DebugGetFieldAddress({}, {})".format(self._ptr, index)).GetValue(), 0) for
132+
index in range(self._children_count)]
133+
134+
def _read_string(self, expr, error):
135+
return self._process.ReadCStringFromMemory(int(evaluate(expr).GetValue(), 0), 0x1000, error)
136+
137+
def _read_value(self, index):
138+
value_type = self._children_types[index]
139+
address = self._children_type_addresses[index]
140+
return self._type_conversion[int(value_type)](address, str(self._children[index]))
141+
142+
def _create_synthetic_child(self, address, name):
143+
index = self.get_child_index(name)
144+
value = self._valobj.CreateChildAtOffset(str(name),
145+
self._children_type_addresses[
146+
index] - self._valobj.GetValueAsUnsigned(),
147+
self._read_type(index))
148+
value.SetSyntheticChildrenGenerated(True)
149+
value.SetPreferSyntheticValue(True)
150+
return value
151+
152+
def _read_type(self, index):
153+
return self._types[int(evaluate("(int)Konan_DebugGetFieldType({}, {})".format(self._ptr, index)).GetValue())]
154+
155+
def _deref_or_obj_summary(self, index):
156+
value = self._values[index]
157+
if not value:
158+
print("_deref_or_obj_summary: value none, index:{}, type:{}".format(index, self._children_types[index]))
159+
return None
160+
if check_type_info(value):
161+
return kotlin_object_type_summary(value, None)
162+
else:
163+
return kotlin_object_type_summary(value.deref, None)
164+
165+
166+
class KonanStringSyntheticProvider(KonanHelperProvider):
167+
def __init__(self, valobj):
168+
super(KonanStringSyntheticProvider, self).__init__(valobj)
169+
fallback = valobj.GetValue()
170+
buff_len = evaluate(
171+
'(int)Konan_DebugObjectToUtf8Array({}, (char *)Konan_DebugBuffer(), (int)Konan_DebugBufferSize());'.format(
172+
self._ptr)
173+
).unsigned
174+
175+
if not buff_len:
176+
self._representation = fallback
177+
return
178+
179+
buff_addr = evaluate("(char *)Konan_DebugBuffer()").unsigned
180+
181+
error = lldb.SBError()
182+
s = self._process.ReadCStringFromMemory(int(buff_addr), int(buff_len), error)
183+
if not error.Success():
184+
raise DebuggerException()
185+
self._representation = s if error.Success() else fallback
186+
self._logger = lldb.formatters.Logger.Logger()
187+
188+
def update(self):
189+
pass
190+
191+
def num_children(self):
192+
return 0
193+
194+
def has_children(self):
195+
return False
196+
197+
def get_child_index(self, _):
198+
return None
199+
200+
def get_child_at_index(self, _):
201+
return None
202+
203+
def to_string(self):
204+
return self._representation
205+
206+
207+
class DebuggerException(Exception):
208+
pass
209+
210+
211+
class KonanObjectSyntheticProvider(KonanHelperProvider):
212+
def __init__(self, valobj):
213+
super(KonanObjectSyntheticProvider, self).__init__(valobj)
214+
error = lldb.SBError()
215+
self._children = [
216+
self._read_string("(const char *)Konan_DebugGetFieldName({}, (int){})".format(self._ptr, i), error) for i in
217+
range(self._children_count) if error.Success()]
218+
if not error.Success():
219+
raise DebuggerException()
220+
self._values = [self._read_value(index) for index in range(self._children_count)]
221+
222+
def num_children(self):
223+
return self._children_count
224+
225+
def has_children(self):
226+
return self._children_count > 0
227+
228+
def get_child_index(self, name):
229+
if not name in self._children:
230+
return -1
231+
return self._children.index(name)
232+
233+
def get_child_at_index(self, index):
234+
return self._values[index]
235+
236+
# TODO: fix cyclic structures stringification.
237+
def to_string(self):
238+
return dict([(self._children[i], self._deref_or_obj_summary(i)) for i in range(self._children_count)])
239+
240+
241+
class KonanArraySyntheticProvider(KonanHelperProvider):
242+
def __init__(self, valobj):
243+
super(KonanArraySyntheticProvider, self).__init__(valobj)
244+
if self._ptr is None:
245+
return
246+
valobj.SetSyntheticChildrenGenerated(True)
247+
self._children = [x for x in range(self.num_children())]
248+
self._values = [self._read_value(i) for i in range(self._children_count)]
249+
250+
def num_children(self):
251+
return self._children_count
252+
253+
def has_children(self):
254+
return self._children_count > 0
255+
256+
def get_child_index(self, name):
257+
index = int(name)
258+
return index if (0 <= index < self._children_count) else -1
259+
260+
def get_child_at_index(self, index):
261+
return self._read_value(index)
262+
263+
def to_string(self):
264+
return [self._deref_or_obj_summary(i) for i in range(self._children_count)]
265+
266+
267+
class KonanProxyTypeProvider:
268+
def __init__(self, valobj, _):
269+
if not check_type_info(valobj):
270+
return
271+
self._proxy = select_provider(valobj)
272+
self.update()
273+
274+
def __getattr__(self, item):
275+
return getattr(self._proxy, item)
276+
277+
def print_this_command(debugger, command, result, internal_dict):
278+
pthis = lldb.frame.FindVariable('<this>')
279+
print(pthis)
280+
281+
def __lldb_init_module(debugger, _):
282+
__FACTORY['object'] = lambda x: KonanObjectSyntheticProvider(x)
283+
__FACTORY['array'] = lambda x: KonanArraySyntheticProvider(x)
284+
__FACTORY['string'] = lambda x: KonanStringSyntheticProvider(x)
285+
debugger.HandleCommand('\
286+
type summary add \
287+
--no-value \
288+
--expand \
289+
--python-function konan_lldb.kotlin_object_type_summary \
290+
"struct ObjHeader *" \
291+
--category Kotlin\
292+
')
293+
debugger.HandleCommand('\
294+
type synthetic add \
295+
--python-class konan_lldb.KonanProxyTypeProvider\
296+
"ObjHeader *" \
297+
--category Kotlin\
298+
')
299+
debugger.HandleCommand('type category enable Kotlin')
300+
debugger.HandleCommand('command script add -f {}.print_this_command print_this'.format(__name__))

0 commit comments

Comments
 (0)