1##===-- lldbutil.py ------------------------------------------*- Python -*-===##
2##
3# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4# See https://llvm.org/LICENSE.txt for license information.
5# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6##
7##===----------------------------------------------------------------------===##
8
9"""
10This LLDB module contains miscellaneous utilities.
11Some of the test suite takes advantage of the utility functions defined here.
12They can also be useful for general purpose lldb scripting.
13"""
14
15from __future__ import print_function
16
17import lldb
18import os
19import sys
20import io
21
22# ===================================================
23# Utilities for locating/checking executable programs
24# ===================================================
25
26
27def is_exe(fpath):
28    """Returns True if fpath is an executable."""
29    return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
30
31
32def which(program):
33    """Returns the full path to a program; None otherwise."""
34    fpath, fname = os.path.split(program)
35    if fpath:
36        if is_exe(program):
37            return program
38    else:
39        for path in os.environ["PATH"].split(os.pathsep):
40            exe_file = os.path.join(path, program)
41            if is_exe(exe_file):
42                return exe_file
43    return None
44
45# ===================================================
46# Disassembly for an SBFunction or an SBSymbol object
47# ===================================================
48
49
50def disassemble(target, function_or_symbol):
51    """Disassemble the function or symbol given a target.
52
53    It returns the disassembly content in a string object.
54    """
55    buf = io.StringIO()
56    insts = function_or_symbol.GetInstructions(target)
57    for i in insts:
58        print(i, file=buf)
59    return buf.getvalue()
60
61# ==========================================================
62# Integer (byte size 1, 2, 4, and 8) to bytearray conversion
63# ==========================================================
64
65
66def int_to_bytearray(val, bytesize):
67    """Utility function to convert an integer into a bytearray.
68
69    It returns the bytearray in the little endian format.  It is easy to get the
70    big endian format, just do ba.reverse() on the returned object.
71    """
72    import struct
73
74    if bytesize == 1:
75        return bytearray([val])
76
77    # Little endian followed by a format character.
78    template = "<%c"
79    if bytesize == 2:
80        fmt = template % 'h'
81    elif bytesize == 4:
82        fmt = template % 'i'
83    elif bytesize == 4:
84        fmt = template % 'q'
85    else:
86        return None
87
88    packed = struct.pack(fmt, val)
89    return bytearray(ord(x) for x in packed)
90
91
92def bytearray_to_int(bytes, bytesize):
93    """Utility function to convert a bytearray into an integer.
94
95    It interprets the bytearray in the little endian format. For a big endian
96    bytearray, just do ba.reverse() on the object before passing it in.
97    """
98    import struct
99
100    if bytesize == 1:
101        return bytes[0]
102
103    # Little endian followed by a format character.
104    template = "<%c"
105    if bytesize == 2:
106        fmt = template % 'h'
107    elif bytesize == 4:
108        fmt = template % 'i'
109    elif bytesize == 4:
110        fmt = template % 'q'
111    else:
112        return None
113
114    unpacked = struct.unpack(fmt, str(bytes))
115    return unpacked[0]
116
117
118# ==============================================================
119# Get the description of an lldb object or None if not available
120# ==============================================================
121def get_description(obj, option=None):
122    """Calls lldb_obj.GetDescription() and returns a string, or None.
123
124    For SBTarget, SBBreakpointLocation, and SBWatchpoint lldb objects, an extra
125    option can be passed in to describe the detailed level of description
126    desired:
127        o lldb.eDescriptionLevelBrief
128        o lldb.eDescriptionLevelFull
129        o lldb.eDescriptionLevelVerbose
130    """
131    method = getattr(obj, 'GetDescription')
132    if not method:
133        return None
134    tuple = (lldb.SBTarget, lldb.SBBreakpointLocation, lldb.SBWatchpoint)
135    if isinstance(obj, tuple):
136        if option is None:
137            option = lldb.eDescriptionLevelBrief
138
139    stream = lldb.SBStream()
140    if option is None:
141        success = method(stream)
142    else:
143        success = method(stream, option)
144    if not success:
145        return None
146    return stream.GetData()
147
148
149# =================================================
150# Convert some enum value to its string counterpart
151# =================================================
152
153def state_type_to_str(enum):
154    """Returns the stateType string given an enum."""
155    if enum == lldb.eStateInvalid:
156        return "invalid"
157    elif enum == lldb.eStateUnloaded:
158        return "unloaded"
159    elif enum == lldb.eStateConnected:
160        return "connected"
161    elif enum == lldb.eStateAttaching:
162        return "attaching"
163    elif enum == lldb.eStateLaunching:
164        return "launching"
165    elif enum == lldb.eStateStopped:
166        return "stopped"
167    elif enum == lldb.eStateRunning:
168        return "running"
169    elif enum == lldb.eStateStepping:
170        return "stepping"
171    elif enum == lldb.eStateCrashed:
172        return "crashed"
173    elif enum == lldb.eStateDetached:
174        return "detached"
175    elif enum == lldb.eStateExited:
176        return "exited"
177    elif enum == lldb.eStateSuspended:
178        return "suspended"
179    else:
180        raise Exception("Unknown StateType enum")
181
182
183def stop_reason_to_str(enum):
184    """Returns the stopReason string given an enum."""
185    if enum == lldb.eStopReasonInvalid:
186        return "invalid"
187    elif enum == lldb.eStopReasonNone:
188        return "none"
189    elif enum == lldb.eStopReasonTrace:
190        return "trace"
191    elif enum == lldb.eStopReasonBreakpoint:
192        return "breakpoint"
193    elif enum == lldb.eStopReasonWatchpoint:
194        return "watchpoint"
195    elif enum == lldb.eStopReasonSignal:
196        return "signal"
197    elif enum == lldb.eStopReasonException:
198        return "exception"
199    elif enum == lldb.eStopReasonPlanComplete:
200        return "plancomplete"
201    elif enum == lldb.eStopReasonThreadExiting:
202        return "threadexiting"
203    else:
204        raise Exception("Unknown StopReason enum")
205
206
207def symbol_type_to_str(enum):
208    """Returns the symbolType string given an enum."""
209    if enum == lldb.eSymbolTypeInvalid:
210        return "invalid"
211    elif enum == lldb.eSymbolTypeAbsolute:
212        return "absolute"
213    elif enum == lldb.eSymbolTypeCode:
214        return "code"
215    elif enum == lldb.eSymbolTypeData:
216        return "data"
217    elif enum == lldb.eSymbolTypeTrampoline:
218        return "trampoline"
219    elif enum == lldb.eSymbolTypeRuntime:
220        return "runtime"
221    elif enum == lldb.eSymbolTypeException:
222        return "exception"
223    elif enum == lldb.eSymbolTypeSourceFile:
224        return "sourcefile"
225    elif enum == lldb.eSymbolTypeHeaderFile:
226        return "headerfile"
227    elif enum == lldb.eSymbolTypeObjectFile:
228        return "objectfile"
229    elif enum == lldb.eSymbolTypeCommonBlock:
230        return "commonblock"
231    elif enum == lldb.eSymbolTypeBlock:
232        return "block"
233    elif enum == lldb.eSymbolTypeLocal:
234        return "local"
235    elif enum == lldb.eSymbolTypeParam:
236        return "param"
237    elif enum == lldb.eSymbolTypeVariable:
238        return "variable"
239    elif enum == lldb.eSymbolTypeVariableType:
240        return "variabletype"
241    elif enum == lldb.eSymbolTypeLineEntry:
242        return "lineentry"
243    elif enum == lldb.eSymbolTypeLineHeader:
244        return "lineheader"
245    elif enum == lldb.eSymbolTypeScopeBegin:
246        return "scopebegin"
247    elif enum == lldb.eSymbolTypeScopeEnd:
248        return "scopeend"
249    elif enum == lldb.eSymbolTypeAdditional:
250        return "additional"
251    elif enum == lldb.eSymbolTypeCompiler:
252        return "compiler"
253    elif enum == lldb.eSymbolTypeInstrumentation:
254        return "instrumentation"
255    elif enum == lldb.eSymbolTypeUndefined:
256        return "undefined"
257
258
259def value_type_to_str(enum):
260    """Returns the valueType string given an enum."""
261    if enum == lldb.eValueTypeInvalid:
262        return "invalid"
263    elif enum == lldb.eValueTypeVariableGlobal:
264        return "global_variable"
265    elif enum == lldb.eValueTypeVariableStatic:
266        return "static_variable"
267    elif enum == lldb.eValueTypeVariableArgument:
268        return "argument_variable"
269    elif enum == lldb.eValueTypeVariableLocal:
270        return "local_variable"
271    elif enum == lldb.eValueTypeRegister:
272        return "register"
273    elif enum == lldb.eValueTypeRegisterSet:
274        return "register_set"
275    elif enum == lldb.eValueTypeConstResult:
276        return "constant_result"
277    else:
278        raise Exception("Unknown ValueType enum")
279
280
281# ==================================================
282# Get stopped threads due to each stop reason.
283# ==================================================
284
285def sort_stopped_threads(process,
286                         breakpoint_threads=None,
287                         crashed_threads=None,
288                         watchpoint_threads=None,
289                         signal_threads=None,
290                         exiting_threads=None,
291                         other_threads=None):
292    """ Fills array *_threads with threads stopped for the corresponding stop
293        reason.
294    """
295    for lst in [breakpoint_threads,
296                watchpoint_threads,
297                signal_threads,
298                exiting_threads,
299                other_threads]:
300        if lst is not None:
301            lst[:] = []
302
303    for thread in process:
304        dispatched = False
305        for (reason, list) in [(lldb.eStopReasonBreakpoint, breakpoint_threads),
306                               (lldb.eStopReasonException, crashed_threads),
307                               (lldb.eStopReasonWatchpoint, watchpoint_threads),
308                               (lldb.eStopReasonSignal, signal_threads),
309                               (lldb.eStopReasonThreadExiting, exiting_threads),
310                               (None, other_threads)]:
311            if not dispatched and list is not None:
312                if thread.GetStopReason() == reason or reason is None:
313                    list.append(thread)
314                    dispatched = True
315
316# ==================================================
317# Utility functions for setting breakpoints
318# ==================================================
319
320
321def run_break_set_by_file_and_line(
322        test,
323        file_name,
324        line_number,
325        extra_options=None,
326        num_expected_locations=1,
327        loc_exact=False,
328        module_name=None):
329    """Set a breakpoint by file and line, returning the breakpoint number.
330
331    If extra_options is not None, then we append it to the breakpoint set command.
332
333    If num_expected_locations is -1 we check that we got AT LEAST one location, otherwise we check that num_expected_locations equals the number of locations.
334
335    If loc_exact is true, we check that there is one location, and that location must be at the input file and line number."""
336
337    if file_name is None:
338        command = 'breakpoint set -l %d' % (line_number)
339    else:
340        command = 'breakpoint set -f "%s" -l %d' % (file_name, line_number)
341
342    if module_name:
343        command += " --shlib '%s'" % (module_name)
344
345    if extra_options:
346        command += " " + extra_options
347
348    break_results = run_break_set_command(test, command)
349
350    if num_expected_locations == 1 and loc_exact:
351        check_breakpoint_result(
352            test,
353            break_results,
354            num_locations=num_expected_locations,
355            file_name=file_name,
356            line_number=line_number,
357            module_name=module_name)
358    else:
359        check_breakpoint_result(
360            test,
361            break_results,
362            num_locations=num_expected_locations)
363
364    return get_bpno_from_match(break_results)
365
366
367def run_break_set_by_symbol(
368        test,
369        symbol,
370        extra_options=None,
371        num_expected_locations=-1,
372        sym_exact=False,
373        module_name=None):
374    """Set a breakpoint by symbol name.  Common options are the same as run_break_set_by_file_and_line.
375
376    If sym_exact is true, then the output symbol must match the input exactly, otherwise we do a substring match."""
377    command = 'breakpoint set -n "%s"' % (symbol)
378
379    if module_name:
380        command += " --shlib '%s'" % (module_name)
381
382    if extra_options:
383        command += " " + extra_options
384
385    break_results = run_break_set_command(test, command)
386
387    if num_expected_locations == 1 and sym_exact:
388        check_breakpoint_result(
389            test,
390            break_results,
391            num_locations=num_expected_locations,
392            symbol_name=symbol,
393            module_name=module_name)
394    else:
395        check_breakpoint_result(
396            test,
397            break_results,
398            num_locations=num_expected_locations)
399
400    return get_bpno_from_match(break_results)
401
402
403def run_break_set_by_selector(
404        test,
405        selector,
406        extra_options=None,
407        num_expected_locations=-1,
408        module_name=None):
409    """Set a breakpoint by selector.  Common options are the same as run_break_set_by_file_and_line."""
410
411    command = 'breakpoint set -S "%s"' % (selector)
412
413    if module_name:
414        command += ' --shlib "%s"' % (module_name)
415
416    if extra_options:
417        command += " " + extra_options
418
419    break_results = run_break_set_command(test, command)
420
421    if num_expected_locations == 1:
422        check_breakpoint_result(
423            test,
424            break_results,
425            num_locations=num_expected_locations,
426            symbol_name=selector,
427            symbol_match_exact=False,
428            module_name=module_name)
429    else:
430        check_breakpoint_result(
431            test,
432            break_results,
433            num_locations=num_expected_locations)
434
435    return get_bpno_from_match(break_results)
436
437
438def run_break_set_by_regexp(
439        test,
440        regexp,
441        extra_options=None,
442        num_expected_locations=-1):
443    """Set a breakpoint by regular expression match on symbol name.  Common options are the same as run_break_set_by_file_and_line."""
444
445    command = 'breakpoint set -r "%s"' % (regexp)
446    if extra_options:
447        command += " " + extra_options
448
449    break_results = run_break_set_command(test, command)
450
451    check_breakpoint_result(
452        test,
453        break_results,
454        num_locations=num_expected_locations)
455
456    return get_bpno_from_match(break_results)
457
458
459def run_break_set_by_source_regexp(
460        test,
461        regexp,
462        extra_options=None,
463        num_expected_locations=-1):
464    """Set a breakpoint by source regular expression.  Common options are the same as run_break_set_by_file_and_line."""
465    command = 'breakpoint set -p "%s"' % (regexp)
466    if extra_options:
467        command += " " + extra_options
468
469    break_results = run_break_set_command(test, command)
470
471    check_breakpoint_result(
472        test,
473        break_results,
474        num_locations=num_expected_locations)
475
476    return get_bpno_from_match(break_results)
477
478
479def run_break_set_command(test, command):
480    """Run the command passed in - it must be some break set variant - and analyze the result.
481    Returns a dictionary of information gleaned from the command-line results.
482    Will assert if the breakpoint setting fails altogether.
483
484    Dictionary will contain:
485        bpno          - breakpoint of the newly created breakpoint, -1 on error.
486        num_locations - number of locations set for the breakpoint.
487
488    If there is only one location, the dictionary MAY contain:
489        file          - source file name
490        line_no       - source line number
491        symbol        - symbol name
492        inline_symbol - inlined symbol name
493        offset        - offset from the original symbol
494        module        - module
495        address       - address at which the breakpoint was set."""
496
497    patterns = [
498        r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>[0-9]+) locations\.$",
499        r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>no) locations \(pending\)\.",
500        r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>[+\-]{0,1}[^+]+)( \+ (?P<offset>[0-9]+)){0,1}( \[inlined\] (?P<inline_symbol>.*)){0,1} at (?P<file>[^:]+):(?P<line_no>[0-9]+), address = (?P<address>0x[0-9a-fA-F]+)$",
501        r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>.*)( \+ (?P<offset>[0-9]+)){0,1}, address = (?P<address>0x[0-9a-fA-F]+)$"]
502    match_object = test.match(command, patterns)
503    break_results = match_object.groupdict()
504
505    # We always insert the breakpoint number, setting it to -1 if we couldn't find it
506    # Also, make sure it gets stored as an integer.
507    if not 'bpno' in break_results:
508        break_results['bpno'] = -1
509    else:
510        break_results['bpno'] = int(break_results['bpno'])
511
512    # We always insert the number of locations
513    # If ONE location is set for the breakpoint, then the output doesn't mention locations, but it has to be 1...
514    # We also make sure it is an integer.
515
516    if not 'num_locations' in break_results:
517        num_locations = 1
518    else:
519        num_locations = break_results['num_locations']
520        if num_locations == 'no':
521            num_locations = 0
522        else:
523            num_locations = int(break_results['num_locations'])
524
525    break_results['num_locations'] = num_locations
526
527    if 'line_no' in break_results:
528        break_results['line_no'] = int(break_results['line_no'])
529
530    return break_results
531
532
533def get_bpno_from_match(break_results):
534    return int(break_results['bpno'])
535
536
537def check_breakpoint_result(
538        test,
539        break_results,
540        file_name=None,
541        line_number=-1,
542        symbol_name=None,
543        symbol_match_exact=True,
544        module_name=None,
545        offset=-1,
546        num_locations=-1):
547
548    out_num_locations = break_results['num_locations']
549
550    if num_locations == -1:
551        test.assertTrue(out_num_locations > 0,
552                        "Expecting one or more locations, got none.")
553    else:
554        test.assertTrue(
555            num_locations == out_num_locations,
556            "Expecting %d locations, got %d." %
557            (num_locations,
558             out_num_locations))
559
560    if file_name:
561        out_file_name = ""
562        if 'file' in break_results:
563            out_file_name = break_results['file']
564        test.assertTrue(
565            file_name == out_file_name,
566            "Breakpoint file name '%s' doesn't match resultant name '%s'." %
567            (file_name,
568             out_file_name))
569
570    if line_number != -1:
571        out_file_line = -1
572        if 'line_no' in break_results:
573            out_line_number = break_results['line_no']
574
575        test.assertTrue(
576            line_number == out_line_number,
577            "Breakpoint line number %s doesn't match resultant line %s." %
578            (line_number,
579             out_line_number))
580
581    if symbol_name:
582        out_symbol_name = ""
583        # Look first for the inlined symbol name, otherwise use the symbol
584        # name:
585        if 'inline_symbol' in break_results and break_results['inline_symbol']:
586            out_symbol_name = break_results['inline_symbol']
587        elif 'symbol' in break_results:
588            out_symbol_name = break_results['symbol']
589
590        if symbol_match_exact:
591            test.assertTrue(
592                symbol_name == out_symbol_name,
593                "Symbol name '%s' doesn't match resultant symbol '%s'." %
594                (symbol_name,
595                 out_symbol_name))
596        else:
597            test.assertTrue(
598                out_symbol_name.find(symbol_name) != -
599                1,
600                "Symbol name '%s' isn't in resultant symbol '%s'." %
601                (symbol_name,
602                 out_symbol_name))
603
604    if module_name:
605        out_nodule_name = None
606        if 'module' in break_results:
607            out_module_name = break_results['module']
608
609        test.assertTrue(
610            module_name.find(out_module_name) != -
611            1,
612            "Symbol module name '%s' isn't in expected module name '%s'." %
613            (out_module_name,
614             module_name))
615
616# ==================================================
617# Utility functions related to Threads and Processes
618# ==================================================
619
620
621def get_stopped_threads(process, reason):
622    """Returns the thread(s) with the specified stop reason in a list.
623
624    The list can be empty if no such thread exists.
625    """
626    threads = []
627    for t in process:
628        if t.GetStopReason() == reason:
629            threads.append(t)
630    return threads
631
632
633def get_stopped_thread(process, reason):
634    """A convenience function which returns the first thread with the given stop
635    reason or None.
636
637    Example usages:
638
639    1. Get the stopped thread due to a breakpoint condition
640
641    ...
642        from lldbutil import get_stopped_thread
643        thread = get_stopped_thread(process, lldb.eStopReasonPlanComplete)
644        self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition")
645    ...
646
647    2. Get the thread stopped due to a breakpoint
648
649    ...
650        from lldbutil import get_stopped_thread
651        thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
652        self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint")
653    ...
654
655    """
656    threads = get_stopped_threads(process, reason)
657    if len(threads) == 0:
658        return None
659    return threads[0]
660
661
662def get_threads_stopped_at_breakpoint(process, bkpt):
663    """ For a stopped process returns the thread stopped at the breakpoint passed in bkpt"""
664    stopped_threads = []
665    threads = []
666
667    stopped_threads = get_stopped_threads(process, lldb.eStopReasonBreakpoint)
668
669    if len(stopped_threads) == 0:
670        return threads
671
672    for thread in stopped_threads:
673        # Make sure we've hit our breakpoint...
674        break_id = thread.GetStopReasonDataAtIndex(0)
675        if break_id == bkpt.GetID():
676            threads.append(thread)
677
678    return threads
679
680
681def continue_to_breakpoint(process, bkpt):
682    """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
683    process.Continue()
684    if process.GetState() != lldb.eStateStopped:
685        return None
686    else:
687        return get_threads_stopped_at_breakpoint(process, bkpt)
688
689
690def get_caller_symbol(thread):
691    """
692    Returns the symbol name for the call site of the leaf function.
693    """
694    depth = thread.GetNumFrames()
695    if depth <= 1:
696        return None
697    caller = thread.GetFrameAtIndex(1).GetSymbol()
698    if caller:
699        return caller.GetName()
700    else:
701        return None
702
703
704def get_function_names(thread):
705    """
706    Returns a sequence of function names from the stack frames of this thread.
707    """
708    def GetFuncName(i):
709        return thread.GetFrameAtIndex(i).GetFunctionName()
710
711    return [GetFuncName(i) for i in range(thread.GetNumFrames())]
712
713
714def get_symbol_names(thread):
715    """
716    Returns a sequence of symbols for this thread.
717    """
718    def GetSymbol(i):
719        return thread.GetFrameAtIndex(i).GetSymbol().GetName()
720
721    return [GetSymbol(i) for i in range(thread.GetNumFrames())]
722
723
724def get_pc_addresses(thread):
725    """
726    Returns a sequence of pc addresses for this thread.
727    """
728    def GetPCAddress(i):
729        return thread.GetFrameAtIndex(i).GetPCAddress()
730
731    return [GetPCAddress(i) for i in range(thread.GetNumFrames())]
732
733
734def get_filenames(thread):
735    """
736    Returns a sequence of file names from the stack frames of this thread.
737    """
738    def GetFilename(i):
739        return thread.GetFrameAtIndex(
740            i).GetLineEntry().GetFileSpec().GetFilename()
741
742    return [GetFilename(i) for i in range(thread.GetNumFrames())]
743
744
745def get_line_numbers(thread):
746    """
747    Returns a sequence of line numbers from the stack frames of this thread.
748    """
749    def GetLineNumber(i):
750        return thread.GetFrameAtIndex(i).GetLineEntry().GetLine()
751
752    return [GetLineNumber(i) for i in range(thread.GetNumFrames())]
753
754
755def get_module_names(thread):
756    """
757    Returns a sequence of module names from the stack frames of this thread.
758    """
759    def GetModuleName(i):
760        return thread.GetFrameAtIndex(
761            i).GetModule().GetFileSpec().GetFilename()
762
763    return [GetModuleName(i) for i in range(thread.GetNumFrames())]
764
765
766def get_stack_frames(thread):
767    """
768    Returns a sequence of stack frames for this thread.
769    """
770    def GetStackFrame(i):
771        return thread.GetFrameAtIndex(i)
772
773    return [GetStackFrame(i) for i in range(thread.GetNumFrames())]
774
775
776def print_stacktrace(thread, string_buffer=False):
777    """Prints a simple stack trace of this thread."""
778
779    output = io.StringIO() if string_buffer else sys.stdout
780    target = thread.GetProcess().GetTarget()
781
782    depth = thread.GetNumFrames()
783
784    mods = get_module_names(thread)
785    funcs = get_function_names(thread)
786    symbols = get_symbol_names(thread)
787    files = get_filenames(thread)
788    lines = get_line_numbers(thread)
789    addrs = get_pc_addresses(thread)
790
791    if thread.GetStopReason() != lldb.eStopReasonInvalid:
792        desc = "stop reason=" + stop_reason_to_str(thread.GetStopReason())
793    else:
794        desc = ""
795    print("Stack trace for thread id={0:#x} name={1} queue={2} ".format(
796        thread.GetThreadID(), thread.GetName(), thread.GetQueueName()) + desc, file=output)
797
798    for i in range(depth):
799        frame = thread.GetFrameAtIndex(i)
800        function = frame.GetFunction()
801
802        load_addr = addrs[i].GetLoadAddress(target)
803        if not function:
804            file_addr = addrs[i].GetFileAddress()
805            start_addr = frame.GetSymbol().GetStartAddress().GetFileAddress()
806            symbol_offset = file_addr - start_addr
807            print("  frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}".format(
808                num=i, addr=load_addr, mod=mods[i], symbol=symbols[i], offset=symbol_offset), file=output)
809        else:
810            print("  frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format(
811                num=i, addr=load_addr, mod=mods[i], func='%s [inlined]' %
812                funcs[i] if frame.IsInlined() else funcs[i], file=files[i], line=lines[i], args=get_args_as_string(
813                    frame, showFuncName=False) if not frame.IsInlined() else '()'), file=output)
814
815    if string_buffer:
816        return output.getvalue()
817
818
819def print_stacktraces(process, string_buffer=False):
820    """Prints the stack traces of all the threads."""
821
822    output = io.StringIO() if string_buffer else sys.stdout
823
824    print("Stack traces for " + str(process), file=output)
825
826    for thread in process:
827        print(print_stacktrace(thread, string_buffer=True), file=output)
828
829    if string_buffer:
830        return output.getvalue()
831
832# ===================================
833# Utility functions related to Frames
834# ===================================
835
836
837def get_parent_frame(frame):
838    """
839    Returns the parent frame of the input frame object; None if not available.
840    """
841    thread = frame.GetThread()
842    parent_found = False
843    for f in thread:
844        if parent_found:
845            return f
846        if f.GetFrameID() == frame.GetFrameID():
847            parent_found = True
848
849    # If we reach here, no parent has been found, return None.
850    return None
851
852
853def get_args_as_string(frame, showFuncName=True):
854    """
855    Returns the args of the input frame object as a string.
856    """
857    # arguments     => True
858    # locals        => False
859    # statics       => False
860    # in_scope_only => True
861    vars = frame.GetVariables(True, False, False, True)  # type of SBValueList
862    args = []  # list of strings
863    for var in vars:
864        args.append("(%s)%s=%s" % (var.GetTypeName(),
865                                   var.GetName(),
866                                   var.GetValue()))
867    if frame.GetFunction():
868        name = frame.GetFunction().GetName()
869    elif frame.GetSymbol():
870        name = frame.GetSymbol().GetName()
871    else:
872        name = ""
873    if showFuncName:
874        return "%s(%s)" % (name, ", ".join(args))
875    else:
876        return "(%s)" % (", ".join(args))
877
878
879def print_registers(frame, string_buffer=False):
880    """Prints all the register sets of the frame."""
881
882    output = io.StringIO() if string_buffer else sys.stdout
883
884    print("Register sets for " + str(frame), file=output)
885
886    registerSet = frame.GetRegisters()  # Return type of SBValueList.
887    print("Frame registers (size of register set = %d):" % registerSet.GetSize(
888    ), file=output)
889    for value in registerSet:
890        #print >> output, value
891        print("%s (number of children = %d):" % (
892            value.GetName(), value.GetNumChildren()), file=output)
893        for child in value:
894            print("Name: %s, Value: %s" % (
895                child.GetName(), child.GetValue()), file=output)
896
897    if string_buffer:
898        return output.getvalue()
899
900
901def get_registers(frame, kind):
902    """Returns the registers given the frame and the kind of registers desired.
903
904    Returns None if there's no such kind.
905    """
906    registerSet = frame.GetRegisters()  # Return type of SBValueList.
907    for value in registerSet:
908        if kind.lower() in value.GetName().lower():
909            return value
910
911    return None
912
913
914def get_GPRs(frame):
915    """Returns the general purpose registers of the frame as an SBValue.
916
917    The returned SBValue object is iterable.  An example:
918        ...
919        from lldbutil import get_GPRs
920        regs = get_GPRs(frame)
921        for reg in regs:
922            print "%s => %s" % (reg.GetName(), reg.GetValue())
923        ...
924    """
925    return get_registers(frame, "general purpose")
926
927
928def get_FPRs(frame):
929    """Returns the floating point registers of the frame as an SBValue.
930
931    The returned SBValue object is iterable.  An example:
932        ...
933        from lldbutil import get_FPRs
934        regs = get_FPRs(frame)
935        for reg in regs:
936            print "%s => %s" % (reg.GetName(), reg.GetValue())
937        ...
938    """
939    return get_registers(frame, "floating point")
940
941
942def get_ESRs(frame):
943    """Returns the exception state registers of the frame as an SBValue.
944
945    The returned SBValue object is iterable.  An example:
946        ...
947        from lldbutil import get_ESRs
948        regs = get_ESRs(frame)
949        for reg in regs:
950            print "%s => %s" % (reg.GetName(), reg.GetValue())
951        ...
952    """
953    return get_registers(frame, "exception state")
954
955# ======================================
956# Utility classes/functions for SBValues
957# ======================================
958
959
960class BasicFormatter(object):
961    """The basic formatter inspects the value object and prints the value."""
962
963    def format(self, value, buffer=None, indent=0):
964        if not buffer:
965            output = io.StringIO()
966        else:
967            output = buffer
968        # If there is a summary, it suffices.
969        val = value.GetSummary()
970        # Otherwise, get the value.
971        if val is None:
972            val = value.GetValue()
973        if val is None and value.GetNumChildren() > 0:
974            val = "%s (location)" % value.GetLocation()
975        print("{indentation}({type}) {name} = {value}".format(
976            indentation=' ' * indent,
977            type=value.GetTypeName(),
978            name=value.GetName(),
979            value=val), file=output)
980        return output.getvalue()
981
982
983class ChildVisitingFormatter(BasicFormatter):
984    """The child visiting formatter prints the value and its immediate children.
985
986    The constructor takes a keyword arg: indent_child, which defaults to 2.
987    """
988
989    def __init__(self, indent_child=2):
990        """Default indentation of 2 SPC's for the children."""
991        self.cindent = indent_child
992
993    def format(self, value, buffer=None):
994        if not buffer:
995            output = io.StringIO()
996        else:
997            output = buffer
998
999        BasicFormatter.format(self, value, buffer=output)
1000        for child in value:
1001            BasicFormatter.format(
1002                self, child, buffer=output, indent=self.cindent)
1003
1004        return output.getvalue()
1005
1006
1007class RecursiveDecentFormatter(BasicFormatter):
1008    """The recursive decent formatter prints the value and the decendents.
1009
1010    The constructor takes two keyword args: indent_level, which defaults to 0,
1011    and indent_child, which defaults to 2.  The current indentation level is
1012    determined by indent_level, while the immediate children has an additional
1013    indentation by inden_child.
1014    """
1015
1016    def __init__(self, indent_level=0, indent_child=2):
1017        self.lindent = indent_level
1018        self.cindent = indent_child
1019
1020    def format(self, value, buffer=None):
1021        if not buffer:
1022            output = io.StringIO()
1023        else:
1024            output = buffer
1025
1026        BasicFormatter.format(self, value, buffer=output, indent=self.lindent)
1027        new_indent = self.lindent + self.cindent
1028        for child in value:
1029            if child.GetSummary() is not None:
1030                BasicFormatter.format(
1031                    self, child, buffer=output, indent=new_indent)
1032            else:
1033                if child.GetNumChildren() > 0:
1034                    rdf = RecursiveDecentFormatter(indent_level=new_indent)
1035                    rdf.format(child, buffer=output)
1036                else:
1037                    BasicFormatter.format(
1038                        self, child, buffer=output, indent=new_indent)
1039
1040        return output.getvalue()
1041