]> git.saurik.com Git - apple/xnu.git/blame - tools/lldbmacros/core/cvalue.py
xnu-4570.1.46.tar.gz
[apple/xnu.git] / tools / lldbmacros / core / cvalue.py
CommitLineData
39236c6e
A
1"""
2Defines a class value which encapsulates the basic lldb Scripting Bridge APIs. This provides an easy
3wrapper to extract information from C based constructs.
4 |------- core.value------------|
5 | |--lldb Scripting Bridge--| |
6 | | |--lldb core--| | |
7 | |-------------------------| |
8 |------------------------------|
9Use the member function GetSBValue() to access the base Scripting Bridge value.
10"""
11import lldb
12import re
13from lazytarget import *
14
15_cstring_rex = re.compile("((?:\s*|const\s+)\s*char(?:\s+\*|\s+[A-Za-z_0-9]*\s*\[|)\s*)",re.MULTILINE|re.DOTALL)
16
17class value(object):
18 '''A class designed to wrap lldb.SBValue() objects so the resulting object
19 can be used as a variable would be in code. So if you have a Point structure
20 variable in your code in the current frame named "pt", you can initialize an instance
21 of this class with it:
22
23 pt = lldb.value(lldb.frame.FindVariable("pt"))
24 print pt
25 print pt.x
26 print pt.y
27
28 pt = lldb.value(lldb.frame.FindVariable("rectangle_array"))
29 print rectangle_array[12]
30 print rectangle_array[5].origin.x'''
31 def __init__(self, sbvalue):
32 #_sbval19k84obscure747 is specifically chosen to be obscure.
33 #This avoids conflicts when attributes could mean any field value in code
34 self._sbval19k84obscure747 = sbvalue
35 self._sbval19k84obscure747_type = sbvalue.GetType()
36 self._sbval19k84obscure747_is_ptr = sbvalue.GetType().IsPointerType()
37 self.sbvalue = sbvalue
38
39 def __nonzero__(self):
40 return ( self._sbval19k84obscure747.__nonzero__() and self._GetValueAsUnsigned() != 0 )
41
42 def __repr__(self):
43 return self._sbval19k84obscure747.__str__()
44
45 def __cmp__(self, other):
5ba3f43e 46 if type(other) is int or type(other) is long:
39236c6e
A
47 me = int(self)
48 if type(me) is long:
49 other = long(other)
50 return me.__cmp__(other)
51 if type(other) is value:
52 return int(self).__cmp__(int(other))
5ba3f43e 53 raise TypeError("Cannot compare value with type {}".format(type(other)))
39236c6e
A
54
55 def __str__(self):
56 global _cstring_rex
57 type_name = self._sbval19k84obscure747_type.GetName()
58 if len(_cstring_rex.findall(type_name)) > 0 :
59 return self._GetValueAsString()
60 summary = self._sbval19k84obscure747.GetSummary()
61 if summary:
62 return summary.strip('"')
63 return self._sbval19k84obscure747.__str__()
64
65 def __getitem__(self, key):
66 # Allow array access if this value has children...
67 if type(key) is slice:
68 _start = int(key.start)
69 _end = int(key.stop)
70 _step = 1
71 if key.step != None:
72 _step = int(key.step)
73 retval = []
74 while _start < _end:
75 retval.append(self[_start])
76 _start += _step
77 return retval
78 if type(key) in (int, long):
79 return value(self._sbval19k84obscure747.GetValueForExpressionPath("[%i]" % key))
80 if type(key) is value:
81 return value(self._sbval19k84obscure747.GetValueForExpressionPath("[%i]" % int(key)))
82 raise TypeError("Cannot fetch Array item for this type")
83
84 def __getattr__(self, name):
85 child_sbvalue = self._sbval19k84obscure747.GetChildMemberWithName (name)
86 if child_sbvalue:
87 return value(child_sbvalue)
88 raise AttributeError("No field by name: "+name )
89
90 def __add__(self, other):
91 return int(self) + int(other)
92
93 def __radd__(self, other):
94 return int(self) + int(other)
95
96 def __sub__(self, other):
97 return int(self) - int(other)
98
99 def __rsub__(self, other):
100 return int(other) - int(self)
101
102 def __mul__(self, other):
103 return int(self) * int(other)
104
105 def __rmul__(self, other):
106 return int(self) * int(other)
107
108 def __floordiv__(self, other):
109 return int(self) // int(other)
110
111 def __mod__(self, other):
112 return int(self) % int(other)
113
114 def __rmod__(self, other):
115 return int(other) % int(self)
116
117 def __divmod__(self, other):
118 return int(self) % int(other)
119
120 def __rdivmod__(self, other):
121 return int(other) % int(self)
122
123 def __pow__(self, other):
124 return int(self) ** int(other)
125
126 def __lshift__(self, other):
127 return int(self) << int(other)
128
129 def __rshift__(self, other):
130 return int(self) >> int(other)
131
132 def __and__(self, other):
133 return int(self) & int(other)
134
135 def __rand(self, other):
136 return int(self) & int(other)
137
138 def __xor__(self, other):
139 return int(self) ^ int(other)
140
141 def __or__(self, other):
142 return int(self) | int(other)
143
144 def __div__(self, other):
145 return int(self) / int(other)
146
147 def __rdiv__(self, other):
148 return int(other)/int(self)
149
150 def __truediv__(self, other):
151 return int(self) / int(other)
152
153 def __iadd__(self, other):
154 result = self.__add__(other)
155 self._sbval19k84obscure747.SetValueFromCString (str(result))
156 return result
157
158 def __isub__(self, other):
159 result = self.__sub__(other)
160 self._sbval19k84obscure747.SetValueFromCString (str(result))
161 return result
162
163 def __imul__(self, other):
164 result = self.__mul__(other)
165 self._sbval19k84obscure747.SetValueFromCString (str(result))
166 return result
167
168 def __idiv__(self, other):
169 result = self.__div__(other)
170 self._sbval19k84obscure747.SetValueFromCString (str(result))
171 return result
172
173 def __itruediv__(self, other):
174 result = self.__truediv__(other)
175 self._sbval19k84obscure747.SetValueFromCString (str(result))
176 return result
177
178 def __ifloordiv__(self, other):
179 result = self.__floordiv__(self, other)
180 self._sbval19k84obscure747.SetValueFromCString (str(result))
181 return result
182
183 def __imod__(self, other):
184 result = self.__and__(self, other)
185 self._sbval19k84obscure747.SetValueFromCString (str(result))
186 return result
187
188 def __ipow__(self, other):
189 result = self.__pow__(self, other)
190 self._sbval19k84obscure747.SetValueFromCString (str(result))
191 return result
192
193 def __ipow__(self, other, modulo):
194 result = self.__pow__(self, other, modulo)
195 self._sbval19k84obscure747.SetValueFromCString (str(result))
196 return result
197
198 def __ilshift__(self, other):
199 result = self.__lshift__(other)
200 self._sbval19k84obscure747.SetValueFromCString (str(result))
201 return result
202
203 def __irshift__(self, other):
204 result = self.__rshift__(other)
205 self._sbval19k84obscure747.SetValueFromCString (str(result))
206 return result
207
208 def __iand__(self, other):
209 result = self.__and__(self, other)
210 self._sbval19k84obscure747.SetValueFromCString (str(result))
211 return result
212
213 def __ixor__(self, other):
214 result = self.__xor__(self, other)
215 self._sbval19k84obscure747.SetValueFromCString (str(result))
216 return result
217
218 def __ior__(self, other):
219 result = self.__ior__(self, other)
220 self._sbval19k84obscure747.SetValueFromCString (str(result))
221 return result
222
223 def __neg__(self):
224 return -int(self)
225
226 def __pos__(self):
227 return +int(self)
228
229 def __abs__(self):
230 return abs(int(self))
231
232 def __invert__(self):
233 return ~int(self)
234
235 def __complex__(self):
236 return complex (int(self))
237
238 def __int__(self):
239 if self._sbval19k84obscure747_is_ptr:
240 return self._GetValueAsUnsigned()
241 tname= self._sbval19k84obscure747_type.GetName()
242 if tname.find('uint') >= 0 or tname.find('unsigned') >= 0:
243 return self._GetValueAsUnsigned()
244 retval = self._sbval19k84obscure747.GetValueAsSigned()
245 # <rdar://problem/12481949> lldb python: GetValueAsSigned does not return the correct value
246 if (retval & 0x80000000):
247 retval = retval - 0x100000000
248 return retval
249
250 def __long__(self):
251 return self._sbval19k84obscure747.GetValueAsSigned()
252
253 def __float__(self):
254 return float (self._sbval19k84obscure747.GetValueAsSigned())
255
256 def __oct__(self):
257 return '0%o' % self._GetValueAsUnsigned()
258
259 def __hex__(self):
260 return '0x%x' % self._GetValueAsUnsigned()
261
262 def __eq__(self, other):
263 self_err = lldb.SBError()
264 other_err = lldb.SBError()
265 self_val = self._sbval19k84obscure747.GetValueAsUnsigned(self_err)
266 if self_err.fail:
267 raise ValueError("unable to extract value of self")
268 if type(other) is value:
269 other_val = other._sbval19k84obscure747.GetValueAsUnsigned(other_err)
270 if other_err.fail:
271 raise ValueError("unable to extract value of other")
272 return self_val == other_val
273 if type(other) is int:
274 return int(self) == other
275 raise TypeError("Equality operation is not defined for this type.")
276
277 def __neq__(self, other):
278 return not self.__eq__(other)
279
280 def GetSBValue(self):
281 return self._sbval19k84obscure747
282
fe8ab488
A
283 def __getstate__(self):
284 err = lldb.SBError()
285 if self._sbval19k84obscure747_is_ptr:
286 addr = self._sbval19k84obscure747.GetValueAsUnsigned()
287 size = self._sbval19k84obscure747_type.GetPointeeType().GetByteSize()
288 else:
289 addr = self._sbval19k84obscure747.AddressOf().GetValueAsUnsigned()
290 size = self._sbval19k84obscure747_type.GetByteSize()
291
292 content = LazyTarget.GetProcess().ReadMemory(addr, size, err)
293 if err.fail:
294 content = ''
295 return content
296
39236c6e
A
297 def _GetValueAsSigned(self):
298 serr = lldb.SBError()
299 retval = self._sbval19k84obscure747.GetValueAsSigned(serr)
300 if serr.success:
301 return retval
302 raise ValueError("Failed to read signed data. "+ str(self._sbval19k84obscure747) +"(type =" + str(self._sbval19k84obscure747_type) + ") Error description: " + serr.GetCString())
303
304 def _GetValueAsUnsigned(self):
305 serr = lldb.SBError()
306 retval = self._sbval19k84obscure747.GetValueAsUnsigned(serr)
307 if serr.success:
308 return retval
309 raise ValueError("Failed to read unsigned data. "+ str(self._sbval19k84obscure747) +"(type =" + str(self._sbval19k84obscure747_type) + ") Error description: " + serr.GetCString())
310
311 def _GetValueAsString(self, offset = 0, maxlen = 1024):
312 serr = lldb.SBError()
313 sbdata = None
314 if self._sbval19k84obscure747.TypeIsPointerType():
315 sbdata = self._sbval19k84obscure747.GetPointeeData(offset, maxlen)
316 else:
317 sbdata = self._sbval19k84obscure747.GetData()
318
319 retval = ''
320 bytesize = sbdata.GetByteSize()
321 if bytesize == 0 :
322 #raise ValueError('Unable to read value as string')
323 return ''
324 for i in range(0, bytesize) :
325 serr.Clear()
326 ch = chr(sbdata.GetUnsignedInt8(serr, i))
327 if serr.fail :
328 raise ValueError("Unable to read string data: " + serr.GetCString())
329 if ch == '\0':
330 break
331 retval += ch
332 return retval
333
334 def __format__(self, format_spec):
335 ret_format = "{0:"+format_spec+"}"
336 # typechar is last char. see http://www.python.org/dev/peps/pep-3101/
337 type_spec=format_spec.strip().lower()[-1]
338 if type_spec == 'x':
339 return ret_format.format(self._GetValueAsUnsigned())
340 if type_spec == 'd':
341 return ret_format.format(int(self))
342 if type_spec == 's':
343 return ret_format.format(str(self))
344 if type_spec == 'o':
345 return ret_format.format(int(oct(self)))
346 if type_spec == 'c':
347 return ret_format.format(int(self))
348
349 return "unknown format " + format_spec + str(self)
350
351
352def unsigned(val):
353 """ Helper function to get unsigned value from core.value
354 params: val - value (see value class above) representation of an integer type
355 returns: int which is unsigned.
356 raises : ValueError if the type cannot be represented as unsigned int.
357 """
358 if type(val) is value:
359 return val._GetValueAsUnsigned()
360 return int(val)
361
362def sizeof(t):
363 """ Find the byte size of a type.
364 params: t - str : ex 'time_spec' returns equivalent of sizeof(time_spec) in C
365 t - value: ex a value object. returns size of the object
366 returns: int - byte size length
367 """
368 if type(t) is value :
369 return t.GetSBValue().GetByteSize()
370 if type(t) is str:
371 return gettype(t).GetByteSize()
372 raise ValueError("Cannot get sizeof. Invalid argument")
373
374
375def dereference(val):
376 """ Get a dereferenced obj for a pointer type obj
377 params: val - value object representing a pointer type C construct in lldb
378 returns: value - value
379 ex. val = dereference(ptr_obj) #python
380 is same as
381 obj_ptr = (int *)0x1234 #C
382 val = *obj_ptr #C
383 """
384 if type(val) is value and val.GetSBValue().TypeIsPointerType():
385 return value(val.GetSBValue().Dereference())
386 raise TypeError('Cannot dereference this type.')
387
388def addressof(val):
389 """ Get address of a core.value object.
390 params: val - value object representing a C construct in lldb
391 returns: value - value object referring to 'type(val) *' type
392 ex. addr = addressof(hello_obj) #python
393 is same as
394 uintptr_t addr = (uintptr_t)&hello_obj #C
395 """
396 if type(val) is value:
397 return value(val.GetSBValue().AddressOf())
398 raise TypeError("Cannot do addressof for non-value type objects")
399
400def cast(obj, target_type):
401 """ Type cast an object to another C type.
402 params:
403 obj - core.value object representing some C construct in lldb
404 target_type - str : ex 'char *'
405 - lldb.SBType :
406 """
407 dest_type = target_type
408 if type(target_type) is str:
409 dest_type = gettype(target_type)
410 elif type(target_type) is value:
411 dest_type = target_type.GetSBValue().GetType()
412
413 if type(obj) is value :
414 return value(obj.GetSBValue().Cast(dest_type))
415 elif type(obj) is int:
416 print "ERROR: You cannot cast an 'int' to %s, please use kern.GetValueFromAddress() for such purposes." % str(target_type)
417 raise TypeError("object of type %s cannot be casted to %s" % (str(type(obj)), str(target_type)))
418
813fb2f6 419
39236c6e
A
420_value_types_cache={}
421
422def gettype(target_type):
423 """ Returns lldb.SBType of the given target_type
424 params:
425 target_type - str, ex. 'char', 'uint32_t' etc
426 returns:
427 lldb.SBType - SBType corresponding to the given target_type
428 raises:
429 NameError - Incase the type is not identified
430 """
431 global _value_types_cache
39236c6e 432 target_type = str(target_type).strip()
813fb2f6
A
433 if target_type in _value_types_cache:
434 return _value_types_cache[target_type]
435
5ba3f43e
A
436 target_type = target_type.strip()
437
438 requested_type_is_struct = False
439 m = re.match(r'\s*struct\s*(.*)$', target_type)
440 if m:
441 requested_type_is_struct = True
442 target_type = m.group(1)
443
813fb2f6
A
444 tmp_type = None
445 requested_type_is_pointer = False
446 if target_type.endswith('*') :
447 requested_type_is_pointer = True
448
449 # tmp_type = LazyTarget.GetTarget().FindFirstType(target_type.rstrip('*').strip())
450 search_type = target_type.rstrip('*').strip()
451 type_arr = [t for t in LazyTarget.GetTarget().FindTypes(search_type)]
452
5ba3f43e
A
453 if requested_type_is_struct:
454 type_arr = [t for t in type_arr if t.type == lldb.eTypeClassStruct]
455
813fb2f6
A
456 # After the sort, the struct type with more fields will be at index [0].
457 # This hueristic helps selecting struct type with more fields compared to ones with "opaque" members
458 type_arr.sort(reverse=True, key=lambda x: x.GetNumberOfFields())
459 if len(type_arr) > 0:
460 tmp_type = type_arr[0]
461 else:
462 raise NameError('Unable to find type '+target_type)
463
464 if not tmp_type.IsValid():
465 raise NameError('Unable to Cast to type '+target_type)
466
467 if requested_type_is_pointer:
468 tmp_type = tmp_type.GetPointerType()
469 _value_types_cache[target_type] = tmp_type
470
39236c6e
A
471 return _value_types_cache[target_type]
472
813fb2f6 473
39236c6e
A
474def getfieldoffset(struct_type, field_name):
475 """ Returns the byte offset of a field inside a given struct
5ba3f43e 476 Understands anonymous unions and field names in sub-structs
39236c6e
A
477 params:
478 struct_type - str or lldb.SBType, ex. 'struct ipc_port *' or port.gettype()
479 field_name - str, name of the field inside the struct ex. 'ip_messages'
480 returns:
481 int - byte offset of the field_name inside the struct_type
482 raises:
483 TypeError - - In case the struct_type has no field with the name field_name
484 """
5ba3f43e 485
39236c6e
A
486 if type(struct_type) == str:
487 struct_type = gettype(struct_type)
5ba3f43e
A
488
489 if '.' in field_name :
490 # Handle recursive fields in sub-structs
491 components = field_name.split('.', 1)
492 for field in struct_type.get_fields_array():
493 if str(field.GetName()) == components[0]:
494 return getfieldoffset(struct_type, components[0]) + getfieldoffset(field.GetType(), components[1])
495 raise TypeError('Field name "%s" not found in type "%s"' % (components[0], str(struct_type)))
496
39236c6e
A
497 offset = 0
498 for field in struct_type.get_fields_array():
499 if str(field.GetName()) == field_name:
500 return field.GetOffsetInBytes()
5ba3f43e 501
39037602
A
502 # Hack for anonymous unions - the compiler does this, so cvalue should too
503 if field.GetName() is None and field.GetType().GetTypeClass() == lldb.eTypeClassUnion :
504 for union_field in field.GetType().get_fields_array():
505 if str(union_field.GetName()) == field_name:
506 return union_field.GetOffsetInBytes() + field.GetOffsetInBytes()
39236c6e
A
507 raise TypeError('Field name "%s" not found in type "%s"' % (field_name, str(struct_type)))
508
509def islong(x):
510 """ Returns True if a string represents a long integer, False otherwise
511 """
512 try:
513 long(x,16)
514 except ValueError:
515 try:
516 long(x)
517 except ValueError:
518 return False
519 return True
fe8ab488
A
520
521def readmemory(val):
522 """ Returns a string of hex data that is referenced by the value.
523 params: val - a value object.
524 return: str - string of hex bytes.
525 raises: TypeError if val is not a valid type
526 """
527 if not type(val) is value:
528 raise TypeError('%s is not of type value' % str(type(val)))
529 return val.__getstate__()