--- /dev/null
+"""
+Defines a class value which encapsulates the basic lldb Scripting Bridge APIs. This provides an easy
+wrapper to extract information from C based constructs.
+ |------- core.value------------|
+ | |--lldb Scripting Bridge--| |
+ | | |--lldb core--| | |
+ | |-------------------------| |
+ |------------------------------|
+Use the member function GetSBValue() to access the base Scripting Bridge value.
+"""
+import lldb
+import re
+from lazytarget import *
+
+_cstring_rex = re.compile("((?:\s*|const\s+)\s*char(?:\s+\*|\s+[A-Za-z_0-9]*\s*\[|)\s*)",re.MULTILINE|re.DOTALL)
+
+class value(object):
+ '''A class designed to wrap lldb.SBValue() objects so the resulting object
+ can be used as a variable would be in code. So if you have a Point structure
+ variable in your code in the current frame named "pt", you can initialize an instance
+ of this class with it:
+
+ pt = lldb.value(lldb.frame.FindVariable("pt"))
+ print pt
+ print pt.x
+ print pt.y
+
+ pt = lldb.value(lldb.frame.FindVariable("rectangle_array"))
+ print rectangle_array[12]
+ print rectangle_array[5].origin.x'''
+ def __init__(self, sbvalue):
+ #_sbval19k84obscure747 is specifically chosen to be obscure.
+ #This avoids conflicts when attributes could mean any field value in code
+ self._sbval19k84obscure747 = sbvalue
+ self._sbval19k84obscure747_type = sbvalue.GetType()
+ self._sbval19k84obscure747_is_ptr = sbvalue.GetType().IsPointerType()
+ self.sbvalue = sbvalue
+
+ def __nonzero__(self):
+ return ( self._sbval19k84obscure747.__nonzero__() and self._GetValueAsUnsigned() != 0 )
+
+ def __repr__(self):
+ return self._sbval19k84obscure747.__str__()
+
+ def __cmp__(self, other):
+ if type(other) is int:
+ me = int(self)
+ if type(me) is long:
+ other = long(other)
+ return me.__cmp__(other)
+ if type(other) is value:
+ return int(self).__cmp__(int(other))
+ raise TypeError("Cannot compare value with this type")
+
+ def __str__(self):
+ global _cstring_rex
+ type_name = self._sbval19k84obscure747_type.GetName()
+ if len(_cstring_rex.findall(type_name)) > 0 :
+ return self._GetValueAsString()
+ summary = self._sbval19k84obscure747.GetSummary()
+ if summary:
+ return summary.strip('"')
+ return self._sbval19k84obscure747.__str__()
+
+ def __getitem__(self, key):
+ # Allow array access if this value has children...
+ if type(key) is slice:
+ _start = int(key.start)
+ _end = int(key.stop)
+ _step = 1
+ if key.step != None:
+ _step = int(key.step)
+ retval = []
+ while _start < _end:
+ retval.append(self[_start])
+ _start += _step
+ return retval
+ if type(key) in (int, long):
+ return value(self._sbval19k84obscure747.GetValueForExpressionPath("[%i]" % key))
+ if type(key) is value:
+ return value(self._sbval19k84obscure747.GetValueForExpressionPath("[%i]" % int(key)))
+ raise TypeError("Cannot fetch Array item for this type")
+
+ def __getattr__(self, name):
+ child_sbvalue = self._sbval19k84obscure747.GetChildMemberWithName (name)
+ if child_sbvalue:
+ return value(child_sbvalue)
+ raise AttributeError("No field by name: "+name )
+
+ def __add__(self, other):
+ return int(self) + int(other)
+
+ def __radd__(self, other):
+ return int(self) + int(other)
+
+ def __sub__(self, other):
+ return int(self) - int(other)
+
+ def __rsub__(self, other):
+ return int(other) - int(self)
+
+ def __mul__(self, other):
+ return int(self) * int(other)
+
+ def __rmul__(self, other):
+ return int(self) * int(other)
+
+ def __floordiv__(self, other):
+ return int(self) // int(other)
+
+ def __mod__(self, other):
+ return int(self) % int(other)
+
+ def __rmod__(self, other):
+ return int(other) % int(self)
+
+ def __divmod__(self, other):
+ return int(self) % int(other)
+
+ def __rdivmod__(self, other):
+ return int(other) % int(self)
+
+ def __pow__(self, other):
+ return int(self) ** int(other)
+
+ def __lshift__(self, other):
+ return int(self) << int(other)
+
+ def __rshift__(self, other):
+ return int(self) >> int(other)
+
+ def __and__(self, other):
+ return int(self) & int(other)
+
+ def __rand(self, other):
+ return int(self) & int(other)
+
+ def __xor__(self, other):
+ return int(self) ^ int(other)
+
+ def __or__(self, other):
+ return int(self) | int(other)
+
+ def __div__(self, other):
+ return int(self) / int(other)
+
+ def __rdiv__(self, other):
+ return int(other)/int(self)
+
+ def __truediv__(self, other):
+ return int(self) / int(other)
+
+ def __iadd__(self, other):
+ result = self.__add__(other)
+ self._sbval19k84obscure747.SetValueFromCString (str(result))
+ return result
+
+ def __isub__(self, other):
+ result = self.__sub__(other)
+ self._sbval19k84obscure747.SetValueFromCString (str(result))
+ return result
+
+ def __imul__(self, other):
+ result = self.__mul__(other)
+ self._sbval19k84obscure747.SetValueFromCString (str(result))
+ return result
+
+ def __idiv__(self, other):
+ result = self.__div__(other)
+ self._sbval19k84obscure747.SetValueFromCString (str(result))
+ return result
+
+ def __itruediv__(self, other):
+ result = self.__truediv__(other)
+ self._sbval19k84obscure747.SetValueFromCString (str(result))
+ return result
+
+ def __ifloordiv__(self, other):
+ result = self.__floordiv__(self, other)
+ self._sbval19k84obscure747.SetValueFromCString (str(result))
+ return result
+
+ def __imod__(self, other):
+ result = self.__and__(self, other)
+ self._sbval19k84obscure747.SetValueFromCString (str(result))
+ return result
+
+ def __ipow__(self, other):
+ result = self.__pow__(self, other)
+ self._sbval19k84obscure747.SetValueFromCString (str(result))
+ return result
+
+ def __ipow__(self, other, modulo):
+ result = self.__pow__(self, other, modulo)
+ self._sbval19k84obscure747.SetValueFromCString (str(result))
+ return result
+
+ def __ilshift__(self, other):
+ result = self.__lshift__(other)
+ self._sbval19k84obscure747.SetValueFromCString (str(result))
+ return result
+
+ def __irshift__(self, other):
+ result = self.__rshift__(other)
+ self._sbval19k84obscure747.SetValueFromCString (str(result))
+ return result
+
+ def __iand__(self, other):
+ result = self.__and__(self, other)
+ self._sbval19k84obscure747.SetValueFromCString (str(result))
+ return result
+
+ def __ixor__(self, other):
+ result = self.__xor__(self, other)
+ self._sbval19k84obscure747.SetValueFromCString (str(result))
+ return result
+
+ def __ior__(self, other):
+ result = self.__ior__(self, other)
+ self._sbval19k84obscure747.SetValueFromCString (str(result))
+ return result
+
+ def __neg__(self):
+ return -int(self)
+
+ def __pos__(self):
+ return +int(self)
+
+ def __abs__(self):
+ return abs(int(self))
+
+ def __invert__(self):
+ return ~int(self)
+
+ def __complex__(self):
+ return complex (int(self))
+
+ def __int__(self):
+ if self._sbval19k84obscure747_is_ptr:
+ return self._GetValueAsUnsigned()
+ tname= self._sbval19k84obscure747_type.GetName()
+ if tname.find('uint') >= 0 or tname.find('unsigned') >= 0:
+ return self._GetValueAsUnsigned()
+ retval = self._sbval19k84obscure747.GetValueAsSigned()
+ # <rdar://problem/12481949> lldb python: GetValueAsSigned does not return the correct value
+ if (retval & 0x80000000):
+ retval = retval - 0x100000000
+ return retval
+
+ def __long__(self):
+ return self._sbval19k84obscure747.GetValueAsSigned()
+
+ def __float__(self):
+ return float (self._sbval19k84obscure747.GetValueAsSigned())
+
+ def __oct__(self):
+ return '0%o' % self._GetValueAsUnsigned()
+
+ def __hex__(self):
+ return '0x%x' % self._GetValueAsUnsigned()
+
+ def __eq__(self, other):
+ self_err = lldb.SBError()
+ other_err = lldb.SBError()
+ self_val = self._sbval19k84obscure747.GetValueAsUnsigned(self_err)
+ if self_err.fail:
+ raise ValueError("unable to extract value of self")
+ if type(other) is value:
+ other_val = other._sbval19k84obscure747.GetValueAsUnsigned(other_err)
+ if other_err.fail:
+ raise ValueError("unable to extract value of other")
+ return self_val == other_val
+ if type(other) is int:
+ return int(self) == other
+ raise TypeError("Equality operation is not defined for this type.")
+
+ def __neq__(self, other):
+ return not self.__eq__(other)
+
+ def GetSBValue(self):
+ return self._sbval19k84obscure747
+
+ def _GetValueAsSigned(self):
+ serr = lldb.SBError()
+ retval = self._sbval19k84obscure747.GetValueAsSigned(serr)
+ if serr.success:
+ return retval
+ raise ValueError("Failed to read signed data. "+ str(self._sbval19k84obscure747) +"(type =" + str(self._sbval19k84obscure747_type) + ") Error description: " + serr.GetCString())
+
+ def _GetValueAsUnsigned(self):
+ serr = lldb.SBError()
+ retval = self._sbval19k84obscure747.GetValueAsUnsigned(serr)
+ if serr.success:
+ return retval
+ raise ValueError("Failed to read unsigned data. "+ str(self._sbval19k84obscure747) +"(type =" + str(self._sbval19k84obscure747_type) + ") Error description: " + serr.GetCString())
+
+ def _GetValueAsString(self, offset = 0, maxlen = 1024):
+ serr = lldb.SBError()
+ sbdata = None
+ if self._sbval19k84obscure747.TypeIsPointerType():
+ sbdata = self._sbval19k84obscure747.GetPointeeData(offset, maxlen)
+ else:
+ sbdata = self._sbval19k84obscure747.GetData()
+
+ retval = ''
+ bytesize = sbdata.GetByteSize()
+ if bytesize == 0 :
+ #raise ValueError('Unable to read value as string')
+ return ''
+ for i in range(0, bytesize) :
+ serr.Clear()
+ ch = chr(sbdata.GetUnsignedInt8(serr, i))
+ if serr.fail :
+ raise ValueError("Unable to read string data: " + serr.GetCString())
+ if ch == '\0':
+ break
+ retval += ch
+ return retval
+
+ def __format__(self, format_spec):
+ ret_format = "{0:"+format_spec+"}"
+ # typechar is last char. see http://www.python.org/dev/peps/pep-3101/
+ type_spec=format_spec.strip().lower()[-1]
+ if type_spec == 'x':
+ return ret_format.format(self._GetValueAsUnsigned())
+ if type_spec == 'd':
+ return ret_format.format(int(self))
+ if type_spec == 's':
+ return ret_format.format(str(self))
+ if type_spec == 'o':
+ return ret_format.format(int(oct(self)))
+ if type_spec == 'c':
+ return ret_format.format(int(self))
+
+ return "unknown format " + format_spec + str(self)
+
+
+def unsigned(val):
+ """ Helper function to get unsigned value from core.value
+ params: val - value (see value class above) representation of an integer type
+ returns: int which is unsigned.
+ raises : ValueError if the type cannot be represented as unsigned int.
+ """
+ if type(val) is value:
+ return val._GetValueAsUnsigned()
+ return int(val)
+
+def sizeof(t):
+ """ Find the byte size of a type.
+ params: t - str : ex 'time_spec' returns equivalent of sizeof(time_spec) in C
+ t - value: ex a value object. returns size of the object
+ returns: int - byte size length
+ """
+ if type(t) is value :
+ return t.GetSBValue().GetByteSize()
+ if type(t) is str:
+ return gettype(t).GetByteSize()
+ raise ValueError("Cannot get sizeof. Invalid argument")
+
+
+def dereference(val):
+ """ Get a dereferenced obj for a pointer type obj
+ params: val - value object representing a pointer type C construct in lldb
+ returns: value - value
+ ex. val = dereference(ptr_obj) #python
+ is same as
+ obj_ptr = (int *)0x1234 #C
+ val = *obj_ptr #C
+ """
+ if type(val) is value and val.GetSBValue().TypeIsPointerType():
+ return value(val.GetSBValue().Dereference())
+ raise TypeError('Cannot dereference this type.')
+
+def addressof(val):
+ """ Get address of a core.value object.
+ params: val - value object representing a C construct in lldb
+ returns: value - value object referring to 'type(val) *' type
+ ex. addr = addressof(hello_obj) #python
+ is same as
+ uintptr_t addr = (uintptr_t)&hello_obj #C
+ """
+ if type(val) is value:
+ return value(val.GetSBValue().AddressOf())
+ raise TypeError("Cannot do addressof for non-value type objects")
+
+def cast(obj, target_type):
+ """ Type cast an object to another C type.
+ params:
+ obj - core.value object representing some C construct in lldb
+ target_type - str : ex 'char *'
+ - lldb.SBType :
+ """
+ dest_type = target_type
+ if type(target_type) is str:
+ dest_type = gettype(target_type)
+ elif type(target_type) is value:
+ dest_type = target_type.GetSBValue().GetType()
+
+ if type(obj) is value :
+ return value(obj.GetSBValue().Cast(dest_type))
+ elif type(obj) is int:
+ print "ERROR: You cannot cast an 'int' to %s, please use kern.GetValueFromAddress() for such purposes." % str(target_type)
+ raise TypeError("object of type %s cannot be casted to %s" % (str(type(obj)), str(target_type)))
+
+_value_types_cache={}
+
+def gettype(target_type):
+ """ Returns lldb.SBType of the given target_type
+ params:
+ target_type - str, ex. 'char', 'uint32_t' etc
+ returns:
+ lldb.SBType - SBType corresponding to the given target_type
+ raises:
+ NameError - Incase the type is not identified
+ """
+ global _value_types_cache
+ # LLDB Somehow does not support finding types for 'struct pmap' while 'pmap' works fine
+ # <rdar://problem/12473003>
+ target_type = target_type.replace('struct', '')
+ target_type = str(target_type).strip()
+ if target_type not in _value_types_cache:
+ tmp_type = None
+ if target_type.endswith('*') :
+ tmp_type = LazyTarget.GetTarget().FindFirstType(target_type.rstrip('*').strip())
+ if not tmp_type.IsValid():
+ raise NameError('Unable to Cast to type '+target_type)
+ tmp_type = tmp_type.GetPointerType()
+ else :
+ tmp_type = LazyTarget.GetTarget().FindFirstType(target_type)
+ if not tmp_type.IsValid():
+ raise NameError('Unable to Cast to type '+target_type)
+ _value_types_cache[target_type] = tmp_type
+ return _value_types_cache[target_type]
+
+def getfieldoffset(struct_type, field_name):
+ """ Returns the byte offset of a field inside a given struct
+ params:
+ struct_type - str or lldb.SBType, ex. 'struct ipc_port *' or port.gettype()
+ field_name - str, name of the field inside the struct ex. 'ip_messages'
+ returns:
+ int - byte offset of the field_name inside the struct_type
+ raises:
+ TypeError - - In case the struct_type has no field with the name field_name
+ """
+ if type(struct_type) == str:
+ struct_type = gettype(struct_type)
+ offset = 0
+ for field in struct_type.get_fields_array():
+ if str(field.GetName()) == field_name:
+ return field.GetOffsetInBytes()
+ raise TypeError('Field name "%s" not found in type "%s"' % (field_name, str(struct_type)))
+
+def islong(x):
+ """ Returns True if a string represents a long integer, False otherwise
+ """
+ try:
+ long(x,16)
+ except ValueError:
+ try:
+ long(x)
+ except ValueError:
+ return False
+ return True