xref: /xnu-11417.140.69/tools/lldbmacros/core/lldbwrap.py (revision 43a90889846e00bfb5cf1d255cdc0a701a1e05a4)
1import functools
2import inspect
3import numbers
4import struct
5import sys
6
7import lldb
8
9__all__ = []
10
11UPCASTS = {}
12
13#
14# List of Quirks, once fixed, replace the booleans with an evaluation
15# of whether the lldb being used has the fix or not.
16#
17
18#
19# rdar://99785324 (GetValueAsUnsigned performs sign extension
20#                  when it REALLY shouldn't on bitfields)
21#
22QUIRK_99785324 = True
23
24#
25# rdar://99806493 (SBValue.Cast() is not doing the right thing with PAC)
26#
27QUIRK_99806493 = True
28
29#
30# rdar://100103405 (Default value for target.prefer-dynamic-value makes
31#                  macros 40x as slow when connected to Astris)
32#
33QUIRK_100103405 = True
34
35#
36# rdar://100162262 ([correctness] Multiple dereferences do not result
37#                  in the same load address in some cases depending
38#                  on whether the original value is a pointer created
39#                  with AddressOf() or not.)
40#
41QUIRK_100162262 = True
42
43#
44# rdar://102642763 (LLDB macros are unable to access member of anon struct
45#                  or union in C++ class)
46#
47QUIRK_102642763 = True
48
49#
50# rdar://104494282 (Lldb computes correct "Value As Address" but Dereference()s
51#                   wrong)
52#
53QUIRK_104494282 = True
54
55
56I8_STRUCT  = struct.Struct('b')
57I16_STRUCT = struct.Struct('h')
58I32_STRUCT = struct.Struct('i')
59I64_STRUCT = struct.Struct('q')
60
61U8_STRUCT  = struct.Struct('B')
62U16_STRUCT = struct.Struct('H')
63U32_STRUCT = struct.Struct('I')
64U64_STRUCT = struct.Struct('Q')
65
66FLT_STRUCT = struct.Struct('f')
67DBL_STRUCT = struct.Struct('d')
68
69
70def lldbwrap_raise(exn, fn, reason, *args, **kwargs):
71    """
72    Helper to form a helpful exception string for the generic lldb.SB*
73    checked wrappers
74
75    @param exn (Exception type)
76        The type of exception to raise
77
78    @param fn (Function)
79        The function that failed (approximately)
80
81    @param reason (string)
82        A reason string to append
83
84    @params *args, **kwargs
85        The arguments that have been passed to @c fn
86        in order to pretty pring them in something useful
87    """
88    args_str = []
89
90    for arg in args:
91        if isinstance(arg, lldb.SBValue):
92            args_str.append("<lldb.SBValue ({} &){:#x}>".format(
93                lldb.SBValue(arg).GetType().GetDisplayTypeName(),
94                lldb.SBValue(arg).GetLoadAddress())
95            )
96        elif isinstance(arg, lldb.SBType):
97            args_str.append("<lldb.SBType {}>".format(lldb.SBType(arg).GetDisplayTypeName()))
98        elif isinstance(arg, numbers.Integral):
99            args_str.append("{:#x}".format(arg))
100        else:
101            args_str.append(repr(arg))
102
103    if len(kwargs) > 0:
104        args_str.append("...")
105
106    if reason:
107        raise exn("{}({}) failed: {}".format(
108            fn.__name__, ", ".join(args_str), reason))
109    raise exn("{}({}) failed".format(fn.__name__, ", ".join(args_str)))
110
111
112def lldbwrap_update_class_dict(basename, basecls, attr):
113    """
114    Make the extension dictionary for our synthesized classes
115
116    This function will add wrappers around certain functions
117    that will inspect their return type, and when it is
118    of one of the @c UPCASTS ones, will monkey patch
119    the return value __class__.
120
121    It would be cleaner to invoke a "copy constructor", however
122    it has a very high cost, so this brittle monkey patching
123    is used instead.
124    """
125
126    def _make_upcast_wrapper(fn):
127        @functools.wraps(fn)
128        def wrapper(*args, **kwargs):
129            result = fn(*args, **kwargs)
130            upcast = UPCASTS.get(result.__class__)
131            if upcast: upcast(result)
132            return result
133
134        return wrapper
135
136    def _make_checked_upcast_wrapper(fn):
137        @functools.wraps(fn)
138        def wrapper(*args, **kwargs):
139            result = fn(*args, **kwargs)
140            upcast = UPCASTS.get(result.__class__)
141            if not upcast:
142                return result
143            upcast(result)
144            if result.IsValid():
145                return result
146            lldbwrap_raise(ValueError, fn, None, *args, **kwargs)
147
148        return wrapper
149
150    @classmethod
151    def xUpcast(cls, value):
152        value.__class__ = cls
153
154    #
155    # Those methods return scalars, and are very popular
156    # wrapping only makes them slow with no benefit.
157    #
158    DO_NOT_WRAP = set([
159        'GetByteSize',
160        'GetAddressByteSize',
161        'GetLoadAddress',
162        'GetName',
163        'GetOffsetInBits',
164        'GetOffsetInBytes',
165        'GetStopID',
166        'GetTypeFlags',
167        'GetUniqueID',
168        'GetValueAsAddress',
169        'GetValueAsSigned',
170        'GetValueAsUnsigned',
171        'TypeIsPointerType',
172        'IsValid',
173        'SetPreferDynamicValue'
174    ])
175
176    DO_NOT_WRAP_PREFIX = [
177        '__',           # do not wrap magic python functions
178        'Is',           # LLDB's "Is*" APIs return booleans
179        'GetNum',       # LLDB's "GetNum*" APIs return integers
180        'GetIndex',     # LLDB's "GetIndex*" APIs return integers
181    ]
182
183    for fname, value in inspect.getmembers(basecls):
184        if fname in DO_NOT_WRAP:
185            continue
186
187        elif any(fname.startswith(pfx) for pfx in DO_NOT_WRAP_PREFIX):
188            continue
189
190        elif inspect.isfunction(value) or inspect.ismethod(value):
191            attr.setdefault(fname, _make_upcast_wrapper(value))
192            attr.setdefault('chk' + fname, _make_checked_upcast_wrapper(value))
193            attr.setdefault('raw' + fname, value)
194
195        elif isinstance(value, property):
196            attr[fname] = property(_make_upcast_wrapper(value.fget), value.fset, doc=value.__doc__)
197
198    attr.setdefault('xUpcast', xUpcast)
199
200
201class LLDBWrapMetaclass(type):
202    """ Metaclass used for manual definitions of lldb.SB* subclasses """
203
204    def __new__(cls, name, bases, attr):
205        lldbwrap_update_class_dict(name, bases[0], attr)
206        return type.__new__(cls, name, bases, attr)
207
208
209class SBProcess(lldb.SBProcess, metaclass=LLDBWrapMetaclass):
210
211    #
212    # Manually written checked wrappers
213    #
214
215    @functools.wraps(lldb.SBProcess.ReadMemory)
216    def chkReadMemory(self, addr, size):
217        err = lldb.SBError()
218        res = self.ReadMemory(addr, size, err)
219        if err.Success():
220            return res
221        lldbwrap_raise(IOError, self.ReadMemory, err.GetCString(),
222            self, addr, size)
223
224    @functools.wraps(lldb.SBProcess.WriteMemory)
225    def chkWriteMemory(self, addr, buf):
226        err = lldb.SBError()
227        res = self.WriteMemory(addr, buf, err)
228        if err.Success():
229            return res
230        lldbwrap_raise(IOError, self.WriteMemory, err.GetCString(),
231            self, addr, buf)
232
233    @functools.wraps(lldb.SBProcess.ReadCStringFromMemory)
234    def chkReadCStringFromMemory(self, addr, max_size):
235        err = lldb.SBError()
236        res = self.ReadCStringFromMemory(addr, max_size, err)
237        if err.Success():
238            return res
239        lldbwrap_raise(IOError, self.ReadCStringFromMemory, err.GetCString(),
240            self, addr, max_size)
241
242    @functools.wraps(lldb.SBProcess.ReadUnsignedFromMemory)
243    def chkReadUnsignedFromMemory(self, addr, byte_size):
244        err = lldb.SBError()
245        res = self.ReadUnsignedFromMemory(addr, byte_size, err)
246        if err.Success():
247            return res
248        lldbwrap_raise(IOError, self.ReadUnsignedFromMemory, err.GetCString(),
249            self, addr, byte_size)
250
251    @functools.wraps(lldb.SBProcess.ReadPointerFromMemory)
252    def chkReadPointerFromMemory(self, addr):
253        err = lldb.SBError()
254        res = self.ReadPointerFromMemory(addr, err)
255        if err.Success():
256            return res
257        lldbwrap_raise(IOError, self.ReadPointerFromMemory, err.GetCString(),
258            self, addr)
259
260
261class SBTarget(lldb.SBTarget, metaclass=LLDBWrapMetaclass):
262
263    #
264    # Manually written checked wrappers
265    #
266
267    @functools.wraps(lldb.SBTarget.ReadMemory)
268    def chkReadMemory(self, addr, buf):
269        err = lldb.SBError()
270        res = self.ReadMemory(addr, buf, err)
271        if err.Success():
272            return res
273        lldbwrap_raise(IOError, self.ReadMemory, err.GetCString(),
274            self, addr, buf)
275
276
277    #
278    # Extensions
279    #
280
281    def xReadBytes(self, addr, size):
282        """
283        Reads memory from the current process's address space and removes any
284        traps that may have been inserted into the memory.
285
286        @param addr (int)
287            The address to start reading at
288
289        @param size (int)
290            The size of the read to perform
291
292        @returns (bytes)
293        """
294        return bytes(self.GetProcess().chkReadMemory(addr, size))
295
296    def xReadCString(self, addr, max_size):
297        """
298        Reads a NULL terminated C string from the current process's address space.
299        It returns a python string of the exact length, or truncates the string if
300        the maximum character limit is reached. Example: ::
301
302        @param addr (int)
303            The address to start reading at
304
305        @param max_size (int)
306            The maximum size of the string
307
308        @returns (str)
309        """
310
311        return self.GetProcess().chkReadCStringFromMemory(addr, max_size)
312
313    def xReadInt8(self, addr):
314        """ Conveniency wrapper to read an int8_t at the specified address """
315        return int(I8_STRUCT.unpack(self.xReadBytes(addr, 1))[0])
316
317    def xReadInt16(self, addr):
318        """ Conveniency wrapper to read an int16_t at the specified address """
319        return int(I16_STRUCT.unpack(self.xReadBytes(addr, 2))[0])
320
321    def xReadInt32(self, addr):
322        """ Conveniency wrapper to read an int32_t at the specified address """
323        return int(I32_STRUCT.unpack(self.xReadBytes(addr, 4))[0])
324
325    def xReadInt64(self, addr):
326        """ Conveniency wrapper to read an int64_t at the specified address """
327        return int(I64_STRUCT.unpack(self.xReadBytes(addr, 8))[0])
328
329    def xReadUInt8(self, addr):
330        """ Conveniency wrapper to read an uint8_t at the specified address """
331        return int(U8_STRUCT.unpack(self.xReadBytes(addr, 1))[0])
332
333    def xReadUInt16(self, addr):
334        """ Conveniency wrapper to read an uint16_t at the specified address """
335        return int(U16_STRUCT.unpack(self.xReadBytes(addr, 2))[0])
336
337    def xReadUInt32(self, addr):
338        """ Conveniency wrapper to read an uint32_t at the specified address """
339        return int(U32_STRUCT.unpack(self.xReadBytes(addr, 4))[0])
340
341    def xReadUInt64(self, addr):
342        """ Conveniency wrapper to read an uint64_t at the specified address """
343        return int(U64_STRUCT.unpack(self.xReadBytes(addr, 8))[0])
344
345    def xReadLong(self, addr):
346        """ Conveniency wrapper to read a long at the specified address """
347        if self.GetProcess().GetAddressByteSize() == 8:
348            return int(I64_STRUCT.unpack(self.xReadBytes(addr, 8))[0])
349        return int(I32_STRUCT.unpack(self.xReadBytes(addr, 4))[0])
350
351    def xReadULong(self, addr):
352        """ Conveniency wrapper to read a long at the specified address """
353        if self.GetProcess().GetAddressByteSize() == 8:
354            return int(U64_STRUCT.unpack(self.xReadBytes(addr, 8))[0])
355        return int(U32_STRUCT.unpack(self.xReadBytes(addr, 4))[0])
356
357    def xReadFloat(self, addr):
358        """ Conveniency wrapper to read a float at the specified address """
359        return FLT_STRUCT.unpack(self.xReadBytes(addr, 4))[0]
360
361    def xReadDouble(self, addr):
362        """ Conveniency wrapper to read a double at the specified address """
363        return DBL_STRUCT.unpack(self.xReadBytes(addr, 8))[0]
364
365
366    def xIterAsStruct(self, spec, addr, count):
367        """
368        Iterate the memory as defined by the specified struct spec
369
370        @param spec (struct.Struct)
371            A struct unpack spec
372
373        @param addr (int)
374            The address to start ieterating from
375
376        @param count (int)
377            The number of structs to read
378        """
379
380        if not count:
381            return ()
382
383        size = spec.size
384        data = self.xReadBytes(addr, count * size)
385        if hasattr(spec, 'iter_unpack'):
386            return spec.iter_unpack(data)
387
388        # Python 2
389        return (
390            spec.unpack(data[i : i + size])
391            for i in range(0, count * size, size)
392        )
393
394
395    def xIterAsScalar(self, spec, addr, count):
396        """
397        Iterate the memory as defined by the specified scalar spec
398
399        Unlike xIterAsStruct() this will return the first element
400        of the struct.Strict.iter_unpack() tuple.
401
402        @param spec (struct.Struct)
403            A struct unpack spec
404
405        @param addr (int)
406            The address to start ieterating from
407
408        @param count (int)
409            The number of scalars to read
410        """
411
412        if not count:
413            return ()
414
415        size = spec.size
416        data = self.xReadBytes(addr, count * size)
417        if hasattr(spec, 'iter_unpack'):
418            return (e[0] for e in spec.iter_unpack(data))
419
420        # Python 2
421        return (
422            int(spec.unpack(data[i : i + size])[0])
423            for i in range(0, count * size, size)
424        )
425
426    def xStripPtr(self, sbvalue):
427        """ Strips top bits in a pointer value """
428
429        if strip := getattr(self, '_strip_ptr', None):
430            return strip(sbvalue)
431
432        is_tagged = False
433        # is_tagged = self.FindFirstGlobalVariable('kasan_tbi_enabled').IsValid()
434
435        def stripPtr(sbvalue: lldb.SBValue):
436            if sbvalue.GetValueAsAddress() != sbvalue.GetValueAsUnsigned():
437                addr = sbvalue.GetValueAsAddress()
438                sbv_new = sbvalue.CreateValueFromExpression(None, '(void *)' + str(addr))
439                return sbv_new.Cast(sbvalue.GetType())
440
441            return sbvalue
442
443        if is_tagged:
444            strip = lambda sbv: stripPtr(sbv)
445        else:
446            strip = lambda sbv : sbv
447
448        self._strip_ptr = strip
449        return strip(sbvalue)
450
451    def xIterAsInt8(self, addr, count):
452        """ Conveniency wrapper to xIterAsScalar() on int8_t """
453        return self.xIterAsScalar(I8_STRUCT, addr, count)
454
455    def xIterAsInt16(self, addr, count):
456        """ Conveniency wrapper to xIterAsScalar() on int16_t """
457        return self.xIterAsScalar(I16_STRUCT, addr, count)
458
459    def xIterAsInt32(self, addr, count):
460        """ Conveniency wrapper to xIterAsScalar() on int32_t """
461        return self.xIterAsScalar(I32_STRUCT, addr, count)
462
463    def xIterAsInt64(self, addr, count):
464        """ Conveniency wrapper to xIterAsScalar() on int64_t """
465        return self.xIterAsScalar(I64_STRUCT, addr, count)
466
467    def xIterAsUInt8(self, addr, count):
468        """ Conveniency wrapper to xIterAsScalar() on uint8_t """
469        return self.xIterAsScalar(U8_STRUCT, addr, count)
470
471    def xIterAsUInt16(self, addr, count):
472        """ Conveniency wrapper to xIterAsScalar() on uint16_t """
473        return self.xIterAsScalar(U16_STRUCT, addr, count)
474
475    def xIterAsUInt32(self, addr, count):
476        """ Conveniency wrapper to xIterAsScalar() on uint32_t """
477        return self.xIterAsScalar(U32_STRUCT, addr, count)
478
479    def xIterAsUInt64(self, addr, count):
480        """ Conveniency wrapper to xIterAsScalar() on uint64_t """
481        return self.xIterAsScalar(U64_STRUCT, addr, count)
482
483    def xIterAsLong(self, addr, count):
484        """ Conveniency wrapper to xIterAsScalar() on long """
485        if self.GetProcess().GetAddressByteSize() == 8:
486            return self.xIterAsScalar(I64_STRUCT, addr, count)
487        return self.xIterAsScalar(I32_STRUCT, addr, count)
488
489    def xIterAsULong(self, addr, count):
490        """ Conveniency wrapper to xIterAsScalar() on unsigned long """
491        if self.GetProcess().GetAddressByteSize() == 8:
492            return self.xIterAsScalar(U64_STRUCT, addr, count)
493        return self.xIterAsScalar(U32_STRUCT, addr, count)
494
495    def xIterAsFloat(self, addr, count):
496        """ Conveniency wrapper to xIterAsScalar() on float """
497        return self.xIterAsScalar(FLT_STRUCT, addr, count)
498
499    def xIterAsDouble(self, addr, count):
500        """ Conveniency wrapper to xIterAsScalar() on double """
501        return self.xIterAsScalar(DBL_STRUCT, addr, count)
502
503
504    def xCreateValueFromAddress(self, name, addr, ty):
505        """
506        Create an SBValue with the given name by treating the memory starting
507        at addr as an entity of type.
508
509        More tolerant wrapper around CreateValueFromAddress() that accepts
510        for @c name to be None and @c addr to be an int.
511
512        @param name (str or None)
513            The name of the resultant SBValue
514
515        @param addr (int or lldb.SBAddress)
516            The address of the start of the memory region to be used.
517
518        @param ty (lldb.SBType)
519            The type to use to interpret the memory starting at addr.
520
521        @return (lldb.SBValue)
522            An SBValue of the given type.
523
524        @raises ValueError
525            For various error conditions.
526        """
527
528        if not isinstance(addr, lldb.SBAddress):
529            addr = self.rawResolveLoadAddress(addr)
530
531        if name is None:
532            # unlike SBValue's variant, SBTargets's will fail to produce
533            # a value if the name is None, don't ask.
534            name = 'newvalue'
535
536        v = self.CreateValueFromAddress(name, addr, ty)
537        if v.IsValid():
538            if QUIRK_100103405 and not addr:
539                v.SetPreferDynamicValue(0)
540            return v
541
542        lldbwrap_raise(ValueError, self.CreateValueFromAddress, None, name)
543
544
545class SBType(lldb.SBType, metaclass=LLDBWrapMetaclass):
546
547    #
548    # Extensions
549    #
550
551    def _findFieldOffsetByName(self, name):
552        """ internal helper """
553
554        for idx in range(self.GetNumberOfFields()):
555            field = self.GetFieldAtIndex(idx)
556            fname = field.GetName()
557
558            if fname == name:
559                return field.GetOffsetInBytes(), field.GetType()
560
561            if fname is None:
562                offs, ty = field.GetType()._findFieldOffsetByName(name)
563                if offs is not None:
564                    return offs + field.GetOffsetInBytes(), ty
565
566        return None, None
567
568    def _findFieldOffsetByPath(self, path):
569        """ internal helper """
570
571        offs = 0
572        ty   = self
573
574        key = path[1:] if path[0] == '.' else path
575
576        while key != '':
577            name, _, key = key.partition('.')
578            index = None
579
580            if name[-1] == ']':
581                name, _, index = name[:-1].partition('[')
582                if not index.isdigit():
583                    raise KeyError("Invalid path '{}'".format(path))
584                index = int(index)
585
586            f_offs, ty = ty._findFieldOffsetByName(name)
587            if f_offs is None:
588                return None, None, None
589
590            offs += f_offs
591            if index is not None:
592                if ty.GetTypeFlags() & lldb.eTypeIsArray:
593                    ty = ty.GetArrayElementType()
594                else:
595                    ty = ty.GetPointeeType()
596                offs += ty.GetByteSize() * index
597
598        return offs, ty, name
599
600    def xGetFieldOffset(self, path_or_name):
601        """
602        Returns offsetof(type, path_or_name) in bytes.
603
604        @param path_or_name (str)
605            The field path or name to compute the offset of
606
607        @return (int or None)
608            The requested offset of the field within the type,
609            or None if the field wasn't found
610        """
611        return self._findFieldOffsetByPath(path_or_name)[0]
612
613    def xContainerOfTransform(self, path):
614        """
615        Returns a function that can be used to apply a "__container_of"
616        transformation repeatedly (by field path).
617
618        @param path_or_name (str)
619            The field path or name to compute the offset of
620
621        @returns (function)
622            A function that returns the value resulting of
623            __container_of(value, type_t, path) for this type.
624        """
625
626        offs = self.xGetFieldOffset(path)
627
628        return lambda x: x.xCreateValueFromAddress(None, x.GetLoadAddress() - offs, self)
629
630    def xContainerOf(self, path_or_name, value):
631        """ same as self.xContainerOfTransform(path_or_name)(value) """
632
633        return self.xContainerOfTransform(path_or_name)(value)
634
635
636class SBValue(lldb.SBValue, metaclass=LLDBWrapMetaclass):
637
638    if QUIRK_100103405:
639        @classmethod
640        def xUpcast(cls, value):
641            #
642            # LLDB insists on trying to translate "NULL" for `void *`
643            # when dynamic values are enabled. It never caches the
644            # negative result which can yield really slow performance.
645            #
646            # Work it around by disabling dynamic values, looking at whether
647            # it's vaguely looking like a pointer and its value is a NULL
648            # pointer, and if not, turn dynamic values back on
649            #
650            # This check is extremely expensive and makes shorcuts,
651            # such as testing against "8" (sizeof(void *) on LP64)
652            # in order to delay realizing the type as much as possible
653            #
654            dyn = value.GetPreferDynamicValue()
655            if dyn:
656                value.SetPreferDynamicValue(0)
657                if (value.GetByteSize() != 8 or
658                        value.GetValueAsUnsigned() or
659                        not value.TypeIsPointerType()):
660                    value.SetPreferDynamicValue(dyn)
661
662            value.__class__ = cls
663
664    #
665    # Manually written checked wrappers
666    #
667
668    @functools.wraps(lldb.SBValue.GetValueAsSigned)
669    def chkGetValueAsSigned(self):
670        err = lldb.SBError()
671        res = self.GetValueAsSigned(err)
672        if res or err.Success():
673            return res
674        lldbwrap_raise(ValueError, self.chkGetValueAsSigned, err.GetCString(),
675            self)
676
677    @functools.wraps(lldb.SBValue.GetValueAsUnsigned)
678    def chkGetValueAsUnsigned(self):
679        err = lldb.SBError()
680        res = self.GetValueAsUnsigned(err)
681        if res or err.Success():
682            return res
683        lldbwrap_raise(ValueError, self.chkGetValueAsUnsigned, err.GetCString(),
684            self)
685
686    @functools.wraps(lldb.SBValue.SetValueFromCString)
687    def chkSetValueFromCString(self, value_str):
688        err = lldb.SBError()
689        if not self.SetValueFromCString(value_str, err):
690            lldbwrap_raise(ValueError, self.chkSetValueFromCString, err.GetCString(),
691                self, value_str)
692
693    @functools.wraps(lldb.SBValue.SetData)
694    def chkSetData(self, data):
695        err = lldb.SBError()
696        if not self.SetData(data, err):
697            lldbwrap_raise(ValueError, self.chkSetData, err.GetCString(),
698                self, data)
699
700    if QUIRK_99806493:
701        def Cast(self, ty):
702            v = super().Cast(ty)
703            SBValue.xUpcast(v)
704
705            if not v.IsValid() or not v.TypeIsPointerType():
706                return v
707
708            #
709            # NULL is fine, needs no PAC stripping,
710            # and it makes CreateValueFromAddress behave funny.
711            #
712            addr = v.GetValueAsAddress()
713            if addr == 0:
714                return v
715
716            #
717            # Casting from a pointer type to another
718            # is not stripping __ptrauth, let's fix it
719            #
720            nv = v.rawCreateValueFromAddress(v.GetName(), addr, ty)
721            nv.SetPreferDynamicValue(v.GetPreferDynamicValue())
722            v = nv.AddressOf().Cast(ty)
723
724            if QUIRK_100162262:
725                nv = v.Persist()
726                nv.SetPreferDynamicValue(v.GetPreferDynamicValue())
727                v = nv
728
729            # no need for QUIRK_100103405, can't be NULL
730            v.__class__ = SBValue
731            return v
732
733        def chkCast(self, ty):
734            v = self.Cast(ty)
735            if v.IsValid():
736                return v
737
738            lldbwrap_raise(ValueError, SBValue.Cast, None, self, ty)
739
740    if QUIRK_100162262:
741        def AddressOf(self):
742            v = super().AddressOf().Persist()
743            # no need for QUIRK_100103405
744            v.__class__ = SBValue
745            return v
746
747        def chkAddressOf(self):
748            v = self.AddressOf()
749            if v.IsValid():
750                return v
751
752            lldbwrap_raise(ValueError, SBValue.AddressOf, None, self)
753
754    if QUIRK_104494282:
755        def Dereference(self):
756            addr = self.GetValueAsAddress()
757            if addr == self.GetValueAsUnsigned():
758                v = super().Dereference()
759                SBValue.xUpcast(v)
760                return v
761
762            return self.xCreateValueFromAddress(self.GetName(),
763                addr, self.GetType().GetPointeeType())
764
765    if QUIRK_102642763:
766        def GetChildMemberWithName(self, name):
767            v = self.rawGetChildMemberWithName(name)
768            SBValue.xUpcast(v)
769            if v.IsValid():
770                return v
771
772            # Emulate compiler logic and visit all nested anon struct/unions.
773            if self.GetType().IsPointerType():
774                return self.xDereference().GetChildMemberWithName(name)
775
776            offs, mty = self.GetType()._findFieldOffsetByName(name)
777            if offs is None:
778                # LLDB returns instance of SBValue that is set as invalid.
779                # Re-use the invalid one from initial lookup.
780                return v
781
782            return self.xCreateValueFromAddress(name, self.GetLoadAddress() + offs, mty)
783
784        def GetValueForExpressionPath(self, path):
785            v = self.rawGetValueForExpressionPath(path)
786            SBValue.xUpcast(v)
787            if v.IsValid():
788                return v
789
790            # Emulate compiler logic and visit all nested anon struct/unions.
791            if self.GetType().IsPointerType():
792                return self.xDereference().GetValueForExpressionPath(path)
793
794            # Emulate compiler logic and visit all nested anon struct/unions.
795            offs, mty, name = self.GetType()._findFieldOffsetByPath(path)
796            if offs is None:
797                # LLDB returns instance of SBValue that is set as invalid.
798                # Re-use the invalid one from initial lookup.
799                return v
800
801            return self.xCreateValueFromAddress(name, self.GetLoadAddress() + offs, mty)
802
803
804    def IsValid(self):
805        """
806        SBValue.IsValid() is necessary but not sufficient to check an SBValue is in a valid state.
807
808        'IsValid means this is an SBValue with something in it that wasn't an obvious error, something you might ask questions of.
809        In particular, it's something you can ask GetError().Success() which is the real way to tell if you have an SBValue you should be using.'
810
811        For XNU macros, we always care about whether we have an SBValue we can use - so we overload IsValid() for convenience
812        """
813        return super().IsValid() and self.error.success
814
815    #
816    # Extensions
817    #
818
819    def xCreateValueFromAddress(self, name, addr, ty):
820        """
821        Create an SBValue with the given name by treating the memory starting
822        at addr as an entity of type.
823
824        More tolerant wrapper around CreateValueFromAddress() that accepts
825        for @c name to be None and @c addr to be an lldb.SBAddress
826
827        @param name (str or None)
828            The name of the resultant SBValue
829
830        @param addr (int or lldb.SBAddress)
831            The address of the start of the memory region to be used.
832
833        @param ty (lldb.SBType)
834            The type to use to interpret the memory starting at addr.
835
836        @return (lldb.SBValue)
837            An SBValue of the given type.
838
839        @raises ValueError
840            For various error conditions.
841        """
842
843        if isinstance(addr, lldb.SBAddress):
844            addr = addr.GetLoadAddress()
845
846        if name is None:
847            # SBValue's version of CreateValueFromAddress() accepts None,
848            # but let's be consistent.
849            name = 'newvalue'
850
851        return self.chkCreateValueFromAddress(name, addr, ty)
852
853    def xGetSiblingValueAtIndex(self, index, stride=None):
854        """
855        Returns a sibling value to the current one in an array.
856
857        This basically performs pointer arithmetics on the SBValue.
858
859        @param index (int)
860            The index of the element to return relative to the current one.
861
862        @param stride (int or None):
863            If specified, use this stride instead of the natural value type size.
864
865        @returns (lldb.SBValue)
866            The resulting value.
867        """
868
869        if index:
870            addr = self.GetLoadAddress() + index * (stride or self.GetByteSize())
871            return self.chkCreateValueFromAddress(self.GetName(), addr, self.GetType())
872        return self
873
874    def xIterSiblings(self, start, stop, step=1):
875        """
876        Returns an iterator for sibling value to the current one in an array.
877
878        This basically performs pointer arithmetics on the SBValue.
879
880        @param start (int)
881            The first index (inclusive) to return
882
883        @param stop (int)
884            The last index (exclusive) to return
885
886        @param step (int or None):
887            The increment step if any
888
889        @returns (lldb.SBValue)
890            The resulting value.
891        """
892
893        size = self.GetByteSize()
894        ty   = self.GetType()
895        base = self.GetLoadAddress()
896
897        # aggressively cache the data
898        self.target.xReadBytes(base + start * size, (stop - start) * size)
899
900        return (
901            self.chkCreateValueFromAddress(None, base + i * size, ty)
902            for i in range(start, stop, step)
903        )
904
905    def xDereference(self):
906        """
907        Version of Dereference() that does the right thing for flexible arrays,
908        and returns None if NULL is being dereferenced.
909
910        @returns (lldb.SBValue):
911            - a reference to value[0] if value is a valid pointer/array
912            - None otherwise
913        """
914
915        rawty = self.rawGetType()
916        fl    = rawty.GetTypeFlags()
917
918        if fl & lldb.eTypeIsArray:
919            return self.xCreateValueFromAddress(self.GetName(),
920                self.GetLoadAddress(), rawty.GetArrayElementType())
921
922        if fl & lldb.eTypeIsPointer:
923            sbv_new = self.GetTarget().xStripPtr(self)
924            return sbv_new.chkDereference() if self.GetValueAsAddress() else None
925
926        lldbwrap_raise(TypeError, self.xDereference, "Type can't be dereferenced")
927
928
929    def xGetValueAsScalar(self, needed=0, rejected=0):
930        """
931        Get the scalar value of an SBValue
932
933        @param needed (lldb.eTypeIs* mask)
934            Sets of flags that should be set or the conversion should fail.
935
936        @param rejected (lldb.eTypeIs* mask)
937            Sets of flags that should fail the conversion if set on the value.
938        """
939
940        flags = self.rawGetType().GetTypeFlags()
941
942        if (flags & needed) != needed:
943            lldbwrap_raise(ValueError, self.xGetValueAsScalar,
944                "value of type {} has missing flags {:#x}".format(
945                self.GetType().GetDisplayTypeName(), (flags & needed) ^ needed),
946                self, needed=needed, rejected=rejected)
947
948        if flags & rejected:
949            lldbwrap_raise(ValueError, self.xGetValueAsScalar,
950                "value of type {} has rejected flags {:#x}".format(
951                self.GetType().GetDisplayTypeName(), flags & rejected),
952                self, needed=needed, rejected=rejected)
953
954        if flags & lldb.eTypeIsPointer:
955            return self.GetValueAsAddress()
956
957        err = lldb.SBError()
958        if flags & lldb.eTypeIsSigned:
959            res = self.GetValueAsSigned(err)
960        else:
961            res = self.GetValueAsUnsigned(err)
962            if QUIRK_99785324 and res and flags & lldb.eTypeIsEnumeration:
963                try:
964                    addr_of = self.rawAddressOf()
965                    if (res >> (self.GetByteSize() * 8 - 1) and
966                            not (addr_of.IsValid() and addr_of.error.success)):
967                        #
968                        # This field is:
969                        # - likely a bitfield (we can't take its AddressOf())
970                        # - unsigned
971                        # - with its top bit set
972                        #
973                        # This might be hitting rdar://99785324 where lldb
974                        # incorrectly sign-extends unsigned bit-fields.
975                        #
976                        # Here comes a crime against good taste: the expression
977                        # evaluator of lldb _knows_ how to do the right thing,
978                        # and now that the only thing we have is this lousy
979                        # lldb.SBValue(), we can only get to it via __str__().
980                        #
981                        # We parse something like this here:
982                        #   '(type_t:12) path = 42'
983                        #
984                        str_value = str(self)
985                        res = int(str_value[str_value.rfind(' '):], 0)
986                except:
987                    pass
988
989        if res or err.Success():
990            return res
991
992        lldbwrap_raise(ValueError, self.xGetValueAsScalar, err.GetCString(),
993            self, needed=needed, rejected=rejected)
994
995
996    def xGetValueAsInteger(self):
997        """
998        Get the integer value of an SBValue (fails for floats or complex)
999        """
1000
1001        mask = lldb.eTypeIsFloat | lldb.eTypeIsComplex
1002        return self.xGetValueAsScalar(rejected=mask)
1003
1004
1005    def xGetValueAsCString(self, max_len=1024):
1006        """
1007        Gets the cstring value of an SBValue.
1008
1009        @param max_len (int)
1010            The maximum lenght expected for that string
1011
1012        @returns (str)
1013            A string holding the contents of the value.
1014
1015        @raises TypeError
1016            If the value can't be converted to a string
1017        """
1018
1019        if not self.IsValid():
1020            lldbwrap_raise(ValueError, self.xGetValueAsCString, "Value is invalid", self)
1021
1022        return self.target.GetProcess().chkReadCStringFromMemory(self.GetValueAsAddress(), max_len)
1023
1024
1025    def xGetScalarByName(self, name):
1026        """ same as chkGetChildMemberWithName(name).xGetValueAsScalar() """
1027
1028        v = self.rawGetChildMemberWithName(name)
1029        SBValue.xUpcast(v)
1030        if v.IsValid():
1031            if QUIRK_100103405:
1032                v.SetPreferDynamicValue(0)
1033            return v.xGetValueAsScalar()
1034
1035        lldbwrap_raise(ValueError, self.GetChildMemberWithName, None, name)
1036
1037    def xGetScalarAtIndex(self, index):
1038        """ same as chkGetChildAtIndex(index).xGetValueAsScalar() """
1039
1040        v = self.GetChildAtIndex(index)
1041        if v.IsValid():
1042            if QUIRK_100103405:
1043                v.SetPreferDynamicValue(0)
1044            return v.xGetValueAsScalar()
1045
1046        lldbwrap_raise(ValueError, self.GetChildAtIndex, None, index)
1047
1048    def xGetScalarByPath(self, path):
1049        """ same as chkGetValueForExpressionPath(path).xGetValueAsScalar() """
1050
1051        v = self.rawGetValueForExpressionPath(path)
1052        SBValue.xUpcast(v)
1053        if v.IsValid():
1054            if QUIRK_100103405:
1055                v.SetPreferDynamicValue(0)
1056            return v.xGetValueAsScalar()
1057
1058        lldbwrap_raise(ValueError, self.GetValueForExpressionPath, None, path)
1059
1060
1061    def xGetIntegerByName(self, name):
1062        """ same as chkGetChildMemberWithName(name).xGetValueAsInteger() """
1063
1064        v = self.rawGetChildMemberWithName(name)
1065        SBValue.xUpcast(v)
1066        if v.IsValid():
1067            if QUIRK_100103405:
1068                v.SetPreferDynamicValue(0)
1069            return v.xGetValueAsInteger()
1070
1071        lldbwrap_raise(ValueError, self.GetChildMemberWithName, None, name)
1072
1073    def xGetIntegerAtIndex(self, index):
1074        """ same as chkGetChildAtIndex(index).xGetValueAsInteger() """
1075
1076        v = self.GetChildAtIndex(index)
1077        if v.IsValid():
1078            if QUIRK_100103405:
1079                v.SetPreferDynamicValue(0)
1080            return v.xGetValueAsInteger()
1081
1082        lldbwrap_raise(ValueError, self.GetChildAtIndex, None, index)
1083
1084    def xGetIntegerByPath(self, path):
1085        """ same as chkGetValueForExpressionPath(path).xGetValueAsInteger() """
1086
1087        v = self.rawGetValueForExpressionPath(path)
1088        SBValue.xUpcast(v)
1089        if v.IsValid():
1090            if QUIRK_100103405:
1091                v.SetPreferDynamicValue(0)
1092            return v.xGetValueAsInteger()
1093
1094        lldbwrap_raise(ValueError, self.GetValueForExpressionPath, None, path)
1095
1096
1097    def xGetPointeeByName(self, name):
1098        """ same as chkGetChildMemberWithName(name).xDereference() """
1099
1100        v = self.rawGetChildMemberWithName(name)
1101        SBValue.xUpcast(v)
1102        if v.IsValid():
1103            return v.xDereference()
1104
1105        lldbwrap_raise(ValueError, self.GetChildMemberWithName, None, name)
1106
1107    def xGetPointeeAtIndex(self, index):
1108        """ same as chkGetChildAtIndex(index).xDereference() """
1109
1110        v = self.GetChildAtIndex(index)
1111        if v.IsValid():
1112            return v.xDereference()
1113
1114        lldbwrap_raise(ValueError, self.GetChildAtIndex, None, index)
1115
1116    def xGetPointeeByPath(self, path):
1117        """ same as chkGetValueForExpressionPath(path).xDereference() """
1118
1119        v = self.rawGetValueForExpressionPath(path)
1120        SBValue.xUpcast(v)
1121        if v.IsValid():
1122            return v.xDereference()
1123
1124        lldbwrap_raise(ValueError, self.GetValueForExpressionPath, None, path)
1125
1126
1127    def xGetLoadAddressByName(self, name):
1128        """ same as chkGetChildMemberWithName(name).GetLoadAddress() """
1129
1130        v = self.rawGetChildMemberWithName(name)
1131        SBValue.xUpcast(v)
1132        if v.IsValid():
1133            if QUIRK_100103405:
1134                v.SetPreferDynamicValue(0)
1135            return v.GetLoadAddress()
1136
1137        lldbwrap_raise(ValueError, self.GetChildMemberWithName, None, name)
1138
1139    def xGetLoadAddressAtIndex(self, index):
1140        """ same as chkGetChildAtIndex(index).GetLoadAddress() """
1141
1142        v = self.GetChildAtIndex(index)
1143        if v.IsValid():
1144            if QUIRK_100103405:
1145                v.SetPreferDynamicValue(0)
1146            return v.GetLoadAddress()
1147
1148        lldbwrap_raise(ValueError, self.GetChildAtIndex, None, index)
1149
1150    def xGetLoadAddressByPath(self, path):
1151        """ same as chkGetValueForExpressionPath(path).GetLoadAddress() """
1152
1153        v = self.rawGetValueForExpressionPath(path)
1154        SBValue.xUpcast(v)
1155        if v.IsValid():
1156            if QUIRK_100103405:
1157                v.SetPreferDynamicValue(0)
1158            return v.GetLoadAddress()
1159
1160        lldbwrap_raise(ValueError, self.GetValueForExpressionPath, None, path)
1161
1162
1163    def xGetCStringByName(self, name, *args):
1164        """ same as chkGetChildMemberWithName(name).xGetValueAsCString() """
1165
1166        v = self.rawGetChildMemberWithName(name)
1167        SBValue.xUpcast(v)
1168        if v.IsValid():
1169            if QUIRK_100103405:
1170                v.SetPreferDynamicValue(0)
1171            return v.xGetValueAsCString(*args)
1172
1173        lldbwrap_raise(ValueError, self.GetChildMemberWithName, None, name)
1174
1175    def xGetCStringAtIndex(self, index, *args):
1176        """ same as chkGetChildAtIndex(index).xGetValueAsCString() """
1177
1178        v = self.GetChildAtIndex(index)
1179        if v.IsValid():
1180            if QUIRK_100103405:
1181                v.SetPreferDynamicValue(0)
1182            return v.xGetValueAsCString(*args)
1183
1184        lldbwrap_raise(ValueError, self.GetChildAtIndex, None, index)
1185
1186    def xGetCStringByPath(self, path, *args):
1187        """ same as chkGetValueForExpressionPath(path).xGetValueAsCString() """
1188
1189        v = self.rawGetValueForExpressionPath(path)
1190        SBValue.xUpcast(v)
1191        if v.IsValid():
1192            if QUIRK_100103405:
1193                v.SetPreferDynamicValue(0)
1194            return v.xGetValueAsCString(*args)
1195
1196        lldbwrap_raise(ValueError, self.GetValueForExpressionPath, None, path)
1197
1198
1199def GetDebugger():
1200    """ Alternative to lldb.debugger since we can't hook globals """
1201    return SBDebugger(lldb.debugger)
1202
1203def GetTarget():
1204    """
1205    Alternative to lldb.target
1206
1207    Using lldb.target has several issues because it is set late by lldb,
1208    and might resolve to None even when there is a selected target already.
1209    """
1210
1211    return GetDebugger().GetSelectedTarget()
1212
1213def GetProcess():
1214    """
1215    Alternative to lldb.process
1216
1217    Using lldb.process has several issues because it is set late by lldb,
1218    and might resolve to None even when there is a selected target already.
1219    """
1220    return GetTarget().GetProcess()
1221
1222__all__.extend((
1223    GetDebugger.__name__,
1224    GetProcess.__name__,
1225    GetTarget.__name__,
1226))
1227
1228
1229################################################################################
1230#
1231# Code to generate the module content by replicating `lldb`
1232#
1233
1234def lldbwrap_generate(this_module):
1235    sb_classes = (
1236       m
1237       for m in inspect.getmembers(lldb, inspect.isclass)
1238       if m[0][:2] == "SB"
1239    )
1240
1241    for name, base in sb_classes:
1242        cls = getattr(this_module, name, None)
1243        if not hasattr(this_module, name):
1244            attr = {}
1245            lldbwrap_update_class_dict(name, base, attr)
1246            cls = type(name, (base,), attr)
1247            setattr(this_module, name, cls)
1248
1249        UPCASTS[base] = cls.xUpcast
1250        __all__.append(name)
1251
1252    #
1253    # Re-export globals
1254    #
1255
1256    for name, value in inspect.getmembers(lldb):
1257
1258        if name.startswith("LLDB_"):
1259            setattr(this_module, name, value)
1260            __all__.append(name)
1261            continue
1262
1263        if name[0] == 'e' and name[1].isupper():
1264            setattr(this_module, name, value)
1265            __all__.append(name)
1266            continue
1267
1268lldbwrap_generate(sys.modules[__name__])
1269