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