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