xref: /xnu-8019.80.24/tools/lldbmacros/core/cvalue.py (revision a325d9c4a84054e40bbe985afedcb50ab80993ea)
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