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:
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))
53        raise TypeError("Cannot compare value with this type")
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
283    def _GetValueAsSigned(self):
284        serr = lldb.SBError()
285        retval = self._sbval19k84obscure747.GetValueAsSigned(serr)
286        if serr.success:
287            return retval
288        raise ValueError("Failed to read signed data. "+ str(self._sbval19k84obscure747) +"(type =" + str(self._sbval19k84obscure747_type) + ") Error description: " + serr.GetCString())
289
290    def _GetValueAsUnsigned(self):
291        serr = lldb.SBError()
292        retval = self._sbval19k84obscure747.GetValueAsUnsigned(serr)
293        if serr.success:
294            return retval
295        raise ValueError("Failed to read unsigned data. "+ str(self._sbval19k84obscure747) +"(type =" + str(self._sbval19k84obscure747_type) + ") Error description: " + serr.GetCString())
296
297    def _GetValueAsString(self, offset = 0, maxlen = 1024):
298        serr = lldb.SBError()
299        sbdata = None
300        if self._sbval19k84obscure747.TypeIsPointerType():
301            sbdata = self._sbval19k84obscure747.GetPointeeData(offset, maxlen)
302        else:
303            sbdata = self._sbval19k84obscure747.GetData()
304
305        retval = ''
306        bytesize = sbdata.GetByteSize()
307        if bytesize == 0 :
308            #raise ValueError('Unable to read value as string')
309            return ''
310        for i in range(0, bytesize) :
311            serr.Clear()
312            ch = chr(sbdata.GetUnsignedInt8(serr, i))
313            if serr.fail :
314                raise ValueError("Unable to read string data: " + serr.GetCString())
315            if ch == '\0':
316                break
317            retval += ch
318        return retval
319
320    def __format__(self, format_spec):
321        ret_format = "{0:"+format_spec+"}"
322        # typechar is last char. see http://www.python.org/dev/peps/pep-3101/
323        type_spec=format_spec.strip().lower()[-1]
324        if type_spec == 'x':
325            return ret_format.format(self._GetValueAsUnsigned())
326        if type_spec == 'd':
327            return ret_format.format(int(self))
328        if type_spec == 's':
329            return ret_format.format(str(self))
330        if type_spec == 'o':
331            return ret_format.format(int(oct(self)))
332        if type_spec == 'c':
333            return ret_format.format(int(self))
334
335        return "unknown format " + format_spec + str(self)
336
337
338def unsigned(val):
339    """ Helper function to get unsigned value from core.value
340        params: val - value (see value class above) representation of an integer type
341        returns: int which is unsigned.
342        raises : ValueError if the type cannot be represented as unsigned int.
343    """
344    if type(val) is value:
345        return val._GetValueAsUnsigned()
346    return int(val)
347
348def sizeof(t):
349    """ Find the byte size of a type.
350        params: t - str : ex 'time_spec' returns equivalent of sizeof(time_spec) in C
351                t - value: ex a value object. returns size of the object
352        returns: int - byte size length
353    """
354    if type(t) is value :
355        return t.GetSBValue().GetByteSize()
356    if type(t) is str:
357        return gettype(t).GetByteSize()
358    raise ValueError("Cannot get sizeof. Invalid argument")
359
360
361def dereference(val):
362    """ Get a dereferenced obj for a pointer type obj
363        params: val - value object representing a pointer type C construct in lldb
364        returns: value - value
365        ex. val = dereference(ptr_obj) #python
366        is same as
367            obj_ptr = (int *)0x1234  #C
368            val = *obj_ptr           #C
369    """
370    if type(val) is value and val.GetSBValue().TypeIsPointerType():
371        return value(val.GetSBValue().Dereference())
372    raise TypeError('Cannot dereference this type.')
373
374def addressof(val):
375    """ Get address of a core.value object.
376        params: val - value object representing a C construct in lldb
377        returns: value - value object referring to 'type(val) *' type
378        ex. addr = addressof(hello_obj)  #python
379        is same as
380           uintptr_t addr = (uintptr_t)&hello_obj  #C
381    """
382    if type(val) is value:
383        return value(val.GetSBValue().AddressOf())
384    raise TypeError("Cannot do addressof for non-value type objects")
385
386def cast(obj, target_type):
387    """ Type cast an object to another C type.
388        params:
389            obj - core.value  object representing some C construct in lldb
390            target_type - str : ex 'char *'
391                        - lldb.SBType :
392    """
393    dest_type = target_type
394    if type(target_type) is str:
395        dest_type = gettype(target_type)
396    elif type(target_type) is value:
397        dest_type = target_type.GetSBValue().GetType()
398
399    if type(obj) is value :
400        return value(obj.GetSBValue().Cast(dest_type))
401    elif type(obj) is int:
402        print "ERROR: You cannot cast an 'int' to %s, please use kern.GetValueFromAddress() for such purposes." % str(target_type)
403    raise TypeError("object of type %s cannot be casted to %s" % (str(type(obj)), str(target_type)))
404
405_value_types_cache={}
406
407def gettype(target_type):
408    """ Returns lldb.SBType of the given target_type
409        params:
410            target_type - str, ex. 'char', 'uint32_t' etc
411        returns:
412            lldb.SBType - SBType corresponding to the given target_type
413        raises:
414            NameError  - Incase the type is not identified
415    """
416    global _value_types_cache
417    # LLDB Somehow does not support finding types for 'struct pmap' while 'pmap' works fine
418    # <rdar://problem/12473003>
419    target_type = target_type.replace('struct', '')
420    target_type = str(target_type).strip()
421    if target_type not in _value_types_cache:
422        tmp_type = None
423        if target_type.endswith('*') :
424            tmp_type = LazyTarget.GetTarget().FindFirstType(target_type.rstrip('*').strip())
425            if not tmp_type.IsValid():
426                raise NameError('Unable to Cast to type '+target_type)
427            tmp_type = tmp_type.GetPointerType()
428        else :
429            tmp_type = LazyTarget.GetTarget().FindFirstType(target_type)
430            if not tmp_type.IsValid():
431                raise NameError('Unable to Cast to type '+target_type)
432        _value_types_cache[target_type] = tmp_type
433    return _value_types_cache[target_type]
434
435def getfieldoffset(struct_type, field_name):
436    """ Returns the byte offset of a field inside a given struct
437        params:
438            struct_type - str or lldb.SBType, ex. 'struct ipc_port *' or port.gettype()
439            field_name  - str, name of the field inside the struct ex. 'ip_messages'
440        returns:
441            int - byte offset of the field_name inside the struct_type
442        raises:
443            TypeError  - - In case the struct_type has no field with the name field_name
444    """
445    if type(struct_type) == str:
446        struct_type = gettype(struct_type)
447    offset = 0
448    for field in struct_type.get_fields_array():
449        if str(field.GetName()) == field_name:
450            return field.GetOffsetInBytes()
451    raise TypeError('Field name "%s" not found in type "%s"' % (field_name, str(struct_type)))
452
453def islong(x):
454    """ Returns True if a string represents a long integer, False otherwise
455    """
456    try:
457        long(x,16)
458    except ValueError:
459        try:
460            long(x)
461        except ValueError:
462            return False
463    return True
464