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