xref: /xnu-8020.121.3/tools/lldbmacros/core/cvalue.py (revision fdd8201d7b966f0c3ea610489d29bd841d358941)
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
5 |------- core.value------------|
6 | |--lldb Scripting Bridge--|  |
7 | |    |--lldb core--|      |  |
8 | |-------------------------|  |
9 |------------------------------|
10
11Use the member function GetSBValue() to access the base Scripting Bridge value.
12"""
13from __future__ import absolute_import, division, print_function
14
15# The value class is designed to be Python 2/3 compatible. Pulling in more
16# builtins classes may break it.
17from builtins import range
18import numbers
19
20# Override int with valueint so we get the desired behavior.
21from .compat import valueint as int
22
23from past.utils import old_div
24import lldb
25import re
26from .lazytarget import LazyTarget
27import six
28
29_CSTRING_REX = re.compile(r"((?:\s*|const\s+)\s*char(?:\s+\*|\s+[A-Za-z_0-9]*\s*\[|)\s*)", re.MULTILINE | re.DOTALL)
30
31
32# pragma pylint: disable=hex-method, div-method, rdiv-method, idiv-method, oct-method, nonzero-method
33class value(object):
34    '''A class designed to wrap lldb.SBValue() objects so the resulting object
35    can be used as a variable would be in code. So if you have a Point structure
36    variable in your code in the current frame named "pt", you can initialize an instance
37    of this class with it:
38
39    pt = lldb.value(lldb.frame.FindVariable("pt"))
40    print pt
41    print pt.x
42    print pt.y
43
44    pt = lldb.value(lldb.frame.FindVariable("rectangle_array"))
45    print rectangle_array[12]
46    print rectangle_array[5].origin.x'''
47    def __init__(self, sbvalue):
48        # _sbval19k84obscure747 is specifically chosen to be obscure.
49        # This avoids conflicts when attributes could mean any field value in code
50        self._sbval19k84obscure747 = sbvalue
51        self._sbval19k84obscure747_type = sbvalue.GetType()
52        self._sbval19k84obscure747_is_ptr = sbvalue.GetType().GetTypeFlags() & lldb.eTypeIsPointer
53        self.sbvalue = sbvalue
54
55    def __bool__(self):
56        return self._sbval19k84obscure747.__bool__() and self._GetValueAsUnsigned() != 0
57
58    def __nonzero__(self):
59        return self._sbval19k84obscure747.__nonzero__() and self._GetValueAsUnsigned() != 0
60
61    def __repr__(self):
62        return self._sbval19k84obscure747.__str__()
63
64    #
65    # Compare operators
66    #
67
68    def __eq__(self, other):
69        self_val = self._GetValueAsUnsigned()
70        if isinstance(other, value):
71            other_val = other._GetValueAsUnsigned()
72            return self_val == other_val
73        if isinstance(other, numbers.Integral):
74            return int(self) == other
75        raise TypeError("EQ operator is not defined for this type.")
76
77    def __ne__(self, other):
78        return not self == other
79
80    def __lt__(self, other):
81        self_val = self._GetValueAsUnsigned()
82        if isinstance(other, value):
83            other_val = other._GetValueAsUnsigned()
84            return self_val < other_val
85        if isinstance(other, numbers.Integral):
86            return int(self) < int(other)
87        raise TypeError("LT operator is not defined for this type")
88
89    def __le__(self, other):
90        return self < other or self == other
91
92    def __gt__(self, other):
93        return not self <= other
94
95    def __ge__(self, other):
96        return not self < other
97
98    def __str__(self):
99        global _CSTRING_REX
100        type_name = self._sbval19k84obscure747_type.GetName()
101        if len(_CSTRING_REX.findall(type_name)) > 0:
102            return self._GetValueAsString()
103        summary = self._sbval19k84obscure747.GetSummary()
104        if summary:
105            return summary.strip('"')
106        return self._sbval19k84obscure747.__str__()
107
108    def __getitem__(self, key):
109        # Allow array access if this value has children...
110        if type(key) is slice:
111            _start = int(key.start)
112            _end = int(key.stop)
113            _step = 1
114            if key.step is not None:
115                _step = int(key.step)
116            retval = []
117            while _start < _end:
118                retval.append(self[_start])
119                _start += _step
120            return retval
121        if isinstance(key, numbers.Integral):
122            return value(self._sbval19k84obscure747.GetValueForExpressionPath("[%i]" % key))
123        if type(key) is value:
124            return value(self._sbval19k84obscure747.GetValueForExpressionPath("[%i]" % int(key)))
125        raise TypeError("Cannot fetch Array item for this type")
126
127    def __getattr__(self, name):
128        child_sbvalue = self._sbval19k84obscure747.GetChildMemberWithName(name)
129        if child_sbvalue:
130            return value(child_sbvalue)
131        raise AttributeError("No field by name: " + name)
132
133    def __add__(self, other):
134        return int(self) + int(other)
135
136    def __radd__(self, other):
137        return int(self) + int(other)
138
139    def __sub__(self, other):
140        return int(self) - int(other)
141
142    def __rsub__(self, other):
143        return int(other) - int(self)
144
145    def __mul__(self, other):
146        return int(self) * int(other)
147
148    def __rmul__(self, other):
149        return int(self) * int(other)
150
151    def __floordiv__(self, other):
152        return int(self) // int(other)
153
154    def __rfloordiv__(self, other):
155        return int(other) // int(self)
156
157    def __mod__(self, other):
158        return int(self) % int(other)
159
160    def __rmod__(self, other):
161        return int(other) % int(self)
162
163    def __divmod__(self, other):
164        return divmod(int(self), int(other))
165
166    def __rdivmod__(self, other):
167        return divmod(int(other), int(self))
168
169    def __pow__(self, other):
170        return int(self) ** int(other)
171
172    def __lshift__(self, other):
173        return int(self) << int(other)
174
175    def __rshift__(self, other):
176        return int(self) >> int(other)
177
178    def __and__(self, other):
179        return int(self) & int(other)
180
181    def __rand__(self, other):
182        return int(other) & int(self)
183
184    def __xor__(self, other):
185        return int(self) ^ int(other)
186
187    def __or__(self, other):
188        return int(self) | int(other)
189
190    def __div__(self, other):
191        return old_div(int(self), int(other))
192
193    def __rdiv__(self, other):
194        return old_div(int(other), int(self))
195
196    def __truediv__(self, other):
197        return int(self) / int(other)
198
199    def __rtruediv__(self, other):
200        return int(other) / int(self)
201
202    def __iadd__(self, other):
203        result = self.__add__(other)
204        self._sbval19k84obscure747.SetValueFromCString(str(result))
205        return result
206
207    def __isub__(self, other):
208        result = self.__sub__(other)
209        self._sbval19k84obscure747.SetValueFromCString(str(result))
210        return result
211
212    def __imul__(self, other):
213        result = self.__mul__(other)
214        self._sbval19k84obscure747.SetValueFromCString(str(result))
215        return result
216
217    def __idiv__(self, other):
218        result = self.__div__(other)
219        self._sbval19k84obscure747.SetValueFromCString(str(result))
220        return result
221
222    def __itruediv__(self, other):
223        result = self.__truediv__(other)
224        self._sbval19k84obscure747.SetValueFromCString(str(result))
225        return result
226
227    def __ifloordiv__(self, other):
228        result = self.__floordiv__(other)
229        self._sbval19k84obscure747.SetValueFromCString(str(result))
230        return result
231
232    def __imod__(self, other):
233        result = self.__mod__(other)
234        self._sbval19k84obscure747.SetValueFromCString(str(result))
235        return result
236
237    def __ipow__(self, other):
238        result = self.__pow__(other)
239        self._sbval19k84obscure747.SetValueFromCString(str(result))
240        return result
241
242    def __ilshift__(self, other):
243        result = self.__lshift__(other)
244        self._sbval19k84obscure747.SetValueFromCString(str(result))
245        return result
246
247    def __irshift__(self, other):
248        result = self.__rshift__(other)
249        self._sbval19k84obscure747.SetValueFromCString(str(result))
250        return result
251
252    def __iand__(self, other):
253        result = self.__and__(other)
254        self._sbval19k84obscure747.SetValueFromCString(str(result))
255        return result
256
257    def __ixor__(self, other):
258        result = self.__xor__(other)
259        self._sbval19k84obscure747.SetValueFromCString(str(result))
260        return result
261
262    def __ior__(self, other):
263        result = self.__or__(other)
264        self._sbval19k84obscure747.SetValueFromCString(str(result))
265        return result
266
267    def __neg__(self):
268        return -int(self)
269
270    def __pos__(self):
271        return +int(self)
272
273    def __abs__(self):
274        return abs(int(self))
275
276    def __invert__(self):
277        return ~int(self)
278
279    def __complex__(self):
280        return complex(int(self))
281
282    def __int__(self):
283        flags = self._sbval19k84obscure747_type.GetTypeFlags()
284        if flags & lldb.eTypeIsPointer:
285            return self._GetValueAsUnsigned()
286        if not flags & lldb.eTypeIsSigned:
287            return self._GetValueAsUnsigned()
288        return int(self._sbval19k84obscure747.GetValueAsSigned())
289
290    # Python 3 conversion to int calls this.
291    def __index__(self):
292        return self.__int__()
293
294    def __long__(self):
295        flags = self._sbval19k84obscure747_type.GetTypeFlags()
296        if flags & lldb.eTypeIsPointer:
297            return self._GetValueAsUnsigned()
298        if not flags & lldb.eTypeIsSigned:
299            return self._GetValueAsUnsigned()
300        return int(self._sbval19k84obscure747.GetValueAsSigned())
301
302    def __float__(self):
303        return float(self._sbval19k84obscure747.GetValueAsSigned())
304
305    # Python 2 must return native string.
306    def __oct__(self):
307        return '0%o' % self._GetValueAsUnsigned()
308
309    # Python 2 must return native string.
310    def __hex__(self):
311        return '0x%x' % self._GetValueAsUnsigned()
312
313    def __hash__(self):
314        return hash(self._sbval19k84obscure747)
315
316    def GetSBValue(self):
317        return self._sbval19k84obscure747
318
319    def __getstate__(self):
320        err = lldb.SBError()
321        if self._sbval19k84obscure747_is_ptr:
322            addr = self._sbval19k84obscure747.GetValueAsAddress()
323            size = self._sbval19k84obscure747_type.GetPointeeType().GetByteSize()
324        else:
325            addr = self._sbval19k84obscure747.AddressOf().GetValueAsAddress()
326            size = self._sbval19k84obscure747_type.GetByteSize()
327
328        content = LazyTarget.GetProcess().ReadMemory(addr, size, err)
329        if err.fail:
330            content = ''
331        return content
332
333    def _GetValueAsSigned(self):
334        if self._sbval19k84obscure747_is_ptr:
335            print("ERROR: You cannot get 'int' from pointer type %s, please use unsigned(obj) for such purposes." % str(self._sbval19k84obscure747_type))
336            raise ValueError("Cannot get signed int for pointer data.")
337        serr = lldb.SBError()
338        retval = self._sbval19k84obscure747.GetValueAsSigned(serr)
339        if serr.success:
340            return retval
341        raise ValueError("Failed to read signed data. " + str(self._sbval19k84obscure747) + "(type =" + str(self._sbval19k84obscure747_type) + ") Error description: " + serr.GetCString())
342
343    def _GetValueAsCast(self, dest_type):
344        if type(dest_type) is not lldb.SBType:
345            raise ValueError("Invalid type for dest_type: {}".format(type(dest_type)))
346        addr = self._GetValueAsUnsigned()
347        sbval = self._sbval19k84obscure747.target.CreateValueFromExpression("newname", "(void *)"+str(addr))
348        val = value(sbval.Cast(dest_type))
349        return val
350
351    def _GetValueAsUnsigned(self):
352        serr = lldb.SBError()
353        if self._sbval19k84obscure747_is_ptr:
354            retval = self._sbval19k84obscure747.GetValueAsAddress()
355        else:
356            retval = self._sbval19k84obscure747.GetValueAsUnsigned(serr)
357        if serr.success:
358            return int(retval)
359        raise ValueError("Failed to read unsigned data. " + str(self._sbval19k84obscure747) + "(type =" + str(self._sbval19k84obscure747_type) + ") Error description: " + serr.GetCString())
360
361    def _GetValueAsString(self, offset=0, maxlen=1024):
362        serr = lldb.SBError()
363        sbdata = None
364        if self._sbval19k84obscure747_is_ptr:
365            sbdata = self._sbval19k84obscure747.GetPointeeData(offset, maxlen)
366        else:
367            sbdata = self._sbval19k84obscure747.GetData()
368
369        retval = ''
370        bytesize = sbdata.GetByteSize()
371        if bytesize == 0:
372            # raise ValueError('Unable to read value as string')
373            return ''
374        for i in range(0, bytesize):
375            serr.Clear()
376            ch = chr(sbdata.GetUnsignedInt8(serr, i))
377            if serr.fail:
378                raise ValueError("Unable to read string data: " + serr.GetCString())
379            if ch == '\0':
380                break
381            retval += ch
382        return retval
383
384    def __format__(self, format_spec):
385        ret_format = "{0:"+format_spec+"}"
386        # typechar is last char. see http://www.python.org/dev/peps/pep-3101/
387        type_spec = format_spec.strip().lower()[-1]
388        if type_spec == 'x':
389            return ret_format.format(int(self))
390        if type_spec == 'd':
391            return ret_format.format(int(self))
392        if type_spec == 's':
393            return ret_format.format(str(self))
394        if type_spec == 'o':
395            return ret_format.format(int(oct(self), 8))
396        if type_spec == 'c':
397            return ret_format.format(int(self))
398
399        raise TypeError("Unsupported value format")
400
401
402def unsigned(val):
403    """ Helper function to get unsigned value from core.value
404        params: val - value (see value class above) representation of an integer type
405        returns: int which is unsigned.
406        raises : ValueError if the type cannot be represented as unsigned int.
407    """
408    if type(val) is value:
409        return int(val._GetValueAsUnsigned())
410    return int(val)
411
412
413def signed(val):
414    """ Helper function to get signed value from core.value
415        params: val - value (see value class above) representation of an integer type
416        returns: int which is signed.
417        raises: ValueError if the type cannot be represented as signed int.
418    """
419    if type(val) is value:
420        return val._sbval19k84obscure747.GetValueAsSigned()
421    return int(val)
422
423
424def sizeof(t):
425    """ Find the byte size of a type.
426        params: t - str : ex 'time_spec' returns equivalent of sizeof(time_spec) in C
427                t - value: ex a value object. returns size of the object
428        returns: int - byte size length
429    """
430    if type(t) is value:
431        return t.GetSBValue().GetByteSize()
432    if isinstance(t, six.string_types):
433        return gettype(t).GetByteSize()
434    raise ValueError("Cannot get sizeof. Invalid argument")
435
436
437def dereference(val):
438    """ Get a dereferenced obj for a pointer type obj
439        params: val - value object representing a pointer type C construct in lldb
440        returns: value - value
441        ex. val = dereference(ptr_obj) #python
442        is same as
443            obj_ptr = (int *)0x1234  #C
444            val = *obj_ptr           #C
445    """
446    if type(val) is value and val._sbval19k84obscure747_is_ptr:
447        return value(val.GetSBValue().Dereference())
448    raise TypeError('Cannot dereference this type.')
449
450
451def addressof(val):
452    """ Get address of a core.value object.
453        params: val - value object representing a C construct in lldb
454        returns: value - value object referring to 'type(val) *' type
455        ex. addr = addressof(hello_obj)  #python
456        is same as
457           uintptr_t addr = (uintptr_t)&hello_obj  #C
458    """
459    if type(val) is value:
460        return value(val.GetSBValue().AddressOf())
461    raise TypeError("Cannot do addressof for non-value type objects")
462
463
464def cast(obj, target_type):
465    """ Type cast an object to another C type.
466        params:
467            obj - core.value  object representing some C construct in lldb
468            target_type - str : ex 'char *'
469                        - lldb.SBType :
470    """
471    dest_type = target_type
472    if isinstance(target_type, six.string_types):
473        dest_type = gettype(target_type)
474    elif type(target_type) is value:
475        dest_type = target_type.GetSBValue().GetType()
476
477    if type(obj) is value:
478        return obj._GetValueAsCast(dest_type)
479    elif type(obj) is int:
480        print("ERROR: You cannot cast an 'int' to %s, please use kern.GetValueFromAddress() for such purposes." % str(target_type))
481    raise TypeError("object of type %s cannot be casted to %s" % (str(type(obj)), str(target_type)))
482
483
484def containerof(obj, target_type, field_name):
485    """ Type cast an object to another C type from a pointer to a field.
486        params:
487            obj - core.value  object representing some C construct in lldb
488            target_type - str : ex 'struct thread'
489                        - lldb.SBType :
490            field_name - the field name within the target_type obj is a pointer to
491    """
492    addr = int(obj) - getfieldoffset(target_type, field_name)
493    obj = value(obj.GetSBValue().CreateValueFromExpression(None, '(void *)' + str(addr)))
494    return cast(obj, target_type + " *")
495
496
497_value_types_cache = {}
498
499
500def gettype(target_type):
501    """ Returns lldb.SBType of the given target_type
502        params:
503            target_type - str, ex. 'char', 'uint32_t' etc
504        returns:
505            lldb.SBType - SBType corresponding to the given target_type
506        raises:
507            NameError  - Incase the type is not identified
508    """
509    global _value_types_cache
510    target_type = str(target_type).strip()
511    if target_type in _value_types_cache:
512        return _value_types_cache[target_type]
513
514    target_type = target_type.strip()
515
516    requested_type_is_struct = False
517    m = re.match(r'\s*struct\s*(.*)$', target_type)
518    if m:
519        requested_type_is_struct = True
520        target_type = m.group(1)
521
522    tmp_type = None
523    requested_type_is_pointer = False
524    if target_type.endswith('*'):
525        requested_type_is_pointer = True
526
527    # tmp_type = LazyTarget.GetTarget().FindFirstType(target_type.rstrip('*').strip())
528    search_type = target_type.rstrip('*').strip()
529    type_arr = [t for t in LazyTarget.GetTarget().FindTypes(search_type)]
530
531    if requested_type_is_struct:
532        type_arr = [t for t in type_arr if t.type == lldb.eTypeClassStruct]
533
534    # After the sort, the struct type with more fields will be at index [0].
535    # This hueristic helps selecting struct type with more fields compared to ones with "opaque" members
536    type_arr.sort(reverse=True, key=lambda x: x.GetNumberOfFields())
537    if len(type_arr) > 0:
538        tmp_type = type_arr[0]
539    else:
540        raise NameError('Unable to find type '+target_type)
541
542    if not tmp_type.IsValid():
543        raise NameError('Unable to Cast to type '+target_type)
544
545    if requested_type_is_pointer:
546        tmp_type = tmp_type.GetPointerType()
547    _value_types_cache[target_type] = tmp_type
548
549    return _value_types_cache[target_type]
550
551
552def getfieldoffset(struct_type, field_name):
553    """ Returns the byte offset of a field inside a given struct
554        Understands anonymous unions and field names in sub-structs
555        params:
556            struct_type - str or lldb.SBType, ex. 'struct ipc_port *' or port.gettype()
557            field_name  - str, name of the field inside the struct ex. 'ip_messages'
558        returns:
559            int - byte offset of the field_name inside the struct_type
560        raises:
561            TypeError  - - In case the struct_type has no field with the name field_name
562    """
563
564    if isinstance(struct_type, six.string_types):
565        struct_type = gettype(struct_type)
566
567    if '.' in field_name:
568        # Handle recursive fields in sub-structs
569        components = field_name.split('.', 1)
570        for field in struct_type.get_fields_array():
571            if str(field.GetName()) == components[0]:
572                return getfieldoffset(struct_type, components[0]) + getfieldoffset(field.GetType(), components[1])
573        raise TypeError('Field name "%s" not found in type "%s"' % (components[0], str(struct_type)))
574
575    for field in struct_type.get_fields_array():
576        if str(field.GetName()) == field_name:
577            return field.GetOffsetInBytes()
578
579        # Hack for anonymous unions - the compiler does this, so cvalue should too
580        if field.GetName() is None and field.GetType().GetTypeClass() == lldb.eTypeClassUnion:
581            for union_field in field.GetType().get_fields_array():
582                if str(union_field.GetName()) == field_name:
583                    return union_field.GetOffsetInBytes() + field.GetOffsetInBytes()
584    raise TypeError('Field name "%s" not found in type "%s"' % (field_name, str(struct_type)))
585
586
587def islong(x):
588    """ Returns True if a string represents a long integer, False otherwise
589    """
590    try:
591        int(x, 16)
592    except ValueError:
593        try:
594            int(x)
595        except ValueError:
596            return False
597    return True
598
599
600def readmemory(val):
601    """ Returns a string of hex data that is referenced by the value.
602        params: val - a value object.
603        return: str - string of hex bytes.
604        raises: TypeError if val is not a valid type
605    """
606    if not type(val) is value:
607        raise TypeError('%s is not of type value' % str(type(val)))
608    return val.__getstate__()
609
610
611def getOSPtr(cpp_obj):
612    """ Returns a core.value created from an intrusive_shared_ptr or itself, cpp_obj
613        params: cpp_obj - core.value object representing a C construct in lldb
614        return: core.value - newly created core.value or cpp_obj
615    """
616    child = cpp_obj._sbval19k84obscure747.GetChildAtIndex(0)
617    if 'intrusive_shared_ptr' in str(child):
618        return value(child.GetChildMemberWithName('ptr_'))
619    return cpp_obj
620