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