xref: /xnu-11215/tools/lldbmacros/core/lldbwrap.py (revision 8d741a5d)
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 = self.FindFirstGlobalVariable('kasan_tbi_enabled').GetValueAsUnsigned()
433
434        if is_tagged:
435            strip = lambda sbv: self.xCreateValueFromAddress(sbv.GetName(), sbv.GetValueAsAddress(), sbv.GetType())
436        else:
437            strip = lambda sbv : sbv
438
439        self._strip_ptr = strip
440        return strip(sbvalue)
441
442    def xIterAsInt8(self, addr, count):
443        """ Conveniency wrapper to xIterAsScalar() on int8_t """
444        return self.xIterAsScalar(I8_STRUCT, addr, count)
445
446    def xIterAsInt16(self, addr, count):
447        """ Conveniency wrapper to xIterAsScalar() on int16_t """
448        return self.xIterAsScalar(I16_STRUCT, addr, count)
449
450    def xIterAsInt32(self, addr, count):
451        """ Conveniency wrapper to xIterAsScalar() on int32_t """
452        return self.xIterAsScalar(I32_STRUCT, addr, count)
453
454    def xIterAsInt64(self, addr, count):
455        """ Conveniency wrapper to xIterAsScalar() on int64_t """
456        return self.xIterAsScalar(I64_STRUCT, addr, count)
457
458    def xIterAsUInt8(self, addr, count):
459        """ Conveniency wrapper to xIterAsScalar() on uint8_t """
460        return self.xIterAsScalar(U8_STRUCT, addr, count)
461
462    def xIterAsUInt16(self, addr, count):
463        """ Conveniency wrapper to xIterAsScalar() on uint16_t """
464        return self.xIterAsScalar(U16_STRUCT, addr, count)
465
466    def xIterAsUInt32(self, addr, count):
467        """ Conveniency wrapper to xIterAsScalar() on uint32_t """
468        return self.xIterAsScalar(U32_STRUCT, addr, count)
469
470    def xIterAsUInt64(self, addr, count):
471        """ Conveniency wrapper to xIterAsScalar() on uint64_t """
472        return self.xIterAsScalar(U64_STRUCT, addr, count)
473
474    def xIterAsLong(self, addr, count):
475        """ Conveniency wrapper to xIterAsScalar() on long """
476        if self.GetProcess().GetAddressByteSize() == 8:
477            return self.xIterAsScalar(I64_STRUCT, addr, count)
478        return self.xIterAsScalar(I32_STRUCT, addr, count)
479
480    def xIterAsULong(self, addr, count):
481        """ Conveniency wrapper to xIterAsScalar() on unsigned long """
482        if self.GetProcess().GetAddressByteSize() == 8:
483            return self.xIterAsScalar(U64_STRUCT, addr, count)
484        return self.xIterAsScalar(U32_STRUCT, addr, count)
485
486    def xIterAsFloat(self, addr, count):
487        """ Conveniency wrapper to xIterAsScalar() on float """
488        return self.xIterAsScalar(FLT_STRUCT, addr, count)
489
490    def xIterAsDouble(self, addr, count):
491        """ Conveniency wrapper to xIterAsScalar() on double """
492        return self.xIterAsScalar(DBL_STRUCT, addr, count)
493
494
495    def xCreateValueFromAddress(self, name, addr, ty):
496        """
497        Create an SBValue with the given name by treating the memory starting
498        at addr as an entity of type.
499
500        More tolerant wrapper around CreateValueFromAddress() that accepts
501        for @c name to be None and @c addr to be an int.
502
503        @param name (str or None)
504            The name of the resultant SBValue
505
506        @param addr (int or lldb.SBAddress)
507            The address of the start of the memory region to be used.
508
509        @param ty (lldb.SBType)
510            The type to use to interpret the memory starting at addr.
511
512        @return (lldb.SBValue)
513            An SBValue of the given type.
514
515        @raises ValueError
516            For various error conditions.
517        """
518
519        if not isinstance(addr, lldb.SBAddress):
520            addr = self.rawResolveLoadAddress(addr)
521
522        if name is None:
523            # unlike SBValue's variant, SBTargets's will fail to produce
524            # a value if the name is None, don't ask.
525            name = 'newvalue'
526
527        v = self.CreateValueFromAddress(name, addr, ty)
528        if v.IsValid():
529            if QUIRK_100103405 and not addr:
530                v.SetPreferDynamicValue(0)
531            return v
532
533        lldbwrap_raise(ValueError, self.CreateValueFromAddress, None, name)
534
535
536class SBType(lldb.SBType, metaclass=LLDBWrapMetaclass):
537
538    #
539    # Extensions
540    #
541
542    def _findFieldOffsetByName(self, name):
543        """ internal helper """
544
545        for idx in range(self.GetNumberOfFields()):
546            field = self.GetFieldAtIndex(idx)
547            fname = field.GetName()
548
549            if fname == name:
550                return field.GetOffsetInBytes(), field.GetType()
551
552            if fname is None:
553                offs, ty = field.GetType()._findFieldOffsetByName(name)
554                if offs is not None:
555                    return offs + field.GetOffsetInBytes(), ty
556
557        return None, None
558
559    def _findFieldOffsetByPath(self, path):
560        """ internal helper """
561
562        offs = 0
563        ty   = self
564
565        key = path[1:] if path[0] == '.' else path
566
567        while key != '':
568            name, _, key = key.partition('.')
569            index = None
570
571            if name[-1] == ']':
572                name, _, index = name[:-1].partition('[')
573                if not index.isdigit():
574                    raise KeyError("Invalid path '{}'".format(path))
575                index = int(index)
576
577            f_offs, ty = ty._findFieldOffsetByName(name)
578            if f_offs is None:
579                return None, None, None
580
581            offs += f_offs
582            if index is not None:
583                if ty.GetTypeFlags() & lldb.eTypeIsArray:
584                    ty = ty.GetArrayElementType()
585                else:
586                    ty = ty.GetPointeeType()
587                offs += ty.GetByteSize() * index
588
589        return offs, ty, name
590
591    def xGetFieldOffset(self, path_or_name):
592        """
593        Returns offsetof(type, path_or_name) in bytes.
594
595        @param path_or_name (str)
596            The field path or name to compute the offset of
597
598        @return (int or None)
599            The requested offset of the field within the type,
600            or None if the field wasn't found
601        """
602        return self._findFieldOffsetByPath(path_or_name)[0]
603
604    def xContainerOfTransform(self, path):
605        """
606        Returns a function that can be used to apply a "__container_of"
607        transformation repeatedly (by field path).
608
609        @param path_or_name (str)
610            The field path or name to compute the offset of
611
612        @returns (function)
613            A function that returns the value resulting of
614            __container_of(value, type_t, path) for this type.
615        """
616
617        offs = self.xGetFieldOffset(path)
618
619        return lambda x: x.xCreateValueFromAddress(None, x.GetLoadAddress() - offs, self)
620
621    def xContainerOf(self, path_or_name, value):
622        """ same as self.xContainerOfTransform(path_or_name)(value) """
623
624        return self.xContainerOfTransform(path_or_name)(value)
625
626
627class SBValue(lldb.SBValue, metaclass=LLDBWrapMetaclass):
628
629    if QUIRK_100103405:
630        @classmethod
631        def xUpcast(cls, value):
632            #
633            # LLDB insists on trying to translate "NULL" for `void *`
634            # when dynamic values are enabled. It never caches the
635            # negative result which can yield really slow performance.
636            #
637            # Work it around by disabling dynamic values, looking at whether
638            # it's vaguely looking like a pointer and its value is a NULL
639            # pointer, and if not, turn dynamic values back on
640            #
641            # This check is extremely expensive and makes shorcuts,
642            # such as testing against "8" (sizeof(void *) on LP64)
643            # in order to delay realizing the type as much as possible
644            #
645            dyn = value.GetPreferDynamicValue()
646            if dyn:
647                value.SetPreferDynamicValue(0)
648                if (value.GetByteSize() != 8 or
649                        value.GetValueAsUnsigned() or
650                        not value.TypeIsPointerType()):
651                    value.SetPreferDynamicValue(dyn)
652
653            value.__class__ = cls
654
655    #
656    # Manually written checked wrappers
657    #
658
659    @functools.wraps(lldb.SBValue.GetValueAsSigned)
660    def chkGetValueAsSigned(self):
661        err = lldb.SBError()
662        res = self.GetValueAsSigned(err)
663        if res or err.Success():
664            return res
665        lldbwrap_raise(ValueError, self.chkGetValueAsSigned, err.GetCString(),
666            self)
667
668    @functools.wraps(lldb.SBValue.GetValueAsUnsigned)
669    def chkGetValueAsUnsigned(self):
670        err = lldb.SBError()
671        res = self.GetValueAsUnsigned(err)
672        if res or err.Success():
673            return res
674        lldbwrap_raise(ValueError, self.chkGetValueAsUnsigned, err.GetCString(),
675            self)
676
677    @functools.wraps(lldb.SBValue.SetValueFromCString)
678    def chkSetValueFromCString(self, value_str):
679        err = lldb.SBError()
680        if not self.SetValueFromCString(value_str, err):
681            lldbwrap_raise(ValueError, self.chkSetValueFromCString, err.GetCString(),
682                self, value_str)
683
684    @functools.wraps(lldb.SBValue.SetData)
685    def chkSetData(self, data):
686        err = lldb.SBError()
687        if not self.SetData(data, err):
688            lldbwrap_raise(ValueError, self.chkSetData, err.GetCString(),
689                self, data)
690
691    if QUIRK_99806493:
692        def Cast(self, ty):
693            v = super().Cast(ty)
694            SBValue.xUpcast(v)
695
696            if not v.IsValid() or not v.TypeIsPointerType():
697                return v
698
699            #
700            # NULL is fine, needs no PAC stripping,
701            # and it makes CreateValueFromAddress behave funny.
702            #
703            addr = v.GetValueAsAddress()
704            if addr == 0:
705                return v
706
707            #
708            # Casting from a pointer type to another
709            # is not stripping __ptrauth, let's fix it
710            #
711            nv = v.rawCreateValueFromAddress(v.GetName(), addr, ty)
712            nv.SetPreferDynamicValue(v.GetPreferDynamicValue())
713            v = nv.AddressOf().Cast(ty)
714
715            if QUIRK_100162262:
716                nv = v.Persist()
717                nv.SetPreferDynamicValue(v.GetPreferDynamicValue())
718                v = nv
719
720            # no need for QUIRK_100103405, can't be NULL
721            v.__class__ = SBValue
722            return v
723
724        def chkCast(self, ty):
725            v = self.Cast(ty)
726            if v.IsValid():
727                return v
728
729            lldbwrap_raise(ValueError, SBValue.Cast, None, self, ty)
730
731    if QUIRK_100162262:
732        def AddressOf(self):
733            v = super().AddressOf().Persist()
734            # no need for QUIRK_100103405
735            v.__class__ = SBValue
736            return v
737
738        def chkAddressOf(self):
739            v = self.AddressOf()
740            if v.IsValid():
741                return v
742
743            lldbwrap_raise(ValueError, SBValue.AddressOf, None, self)
744
745    if QUIRK_104494282:
746        def Dereference(self):
747            addr = self.GetValueAsAddress()
748            if addr == self.GetValueAsUnsigned():
749                v = super().Dereference()
750                SBValue.xUpcast(v)
751                return v
752
753            return self.xCreateValueFromAddress(self.GetName(),
754                addr, self.GetType().GetPointeeType())
755
756    if QUIRK_102642763:
757        def GetChildMemberWithName(self, name):
758            v = self.rawGetChildMemberWithName(name)
759            SBValue.xUpcast(v)
760            if v.IsValid():
761                return v
762
763            # Emulate compiler logic and visit all nested anon struct/unions.
764            if self.GetType().IsPointerType():
765                return self.xDereference().GetChildMemberWithName(name)
766
767            offs, mty = self.GetType()._findFieldOffsetByName(name)
768            if offs is None:
769                # LLDB returns instance of SBValue that is set as invalid.
770                # Re-use the invalid one from initial lookup.
771                return v
772
773            return self.xCreateValueFromAddress(name, self.GetLoadAddress() + offs, mty)
774
775        def GetValueForExpressionPath(self, path):
776            v = self.rawGetValueForExpressionPath(path)
777            SBValue.xUpcast(v)
778            if v.IsValid():
779                return v
780
781            # Emulate compiler logic and visit all nested anon struct/unions.
782            if self.GetType().IsPointerType():
783                return self.xDereference().GetValueForExpressionPath(path)
784
785            # Emulate compiler logic and visit all nested anon struct/unions.
786            offs, mty, name = self.GetType()._findFieldOffsetByPath(path)
787            if offs is None:
788                # LLDB returns instance of SBValue that is set as invalid.
789                # Re-use the invalid one from initial lookup.
790                return v
791
792            return self.xCreateValueFromAddress(name, self.GetLoadAddress() + offs, mty)
793
794
795    def IsValid(self):
796        """
797        SBValue.IsValid() is necessary but not sufficient to check an SBValue is in a valid state.
798
799        'IsValid means this is an SBValue with something in it that wasn't an obvious error, something you might ask questions of.
800        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.'
801
802        For XNU macros, we always care about whether we have an SBValue we can use - so we overload IsValid() for convenience
803        """
804        return super().IsValid() and self.error.success
805
806    #
807    # Extensions
808    #
809
810    def xCreateValueFromAddress(self, name, addr, ty):
811        """
812        Create an SBValue with the given name by treating the memory starting
813        at addr as an entity of type.
814
815        More tolerant wrapper around CreateValueFromAddress() that accepts
816        for @c name to be None and @c addr to be an lldb.SBAddress
817
818        @param name (str or None)
819            The name of the resultant SBValue
820
821        @param addr (int or lldb.SBAddress)
822            The address of the start of the memory region to be used.
823
824        @param ty (lldb.SBType)
825            The type to use to interpret the memory starting at addr.
826
827        @return (lldb.SBValue)
828            An SBValue of the given type.
829
830        @raises ValueError
831            For various error conditions.
832        """
833
834        if isinstance(addr, lldb.SBAddress):
835            addr = addr.GetLoadAddress()
836
837        if name is None:
838            # SBValue's version of CreateValueFromAddress() accepts None,
839            # but let's be consistent.
840            name = 'newvalue'
841
842        return self.chkCreateValueFromAddress(name, addr, ty)
843
844    def xGetSiblingValueAtIndex(self, index, stride=None):
845        """
846        Returns a sibling value to the current one in an array.
847
848        This basically performs pointer arithmetics on the SBValue.
849
850        @param index (int)
851            The index of the element to return relative to the current one.
852
853        @param stride (int or None):
854            If specified, use this stride instead of the natural value type size.
855
856        @returns (lldb.SBValue)
857            The resulting value.
858        """
859
860        if index:
861            addr = self.GetLoadAddress() + index * (stride or self.GetByteSize())
862            return self.chkCreateValueFromAddress(self.GetName(), addr, self.GetType())
863        return self
864
865    def xIterSiblings(self, start, stop, step=1):
866        """
867        Returns an iterator for sibling value to the current one in an array.
868
869        This basically performs pointer arithmetics on the SBValue.
870
871        @param start (int)
872            The first index (inclusive) to return
873
874        @param stop (int)
875            The last index (exclusive) to return
876
877        @param step (int or None):
878            The increment step if any
879
880        @returns (lldb.SBValue)
881            The resulting value.
882        """
883
884        size = self.GetByteSize()
885        ty   = self.GetType()
886        base = self.GetLoadAddress()
887
888        # aggressively cache the data
889        self.target.xReadBytes(base + start * size, (stop - start) * size)
890
891        return (
892            self.chkCreateValueFromAddress(None, base + i * size, ty)
893            for i in range(start, stop, step)
894        )
895
896    def xDereference(self):
897        """
898        Version of Dereference() that does the right thing for flexible arrays,
899        and returns None if NULL is being dereferenced.
900
901        @returns (lldb.SBValue):
902            - a reference to value[0] if value is a valid pointer/array
903            - None otherwise
904        """
905
906        rawty = self.rawGetType()
907        fl    = rawty.GetTypeFlags()
908
909        if fl & lldb.eTypeIsArray:
910            return self.xCreateValueFromAddress(self.GetName(),
911                self.GetLoadAddress(), rawty.GetArrayElementType())
912
913        if fl & lldb.eTypeIsPointer:
914            sbv_new = self.GetTarget().xStripPtr(self)
915            return sbv_new.chkDereference() if self.GetValueAsAddress() else None
916
917        lldbwrap_raise(TypeError, self.xDereference, "Type can't be dereferenced")
918
919
920    def xGetValueAsScalar(self, needed=0, rejected=0):
921        """
922        Get the scalar value of an SBValue
923
924        @param needed (lldb.eTypeIs* mask)
925            Sets of flags that should be set or the conversion should fail.
926
927        @param rejected (lldb.eTypeIs* mask)
928            Sets of flags that should fail the conversion if set on the value.
929        """
930
931        flags = self.rawGetType().GetTypeFlags()
932
933        if (flags & needed) != needed:
934            lldbwrap_raise(ValueError, self.xGetValueAsScalar,
935                "value of type {} has missing flags {:#x}".format(
936                self.GetType().GetDisplayTypeName(), (flags & needed) ^ needed),
937                self, needed=needed, rejected=rejected)
938
939        if flags & rejected:
940            lldbwrap_raise(ValueError, self.xGetValueAsScalar,
941                "value of type {} has rejected flags {:#x}".format(
942                self.GetType().GetDisplayTypeName(), flags & rejected),
943                self, needed=needed, rejected=rejected)
944
945        if flags & lldb.eTypeIsPointer:
946            return self.GetValueAsAddress()
947
948        err = lldb.SBError()
949        if flags & lldb.eTypeIsSigned:
950            res = self.GetValueAsSigned(err)
951        else:
952            res = self.GetValueAsUnsigned(err)
953            if QUIRK_99785324 and res and flags & lldb.eTypeIsEnumeration:
954                try:
955                    addr_of = self.rawAddressOf()
956                    if (res >> (self.GetByteSize() * 8 - 1) and
957                            not (addr_of.IsValid() and addr_of.error.success)):
958                        #
959                        # This field is:
960                        # - likely a bitfield (we can't take its AddressOf())
961                        # - unsigned
962                        # - with its top bit set
963                        #
964                        # This might be hitting rdar://99785324 where lldb
965                        # incorrectly sign-extends unsigned bit-fields.
966                        #
967                        # Here comes a crime against good taste: the expression
968                        # evaluator of lldb _knows_ how to do the right thing,
969                        # and now that the only thing we have is this lousy
970                        # lldb.SBValue(), we can only get to it via __str__().
971                        #
972                        # We parse something like this here:
973                        #   '(type_t:12) path = 42'
974                        #
975                        str_value = str(self)
976                        res = int(str_value[str_value.rfind(' '):], 0)
977                except:
978                    pass
979
980        if res or err.Success():
981            return res
982
983        lldbwrap_raise(ValueError, self.xGetValueAsScalar, err.GetCString(),
984            self, needed=needed, rejected=rejected)
985
986
987    def xGetValueAsInteger(self):
988        """
989        Get the integer value of an SBValue (fails for floats or complex)
990        """
991
992        mask = lldb.eTypeIsFloat | lldb.eTypeIsComplex
993        return self.xGetValueAsScalar(rejected=mask)
994
995
996    def xGetValueAsCString(self, max_len=1024):
997        """
998        Gets the cstring value of an SBValue.
999
1000        @param max_len (int)
1001            The maximum lenght expected for that string
1002
1003        @returns (str)
1004            A string holding the contents of the value.
1005
1006        @raises TypeError
1007            If the value can't be converted to a string
1008        """
1009
1010        if not self.IsValid():
1011            lldbwrap_raise(ValueError, self.xGetValueAsCString, "Value is invalid", self)
1012
1013        return self.target.GetProcess().chkReadCStringFromMemory(self.GetValueAsAddress(), max_len)
1014
1015
1016    def xGetScalarByName(self, name):
1017        """ same as chkGetChildMemberWithName(name).xGetValueAsScalar() """
1018
1019        v = self.rawGetChildMemberWithName(name)
1020        SBValue.xUpcast(v)
1021        if v.IsValid():
1022            if QUIRK_100103405:
1023                v.SetPreferDynamicValue(0)
1024            return v.xGetValueAsScalar()
1025
1026        lldbwrap_raise(ValueError, self.GetChildMemberWithName, None, name)
1027
1028    def xGetScalarAtIndex(self, index):
1029        """ same as chkGetChildAtIndex(index).xGetValueAsScalar() """
1030
1031        v = self.GetChildAtIndex(index)
1032        if v.IsValid():
1033            if QUIRK_100103405:
1034                v.SetPreferDynamicValue(0)
1035            return v.xGetValueAsScalar()
1036
1037        lldbwrap_raise(ValueError, self.GetChildAtIndex, None, index)
1038
1039    def xGetScalarByPath(self, path):
1040        """ same as chkGetValueForExpressionPath(path).xGetValueAsScalar() """
1041
1042        v = self.rawGetValueForExpressionPath(path)
1043        SBValue.xUpcast(v)
1044        if v.IsValid():
1045            if QUIRK_100103405:
1046                v.SetPreferDynamicValue(0)
1047            return v.xGetValueAsScalar()
1048
1049        lldbwrap_raise(ValueError, self.GetValueForExpressionPath, None, path)
1050
1051
1052    def xGetIntegerByName(self, name):
1053        """ same as chkGetChildMemberWithName(name).xGetValueAsInteger() """
1054
1055        v = self.rawGetChildMemberWithName(name)
1056        SBValue.xUpcast(v)
1057        if v.IsValid():
1058            if QUIRK_100103405:
1059                v.SetPreferDynamicValue(0)
1060            return v.xGetValueAsInteger()
1061
1062        lldbwrap_raise(ValueError, self.GetChildMemberWithName, None, name)
1063
1064    def xGetIntegerAtIndex(self, index):
1065        """ same as chkGetChildAtIndex(index).xGetValueAsInteger() """
1066
1067        v = self.GetChildAtIndex(index)
1068        if v.IsValid():
1069            if QUIRK_100103405:
1070                v.SetPreferDynamicValue(0)
1071            return v.xGetValueAsInteger()
1072
1073        lldbwrap_raise(ValueError, self.GetChildAtIndex, None, index)
1074
1075    def xGetIntegerByPath(self, path):
1076        """ same as chkGetValueForExpressionPath(path).xGetValueAsInteger() """
1077
1078        v = self.rawGetValueForExpressionPath(path)
1079        SBValue.xUpcast(v)
1080        if v.IsValid():
1081            if QUIRK_100103405:
1082                v.SetPreferDynamicValue(0)
1083            return v.xGetValueAsInteger()
1084
1085        lldbwrap_raise(ValueError, self.GetValueForExpressionPath, None, path)
1086
1087
1088    def xGetPointeeByName(self, name):
1089        """ same as chkGetChildMemberWithName(name).xDereference() """
1090
1091        v = self.rawGetChildMemberWithName(name)
1092        SBValue.xUpcast(v)
1093        if v.IsValid():
1094            return v.xDereference()
1095
1096        lldbwrap_raise(ValueError, self.GetChildMemberWithName, None, name)
1097
1098    def xGetPointeeAtIndex(self, index):
1099        """ same as chkGetChildAtIndex(index).xDereference() """
1100
1101        v = self.GetChildAtIndex(index)
1102        if v.IsValid():
1103            return v.xDereference()
1104
1105        lldbwrap_raise(ValueError, self.GetChildAtIndex, None, index)
1106
1107    def xGetPointeeByPath(self, path):
1108        """ same as chkGetValueForExpressionPath(path).xDereference() """
1109
1110        v = self.rawGetValueForExpressionPath(path)
1111        SBValue.xUpcast(v)
1112        if v.IsValid():
1113            return v.xDereference()
1114
1115        lldbwrap_raise(ValueError, self.GetValueForExpressionPath, None, path)
1116
1117
1118    def xGetLoadAddressByName(self, name):
1119        """ same as chkGetChildMemberWithName(name).GetLoadAddress() """
1120
1121        v = self.rawGetChildMemberWithName(name)
1122        SBValue.xUpcast(v)
1123        if v.IsValid():
1124            if QUIRK_100103405:
1125                v.SetPreferDynamicValue(0)
1126            return v.GetLoadAddress()
1127
1128        lldbwrap_raise(ValueError, self.GetChildMemberWithName, None, name)
1129
1130    def xGetLoadAddressAtIndex(self, index):
1131        """ same as chkGetChildAtIndex(index).GetLoadAddress() """
1132
1133        v = self.GetChildAtIndex(index)
1134        if v.IsValid():
1135            if QUIRK_100103405:
1136                v.SetPreferDynamicValue(0)
1137            return v.GetLoadAddress()
1138
1139        lldbwrap_raise(ValueError, self.GetChildAtIndex, None, index)
1140
1141    def xGetLoadAddressByPath(self, path):
1142        """ same as chkGetValueForExpressionPath(path).GetLoadAddress() """
1143
1144        v = self.rawGetValueForExpressionPath(path)
1145        SBValue.xUpcast(v)
1146        if v.IsValid():
1147            if QUIRK_100103405:
1148                v.SetPreferDynamicValue(0)
1149            return v.GetLoadAddress()
1150
1151        lldbwrap_raise(ValueError, self.GetValueForExpressionPath, None, path)
1152
1153
1154    def xGetCStringByName(self, name, *args):
1155        """ same as chkGetChildMemberWithName(name).xGetValueAsCString() """
1156
1157        v = self.rawGetChildMemberWithName(name)
1158        SBValue.xUpcast(v)
1159        if v.IsValid():
1160            if QUIRK_100103405:
1161                v.SetPreferDynamicValue(0)
1162            return v.xGetValueAsCString(*args)
1163
1164        lldbwrap_raise(ValueError, self.GetChildMemberWithName, None, name)
1165
1166    def xGetCStringAtIndex(self, index, *args):
1167        """ same as chkGetChildAtIndex(index).xGetValueAsCString() """
1168
1169        v = self.GetChildAtIndex(index)
1170        if v.IsValid():
1171            if QUIRK_100103405:
1172                v.SetPreferDynamicValue(0)
1173            return v.xGetValueAsCString(*args)
1174
1175        lldbwrap_raise(ValueError, self.GetChildAtIndex, None, index)
1176
1177    def xGetCStringByPath(self, path, *args):
1178        """ same as chkGetValueForExpressionPath(path).xGetValueAsCString() """
1179
1180        v = self.rawGetValueForExpressionPath(path)
1181        SBValue.xUpcast(v)
1182        if v.IsValid():
1183            if QUIRK_100103405:
1184                v.SetPreferDynamicValue(0)
1185            return v.xGetValueAsCString(*args)
1186
1187        lldbwrap_raise(ValueError, self.GetValueForExpressionPath, None, path)
1188
1189
1190def GetDebugger():
1191    """ Alternative to lldb.debugger since we can't hook globals """
1192    return SBDebugger(lldb.debugger)
1193
1194def GetTarget():
1195    """
1196    Alternative to lldb.target
1197
1198    Using lldb.target has several issues because it is set late by lldb,
1199    and might resolve to None even when there is a selected target already.
1200    """
1201
1202    return GetDebugger().GetSelectedTarget()
1203
1204def GetProcess():
1205    """
1206    Alternative to lldb.process
1207
1208    Using lldb.process has several issues because it is set late by lldb,
1209    and might resolve to None even when there is a selected target already.
1210    """
1211    return GetTarget().GetProcess()
1212
1213__all__.extend((
1214    GetDebugger.__name__,
1215    GetProcess.__name__,
1216    GetTarget.__name__,
1217))
1218
1219
1220################################################################################
1221#
1222# Code to generate the module content by replicating `lldb`
1223#
1224
1225def lldbwrap_generate(this_module):
1226    sb_classes = (
1227       m
1228       for m in inspect.getmembers(lldb, inspect.isclass)
1229       if m[0][:2] == "SB"
1230    )
1231
1232    for name, base in sb_classes:
1233        cls = getattr(this_module, name, None)
1234        if not hasattr(this_module, name):
1235            attr = {}
1236            lldbwrap_update_class_dict(name, base, attr)
1237            cls = type(name, (base,), attr)
1238            setattr(this_module, name, cls)
1239
1240        UPCASTS[base] = cls.xUpcast
1241        __all__.append(name)
1242
1243    #
1244    # Re-export globals
1245    #
1246
1247    for name, value in inspect.getmembers(lldb):
1248
1249        if name.startswith("LLDB_"):
1250            setattr(this_module, name, value)
1251            __all__.append(name)
1252            continue
1253
1254        if name[0] == 'e' and name[1].isupper():
1255            setattr(this_module, name, value)
1256            __all__.append(name)
1257            continue
1258
1259lldbwrap_generate(sys.modules[__name__])
1260