| 
									
										
										
										
											2013-09-11 21:35:39 +02:00
										 |  |  | ############################################################################ | 
					
						
							|  |  |  | # | 
					
						
							| 
									
										
										
										
											2016-01-15 14:53:55 +01:00
										 |  |  | # Copyright (C) 2016 The Qt Company Ltd. | 
					
						
							|  |  |  | # Contact: https://www.qt.io/licensing/ | 
					
						
							| 
									
										
										
										
											2013-09-11 21:35:39 +02:00
										 |  |  | # | 
					
						
							|  |  |  | # This file is part of Qt Creator. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Commercial License Usage | 
					
						
							|  |  |  | # Licensees holding valid commercial Qt licenses may use this file in | 
					
						
							|  |  |  | # accordance with the commercial license agreement provided with the | 
					
						
							|  |  |  | # Software or, alternatively, in accordance with the terms contained in | 
					
						
							| 
									
										
										
										
											2016-01-15 14:53:55 +01:00
										 |  |  | # a written agreement between you and The Qt Company. For licensing terms | 
					
						
							|  |  |  | # and conditions see https://www.qt.io/terms-conditions. For further | 
					
						
							|  |  |  | # information use the contact form at https://www.qt.io/contact-us. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # GNU General Public License Usage | 
					
						
							|  |  |  | # Alternatively, this file may be used under the terms of the GNU | 
					
						
							|  |  |  | # General Public License version 3 as published by the Free Software | 
					
						
							|  |  |  | # Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT | 
					
						
							|  |  |  | # included in the packaging of this file. Please review the following | 
					
						
							|  |  |  | # information to ensure the GNU General Public License requirements will | 
					
						
							|  |  |  | # be met: https://www.gnu.org/licenses/gpl-3.0.html. | 
					
						
							| 
									
										
										
										
											2013-09-11 21:35:39 +02:00
										 |  |  | # | 
					
						
							| 
									
										
										
										
											2016-01-15 14:53:55 +01:00
										 |  |  | ############################################################################ | 
					
						
							| 
									
										
										
										
											2013-04-11 17:06:17 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | import inspect | 
					
						
							|  |  |  | import os | 
					
						
							| 
									
										
										
										
											2014-02-10 17:38:58 +01:00
										 |  |  | import platform | 
					
						
							| 
									
										
										
										
											2013-10-21 12:02:57 +02:00
										 |  |  | import re | 
					
						
							| 
									
										
										
										
											2013-05-13 16:04:00 +02:00
										 |  |  | import sys | 
					
						
							| 
									
										
										
										
											2013-10-21 12:02:57 +02:00
										 |  |  | import threading | 
					
						
							| 
									
										
										
										
											2020-01-13 11:02:27 +01:00
										 |  |  | import time | 
					
						
							| 
									
										
										
										
											2015-01-30 12:36:04 +01:00
										 |  |  | import lldb | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  | import utils | 
					
						
							| 
									
										
										
										
											2020-05-07 17:35:34 +02:00
										 |  |  | from utils import DebuggerStartMode, BreakpointType, TypeCode, LogChannel | 
					
						
							| 
									
										
										
										
											2013-05-16 15:09:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  | from contextlib import contextmanager | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-13 10:02:35 +01:00
										 |  |  | sys.path.insert(1, os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))) | 
					
						
							| 
									
										
										
										
											2013-09-11 21:35:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  | # Simplify development of this module by reloading deps | 
					
						
							|  |  |  | if 'dumper' in sys.modules: | 
					
						
							| 
									
										
										
										
											2020-05-13 11:31:19 +02:00
										 |  |  |     if sys.version_info[0] >= 3: | 
					
						
							|  |  |  |         if sys.version_info[1] > 3: | 
					
						
							|  |  |  |             from importlib import reload | 
					
						
							|  |  |  |         else: | 
					
						
							| 
									
										
										
										
											2020-06-11 14:46:09 +02:00
										 |  |  |             def reload(m): print('Unsupported Python version - not reloading %s' % str(m)) | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  |     reload(sys.modules['dumper']) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-24 10:14:27 +01:00
										 |  |  | from dumper import DumperBase, SubItem, Children, TopLevelItem | 
					
						
							| 
									
										
										
										
											2013-09-11 21:35:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-11 17:06:17 +02:00
										 |  |  | ####################################################################### | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Helpers | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | ####################################################################### | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-14 15:15:09 +02:00
										 |  |  | qqWatchpointOffset = 10000 | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  | _c_str_trans = None | 
					
						
							| 
									
										
										
										
											2013-05-15 15:30:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  | if sys.version_info[0] >= 3: | 
					
						
							|  |  |  |     _c_str_trans = str.maketrans({"\n": "\\n", '"':'\\"', "\\":"\\\\"}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def toCString(s): | 
					
						
							|  |  |  |     if _c_str_trans is not None: | 
					
						
							|  |  |  |         return str(s).translate(_c_str_trans) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         return str(s).replace('\\', '\\\\').replace('\n', '\\n').replace('"', '\\"') | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-08 16:19:57 +02:00
										 |  |  | def fileNameAsString(file): | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |     return toCString(file) if file.IsValid() else '' | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-11 17:06:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-07 16:43:20 +02:00
										 |  |  | def check(exp): | 
					
						
							|  |  |  |     if not exp: | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |         raise RuntimeError('Check failed') | 
					
						
							| 
									
										
										
										
											2013-05-07 16:43:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-11 21:35:39 +02:00
										 |  |  | class Dumper(DumperBase): | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |     def __init__(self, debugger=None): | 
					
						
							| 
									
										
										
										
											2013-09-11 21:35:39 +02:00
										 |  |  |         DumperBase.__init__(self) | 
					
						
							| 
									
										
										
										
											2016-04-13 18:19:45 +02:00
										 |  |  |         lldb.theDumper = self | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-07 12:23:35 +02:00
										 |  |  |         self.isLldb = True | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |         self.typeCache = {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-19 12:08:25 +01:00
										 |  |  |         self.outputLock = threading.Lock() | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if debugger: | 
					
						
							|  |  |  |             # Re-use existing debugger | 
					
						
							|  |  |  |             self.debugger = debugger | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.debugger = lldb.SBDebugger.Create() | 
					
						
							|  |  |  |             #self.debugger.SetLoggingCallback(loggingCallback) | 
					
						
							|  |  |  |             #def loggingCallback(args): | 
					
						
							|  |  |  |             #    s = args.strip() | 
					
						
							|  |  |  |             #    s = s.replace('"', "'") | 
					
						
							|  |  |  |             #    sys.stdout.write('log="%s"@\n' % s) | 
					
						
							|  |  |  |             #Same as: self.debugger.HandleCommand('log enable lldb dyld step') | 
					
						
							|  |  |  |             #self.debugger.EnableLog('lldb', ['dyld', 'step', 'process', 'state', | 
					
						
							|  |  |  |             #    'thread', 'events', | 
					
						
							|  |  |  |             #    'communication', 'unwind', 'commands']) | 
					
						
							|  |  |  |             #self.debugger.EnableLog('lldb', ['all']) | 
					
						
							|  |  |  |             self.debugger.Initialize() | 
					
						
							| 
									
										
										
										
											2019-09-25 13:15:26 +02:00
										 |  |  |             self.debugger.SetAsync(True) | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  |             self.debugger.HandleCommand('settings set auto-confirm on') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # FIXME: warn('DISABLING DEFAULT FORMATTERS') | 
					
						
							|  |  |  |             # It doesn't work at all with 179.5 and we have some bad | 
					
						
							|  |  |  |             # interaction in 300 | 
					
						
							|  |  |  |             # if not hasattr(lldb.SBType, 'GetCanonicalType'): # 'Test' for 179.5 | 
					
						
							|  |  |  |             #self.debugger.HandleCommand('type category delete gnu-libstdc++') | 
					
						
							|  |  |  |             #self.debugger.HandleCommand('type category delete libcxx') | 
					
						
							|  |  |  |             #self.debugger.HandleCommand('type category delete default') | 
					
						
							|  |  |  |             self.debugger.DeleteCategory('gnu-libstdc++') | 
					
						
							|  |  |  |             self.debugger.DeleteCategory('libcxx') | 
					
						
							|  |  |  |             self.debugger.DeleteCategory('default') | 
					
						
							|  |  |  |             self.debugger.DeleteCategory('cplusplus') | 
					
						
							|  |  |  |             #for i in range(self.debugger.GetNumCategories()): | 
					
						
							|  |  |  |             #    self.debugger.GetCategoryAtIndex(i).SetEnabled(False) | 
					
						
							| 
									
										
										
										
											2013-11-01 14:18:10 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |         self.process = None | 
					
						
							|  |  |  |         self.target = None | 
					
						
							| 
									
										
										
										
											2020-09-07 14:00:09 +02:00
										 |  |  |         self.fakeAddress_ = None | 
					
						
							|  |  |  |         self.fakeLAddress_ = None | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |         self.eventState = lldb.eStateInvalid | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-22 14:30:36 +02:00
										 |  |  |         self.executable_ = None | 
					
						
							| 
									
										
										
										
											2020-04-02 17:58:24 +02:00
										 |  |  |         self.symbolFile_ = None | 
					
						
							| 
									
										
										
										
											2013-10-01 02:30:12 +02:00
										 |  |  |         self.startMode_ = None | 
					
						
							|  |  |  |         self.processArgs_ = None | 
					
						
							|  |  |  |         self.attachPid_ = None | 
					
						
							| 
									
										
										
										
											2015-12-08 16:58:20 +01:00
										 |  |  |         self.dyldImageSuffix = None | 
					
						
							|  |  |  |         self.dyldLibraryPath = None | 
					
						
							|  |  |  |         self.dyldFrameworkPath = None | 
					
						
							| 
									
										
										
										
											2013-10-01 02:30:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-29 15:38:49 +02:00
										 |  |  |         self.isShuttingDown_ = False | 
					
						
							| 
									
										
										
										
											2013-06-24 17:40:00 +02:00
										 |  |  |         self.isInterrupting_ = False | 
					
						
							| 
									
										
										
										
											2015-10-09 15:00:20 +02:00
										 |  |  |         self.interpreterBreakpointResolvers = [] | 
					
						
							| 
									
										
										
										
											2013-05-17 13:53:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 17:35:34 +02:00
										 |  |  |         DumperBase.warn = Dumper.warn_impl | 
					
						
							| 
									
										
										
										
											2015-02-13 10:02:35 +01:00
										 |  |  |         self.report('lldbversion=\"%s\"' % lldb.SBDebugger.GetVersionString()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 17:35:34 +02:00
										 |  |  |     @staticmethod | 
					
						
							|  |  |  |     def warn_impl(message): | 
					
						
							|  |  |  |         if message[-1:] == '\n': | 
					
						
							|  |  |  |             message += '\n' | 
					
						
							|  |  |  |         print('@\nbridgemessage={msg="%s",channel="%s"}\n@' | 
					
						
							|  |  |  |                 % (message.replace('"', '$'), LogChannel.AppError)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |     def fromNativeFrameValue(self, nativeValue): | 
					
						
							|  |  |  |         return self.fromNativeValue(nativeValue) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-06 08:54:43 +02:00
										 |  |  |     def fromNativeValue(self, nativeValue): | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |         self.check(isinstance(nativeValue, lldb.SBValue)) | 
					
						
							| 
									
										
										
										
											2016-09-26 14:29:16 +02:00
										 |  |  |         nativeType = nativeValue.GetType() | 
					
						
							| 
									
										
										
										
											2017-08-15 15:17:12 +02:00
										 |  |  |         typeName = nativeType.GetName() | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |         code = nativeType.GetTypeClass() | 
					
						
							| 
									
										
										
										
											2017-05-15 16:54:07 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 15:17:12 +02:00
										 |  |  |         # Display the result of GetSummary() for Core Foundation string | 
					
						
							|  |  |  |         # and string-like types. | 
					
						
							|  |  |  |         summary = None | 
					
						
							|  |  |  |         if self.useFancy: | 
					
						
							|  |  |  |             if (typeName.startswith('CF') | 
					
						
							|  |  |  |                     or typeName.startswith('__CF') | 
					
						
							|  |  |  |                     or typeName.startswith('NS') | 
					
						
							|  |  |  |                     or typeName.startswith('__NSCF')): | 
					
						
							|  |  |  |                 if code == lldb.eTypeClassPointer: | 
					
						
							|  |  |  |                     summary = nativeValue.Dereference().GetSummary() | 
					
						
							|  |  |  |                 elif code == lldb.eTypeClassReference: | 
					
						
							|  |  |  |                     summary = nativeValue.Dereference().GetSummary() | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     summary = nativeValue.GetSummary() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         nativeValue.SetPreferSyntheticValue(False) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |         if code == lldb.eTypeClassReference: | 
					
						
							|  |  |  |             nativeTargetType = nativeType.GetDereferencedType() | 
					
						
							|  |  |  |             if not nativeTargetType.IsPointerType(): | 
					
						
							|  |  |  |                 nativeTargetType = nativeTargetType.GetUnqualifiedType() | 
					
						
							|  |  |  |             targetType = self.fromNativeType(nativeTargetType) | 
					
						
							|  |  |  |             val = self.createReferenceValue(nativeValue.GetValueAsUnsigned(), targetType) | 
					
						
							|  |  |  |             val.laddress = nativeValue.AddressOf().GetValueAsUnsigned() | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             #DumperBase.warn('CREATED REF: %s' % val) | 
					
						
							| 
									
										
										
										
											2017-05-15 16:54:07 +02:00
										 |  |  |         elif code == lldb.eTypeClassPointer: | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             nativeTargetType = nativeType.GetPointeeType() | 
					
						
							|  |  |  |             if not nativeTargetType.IsPointerType(): | 
					
						
							|  |  |  |                 nativeTargetType = nativeTargetType.GetUnqualifiedType() | 
					
						
							|  |  |  |             targetType = self.fromNativeType(nativeTargetType) | 
					
						
							|  |  |  |             val = self.createPointerValue(nativeValue.GetValueAsUnsigned(), targetType) | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             #DumperBase.warn('CREATED PTR 1: %s' % val) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             val.laddress = nativeValue.AddressOf().GetValueAsUnsigned() | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             #DumperBase.warn('CREATED PTR 2: %s' % val) | 
					
						
							| 
									
										
										
										
											2017-05-15 16:54:07 +02:00
										 |  |  |         elif code == lldb.eTypeClassTypedef: | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             nativeTargetType = nativeType.GetUnqualifiedType() | 
					
						
							|  |  |  |             if hasattr(nativeTargetType, 'GetCanonicalType'): | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                 nativeTargetType = nativeTargetType.GetCanonicalType() | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             val = self.fromNativeValue(nativeValue.Cast(nativeTargetType)) | 
					
						
							| 
									
										
										
										
											2021-01-19 16:02:48 +01:00
										 |  |  |             val._type = self.fromNativeType(nativeType) | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             #DumperBase.warn('CREATED TYPEDEF: %s' % val) | 
					
						
							| 
									
										
										
										
											2017-05-15 16:54:07 +02:00
										 |  |  |         else: | 
					
						
							|  |  |  |             val = self.Value(self) | 
					
						
							|  |  |  |             address = nativeValue.GetLoadAddress() | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |             if address is not None: | 
					
						
							| 
									
										
										
										
											2017-05-15 16:54:07 +02:00
										 |  |  |                 val.laddress = address | 
					
						
							|  |  |  |             if True: | 
					
						
							|  |  |  |                 data = nativeValue.GetData() | 
					
						
							|  |  |  |                 error = lldb.SBError() | 
					
						
							|  |  |  |                 size = nativeValue.GetType().GetByteSize() | 
					
						
							|  |  |  |                 if size > 1: | 
					
						
							|  |  |  |                     # 0 happens regularly e.g. for cross-shared-object types. | 
					
						
							|  |  |  |                     # 1 happens on Linux e.g. for QObject uses outside of QtCore. | 
					
						
							|  |  |  |                     try: | 
					
						
							|  |  |  |                         val.ldata = data.ReadRawData(error, 0, size) | 
					
						
							|  |  |  |                     except: | 
					
						
							|  |  |  |                         pass | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-19 16:02:48 +01:00
										 |  |  |             val._type = self.fromNativeType(nativeType) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-15 16:54:07 +02:00
										 |  |  |             if code == lldb.eTypeClassEnumeration: | 
					
						
							|  |  |  |                 intval = nativeValue.GetValueAsSigned() | 
					
						
							| 
									
										
										
										
											2020-12-11 08:42:58 +01:00
										 |  |  |                 display = str(nativeValue).split(' = ') | 
					
						
							|  |  |  |                 if len(display) == 2: | 
					
						
							|  |  |  |                     verbose = display[1] | 
					
						
							|  |  |  |                     if '|' in verbose and not verbose.startswith('('): | 
					
						
							|  |  |  |                         verbose = '(' + verbose + ')' | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     verbose = intval | 
					
						
							|  |  |  |                 val.ldisplay = '%s (%d)' % (verbose, intval) | 
					
						
							| 
									
										
										
										
											2017-05-15 16:54:07 +02:00
										 |  |  |             elif code in (lldb.eTypeClassComplexInteger, lldb.eTypeClassComplexFloat): | 
					
						
							|  |  |  |                 val.ldisplay = str(nativeValue.GetValue()) | 
					
						
							|  |  |  |             #elif code == lldb.eTypeClassArray: | 
					
						
							|  |  |  |             #    if hasattr(nativeType, 'GetArrayElementType'): # New in 3.8(?) / 350.x | 
					
						
							|  |  |  |             #        val.type.ltarget = self.fromNativeType(nativeType.GetArrayElementType()) | 
					
						
							|  |  |  |             #    else: | 
					
						
							|  |  |  |             #        fields = nativeType.get_fields_array() | 
					
						
							|  |  |  |             #        if len(fields): | 
					
						
							|  |  |  |             #            val.type.ltarget = self.fromNativeType(fields[0]) | 
					
						
							|  |  |  |             #elif code == lldb.eTypeClassVector: | 
					
						
							|  |  |  |             #    val.type.ltarget = self.fromNativeType(nativeType.GetVectorElementType()) | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 15:17:12 +02:00
										 |  |  |         val.summary = summary | 
					
						
							| 
									
										
										
										
											2017-05-15 16:54:07 +02:00
										 |  |  |         val.lIsInScope = nativeValue.IsInScope() | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  |         val.name = nativeValue.GetName() | 
					
						
							| 
									
										
										
										
											2016-09-06 08:54:43 +02:00
										 |  |  |         return val | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  |     def nativeStructAlignment(self, nativeType): | 
					
						
							|  |  |  |         def handleItem(nativeFieldType, align): | 
					
						
							|  |  |  |             a = self.fromNativeType(nativeFieldType).alignment() | 
					
						
							|  |  |  |             return a if a > align else align | 
					
						
							|  |  |  |         align = 1 | 
					
						
							|  |  |  |         for i in range(nativeType.GetNumberOfDirectBaseClasses()): | 
					
						
							|  |  |  |             base = nativeType.GetDirectBaseClassAtIndex(i) | 
					
						
							|  |  |  |             align = handleItem(base.GetType(), align) | 
					
						
							|  |  |  |         for i in range(nativeType.GetNumberOfFields()): | 
					
						
							|  |  |  |             child = nativeType.GetFieldAtIndex(i) | 
					
						
							|  |  |  |             align = handleItem(child.GetType(), align) | 
					
						
							|  |  |  |         return align | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-08 16:37:52 +01:00
										 |  |  |     def listMembers(self, value, nativeType): | 
					
						
							| 
									
										
										
										
											2020-09-07 14:00:09 +02:00
										 |  |  |         #DumperBase.warn("ADDR: 0x%x" % self.fakeAddress_) | 
					
						
							|  |  |  |         if value.laddress: | 
					
						
							|  |  |  |             fakeAddress = lldb.SBAddress(value.laddress, self.target) | 
					
						
							|  |  |  |             fakeLAddress = value.laddress | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             fakeAddress = self.fakeAddress_ | 
					
						
							|  |  |  |             fakeLAddress = self.fakeLAddress_ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         fakeValue = self.target.CreateValueFromAddress('x', fakeAddress, nativeType) | 
					
						
							| 
									
										
										
										
											2016-11-07 08:57:26 +01:00
										 |  |  |         fakeValue.SetPreferSyntheticValue(False) | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         baseNames = {} | 
					
						
							|  |  |  |         for i in range(nativeType.GetNumberOfDirectBaseClasses()): | 
					
						
							|  |  |  |             base = nativeType.GetDirectBaseClassAtIndex(i) | 
					
						
							|  |  |  |             baseNames[base.GetName()] = i | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         fieldBits = {} | 
					
						
							|  |  |  |         for f in nativeType.get_fields_array(): | 
					
						
							|  |  |  |             bitsize = f.GetBitfieldSizeInBits() | 
					
						
							|  |  |  |             if bitsize == 0: | 
					
						
							|  |  |  |                 bitsize = f.GetType().GetByteSize() * 8 | 
					
						
							|  |  |  |             bitpos = f.GetOffsetInBits() | 
					
						
							| 
									
										
										
										
											2016-11-15 11:56:18 +01:00
										 |  |  |             fieldBits[f.name] = (bitsize, bitpos, f.IsBitfield()) | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # Normal members and non-empty base classes. | 
					
						
							| 
									
										
										
										
											2017-03-08 16:37:52 +01:00
										 |  |  |         anonNumber = 0 | 
					
						
							| 
									
										
										
										
											2016-11-07 08:57:26 +01:00
										 |  |  |         for i in range(fakeValue.GetNumChildren()): | 
					
						
							|  |  |  |             nativeField = fakeValue.GetChildAtIndex(i) | 
					
						
							|  |  |  |             nativeField.SetPreferSyntheticValue(False) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-08 16:37:52 +01:00
										 |  |  |             fieldName = nativeField.GetName() | 
					
						
							| 
									
										
										
										
											2016-11-07 08:57:26 +01:00
										 |  |  |             nativeFieldType = nativeField.GetType() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-08 16:37:52 +01:00
										 |  |  |             if fieldName in fieldBits: | 
					
						
							|  |  |  |                 (fieldBitsize, fieldBitpos, isBitfield) = fieldBits[fieldName] | 
					
						
							| 
									
										
										
										
											2016-11-07 08:57:26 +01:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2017-03-08 16:37:52 +01:00
										 |  |  |                 fieldBitsize = nativeFieldType.GetByteSize() * 8 | 
					
						
							| 
									
										
										
										
											2018-11-01 15:24:17 +01:00
										 |  |  |                 fieldBitpos = None | 
					
						
							| 
									
										
										
										
											2016-11-15 11:56:18 +01:00
										 |  |  |                 isBitfield = False | 
					
						
							| 
									
										
										
										
											2016-11-07 08:57:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |             if isBitfield:  # Bit fields | 
					
						
							| 
									
										
										
										
											2017-06-02 15:04:40 +03:00
										 |  |  |                 fieldType = self.createBitfieldType( | 
					
						
							|  |  |  |                     self.createType(self.typeName(nativeFieldType)), fieldBitsize) | 
					
						
							| 
									
										
										
										
											2017-03-08 16:37:52 +01:00
										 |  |  |                 yield self.Field(self, name=fieldName, type=fieldType, | 
					
						
							|  |  |  |                                  bitsize=fieldBitsize, bitpos=fieldBitpos) | 
					
						
							| 
									
										
										
										
											2016-11-25 11:35:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |             elif fieldName is None:  # Anon members | 
					
						
							| 
									
										
										
										
											2017-03-08 16:37:52 +01:00
										 |  |  |                 anonNumber += 1 | 
					
						
							|  |  |  |                 fieldName = '#%s' % anonNumber | 
					
						
							| 
									
										
										
										
											2016-11-07 08:57:26 +01:00
										 |  |  |                 fakeMember = fakeValue.GetChildAtIndex(i) | 
					
						
							|  |  |  |                 fakeMemberAddress = fakeMember.GetLoadAddress() | 
					
						
							| 
									
										
										
										
											2020-09-07 14:00:09 +02:00
										 |  |  |                 offset = fakeMemberAddress - fakeLAddress | 
					
						
							| 
									
										
										
										
											2017-03-08 16:37:52 +01:00
										 |  |  |                 yield self.Field(self, name=fieldName, type=self.fromNativeType(nativeFieldType), | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                                  bitsize=fieldBitsize, bitpos=8 * offset) | 
					
						
							| 
									
										
										
										
											2016-11-07 08:57:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-08 16:37:52 +01:00
										 |  |  |             elif fieldName in baseNames:  # Simple bases | 
					
						
							| 
									
										
										
										
											2016-11-25 11:35:31 +01:00
										 |  |  |                 member = self.fromNativeValue(fakeValue.GetChildAtIndex(i)) | 
					
						
							|  |  |  |                 member.isBaseClass = True | 
					
						
							|  |  |  |                 yield member | 
					
						
							| 
									
										
										
										
											2016-11-07 08:57:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |             else:  # Normal named members | 
					
						
							| 
									
										
										
										
											2016-11-25 11:35:31 +01:00
										 |  |  |                 member = self.fromNativeValue(fakeValue.GetChildAtIndex(i)) | 
					
						
							|  |  |  |                 member.name = nativeField.GetName() | 
					
						
							|  |  |  |                 yield member | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # Empty bases are not covered above. | 
					
						
							|  |  |  |         for i in range(nativeType.GetNumberOfDirectBaseClasses()): | 
					
						
							|  |  |  |             fieldObj = nativeType.GetDirectBaseClassAtIndex(i) | 
					
						
							|  |  |  |             fieldType = fieldObj.GetType() | 
					
						
							|  |  |  |             if fieldType.GetNumberOfFields() == 0: | 
					
						
							|  |  |  |                 if fieldType.GetNumberOfDirectBaseClasses() == 0: | 
					
						
							|  |  |  |                     member = self.Value(self) | 
					
						
							|  |  |  |                     fieldName = fieldObj.GetName() | 
					
						
							| 
									
										
										
										
											2021-01-19 16:02:48 +01:00
										 |  |  |                     member._type = self.fromNativeType(fieldType) | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  |                     member.name = fieldName | 
					
						
							|  |  |  |                     member.fields = [] | 
					
						
							| 
									
										
										
										
											2016-11-18 18:07:11 +01:00
										 |  |  |                     if False: | 
					
						
							|  |  |  |                         # This would be correct if we came here only for | 
					
						
							|  |  |  |                         # truly empty base classes. Alas, we don't, see below. | 
					
						
							|  |  |  |                         member.ldata = bytes() | 
					
						
							|  |  |  |                         member.lbitsize = fieldType.GetByteSize() * 8 | 
					
						
							|  |  |  |                     else: | 
					
						
							|  |  |  |                         # This is a hack. LLDB 3.8 reports declared but not defined | 
					
						
							|  |  |  |                         # types as having no fields and(!) size == 1. At least | 
					
						
							|  |  |  |                         # for the common case of a single base class we can | 
					
						
							|  |  |  |                         # fake the contents by using the whole derived object's | 
					
						
							|  |  |  |                         # data as base class data. | 
					
						
							|  |  |  |                         data = fakeValue.GetData() | 
					
						
							|  |  |  |                         size = nativeType.GetByteSize() | 
					
						
							|  |  |  |                         member.lbitsize = size * 8 | 
					
						
							|  |  |  |                         error = lldb.SBError() | 
					
						
							|  |  |  |                         member.laddress = value.laddress | 
					
						
							|  |  |  |                         member.ldata = data.ReadRawData(error, 0, size) | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  |                     member.isBaseClass = True | 
					
						
							|  |  |  |                     member.ltype = self.fromNativeType(fieldType) | 
					
						
							|  |  |  |                     member.name = fieldName | 
					
						
							|  |  |  |                     yield member | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |     def ptrSize(self): | 
					
						
							|  |  |  |         result = self.target.GetAddressByteSize() | 
					
						
							|  |  |  |         self.ptrSize = lambda: result | 
					
						
							|  |  |  |         return result | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-06 08:54:43 +02:00
										 |  |  |     def fromNativeType(self, nativeType): | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |         self.check(isinstance(nativeType, lldb.SBType)) | 
					
						
							| 
									
										
										
										
											2016-09-06 08:54:43 +02:00
										 |  |  |         code = nativeType.GetTypeClass() | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  |         # eTypeClassInvalid           = (0u), | 
					
						
							|  |  |  |         # eTypeClassArray             = (1u << 0), | 
					
						
							|  |  |  |         # eTypeClassBlockPointer      = (1u << 1), | 
					
						
							|  |  |  |         # eTypeClassBuiltin           = (1u << 2), | 
					
						
							|  |  |  |         # eTypeClassClass             = (1u << 3), | 
					
						
							|  |  |  |         # eTypeClassComplexFloat      = (1u << 4), | 
					
						
							|  |  |  |         # eTypeClassComplexInteger    = (1u << 5), | 
					
						
							|  |  |  |         # eTypeClassEnumeration       = (1u << 6), | 
					
						
							|  |  |  |         # eTypeClassFunction          = (1u << 7), | 
					
						
							|  |  |  |         # eTypeClassMemberPointer     = (1u << 8), | 
					
						
							|  |  |  |         # eTypeClassObjCObject        = (1u << 9), | 
					
						
							|  |  |  |         # eTypeClassObjCInterface     = (1u << 10), | 
					
						
							|  |  |  |         # eTypeClassObjCObjectPointer = (1u << 11), | 
					
						
							|  |  |  |         # eTypeClassPointer           = (1u << 12), | 
					
						
							|  |  |  |         # eTypeClassReference         = (1u << 13), | 
					
						
							|  |  |  |         # eTypeClassStruct            = (1u << 14), | 
					
						
							|  |  |  |         # eTypeClassTypedef           = (1u << 15), | 
					
						
							|  |  |  |         # eTypeClassUnion             = (1u << 16), | 
					
						
							|  |  |  |         # eTypeClassVector            = (1u << 17), | 
					
						
							|  |  |  |         # // Define the last type class as the MSBit of a 32 bit value | 
					
						
							|  |  |  |         # eTypeClassOther             = (1u << 31), | 
					
						
							|  |  |  |         # // Define a mask that can be used for any type when finding types | 
					
						
							|  |  |  |         # eTypeClassAny               = (0xffffffffu) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |         #DumperBase.warn('CURRENT: %s' % self.typeData.keys()) | 
					
						
							|  |  |  |         #DumperBase.warn('FROM NATIVE TYPE: %s' % nativeType.GetName()) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |         if code == lldb.eTypeClassInvalid: | 
					
						
							|  |  |  |             return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if code == lldb.eTypeClassBuiltin: | 
					
						
							|  |  |  |             nativeType = nativeType.GetUnqualifiedType() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if code == lldb.eTypeClassPointer: | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             #DumperBase.warn('PTR') | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             nativeTargetType = nativeType.GetPointeeType() | 
					
						
							|  |  |  |             if not nativeTargetType.IsPointerType(): | 
					
						
							|  |  |  |                 nativeTargetType = nativeTargetType.GetUnqualifiedType() | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             #DumperBase.warn('PTR: %s' % nativeTargetType.name) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             return self.createPointerType(self.fromNativeType(nativeTargetType)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if code == lldb.eTypeClassReference: | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             #DumperBase.warn('REF') | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             nativeTargetType = nativeType.GetDereferencedType() | 
					
						
							|  |  |  |             if not nativeTargetType.IsPointerType(): | 
					
						
							|  |  |  |                 nativeTargetType = nativeTargetType.GetUnqualifiedType() | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             #DumperBase.warn('REF: %s' % nativeTargetType.name) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             return self.createReferenceType(self.fromNativeType(nativeTargetType)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  |         if code == lldb.eTypeClassTypedef: | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             #DumperBase.warn('TYPEDEF') | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  |             nativeTargetType = nativeType.GetUnqualifiedType() | 
					
						
							|  |  |  |             if hasattr(nativeTargetType, 'GetCanonicalType'): | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                 nativeTargetType = nativeTargetType.GetCanonicalType() | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  |             targetType = self.fromNativeType(nativeTargetType) | 
					
						
							| 
									
										
										
										
											2020-12-11 10:46:38 +01:00
										 |  |  |             return self.createTypedefedType(targetType, nativeType.GetName(), | 
					
						
							|  |  |  |                                             self.nativeTypeId(nativeType)) | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         nativeType = nativeType.GetUnqualifiedType() | 
					
						
							| 
									
										
										
										
											2016-11-07 08:57:26 +01:00
										 |  |  |         typeName = self.typeName(nativeType) | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |         if code in (lldb.eTypeClassArray, lldb.eTypeClassVector): | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             #DumperBase.warn('ARRAY: %s' % nativeType.GetName()) | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |             if hasattr(nativeType, 'GetArrayElementType'):  # New in 3.8(?) / 350.x | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                 nativeTargetType = nativeType.GetArrayElementType() | 
					
						
							|  |  |  |                 if not nativeTargetType.IsValid(): | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                     if hasattr(nativeType, 'GetVectorElementType'):  # New in 3.8(?) / 350.x | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |                         #DumperBase.warn('BAD: %s ' % nativeTargetType.get_fields_array()) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                         nativeTargetType = nativeType.GetVectorElementType() | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  |                 count = nativeType.GetByteSize() // nativeTargetType.GetByteSize() | 
					
						
							|  |  |  |                 targetTypeName = nativeTargetType.GetName() | 
					
						
							|  |  |  |                 if targetTypeName.startswith('(anon'): | 
					
						
							|  |  |  |                     typeName = nativeType.GetName() | 
					
						
							|  |  |  |                     pos1 = typeName.rfind('[') | 
					
						
							|  |  |  |                     targetTypeName = typeName[0:pos1].strip() | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |                 #DumperBase.warn("TARGET TYPENAME: %s" % targetTypeName) | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  |                 targetType = self.fromNativeType(nativeTargetType) | 
					
						
							|  |  |  |                 tdata = targetType.typeData().copy() | 
					
						
							|  |  |  |                 tdata.name = targetTypeName | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                 targetType.typeData = lambda: tdata | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  |                 return self.createArrayType(targetType, count) | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |             if hasattr(nativeType, 'GetVectorElementType'):  # New in 3.8(?) / 350.x | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                 nativeTargetType = nativeType.GetVectorElementType() | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  |                 count = nativeType.GetByteSize() // nativeTargetType.GetByteSize() | 
					
						
							|  |  |  |                 targetType = self.fromNativeType(nativeTargetType) | 
					
						
							|  |  |  |                 return self.createArrayType(targetType, count) | 
					
						
							|  |  |  |             return self.createType(nativeType.GetName()) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         typeId = self.nativeTypeId(nativeType) | 
					
						
							|  |  |  |         res = self.typeData.get(typeId, None) | 
					
						
							|  |  |  |         if res is None: | 
					
						
							|  |  |  |             #  # This strips typedefs for pointers. We don't want that. | 
					
						
							|  |  |  |             #  typeobj.nativeType = nativeType.GetUnqualifiedType() | 
					
						
							|  |  |  |             tdata = self.TypeData(self) | 
					
						
							|  |  |  |             tdata.typeId = typeId | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  |             tdata.name = typeName | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             tdata.lbitsize = nativeType.GetByteSize() * 8 | 
					
						
							| 
									
										
										
										
											2016-09-19 12:05:16 +02:00
										 |  |  |             if code == lldb.eTypeClassBuiltin: | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |                 if utils.isFloatingPointTypeName(typeName): | 
					
						
							| 
									
										
										
										
											2020-02-24 15:10:47 +01:00
										 |  |  |                     tdata.code = TypeCode.Float | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |                 elif utils.isIntegralTypeName(typeName): | 
					
						
							| 
									
										
										
										
											2020-02-24 15:10:47 +01:00
										 |  |  |                     tdata.code = TypeCode.Integral | 
					
						
							| 
									
										
										
										
											2019-01-21 12:16:52 +01:00
										 |  |  |                 elif typeName in ('__int128', 'unsigned __int128'): | 
					
						
							| 
									
										
										
										
											2020-02-24 15:10:47 +01:00
										 |  |  |                     tdata.code = TypeCode.Integral | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  |                 elif typeName == 'void': | 
					
						
							| 
									
										
										
										
											2020-02-24 15:10:47 +01:00
										 |  |  |                     tdata.code = TypeCode.Void | 
					
						
							| 
									
										
										
										
											2020-12-10 14:50:40 +01:00
										 |  |  |                 elif typeName == 'wchar_t': | 
					
						
							|  |  |  |                     tdata.code = TypeCode.Integral | 
					
						
							| 
									
										
										
										
											2016-09-19 12:05:16 +02:00
										 |  |  |                 else: | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |                     self.warn('UNKNOWN TYPE KEY: %s: %s' % (typeName, code)) | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  |             elif code == lldb.eTypeClassEnumeration: | 
					
						
							| 
									
										
										
										
											2020-02-24 15:10:47 +01:00
										 |  |  |                 tdata.code = TypeCode.Enum | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                 tdata.enumDisplay = lambda intval, addr, form: \ | 
					
						
							| 
									
										
										
										
											2018-03-21 17:10:24 +01:00
										 |  |  |                     self.nativeTypeEnumDisplay(nativeType, intval, form) | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  |             elif code in (lldb.eTypeClassComplexInteger, lldb.eTypeClassComplexFloat): | 
					
						
							| 
									
										
										
										
											2020-02-24 15:10:47 +01:00
										 |  |  |                 tdata.code = TypeCode.Complex | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  |             elif code in (lldb.eTypeClassClass, lldb.eTypeClassStruct, lldb.eTypeClassUnion): | 
					
						
							| 
									
										
										
										
											2020-02-24 15:10:47 +01:00
										 |  |  |                 tdata.code = TypeCode.Struct | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                 tdata.lalignment = lambda: \ | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  |                     self.nativeStructAlignment(nativeType) | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                 tdata.lfields = lambda value: \ | 
					
						
							| 
									
										
										
										
											2017-03-08 16:37:52 +01:00
										 |  |  |                     self.listMembers(value, nativeType) | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  |                 tdata.templateArguments = self.listTemplateParametersHelper(nativeType) | 
					
						
							|  |  |  |             elif code == lldb.eTypeClassFunction: | 
					
						
							| 
									
										
										
										
											2020-02-24 15:10:47 +01:00
										 |  |  |                 tdata.code = TypeCode.Function | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  |             elif code == lldb.eTypeClassMemberPointer: | 
					
						
							| 
									
										
										
										
											2020-02-24 15:10:47 +01:00
										 |  |  |                 tdata.code = TypeCode.MemberPointer | 
					
						
							| 
									
										
										
										
											2016-11-01 09:50:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |             self.registerType(typeId, tdata)  # Fix up fields and template args | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |         #    warn('CREATE TYPE: %s' % typeId) | 
					
						
							|  |  |  |         #else: | 
					
						
							|  |  |  |         #    warn('REUSE TYPE: %s' % typeId) | 
					
						
							|  |  |  |         return self.Type(self, typeId) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def listTemplateParametersHelper(self, nativeType): | 
					
						
							|  |  |  |         stringArgs = self.listTemplateParameters(nativeType.GetName()) | 
					
						
							|  |  |  |         n = nativeType.GetNumberOfTemplateArguments() | 
					
						
							|  |  |  |         if n != len(stringArgs): | 
					
						
							|  |  |  |             # Something wrong in the debug info. | 
					
						
							|  |  |  |             # Should work in theory, doesn't work in practice. | 
					
						
							|  |  |  |             # Items like std::allocator<std::pair<unsigned int const, float> report 0 | 
					
						
							|  |  |  |             # for nativeType.GetNumberOfTemplateArguments() with LLDB 3.8 | 
					
						
							|  |  |  |             return stringArgs | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         targs = [] | 
					
						
							|  |  |  |         for i in range(nativeType.GetNumberOfTemplateArguments()): | 
					
						
							|  |  |  |             kind = nativeType.GetTemplateArgumentKind(i) | 
					
						
							|  |  |  |             # eTemplateArgumentKindNull = 0, | 
					
						
							|  |  |  |             # eTemplateArgumentKindType, | 
					
						
							|  |  |  |             # eTemplateArgumentKindDeclaration, | 
					
						
							|  |  |  |             # eTemplateArgumentKindIntegral, | 
					
						
							|  |  |  |             # eTemplateArgumentKindTemplate, | 
					
						
							|  |  |  |             # eTemplateArgumentKindTemplateExpansion, | 
					
						
							|  |  |  |             # eTemplateArgumentKindExpression, | 
					
						
							|  |  |  |             # eTemplateArgumentKindPack | 
					
						
							|  |  |  |             if kind == lldb.eTemplateArgumentKindType: | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                 innerType = nativeType.GetTemplateArgumentType( | 
					
						
							|  |  |  |                     i).GetUnqualifiedType().GetCanonicalType() | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                 targs.append(self.fromNativeType(innerType)) | 
					
						
							|  |  |  |             #elif kind == lldb.eTemplateArgumentKindIntegral: | 
					
						
							|  |  |  |             #   innerType = nativeType.GetTemplateArgumentType(i).GetUnqualifiedType().GetCanonicalType() | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             #   #DumperBase.warn('INNER TYP: %s' % innerType) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             #   basicType = innerType.GetBasicType() | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             #   #DumperBase.warn('IBASIC TYP: %s' % basicType) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             #   inner = self.extractTemplateArgument(nativeType.GetName(), i) | 
					
						
							|  |  |  |             #   exp = '(%s)%s' % (innerType.GetName(), inner) | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             #   #DumperBase.warn('EXP : %s' % exp) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             #   val = self.nativeParseAndEvaluate('(%s)%s' % (innerType.GetName(), inner)) | 
					
						
							|  |  |  |             #   # Clang writes 'int' and '0xfffffff' into the debug info | 
					
						
							|  |  |  |             #   # LLDB manages to read a value of 0xfffffff... | 
					
						
							|  |  |  |             #   #if basicType == lldb.eBasicTypeInt: | 
					
						
							|  |  |  |             #   value = val.GetValueAsUnsigned() | 
					
						
							|  |  |  |             #   if value >= 0x8000000: | 
					
						
							|  |  |  |             #       value -= 0x100000000 | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             #   #DumperBase.warn('KIND: %s' % kind) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             #   targs.append(value) | 
					
						
							| 
									
										
										
										
											2016-09-19 12:05:16 +02:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |                 #DumperBase.warn('UNHANDLED TEMPLATE TYPE : %s' % kind) | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                 targs.append(stringArgs[i])  # Best we can do. | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |         #DumperBase.warn('TARGS: %s %s' % (nativeType.GetName(), [str(x) for x in  targs])) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |         return targs | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-07 08:57:26 +01:00
										 |  |  |     def typeName(self, nativeType): | 
					
						
							| 
									
										
										
										
											2020-09-29 20:12:25 -07:00
										 |  |  |         # Don't use GetDisplayTypeName since LLDB removed the inline namespace __1 | 
					
						
							|  |  |  |         # https://reviews.llvm.org/D74478 | 
					
						
							|  |  |  |         return nativeType.GetName() | 
					
						
							| 
									
										
										
										
											2016-11-07 08:57:26 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def nativeTypeId(self, nativeType): | 
					
						
							| 
									
										
										
										
											2020-12-11 10:46:38 +01:00
										 |  |  |         if nativeType and (nativeType.GetTypeClass() == lldb.eTypeClassTypedef): | 
					
						
							|  |  |  |             nativeTargetType = nativeType.GetUnqualifiedType() | 
					
						
							|  |  |  |             if hasattr(nativeTargetType, 'GetCanonicalType'): | 
					
						
							|  |  |  |                 nativeTargetType = nativeTargetType.GetCanonicalType() | 
					
						
							|  |  |  |             return '%s{%s}' % (nativeType.name, nativeTargetType.name) | 
					
						
							| 
									
										
										
										
											2016-11-07 08:57:26 +01:00
										 |  |  |         name = self.typeName(nativeType) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |         if name is None or len(name) == 0: | 
					
						
							|  |  |  |             c = '0' | 
					
						
							|  |  |  |         elif name == '(anonymous struct)' and nativeType.GetTypeClass() == lldb.eTypeClassStruct: | 
					
						
							|  |  |  |             c = 's' | 
					
						
							|  |  |  |         elif name == '(anonymous struct)' and nativeType.GetTypeClass() == lldb.eTypeClassUnion: | 
					
						
							|  |  |  |             c = 'u' | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return name | 
					
						
							|  |  |  |         fields = nativeType.get_fields_array() | 
					
						
							|  |  |  |         typeId = c + ''.join(['{%s:%s}' % (f.name, self.nativeTypeId(f.GetType())) for f in fields]) | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |         #DumperBase.warn('NATIVE TYPE ID FOR %s IS %s' % (name, typeId)) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |         return typeId | 
					
						
							| 
									
										
										
										
											2016-09-06 08:54:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-21 17:10:24 +01:00
										 |  |  |     def nativeTypeEnumDisplay(self, nativeType, intval, form): | 
					
						
							| 
									
										
										
										
											2016-09-15 12:31:28 +02:00
										 |  |  |         if hasattr(nativeType, 'get_enum_members_array'): | 
					
						
							| 
									
										
										
										
											2018-11-15 09:04:39 +01:00
										 |  |  |             enumerators = [] | 
					
						
							|  |  |  |             flags = [] | 
					
						
							|  |  |  |             found = False | 
					
						
							| 
									
										
										
										
											2016-09-15 12:31:28 +02:00
										 |  |  |             for enumMember in nativeType.get_enum_members_array(): | 
					
						
							|  |  |  |                 # Even when asking for signed we get unsigned with LLDB 3.8. | 
					
						
							| 
									
										
										
										
											2018-11-15 09:04:39 +01:00
										 |  |  |                 value = enumMember.GetValueAsSigned() | 
					
						
							|  |  |  |                 name = nativeType.GetName().split('::') | 
					
						
							|  |  |  |                 name[-1] = enumMember.GetName() | 
					
						
							|  |  |  |                 if value == intval: | 
					
						
							|  |  |  |                     return '::'.join(name) + ' (' + (form % intval) + ')' | 
					
						
							|  |  |  |                 enumerators.append(('::'.join(name), value)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             given = intval | 
					
						
							|  |  |  |             for (name, value) in enumerators: | 
					
						
							|  |  |  |                 if value & given != 0: | 
					
						
							|  |  |  |                     flags.append(name) | 
					
						
							|  |  |  |                     given = given & ~value | 
					
						
							|  |  |  |                     found = True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if not found or given != 0: | 
					
						
							|  |  |  |                 flags.append('unknown: %d' % given) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return '(' + ' | '.join(flags) + ') (' + (form % intval) + ')' | 
					
						
							| 
									
										
										
										
											2018-03-21 17:10:24 +01:00
										 |  |  |         return form % intval | 
					
						
							| 
									
										
										
										
											2016-09-15 12:31:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-26 14:29:16 +02:00
										 |  |  |     def nativeDynamicTypeName(self, address, baseType): | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |         return None  # FIXME: Seems sufficient, no idea why. | 
					
						
							| 
									
										
										
										
											2016-09-26 14:29:16 +02:00
										 |  |  |         addr = self.target.ResolveLoadAddress(address) | 
					
						
							|  |  |  |         ctx = self.target.ResolveSymbolContextForAddress(addr, 0) | 
					
						
							|  |  |  |         sym = ctx.GetSymbol() | 
					
						
							|  |  |  |         return sym.GetName() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-04 14:15:14 +01:00
										 |  |  |     def stateName(self, s): | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             # See db.StateType | 
					
						
							|  |  |  |             return ( | 
					
						
							|  |  |  |                 'invalid', | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                 'unloaded',   # Process is object is valid, but not currently loaded | 
					
						
							|  |  |  |                 'connected',  # Process is connected to remote debug services, | 
					
						
							|  |  |  |                               #  but not launched or attached to anything yet | 
					
						
							|  |  |  |                 'attaching',  # Process is currently trying to attach | 
					
						
							|  |  |  |                 'launching',  # Process is in the process of launching | 
					
						
							|  |  |  |                 'stopped',    # Process or thread is stopped and can be examined. | 
					
						
							|  |  |  |                 'running',    # Process or thread is running and can't be examined. | 
					
						
							|  |  |  |                 'stepping',   # Process or thread is in the process of stepping | 
					
						
							|  |  |  |                               #  and can not be examined. | 
					
						
							|  |  |  |                 'crashed',    # Process or thread has crashed and can be examined. | 
					
						
							|  |  |  |                 'detached',   # Process has been detached and can't be examined. | 
					
						
							|  |  |  |                 'exited',     # Process has exited and can't be examined. | 
					
						
							|  |  |  |                 'suspended'   # Process or thread is in a suspended state as far | 
					
						
							|  |  |  |             )[s] | 
					
						
							| 
									
										
										
										
											2015-02-04 14:15:14 +01:00
										 |  |  |         except: | 
					
						
							|  |  |  |             return 'unknown(%s)' % s | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def stopReason(self, s): | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             return ( | 
					
						
							|  |  |  |                 'invalid', | 
					
						
							|  |  |  |                 'none', | 
					
						
							|  |  |  |                 'trace', | 
					
						
							|  |  |  |                 'breakpoint', | 
					
						
							|  |  |  |                 'watchpoint', | 
					
						
							|  |  |  |                 'signal', | 
					
						
							|  |  |  |                 'exception', | 
					
						
							|  |  |  |                 'exec', | 
					
						
							|  |  |  |                 'plancomplete', | 
					
						
							|  |  |  |                 'threadexiting', | 
					
						
							|  |  |  |                 'instrumentation', | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |             )[s] | 
					
						
							| 
									
										
										
										
											2015-02-04 14:15:14 +01:00
										 |  |  |         except: | 
					
						
							|  |  |  |             return 'unknown(%s)' % s | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-10 20:01:35 +01:00
										 |  |  |     def enumExpression(self, enumType, enumValue): | 
					
						
							|  |  |  |         ns = self.qtNamespace() | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |         return ns + 'Qt::' + enumType + '(' \ | 
					
						
							|  |  |  |             + ns + 'Qt::' + enumType + '::' + enumValue + ')' | 
					
						
							| 
									
										
										
										
											2014-01-10 20:01:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-06 08:54:43 +02:00
										 |  |  |     def callHelper(self, rettype, value, func, args): | 
					
						
							| 
									
										
										
										
											2013-09-11 21:35:39 +02:00
										 |  |  |         # args is a tuple. | 
					
						
							|  |  |  |         arg = ','.join(args) | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |         #DumperBase.warn('PRECALL: %s -> %s(%s)' % (value.address(), func, arg)) | 
					
						
							| 
									
										
										
										
											2016-09-06 08:54:43 +02:00
										 |  |  |         typename = value.type.name | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |         exp = '((%s*)0x%x)->%s(%s)' % (typename, value.address(), func, arg) | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |         #DumperBase.warn('CALL: %s' % exp) | 
					
						
							| 
									
										
										
										
											2016-09-06 08:54:43 +02:00
										 |  |  |         result = self.currentContextValue.CreateValueFromExpression('', exp) | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |         #DumperBase.warn('  -> %s' % result) | 
					
						
							| 
									
										
										
										
											2016-09-06 08:54:43 +02:00
										 |  |  |         return self.fromNativeValue(result) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def pokeValue(self, typeName, *args): | 
					
						
							| 
									
										
										
										
											2014-01-22 16:25:39 +01:00
										 |  |  |         thread = self.currentThread() | 
					
						
							|  |  |  |         frame = thread.GetFrameAtIndex(0) | 
					
						
							|  |  |  |         inner = ','.join(args) | 
					
						
							| 
									
										
										
										
											2016-09-06 08:54:43 +02:00
										 |  |  |         value = frame.EvaluateExpression(typeName + '{' + inner + '}') | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |         #DumperBase.warn('  TYPE: %s' % value.type) | 
					
						
							|  |  |  |         #DumperBase.warn('  ADDR: 0x%x' % value.address) | 
					
						
							|  |  |  |         #DumperBase.warn('  VALUE: %s' % value) | 
					
						
							| 
									
										
										
										
											2014-01-22 16:25:39 +01:00
										 |  |  |         return value | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |     def nativeParseAndEvaluate(self, exp): | 
					
						
							| 
									
										
										
										
											2013-10-23 12:51:11 +02:00
										 |  |  |         thread = self.currentThread() | 
					
						
							|  |  |  |         frame = thread.GetFrameAtIndex(0) | 
					
						
							| 
									
										
										
										
											2016-09-06 08:54:43 +02:00
										 |  |  |         val = frame.EvaluateExpression(exp) | 
					
						
							|  |  |  |         #options = lldb.SBExpressionOptions() | 
					
						
							|  |  |  |         #val = self.target.EvaluateExpression(exp, options) | 
					
						
							|  |  |  |         err = val.GetError() | 
					
						
							|  |  |  |         if err.Fail(): | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             #DumperBase.warn('FAILING TO EVAL: %s' % exp) | 
					
						
							| 
									
										
										
										
											2016-09-06 08:54:43 +02:00
										 |  |  |             return None | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |         #DumperBase.warn('NO ERROR.') | 
					
						
							|  |  |  |         #DumperBase.warn('EVAL: %s -> %s' % (exp, val.IsValid())) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |         return val | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def parseAndEvaluate(self, exp): | 
					
						
							|  |  |  |         val = self.nativeParseAndEvaluate(exp) | 
					
						
							|  |  |  |         return None if val is None else self.fromNativeValue(val) | 
					
						
							| 
									
										
										
										
											2016-09-06 08:54:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-01 18:11:57 +02:00
										 |  |  |     def isWindowsTarget(self): | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def isQnxTarget(self): | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def isArmArchitecture(self): | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-06 13:36:02 +02:00
										 |  |  |     def isMsvcTarget(self): | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-15 17:26:56 +02:00
										 |  |  |     def prettySymbolByAddress(self, address): | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             result = lldb.SBCommandReturnObject() | 
					
						
							|  |  |  |             # Cast the address to a function pointer to get the name and location of the function. | 
					
						
							|  |  |  |             expression = 'po (void (*)()){}' | 
					
						
							|  |  |  |             self.debugger.GetCommandInterpreter().HandleCommand(expression.format(address), result) | 
					
						
							|  |  |  |             output = '' | 
					
						
							|  |  |  |             if result.Succeeded(): | 
					
						
							|  |  |  |                 output = result.GetOutput().strip() | 
					
						
							|  |  |  |             if output: | 
					
						
							|  |  |  |                 return output | 
					
						
							|  |  |  |         except: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  |         return '0x%x' % address | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-09 13:25:17 +01:00
										 |  |  |     def qtVersionAndNamespace(self): | 
					
						
							| 
									
										
										
										
											2014-03-12 18:04:51 +01:00
										 |  |  |         for func in self.target.FindFunctions('qVersion'): | 
					
						
							|  |  |  |             name = func.GetSymbol().GetName() | 
					
						
							| 
									
										
										
										
											2014-03-19 12:16:43 +01:00
										 |  |  |             if name.endswith('()'): | 
					
						
							|  |  |  |                 name = name[:-2] | 
					
						
							| 
									
										
										
										
											2014-03-12 18:04:51 +01:00
										 |  |  |             if name.count(':') > 2: | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-19 12:16:43 +01:00
										 |  |  |             qtNamespace = name[:name.find('qVersion')] | 
					
						
							|  |  |  |             self.qtNamespace = lambda: qtNamespace | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-04 15:37:55 +02:00
										 |  |  |             options = lldb.SBExpressionOptions() | 
					
						
							|  |  |  |             res = self.target.EvaluateExpression(name + '()', options) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if not res.IsValid() or not res.GetType().IsPointerType(): | 
					
						
							|  |  |  |                 exp = '((const char*())%s)()' % name | 
					
						
							|  |  |  |                 res = self.target.EvaluateExpression(exp, options) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if not res.IsValid() or not res.GetType().IsPointerType(): | 
					
						
							|  |  |  |                 exp = '((const char*())_Z8qVersionv)()' | 
					
						
							|  |  |  |                 res = self.target.EvaluateExpression(exp, options) | 
					
						
							| 
									
										
										
										
											2014-03-12 18:04:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-04 15:37:55 +02:00
										 |  |  |             if not res.IsValid() or not res.GetType().IsPointerType(): | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             version = str(res) | 
					
						
							| 
									
										
										
										
											2014-03-12 18:04:51 +01:00
										 |  |  |             if version.count('.') != 2: | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |             version.replace("'", '"')  # Both seem possible | 
					
						
							|  |  |  |             version = version[version.find('"') + 1:version.rfind('"')] | 
					
						
							| 
									
										
										
										
											2014-03-12 18:04:51 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             (major, minor, patch) = version.split('.') | 
					
						
							|  |  |  |             qtVersion = 0x10000 * int(major) + 0x100 * int(minor) + int(patch) | 
					
						
							|  |  |  |             self.qtVersion = lambda: qtVersion | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-01 09:22:53 +01:00
										 |  |  |             funcs = self.target.FindFunctions('QObject::customEvent') | 
					
						
							|  |  |  |             if len(funcs): | 
					
						
							|  |  |  |                 symbol = funcs[0].GetSymbol() | 
					
						
							|  |  |  |                 self.qtCustomEventFunc = symbol.GetStartAddress().GetLoadAddress(self.target) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-02 09:06:05 +01:00
										 |  |  |             funcs = self.target.FindFunctions('QObject::property') | 
					
						
							|  |  |  |             if len(funcs): | 
					
						
							|  |  |  |                 symbol = funcs[0].GetSymbol() | 
					
						
							|  |  |  |                 self.qtPropertyFunc = symbol.GetStartAddress().GetLoadAddress(self.target) | 
					
						
							| 
									
										
										
										
											2014-03-12 18:04:51 +01:00
										 |  |  |             return (qtNamespace, qtVersion) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return ('', 0x50200) | 
					
						
							| 
									
										
										
										
											2014-01-09 13:25:17 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def qtNamespace(self): | 
					
						
							| 
									
										
										
										
											2014-03-12 18:04:51 +01:00
										 |  |  |         return self.qtVersionAndNamespace()[0] | 
					
						
							| 
									
										
										
										
											2014-01-09 13:25:17 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def qtVersion(self): | 
					
						
							| 
									
										
										
										
											2014-01-09 16:23:17 +01:00
										 |  |  |         self.qtVersionAndNamespace() | 
					
						
							| 
									
										
										
										
											2014-03-12 18:04:51 +01:00
										 |  |  |         return self.qtVersionAndNamespace()[1] | 
					
						
							| 
									
										
										
										
											2013-06-27 10:42:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |     def handleCommand(self, command): | 
					
						
							|  |  |  |         result = lldb.SBCommandReturnObject() | 
					
						
							|  |  |  |         self.debugger.GetCommandInterpreter().HandleCommand(command, result) | 
					
						
							|  |  |  |         success = result.Succeeded() | 
					
						
							|  |  |  |         if success: | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |             self.report('output="%s"' % toCString(result.GetOutput())) | 
					
						
							| 
									
										
										
										
											2013-04-10 13:55:15 +02:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |             self.report('error="%s"' % toCString(result.GetError())) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-16 14:23:53 +01:00
										 |  |  |     def canonicalTypeName(self, name): | 
					
						
							|  |  |  |         return re.sub('\\bconst\\b', '', name).replace(' ', '') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-12 12:47:24 +01:00
										 |  |  |     def removeTypePrefix(self, name): | 
					
						
							|  |  |  |         return re.sub('^(struct|class|union|enum|typedef) ', '', name) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-06 08:54:43 +02:00
										 |  |  |     def lookupNativeType(self, name): | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |         #DumperBase.warn('LOOKUP TYPE NAME: %s' % name) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |         typeobj = self.typeCache.get(name) | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |         if typeobj is not None: | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             #DumperBase.warn('CACHED: %s' % name) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             return typeobj | 
					
						
							| 
									
										
										
										
											2014-01-16 14:23:53 +01:00
										 |  |  |         typeobj = self.target.FindFirstType(name) | 
					
						
							|  |  |  |         if typeobj.IsValid(): | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             #DumperBase.warn('VALID FIRST : %s' % typeobj) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             self.typeCache[name] = typeobj | 
					
						
							| 
									
										
										
										
											2014-01-16 14:23:53 +01:00
										 |  |  |             return typeobj | 
					
						
							| 
									
										
										
										
											2017-01-12 12:47:24 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # FindFirstType has a bug (in lldb) that if there are two types with the same base name | 
					
						
							|  |  |  |         # but different scope name (e.g. inside different classes) and the searched for type name | 
					
						
							|  |  |  |         # would be returned as the second result in a call to FindTypes, FindFirstType would return | 
					
						
							|  |  |  |         # an empty result. | 
					
						
							|  |  |  |         # Therefore an additional call to FindTypes is done as a fallback. | 
					
						
							|  |  |  |         # Note that specifying a prefix like enum or typedef or class will make the call fail to | 
					
						
							|  |  |  |         # find the type, thus the prefix is stripped. | 
					
						
							|  |  |  |         nonPrefixedName = self.canonicalTypeName(self.removeTypePrefix(name)) | 
					
						
							| 
									
										
										
										
											2021-03-01 15:58:10 +01:00
										 |  |  |         if re.match(r'^.+\(.*\)', nonPrefixedName) is not None: | 
					
						
							| 
									
										
										
										
											2021-02-12 12:50:23 +01:00
										 |  |  |             return lldb.SBType() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-12 12:47:24 +01:00
										 |  |  |         typeobjlist = self.target.FindTypes(nonPrefixedName) | 
					
						
							|  |  |  |         if typeobjlist.IsValid(): | 
					
						
							|  |  |  |             for typeobj in typeobjlist: | 
					
						
							| 
									
										
										
										
											2020-09-29 20:12:25 -07:00
										 |  |  |                 n = self.canonicalTypeName(self.removeTypePrefix(typeobj.GetName())) | 
					
						
							| 
									
										
										
										
											2017-01-12 12:47:24 +01:00
										 |  |  |                 if n == nonPrefixedName: | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |                     #DumperBase.warn('FOUND TYPE USING FindTypes : %s' % typeobj) | 
					
						
							| 
									
										
										
										
											2017-01-12 12:47:24 +01:00
										 |  |  |                     self.typeCache[name] = typeobj | 
					
						
							|  |  |  |                     return typeobj | 
					
						
							| 
									
										
										
										
											2014-12-01 12:17:56 +01:00
										 |  |  |         if name.endswith('*'): | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             #DumperBase.warn('RECURSE PTR') | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             typeobj = self.lookupNativeType(name[:-1].strip()) | 
					
						
							|  |  |  |             if typeobj is not None: | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |                 #DumperBase.warn('RECURSE RESULT X: %s' % typeobj) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                 self.fromNativeType(typeobj.GetPointerType()) | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |                 #DumperBase.warn('RECURSE RESULT: %s' % typeobj.GetPointerType()) | 
					
						
							| 
									
										
										
										
											2014-12-01 12:17:56 +01:00
										 |  |  |                 return typeobj.GetPointerType() | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             #typeobj = self.target.FindFirstType(name[:-1].strip()) | 
					
						
							|  |  |  |             #if typeobj.IsValid(): | 
					
						
							|  |  |  |             #    self.typeCache[name] = typeobj.GetPointerType() | 
					
						
							|  |  |  |             #    return typeobj.GetPointerType() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if name.endswith(' const'): | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             #DumperBase.warn('LOOKUP END CONST') | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             typeobj = self.lookupNativeType(name[:-6]) | 
					
						
							|  |  |  |             if typeobj is not None: | 
					
						
							|  |  |  |                 return typeobj | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if name.startswith('const '): | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             #DumperBase.warn('LOOKUP START CONST') | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             typeobj = self.lookupNativeType(name[6:]) | 
					
						
							|  |  |  |             if typeobj is not None: | 
					
						
							|  |  |  |                 return typeobj | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 12:52:22 +01:00
										 |  |  |         return lldb.SBType() | 
					
						
							| 
									
										
										
										
											2013-05-08 16:20:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-07 12:34:10 +02:00
										 |  |  |     def setupInferior(self, args): | 
					
						
							| 
									
										
										
										
											2020-05-05 17:33:48 +02:00
										 |  |  |         """ Set up SBTarget instance """ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |         error = lldb.SBError() | 
					
						
							| 
									
										
										
										
											2013-10-01 02:30:12 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.executable_ = args['executable'] | 
					
						
							| 
									
										
										
										
											2015-10-27 15:50:41 +01:00
										 |  |  |         self.startMode_ = args.get('startmode', 1) | 
					
						
							|  |  |  |         self.breakOnMain_ = args.get('breakonmain', 0) | 
					
						
							|  |  |  |         self.useTerminal_ = args.get('useterminal', 0) | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |         pargs = self.hexdecode(args.get('processargs', '')) | 
					
						
							| 
									
										
										
										
											2019-09-19 16:55:21 +02:00
										 |  |  |         self.processArgs_ = pargs.split('\0') if len(pargs) else [] | 
					
						
							| 
									
										
										
										
											2016-12-06 15:39:05 +01:00
										 |  |  |         self.environment_ = args.get('environment', []) | 
					
						
							|  |  |  |         self.environment_ = list(map(lambda x: self.hexdecode(x), self.environment_)) | 
					
						
							| 
									
										
										
										
											2015-10-27 15:50:41 +01:00
										 |  |  |         self.attachPid_ = args.get('attachpid', 0) | 
					
						
							|  |  |  |         self.sysRoot_ = args.get('sysroot', '') | 
					
						
							|  |  |  |         self.remoteChannel_ = args.get('remotechannel', '') | 
					
						
							| 
									
										
										
										
											2013-10-31 10:07:28 +01:00
										 |  |  |         self.platform_ = args.get('platform', '') | 
					
						
							| 
									
										
										
										
											2015-10-09 15:00:20 +02:00
										 |  |  |         self.nativeMixed = int(args.get('nativemixed', 0)) | 
					
						
							| 
									
										
										
										
											2020-04-02 17:58:24 +02:00
										 |  |  |         self.symbolFile_ = args['symbolfile']; | 
					
						
							| 
									
										
										
										
											2016-09-26 13:47:19 +02:00
										 |  |  |         self.workingDirectory_ = args.get('workingdirectory', '') | 
					
						
							|  |  |  |         if self.workingDirectory_ == '': | 
					
						
							| 
									
										
										
										
											2017-04-07 13:23:01 +02:00
										 |  |  |             try: | 
					
						
							|  |  |  |                 self.workingDirectory_ = os.getcwd() | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |             except:  # Could have been deleted in the mean time. | 
					
						
							| 
									
										
										
										
											2017-04-07 13:23:01 +02:00
										 |  |  |                 pass | 
					
						
							| 
									
										
										
										
											2013-10-01 02:30:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-31 10:07:28 +01:00
										 |  |  |         if self.platform_: | 
					
						
							|  |  |  |             self.debugger.SetCurrentPlatform(self.platform_) | 
					
						
							| 
									
										
										
										
											2013-12-10 12:53:20 +01:00
										 |  |  |         # sysroot has to be set *after* the platform | 
					
						
							|  |  |  |         if self.sysRoot_: | 
					
						
							|  |  |  |             self.debugger.SetCurrentPlatformSDKRoot(self.sysRoot_) | 
					
						
							| 
									
										
										
										
											2014-02-04 18:36:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 15:51:09 +02:00
										 |  |  |         # There seems to be some kind of unexpected behavior, or bug in LLDB | 
					
						
							|  |  |  |         # such that target.Attach(attachInfo, error) below does not create | 
					
						
							|  |  |  |         # a valid process if this symbolFile here is valid. | 
					
						
							|  |  |  |         if self.startMode_ == DebuggerStartMode.AttachExternal: | 
					
						
							|  |  |  |             self.symbolFile_ = '' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-02 11:19:28 +02:00
										 |  |  |         self.target = self.debugger.CreateTarget( | 
					
						
							| 
									
										
										
										
											2020-04-02 17:58:24 +02:00
										 |  |  |             self.symbolFile_, None, self.platform_, True, error) | 
					
						
							| 
									
										
										
										
											2020-04-02 11:19:28 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if not error.Success(): | 
					
						
							|  |  |  |             self.report(self.describeError(error)) | 
					
						
							|  |  |  |             self.reportState('enginerunfailed') | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         broadcaster = self.target.GetBroadcaster() | 
					
						
							|  |  |  |         listener = self.debugger.GetListener() | 
					
						
							|  |  |  |         broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged) | 
					
						
							|  |  |  |         listener.StartListeningForEvents(broadcaster, lldb.SBProcess.eBroadcastBitStateChanged) | 
					
						
							|  |  |  |         broadcaster.AddListener(listener, lldb.SBTarget.eBroadcastBitBreakpointChanged) | 
					
						
							|  |  |  |         listener.StartListeningForEvents( | 
					
						
							|  |  |  |             broadcaster, lldb.SBTarget.eBroadcastBitBreakpointChanged) | 
					
						
							| 
									
										
										
										
											2013-05-29 14:55:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-09 15:00:20 +02:00
										 |  |  |         if self.nativeMixed: | 
					
						
							|  |  |  |             self.interpreterEventBreakpoint = \ | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                 self.target.BreakpointCreateByName('qt_qmlDebugMessageAvailable') | 
					
						
							| 
									
										
										
										
											2015-10-09 15:00:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         state = 1 if self.target.IsValid() else 0 | 
					
						
							| 
									
										
										
										
											2016-10-07 12:23:35 +02:00
										 |  |  |         self.reportResult('success="%s",msg="%s",exe="%s"' | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |                           % (state, toCString(error), toCString(self.executable_)), args) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 11:56:03 +01:00
										 |  |  |     def runEngine(self, args): | 
					
						
							| 
									
										
										
										
											2020-05-05 17:33:48 +02:00
										 |  |  |         """ Set up SBProcess instance """ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |         error = lldb.SBError() | 
					
						
							| 
									
										
										
										
											2013-05-31 15:27:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 17:33:48 +02:00
										 |  |  |         if self.startMode_ == DebuggerStartMode.AttachExternal: | 
					
						
							|  |  |  |             attach_info = lldb.SBAttachInfo(self.attachPid_) | 
					
						
							|  |  |  |             self.process = self.target.Attach(attach_info, error) | 
					
						
							| 
									
										
										
										
											2013-10-31 10:07:28 +01:00
										 |  |  |             if not error.Success(): | 
					
						
							| 
									
										
										
										
											2020-05-05 17:33:48 +02:00
										 |  |  |                 self.reportState('enginerunfailed') | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 self.report('pid="%s"' % self.process.GetProcessID()) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                 self.reportState('enginerunandinferiorstopok') | 
					
						
							| 
									
										
										
										
											2020-05-05 17:33:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         elif (self.startMode_ == DebuggerStartMode.AttachToRemoteServer | 
					
						
							|  |  |  |                     and self.platform_ == 'remote-android'): | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-13 08:39:37 +02:00
										 |  |  |             connect_options = lldb.SBPlatformConnectOptions(self.remoteChannel_) | 
					
						
							| 
									
										
										
										
											2020-05-05 17:33:48 +02:00
										 |  |  |             res = self.target.GetPlatform().ConnectRemote(connect_options) | 
					
						
							| 
									
										
										
										
											2020-05-13 08:39:37 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             DumperBase.warn("CONNECT: %s %s platform: %s %s" % (res, | 
					
						
							|  |  |  |                         self.remoteChannel_, | 
					
						
							| 
									
										
										
										
											2020-05-05 17:33:48 +02:00
										 |  |  |                         self.target.GetPlatform().GetName(), | 
					
						
							|  |  |  |                         self.target.GetPlatform().IsConnected())) | 
					
						
							|  |  |  |             if not res.Success(): | 
					
						
							| 
									
										
										
										
											2021-12-15 18:52:06 +01:00
										 |  |  |                 self.report(self.describeError(res)) | 
					
						
							| 
									
										
										
										
											2020-05-05 17:33:48 +02:00
										 |  |  |                 self.reportState('enginerunfailed') | 
					
						
							|  |  |  |                 return | 
					
						
							| 
									
										
										
										
											2020-05-13 08:39:37 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 17:33:48 +02:00
										 |  |  |             attach_info = lldb.SBAttachInfo(self.attachPid_) | 
					
						
							|  |  |  |             self.process = self.target.Attach(attach_info, error) | 
					
						
							|  |  |  |             if not error.Success(): | 
					
						
							| 
									
										
										
										
											2020-05-13 08:57:12 +02:00
										 |  |  |                 self.report(self.describeError(error)) | 
					
						
							| 
									
										
										
										
											2020-05-05 17:33:48 +02:00
										 |  |  |                 self.reportState('enginerunfailed') | 
					
						
							| 
									
										
										
										
											2016-09-14 14:31:27 +02:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2020-05-05 17:33:48 +02:00
										 |  |  |                 self.report('pid="%s"' % self.process.GetProcessID()) | 
					
						
							|  |  |  |                 self.reportState('enginerunandinferiorstopok') | 
					
						
							| 
									
										
										
										
											2020-04-15 09:01:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |         elif (self.startMode_ == DebuggerStartMode.AttachToRemoteServer | 
					
						
							|  |  |  |               or self.startMode_ == DebuggerStartMode.AttachToRemoteProcess): | 
					
						
							| 
									
										
										
										
											2020-07-03 18:00:34 +02:00
										 |  |  |             if self.platform_ == 'remote-ios': | 
					
						
							|  |  |  |                 self.process = self.target.ConnectRemote( | 
					
						
							|  |  |  |                     self.debugger.GetListener(), | 
					
						
							|  |  |  |                     self.remoteChannel_, None, error) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 f = lldb.SBFileSpec() | 
					
						
							|  |  |  |                 f.SetFilename(self.executable_) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 launchInfo = lldb.SBLaunchInfo(self.processArgs_) | 
					
						
							|  |  |  |                 #launchInfo.SetWorkingDirectory(self.workingDirectory_) | 
					
						
							|  |  |  |                 launchInfo.SetWorkingDirectory('/tmp') | 
					
						
							| 
									
										
										
										
											2020-07-06 16:23:13 +02:00
										 |  |  |                 if self.platform_ == 'remote-android': | 
					
						
							|  |  |  |                     launchInfo.SetWorkingDirectory('/data/local/tmp') | 
					
						
							|  |  |  |                 launchInfo.SetEnvironmentEntries(self.environment_, False) | 
					
						
							| 
									
										
										
										
											2020-07-03 18:00:34 +02:00
										 |  |  |                 launchInfo.SetExecutableFile(f, True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 DumperBase.warn("TARGET: %s" % self.target) | 
					
						
							|  |  |  |                 self.process = self.target.Launch(launchInfo, error) | 
					
						
							|  |  |  |                 DumperBase.warn("PROCESS: %s" % self.process) | 
					
						
							| 
									
										
										
										
											2020-04-02 11:19:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-31 10:07:28 +01:00
										 |  |  |             if not error.Success(): | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |                 self.report(self.describeError(error)) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                 self.reportState('enginerunfailed') | 
					
						
							| 
									
										
										
										
											2013-10-31 10:07:28 +01:00
										 |  |  |                 return | 
					
						
							| 
									
										
										
										
											2020-04-02 11:19:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-19 12:12:24 +01:00
										 |  |  |             # Even if it stops it seems that LLDB assumes it is running | 
					
						
							|  |  |  |             # and later detects that it did stop after all, so it is be | 
					
						
							|  |  |  |             # better to mirror that and wait for the spontaneous stop. | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             self.reportState('enginerunandinferiorrunok') | 
					
						
							| 
									
										
										
										
											2020-04-02 11:19:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |         elif self.startMode_ == DebuggerStartMode.AttachCore: | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |             coreFile = args.get('coreFile', '') | 
					
						
							| 
									
										
										
										
											2015-02-27 11:56:03 +01:00
										 |  |  |             self.process = self.target.LoadCore(coreFile) | 
					
						
							| 
									
										
										
										
											2018-02-07 15:23:43 +01:00
										 |  |  |             if self.process.IsValid(): | 
					
						
							|  |  |  |                 self.reportState('enginerunokandinferiorunrunnable') | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 self.reportState('enginerunfailed') | 
					
						
							| 
									
										
										
										
											2013-10-01 02:30:12 +02:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2019-08-05 16:26:20 +02:00
										 |  |  |             launchInfo = lldb.SBLaunchInfo(self.processArgs_) | 
					
						
							| 
									
										
										
										
											2016-09-26 13:47:19 +02:00
										 |  |  |             launchInfo.SetWorkingDirectory(self.workingDirectory_) | 
					
						
							| 
									
										
										
										
											2016-12-06 15:39:05 +01:00
										 |  |  |             launchInfo.SetEnvironmentEntries(self.environment_, False) | 
					
						
							| 
									
										
										
										
											2014-02-28 13:03:21 +01:00
										 |  |  |             if self.breakOnMain_: | 
					
						
							|  |  |  |                 self.createBreakpointAtMain() | 
					
						
							| 
									
										
										
										
											2013-10-01 02:30:12 +02:00
										 |  |  |             self.process = self.target.Launch(launchInfo, error) | 
					
						
							| 
									
										
										
										
											2013-11-01 11:32:04 +01:00
										 |  |  |             if not error.Success(): | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |                 self.report(self.describeError(error)) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                 self.reportState('enginerunfailed') | 
					
						
							| 
									
										
										
										
											2013-10-29 22:25:41 +01:00
										 |  |  |                 return | 
					
						
							|  |  |  |             self.report('pid="%s"' % self.process.GetProcessID()) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             self.reportState('enginerunandinferiorrunok') | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 12:49:01 +02:00
										 |  |  |         s = threading.Thread(target=self.loop, args=[]) | 
					
						
							|  |  |  |         s.start() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-22 17:55:20 +02:00
										 |  |  |     def loop(self): | 
					
						
							| 
									
										
										
										
											2013-05-31 15:27:54 +02:00
										 |  |  |         event = lldb.SBEvent() | 
					
						
							| 
									
										
										
										
											2020-01-13 11:02:27 +01:00
										 |  |  |         #broadcaster = self.target.GetBroadcaster() | 
					
						
							| 
									
										
										
										
											2014-09-22 17:55:20 +02:00
										 |  |  |         listener = self.debugger.GetListener() | 
					
						
							| 
									
										
										
										
											2020-01-13 11:02:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-31 15:27:54 +02:00
										 |  |  |         while True: | 
					
						
							| 
									
										
										
										
											2019-09-25 13:15:26 +02:00
										 |  |  |             while listener.GetNextEvent(event): | 
					
						
							|  |  |  |                 self.handleEvent(event) | 
					
						
							| 
									
										
										
										
											2020-01-13 11:02:27 +01:00
										 |  |  |             time.sleep(0.25) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             #if listener.WaitForEventForBroadcaster(0, broadcaster, event): | 
					
						
							|  |  |  |             #    self.handleEvent(event) | 
					
						
							| 
									
										
										
										
											2019-09-25 13:15:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-07 08:46:51 +02:00
										 |  |  |     def describeError(self, error): | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |         desc = lldb.SBStream() | 
					
						
							|  |  |  |         error.GetDescription(desc) | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |         result = 'success="%d",' % int(error.Success()) | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         result += 'error={type="%s"' % error.GetType() | 
					
						
							|  |  |  |         if error.GetType(): | 
					
						
							|  |  |  |             result += ',status="%s"' % error.GetCString() | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |         result += ',code="%s"' % error.GetError() | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |         result += ',desc="%s"}' % toCString(desc.GetData()) | 
					
						
							| 
									
										
										
										
											2013-05-07 08:46:51 +02:00
										 |  |  |         return result | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |     def describeStatus(self, status): | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |         return 'status="%s",' % toCString(status) | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def describeLocation(self, frame): | 
					
						
							|  |  |  |         if int(frame.pc) == 0xffffffffffffffff: | 
					
						
							|  |  |  |             return '' | 
					
						
							| 
									
										
										
										
											2015-10-09 15:00:20 +02:00
										 |  |  |         fileName = fileNameAsString(frame.line_entry.file) | 
					
						
							|  |  |  |         function = frame.GetFunctionName() | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         line = frame.line_entry.line | 
					
						
							| 
									
										
										
										
											2015-10-09 15:00:20 +02:00
										 |  |  |         return 'location={file="%s",line="%s",address="%s",function="%s"}' \ | 
					
						
							|  |  |  |             % (fileName, line, frame.pc, function) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def currentThread(self): | 
					
						
							| 
									
										
										
										
											2014-01-29 11:43:11 +01:00
										 |  |  |         return None if self.process is None else self.process.GetSelectedThread() | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def currentFrame(self): | 
					
						
							| 
									
										
										
										
											2014-01-29 11:43:11 +01:00
										 |  |  |         thread = self.currentThread() | 
					
						
							|  |  |  |         return None if thread is None else thread.GetSelectedFrame() | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-11 15:27:24 +01:00
										 |  |  |     def firstStoppedThread(self): | 
					
						
							| 
									
										
										
										
											2020-02-24 10:37:40 +01:00
										 |  |  |         for i in range(0, self.process.GetNumThreads()): | 
					
						
							| 
									
										
										
										
											2013-11-11 15:27:24 +01:00
										 |  |  |             thread = self.process.GetThreadAtIndex(i) | 
					
						
							| 
									
										
										
										
											2013-12-02 10:37:16 +01:00
										 |  |  |             reason = thread.GetStopReason() | 
					
						
							|  |  |  |             if (reason == lldb.eStopReasonBreakpoint or | 
					
						
							|  |  |  |                     reason == lldb.eStopReasonException or | 
					
						
							|  |  |  |                     reason == lldb.eStopReasonPlanComplete or | 
					
						
							|  |  |  |                     reason == lldb.eStopReasonSignal or | 
					
						
							|  |  |  |                     reason == lldb.eStopReasonWatchpoint): | 
					
						
							| 
									
										
										
										
											2013-11-11 15:27:24 +01:00
										 |  |  |                 return thread | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |     def fetchThreads(self, args): | 
					
						
							|  |  |  |         result = 'threads=[' | 
					
						
							| 
									
										
										
										
											2020-02-24 10:37:40 +01:00
										 |  |  |         for i in range(0, self.process.GetNumThreads()): | 
					
						
							| 
									
										
										
										
											2013-05-02 14:57:06 +02:00
										 |  |  |             thread = self.process.GetThreadAtIndex(i) | 
					
						
							| 
									
										
										
										
											2015-02-04 14:15:14 +01:00
										 |  |  |             if thread.is_stopped: | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                 state = 'stopped' | 
					
						
							| 
									
										
										
										
											2015-02-04 14:15:14 +01:00
										 |  |  |             elif thread.is_suspended: | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                 state = 'suspended' | 
					
						
							| 
									
										
										
										
											2015-02-04 14:15:14 +01:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                 state = 'unknown' | 
					
						
							| 
									
										
										
										
											2015-02-04 14:15:14 +01:00
										 |  |  |             reason = thread.GetStopReason() | 
					
						
							| 
									
										
										
										
											2013-05-22 12:06:56 +02:00
										 |  |  |             result += '{id="%d"' % thread.GetThreadID() | 
					
						
							|  |  |  |             result += ',index="%s"' % i | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |             result += ',details="%s"' % toCString(thread.GetQueueName()) | 
					
						
							| 
									
										
										
										
											2015-02-04 14:15:14 +01:00
										 |  |  |             result += ',stop-reason="%s"' % self.stopReason(thread.GetStopReason()) | 
					
						
							|  |  |  |             result += ',state="%s"' % state | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |             result += ',name="%s"' % toCString(thread.GetName()) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |             result += ',frame={' | 
					
						
							|  |  |  |             frame = thread.GetFrameAtIndex(0) | 
					
						
							|  |  |  |             result += 'pc="0x%x"' % frame.pc | 
					
						
							|  |  |  |             result += ',addr="0x%x"' % frame.pc | 
					
						
							|  |  |  |             result += ',fp="0x%x"' % frame.fp | 
					
						
							| 
									
										
										
										
											2013-05-29 16:59:16 +02:00
										 |  |  |             result += ',func="%s"' % frame.GetFunctionName() | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |             result += ',line="%s"' % frame.line_entry.line | 
					
						
							| 
									
										
										
										
											2015-10-08 16:19:57 +02:00
										 |  |  |             result += ',fullname="%s"' % fileNameAsString(frame.line_entry.file) | 
					
						
							|  |  |  |             result += ',file="%s"' % fileNameAsString(frame.line_entry.file) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |             result += '}},' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         result += '],current-thread-id="%s"' % self.currentThread().id | 
					
						
							|  |  |  |         self.reportResult(result, args) | 
					
						
							| 
									
										
										
										
											2015-03-25 16:34:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-11 15:27:24 +01:00
										 |  |  |     def firstUsableFrame(self, thread): | 
					
						
							| 
									
										
										
										
											2020-02-24 10:37:40 +01:00
										 |  |  |         for i in range(10): | 
					
						
							| 
									
										
										
										
											2013-06-14 10:03:00 +02:00
										 |  |  |             frame = thread.GetFrameAtIndex(i) | 
					
						
							|  |  |  |             lineEntry = frame.GetLineEntry() | 
					
						
							|  |  |  |             line = lineEntry.GetLine() | 
					
						
							|  |  |  |             if line != 0: | 
					
						
							|  |  |  |                 return i | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |     def fetchStack(self, args): | 
					
						
							| 
									
										
										
										
											2013-11-05 16:12:31 +01:00
										 |  |  |         if not self.process: | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |             self.reportResult('msg="No process"', args) | 
					
						
							| 
									
										
										
										
											2013-11-05 16:12:31 +01:00
										 |  |  |             return | 
					
						
							|  |  |  |         thread = self.currentThread() | 
					
						
							|  |  |  |         if not thread: | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |             self.reportResult('msg="No thread"', args) | 
					
						
							| 
									
										
										
										
											2013-11-05 16:12:31 +01:00
										 |  |  |             return | 
					
						
							| 
									
										
										
										
											2014-02-03 13:47:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-08 16:19:57 +02:00
										 |  |  |         isNativeMixed = int(args.get('nativemixed', 0)) | 
					
						
							| 
									
										
										
										
											2021-05-04 14:55:33 +02:00
										 |  |  |         extraQml = int(args.get('extraqml', '0')) | 
					
						
							| 
									
										
										
										
											2014-02-03 13:47:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-05 14:19:32 +01:00
										 |  |  |         limit = args.get('stacklimit', -1) | 
					
						
							|  |  |  |         (n, isLimited) = (limit, True) if limit > 0 else (thread.GetNumFrames(), False) | 
					
						
							| 
									
										
										
										
											2015-02-04 17:21:55 +01:00
										 |  |  |         self.currentCallContext = None | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |         result = 'stack={current-thread="%d"' % thread.GetThreadID() | 
					
						
							| 
									
										
										
										
											2013-11-05 16:12:31 +01:00
										 |  |  |         result += ',frames=[' | 
					
						
							| 
									
										
										
										
											2021-05-04 14:55:33 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         ii = 0 | 
					
						
							|  |  |  |         if extraQml: | 
					
						
							|  |  |  |             ns = self.qtNamespace() | 
					
						
							|  |  |  |             needle = self.qtNamespace() + 'QV4::ExecutionEngine' | 
					
						
							|  |  |  |             pats = [ | 
					
						
							|  |  |  |                     '{0}qt_v4StackTraceForEngine((void*)0x{1:x})', | 
					
						
							|  |  |  |                     '{0}qt_v4StackTrace((({0}QV4::ExecutionEngine *)0x{1:x})->currentContext())', | 
					
						
							|  |  |  |                     '{0}qt_v4StackTrace((({0}QV4::ExecutionEngine *)0x{1:x})->currentContext)', | 
					
						
							|  |  |  |                    ] | 
					
						
							|  |  |  |             done = False | 
					
						
							|  |  |  |             while ii < n and not done: | 
					
						
							|  |  |  |                 res = None | 
					
						
							|  |  |  |                 frame = thread.GetFrameAtIndex(ii) | 
					
						
							| 
									
										
										
										
											2021-05-06 16:11:24 +02:00
										 |  |  |                 if not frame.IsValid(): | 
					
						
							|  |  |  |                     break | 
					
						
							| 
									
										
										
										
											2021-05-04 14:55:33 +02:00
										 |  |  |                 for variable in frame.GetVariables(True, True, False, True): | 
					
						
							|  |  |  |                     if not variable.GetType().IsPointerType(): | 
					
						
							|  |  |  |                         continue | 
					
						
							|  |  |  |                     derefvar = variable.Dereference() | 
					
						
							|  |  |  |                     if derefvar.GetType().GetName() != needle: | 
					
						
							|  |  |  |                         continue | 
					
						
							|  |  |  |                     addr = derefvar.GetLoadAddress() | 
					
						
							|  |  |  |                     for pat in pats: | 
					
						
							|  |  |  |                         exp = pat.format(ns, addr) | 
					
						
							|  |  |  |                         val = frame.EvaluateExpression(exp) | 
					
						
							|  |  |  |                         err = val.GetError() | 
					
						
							|  |  |  |                         res = str(val) | 
					
						
							|  |  |  |                         if err.Fail(): | 
					
						
							|  |  |  |                             continue | 
					
						
							|  |  |  |                         pos = res.find('"stack=[') | 
					
						
							|  |  |  |                         if pos == -1: | 
					
						
							|  |  |  |                             continue | 
					
						
							|  |  |  |                         res = res[pos + 8:-2] | 
					
						
							|  |  |  |                         res = res.replace('\\\"', '\"') | 
					
						
							|  |  |  |                         res = res.replace('func=', 'function=') | 
					
						
							|  |  |  |                         result += res | 
					
						
							|  |  |  |                         done = True | 
					
						
							|  |  |  |                         break | 
					
						
							|  |  |  |                 ii += 1 | 
					
						
							| 
									
										
										
										
											2021-05-06 16:11:24 +02:00
										 |  |  |             # if we have not found a qml stack do not omit original stack | 
					
						
							|  |  |  |             if not done: | 
					
						
							|  |  |  |                 DumperBase.warn("Failed to fetch qml stack - you need Qt debug information") | 
					
						
							|  |  |  |                 ii = 0 | 
					
						
							| 
									
										
										
										
											2021-05-04 14:55:33 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         for i in range(n - ii): | 
					
						
							| 
									
										
										
										
											2013-11-05 16:12:31 +01:00
										 |  |  |             frame = thread.GetFrameAtIndex(i) | 
					
						
							| 
									
										
										
										
											2014-02-03 13:47:26 +01:00
										 |  |  |             if not frame.IsValid(): | 
					
						
							|  |  |  |                 isLimited = False | 
					
						
							|  |  |  |                 break | 
					
						
							| 
									
										
										
										
											2015-02-04 13:29:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-05 16:12:31 +01:00
										 |  |  |             lineEntry = frame.GetLineEntry() | 
					
						
							| 
									
										
										
										
											2015-02-04 13:29:42 +01:00
										 |  |  |             lineNumber = lineEntry.GetLine() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             pc = frame.GetPC() | 
					
						
							|  |  |  |             level = frame.idx | 
					
						
							|  |  |  |             addr = frame.GetPCAddress().GetLoadAddress(self.target) | 
					
						
							| 
									
										
										
										
											2015-10-09 15:00:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-04 13:29:42 +01:00
										 |  |  |             functionName = frame.GetFunctionName() | 
					
						
							| 
									
										
										
										
											2018-11-22 09:42:35 +01:00
										 |  |  |             module = frame.GetModule() | 
					
						
							| 
									
										
										
										
											2015-02-04 13:29:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             if isNativeMixed and functionName == '::qt_qmlDebugMessageAvailable()': | 
					
						
							| 
									
										
										
										
											2015-10-09 15:00:20 +02:00
										 |  |  |                 interpreterStack = self.extractInterpreterStack() | 
					
						
							|  |  |  |                 for interpreterFrame in interpreterStack.get('frames', []): | 
					
						
							|  |  |  |                     function = interpreterFrame.get('function', '') | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |                     fileName = toCString(interpreterFrame.get('file', '')) | 
					
						
							| 
									
										
										
										
											2015-10-09 15:00:20 +02:00
										 |  |  |                     language = interpreterFrame.get('language', '') | 
					
						
							|  |  |  |                     lineNumber = interpreterFrame.get('line', 0) | 
					
						
							|  |  |  |                     context = interpreterFrame.get('context', 0) | 
					
						
							|  |  |  |                     result += ('frame={function="%s",file="%s",' | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                                'line="%s",language="%s",context="%s"}' | 
					
						
							|  |  |  |                                % (function, fileName, lineNumber, language, context)) | 
					
						
							| 
									
										
										
										
											2015-10-09 15:00:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             fileName = fileNameAsString(lineEntry.file) | 
					
						
							| 
									
										
										
										
											2015-02-04 13:29:42 +01:00
										 |  |  |             result += '{pc="0x%x"' % pc | 
					
						
							|  |  |  |             result += ',level="%d"' % level | 
					
						
							| 
									
										
										
										
											2015-10-08 16:19:57 +02:00
										 |  |  |             result += ',address="0x%x"' % addr | 
					
						
							|  |  |  |             result += ',function="%s"' % functionName | 
					
						
							| 
									
										
										
										
											2015-02-04 13:29:42 +01:00
										 |  |  |             result += ',line="%d"' % lineNumber | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |             result += ',module="%s"' % toCString(module) | 
					
						
							| 
									
										
										
										
											2015-10-08 16:19:57 +02:00
										 |  |  |             result += ',file="%s"},' % fileName | 
					
						
							| 
									
										
										
										
											2014-02-03 13:47:26 +01:00
										 |  |  |         result += ']' | 
					
						
							|  |  |  |         result += ',hasmore="%d"' % isLimited | 
					
						
							|  |  |  |         result += ',limit="%d"' % limit | 
					
						
							|  |  |  |         result += '}' | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         self.reportResult(result, args) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def reportResult(self, result, args): | 
					
						
							|  |  |  |         self.report('result={token="%s",%s}' % (args.get("token", 0), result)) | 
					
						
							| 
									
										
										
										
											2015-02-24 11:33:25 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-05 10:41:16 +01:00
										 |  |  |     def reportToken(self, args): | 
					
						
							|  |  |  |         if "token" in args: | 
					
						
							|  |  |  |             # Unusual syntax intended, to support the double-click in left | 
					
						
							|  |  |  |             # logview pane feature. | 
					
						
							|  |  |  |             self.report('token(\"%s\")' % args["token"]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-01 14:58:57 +01:00
										 |  |  |     def reportBreakpointUpdate(self, bp): | 
					
						
							|  |  |  |         self.report('breakpointmodified={%s}' % self.describeBreakpoint(bp)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-22 10:20:01 +02:00
										 |  |  |     def readRawMemory(self, address, size): | 
					
						
							| 
									
										
										
										
											2013-05-22 14:30:36 +02:00
										 |  |  |         if size == 0: | 
					
						
							| 
									
										
										
										
											2016-09-06 08:54:43 +02:00
										 |  |  |             return bytes() | 
					
						
							| 
									
										
										
										
											2013-05-22 14:30:36 +02:00
										 |  |  |         error = lldb.SBError() | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |         #DumperBase.warn("READ: %s %s" % (address, size)) | 
					
						
							| 
									
										
										
										
											2016-09-06 08:54:43 +02:00
										 |  |  |         res = self.process.ReadMemory(address, size, error) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |         if res is None or len(res) != size: | 
					
						
							|  |  |  |             # Using code in e.g. readToFirstZero relies on exceptions. | 
					
						
							|  |  |  |             raise RuntimeError("Unreadable %s bytes at 0x%x" % (size, address)) | 
					
						
							| 
									
										
										
										
											2016-09-06 08:54:43 +02:00
										 |  |  |         return res | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-07 08:40:43 +01:00
										 |  |  |     def findStaticMetaObject(self, type): | 
					
						
							|  |  |  |         symbolName = self.mangleName(type.name + '::staticMetaObject') | 
					
						
							| 
									
										
										
										
											2016-07-22 10:20:01 +02:00
										 |  |  |         symbol = self.target.FindFirstGlobalVariable(symbolName) | 
					
						
							| 
									
										
										
										
											2016-09-06 08:54:43 +02:00
										 |  |  |         return symbol.AddressOf().GetValueAsUnsigned() if symbol.IsValid() else 0 | 
					
						
							| 
									
										
										
										
											2014-04-11 13:20:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-12 13:20:21 +01:00
										 |  |  |     def findSymbol(self, symbolName): | 
					
						
							|  |  |  |         return self.target.FindFirstGlobalVariable(symbolName) | 
					
						
							| 
									
										
										
										
											2013-07-03 13:32:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-22 14:01:07 +01:00
										 |  |  |     def warn(self, msg): | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |         self.put('{name="%s",value="",type="",numchild="0"},' % toCString(msg)) | 
					
						
							| 
									
										
										
										
											2014-01-22 14:01:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-09 15:00:20 +02:00
										 |  |  |     def fetchVariables(self, args): | 
					
						
							|  |  |  |         (ok, res) = self.tryFetchInterpreterVariables(args) | 
					
						
							|  |  |  |         if ok: | 
					
						
							|  |  |  |             self.reportResult(res, args) | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-07 12:23:35 +02:00
										 |  |  |         self.setVariableFetchingOptions(args) | 
					
						
							| 
									
										
										
										
											2014-03-19 12:08:25 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 16:05:14 +02:00
										 |  |  |         # Reset certain caches whenever a step over / into / continue | 
					
						
							|  |  |  |         # happens. | 
					
						
							|  |  |  |         # FIXME: Caches are currently also cleared if currently | 
					
						
							|  |  |  |         # selected frame is changed, that shouldn't happen. | 
					
						
							|  |  |  |         if not self.partialVariable: | 
					
						
							|  |  |  |             self.resetPerStepCaches() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-29 11:43:11 +01:00
										 |  |  |         frame = self.currentFrame() | 
					
						
							|  |  |  |         if frame is None: | 
					
						
							| 
									
										
										
										
											2015-10-09 15:00:20 +02:00
										 |  |  |             self.reportResult('error="No frame"', args) | 
					
						
							| 
									
										
										
										
											2014-01-29 11:43:11 +01:00
										 |  |  |             return | 
					
						
							| 
									
										
										
										
											2015-03-26 13:03:38 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-09 15:00:20 +02:00
										 |  |  |         self.output = '' | 
					
						
							| 
									
										
										
										
											2016-10-07 12:23:35 +02:00
										 |  |  |         isPartial = len(self.partialVariable) > 0 | 
					
						
							| 
									
										
										
										
											2015-03-26 13:03:38 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-30 15:35:52 +02:00
										 |  |  |         self.currentIName = 'local' | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         self.put('data=[') | 
					
						
							| 
									
										
										
										
											2013-05-30 15:35:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-04 19:32:24 +01:00
										 |  |  |         with SubItem(self, '[statics]'): | 
					
						
							|  |  |  |             self.put('iname="%s",' % self.currentIName) | 
					
						
							|  |  |  |             self.putEmptyValue() | 
					
						
							| 
									
										
										
										
											2020-06-02 10:38:25 +02:00
										 |  |  |             self.putExpandable() | 
					
						
							| 
									
										
										
										
											2014-02-04 19:32:24 +01:00
										 |  |  |             if self.isExpanded(): | 
					
						
							|  |  |  |                 with Children(self): | 
					
						
							|  |  |  |                     statics = frame.GetVariables(False, False, True, False) | 
					
						
							|  |  |  |                     if len(statics): | 
					
						
							| 
									
										
										
										
											2020-02-24 10:37:40 +01:00
										 |  |  |                         for i in range(len(statics)): | 
					
						
							| 
									
										
										
										
											2014-02-04 19:32:24 +01:00
										 |  |  |                             staticVar = statics[i] | 
					
						
							| 
									
										
										
										
											2016-09-26 14:29:16 +02:00
										 |  |  |                             staticVar.SetPreferSyntheticValue(False) | 
					
						
							| 
									
										
										
										
											2014-02-04 19:32:24 +01:00
										 |  |  |                             typename = staticVar.GetType().GetName() | 
					
						
							|  |  |  |                             name = staticVar.GetName() | 
					
						
							|  |  |  |                             with SubItem(self, i): | 
					
						
							|  |  |  |                                 self.put('name="%s",' % name) | 
					
						
							|  |  |  |                                 self.put('iname="%s",' % self.currentIName) | 
					
						
							| 
									
										
										
										
											2016-09-06 08:54:43 +02:00
										 |  |  |                                 self.putItem(self.fromNativeValue(staticVar)) | 
					
						
							| 
									
										
										
										
											2014-02-04 19:32:24 +01:00
										 |  |  |                     else: | 
					
						
							|  |  |  |                         with SubItem(self, "None"): | 
					
						
							|  |  |  |                             self.putEmptyValue() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-20 11:52:06 +02:00
										 |  |  |         # FIXME: Implement shortcut for partial updates. | 
					
						
							|  |  |  |         #if isPartial: | 
					
						
							|  |  |  |         #    values = [frame.FindVariable(partialVariable)] | 
					
						
							|  |  |  |         #else: | 
					
						
							|  |  |  |         if True: | 
					
						
							| 
									
										
										
										
											2017-12-13 17:42:57 +01:00
										 |  |  |             values = list(frame.GetVariables(True, True, False, True)) | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |             values.reverse()  # To get shadowed vars numbered backwards. | 
					
						
							| 
									
										
										
										
											2016-09-20 11:52:06 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         variables = [] | 
					
						
							|  |  |  |         for val in values: | 
					
						
							| 
									
										
										
										
											2016-09-26 14:29:16 +02:00
										 |  |  |             val.SetPreferSyntheticValue(False) | 
					
						
							| 
									
										
										
										
											2016-09-20 11:52:06 +02:00
										 |  |  |             if not val.IsValid(): | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             self.currentContextValue = val | 
					
						
							|  |  |  |             name = val.GetName() | 
					
						
							|  |  |  |             if name is None: | 
					
						
							|  |  |  |                 # This can happen for unnamed function parameters with | 
					
						
							|  |  |  |                 # default values:  void foo(int = 0) | 
					
						
							|  |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             value = self.fromNativeFrameValue(val) | 
					
						
							| 
									
										
										
										
											2016-09-20 11:52:06 +02:00
										 |  |  |             variables.append(value) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.handleLocals(variables) | 
					
						
							| 
									
										
										
										
											2015-03-26 13:03:38 +01:00
										 |  |  |         self.handleWatches(args) | 
					
						
							| 
									
										
										
										
											2013-05-30 15:35:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         self.put('],partial="%d"' % isPartial) | 
					
						
							| 
									
										
										
										
											2015-10-09 15:00:20 +02:00
										 |  |  |         self.reportResult(self.output, args) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 11:10:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |     def fetchRegisters(self, args=None): | 
					
						
							| 
									
										
										
										
											2020-05-06 11:10:04 +02:00
										 |  |  |         if not self.process: | 
					
						
							|  |  |  |             self.reportResult('process="none",registers=[]', args) | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         frame = self.currentFrame() | 
					
						
							|  |  |  |         if not frame or not frame.IsValid(): | 
					
						
							|  |  |  |             self.reportResult('frame="none",registers=[]', args) | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = 'registers=[' | 
					
						
							|  |  |  |         for group in frame.GetRegisters(): | 
					
						
							|  |  |  |             for reg in group: | 
					
						
							| 
									
										
										
										
											2020-11-30 13:14:11 +01:00
										 |  |  |                 data = reg.GetData() | 
					
						
							|  |  |  |                 if data.GetByteOrder() == lldb.eByteOrderLittle: | 
					
						
							|  |  |  |                     value = ''.join(["%02x" % x for x in reversed(data.uint8s)]) | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     value = ''.join(["%02x" % x for x in data.uint8s]) | 
					
						
							| 
									
										
										
										
											2020-05-06 11:10:04 +02:00
										 |  |  |                 result += '{name="%s"' % reg.GetName() | 
					
						
							|  |  |  |                 result += ',value="0x%s"' % value | 
					
						
							|  |  |  |                 result += ',size="%s"' % reg.GetByteSize() | 
					
						
							|  |  |  |                 result += ',type="%s"},' % reg.GetType() | 
					
						
							|  |  |  |         result += ']' | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         self.reportResult(result, args) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 11:10:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-25 13:48:55 +02:00
										 |  |  |     def setRegister(self, args): | 
					
						
							|  |  |  |         name = args["name"] | 
					
						
							|  |  |  |         value = args["value"] | 
					
						
							|  |  |  |         result = lldb.SBCommandReturnObject() | 
					
						
							| 
									
										
										
										
											2015-08-27 13:38:41 +02:00
										 |  |  |         interp = self.debugger.GetCommandInterpreter() | 
					
						
							|  |  |  |         interp.HandleCommand("register write %s %s" % (name, value), result) | 
					
						
							| 
									
										
										
										
											2015-08-25 13:48:55 +02:00
										 |  |  |         success = result.Succeeded() | 
					
						
							|  |  |  |         if success: | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |             self.reportResult('output="%s"' % toCString(result.GetOutput()), args) | 
					
						
							| 
									
										
										
										
											2015-08-27 13:38:41 +02:00
										 |  |  |             return | 
					
						
							|  |  |  |         # Try again with  register write xmm0 "{0x00 ... 0x02}" syntax: | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |         vec = ' '.join(["0x" + value[i:i + 2] for i in range(2, len(value), 2)]) | 
					
						
							| 
									
										
										
										
											2015-08-27 13:38:41 +02:00
										 |  |  |         success = interp.HandleCommand('register write %s "{%s}"' % (name, vec), result) | 
					
						
							|  |  |  |         if success: | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |             self.reportResult('output="%s"' % toCString(result.GetOutput()), args) | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |             self.reportResult('error="%s"' % toCString(result.GetError()), args) | 
					
						
							| 
									
										
										
										
											2015-08-25 13:48:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |     def report(self, stuff): | 
					
						
							| 
									
										
										
										
											2014-03-19 12:08:25 +01:00
										 |  |  |         with self.outputLock: | 
					
						
							| 
									
										
										
										
											2015-01-30 12:36:04 +01:00
										 |  |  |             sys.stdout.write("@\n" + stuff + "@\n") | 
					
						
							| 
									
										
										
										
											2021-06-23 08:23:09 +02:00
										 |  |  |             sys.stdout.flush() | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |     def reportState(self, state): | 
					
						
							|  |  |  |         self.report('state="%s"' % state) | 
					
						
							| 
									
										
										
										
											2014-02-06 16:47:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |     def interruptInferior(self, args): | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |         if self.process is None: | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |             self.reportResult('status="No process to interrupt",success="0"', args) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.isInterrupting_ = True | 
					
						
							|  |  |  |             error = self.process.Stop() | 
					
						
							| 
									
										
										
										
											2015-10-09 15:00:20 +02:00
										 |  |  |             self.reportResult(self.describeError(error), args) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |     def detachInferior(self, args): | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |         if self.process is None: | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |             self.reportResult('status="No process to detach from."', args) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |         else: | 
					
						
							|  |  |  |             error = self.process.Detach() | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |             self.reportResult(self.describeError(error), args) | 
					
						
							| 
									
										
										
										
											2013-04-10 13:55:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |     def continueInferior(self, args): | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |         if self.process is None: | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |             self.reportResult('status="No process to continue."', args) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |             # Can fail when attaching to GDBserver. | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |             error = self.process.Continue() | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |             self.reportResult(self.describeError(error), args) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |     def quitDebugger(self, args): | 
					
						
							| 
									
										
										
										
											2014-03-19 12:12:24 +01:00
										 |  |  |         self.reportState("inferiorshutdownrequested") | 
					
						
							| 
									
										
										
										
											2013-06-24 17:40:00 +02:00
										 |  |  |         self.process.Kill() | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         self.reportResult('', args) | 
					
						
							| 
									
										
										
										
											2013-06-24 17:40:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-01 14:58:57 +01:00
										 |  |  |     def handleBreakpointEvent(self, event): | 
					
						
							|  |  |  |         eventType = lldb.SBBreakpoint.GetBreakpointEventTypeFromEvent(event) | 
					
						
							|  |  |  |         # handle only the resolved locations for now.. | 
					
						
							|  |  |  |         if eventType & lldb.eBreakpointEventTypeLocationsResolved: | 
					
						
							|  |  |  |             bp = lldb.SBBreakpoint.GetBreakpointFromEvent(event) | 
					
						
							|  |  |  |             if bp is not None: | 
					
						
							|  |  |  |                 self.reportBreakpointUpdate(bp) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |     def handleEvent(self, event): | 
					
						
							| 
									
										
										
										
											2019-03-01 14:58:57 +01:00
										 |  |  |         if lldb.SBBreakpoint.EventIsBreakpointEvent(event): | 
					
						
							|  |  |  |             self.handleBreakpointEvent(event) | 
					
						
							|  |  |  |             return | 
					
						
							| 
									
										
										
										
											2019-09-25 13:15:26 +02:00
										 |  |  |         if not lldb.SBProcess.EventIsProcessEvent(event): | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             self.warn("UNEXPECTED event (%s)" % event.GetType()) | 
					
						
							| 
									
										
										
										
											2019-09-25 13:15:26 +02:00
										 |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |         out = lldb.SBStream() | 
					
						
							|  |  |  |         event.GetDescription(out) | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |         #DumperBase.warn("EVENT: %s" % event) | 
					
						
							| 
									
										
										
										
											2015-01-23 17:54:00 +01:00
										 |  |  |         eventType = event.GetType() | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |         msg = lldb.SBEvent.GetCStringFromEvent(event) | 
					
						
							|  |  |  |         flavor = event.GetDataFlavor() | 
					
						
							| 
									
										
										
										
											2013-05-02 14:31:35 +02:00
										 |  |  |         state = lldb.SBProcess.GetStateFromEvent(event) | 
					
						
							| 
									
										
										
										
											2015-02-04 13:29:42 +01:00
										 |  |  |         bp = lldb.SBBreakpoint.GetBreakpointFromEvent(event) | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |         skipEventReporting = eventType in ( | 
					
						
							|  |  |  |             lldb.SBProcess.eBroadcastBitSTDOUT, lldb.SBProcess.eBroadcastBitSTDERR) | 
					
						
							| 
									
										
										
										
											2015-02-04 13:29:42 +01:00
										 |  |  |         self.report('event={type="%s",data="%s",msg="%s",flavor="%s",state="%s",bp="%s"}' | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |                     % (eventType, toCString(out.GetData()), | 
					
						
							|  |  |  |                        toCString(msg), flavor, self.stateName(state), bp)) | 
					
						
							| 
									
										
										
										
											2019-08-02 14:07:17 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if state == lldb.eStateExited: | 
					
						
							|  |  |  |             self.eventState = state | 
					
						
							|  |  |  |             if not self.isShuttingDown_: | 
					
						
							|  |  |  |                 self.reportState("inferiorexited") | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |             self.report('exited={status="%d",desc="%s"}' | 
					
						
							|  |  |  |                         % (self.process.GetExitStatus(), | 
					
						
							|  |  |  |                            toCString(self.process.GetExitDescription()))) | 
					
						
							| 
									
										
										
										
											2019-08-02 14:07:17 +02:00
										 |  |  |         elif state != self.eventState and not skipEventReporting: | 
					
						
							|  |  |  |             self.eventState = state | 
					
						
							|  |  |  |             if state == lldb.eStateStopped: | 
					
						
							| 
									
										
										
										
											2015-02-04 13:29:42 +01:00
										 |  |  |                 stoppedThread = self.firstStoppedThread() | 
					
						
							|  |  |  |                 if stoppedThread: | 
					
						
							|  |  |  |                     #self.report("STOPPED THREAD: %s" % stoppedThread) | 
					
						
							|  |  |  |                     frame = stoppedThread.GetFrameAtIndex(0) | 
					
						
							|  |  |  |                     #self.report("FRAME: %s" % frame) | 
					
						
							|  |  |  |                     function = frame.GetFunction() | 
					
						
							| 
									
										
										
										
											2015-10-09 15:00:20 +02:00
										 |  |  |                     functionName = function.GetName() | 
					
						
							|  |  |  |                     if functionName == "::qt_qmlDebugConnectorOpen()": | 
					
						
							|  |  |  |                         self.report("RESOLVER HIT") | 
					
						
							|  |  |  |                         for resolver in self.interpreterBreakpointResolvers: | 
					
						
							|  |  |  |                             resolver() | 
					
						
							|  |  |  |                         self.report("AUTO-CONTINUE AFTER RESOLVING") | 
					
						
							|  |  |  |                         self.reportState("inferiorstopok") | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                         self.process.Continue() | 
					
						
							| 
									
										
										
										
											2015-02-04 13:29:42 +01:00
										 |  |  |                         return | 
					
						
							| 
									
										
										
										
											2015-10-14 13:26:22 +02:00
										 |  |  |                     if functionName == "::qt_qmlDebugMessageAvailable()": | 
					
						
							|  |  |  |                         self.report("ASYNC MESSAGE FROM SERVICE") | 
					
						
							|  |  |  |                         res = self.handleInterpreterMessage() | 
					
						
							| 
									
										
										
										
											2015-10-09 15:00:20 +02:00
										 |  |  |                         if not res: | 
					
						
							|  |  |  |                             self.report("EVENT NEEDS NO STOP") | 
					
						
							|  |  |  |                             self.reportState("stopped") | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                             self.process.Continue() | 
					
						
							| 
									
										
										
										
											2015-10-09 15:00:20 +02:00
										 |  |  |                             return | 
					
						
							| 
									
										
										
										
											2013-06-24 17:40:00 +02:00
										 |  |  |                 if self.isInterrupting_: | 
					
						
							|  |  |  |                     self.isInterrupting_ = False | 
					
						
							| 
									
										
										
										
											2017-09-19 12:37:56 +02:00
										 |  |  |                     self.reportState("inferiorstopok") | 
					
						
							| 
									
										
										
										
											2013-06-24 17:40:00 +02:00
										 |  |  |                 else: | 
					
						
							| 
									
										
										
										
											2014-03-19 12:12:24 +01:00
										 |  |  |                     self.reportState("stopped") | 
					
						
							| 
									
										
										
										
											2013-06-24 17:40:00 +02:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2019-08-02 14:07:17 +02:00
										 |  |  |                 self.reportState(self.stateName(state)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |         if eventType == lldb.SBProcess.eBroadcastBitStateChanged:  # 1 | 
					
						
							| 
									
										
										
										
											2013-06-14 10:03:00 +02:00
										 |  |  |             state = self.process.GetState() | 
					
						
							|  |  |  |             if state == lldb.eStateStopped: | 
					
						
							| 
									
										
										
										
											2013-11-11 15:27:24 +01:00
										 |  |  |                 stoppedThread = self.firstStoppedThread() | 
					
						
							|  |  |  |                 if stoppedThread: | 
					
						
							|  |  |  |                     self.process.SetSelectedThread(stoppedThread) | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |         elif eventType == lldb.SBProcess.eBroadcastBitInterrupt:  # 2 | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |             pass | 
					
						
							| 
									
										
										
										
											2015-01-23 17:54:00 +01:00
										 |  |  |         elif eventType == lldb.SBProcess.eBroadcastBitSTDOUT: | 
					
						
							| 
									
										
										
										
											2020-12-14 08:25:11 +01:00
										 |  |  |             self.handleInferiorOutput(self.process.GetSTDOUT, "stdout") | 
					
						
							| 
									
										
										
										
											2015-01-23 17:54:00 +01:00
										 |  |  |         elif eventType == lldb.SBProcess.eBroadcastBitSTDERR: | 
					
						
							| 
									
										
										
										
											2020-12-14 08:25:11 +01:00
										 |  |  |             self.handleInferiorOutput(self.process.GetSTDERR, "stderr") | 
					
						
							| 
									
										
										
										
											2015-01-23 17:54:00 +01:00
										 |  |  |         elif eventType == lldb.SBProcess.eBroadcastBitProfileData: | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-14 08:25:11 +01:00
										 |  |  |     def handleInferiorOutput(self, proc, channel): | 
					
						
							|  |  |  |         while True: | 
					
						
							|  |  |  |             msg = proc(1024) | 
					
						
							|  |  |  |             if msg == None or len(msg) == 0: | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |             self.report('output={channel="%s",data="%s"}' % (channel, self.hexencode(msg))) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-05 19:06:24 +01:00
										 |  |  |     def describeBreakpoint(self, bp): | 
					
						
							| 
									
										
										
										
											2013-06-14 15:15:09 +02:00
										 |  |  |         isWatch = isinstance(bp, lldb.SBWatchpoint) | 
					
						
							|  |  |  |         if isWatch: | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |             result = 'lldbid="%s"' % (qqWatchpointOffset + bp.GetID()) | 
					
						
							| 
									
										
										
										
											2013-06-14 15:15:09 +02:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |             result = 'lldbid="%s"' % bp.GetID() | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |         result += ',valid="%d"' % (1 if bp.IsValid() else 0) | 
					
						
							|  |  |  |         result += ',hitcount="%d"' % bp.GetHitCount() | 
					
						
							| 
									
										
										
										
											2016-01-06 13:16:37 +01:00
										 |  |  |         if bp.IsValid(): | 
					
						
							|  |  |  |             if isinstance(bp, lldb.SBBreakpoint): | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |                 result += ',threadid="%d"' % bp.GetThreadID() | 
					
						
							|  |  |  |                 result += ',oneshot="%d"' % (1 if bp.IsOneShot() else 0) | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         cond = bp.GetCondition() | 
					
						
							|  |  |  |         result += ',condition="%s"' % self.hexencode("" if cond is None else cond) | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |         result += ',enabled="%d"' % (1 if bp.IsEnabled() else 0) | 
					
						
							|  |  |  |         result += ',valid="%d"' % (1 if bp.IsValid() else 0) | 
					
						
							|  |  |  |         result += ',ignorecount="%d"' % bp.GetIgnoreCount() | 
					
						
							| 
									
										
										
										
											2016-01-06 13:16:37 +01:00
										 |  |  |         if bp.IsValid() and isinstance(bp, lldb.SBBreakpoint): | 
					
						
							|  |  |  |             result += ',locations=[' | 
					
						
							|  |  |  |             lineEntry = None | 
					
						
							| 
									
										
										
										
											2020-02-24 10:37:40 +01:00
										 |  |  |             for i in range(bp.GetNumLocations()): | 
					
						
							| 
									
										
										
										
											2016-01-06 13:16:37 +01:00
										 |  |  |                 loc = bp.GetLocationAtIndex(i) | 
					
						
							|  |  |  |                 addr = loc.GetAddress() | 
					
						
							|  |  |  |                 lineEntry = addr.GetLineEntry() | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |                 result += '{locid="%d"' % loc.GetID() | 
					
						
							| 
									
										
										
										
											2016-01-06 13:16:37 +01:00
										 |  |  |                 result += ',function="%s"' % addr.GetFunction().GetName() | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |                 result += ',enabled="%d"' % (1 if loc.IsEnabled() else 0) | 
					
						
							|  |  |  |                 result += ',resolved="%d"' % (1 if loc.IsResolved() else 0) | 
					
						
							|  |  |  |                 result += ',valid="%d"' % (1 if loc.IsValid() else 0) | 
					
						
							|  |  |  |                 result += ',ignorecount="%d"' % loc.GetIgnoreCount() | 
					
						
							|  |  |  |                 result += ',file="%s"' % toCString(lineEntry.GetFileSpec()) | 
					
						
							|  |  |  |                 result += ',line="%d"' % lineEntry.GetLine() | 
					
						
							| 
									
										
										
										
											2016-01-06 13:16:37 +01:00
										 |  |  |                 result += ',addr="%s"},' % addr.GetFileAddress() | 
					
						
							|  |  |  |             result += ']' | 
					
						
							|  |  |  |             if lineEntry is not None: | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |                 result += ',file="%s"' % toCString(lineEntry.GetFileSpec()) | 
					
						
							|  |  |  |                 result += ',line="%d"' % lineEntry.GetLine() | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |         return result | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-28 13:03:21 +01:00
										 |  |  |     def createBreakpointAtMain(self): | 
					
						
							|  |  |  |         return self.target.BreakpointCreateByName( | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             'main', self.target.GetExecutable().GetFilename()) | 
					
						
							| 
									
										
										
										
											2014-02-28 13:03:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-02 13:48:33 +01:00
										 |  |  |     def insertBreakpoint(self, args): | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |         bpType = args['type'] | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |         if bpType == BreakpointType.BreakpointByFileAndLine: | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             fileName = args['file'] | 
					
						
							|  |  |  |             if fileName.endswith('.js') or fileName.endswith('.qml'): | 
					
						
							| 
									
										
										
										
											2015-10-14 13:26:22 +02:00
										 |  |  |                 self.insertInterpreterBreakpoint(args) | 
					
						
							| 
									
										
										
										
											2015-02-04 13:29:42 +01:00
										 |  |  |                 return | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         extra = '' | 
					
						
							| 
									
										
										
										
											2015-02-02 13:48:33 +01:00
										 |  |  |         more = True | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |         if bpType == BreakpointType.BreakpointByFileAndLine: | 
					
						
							| 
									
										
										
										
											2014-03-05 19:06:24 +01:00
										 |  |  |             bp = self.target.BreakpointCreateByLocation( | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                 str(args['file']), int(args['line'])) | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |         elif bpType == BreakpointType.BreakpointByFunction: | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             bp = self.target.BreakpointCreateByName(args['function']) | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |         elif bpType == BreakpointType.BreakpointByAddress: | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             bp = self.target.BreakpointCreateByAddress(args['address']) | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |         elif bpType == BreakpointType.BreakpointAtMain: | 
					
						
							| 
									
										
										
										
											2014-03-05 19:06:24 +01:00
										 |  |  |             bp = self.createBreakpointAtMain() | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |         elif bpType == BreakpointType.BreakpointAtThrow: | 
					
						
							| 
									
										
										
										
											2014-03-05 19:06:24 +01:00
										 |  |  |             bp = self.target.BreakpointCreateForException( | 
					
						
							| 
									
										
										
										
											2013-06-13 18:22:44 +02:00
										 |  |  |                 lldb.eLanguageTypeC_plus_plus, False, True) | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |         elif bpType == BreakpointType.BreakpointAtCatch: | 
					
						
							| 
									
										
										
										
											2014-03-05 19:06:24 +01:00
										 |  |  |             bp = self.target.BreakpointCreateForException( | 
					
						
							| 
									
										
										
										
											2013-06-13 18:22:44 +02:00
										 |  |  |                 lldb.eLanguageTypeC_plus_plus, True, False) | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |         elif bpType == BreakpointType.WatchpointAtAddress: | 
					
						
							| 
									
										
										
										
											2013-06-14 15:15:09 +02:00
										 |  |  |             error = lldb.SBError() | 
					
						
							| 
									
										
										
										
											2016-01-06 13:16:37 +01:00
										 |  |  |             # This might yield bp.IsValid() == False and | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             # error.desc == 'process is not alive'. | 
					
						
							|  |  |  |             bp = self.target.WatchAddress(args['address'], 4, False, True, error) | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |             extra = self.describeError(error) | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |         elif bpType == BreakpointType.WatchpointAtExpression: | 
					
						
							| 
									
										
										
										
											2013-06-14 15:15:09 +02:00
										 |  |  |             # FIXME: Top level-only for now. | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 frame = self.currentFrame() | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                 value = frame.FindVariable(args['expression']) | 
					
						
							| 
									
										
										
										
											2013-06-14 15:15:09 +02:00
										 |  |  |                 error = lldb.SBError() | 
					
						
							| 
									
										
										
										
											2014-03-05 19:06:24 +01:00
										 |  |  |                 bp = self.target.WatchAddress(value.GetLoadAddress(), | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                                               value.GetByteSize(), False, True, error) | 
					
						
							| 
									
										
										
										
											2013-06-14 15:15:09 +02:00
										 |  |  |             except: | 
					
						
							| 
									
										
										
										
											2015-02-02 13:48:33 +01:00
										 |  |  |                 bp = self.target.BreakpointCreateByName(None) | 
					
						
							| 
									
										
										
										
											2013-05-16 17:37:41 +02:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2014-02-06 17:50:21 +01:00
										 |  |  |             # This leaves the unhandled breakpoint in a (harmless) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             # 'pending' state. | 
					
						
							| 
									
										
										
										
											2015-02-02 13:48:33 +01:00
										 |  |  |             bp = self.target.BreakpointCreateByName(None) | 
					
						
							|  |  |  |             more = False | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 13:16:37 +01:00
										 |  |  |         if more and bp.IsValid(): | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             bp.SetIgnoreCount(int(args['ignorecount'])) | 
					
						
							|  |  |  |             bp.SetCondition(self.hexdecode(args['condition'])) | 
					
						
							|  |  |  |             bp.SetEnabled(bool(args['enabled'])) | 
					
						
							| 
									
										
										
										
											2016-04-13 18:19:45 +02:00
										 |  |  |             bp.SetScriptCallbackBody('\n'.join([ | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                 'def foo(frame = frame, bp_loc = bp_loc, dict = internal_dict):', | 
					
						
							|  |  |  |                 '  ' + self.hexdecode(args['command']).replace('\n', '\n  '), | 
					
						
							|  |  |  |                 'from cStringIO import StringIO', | 
					
						
							|  |  |  |                 'origout = sys.stdout', | 
					
						
							|  |  |  |                 'sys.stdout = StringIO()', | 
					
						
							|  |  |  |                 'result = foo()', | 
					
						
							|  |  |  |                 'd = lldb.theDumper', | 
					
						
							|  |  |  |                 'output = d.hexencode(sys.stdout.getvalue())', | 
					
						
							|  |  |  |                 'sys.stdout = origout', | 
					
						
							| 
									
										
										
										
											2016-11-17 12:17:14 +01:00
										 |  |  |                 'd.report("output={channel=\"stderr\",data=\" + output + \"}")', | 
					
						
							| 
									
										
										
										
											2021-06-23 08:23:09 +02:00
										 |  |  |                 'sys.stdout.flush()', | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                 'if result is False:', | 
					
						
							|  |  |  |                 '  d.reportState("continueafternextstop")', | 
					
						
							|  |  |  |                 'return True' | 
					
						
							| 
									
										
										
										
											2016-04-13 18:19:45 +02:00
										 |  |  |             ])) | 
					
						
							| 
									
										
										
										
											2016-01-06 13:16:37 +01:00
										 |  |  |             if isinstance(bp, lldb.SBBreakpoint): | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                 bp.SetOneShot(bool(args['oneshot'])) | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         self.reportResult(self.describeBreakpoint(bp) + extra, args) | 
					
						
							| 
									
										
										
										
											2013-05-16 17:37:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def changeBreakpoint(self, args): | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |         lldbId = int(args['lldbid']) | 
					
						
							| 
									
										
										
										
											2015-02-02 13:48:33 +01:00
										 |  |  |         if lldbId > qqWatchpointOffset: | 
					
						
							|  |  |  |             bp = self.target.FindWatchpointByID(lldbId) | 
					
						
							| 
									
										
										
										
											2013-06-14 15:15:09 +02:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2015-02-02 13:48:33 +01:00
										 |  |  |             bp = self.target.FindBreakpointByID(lldbId) | 
					
						
							| 
									
										
										
										
											2016-01-06 13:16:37 +01:00
										 |  |  |         if bp.IsValid(): | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             bp.SetIgnoreCount(int(args['ignorecount'])) | 
					
						
							|  |  |  |             bp.SetCondition(self.hexdecode(args['condition'])) | 
					
						
							|  |  |  |             bp.SetEnabled(bool(args['enabled'])) | 
					
						
							| 
									
										
										
										
											2016-01-06 13:16:37 +01:00
										 |  |  |             if isinstance(bp, lldb.SBBreakpoint): | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                 bp.SetOneShot(bool(args['oneshot'])) | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         self.reportResult(self.describeBreakpoint(bp), args) | 
					
						
							| 
									
										
										
										
											2013-05-16 17:37:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-22 14:26:28 +02:00
										 |  |  |     def enableSubbreakpoint(self, args): | 
					
						
							|  |  |  |         lldbId = int(args['lldbid']) | 
					
						
							|  |  |  |         locId = int(args['locid']) | 
					
						
							|  |  |  |         bp = self.target.FindBreakpointByID(lldbId) | 
					
						
							|  |  |  |         res = False | 
					
						
							|  |  |  |         enabled = False | 
					
						
							|  |  |  |         if bp.IsValid(): | 
					
						
							|  |  |  |             loc = bp.FindLocationByID(locId) | 
					
						
							|  |  |  |             if loc.IsValid(): | 
					
						
							|  |  |  |                 loc.SetEnabled(bool(args['enabled'])) | 
					
						
							|  |  |  |                 enabled = loc.IsEnabled() | 
					
						
							|  |  |  |                 res = True | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |         self.reportResult('success="%d",enabled="%d",locid="%d"' | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                           % (int(res), int(enabled), locId), args) | 
					
						
							| 
									
										
										
										
											2018-10-22 14:26:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-16 17:37:41 +02:00
										 |  |  |     def removeBreakpoint(self, args): | 
					
						
							| 
									
										
										
										
											2015-02-02 13:48:33 +01:00
										 |  |  |         lldbId = int(args['lldbid']) | 
					
						
							|  |  |  |         if lldbId > qqWatchpointOffset: | 
					
						
							|  |  |  |             res = self.target.DeleteWatchpoint(lldbId - qqWatchpointOffset) | 
					
						
							|  |  |  |         res = self.target.BreakpointDelete(lldbId) | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |         self.reportResult('success="%d"' % int(res), args) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |     def fetchModules(self, args): | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |         result = 'modules=[' | 
					
						
							| 
									
										
										
										
											2020-02-24 10:37:40 +01:00
										 |  |  |         for i in range(self.target.GetNumModules()): | 
					
						
							| 
									
										
										
										
											2013-05-22 14:30:36 +02:00
										 |  |  |             module = self.target.GetModuleAtIndex(i) | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |             result += '{file="%s"' % toCString(module.file.fullpath) | 
					
						
							|  |  |  |             result += ',name="%s"' % toCString(module.file.basename) | 
					
						
							|  |  |  |             result += ',addrsize="%d"' % module.addr_size | 
					
						
							| 
									
										
										
										
											2013-05-07 11:39:31 +02:00
										 |  |  |             result += ',triple="%s"' % module.triple | 
					
						
							|  |  |  |             #result += ',sections={' | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |             #for section in module.sections: | 
					
						
							|  |  |  |             #    result += '[name="%s"' % section.name | 
					
						
							|  |  |  |             #    result += ',addr="%s"' % section.addr | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |             #    result += ',size="%d"],' % section.size | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |             #result += '}' | 
					
						
							|  |  |  |             result += '},' | 
					
						
							|  |  |  |         result += ']' | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         self.reportResult(result, args) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |     def fetchSymbols(self, args): | 
					
						
							| 
									
										
										
										
											2013-05-07 12:34:10 +02:00
										 |  |  |         moduleName = args['module'] | 
					
						
							| 
									
										
										
										
											2013-05-07 11:39:31 +02:00
										 |  |  |         #file = lldb.SBFileSpec(moduleName) | 
					
						
							|  |  |  |         #module = self.target.FindModule(file) | 
					
						
							| 
									
										
										
										
											2020-02-24 10:37:40 +01:00
										 |  |  |         for i in range(self.target.GetNumModules()): | 
					
						
							| 
									
										
										
										
											2013-05-22 14:30:36 +02:00
										 |  |  |             module = self.target.GetModuleAtIndex(i) | 
					
						
							| 
									
										
										
										
											2013-05-29 16:24:17 +02:00
										 |  |  |             if module.file.fullpath == moduleName: | 
					
						
							| 
									
										
										
										
											2013-05-07 11:39:31 +02:00
										 |  |  |                 break | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         result = 'symbols={valid="%s"' % module.IsValid() | 
					
						
							| 
									
										
										
										
											2013-05-07 11:39:31 +02:00
										 |  |  |         result += ',sections="%s"' % module.GetNumSections() | 
					
						
							|  |  |  |         result += ',symbols=[' | 
					
						
							|  |  |  |         for symbol in module.symbols: | 
					
						
							|  |  |  |             startAddress = symbol.GetStartAddress().GetLoadAddress(self.target) | 
					
						
							|  |  |  |             endAddress = symbol.GetEndAddress().GetLoadAddress(self.target) | 
					
						
							|  |  |  |             result += '{type="%s"' % symbol.GetType() | 
					
						
							|  |  |  |             result += ',name="%s"' % symbol.GetName() | 
					
						
							|  |  |  |             result += ',address="0x%x"' % startAddress | 
					
						
							|  |  |  |             result += ',demangled="%s"' % symbol.GetMangledName() | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |             result += ',size="%d"' % (endAddress - startAddress) | 
					
						
							| 
									
										
										
										
											2013-05-07 11:39:31 +02:00
										 |  |  |             result += '},' | 
					
						
							|  |  |  |         result += ']}' | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         self.reportResult(result, args) | 
					
						
							| 
									
										
										
										
											2013-05-07 11:39:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |     def executeNext(self, args): | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |         self.currentThread().StepOver() | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         self.reportResult('', args) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |     def executeNextI(self, args): | 
					
						
							| 
									
										
										
										
											2018-07-24 12:12:28 +02:00
										 |  |  |         self.currentThread().StepInstruction(True) | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         self.reportResult('', args) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |     def executeStep(self, args): | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |         self.currentThread().StepInto() | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         self.reportResult('', args) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |     def shutdownInferior(self, args): | 
					
						
							| 
									
										
										
										
											2013-05-29 15:38:49 +02:00
										 |  |  |         self.isShuttingDown_ = True | 
					
						
							| 
									
										
										
										
											2017-12-14 09:36:41 +01:00
										 |  |  |         if self.process is not None: | 
					
						
							| 
									
										
										
										
											2014-06-02 16:45:12 +02:00
										 |  |  |             state = self.process.GetState() | 
					
						
							|  |  |  |             if state == lldb.eStateStopped: | 
					
						
							|  |  |  |                 self.process.Kill() | 
					
						
							| 
									
										
										
										
											2017-12-14 09:36:41 +01:00
										 |  |  |         self.reportState('inferiorshutdownfinished') | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         self.reportResult('', args) | 
					
						
							| 
									
										
										
										
											2013-05-29 15:38:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |     def quit(self, args): | 
					
						
							| 
									
										
										
										
											2017-12-14 09:11:16 +01:00
										 |  |  |         self.reportState('engineshutdownfinished') | 
					
						
							| 
									
										
										
										
											2013-05-29 15:38:49 +02:00
										 |  |  |         self.process.Kill() | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         self.reportResult('', args) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |     def executeStepI(self, args): | 
					
						
							| 
									
										
										
										
											2018-07-24 12:12:28 +02:00
										 |  |  |         self.currentThread().StepInstruction(False) | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         self.reportResult('', args) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |     def executeStepOut(self, args={}): | 
					
						
							| 
									
										
										
										
											2013-05-24 08:32:12 +02:00
										 |  |  |         self.currentThread().StepOut() | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         self.reportResult('', args) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-06 16:47:07 +01:00
										 |  |  |     def executeRunToLocation(self, args): | 
					
						
							| 
									
										
										
										
											2015-03-05 10:41:16 +01:00
										 |  |  |         self.reportToken(args) | 
					
						
							| 
									
										
										
										
											2014-02-06 16:47:07 +01:00
										 |  |  |         addr = args.get('address', 0) | 
					
						
							|  |  |  |         if addr: | 
					
						
							| 
									
										
										
										
											2015-08-10 13:25:30 +02:00
										 |  |  |             # Does not seem to hit anything on Linux: | 
					
						
							|  |  |  |             # self.currentThread().RunToAddress(addr) | 
					
						
							|  |  |  |             bp = self.target.BreakpointCreateByAddress(addr) | 
					
						
							|  |  |  |             if bp.GetNumLocations() == 0: | 
					
						
							|  |  |  |                 self.target.BreakpointDelete(bp.GetID()) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                 self.reportResult(self.describeStatus('No target location found.') | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                                   + self.describeLocation(frame), args) | 
					
						
							| 
									
										
										
										
											2015-08-10 13:25:30 +02:00
										 |  |  |                 return | 
					
						
							|  |  |  |             bp.SetOneShot(True) | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |             self.reportResult('', args) | 
					
						
							| 
									
										
										
										
											2015-08-10 13:25:30 +02:00
										 |  |  |             self.process.Continue() | 
					
						
							| 
									
										
										
										
											2014-02-06 16:47:07 +01:00
										 |  |  |         else: | 
					
						
							|  |  |  |             frame = self.currentFrame() | 
					
						
							|  |  |  |             file = args['file'] | 
					
						
							|  |  |  |             line = int(args['line']) | 
					
						
							|  |  |  |             error = self.currentThread().StepOverUntil(frame, lldb.SBFileSpec(file), line) | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |             self.reportResult(self.describeError(error), args) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             self.reportState('running') | 
					
						
							|  |  |  |             self.reportState('stopped') | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-06 15:40:23 +01:00
										 |  |  |     def executeJumpToLocation(self, args): | 
					
						
							| 
									
										
										
										
											2015-03-05 10:41:16 +01:00
										 |  |  |         self.reportToken(args) | 
					
						
							| 
									
										
										
										
											2014-02-05 17:03:51 +01:00
										 |  |  |         frame = self.currentFrame() | 
					
						
							|  |  |  |         if not frame: | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             self.reportResult(self.describeStatus('No frame available.'), args) | 
					
						
							| 
									
										
										
										
											2014-02-05 17:03:51 +01:00
										 |  |  |             return | 
					
						
							| 
									
										
										
										
											2014-02-06 15:40:23 +01:00
										 |  |  |         addr = args.get('address', 0) | 
					
						
							|  |  |  |         if addr: | 
					
						
							|  |  |  |             bp = self.target.BreakpointCreateByAddress(addr) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             bp = self.target.BreakpointCreateByLocation( | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                 str(args['file']), int(args['line'])) | 
					
						
							| 
									
										
										
										
											2014-02-05 17:03:51 +01:00
										 |  |  |         if bp.GetNumLocations() == 0: | 
					
						
							|  |  |  |             self.target.BreakpointDelete(bp.GetID()) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             status = 'No target location found.' | 
					
						
							| 
									
										
										
										
											2015-02-27 15:01:29 +01:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |             loc = bp.GetLocationAtIndex(0) | 
					
						
							|  |  |  |             self.target.BreakpointDelete(bp.GetID()) | 
					
						
							|  |  |  |             res = frame.SetPC(loc.GetLoadAddress()) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |             status = 'Jumped.' if res else 'Cannot jump.' | 
					
						
							| 
									
										
										
										
											2017-08-11 19:05:12 +02:00
										 |  |  |         self.report(self.describeLocation(frame)) | 
					
						
							|  |  |  |         self.reportResult(self.describeStatus(status), args) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def breakList(self): | 
					
						
							|  |  |  |         result = lldb.SBCommandReturnObject() | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |         self.debugger.GetCommandInterpreter().HandleCommand('break list', result) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |         self.report('success="%d",output="%s",error="%s"' | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |                     % (result.Succeeded(), toCString(result.GetOutput()), | 
					
						
							|  |  |  |                        toCString(result.GetError()))) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-24 10:14:11 +02:00
										 |  |  |     def activateFrame(self, args): | 
					
						
							| 
									
										
										
										
											2015-09-07 12:16:05 +02:00
										 |  |  |         self.reportToken(args) | 
					
						
							| 
									
										
										
										
											2020-05-06 10:27:09 +02:00
										 |  |  |         frame = max(0, int(args['index'])) # Can be -1 in all-asm stacks | 
					
						
							|  |  |  |         self.currentThread().SetSelectedFrame(frame) | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         self.reportResult('', args) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-29 16:24:17 +02:00
										 |  |  |     def selectThread(self, args): | 
					
						
							| 
									
										
										
										
											2015-09-07 12:16:05 +02:00
										 |  |  |         self.reportToken(args) | 
					
						
							| 
									
										
										
										
											2018-11-22 16:22:45 +01:00
										 |  |  |         self.process.SetSelectedThreadByID(int(args['id'])) | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         self.reportResult('', args) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |     def fetchFullBacktrace(self, _=None): | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |         command = 'thread backtrace all' | 
					
						
							| 
									
										
										
										
											2014-03-11 16:40:07 +01:00
										 |  |  |         result = lldb.SBCommandReturnObject() | 
					
						
							|  |  |  |         self.debugger.GetCommandInterpreter().HandleCommand(command, result) | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         self.reportResult(self.hexencode(result.GetOutput()), {}) | 
					
						
							| 
									
										
										
										
											2014-03-11 16:40:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-07 16:43:20 +02:00
										 |  |  |     def executeDebuggerCommand(self, args): | 
					
						
							| 
									
										
										
										
											2015-09-07 12:16:05 +02:00
										 |  |  |         self.reportToken(args) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |         result = lldb.SBCommandReturnObject() | 
					
						
							| 
									
										
										
										
											2013-05-07 16:43:20 +02:00
										 |  |  |         command = args['command'] | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |         self.debugger.GetCommandInterpreter().HandleCommand(command, result) | 
					
						
							|  |  |  |         success = result.Succeeded() | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |         output = toCString(result.GetOutput()) | 
					
						
							|  |  |  |         error = toCString(str(result.GetError())) | 
					
						
							| 
									
										
										
										
											2013-04-30 10:46:48 +02:00
										 |  |  |         self.report('success="%d",output="%s",error="%s"' % (success, output, error)) | 
					
						
							| 
									
										
										
										
											2013-04-10 13:55:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 10:46:05 +02:00
										 |  |  |     def executeRoundtrip(self, args): | 
					
						
							|  |  |  |         self.reportResult('', args) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |     def fetchDisassembler(self, args): | 
					
						
							| 
									
										
										
										
											2014-03-06 12:04:47 +01:00
										 |  |  |         functionName = args.get('function', '') | 
					
						
							|  |  |  |         flavor = args.get('flavor', '') | 
					
						
							|  |  |  |         function = None | 
					
						
							|  |  |  |         if len(functionName): | 
					
						
							|  |  |  |             functions = self.target.FindFunctions(functionName).functions | 
					
						
							|  |  |  |             if len(functions): | 
					
						
							|  |  |  |                 function = functions[0] | 
					
						
							|  |  |  |         if function: | 
					
						
							|  |  |  |             base = function.GetStartAddress().GetLoadAddress(self.target) | 
					
						
							|  |  |  |             instructions = function.GetInstructions(self.target) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             base = args.get('address', 0) | 
					
						
							| 
									
										
										
										
											2015-02-04 17:21:55 +01:00
										 |  |  |             if int(base) == 0xffffffffffffffff: | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |                 self.warn('INVALID DISASSEMBLER BASE') | 
					
						
							| 
									
										
										
										
											2015-02-04 17:21:55 +01:00
										 |  |  |                 return | 
					
						
							| 
									
										
										
										
											2014-03-06 12:04:47 +01:00
										 |  |  |             addr = lldb.SBAddress(base, self.target) | 
					
						
							|  |  |  |             instructions = self.target.ReadInstructions(addr, 100) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-28 14:35:25 +02:00
										 |  |  |         currentFile = None | 
					
						
							|  |  |  |         currentLine = None | 
					
						
							|  |  |  |         hunks = dict() | 
					
						
							|  |  |  |         sources = dict() | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         result = 'lines=[' | 
					
						
							| 
									
										
										
										
											2014-03-06 12:04:47 +01:00
										 |  |  |         for insn in instructions: | 
					
						
							| 
									
										
										
										
											2013-05-03 17:18:07 +02:00
										 |  |  |             comment = insn.GetComment(self.target) | 
					
						
							| 
									
										
										
										
											2015-08-28 14:35:25 +02:00
										 |  |  |             addr = insn.GetAddress() | 
					
						
							|  |  |  |             loadAddr = addr.GetLoadAddress(self.target) | 
					
						
							|  |  |  |             lineEntry = addr.GetLineEntry() | 
					
						
							|  |  |  |             if lineEntry: | 
					
						
							|  |  |  |                 lineNumber = lineEntry.GetLine() | 
					
						
							|  |  |  |                 fileName = str(lineEntry.GetFileSpec()) | 
					
						
							|  |  |  |                 if lineNumber != currentLine or fileName != currentFile: | 
					
						
							|  |  |  |                     currentLine = lineNumber | 
					
						
							|  |  |  |                     currentFile = fileName | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                     key = '%s:%s' % (fileName, lineNumber) | 
					
						
							| 
									
										
										
										
											2015-08-28 14:35:25 +02:00
										 |  |  |                     hunk = hunks.get(key, 0) + 1 | 
					
						
							|  |  |  |                     hunks[key] = hunk | 
					
						
							|  |  |  |                     source = sources.get(fileName, None) | 
					
						
							|  |  |  |                     if source is None: | 
					
						
							| 
									
										
										
										
											2016-01-19 14:11:04 +01:00
										 |  |  |                         try: | 
					
						
							|  |  |  |                             with open(fileName, 'r') as f: | 
					
						
							|  |  |  |                                 source = f.read().splitlines() | 
					
						
							|  |  |  |                                 sources[fileName] = source | 
					
						
							|  |  |  |                         except IOError as error: | 
					
						
							|  |  |  |                             # With lldb-3.8 files like /data/dev/creator-3.6/tests/ | 
					
						
							|  |  |  |                             # auto/debugger/qt_tst_dumpers_StdVector_bfNWZa/main.cpp | 
					
						
							|  |  |  |                             # with non-existent directories appear. | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |                             self.warn('FILE: %s  ERROR: %s' % (fileName, error)) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                             source = '' | 
					
						
							| 
									
										
										
											
												LLDB: Escape strings for correct parsing
Sample broken output:
>result={token="9",lldbid="1",valid="1",hitcount="0",threadid="0",oneshot="0",
condition="",enabled="1",valid="1",ignorecount="0",locations=[
{locid="1",function="foo()",enabled="1",resolved="0",valid="1",ignorecount="0",
file="F:\Projects\test\main.cpp",line="5",addr="4199979"},],
file="F:\Projects\test\main.cpp",line="5"}@
When parsed as GdbMi value, the strings are expected to be escaped.
Change-Id: Idb923516c1cf6e25b970ad08fae977bdf1045b4b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
											
										 
											2020-08-28 11:20:41 +03:00
										 |  |  |                     result += '{line="%d"' % lineNumber | 
					
						
							|  |  |  |                     result += ',file="%s"' % toCString(fileName) | 
					
						
							| 
									
										
										
										
											2015-08-28 14:35:25 +02:00
										 |  |  |                     if 0 < lineNumber and lineNumber <= len(source): | 
					
						
							| 
									
										
										
										
											2017-08-11 18:02:49 +02:00
										 |  |  |                         result += ',hexdata="%s"' % self.hexencode(source[lineNumber - 1]) | 
					
						
							| 
									
										
										
										
											2015-08-28 14:35:25 +02:00
										 |  |  |                     result += ',hunk="%s"}' % hunk | 
					
						
							|  |  |  |             result += '{address="%s"' % loadAddr | 
					
						
							| 
									
										
										
										
											2015-08-28 15:43:19 +02:00
										 |  |  |             result += ',data="%s %s"' % (insn.GetMnemonic(self.target), | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                                          insn.GetOperands(self.target)) | 
					
						
							| 
									
										
										
										
											2015-08-28 15:43:19 +02:00
										 |  |  |             result += ',function="%s"' % functionName | 
					
						
							| 
									
										
										
										
											2016-12-13 09:46:51 +01:00
										 |  |  |             rawData = insn.GetData(self.target).uint8s | 
					
						
							| 
									
										
										
										
											2015-08-28 15:43:19 +02:00
										 |  |  |             result += ',rawdata="%s"' % ' '.join(["%02x" % x for x in rawData]) | 
					
						
							| 
									
										
										
										
											2013-05-03 17:18:07 +02:00
										 |  |  |             if comment: | 
					
						
							| 
									
										
										
										
											2016-04-13 19:37:31 +02:00
										 |  |  |                 result += ',comment="%s"' % self.hexencode(comment) | 
					
						
							| 
									
										
										
										
											2015-08-28 14:35:25 +02:00
										 |  |  |             result += ',offset="%s"}' % (loadAddr - base) | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         self.reportResult(result + ']', args) | 
					
						
							| 
									
										
										
										
											2013-05-03 17:18:07 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-11 21:35:39 +02:00
										 |  |  |     def fetchMemory(self, args): | 
					
						
							| 
									
										
										
										
											2013-05-07 12:34:10 +02:00
										 |  |  |         address = args['address'] | 
					
						
							|  |  |  |         length = args['length'] | 
					
						
							| 
									
										
										
										
											2013-05-07 08:46:51 +02:00
										 |  |  |         error = lldb.SBError() | 
					
						
							|  |  |  |         contents = self.process.ReadMemory(address, length, error) | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         result = 'address="%s",' % address | 
					
						
							| 
									
										
										
										
											2013-05-07 08:46:51 +02:00
										 |  |  |         result += self.describeError(error) | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         result += ',contents="%s"' % self.hexencode(contents) | 
					
						
							|  |  |  |         self.reportResult(result, args) | 
					
						
							| 
									
										
										
										
											2013-05-07 08:46:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-11 18:55:09 +02:00
										 |  |  |     def findValueByExpression(self, exp): | 
					
						
							|  |  |  |         # FIXME: Top level-only for now. | 
					
						
							|  |  |  |         frame = self.currentFrame() | 
					
						
							|  |  |  |         value = frame.FindVariable(exp) | 
					
						
							|  |  |  |         return value | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-09 17:37:14 +01:00
										 |  |  |     def setValue(self, address, typename, value): | 
					
						
							|  |  |  |         sbtype = self.lookupNativeType(typename) | 
					
						
							|  |  |  |         error = lldb.SBError() | 
					
						
							|  |  |  |         sbaddr = lldb.SBAddress(address, self.target) | 
					
						
							|  |  |  |         sbvalue = self.target.CreateValueFromAddress('x', sbaddr, sbtype) | 
					
						
							|  |  |  |         sbvalue.SetValueFromCString(str(value), error) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def setValues(self, address, typename, values): | 
					
						
							|  |  |  |         sbtype = self.lookupNativeType(typename) | 
					
						
							|  |  |  |         sizeof = sbtype.GetByteSize() | 
					
						
							|  |  |  |         error = lldb.SBError() | 
					
						
							|  |  |  |         for i in range(len(values)): | 
					
						
							|  |  |  |             sbaddr = lldb.SBAddress(address + i * sizeof, self.target) | 
					
						
							|  |  |  |             sbvalue = self.target.CreateValueFromAddress('x', sbaddr, sbtype) | 
					
						
							|  |  |  |             sbvalue.SetValueFromCString(str(values[i]), error) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-30 15:35:52 +02:00
										 |  |  |     def assignValue(self, args): | 
					
						
							| 
									
										
										
										
											2015-09-07 12:16:05 +02:00
										 |  |  |         self.reportToken(args) | 
					
						
							| 
									
										
										
										
											2013-06-11 18:55:09 +02:00
										 |  |  |         error = lldb.SBError() | 
					
						
							| 
									
										
										
										
											2018-11-09 17:37:14 +01:00
										 |  |  |         expr = self.hexdecode(args['expr']) | 
					
						
							| 
									
										
										
										
											2014-01-23 15:30:51 +01:00
										 |  |  |         value = self.hexdecode(args['value']) | 
					
						
							| 
									
										
										
										
											2018-11-09 17:37:14 +01:00
										 |  |  |         simpleType = int(args['simpleType']) | 
					
						
							|  |  |  |         lhs = self.findValueByExpression(expr) | 
					
						
							|  |  |  |         typeName = lhs.GetType().GetName() | 
					
						
							|  |  |  |         typeName = typeName.replace('::', '__') | 
					
						
							|  |  |  |         pos = typeName.find('<') | 
					
						
							|  |  |  |         if pos != -1: | 
					
						
							|  |  |  |             typeName = typeName[0:pos] | 
					
						
							|  |  |  |         if typeName in self.qqEditable and not simpleType: | 
					
						
							|  |  |  |             expr = self.parseAndEvaluate(expr) | 
					
						
							|  |  |  |             self.qqEditable[typeName](self, expr, value) | 
					
						
							|  |  |  |         else: | 
					
						
							| 
									
										
										
										
											2019-09-25 12:51:41 +02:00
										 |  |  |             self.parseAndEvaluate(expr + '=' + value) | 
					
						
							| 
									
										
										
										
											2015-10-09 15:00:20 +02:00
										 |  |  |         self.reportResult(self.describeError(error), args) | 
					
						
							| 
									
										
										
										
											2013-05-30 15:35:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-13 09:46:51 +01:00
										 |  |  |     def watchPoint(self, args): | 
					
						
							|  |  |  |         self.reportToken(args) | 
					
						
							|  |  |  |         ns = self.qtNamespace() | 
					
						
							|  |  |  |         lenns = len(ns) | 
					
						
							|  |  |  |         funcs = self.target.FindGlobalFunctions('.*QApplication::widgetAt', 2, 1) | 
					
						
							|  |  |  |         func = funcs[1] | 
					
						
							|  |  |  |         addr = func.GetFunction().GetStartAddress().GetLoadAddress(self.target) | 
					
						
							|  |  |  |         expr = '((void*(*)(int,int))0x%x)' % addr | 
					
						
							|  |  |  |         #expr = '%sQApplication::widgetAt(%s,%s)' % (ns, args['x'], args['y']) | 
					
						
							|  |  |  |         res = self.parseAndEvaluate(expr) | 
					
						
							|  |  |  |         p = 0 if res is None else res.pointer() | 
					
						
							|  |  |  |         n = ns + 'QWidget' | 
					
						
							|  |  |  |         self.reportResult('selected="0x%x",expr="(%s*)0x%x"' % (p, n, p), args) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-04 16:27:46 +01:00
										 |  |  |     def createResolvePendingBreakpointsHookBreakpoint(self, args): | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |         bp = self.target.BreakpointCreateByName('qt_qmlDebugConnectorOpen') | 
					
						
							| 
									
										
										
										
											2015-02-04 13:29:42 +01:00
										 |  |  |         bp.SetOneShot(True) | 
					
						
							| 
									
										
										
										
											2015-10-09 15:00:20 +02:00
										 |  |  |         self.interpreterBreakpointResolvers.append( | 
					
						
							| 
									
										
										
										
											2015-10-14 13:26:22 +02:00
										 |  |  |             lambda: self.resolvePendingInterpreterBreakpoint(args)) | 
					
						
							| 
									
										
										
										
											2013-10-17 17:08:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-29 14:55:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-04 10:44:20 +02:00
										 |  |  | # Used in dumper auto test. | 
					
						
							| 
									
										
										
										
											2015-01-23 17:54:00 +01:00
										 |  |  | class Tester(Dumper): | 
					
						
							| 
									
										
										
										
											2015-11-10 09:23:58 +01:00
										 |  |  |     def __init__(self, binary, args): | 
					
						
							| 
									
										
										
										
											2015-01-23 17:54:00 +01:00
										 |  |  |         Dumper.__init__(self) | 
					
						
							|  |  |  |         lldb.theDumper = self | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |         self.loadDumpers({'token': 1}) | 
					
						
							| 
									
										
										
										
											2015-01-23 17:54:00 +01:00
										 |  |  |         error = lldb.SBError() | 
					
						
							| 
									
										
										
										
											2015-01-30 12:36:04 +01:00
										 |  |  |         self.target = self.debugger.CreateTarget(binary, None, None, True, error) | 
					
						
							| 
									
										
										
										
											2013-06-04 10:44:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-23 17:54:00 +01:00
										 |  |  |         if error.GetType(): | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             self.warn('ERROR: %s' % error) | 
					
						
							| 
									
										
										
										
											2015-01-23 17:54:00 +01:00
										 |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 09:23:58 +01:00
										 |  |  |         s = threading.Thread(target=self.testLoop, args=(args,)) | 
					
						
							| 
									
										
										
										
											2015-01-23 17:54:00 +01:00
										 |  |  |         s.start() | 
					
						
							| 
									
										
										
										
											2015-01-30 12:36:04 +01:00
										 |  |  |         s.join(30) | 
					
						
							| 
									
										
										
										
											2013-06-04 10:44:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 09:23:58 +01:00
										 |  |  |     def testLoop(self, args): | 
					
						
							| 
									
										
										
										
											2015-01-23 17:54:00 +01:00
										 |  |  |         # Disable intermediate reporting. | 
					
						
							|  |  |  |         savedReport = self.report | 
					
						
							|  |  |  |         self.report = lambda stuff: 0 | 
					
						
							| 
									
										
										
										
											2013-06-04 10:44:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-23 17:54:00 +01:00
										 |  |  |         error = lldb.SBError() | 
					
						
							|  |  |  |         launchInfo = lldb.SBLaunchInfo([]) | 
					
						
							|  |  |  |         launchInfo.SetWorkingDirectory(os.getcwd()) | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |         environmentList = [key + '=' + value for key, value in os.environ.items()] | 
					
						
							| 
									
										
										
										
											2015-01-23 17:54:00 +01:00
										 |  |  |         launchInfo.SetEnvironmentEntries(environmentList, False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.process = self.target.Launch(launchInfo, error) | 
					
						
							|  |  |  |         if error.GetType(): | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |             self.warn('ERROR: %s' % error) | 
					
						
							| 
									
										
										
										
											2015-01-23 17:54:00 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         event = lldb.SBEvent() | 
					
						
							|  |  |  |         listener = self.debugger.GetListener() | 
					
						
							|  |  |  |         while True: | 
					
						
							|  |  |  |             state = self.process.GetState() | 
					
						
							|  |  |  |             if listener.WaitForEvent(100, event): | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |                 #DumperBase.warn('EVENT: %s' % event) | 
					
						
							| 
									
										
										
										
											2015-01-23 17:54:00 +01:00
										 |  |  |                 state = lldb.SBProcess.GetStateFromEvent(event) | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                 if state == lldb.eStateExited:  # 10 | 
					
						
							| 
									
										
										
										
											2015-01-23 17:54:00 +01:00
										 |  |  |                     break | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                 if state == lldb.eStateStopped:  # 5 | 
					
						
							| 
									
										
										
										
											2015-04-14 09:06:28 +02:00
										 |  |  |                     stoppedThread = None | 
					
						
							| 
									
										
										
										
											2020-02-24 10:37:40 +01:00
										 |  |  |                     for i in range(0, self.process.GetNumThreads()): | 
					
						
							| 
									
										
										
										
											2015-04-14 09:06:28 +02:00
										 |  |  |                         thread = self.process.GetThreadAtIndex(i) | 
					
						
							|  |  |  |                         reason = thread.GetStopReason() | 
					
						
							| 
									
										
										
										
											2020-02-21 10:10:00 +01:00
										 |  |  |                         #DumperBase.warn('THREAD: %s REASON: %s' % (thread, reason)) | 
					
						
							| 
									
										
										
										
											2015-04-14 09:06:28 +02:00
										 |  |  |                         if (reason == lldb.eStopReasonBreakpoint or | 
					
						
							|  |  |  |                                 reason == lldb.eStopReasonException or | 
					
						
							|  |  |  |                                 reason == lldb.eStopReasonSignal): | 
					
						
							|  |  |  |                             stoppedThread = thread | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if stoppedThread: | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                         # This seems highly fragile and depending on the 'No-ops' in the | 
					
						
							| 
									
										
										
										
											2015-04-14 09:06:28 +02:00
										 |  |  |                         # event handling above. | 
					
						
							| 
									
										
										
										
											2015-01-27 10:25:21 +01:00
										 |  |  |                         frame = stoppedThread.GetFrameAtIndex(0) | 
					
						
							| 
									
										
										
										
											2015-04-14 09:06:28 +02:00
										 |  |  |                         line = frame.line_entry.line | 
					
						
							|  |  |  |                         if line != 0: | 
					
						
							|  |  |  |                             self.report = savedReport | 
					
						
							|  |  |  |                             self.process.SetSelectedThread(stoppedThread) | 
					
						
							| 
									
										
										
										
											2020-09-07 14:00:09 +02:00
										 |  |  |                             self.fakeAddress_ = frame.GetPC() | 
					
						
							|  |  |  |                             self.fakeLAddress_ = frame.GetPCAddress() | 
					
						
							| 
									
										
										
										
											2015-11-10 09:23:58 +01:00
										 |  |  |                             self.fetchVariables(args) | 
					
						
							| 
									
										
										
										
											2015-09-09 16:34:09 +02:00
										 |  |  |                             #self.describeLocation(frame) | 
					
						
							| 
									
										
										
										
											2016-10-25 15:32:13 +02:00
										 |  |  |                             self.report('@NS@%s@' % self.qtNamespace()) | 
					
						
							|  |  |  |                             #self.report('ENV=%s' % os.environ.items()) | 
					
						
							|  |  |  |                             #self.report('DUMPER=%s' % self.qqDumpers) | 
					
						
							| 
									
										
										
										
											2015-04-14 09:06:28 +02:00
										 |  |  |                             break | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-23 17:54:00 +01:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2020-02-24 10:14:27 +01:00
										 |  |  |                 self.warn('TIMEOUT') | 
					
						
							|  |  |  |                 self.warn('Cannot determined stopped thread') | 
					
						
							| 
									
										
										
										
											2014-01-17 16:13:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-23 17:54:00 +01:00
										 |  |  |         lldb.SBDebugger.Destroy(self.debugger) | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | # ------------------------------ For use in LLDB ------------------------------ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  | from pprint import pprint | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | __module__ = sys.modules[__name__] | 
					
						
							|  |  |  | DEBUG = False if not hasattr(__module__, 'DEBUG') else DEBUG | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | class LogMixin(): | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  |     @staticmethod | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |     def log(message='', log_caller=False, frame=1, args=''): | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  |         if not DEBUG: | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         if log_caller: | 
					
						
							|  |  |  |             message = ": " + message if len(message) else '' | 
					
						
							|  |  |  |             # FIXME: Compute based on first frame not in this class? | 
					
						
							|  |  |  |             frame = sys._getframe(frame) | 
					
						
							|  |  |  |             fn = frame.f_code.co_name | 
					
						
							|  |  |  |             localz = frame.f_locals | 
					
						
							|  |  |  |             instance = str(localz["self"]) + "." if 'self' in localz else '' | 
					
						
							|  |  |  |             message = "%s%s(%s)%s" % (instance, fn, args, message) | 
					
						
							| 
									
										
										
										
											2019-09-16 14:01:48 +02:00
										 |  |  |         print(message) | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @staticmethod | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |     def log_fn(arg_str=''): | 
					
						
							|  |  |  |         LogMixin.log(log_caller=True, frame=2, args=arg_str) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | class DummyDebugger(object): | 
					
						
							|  |  |  |     def __getattr__(self, attr): | 
					
						
							|  |  |  |         raise AttributeError("Debugger should not be needed to create summaries") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  | class SummaryDumper(Dumper, LogMixin): | 
					
						
							|  |  |  |     _instance = None | 
					
						
							|  |  |  |     _lock = threading.RLock() | 
					
						
							|  |  |  |     _type_caches = {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @staticmethod | 
					
						
							|  |  |  |     def initialize(): | 
					
						
							|  |  |  |         SummaryDumper._instance = SummaryDumper() | 
					
						
							|  |  |  |         return SummaryDumper._instance | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @staticmethod | 
					
						
							|  |  |  |     @contextmanager | 
					
						
							|  |  |  |     def shared(valobj): | 
					
						
							|  |  |  |         SummaryDumper._lock.acquire() | 
					
						
							|  |  |  |         dumper = SummaryDumper._instance | 
					
						
							|  |  |  |         dumper.target = valobj.target | 
					
						
							|  |  |  |         dumper.process = valobj.process | 
					
						
							|  |  |  |         debugger_id = dumper.target.debugger.GetID() | 
					
						
							|  |  |  |         dumper.typeCache = SummaryDumper._type_caches.get(debugger_id, {}) | 
					
						
							|  |  |  |         yield dumper | 
					
						
							|  |  |  |         SummaryDumper._type_caches[debugger_id] = dumper.typeCache | 
					
						
							|  |  |  |         SummaryDumper._lock.release() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @staticmethod | 
					
						
							|  |  |  |     def warn(message): | 
					
						
							| 
									
										
										
										
											2019-09-16 14:01:48 +02:00
										 |  |  |         print("Qt summary warning: %s" % message) | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @staticmethod | 
					
						
							|  |  |  |     def showException(message, exType, exValue, exTraceback): | 
					
						
							|  |  |  |         # FIXME: Store for later and report back in summary | 
					
						
							|  |  |  |         SummaryDumper.log("Exception during dumping: %s" % exValue) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self): | 
					
						
							|  |  |  |         DumperBase.warn = staticmethod(SummaryDumper.warn) | 
					
						
							|  |  |  |         DumperBase.showException = staticmethod(SummaryDumper.showException) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Dumper.__init__(self, DummyDebugger()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.setVariableFetchingOptions({ | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |             'fancy': True, | 
					
						
							|  |  |  |             'qobjectnames': True, | 
					
						
							|  |  |  |             'passexceptions': True | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.dumpermodules = ['qttypes'] | 
					
						
							|  |  |  |         self.loadDumpers({}) | 
					
						
							|  |  |  |         self.output = '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def report(self, stuff): | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |         return  # Don't mess up lldb output | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |     def dump_summary(self, valobj, expanded=False): | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  |         try: | 
					
						
							|  |  |  |             from pygdbmi import gdbmiparser | 
					
						
							|  |  |  |         except ImportError: | 
					
						
							| 
									
										
										
										
											2019-09-16 14:01:48 +02:00
										 |  |  |             print("Qt summary provider requires the pygdbmi module, " | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                   "please install using 'sudo /usr/bin/easy_install pygdbmi', " | 
					
						
							|  |  |  |                   "and then restart Xcode.") | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  |             lldb.debugger.HandleCommand('type category delete Qt') | 
					
						
							|  |  |  |             return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         value = self.fromNativeValue(valobj) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Expand variable if we need synthetic children | 
					
						
							|  |  |  |         oldExpanded = self.expandedINames | 
					
						
							|  |  |  |         self.expandedINames = [value.name] if expanded else [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         savedOutput = self.output | 
					
						
							|  |  |  |         self.output = '' | 
					
						
							|  |  |  |         with TopLevelItem(self, value.name): | 
					
						
							|  |  |  |             self.putItem(value) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # FIXME: Hook into putField, etc to build up object instead of parsing MI | 
					
						
							|  |  |  |         response = gdbmiparser.parse_response("^ok,summary=%s" % self.output) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.output = savedOutput | 
					
						
							|  |  |  |         self.expandedINames = oldExpanded | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         summary = response["payload"]["summary"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         #print value, " --> ", | 
					
						
							|  |  |  |         #pprint(summary) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return summary | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  | class SummaryProvider(LogMixin): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     DEFAULT_SUMMARY = '' | 
					
						
							|  |  |  |     VOID_PTR_TYPE = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @staticmethod | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |     def provide_summary(valobj, internal_dict, options=None): | 
					
						
							|  |  |  |         if __name__ not in internal_dict: | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  |             # When disabling the import of the Qt summary providers, the | 
					
						
							|  |  |  |             # summary functions are still registered with LLDB, and we will | 
					
						
							|  |  |  |             # get callbacks to provide summaries, but at this point the child | 
					
						
							|  |  |  |             # providers are not active, so instead of providing half-baked and | 
					
						
							|  |  |  |             # confusing summaries we opt to unload all the summaries. | 
					
						
							|  |  |  |             SummaryDumper.log("Module '%s' was unloaded, removing Qt category" % __name__) | 
					
						
							|  |  |  |             lldb.debugger.HandleCommand('type category delete Qt') | 
					
						
							|  |  |  |             return SummaryProvider.DEFAULT_SUMMARY | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # FIXME: It would be nice to cache the providers, so that if a | 
					
						
							|  |  |  |         # synthetic child provider has already been created for a valobj, | 
					
						
							|  |  |  |         # we can re-use that when providing summary for the synthetic child | 
					
						
							|  |  |  |         # parent, but we lack a consistent cache key for that to work. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         provider = SummaryProvider(valobj) | 
					
						
							|  |  |  |         provider.update() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return provider.get_summary(options) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |     def __init__(self, valobj, expand=False): | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  |         # Prevent recursive evaluation during logging, etc | 
					
						
							|  |  |  |         valobj.SetPreferSyntheticValue(False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.log_fn(valobj.path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.valobj = valobj | 
					
						
							|  |  |  |         self.expand = expand | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not SummaryProvider.VOID_PTR_TYPE: | 
					
						
							|  |  |  |             with SummaryDumper.shared(self.valobj) as dumper: | 
					
						
							|  |  |  |                 SummaryProvider.VOID_PTR_TYPE = dumper.lookupNativeType('void*') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __repr__(self): | 
					
						
							|  |  |  |         return "%s(%s)" % (self.__class__.__name__, repr(self.key())) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def key(self): | 
					
						
							|  |  |  |         if not hasattr(self, 'valobj'): | 
					
						
							|  |  |  |             return None | 
					
						
							|  |  |  |         return self.valobj.path | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def update(self): | 
					
						
							|  |  |  |         self.log_fn() | 
					
						
							|  |  |  |         with SummaryDumper.shared(self.valobj) as dumper: | 
					
						
							|  |  |  |             self.summary = dumper.dump_summary(self.valobj, self.expand) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_summary(self, options): | 
					
						
							|  |  |  |         self.log_fn() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         summary = self.summary | 
					
						
							|  |  |  |         if not summary: | 
					
						
							|  |  |  |             return '<error: could not get summary from Qt provider>' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         encoding = summary.get("valueencoded") | 
					
						
							|  |  |  |         summaryValue = summary["value"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # FIXME: Share between Creator and LLDB in the python code | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if encoding: | 
					
						
							|  |  |  |             special_encodings = { | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                 "empty":            "<empty>", | 
					
						
							|  |  |  |                 "minimumitemcount": "<at least %s items>" % summaryValue, | 
					
						
							|  |  |  |                 "undefined":        "<undefined>", | 
					
						
							|  |  |  |                 "null":             "<null>", | 
					
						
							|  |  |  |                 "itemcount":        "<%s items>" % summaryValue, | 
					
						
							|  |  |  |                 "notaccessible":    "<not accessible>", | 
					
						
							|  |  |  |                 "optimizedout":     "<optimized out>", | 
					
						
							|  |  |  |                 "nullreference":    "<null reference>", | 
					
						
							|  |  |  |                 "emptystructure":   "<empty structure>", | 
					
						
							|  |  |  |                 "uninitialized":    "<uninitialized>", | 
					
						
							|  |  |  |                 "invalid":          "<invalid>", | 
					
						
							|  |  |  |                 "notcallable":      "<not callable>", | 
					
						
							|  |  |  |                 "outofscope":       "<out of scope>" | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |             if encoding in special_encodings: | 
					
						
							|  |  |  |                 return special_encodings[encoding] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             text_encodings = [ | 
					
						
							|  |  |  |                 'latin1', | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                 # 'local8bit', | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  |                 'utf8', | 
					
						
							|  |  |  |                 'utf16', | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                 #  'ucs4' | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  |             ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if encoding in text_encodings: | 
					
						
							|  |  |  |                 try: | 
					
						
							| 
									
										
										
										
											2021-07-23 13:02:02 +01:00
										 |  |  |                     decodedValue = Dumper.hexdecode(summaryValue, encoding) | 
					
						
							|  |  |  |                     # LLDB expects UTF-8 for python 2 | 
					
						
							|  |  |  |                     if sys.version_info[0] < 3: | 
					
						
							|  |  |  |                         return "\"%s\"" % (decodedValue.encode('utf8')) | 
					
						
							|  |  |  |                     return '"' + decodedValue + '"' | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  |                 except: | 
					
						
							| 
									
										
										
										
											2021-07-23 13:02:02 +01:00
										 |  |  |                     return "<failed to decode '%s' as '%s': %s>" % (summaryValue, encoding, sys.exc_info()[1]) | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # FIXME: Support these | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |             other_encodings = [ | 
					
						
							|  |  |  |                 'int', | 
					
						
							|  |  |  |                 'uint', | 
					
						
							|  |  |  |                 'float', | 
					
						
							|  |  |  |                 'juliandate', | 
					
						
							|  |  |  |                 'juliandateandmillisecondssincemidnight', | 
					
						
							|  |  |  |                 'millisecondssincemidnight', | 
					
						
							|  |  |  |                 'ipv6addressandhexscopeid', | 
					
						
							|  |  |  |                 'datetimeinternal'] | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             summaryValue += " <encoding='%s'>" % encoding | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.valobj.value: | 
					
						
							|  |  |  |             # If we've resolved a pointer that matches what LLDB natively chose, | 
					
						
							|  |  |  |             # then use that instead of printing the values twice. FIXME, ideally | 
					
						
							|  |  |  |             # we'd have the same pointer format as LLDB uses natively. | 
					
						
							|  |  |  |             if re.sub('^0x0*', '', self.valobj.value) == re.sub('^0x0*', '', summaryValue): | 
					
						
							|  |  |  |                 return SummaryProvider.DEFAULT_SUMMARY | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return summaryValue.strip() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  | class SyntheticChildrenProvider(SummaryProvider): | 
					
						
							|  |  |  |     def __init__(self, valobj, dict): | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |         SummaryProvider.__init__(self, valobj, expand=True) | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  |         self.summary = None | 
					
						
							|  |  |  |         self.synthetic_children = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def num_native_children(self): | 
					
						
							|  |  |  |         return self.valobj.GetNumChildren() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def num_children(self): | 
					
						
							|  |  |  |         self.log("native: %d synthetic: %d" % | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                  (self.num_native_children(), len(self.synthetic_children)), True) | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  |         return self._num_children() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _num_children(self): | 
					
						
							|  |  |  |         return self.num_native_children() + len(self.synthetic_children) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def has_children(self): | 
					
						
							|  |  |  |         return self._num_children() > 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_child_index(self, name): | 
					
						
							|  |  |  |         # FIXME: Do we ever need this to return something? | 
					
						
							|  |  |  |         self.log_fn(name) | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_child_at_index(self, index): | 
					
						
							|  |  |  |         self.log_fn(index) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if index < 0 or index > self._num_children(): | 
					
						
							|  |  |  |             return None | 
					
						
							|  |  |  |         if not self.valobj.IsValid() or not self.summary: | 
					
						
							|  |  |  |             return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if index < self.num_native_children(): | 
					
						
							|  |  |  |             # Built-in children | 
					
						
							|  |  |  |             value = self.valobj.GetChildAtIndex(index) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             # Synthetic children | 
					
						
							|  |  |  |             index -= self.num_native_children() | 
					
						
							|  |  |  |             child = self.synthetic_children[index] | 
					
						
							|  |  |  |             name = child.get('name', "[%s]" % index) | 
					
						
							|  |  |  |             value = self.create_value(child, name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return value | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |     def create_value(self, child, name=''): | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  |         child_type = child.get('type', self.summary.get('childtype')) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         value = None | 
					
						
							|  |  |  |         if child_type: | 
					
						
							|  |  |  |             if 'address' in child: | 
					
						
							|  |  |  |                 value_type = None | 
					
						
							|  |  |  |                 with SummaryDumper.shared(self.valobj) as dumper: | 
					
						
							|  |  |  |                     value_type = dumper.lookupNativeType(child_type) | 
					
						
							|  |  |  |                 if not value_type or not value_type.IsValid(): | 
					
						
							|  |  |  |                     return None | 
					
						
							|  |  |  |                 address = int(child['address'], 16) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 # Create as void* so that the value is fully initialized before | 
					
						
							|  |  |  |                 # we trigger our own summary/child providers recursively. | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |                 value = self.valobj.synthetic_child_from_address( | 
					
						
							|  |  |  |                     name, address, SummaryProvider.VOID_PTR_TYPE).Cast(value_type) | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 self.log("Don't know how to create value for child %s" % child) | 
					
						
							|  |  |  |                 # FIXME: Figure out if we ever will hit this case, and deal with it | 
					
						
							|  |  |  |                 #value = self.valobj.synthetic_child_from_expression(name, | 
					
						
							|  |  |  |                 #    "(%s)(%s)" % (child_type, child['value'])) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             # FIXME: Find a good way to deal with synthetic values | 
					
						
							|  |  |  |             self.log("Don't know how to create value for child %s" % child) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # FIXME: Handle value type or value errors consistently | 
					
						
							|  |  |  |         return value | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def update(self): | 
					
						
							|  |  |  |         SummaryProvider.update(self) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.synthetic_children = [] | 
					
						
							| 
									
										
										
										
											2019-05-02 18:16:47 +02:00
										 |  |  |         if 'children' not in self.summary: | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         dereference_child = None | 
					
						
							|  |  |  |         for child in self.summary['children']: | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |             if not child or not isinstance(child, dict): | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  |                 continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # Skip base classes, they are built-in children | 
					
						
							|  |  |  |             # FIXME: Is there a better check than 'iname'? | 
					
						
							|  |  |  |             if 'iname' in child: | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             name = child.get('name') | 
					
						
							|  |  |  |             if name: | 
					
						
							|  |  |  |                 if name == '*': | 
					
						
							|  |  |  |                     # No use for this unless the built in children failed to resolve | 
					
						
							|  |  |  |                     dereference_child = child | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if name.startswith('['): | 
					
						
							|  |  |  |                     # Skip pure synthetic children until we can deal with them | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if name.startswith('#'): | 
					
						
							|  |  |  |                     # Skip anonymous unions, lookupNativeType doesn't handle them (yet), | 
					
						
							|  |  |  |                     # so it triggers the slow lookup path, and the union is provided as | 
					
						
							|  |  |  |                     # a native child anyways. | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 # Skip native children | 
					
						
							|  |  |  |                 if self.valobj.GetChildMemberWithName(name): | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             self.synthetic_children.append(child) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Xcode will sometimes fail to show the children of pointers in | 
					
						
							|  |  |  |         # the debugger UI, even if dereferencing the pointer works fine. | 
					
						
							|  |  |  |         # We fall back to the special child reported by the Qt dumper. | 
					
						
							|  |  |  |         if not self.valobj.GetNumChildren() and dereference_child: | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |             self.valobj = self.create_value(dereference_child) | 
					
						
							|  |  |  |             self.update() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | def __lldb_init_module(debugger, internal_dict): | 
					
						
							|  |  |  |     # Module is being imported in an LLDB session | 
					
						
							|  |  |  |     dumper = SummaryDumper.initialize() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     type_category = 'Qt' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Concrete types | 
					
						
							|  |  |  |     summary_function = "%s.%s.%s" % (__name__, 'SummaryProvider', 'provide_summary') | 
					
						
							|  |  |  |     types = map(lambda x: x.replace('__', '::'), dumper.qqDumpers) | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |     debugger.HandleCommand("type summary add -F %s -w %s %s" | 
					
						
							|  |  |  |                            % (summary_function, type_category, ' '.join(types))) | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-15 18:27:55 +01:00
										 |  |  |     regex_types = list(map(lambda x: "'" + x + "'", dumper.qqDumpersEx.keys())) | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  |     if regex_types: | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |         debugger.HandleCommand("type summary add -x -F %s -w %s %s" | 
					
						
							|  |  |  |                                % (summary_function, type_category, ' '.join(regex_types))) | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Global catch-all for Qt classes | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |     debugger.HandleCommand("type summary add -x '^Q.*$' -F %s -w %s" | 
					
						
							|  |  |  |                            % (summary_function, type_category)) | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Named summary ('frame variable foo --summary Qt') | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |     debugger.HandleCommand("type summary add --name Qt -F %s -w %s" | 
					
						
							|  |  |  |                            % (summary_function, type_category)) | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Synthetic children | 
					
						
							| 
									
										
										
										
											2020-02-24 14:37:56 +01:00
										 |  |  |     debugger.HandleCommand("type synthetic add -x '^Q.*$' -l %s -w %s" | 
					
						
							|  |  |  |                            % ("lldbbridge.SyntheticChildrenProvider", type_category)) | 
					
						
							| 
									
										
										
										
											2017-05-13 15:19:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     debugger.HandleCommand('type category enable %s' % type_category) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if not __name__ == 'qt': | 
					
						
							|  |  |  |         # Make available under global 'qt' name for consistency | 
					
						
							|  |  |  |         internal_dict['qt'] = internal_dict[__name__] | 
					
						
							| 
									
										
										
										
											2018-11-09 16:19:12 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == "lldbbridge": | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         theDumper = Dumper() | 
					
						
							|  |  |  |     except Exception as error: | 
					
						
							|  |  |  |         print('@\nstate="enginesetupfailed",error="{}"@\n'.format(error)) |