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): 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_val = self._GetValueAsUnsigned() 267 if type(other) is value: 268 other_val = other._GetValueAsUnsigned() 269 return self_val == other_val 270 if type(other) is int: 271 return int(self) == other 272 raise TypeError("Equality operation is not defined for this type.") 273 274 def __neq__(self, other): 275 return not self.__eq__(other) 276 277 def GetSBValue(self): 278 return self._sbval19k84obscure747 279 280 def __getstate__(self): 281 err = lldb.SBError() 282 if self._sbval19k84obscure747_is_ptr: 283 addr = self._sbval19k84obscure747.GetValueAsAddress() 284 size = self._sbval19k84obscure747_type.GetPointeeType().GetByteSize() 285 else: 286 addr = self._sbval19k84obscure747.AddressOf().GetValueAsAddress() 287 size = self._sbval19k84obscure747_type.GetByteSize() 288 289 content = LazyTarget.GetProcess().ReadMemory(addr, size, err) 290 if err.fail: 291 content = '' 292 return content 293 294 def _GetValueAsSigned(self): 295 if self._sbval19k84obscure747_is_ptr: 296 print "ERROR: You cannot get 'int' from pointer type %s, please use unsigned(obj) for such purposes." % str(self._sbval19k84obscure747_type) 297 raise ValueError("Cannot get signed int for pointer data.") 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 _GetValueAsCast(self, dest_type): 305 if type(dest_type) is not lldb.SBType: 306 raise ValueError("Invalid type for dest_type: {}".format(type(dest_type))) 307 addr = self._GetValueAsUnsigned() 308 sbval = self._sbval19k84obscure747.target.CreateValueFromExpression("newname", "(void *)"+str(addr)) 309 val = value(sbval.Cast(dest_type)) 310 return val 311 312 def _GetValueAsUnsigned(self): 313 serr = lldb.SBError() 314 if self._sbval19k84obscure747_is_ptr: 315 retval = self._sbval19k84obscure747.GetValueAsAddress() 316 else: 317 retval = self._sbval19k84obscure747.GetValueAsUnsigned(serr) 318 if serr.success: 319 return retval 320 raise ValueError("Failed to read unsigned data. "+ str(self._sbval19k84obscure747) +"(type =" + str(self._sbval19k84obscure747_type) + ") Error description: " + serr.GetCString()) 321 322 def _GetValueAsString(self, offset = 0, maxlen = 1024): 323 serr = lldb.SBError() 324 sbdata = None 325 if self._sbval19k84obscure747_is_ptr: 326 sbdata = self._sbval19k84obscure747.GetPointeeData(offset, maxlen) 327 else: 328 sbdata = self._sbval19k84obscure747.GetData() 329 330 retval = '' 331 bytesize = sbdata.GetByteSize() 332 if bytesize == 0 : 333 #raise ValueError('Unable to read value as string') 334 return '' 335 for i in range(0, bytesize) : 336 serr.Clear() 337 ch = chr(sbdata.GetUnsignedInt8(serr, i)) 338 if serr.fail : 339 raise ValueError("Unable to read string data: " + serr.GetCString()) 340 if ch == '\0': 341 break 342 retval += ch 343 return retval 344 345 def __format__(self, format_spec): 346 ret_format = "{0:"+format_spec+"}" 347 # typechar is last char. see http://www.python.org/dev/peps/pep-3101/ 348 type_spec=format_spec.strip().lower()[-1] 349 if type_spec == 'x': 350 return ret_format.format(self._GetValueAsUnsigned()) 351 if type_spec == 'd': 352 return ret_format.format(int(self)) 353 if type_spec == 's': 354 return ret_format.format(str(self)) 355 if type_spec == 'o': 356 return ret_format.format(int(oct(self))) 357 if type_spec == 'c': 358 return ret_format.format(int(self)) 359 360 return "unknown format " + format_spec + str(self) 361 362 363def unsigned(val): 364 """ Helper function to get unsigned value from core.value 365 params: val - value (see value class above) representation of an integer type 366 returns: int which is unsigned. 367 raises : ValueError if the type cannot be represented as unsigned int. 368 """ 369 if type(val) is value: 370 return val._GetValueAsUnsigned() 371 return int(val) 372 373def sizeof(t): 374 """ Find the byte size of a type. 375 params: t - str : ex 'time_spec' returns equivalent of sizeof(time_spec) in C 376 t - value: ex a value object. returns size of the object 377 returns: int - byte size length 378 """ 379 if type(t) is value : 380 return t.GetSBValue().GetByteSize() 381 if type(t) is str: 382 return gettype(t).GetByteSize() 383 raise ValueError("Cannot get sizeof. Invalid argument") 384 385 386def dereference(val): 387 """ Get a dereferenced obj for a pointer type obj 388 params: val - value object representing a pointer type C construct in lldb 389 returns: value - value 390 ex. val = dereference(ptr_obj) #python 391 is same as 392 obj_ptr = (int *)0x1234 #C 393 val = *obj_ptr #C 394 """ 395 if type(val) is value and val._sbval19k84obscure747_is_ptr: 396 return value(val.GetSBValue().Dereference()) 397 raise TypeError('Cannot dereference this type.') 398 399def addressof(val): 400 """ Get address of a core.value object. 401 params: val - value object representing a C construct in lldb 402 returns: value - value object referring to 'type(val) *' type 403 ex. addr = addressof(hello_obj) #python 404 is same as 405 uintptr_t addr = (uintptr_t)&hello_obj #C 406 """ 407 if type(val) is value: 408 return value(val.GetSBValue().AddressOf()) 409 raise TypeError("Cannot do addressof for non-value type objects") 410 411def cast(obj, target_type): 412 """ Type cast an object to another C type. 413 params: 414 obj - core.value object representing some C construct in lldb 415 target_type - str : ex 'char *' 416 - lldb.SBType : 417 """ 418 dest_type = target_type 419 if type(target_type) is str: 420 dest_type = gettype(target_type) 421 elif type(target_type) is value: 422 dest_type = target_type.GetSBValue().GetType() 423 424 if type(obj) is value: 425 return obj._GetValueAsCast(dest_type) 426 elif type(obj) is int: 427 print "ERROR: You cannot cast an 'int' to %s, please use kern.GetValueFromAddress() for such purposes." % str(target_type) 428 raise TypeError("object of type %s cannot be casted to %s" % (str(type(obj)), str(target_type))) 429 430def containerof(obj, target_type, field_name): 431 """ Type cast an object to another C type from a pointer to a field. 432 params: 433 obj - core.value object representing some C construct in lldb 434 target_type - str : ex 'struct thread' 435 - lldb.SBType : 436 field_name - the field name within the target_type obj is a pointer to 437 """ 438 addr = int(obj) - getfieldoffset(target_type, field_name) 439 obj = value(obj.GetSBValue().CreateValueFromExpression(None,'(void *)'+str(addr))) 440 return cast(obj, target_type + " *") 441 442 443_value_types_cache={} 444 445def gettype(target_type): 446 """ Returns lldb.SBType of the given target_type 447 params: 448 target_type - str, ex. 'char', 'uint32_t' etc 449 returns: 450 lldb.SBType - SBType corresponding to the given target_type 451 raises: 452 NameError - Incase the type is not identified 453 """ 454 global _value_types_cache 455 target_type = str(target_type).strip() 456 if target_type in _value_types_cache: 457 return _value_types_cache[target_type] 458 459 target_type = target_type.strip() 460 461 requested_type_is_struct = False 462 m = re.match(r'\s*struct\s*(.*)$', target_type) 463 if m: 464 requested_type_is_struct = True 465 target_type = m.group(1) 466 467 tmp_type = None 468 requested_type_is_pointer = False 469 if target_type.endswith('*') : 470 requested_type_is_pointer = True 471 472 # tmp_type = LazyTarget.GetTarget().FindFirstType(target_type.rstrip('*').strip()) 473 search_type = target_type.rstrip('*').strip() 474 type_arr = [t for t in LazyTarget.GetTarget().FindTypes(search_type)] 475 476 if requested_type_is_struct: 477 type_arr = [t for t in type_arr if t.type == lldb.eTypeClassStruct] 478 479 # After the sort, the struct type with more fields will be at index [0]. 480 # This hueristic helps selecting struct type with more fields compared to ones with "opaque" members 481 type_arr.sort(reverse=True, key=lambda x: x.GetNumberOfFields()) 482 if len(type_arr) > 0: 483 tmp_type = type_arr[0] 484 else: 485 raise NameError('Unable to find type '+target_type) 486 487 if not tmp_type.IsValid(): 488 raise NameError('Unable to Cast to type '+target_type) 489 490 if requested_type_is_pointer: 491 tmp_type = tmp_type.GetPointerType() 492 _value_types_cache[target_type] = tmp_type 493 494 return _value_types_cache[target_type] 495 496 497def getfieldoffset(struct_type, field_name): 498 """ Returns the byte offset of a field inside a given struct 499 Understands anonymous unions and field names in sub-structs 500 params: 501 struct_type - str or lldb.SBType, ex. 'struct ipc_port *' or port.gettype() 502 field_name - str, name of the field inside the struct ex. 'ip_messages' 503 returns: 504 int - byte offset of the field_name inside the struct_type 505 raises: 506 TypeError - - In case the struct_type has no field with the name field_name 507 """ 508 509 if type(struct_type) == str: 510 struct_type = gettype(struct_type) 511 512 if '.' in field_name : 513 # Handle recursive fields in sub-structs 514 components = field_name.split('.', 1) 515 for field in struct_type.get_fields_array(): 516 if str(field.GetName()) == components[0]: 517 return getfieldoffset(struct_type, components[0]) + getfieldoffset(field.GetType(), components[1]) 518 raise TypeError('Field name "%s" not found in type "%s"' % (components[0], str(struct_type))) 519 520 offset = 0 521 for field in struct_type.get_fields_array(): 522 if str(field.GetName()) == field_name: 523 return field.GetOffsetInBytes() 524 525 # Hack for anonymous unions - the compiler does this, so cvalue should too 526 if field.GetName() is None and field.GetType().GetTypeClass() == lldb.eTypeClassUnion : 527 for union_field in field.GetType().get_fields_array(): 528 if str(union_field.GetName()) == field_name: 529 return union_field.GetOffsetInBytes() + field.GetOffsetInBytes() 530 raise TypeError('Field name "%s" not found in type "%s"' % (field_name, str(struct_type))) 531 532def islong(x): 533 """ Returns True if a string represents a long integer, False otherwise 534 """ 535 try: 536 long(x,16) 537 except ValueError: 538 try: 539 long(x) 540 except ValueError: 541 return False 542 return True 543 544def readmemory(val): 545 """ Returns a string of hex data that is referenced by the value. 546 params: val - a value object. 547 return: str - string of hex bytes. 548 raises: TypeError if val is not a valid type 549 """ 550 if not type(val) is value: 551 raise TypeError('%s is not of type value' % str(type(val))) 552 return val.__getstate__() 553 554def getOSPtr(cpp_obj): 555 """ Returns a core.value created from an intrusive_shared_ptr or itself, cpp_obj 556 params: cpp_obj - core.value object representing a C construct in lldb 557 return: core.value - newly created core.value or cpp_obj 558 """ 559 child = cpp_obj._sbval19k84obscure747.GetChildAtIndex(0) 560 if 'intrusive_shared_ptr' in str(child): 561 return value(child.GetChildMemberWithName('ptr_')) 562 return cpp_obj 563