[OpenACC] Enable 'attach' clause for combined constructs
[llvm-project.git] / lldb / examples / python / diagnose_nsstring.py
blob519799355104d87825407ba5f03ab04120b9cd5b
1 # This implements the "diagnose-nsstring" command, usually installed in the debug session like
2 # command script import lldb.diagnose
3 # it is used when NSString summary formatter fails to replicate the logic that went into LLDB making the
4 # decisions it did and providing some useful context information that can
5 # be used for improving the formatter
7 import lldb
10 def read_memory(process, location, size):
11 data = ""
12 error = lldb.SBError()
13 for x in range(0, size - 1):
14 byte = process.ReadUnsignedFromMemory(x + location, 1, error)
15 if error.fail:
16 data = data + "err%s" % "" if x == size - 2 else ":"
17 else:
18 try:
19 data = data + "0x%x" % byte
20 if byte == 0:
21 data = data + "(\\0)"
22 elif byte == 0xA:
23 data = data + "(\\a)"
24 elif byte == 0xB:
25 data = data + "(\\b)"
26 elif byte == 0xC:
27 data = data + "(\\c)"
28 elif byte == "\n":
29 data = data + "(\\n)"
30 else:
31 data = data + "(%s)" % chr(byte)
32 if x < size - 2:
33 data = data + ":"
34 except Exception as e:
35 print(e)
36 return data
39 def diagnose_nsstring_Command_Impl(debugger, command, result, internal_dict):
40 """
41 A command to diagnose the LLDB NSString data formatter
42 invoke as
43 (lldb) diagnose-nsstring <expr returning NSString>
44 e.g.
45 (lldb) diagnose-nsstring @"Hello world"
46 """
47 target = debugger.GetSelectedTarget()
48 process = target.GetProcess()
49 thread = process.GetSelectedThread()
50 frame = thread.GetSelectedFrame()
51 if not target.IsValid() or not process.IsValid():
52 return "unable to get target/process - cannot proceed"
53 options = lldb.SBExpressionOptions()
54 options.SetFetchDynamicValue()
55 error = lldb.SBError()
56 if frame.IsValid():
57 nsstring = frame.EvaluateExpression(command, options)
58 else:
59 nsstring = target.EvaluateExpression(command, options)
60 print(str(nsstring), file=result)
61 nsstring_address = nsstring.GetValueAsUnsigned(0)
62 if nsstring_address == 0:
63 return "unable to obtain the string - cannot proceed"
64 expression = "\
65 struct $__lldb__notInlineMutable {\
66 char* buffer;\
67 signed long length;\
68 signed long capacity;\
69 unsigned int hasGap:1;\
70 unsigned int isFixedCapacity:1;\
71 unsigned int isExternalMutable:1;\
72 unsigned int capacityProvidedExternally:1;\n\
73 #if __LP64__\n\
74 unsigned long desiredCapacity:60;\n\
75 #else\n\
76 unsigned long desiredCapacity:28;\n\
77 #endif\n\
78 void* contentsAllocator;\
79 };\
81 struct $__lldb__CFString {\
82 void* _cfisa;\
83 uint8_t _cfinfo[4];\
84 uint32_t _rc;\
85 union {\
86 struct __inline1 {\
87 signed long length;\
88 } inline1;\
89 struct __notInlineImmutable1 {\
90 char* buffer;\
91 signed long length;\
92 void* contentsDeallocator;\
93 } notInlineImmutable1;\
94 struct __notInlineImmutable2 {\
95 char* buffer;\
96 void* contentsDeallocator;\
97 } notInlineImmutable2;\
98 struct $__lldb__notInlineMutable notInlineMutable;\
99 } variants;\
103 expression = expression + "*(($__lldb__CFString*) %d)" % nsstring_address
104 # print expression
105 dumped = target.EvaluateExpression(expression, options)
106 print(str(dumped), file=result)
108 little_endian = target.byte_order == lldb.eByteOrderLittle
109 ptr_size = target.addr_size
111 info_bits = (
112 dumped.GetChildMemberWithName("_cfinfo")
113 .GetChildAtIndex(0 if little_endian else 3)
114 .GetValueAsUnsigned(0)
116 is_mutable = (info_bits & 1) == 1
117 is_inline = (info_bits & 0x60) == 0
118 has_explicit_length = (info_bits & (1 | 4)) != 4
119 is_unicode = (info_bits & 0x10) == 0x10
120 is_special = (
121 nsstring.GetDynamicValue(lldb.eDynamicCanRunTarget).GetTypeName()
122 == "NSPathStore2"
124 has_null = (info_bits & 8) == 8
126 print(
127 "\nInfo=%d\nMutable=%s\nInline=%s\nExplicit=%s\nUnicode=%s\nSpecial=%s\nNull=%s\n"
129 info_bits,
130 "yes" if is_mutable else "no",
131 "yes" if is_inline else "no",
132 "yes" if has_explicit_length else "no",
133 "yes" if is_unicode else "no",
134 "yes" if is_special else "no",
135 "yes" if has_null else "no",
137 file=result,
140 explicit_length_offset = 0
141 if not has_null and has_explicit_length and not is_special:
142 explicit_length_offset = 2 * ptr_size
143 if is_mutable and not is_inline:
144 explicit_length_offset = explicit_length_offset + ptr_size
145 elif is_inline:
146 pass
147 elif not is_inline and not is_mutable:
148 explicit_length_offset = explicit_length_offset + ptr_size
149 else:
150 explicit_length_offset = 0
152 if explicit_length_offset == 0:
153 print("There is no explicit length marker - skipping this step\n", file=result)
154 else:
155 explicit_length_offset = nsstring_address + explicit_length_offset
156 explicit_length = process.ReadUnsignedFromMemory(
157 explicit_length_offset, 4, error
159 print(
160 "Explicit length location is at 0x%x - read value is %d\n"
161 % (explicit_length_offset, explicit_length),
162 file=result,
165 if is_mutable:
166 location = 2 * ptr_size + nsstring_address
167 location = process.ReadPointerFromMemory(location, error)
168 elif (
169 is_inline
170 and has_explicit_length
171 and not is_unicode
172 and not is_special
173 and not is_mutable
175 location = 3 * ptr_size + nsstring_address
176 elif is_unicode:
177 location = 2 * ptr_size + nsstring_address
178 if is_inline:
179 if not has_explicit_length:
180 print(
181 "Unicode & Inline & !Explicit is a new combo - no formula for it",
182 file=result,
184 else:
185 location += ptr_size
186 else:
187 location = process.ReadPointerFromMemory(location, error)
188 elif is_special:
189 location = nsstring_address + ptr_size + 4
190 elif is_inline:
191 location = 2 * ptr_size + nsstring_address
192 if not has_explicit_length:
193 location += 1
194 else:
195 location = 2 * ptr_size + nsstring_address
196 location = process.ReadPointerFromMemory(location, error)
197 print("Expected data location: 0x%x\n" % (location), file=result)
198 print(
199 "1K of data around location: %s\n" % read_memory(process, location, 1024),
200 file=result,
202 print(
203 "5K of data around string pointer: %s\n"
204 % read_memory(process, nsstring_address, 1024 * 5),
205 file=result,
209 def __lldb_init_module(debugger, internal_dict):
210 debugger.HandleCommand(
211 "command script add -o -f %s.diagnose_nsstring_Command_Impl diagnose-nsstring"
212 % __name__
214 print(
215 'The "diagnose-nsstring" command has been installed, type "help diagnose-nsstring" for detailed help.'
219 __lldb_init_module(lldb.debugger, None)
220 __lldb_init_module = None