1"""
2This LLDB module contains miscellaneous utilities.
3Some of the test suite takes advantage of the utility functions defined here.
4They can also be useful for general purpose lldb scripting.
5"""
6
7from __future__ import print_function
8from __future__ import absolute_import
9
10# System modules
11import errno
12import os
13import re
14import sys
15import subprocess
16
17# Third-party modules
18from six import StringIO as SixStringIO
19import six
20
21# LLDB modules
22import lldb
23from . import lldbtest_config
24from . import configuration
25
26# How often failed simulator process launches are retried.
27SIMULATOR_RETRY = 3
28
29# ===================================================
30# Utilities for locating/checking executable programs
31# ===================================================
32
33def is_exe(fpath):
34    """Returns True if fpath is an executable."""
35    return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
36
37
38def which(program):
39    """Returns the full path to a program; None otherwise."""
40    fpath, fname = os.path.split(program)
41    if fpath:
42        if is_exe(program):
43            return program
44    else:
45        for path in os.environ["PATH"].split(os.pathsep):
46            exe_file = os.path.join(path, program)
47            if is_exe(exe_file):
48                return exe_file
49    return None
50
51def mkdir_p(path):
52    try:
53        os.makedirs(path)
54    except OSError as e:
55        if e.errno != errno.EEXIST:
56            raise
57    if not os.path.isdir(path):
58        raise OSError(errno.ENOTDIR, "%s is not a directory"%path)
59
60
61# ============================
62# Dealing with SDK and triples
63# ============================
64
65def get_xcode_sdk(os, env):
66    # Respect --apple-sdk <path> if it's specified. If the SDK is simply
67    # mounted from some disk image, and not actually installed, this is the
68    # only way to use it.
69    if configuration.apple_sdk:
70        return configuration.apple_sdk
71    if os == "ios":
72        if env == "simulator":
73            return "iphonesimulator"
74        if env == "macabi":
75            return "macosx"
76        return "iphoneos"
77    elif os == "tvos":
78        if env == "simulator":
79            return "appletvsimulator"
80        return "appletvos"
81    elif os == "watchos":
82        if env == "simulator":
83            return "watchsimulator"
84        return "watchos"
85    return os
86
87
88def get_xcode_sdk_version(sdk):
89    return subprocess.check_output(
90        ['xcrun', '--sdk', sdk, '--show-sdk-version']).rstrip().decode('utf-8')
91
92
93def get_xcode_sdk_root(sdk):
94    return subprocess.check_output(['xcrun', '--sdk', sdk, '--show-sdk-path'
95                                    ]).rstrip().decode('utf-8')
96
97
98def get_xcode_clang(sdk):
99    return subprocess.check_output(['xcrun', '-sdk', sdk, '-f', 'clang'
100                                    ]).rstrip().decode("utf-8")
101
102
103# ===================================================
104# Disassembly for an SBFunction or an SBSymbol object
105# ===================================================
106
107
108def disassemble(target, function_or_symbol):
109    """Disassemble the function or symbol given a target.
110
111    It returns the disassembly content in a string object.
112    """
113    buf = SixStringIO()
114    insts = function_or_symbol.GetInstructions(target)
115    for i in insts:
116        print(i, file=buf)
117    return buf.getvalue()
118
119# ==========================================================
120# Integer (byte size 1, 2, 4, and 8) to bytearray conversion
121# ==========================================================
122
123
124def int_to_bytearray(val, bytesize):
125    """Utility function to convert an integer into a bytearray.
126
127    It returns the bytearray in the little endian format.  It is easy to get the
128    big endian format, just do ba.reverse() on the returned object.
129    """
130    import struct
131
132    if bytesize == 1:
133        return bytearray([val])
134
135    # Little endian followed by a format character.
136    template = "<%c"
137    if bytesize == 2:
138        fmt = template % 'h'
139    elif bytesize == 4:
140        fmt = template % 'i'
141    elif bytesize == 4:
142        fmt = template % 'q'
143    else:
144        return None
145
146    packed = struct.pack(fmt, val)
147    return bytearray(packed)
148
149
150def bytearray_to_int(bytes, bytesize):
151    """Utility function to convert a bytearray into an integer.
152
153    It interprets the bytearray in the little endian format. For a big endian
154    bytearray, just do ba.reverse() on the object before passing it in.
155    """
156    import struct
157
158    if bytesize == 1:
159        return bytes[0]
160
161    # Little endian followed by a format character.
162    template = "<%c"
163    if bytesize == 2:
164        fmt = template % 'h'
165    elif bytesize == 4:
166        fmt = template % 'i'
167    elif bytesize == 4:
168        fmt = template % 'q'
169    else:
170        return None
171
172    unpacked = struct.unpack_from(fmt, bytes)
173    return unpacked[0]
174
175
176# ==============================================================
177# Get the description of an lldb object or None if not available
178# ==============================================================
179def get_description(obj, option=None):
180    """Calls lldb_obj.GetDescription() and returns a string, or None.
181
182    For SBTarget, SBBreakpointLocation, and SBWatchpoint lldb objects, an extra
183    option can be passed in to describe the detailed level of description
184    desired:
185        o lldb.eDescriptionLevelBrief
186        o lldb.eDescriptionLevelFull
187        o lldb.eDescriptionLevelVerbose
188    """
189    method = getattr(obj, 'GetDescription')
190    if not method:
191        return None
192    tuple = (lldb.SBTarget, lldb.SBBreakpointLocation, lldb.SBWatchpoint)
193    if isinstance(obj, tuple):
194        if option is None:
195            option = lldb.eDescriptionLevelBrief
196
197    stream = lldb.SBStream()
198    if option is None:
199        success = method(stream)
200    else:
201        success = method(stream, option)
202    if not success:
203        return None
204    return stream.GetData()
205
206
207# =================================================
208# Convert some enum value to its string counterpart
209# =================================================
210
211def state_type_to_str(enum):
212    """Returns the stateType string given an enum."""
213    if enum == lldb.eStateInvalid:
214        return "invalid"
215    elif enum == lldb.eStateUnloaded:
216        return "unloaded"
217    elif enum == lldb.eStateConnected:
218        return "connected"
219    elif enum == lldb.eStateAttaching:
220        return "attaching"
221    elif enum == lldb.eStateLaunching:
222        return "launching"
223    elif enum == lldb.eStateStopped:
224        return "stopped"
225    elif enum == lldb.eStateRunning:
226        return "running"
227    elif enum == lldb.eStateStepping:
228        return "stepping"
229    elif enum == lldb.eStateCrashed:
230        return "crashed"
231    elif enum == lldb.eStateDetached:
232        return "detached"
233    elif enum == lldb.eStateExited:
234        return "exited"
235    elif enum == lldb.eStateSuspended:
236        return "suspended"
237    else:
238        raise Exception("Unknown StateType enum")
239
240
241def stop_reason_to_str(enum):
242    """Returns the stopReason string given an enum."""
243    if enum == lldb.eStopReasonInvalid:
244        return "invalid"
245    elif enum == lldb.eStopReasonNone:
246        return "none"
247    elif enum == lldb.eStopReasonTrace:
248        return "trace"
249    elif enum == lldb.eStopReasonBreakpoint:
250        return "breakpoint"
251    elif enum == lldb.eStopReasonWatchpoint:
252        return "watchpoint"
253    elif enum == lldb.eStopReasonExec:
254        return "exec"
255    elif enum == lldb.eStopReasonFork:
256        return "fork"
257    elif enum == lldb.eStopReasonVFork:
258        return "vfork"
259    elif enum == lldb.eStopReasonVForkDone:
260        return "vforkdone"
261    elif enum == lldb.eStopReasonSignal:
262        return "signal"
263    elif enum == lldb.eStopReasonException:
264        return "exception"
265    elif enum == lldb.eStopReasonPlanComplete:
266        return "plancomplete"
267    elif enum == lldb.eStopReasonThreadExiting:
268        return "threadexiting"
269    else:
270        raise Exception("Unknown StopReason enum")
271
272
273def symbol_type_to_str(enum):
274    """Returns the symbolType string given an enum."""
275    if enum == lldb.eSymbolTypeInvalid:
276        return "invalid"
277    elif enum == lldb.eSymbolTypeAbsolute:
278        return "absolute"
279    elif enum == lldb.eSymbolTypeCode:
280        return "code"
281    elif enum == lldb.eSymbolTypeData:
282        return "data"
283    elif enum == lldb.eSymbolTypeTrampoline:
284        return "trampoline"
285    elif enum == lldb.eSymbolTypeRuntime:
286        return "runtime"
287    elif enum == lldb.eSymbolTypeException:
288        return "exception"
289    elif enum == lldb.eSymbolTypeSourceFile:
290        return "sourcefile"
291    elif enum == lldb.eSymbolTypeHeaderFile:
292        return "headerfile"
293    elif enum == lldb.eSymbolTypeObjectFile:
294        return "objectfile"
295    elif enum == lldb.eSymbolTypeCommonBlock:
296        return "commonblock"
297    elif enum == lldb.eSymbolTypeBlock:
298        return "block"
299    elif enum == lldb.eSymbolTypeLocal:
300        return "local"
301    elif enum == lldb.eSymbolTypeParam:
302        return "param"
303    elif enum == lldb.eSymbolTypeVariable:
304        return "variable"
305    elif enum == lldb.eSymbolTypeVariableType:
306        return "variabletype"
307    elif enum == lldb.eSymbolTypeLineEntry:
308        return "lineentry"
309    elif enum == lldb.eSymbolTypeLineHeader:
310        return "lineheader"
311    elif enum == lldb.eSymbolTypeScopeBegin:
312        return "scopebegin"
313    elif enum == lldb.eSymbolTypeScopeEnd:
314        return "scopeend"
315    elif enum == lldb.eSymbolTypeAdditional:
316        return "additional"
317    elif enum == lldb.eSymbolTypeCompiler:
318        return "compiler"
319    elif enum == lldb.eSymbolTypeInstrumentation:
320        return "instrumentation"
321    elif enum == lldb.eSymbolTypeUndefined:
322        return "undefined"
323
324
325def value_type_to_str(enum):
326    """Returns the valueType string given an enum."""
327    if enum == lldb.eValueTypeInvalid:
328        return "invalid"
329    elif enum == lldb.eValueTypeVariableGlobal:
330        return "global_variable"
331    elif enum == lldb.eValueTypeVariableStatic:
332        return "static_variable"
333    elif enum == lldb.eValueTypeVariableArgument:
334        return "argument_variable"
335    elif enum == lldb.eValueTypeVariableLocal:
336        return "local_variable"
337    elif enum == lldb.eValueTypeRegister:
338        return "register"
339    elif enum == lldb.eValueTypeRegisterSet:
340        return "register_set"
341    elif enum == lldb.eValueTypeConstResult:
342        return "constant_result"
343    else:
344        raise Exception("Unknown ValueType enum")
345
346
347# ==================================================
348# Get stopped threads due to each stop reason.
349# ==================================================
350
351def sort_stopped_threads(process,
352                         breakpoint_threads=None,
353                         crashed_threads=None,
354                         watchpoint_threads=None,
355                         signal_threads=None,
356                         exiting_threads=None,
357                         other_threads=None):
358    """ Fills array *_threads with threads stopped for the corresponding stop
359        reason.
360    """
361    for lst in [breakpoint_threads,
362                watchpoint_threads,
363                signal_threads,
364                exiting_threads,
365                other_threads]:
366        if lst is not None:
367            lst[:] = []
368
369    for thread in process:
370        dispatched = False
371        for (reason, list) in [(lldb.eStopReasonBreakpoint, breakpoint_threads),
372                               (lldb.eStopReasonException, crashed_threads),
373                               (lldb.eStopReasonWatchpoint, watchpoint_threads),
374                               (lldb.eStopReasonSignal, signal_threads),
375                               (lldb.eStopReasonThreadExiting, exiting_threads),
376                               (None, other_threads)]:
377            if not dispatched and list is not None:
378                if thread.GetStopReason() == reason or reason is None:
379                    list.append(thread)
380                    dispatched = True
381
382# ==================================================
383# Utility functions for setting breakpoints
384# ==================================================
385
386def run_break_set_by_script(
387        test,
388        class_name,
389        extra_options=None,
390        num_expected_locations=1):
391    """Set a scripted breakpoint.  Check that it got the right number of locations."""
392    test.assertTrue(class_name is not None, "Must pass in a class name.")
393    command = "breakpoint set -P " + class_name
394    if extra_options is not None:
395        command += " " + extra_options
396
397    break_results = run_break_set_command(test, command)
398    check_breakpoint_result(test, break_results, num_locations=num_expected_locations)
399    return get_bpno_from_match(break_results)
400
401def run_break_set_by_file_and_line(
402        test,
403        file_name,
404        line_number,
405        extra_options=None,
406        num_expected_locations=1,
407        loc_exact=False,
408        module_name=None):
409    """Set a breakpoint by file and line, returning the breakpoint number.
410
411    If extra_options is not None, then we append it to the breakpoint set command.
412
413    If num_expected_locations is -1, we check that we got AT LEAST one location. If num_expected_locations is -2, we don't
414    check the actual number at all. Otherwise, we check that num_expected_locations equals the number of locations.
415
416    If loc_exact is true, we check that there is one location, and that location must be at the input file and line number."""
417
418    if file_name is None:
419        command = 'breakpoint set -l %d' % (line_number)
420    else:
421        command = 'breakpoint set -f "%s" -l %d' % (file_name, line_number)
422
423    if module_name:
424        command += " --shlib '%s'" % (module_name)
425
426    if extra_options:
427        command += " " + extra_options
428
429    break_results = run_break_set_command(test, command)
430
431    if num_expected_locations == 1 and loc_exact:
432        check_breakpoint_result(
433            test,
434            break_results,
435            num_locations=num_expected_locations,
436            file_name=file_name,
437            line_number=line_number,
438            module_name=module_name)
439    else:
440        check_breakpoint_result(
441            test,
442            break_results,
443            num_locations=num_expected_locations)
444
445    return get_bpno_from_match(break_results)
446
447
448def run_break_set_by_symbol(
449        test,
450        symbol,
451        extra_options=None,
452        num_expected_locations=-1,
453        sym_exact=False,
454        module_name=None):
455    """Set a breakpoint by symbol name.  Common options are the same as run_break_set_by_file_and_line.
456
457    If sym_exact is true, then the output symbol must match the input exactly, otherwise we do a substring match."""
458    command = 'breakpoint set -n "%s"' % (symbol)
459
460    if module_name:
461        command += " --shlib '%s'" % (module_name)
462
463    if extra_options:
464        command += " " + extra_options
465
466    break_results = run_break_set_command(test, command)
467
468    if num_expected_locations == 1 and sym_exact:
469        check_breakpoint_result(
470            test,
471            break_results,
472            num_locations=num_expected_locations,
473            symbol_name=symbol,
474            module_name=module_name)
475    else:
476        check_breakpoint_result(
477            test,
478            break_results,
479            num_locations=num_expected_locations)
480
481    return get_bpno_from_match(break_results)
482
483
484def run_break_set_by_selector(
485        test,
486        selector,
487        extra_options=None,
488        num_expected_locations=-1,
489        module_name=None):
490    """Set a breakpoint by selector.  Common options are the same as run_break_set_by_file_and_line."""
491
492    command = 'breakpoint set -S "%s"' % (selector)
493
494    if module_name:
495        command += ' --shlib "%s"' % (module_name)
496
497    if extra_options:
498        command += " " + extra_options
499
500    break_results = run_break_set_command(test, command)
501
502    if num_expected_locations == 1:
503        check_breakpoint_result(
504            test,
505            break_results,
506            num_locations=num_expected_locations,
507            symbol_name=selector,
508            symbol_match_exact=False,
509            module_name=module_name)
510    else:
511        check_breakpoint_result(
512            test,
513            break_results,
514            num_locations=num_expected_locations)
515
516    return get_bpno_from_match(break_results)
517
518
519def run_break_set_by_regexp(
520        test,
521        regexp,
522        extra_options=None,
523        num_expected_locations=-1):
524    """Set a breakpoint by regular expression match on symbol name.  Common options are the same as run_break_set_by_file_and_line."""
525
526    command = 'breakpoint set -r "%s"' % (regexp)
527    if extra_options:
528        command += " " + extra_options
529
530    break_results = run_break_set_command(test, command)
531
532    check_breakpoint_result(
533        test,
534        break_results,
535        num_locations=num_expected_locations)
536
537    return get_bpno_from_match(break_results)
538
539
540def run_break_set_by_source_regexp(
541        test,
542        regexp,
543        extra_options=None,
544        num_expected_locations=-1):
545    """Set a breakpoint by source regular expression.  Common options are the same as run_break_set_by_file_and_line."""
546    command = 'breakpoint set -p "%s"' % (regexp)
547    if extra_options:
548        command += " " + extra_options
549
550    break_results = run_break_set_command(test, command)
551
552    check_breakpoint_result(
553        test,
554        break_results,
555        num_locations=num_expected_locations)
556
557    return get_bpno_from_match(break_results)
558
559def run_break_set_by_file_colon_line(
560        test,
561        specifier,
562        path,
563        line_number,
564        column_number = 0,
565        extra_options=None,
566        num_expected_locations=-1):
567    command = 'breakpoint set -y "%s"'%(specifier)
568    if extra_options:
569        command += " " + extra_options
570
571    print("About to run: '%s'", command)
572    break_results = run_break_set_command(test, command)
573    check_breakpoint_result(
574        test,
575        break_results,
576        num_locations = num_expected_locations,
577        file_name = path,
578        line_number = line_number,
579        column_number = column_number)
580
581    return get_bpno_from_match(break_results)
582
583def run_break_set_command(test, command):
584    """Run the command passed in - it must be some break set variant - and analyze the result.
585    Returns a dictionary of information gleaned from the command-line results.
586    Will assert if the breakpoint setting fails altogether.
587
588    Dictionary will contain:
589        bpno          - breakpoint of the newly created breakpoint, -1 on error.
590        num_locations - number of locations set for the breakpoint.
591
592    If there is only one location, the dictionary MAY contain:
593        file          - source file name
594        line_no       - source line number
595        column        - source column number
596        symbol        - symbol name
597        inline_symbol - inlined symbol name
598        offset        - offset from the original symbol
599        module        - module
600        address       - address at which the breakpoint was set."""
601
602    patterns = [
603        r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>[0-9]+) locations\.$",
604        r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>no) locations \(pending\)\.",
605        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]+)(?P<column>(:[0-9]+)?), address = (?P<address>0x[0-9a-fA-F]+)$",
606        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]+)$"]
607    match_object = test.match(command, patterns)
608    break_results = match_object.groupdict()
609
610    # We always insert the breakpoint number, setting it to -1 if we couldn't find it
611    # Also, make sure it gets stored as an integer.
612    if not 'bpno' in break_results:
613        break_results['bpno'] = -1
614    else:
615        break_results['bpno'] = int(break_results['bpno'])
616
617    # We always insert the number of locations
618    # If ONE location is set for the breakpoint, then the output doesn't mention locations, but it has to be 1...
619    # We also make sure it is an integer.
620
621    if not 'num_locations' in break_results:
622        num_locations = 1
623    else:
624        num_locations = break_results['num_locations']
625        if num_locations == 'no':
626            num_locations = 0
627        else:
628            num_locations = int(break_results['num_locations'])
629
630    break_results['num_locations'] = num_locations
631
632    if 'line_no' in break_results:
633        break_results['line_no'] = int(break_results['line_no'])
634
635    return break_results
636
637
638def get_bpno_from_match(break_results):
639    return int(break_results['bpno'])
640
641
642def check_breakpoint_result(
643        test,
644        break_results,
645        file_name=None,
646        line_number=-1,
647        column_number=0,
648        symbol_name=None,
649        symbol_match_exact=True,
650        module_name=None,
651        offset=-1,
652        num_locations=-1):
653
654    out_num_locations = break_results['num_locations']
655
656    if num_locations == -1:
657        test.assertTrue(out_num_locations > 0,
658                        "Expecting one or more locations, got none.")
659    elif num_locations != -2:
660        test.assertTrue(
661            num_locations == out_num_locations,
662            "Expecting %d locations, got %d." %
663            (num_locations,
664             out_num_locations))
665
666    if file_name:
667        out_file_name = ""
668        if 'file' in break_results:
669            out_file_name = break_results['file']
670        test.assertTrue(
671            file_name.endswith(out_file_name),
672            "Breakpoint file name '%s' doesn't match resultant name '%s'." %
673            (file_name,
674             out_file_name))
675
676    if line_number != -1:
677        out_line_number = -1
678        if 'line_no' in break_results:
679            out_line_number = break_results['line_no']
680
681        test.assertTrue(
682            line_number == out_line_number,
683            "Breakpoint line number %s doesn't match resultant line %s." %
684            (line_number,
685             out_line_number))
686
687    if column_number != 0:
688        out_column_number = 0
689        if 'column' in break_results:
690            out_column_number = break_results['column']
691
692        test.assertTrue(
693            column_number == out_column_number,
694            "Breakpoint column number %s doesn't match resultant column %s." %
695            (column_number,
696             out_column_number))
697
698    if symbol_name:
699        out_symbol_name = ""
700        # Look first for the inlined symbol name, otherwise use the symbol
701        # name:
702        if 'inline_symbol' in break_results and break_results['inline_symbol']:
703            out_symbol_name = break_results['inline_symbol']
704        elif 'symbol' in break_results:
705            out_symbol_name = break_results['symbol']
706
707        if symbol_match_exact:
708            test.assertTrue(
709                symbol_name == out_symbol_name,
710                "Symbol name '%s' doesn't match resultant symbol '%s'." %
711                (symbol_name,
712                 out_symbol_name))
713        else:
714            test.assertTrue(
715                out_symbol_name.find(symbol_name) != -
716                1,
717                "Symbol name '%s' isn't in resultant symbol '%s'." %
718                (symbol_name,
719                 out_symbol_name))
720
721    if module_name:
722        out_module_name = None
723        if 'module' in break_results:
724            out_module_name = break_results['module']
725
726        test.assertTrue(
727            module_name.find(out_module_name) != -
728            1,
729            "Symbol module name '%s' isn't in expected module name '%s'." %
730            (out_module_name,
731             module_name))
732
733def check_breakpoint(
734            test,
735            bpno,
736            expected_locations = None,
737            expected_resolved_count = None,
738            expected_hit_count = None,
739            location_id = None,
740            expected_location_resolved = True,
741            expected_location_hit_count = None):
742    """
743    Test breakpoint or breakpoint location.
744    Breakpoint resolved count is always checked. If not specified the assumption is that all locations
745    should be resolved.
746    To test a breakpoint location, breakpoint number (bpno) and location_id must be set. In this case
747    the resolved count for a breakpoint is not tested by default. The location is expected to be resolved,
748    unless expected_location_resolved is set to False.
749    test - test context
750    bpno - breakpoint number to test
751    expected_locations - expected number of locations for this breakpoint. If 'None' this parameter is not tested.
752    expected_resolved_count - expected resolved locations number for the breakpoint.  If 'None' - all locations should be resolved.
753    expected_hit_count - expected hit count for this breakpoint. If 'None' this parameter is not tested.
754    location_id - If not 'None' sets the location ID for the breakpoint to test.
755    expected_location_resolved - Extected resolved status for the location_id (True/False). Default - True.
756    expected_location_hit_count - Expected hit count for the breakpoint at location_id. Must be set if the location_id parameter is set.
757    """
758
759    if isinstance(test.target, lldb.SBTarget):
760        target = test.target
761    else:
762        target = test.target()
763    bkpt = target.FindBreakpointByID(bpno)
764
765    test.assertTrue(bkpt.IsValid(), "Breakpoint is not valid.")
766
767    if expected_locations is not None:
768        test.assertEquals(expected_locations, bkpt.GetNumLocations())
769
770    if expected_resolved_count is not None:
771        test.assertEquals(expected_resolved_count, bkpt.GetNumResolvedLocations())
772    else:
773        expected_resolved_count = bkpt.GetNumLocations()
774        if location_id is None:
775            test.assertEquals(expected_resolved_count, bkpt.GetNumResolvedLocations())
776
777    if expected_hit_count is not None:
778        test.assertEquals(expected_hit_count, bkpt.GetHitCount())
779
780    if location_id is not None:
781        loc_bkpt = bkpt.FindLocationByID(location_id)
782        test.assertTrue(loc_bkpt.IsValid(), "Breakpoint location is not valid.")
783        test.assertEquals(loc_bkpt.IsResolved(), expected_location_resolved)
784        if expected_location_hit_count is not None:
785            test.assertEquals(expected_location_hit_count, loc_bkpt.GetHitCount())
786
787
788
789# ==================================================
790# Utility functions related to Threads and Processes
791# ==================================================
792
793
794def get_stopped_threads(process, reason):
795    """Returns the thread(s) with the specified stop reason in a list.
796
797    The list can be empty if no such thread exists.
798    """
799    threads = []
800    for t in process:
801        if t.GetStopReason() == reason:
802            threads.append(t)
803    return threads
804
805
806def get_stopped_thread(process, reason):
807    """A convenience function which returns the first thread with the given stop
808    reason or None.
809
810    Example usages:
811
812    1. Get the stopped thread due to a breakpoint condition
813
814    ...
815        from lldbutil import get_stopped_thread
816        thread = get_stopped_thread(process, lldb.eStopReasonPlanComplete)
817        self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition")
818    ...
819
820    2. Get the thread stopped due to a breakpoint
821
822    ...
823        from lldbutil import get_stopped_thread
824        thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
825        self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint")
826    ...
827
828    """
829    threads = get_stopped_threads(process, reason)
830    if len(threads) == 0:
831        return None
832    return threads[0]
833
834
835def get_threads_stopped_at_breakpoint_id(process, bpid):
836    """ For a stopped process returns the thread stopped at the breakpoint passed in bkpt"""
837    stopped_threads = []
838    threads = []
839
840    stopped_threads = get_stopped_threads(process, lldb.eStopReasonBreakpoint)
841
842    if len(stopped_threads) == 0:
843        return threads
844
845    for thread in stopped_threads:
846        # Make sure we've hit our breakpoint...
847        break_id = thread.GetStopReasonDataAtIndex(0)
848        if break_id == bpid:
849            threads.append(thread)
850
851    return threads
852
853
854def get_threads_stopped_at_breakpoint(process, bkpt):
855    return get_threads_stopped_at_breakpoint_id(process, bkpt.GetID())
856
857
858def get_one_thread_stopped_at_breakpoint_id(
859        process, bpid, require_exactly_one=True):
860    threads = get_threads_stopped_at_breakpoint_id(process, bpid)
861    if len(threads) == 0:
862        return None
863    if require_exactly_one and len(threads) != 1:
864        return None
865
866    return threads[0]
867
868
869def get_one_thread_stopped_at_breakpoint(
870        process, bkpt, require_exactly_one=True):
871    return get_one_thread_stopped_at_breakpoint_id(
872        process, bkpt.GetID(), require_exactly_one)
873
874
875def is_thread_crashed(test, thread):
876    """In the test suite we dereference a null pointer to simulate a crash. The way this is
877    reported depends on the platform."""
878    if test.platformIsDarwin():
879        return thread.GetStopReason(
880        ) == lldb.eStopReasonException and "EXC_BAD_ACCESS" in thread.GetStopDescription(100)
881    elif test.getPlatform() == "linux":
882        return thread.GetStopReason() == lldb.eStopReasonSignal and thread.GetStopReasonDataAtIndex(
883            0) == thread.GetProcess().GetUnixSignals().GetSignalNumberFromName("SIGSEGV")
884    elif test.getPlatform() == "windows":
885        return "Exception 0xc0000005" in thread.GetStopDescription(200)
886    else:
887        return "invalid address" in thread.GetStopDescription(100)
888
889
890def get_crashed_threads(test, process):
891    threads = []
892    if process.GetState() != lldb.eStateStopped:
893        return threads
894    for thread in process:
895        if is_thread_crashed(test, thread):
896            threads.append(thread)
897    return threads
898
899# Helper functions for run_to_{source,name}_breakpoint:
900
901def run_to_breakpoint_make_target(test, exe_name = "a.out", in_cwd = True):
902    if in_cwd:
903        exe = test.getBuildArtifact(exe_name)
904
905    # Create the target
906    target = test.dbg.CreateTarget(exe)
907    test.assertTrue(target, "Target: %s is not valid."%(exe_name))
908
909    # Set environment variables for the inferior.
910    if lldbtest_config.inferior_env:
911        test.runCmd('settings set target.env-vars {}'.format(
912            lldbtest_config.inferior_env))
913
914    return target
915
916def run_to_breakpoint_do_run(test, target, bkpt, launch_info = None,
917                             only_one_thread = True, extra_images = None):
918
919    # Launch the process, and do not stop at the entry point.
920    if not launch_info:
921        launch_info = target.GetLaunchInfo()
922        launch_info.SetWorkingDirectory(test.get_process_working_directory())
923
924    if extra_images:
925        environ = test.registerSharedLibrariesWithTarget(target, extra_images)
926        launch_info.SetEnvironmentEntries(environ, True)
927
928    error = lldb.SBError()
929    process = target.Launch(launch_info, error)
930
931    # Unfortunate workaround for the iPhone simulator.
932    retry = SIMULATOR_RETRY
933    while (retry and error.Fail() and error.GetCString() and
934           "Unable to boot the Simulator" in error.GetCString()):
935        retry -= 1
936        print("** Simulator is unresponsive. Retrying %d more time(s)"%retry)
937        import time
938        time.sleep(60)
939        error = lldb.SBError()
940        process = target.Launch(launch_info, error)
941
942    test.assertTrue(process,
943                    "Could not create a valid process for %s: %s" %
944                    (target.GetExecutable().GetFilename(), error.GetCString()))
945    test.assertFalse(error.Fail(),
946                     "Process launch failed: %s" % (error.GetCString()))
947
948    test.assertEqual(process.GetState(), lldb.eStateStopped)
949
950    # Frame #0 should be at our breakpoint.
951    threads = get_threads_stopped_at_breakpoint(
952                process, bkpt)
953
954    num_threads = len(threads)
955    if only_one_thread:
956        test.assertEqual(num_threads, 1, "Expected 1 thread to stop at breakpoint, %d did."%(num_threads))
957    else:
958        test.assertGreater(num_threads, 0, "No threads stopped at breakpoint")
959
960    thread = threads[0]
961    return (target, process, thread, bkpt)
962
963def run_to_name_breakpoint (test, bkpt_name, launch_info = None,
964                            exe_name = "a.out",
965                            bkpt_module = None,
966                            in_cwd = True,
967                            only_one_thread = True,
968                            extra_images = None):
969    """Start up a target, using exe_name as the executable, and run it to
970       a breakpoint set by name on bkpt_name restricted to bkpt_module.
971
972       If you want to pass in launch arguments or environment
973       variables, you can optionally pass in an SBLaunchInfo.  If you
974       do that, remember to set the working directory as well.
975
976       If your executable isn't called a.out, you can pass that in.
977       And if your executable isn't in the CWD, pass in the absolute
978       path to the executable in exe_name, and set in_cwd to False.
979
980       If you need to restrict the breakpoint to a particular module,
981       pass the module name (a string not a FileSpec) in bkpt_module.  If
982       nothing is passed in setting will be unrestricted.
983
984       If the target isn't valid, the breakpoint isn't found, or hit, the
985       function will cause a testsuite failure.
986
987       If successful it returns a tuple with the target process and
988       thread that hit the breakpoint, and the breakpoint that we set
989       for you.
990
991       If only_one_thread is true, we require that there be only one
992       thread stopped at the breakpoint.  Otherwise we only require one
993       or more threads stop there.  If there are more than one, we return
994       the first thread that stopped.
995    """
996
997    target = run_to_breakpoint_make_target(test, exe_name, in_cwd)
998
999    breakpoint = target.BreakpointCreateByName(bkpt_name, bkpt_module)
1000
1001
1002    test.assertTrue(breakpoint.GetNumLocations() > 0,
1003                    "No locations found for name breakpoint: '%s'."%(bkpt_name))
1004    return run_to_breakpoint_do_run(test, target, breakpoint, launch_info,
1005                                    only_one_thread, extra_images)
1006
1007def run_to_source_breakpoint(test, bkpt_pattern, source_spec,
1008                             launch_info = None, exe_name = "a.out",
1009                             bkpt_module = None,
1010                             in_cwd = True,
1011                             only_one_thread = True,
1012                             extra_images = None,
1013                             has_locations_before_run = True):
1014    """Start up a target, using exe_name as the executable, and run it to
1015       a breakpoint set by source regex bkpt_pattern.
1016
1017       The rest of the behavior is the same as run_to_name_breakpoint.
1018    """
1019
1020    target = run_to_breakpoint_make_target(test, exe_name, in_cwd)
1021    # Set the breakpoints
1022    breakpoint = target.BreakpointCreateBySourceRegex(
1023            bkpt_pattern, source_spec, bkpt_module)
1024    if has_locations_before_run:
1025        test.assertTrue(breakpoint.GetNumLocations() > 0,
1026                        'No locations found for source breakpoint: "%s", file: "%s", dir: "%s"'
1027                        %(bkpt_pattern, source_spec.GetFilename(), source_spec.GetDirectory()))
1028    return run_to_breakpoint_do_run(test, target, breakpoint, launch_info,
1029                                    only_one_thread, extra_images)
1030
1031def run_to_line_breakpoint(test, source_spec, line_number, column = 0,
1032                           launch_info = None, exe_name = "a.out",
1033                           bkpt_module = None,
1034                           in_cwd = True,
1035                           only_one_thread = True,
1036                           extra_images = None):
1037    """Start up a target, using exe_name as the executable, and run it to
1038       a breakpoint set by (source_spec, line_number(, column)).
1039
1040       The rest of the behavior is the same as run_to_name_breakpoint.
1041    """
1042
1043    target = run_to_breakpoint_make_target(test, exe_name, in_cwd)
1044    # Set the breakpoints
1045    breakpoint = target.BreakpointCreateByLocation(
1046        source_spec, line_number, column, 0, lldb.SBFileSpecList())
1047    test.assertTrue(breakpoint.GetNumLocations() > 0,
1048        'No locations found for line breakpoint: "%s:%d(:%d)", dir: "%s"'
1049        %(source_spec.GetFilename(), line_number, column,
1050          source_spec.GetDirectory()))
1051    return run_to_breakpoint_do_run(test, target, breakpoint, launch_info,
1052                                    only_one_thread, extra_images)
1053
1054
1055def continue_to_breakpoint(process, bkpt):
1056    """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
1057    process.Continue()
1058    if process.GetState() != lldb.eStateStopped:
1059        return None
1060    else:
1061        return get_threads_stopped_at_breakpoint(process, bkpt)
1062
1063
1064def get_caller_symbol(thread):
1065    """
1066    Returns the symbol name for the call site of the leaf function.
1067    """
1068    depth = thread.GetNumFrames()
1069    if depth <= 1:
1070        return None
1071    caller = thread.GetFrameAtIndex(1).GetSymbol()
1072    if caller:
1073        return caller.GetName()
1074    else:
1075        return None
1076
1077
1078def get_function_names(thread):
1079    """
1080    Returns a sequence of function names from the stack frames of this thread.
1081    """
1082    def GetFuncName(i):
1083        return thread.GetFrameAtIndex(i).GetFunctionName()
1084
1085    return list(map(GetFuncName, list(range(thread.GetNumFrames()))))
1086
1087
1088def get_symbol_names(thread):
1089    """
1090    Returns a sequence of symbols for this thread.
1091    """
1092    def GetSymbol(i):
1093        return thread.GetFrameAtIndex(i).GetSymbol().GetName()
1094
1095    return list(map(GetSymbol, list(range(thread.GetNumFrames()))))
1096
1097
1098def get_pc_addresses(thread):
1099    """
1100    Returns a sequence of pc addresses for this thread.
1101    """
1102    def GetPCAddress(i):
1103        return thread.GetFrameAtIndex(i).GetPCAddress()
1104
1105    return list(map(GetPCAddress, list(range(thread.GetNumFrames()))))
1106
1107
1108def get_filenames(thread):
1109    """
1110    Returns a sequence of file names from the stack frames of this thread.
1111    """
1112    def GetFilename(i):
1113        return thread.GetFrameAtIndex(
1114            i).GetLineEntry().GetFileSpec().GetFilename()
1115
1116    return list(map(GetFilename, list(range(thread.GetNumFrames()))))
1117
1118
1119def get_line_numbers(thread):
1120    """
1121    Returns a sequence of line numbers from the stack frames of this thread.
1122    """
1123    def GetLineNumber(i):
1124        return thread.GetFrameAtIndex(i).GetLineEntry().GetLine()
1125
1126    return list(map(GetLineNumber, list(range(thread.GetNumFrames()))))
1127
1128
1129def get_module_names(thread):
1130    """
1131    Returns a sequence of module names from the stack frames of this thread.
1132    """
1133    def GetModuleName(i):
1134        return thread.GetFrameAtIndex(
1135            i).GetModule().GetFileSpec().GetFilename()
1136
1137    return list(map(GetModuleName, list(range(thread.GetNumFrames()))))
1138
1139
1140def get_stack_frames(thread):
1141    """
1142    Returns a sequence of stack frames for this thread.
1143    """
1144    def GetStackFrame(i):
1145        return thread.GetFrameAtIndex(i)
1146
1147    return list(map(GetStackFrame, list(range(thread.GetNumFrames()))))
1148
1149
1150def print_stacktrace(thread, string_buffer=False):
1151    """Prints a simple stack trace of this thread."""
1152
1153    output = SixStringIO() if string_buffer else sys.stdout
1154    target = thread.GetProcess().GetTarget()
1155
1156    depth = thread.GetNumFrames()
1157
1158    mods = get_module_names(thread)
1159    funcs = get_function_names(thread)
1160    symbols = get_symbol_names(thread)
1161    files = get_filenames(thread)
1162    lines = get_line_numbers(thread)
1163    addrs = get_pc_addresses(thread)
1164
1165    if thread.GetStopReason() != lldb.eStopReasonInvalid:
1166        desc = "stop reason=" + stop_reason_to_str(thread.GetStopReason())
1167    else:
1168        desc = ""
1169    print(
1170        "Stack trace for thread id={0:#x} name={1} queue={2} ".format(
1171            thread.GetThreadID(),
1172            thread.GetName(),
1173            thread.GetQueueName()) + desc,
1174        file=output)
1175
1176    for i in range(depth):
1177        frame = thread.GetFrameAtIndex(i)
1178        function = frame.GetFunction()
1179
1180        load_addr = addrs[i].GetLoadAddress(target)
1181        if not function:
1182            file_addr = addrs[i].GetFileAddress()
1183            start_addr = frame.GetSymbol().GetStartAddress().GetFileAddress()
1184            symbol_offset = file_addr - start_addr
1185            print(
1186                "  frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}".format(
1187                    num=i,
1188                    addr=load_addr,
1189                    mod=mods[i],
1190                    symbol=symbols[i],
1191                    offset=symbol_offset),
1192                file=output)
1193        else:
1194            print(
1195                "  frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format(
1196                    num=i,
1197                    addr=load_addr,
1198                    mod=mods[i],
1199                    func='%s [inlined]' %
1200                    funcs[i] if frame.IsInlined() else funcs[i],
1201                    file=files[i],
1202                    line=lines[i],
1203                    args=get_args_as_string(
1204                        frame,
1205                        showFuncName=False) if not frame.IsInlined() else '()'),
1206                file=output)
1207
1208    if string_buffer:
1209        return output.getvalue()
1210
1211
1212def print_stacktraces(process, string_buffer=False):
1213    """Prints the stack traces of all the threads."""
1214
1215    output = SixStringIO() if string_buffer else sys.stdout
1216
1217    print("Stack traces for " + str(process), file=output)
1218
1219    for thread in process:
1220        print(print_stacktrace(thread, string_buffer=True), file=output)
1221
1222    if string_buffer:
1223        return output.getvalue()
1224
1225
1226def expect_state_changes(test, listener, process, states, timeout=30):
1227    """Listens for state changed events on the listener and makes sure they match what we
1228    expect. Stop-and-restart events (where GetRestartedFromEvent() returns true) are ignored."""
1229
1230    for expected_state in states:
1231        def get_next_event():
1232            event = lldb.SBEvent()
1233            if not listener.WaitForEventForBroadcasterWithType(
1234                    timeout,
1235                    process.GetBroadcaster(),
1236                    lldb.SBProcess.eBroadcastBitStateChanged,
1237                    event):
1238                test.fail(
1239                    "Timed out while waiting for a transition to state %s" %
1240                    lldb.SBDebugger.StateAsCString(expected_state))
1241            return event
1242
1243        event = get_next_event()
1244        while (lldb.SBProcess.GetStateFromEvent(event) == lldb.eStateStopped and
1245                lldb.SBProcess.GetRestartedFromEvent(event)):
1246            # Ignore restarted event and the subsequent running event.
1247            event = get_next_event()
1248            test.assertEqual(
1249                lldb.SBProcess.GetStateFromEvent(event),
1250                lldb.eStateRunning,
1251                "Restarted event followed by a running event")
1252            event = get_next_event()
1253
1254        test.assertEqual(
1255            lldb.SBProcess.GetStateFromEvent(event),
1256            expected_state)
1257
1258def start_listening_from(broadcaster, event_mask):
1259    """Creates a listener for a specific event mask and add it to the source broadcaster."""
1260
1261    listener = lldb.SBListener("lldb.test.listener")
1262    broadcaster.AddListener(listener, event_mask)
1263    return listener
1264
1265def fetch_next_event(test, listener, broadcaster, timeout=10):
1266    """Fetch one event from the listener and return it if it matches the provided broadcaster.
1267    Fails otherwise."""
1268
1269    event = lldb.SBEvent()
1270
1271    if listener.WaitForEvent(timeout, event):
1272        if event.BroadcasterMatchesRef(broadcaster):
1273            return event
1274
1275        test.fail("received event '%s' from unexpected broadcaster '%s'." %
1276                  (event.GetDescription(), event.GetBroadcaster().GetName()))
1277
1278    test.fail("couldn't fetch an event before reaching the timeout.")
1279
1280
1281# ===================================
1282# Utility functions related to Frames
1283# ===================================
1284
1285
1286def get_parent_frame(frame):
1287    """
1288    Returns the parent frame of the input frame object; None if not available.
1289    """
1290    thread = frame.GetThread()
1291    parent_found = False
1292    for f in thread:
1293        if parent_found:
1294            return f
1295        if f.GetFrameID() == frame.GetFrameID():
1296            parent_found = True
1297
1298    # If we reach here, no parent has been found, return None.
1299    return None
1300
1301
1302def get_args_as_string(frame, showFuncName=True):
1303    """
1304    Returns the args of the input frame object as a string.
1305    """
1306    # arguments     => True
1307    # locals        => False
1308    # statics       => False
1309    # in_scope_only => True
1310    vars = frame.GetVariables(True, False, False, True)  # type of SBValueList
1311    args = []  # list of strings
1312    for var in vars:
1313        args.append("(%s)%s=%s" % (var.GetTypeName(),
1314                                   var.GetName(),
1315                                   var.GetValue()))
1316    if frame.GetFunction():
1317        name = frame.GetFunction().GetName()
1318    elif frame.GetSymbol():
1319        name = frame.GetSymbol().GetName()
1320    else:
1321        name = ""
1322    if showFuncName:
1323        return "%s(%s)" % (name, ", ".join(args))
1324    else:
1325        return "(%s)" % (", ".join(args))
1326
1327
1328def print_registers(frame, string_buffer=False):
1329    """Prints all the register sets of the frame."""
1330
1331    output = SixStringIO() if string_buffer else sys.stdout
1332
1333    print("Register sets for " + str(frame), file=output)
1334
1335    registerSet = frame.GetRegisters()  # Return type of SBValueList.
1336    print("Frame registers (size of register set = %d):" %
1337          registerSet.GetSize(), file=output)
1338    for value in registerSet:
1339        #print(value, file=output)
1340        print("%s (number of children = %d):" %
1341              (value.GetName(), value.GetNumChildren()), file=output)
1342        for child in value:
1343            print(
1344                "Name: %s, Value: %s" %
1345                (child.GetName(),
1346                 child.GetValue()),
1347                file=output)
1348
1349    if string_buffer:
1350        return output.getvalue()
1351
1352
1353def get_registers(frame, kind):
1354    """Returns the registers given the frame and the kind of registers desired.
1355
1356    Returns None if there's no such kind.
1357    """
1358    registerSet = frame.GetRegisters()  # Return type of SBValueList.
1359    for value in registerSet:
1360        if kind.lower() in value.GetName().lower():
1361            return value
1362
1363    return None
1364
1365
1366def get_GPRs(frame):
1367    """Returns the general purpose registers of the frame as an SBValue.
1368
1369    The returned SBValue object is iterable.  An example:
1370        ...
1371        from lldbutil import get_GPRs
1372        regs = get_GPRs(frame)
1373        for reg in regs:
1374            print("%s => %s" % (reg.GetName(), reg.GetValue()))
1375        ...
1376    """
1377    return get_registers(frame, "general purpose")
1378
1379
1380def get_FPRs(frame):
1381    """Returns the floating point registers of the frame as an SBValue.
1382
1383    The returned SBValue object is iterable.  An example:
1384        ...
1385        from lldbutil import get_FPRs
1386        regs = get_FPRs(frame)
1387        for reg in regs:
1388            print("%s => %s" % (reg.GetName(), reg.GetValue()))
1389        ...
1390    """
1391    return get_registers(frame, "floating point")
1392
1393
1394def get_ESRs(frame):
1395    """Returns the exception state registers of the frame as an SBValue.
1396
1397    The returned SBValue object is iterable.  An example:
1398        ...
1399        from lldbutil import get_ESRs
1400        regs = get_ESRs(frame)
1401        for reg in regs:
1402            print("%s => %s" % (reg.GetName(), reg.GetValue()))
1403        ...
1404    """
1405    return get_registers(frame, "exception state")
1406
1407# ======================================
1408# Utility classes/functions for SBValues
1409# ======================================
1410
1411
1412class BasicFormatter(object):
1413    """The basic formatter inspects the value object and prints the value."""
1414
1415    def format(self, value, buffer=None, indent=0):
1416        if not buffer:
1417            output = SixStringIO()
1418        else:
1419            output = buffer
1420        # If there is a summary, it suffices.
1421        val = value.GetSummary()
1422        # Otherwise, get the value.
1423        if val is None:
1424            val = value.GetValue()
1425        if val is None and value.GetNumChildren() > 0:
1426            val = "%s (location)" % value.GetLocation()
1427        print("{indentation}({type}) {name} = {value}".format(
1428            indentation=' ' * indent,
1429            type=value.GetTypeName(),
1430            name=value.GetName(),
1431            value=val), file=output)
1432        return output.getvalue()
1433
1434
1435class ChildVisitingFormatter(BasicFormatter):
1436    """The child visiting formatter prints the value and its immediate children.
1437
1438    The constructor takes a keyword arg: indent_child, which defaults to 2.
1439    """
1440
1441    def __init__(self, indent_child=2):
1442        """Default indentation of 2 SPC's for the children."""
1443        self.cindent = indent_child
1444
1445    def format(self, value, buffer=None):
1446        if not buffer:
1447            output = SixStringIO()
1448        else:
1449            output = buffer
1450
1451        BasicFormatter.format(self, value, buffer=output)
1452        for child in value:
1453            BasicFormatter.format(
1454                self, child, buffer=output, indent=self.cindent)
1455
1456        return output.getvalue()
1457
1458
1459class RecursiveDecentFormatter(BasicFormatter):
1460    """The recursive decent formatter prints the value and the decendents.
1461
1462    The constructor takes two keyword args: indent_level, which defaults to 0,
1463    and indent_child, which defaults to 2.  The current indentation level is
1464    determined by indent_level, while the immediate children has an additional
1465    indentation by inden_child.
1466    """
1467
1468    def __init__(self, indent_level=0, indent_child=2):
1469        self.lindent = indent_level
1470        self.cindent = indent_child
1471
1472    def format(self, value, buffer=None):
1473        if not buffer:
1474            output = SixStringIO()
1475        else:
1476            output = buffer
1477
1478        BasicFormatter.format(self, value, buffer=output, indent=self.lindent)
1479        new_indent = self.lindent + self.cindent
1480        for child in value:
1481            if child.GetSummary() is not None:
1482                BasicFormatter.format(
1483                    self, child, buffer=output, indent=new_indent)
1484            else:
1485                if child.GetNumChildren() > 0:
1486                    rdf = RecursiveDecentFormatter(indent_level=new_indent)
1487                    rdf.format(child, buffer=output)
1488                else:
1489                    BasicFormatter.format(
1490                        self, child, buffer=output, indent=new_indent)
1491
1492        return output.getvalue()
1493
1494# ===========================================================
1495# Utility functions for path manipulation on remote platforms
1496# ===========================================================
1497
1498
1499def join_remote_paths(*paths):
1500    # TODO: update with actual platform name for remote windows once it exists
1501    if lldb.remote_platform.GetName() == 'remote-windows':
1502        return os.path.join(*paths).replace(os.path.sep, '\\')
1503    return os.path.join(*paths).replace(os.path.sep, '/')
1504
1505
1506def append_to_process_working_directory(test, *paths):
1507    remote = lldb.remote_platform
1508    if remote:
1509        return join_remote_paths(remote.GetWorkingDirectory(), *paths)
1510    return os.path.join(test.getBuildDir(), *paths)
1511
1512# ==================================================
1513# Utility functions to get the correct signal number
1514# ==================================================
1515
1516import signal
1517
1518
1519def get_signal_number(signal_name):
1520    platform = lldb.remote_platform
1521    if platform and platform.IsValid():
1522        signals = platform.GetUnixSignals()
1523        if signals.IsValid():
1524            signal_number = signals.GetSignalNumberFromName(signal_name)
1525            if signal_number > 0:
1526                return signal_number
1527    # No remote platform; fall back to using local python signals.
1528    return getattr(signal, signal_name)
1529
1530def get_actions_for_signal(testcase, signal_name, from_target=False, expected_absent=False):
1531    """Returns a triple of (pass, stop, notify)"""
1532    return_obj = lldb.SBCommandReturnObject()
1533    command = "process handle {0}".format(signal_name)
1534    if from_target:
1535        command += " -t"
1536    testcase.dbg.GetCommandInterpreter().HandleCommand(
1537        command, return_obj)
1538    match = re.match(
1539        'NAME *PASS *STOP *NOTIFY.*(false|true|not set) *(false|true|not set) *(false|true|not set)',
1540        return_obj.GetOutput(),
1541        re.IGNORECASE | re.DOTALL)
1542    if match and expected_absent:
1543        testcase.fail('Signal "{0}" was supposed to be absent'.format(signal_name))
1544    if not match:
1545        if expected_absent:
1546            return (None, None, None)
1547        testcase.fail('Unable to retrieve default signal disposition.')
1548    return (match.group(1), match.group(2), match.group(3))
1549
1550
1551
1552def set_actions_for_signal(testcase, signal_name, pass_action, stop_action, notify_action, expect_success=True):
1553        return_obj = lldb.SBCommandReturnObject()
1554        command = "process handle {0}".format(signal_name)
1555        if pass_action != None:
1556            command += " -p {0}".format(pass_action)
1557        if stop_action != None:
1558            command += " -s {0}".format(stop_action)
1559        if notify_action != None:
1560            command +=" -n {0}".format(notify_action)
1561
1562        testcase.dbg.GetCommandInterpreter().HandleCommand(command, return_obj)
1563        testcase.assertEqual(expect_success,
1564            return_obj.Succeeded(),
1565            "Setting signal handling for {0} worked as expected".format(signal_name))
1566
1567class PrintableRegex(object):
1568
1569    def __init__(self, text):
1570        self.regex = re.compile(text)
1571        self.text = text
1572
1573    def match(self, str):
1574        return self.regex.match(str)
1575
1576    def __str__(self):
1577        return "%s" % (self.text)
1578
1579    def __repr__(self):
1580        return "re.compile(%s) -> %s" % (self.text, self.regex)
1581
1582
1583def skip_if_callable(test, mycallable, reason):
1584    if six.callable(mycallable):
1585        if mycallable(test):
1586            test.skipTest(reason)
1587            return True
1588    return False
1589
1590
1591def skip_if_library_missing(test, target, library):
1592    def find_library(target, library):
1593        for module in target.modules:
1594            filename = module.file.GetFilename()
1595            if isinstance(library, str):
1596                if library == filename:
1597                    return False
1598            elif hasattr(library, 'match'):
1599                if library.match(filename):
1600                    return False
1601        return True
1602
1603    def find_library_callable(test):
1604        return find_library(target, library)
1605    return skip_if_callable(
1606        test,
1607        find_library_callable,
1608        "could not find library matching '%s' in target %s" %
1609        (library,
1610         target))
1611
1612
1613def read_file_on_target(test, remote):
1614    if lldb.remote_platform:
1615        local = test.getBuildArtifact("file_from_target")
1616        error = lldb.remote_platform.Get(lldb.SBFileSpec(remote, False),
1617                    lldb.SBFileSpec(local, True))
1618        test.assertTrue(error.Success(), "Reading file {0} failed: {1}".format(remote, error))
1619    else:
1620        local = remote
1621    with open(local, 'r') as f:
1622        return f.read()
1623
1624def read_file_from_process_wd(test, name):
1625    path = append_to_process_working_directory(test, name)
1626    return read_file_on_target(test, path)
1627
1628def wait_for_file_on_target(testcase, file_path, max_attempts=6):
1629    for i in range(max_attempts):
1630        err, retcode, msg = testcase.run_platform_command("ls %s" % file_path)
1631        if err.Success() and retcode == 0:
1632            break
1633        if i < max_attempts:
1634            # Exponential backoff!
1635            import time
1636            time.sleep(pow(2, i) * 0.25)
1637    else:
1638        testcase.fail(
1639            "File %s not found even after %d attempts." %
1640            (file_path, max_attempts))
1641
1642    return read_file_on_target(testcase, file_path)
1643
1644def packetlog_get_process_info(log):
1645    """parse a gdb-remote packet log file and extract the response to qProcessInfo"""
1646    process_info = dict()
1647    with open(log, "r") as logfile:
1648        process_info_ostype = None
1649        expect_process_info_response = False
1650        for line in logfile:
1651            if expect_process_info_response:
1652                for pair in line.split(';'):
1653                    keyval = pair.split(':')
1654                    if len(keyval) == 2:
1655                        process_info[keyval[0]] = keyval[1]
1656                break
1657            if 'send packet: $qProcessInfo#' in line:
1658                expect_process_info_response = True
1659    return process_info
1660
1661def packetlog_get_dylib_info(log):
1662    """parse a gdb-remote packet log file and extract the *last* complete
1663    (=> fetch_all_solibs=true) response to jGetLoadedDynamicLibrariesInfos"""
1664    import json
1665    dylib_info = None
1666    with open(log, "r") as logfile:
1667        dylib_info = None
1668        expect_dylib_info_response = False
1669        for line in logfile:
1670            if expect_dylib_info_response:
1671                while line[0] != '$':
1672                    line = line[1:]
1673                line = line[1:]
1674                # Unescape '}'.
1675                dylib_info = json.loads(line.replace('}]','}')[:-4])
1676                expect_dylib_info_response = False
1677            if 'send packet: $jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}' in line:
1678                expect_dylib_info_response = True
1679
1680    return dylib_info
1681