]>
Commit | Line | Data |
---|---|---|
39236c6e A |
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): | |
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 | ||
352 | def 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 | ||
362 | def 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 | ||
375 | def 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 | ||
388 | def 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 | ||
400 | def 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 | ||
422 | def 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 |
474 | def 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 | ||
509 | def 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 | |
521 | def 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__() |