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.eStopReasonSignal:
256        return "signal"
257    elif enum == lldb.eStopReasonException:
258        return "exception"
259    elif enum == lldb.eStopReasonPlanComplete:
260        return "plancomplete"
261    elif enum == lldb.eStopReasonThreadExiting:
262        return "threadexiting"
263    else:
264        raise Exception("Unknown StopReason enum")
265
266
267def symbol_type_to_str(enum):
268    """Returns the symbolType string given an enum."""
269    if enum == lldb.eSymbolTypeInvalid:
270        return "invalid"
271    elif enum == lldb.eSymbolTypeAbsolute:
272        return "absolute"
273    elif enum == lldb.eSymbolTypeCode:
274        return "code"
275    elif enum == lldb.eSymbolTypeData:
276        return "data"
277    elif enum == lldb.eSymbolTypeTrampoline:
278        return "trampoline"
279    elif enum == lldb.eSymbolTypeRuntime:
280        return "runtime"
281    elif enum == lldb.eSymbolTypeException:
282        return "exception"
283    elif enum == lldb.eSymbolTypeSourceFile:
284        return "sourcefile"
285    elif enum == lldb.eSymbolTypeHeaderFile:
286        return "headerfile"
287    elif enum == lldb.eSymbolTypeObjectFile:
288        return "objectfile"
289    elif enum == lldb.eSymbolTypeCommonBlock:
290        return "commonblock"
291    elif enum == lldb.eSymbolTypeBlock:
292        return "block"
293    elif enum == lldb.eSymbolTypeLocal:
294        return "local"
295    elif enum == lldb.eSymbolTypeParam:
296        return "param"
297    elif enum == lldb.eSymbolTypeVariable:
298        return "variable"
299    elif enum == lldb.eSymbolTypeVariableType:
300        return "variabletype"
301    elif enum == lldb.eSymbolTypeLineEntry:
302        return "lineentry"
303    elif enum == lldb.eSymbolTypeLineHeader:
304        return "lineheader"
305    elif enum == lldb.eSymbolTypeScopeBegin:
306        return "scopebegin"
307    elif enum == lldb.eSymbolTypeScopeEnd:
308        return "scopeend"
309    elif enum == lldb.eSymbolTypeAdditional:
310        return "additional"
311    elif enum == lldb.eSymbolTypeCompiler:
312        return "compiler"
313    elif enum == lldb.eSymbolTypeInstrumentation:
314        return "instrumentation"
315    elif enum == lldb.eSymbolTypeUndefined:
316        return "undefined"
317
318
319def value_type_to_str(enum):
320    """Returns the valueType string given an enum."""
321    if enum == lldb.eValueTypeInvalid:
322        return "invalid"
323    elif enum == lldb.eValueTypeVariableGlobal:
324        return "global_variable"
325    elif enum == lldb.eValueTypeVariableStatic:
326        return "static_variable"
327    elif enum == lldb.eValueTypeVariableArgument:
328        return "argument_variable"
329    elif enum == lldb.eValueTypeVariableLocal:
330        return "local_variable"
331    elif enum == lldb.eValueTypeRegister:
332        return "register"
333    elif enum == lldb.eValueTypeRegisterSet:
334        return "register_set"
335    elif enum == lldb.eValueTypeConstResult:
336        return "constant_result"
337    else:
338        raise Exception("Unknown ValueType enum")
339
340
341# ==================================================
342# Get stopped threads due to each stop reason.
343# ==================================================
344
345def sort_stopped_threads(process,
346                         breakpoint_threads=None,
347                         crashed_threads=None,
348                         watchpoint_threads=None,
349                         signal_threads=None,
350                         exiting_threads=None,
351                         other_threads=None):
352    """ Fills array *_threads with threads stopped for the corresponding stop
353        reason.
354    """
355    for lst in [breakpoint_threads,
356                watchpoint_threads,
357                signal_threads,
358                exiting_threads,
359                other_threads]:
360        if lst is not None:
361            lst[:] = []
362
363    for thread in process:
364        dispatched = False
365        for (reason, list) in [(lldb.eStopReasonBreakpoint, breakpoint_threads),
366                               (lldb.eStopReasonException, crashed_threads),
367                               (lldb.eStopReasonWatchpoint, watchpoint_threads),
368                               (lldb.eStopReasonSignal, signal_threads),
369                               (lldb.eStopReasonThreadExiting, exiting_threads),
370                               (None, other_threads)]:
371            if not dispatched and list is not None:
372                if thread.GetStopReason() == reason or reason is None:
373                    list.append(thread)
374                    dispatched = True
375
376# ==================================================
377# Utility functions for setting breakpoints
378# ==================================================
379
380def run_break_set_by_script(
381        test,
382        class_name,
383        extra_options=None,
384        num_expected_locations=1):
385    """Set a scripted breakpoint.  Check that it got the right number of locations."""
386    test.assertTrue(class_name is not None, "Must pass in a class name.")
387    command = "breakpoint set -P " + class_name
388    if extra_options is not None:
389        command += " " + extra_options
390
391    break_results = run_break_set_command(test, command)
392    check_breakpoint_result(test, break_results, num_locations=num_expected_locations)
393    return get_bpno_from_match(break_results)
394
395def run_break_set_by_file_and_line(
396        test,
397        file_name,
398        line_number,
399        extra_options=None,
400        num_expected_locations=1,
401        loc_exact=False,
402        module_name=None):
403    """Set a breakpoint by file and line, returning the breakpoint number.
404
405    If extra_options is not None, then we append it to the breakpoint set command.
406
407    If num_expected_locations is -1, we check that we got AT LEAST one location. If num_expected_locations is -2, we don't
408    check the actual number at all. Otherwise, we check that num_expected_locations equals the number of locations.
409
410    If loc_exact is true, we check that there is one location, and that location must be at the input file and line number."""
411
412    if file_name is None:
413        command = 'breakpoint set -l %d' % (line_number)
414    else:
415        command = 'breakpoint set -f "%s" -l %d' % (file_name, line_number)
416
417    if module_name:
418        command += " --shlib '%s'" % (module_name)
419
420    if extra_options:
421        command += " " + extra_options
422
423    break_results = run_break_set_command(test, command)
424
425    if num_expected_locations == 1 and loc_exact:
426        check_breakpoint_result(
427            test,
428            break_results,
429            num_locations=num_expected_locations,
430            file_name=file_name,
431            line_number=line_number,
432            module_name=module_name)
433    else:
434        check_breakpoint_result(
435            test,
436            break_results,
437            num_locations=num_expected_locations)
438
439    return get_bpno_from_match(break_results)
440
441
442def run_break_set_by_symbol(
443        test,
444        symbol,
445        extra_options=None,
446        num_expected_locations=-1,
447        sym_exact=False,
448        module_name=None):
449    """Set a breakpoint by symbol name.  Common options are the same as run_break_set_by_file_and_line.
450
451    If sym_exact is true, then the output symbol must match the input exactly, otherwise we do a substring match."""
452    command = 'breakpoint set -n "%s"' % (symbol)
453
454    if module_name:
455        command += " --shlib '%s'" % (module_name)
456
457    if extra_options:
458        command += " " + extra_options
459
460    break_results = run_break_set_command(test, command)
461
462    if num_expected_locations == 1 and sym_exact:
463        check_breakpoint_result(
464            test,
465            break_results,
466            num_locations=num_expected_locations,
467            symbol_name=symbol,
468            module_name=module_name)
469    else:
470        check_breakpoint_result(
471            test,
472            break_results,
473            num_locations=num_expected_locations)
474
475    return get_bpno_from_match(break_results)
476
477
478def run_break_set_by_selector(
479        test,
480        selector,
481        extra_options=None,
482        num_expected_locations=-1,
483        module_name=None):
484    """Set a breakpoint by selector.  Common options are the same as run_break_set_by_file_and_line."""
485
486    command = 'breakpoint set -S "%s"' % (selector)
487
488    if module_name:
489        command += ' --shlib "%s"' % (module_name)
490
491    if extra_options:
492        command += " " + extra_options
493
494    break_results = run_break_set_command(test, command)
495
496    if num_expected_locations == 1:
497        check_breakpoint_result(
498            test,
499            break_results,
500            num_locations=num_expected_locations,
501            symbol_name=selector,
502            symbol_match_exact=False,
503            module_name=module_name)
504    else:
505        check_breakpoint_result(
506            test,
507            break_results,
508            num_locations=num_expected_locations)
509
510    return get_bpno_from_match(break_results)
511
512
513def run_break_set_by_regexp(
514        test,
515        regexp,
516        extra_options=None,
517        num_expected_locations=-1):
518    """Set a breakpoint by regular expression match on symbol name.  Common options are the same as run_break_set_by_file_and_line."""
519
520    command = 'breakpoint set -r "%s"' % (regexp)
521    if extra_options:
522        command += " " + extra_options
523
524    break_results = run_break_set_command(test, command)
525
526    check_breakpoint_result(
527        test,
528        break_results,
529        num_locations=num_expected_locations)
530
531    return get_bpno_from_match(break_results)
532
533
534def run_break_set_by_source_regexp(
535        test,
536        regexp,
537        extra_options=None,
538        num_expected_locations=-1):
539    """Set a breakpoint by source regular expression.  Common options are the same as run_break_set_by_file_and_line."""
540    command = 'breakpoint set -p "%s"' % (regexp)
541    if extra_options:
542        command += " " + extra_options
543
544    break_results = run_break_set_command(test, command)
545
546    check_breakpoint_result(
547        test,
548        break_results,
549        num_locations=num_expected_locations)
550
551    return get_bpno_from_match(break_results)
552
553def run_break_set_by_file_colon_line(
554        test,
555        specifier,
556        path,
557        line_number,
558        column_number = 0,
559        extra_options=None,
560        num_expected_locations=-1):
561    command = 'breakpoint set -y "%s"'%(specifier)
562    if extra_options:
563        command += " " + extra_options
564
565    print("About to run: '%s'", command)
566    break_results = run_break_set_command(test, command)
567    check_breakpoint_result(
568        test,
569        break_results,
570        num_locations = num_expected_locations,
571        file_name = path,
572        line_number = line_number,
573        column_number = column_number)
574
575    return get_bpno_from_match(break_results)
576
577def run_break_set_command(test, command):
578    """Run the command passed in - it must be some break set variant - and analyze the result.
579    Returns a dictionary of information gleaned from the command-line results.
580    Will assert if the breakpoint setting fails altogether.
581
582    Dictionary will contain:
583        bpno          - breakpoint of the newly created breakpoint, -1 on error.
584        num_locations - number of locations set for the breakpoint.
585
586    If there is only one location, the dictionary MAY contain:
587        file          - source file name
588        line_no       - source line number
589        column        - source column number
590        symbol        - symbol name
591        inline_symbol - inlined symbol name
592        offset        - offset from the original symbol
593        module        - module
594        address       - address at which the breakpoint was set."""
595
596    patterns = [
597        r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>[0-9]+) locations\.$",
598        r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>no) locations \(pending\)\.",
599        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]+)$",
600        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]+)$"]
601    match_object = test.match(command, patterns)
602    break_results = match_object.groupdict()
603
604    # We always insert the breakpoint number, setting it to -1 if we couldn't find it
605    # Also, make sure it gets stored as an integer.
606    if not 'bpno' in break_results:
607        break_results['bpno'] = -1
608    else:
609        break_results['bpno'] = int(break_results['bpno'])
610
611    # We always insert the number of locations
612    # If ONE location is set for the breakpoint, then the output doesn't mention locations, but it has to be 1...
613    # We also make sure it is an integer.
614
615    if not 'num_locations' in break_results:
616        num_locations = 1
617    else:
618        num_locations = break_results['num_locations']
619        if num_locations == 'no':
620            num_locations = 0
621        else:
622            num_locations = int(break_results['num_locations'])
623
624    break_results['num_locations'] = num_locations
625
626    if 'line_no' in break_results:
627        break_results['line_no'] = int(break_results['line_no'])
628
629    return break_results
630
631
632def get_bpno_from_match(break_results):
633    return int(break_results['bpno'])
634
635
636def check_breakpoint_result(
637        test,
638        break_results,
639        file_name=None,
640        line_number=-1,
641        column_number=0,
642        symbol_name=None,
643        symbol_match_exact=True,
644        module_name=None,
645        offset=-1,
646        num_locations=-1):
647
648    out_num_locations = break_results['num_locations']
649
650    if num_locations == -1:
651        test.assertTrue(out_num_locations > 0,
652                        "Expecting one or more locations, got none.")
653    elif num_locations != -2:
654        test.assertTrue(
655            num_locations == out_num_locations,
656            "Expecting %d locations, got %d." %
657            (num_locations,
658             out_num_locations))
659
660    if file_name:
661        out_file_name = ""
662        if 'file' in break_results:
663            out_file_name = break_results['file']
664        test.assertTrue(
665            file_name.endswith(out_file_name),
666            "Breakpoint file name '%s' doesn't match resultant name '%s'." %
667            (file_name,
668             out_file_name))
669
670    if line_number != -1:
671        out_line_number = -1
672        if 'line_no' in break_results:
673            out_line_number = break_results['line_no']
674
675        test.assertTrue(
676            line_number == out_line_number,
677            "Breakpoint line number %s doesn't match resultant line %s." %
678            (line_number,
679             out_line_number))
680
681    if column_number != 0:
682        out_column_number = 0
683        if 'column' in break_results:
684            out_column_number = break_results['column']
685
686        test.assertTrue(
687            column_number == out_column_number,
688            "Breakpoint column number %s doesn't match resultant column %s." %
689            (column_number,
690             out_column_number))
691
692    if symbol_name:
693        out_symbol_name = ""
694        # Look first for the inlined symbol name, otherwise use the symbol
695        # name:
696        if 'inline_symbol' in break_results and break_results['inline_symbol']:
697            out_symbol_name = break_results['inline_symbol']
698        elif 'symbol' in break_results:
699            out_symbol_name = break_results['symbol']
700
701        if symbol_match_exact:
702            test.assertTrue(
703                symbol_name == out_symbol_name,
704                "Symbol name '%s' doesn't match resultant symbol '%s'." %
705                (symbol_name,
706                 out_symbol_name))
707        else:
708            test.assertTrue(
709                out_symbol_name.find(symbol_name) != -
710                1,
711                "Symbol name '%s' isn't in resultant symbol '%s'." %
712                (symbol_name,
713                 out_symbol_name))
714
715    if module_name:
716        out_module_name = None
717        if 'module' in break_results:
718            out_module_name = break_results['module']
719
720        test.assertTrue(
721            module_name.find(out_module_name) != -
722            1,
723            "Symbol module name '%s' isn't in expected module name '%s'." %
724            (out_module_name,
725             module_name))
726
727# ==================================================
728# Utility functions related to Threads and Processes
729# ==================================================
730
731
732def get_stopped_threads(process, reason):
733    """Returns the thread(s) with the specified stop reason in a list.
734
735    The list can be empty if no such thread exists.
736    """
737    threads = []
738    for t in process:
739        if t.GetStopReason() == reason:
740            threads.append(t)
741    return threads
742
743
744def get_stopped_thread(process, reason):
745    """A convenience function which returns the first thread with the given stop
746    reason or None.
747
748    Example usages:
749
750    1. Get the stopped thread due to a breakpoint condition
751
752    ...
753        from lldbutil import get_stopped_thread
754        thread = get_stopped_thread(process, lldb.eStopReasonPlanComplete)
755        self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition")
756    ...
757
758    2. Get the thread stopped due to a breakpoint
759
760    ...
761        from lldbutil import get_stopped_thread
762        thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
763        self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint")
764    ...
765
766    """
767    threads = get_stopped_threads(process, reason)
768    if len(threads) == 0:
769        return None
770    return threads[0]
771
772
773def get_threads_stopped_at_breakpoint_id(process, bpid):
774    """ For a stopped process returns the thread stopped at the breakpoint passed in bkpt"""
775    stopped_threads = []
776    threads = []
777
778    stopped_threads = get_stopped_threads(process, lldb.eStopReasonBreakpoint)
779
780    if len(stopped_threads) == 0:
781        return threads
782
783    for thread in stopped_threads:
784        # Make sure we've hit our breakpoint...
785        break_id = thread.GetStopReasonDataAtIndex(0)
786        if break_id == bpid:
787            threads.append(thread)
788
789    return threads
790
791
792def get_threads_stopped_at_breakpoint(process, bkpt):
793    return get_threads_stopped_at_breakpoint_id(process, bkpt.GetID())
794
795
796def get_one_thread_stopped_at_breakpoint_id(
797        process, bpid, require_exactly_one=True):
798    threads = get_threads_stopped_at_breakpoint_id(process, bpid)
799    if len(threads) == 0:
800        return None
801    if require_exactly_one and len(threads) != 1:
802        return None
803
804    return threads[0]
805
806
807def get_one_thread_stopped_at_breakpoint(
808        process, bkpt, require_exactly_one=True):
809    return get_one_thread_stopped_at_breakpoint_id(
810        process, bkpt.GetID(), require_exactly_one)
811
812
813def is_thread_crashed(test, thread):
814    """In the test suite we dereference a null pointer to simulate a crash. The way this is
815    reported depends on the platform."""
816    if test.platformIsDarwin():
817        return thread.GetStopReason(
818        ) == lldb.eStopReasonException and "EXC_BAD_ACCESS" in thread.GetStopDescription(100)
819    elif test.getPlatform() == "linux":
820        return thread.GetStopReason() == lldb.eStopReasonSignal and thread.GetStopReasonDataAtIndex(
821            0) == thread.GetProcess().GetUnixSignals().GetSignalNumberFromName("SIGSEGV")
822    elif test.getPlatform() == "windows":
823        return "Exception 0xc0000005" in thread.GetStopDescription(200)
824    else:
825        return "invalid address" in thread.GetStopDescription(100)
826
827
828def get_crashed_threads(test, process):
829    threads = []
830    if process.GetState() != lldb.eStateStopped:
831        return threads
832    for thread in process:
833        if is_thread_crashed(test, thread):
834            threads.append(thread)
835    return threads
836
837# Helper functions for run_to_{source,name}_breakpoint:
838
839def run_to_breakpoint_make_target(test, exe_name = "a.out", in_cwd = True):
840    if in_cwd:
841        exe = test.getBuildArtifact(exe_name)
842
843    # Create the target
844    target = test.dbg.CreateTarget(exe)
845    test.assertTrue(target, "Target: %s is not valid."%(exe_name))
846
847    # Set environment variables for the inferior.
848    if lldbtest_config.inferior_env:
849        test.runCmd('settings set target.env-vars {}'.format(
850            lldbtest_config.inferior_env))
851
852    return target
853
854def run_to_breakpoint_do_run(test, target, bkpt, launch_info = None,
855                             only_one_thread = True, extra_images = None):
856
857    # Launch the process, and do not stop at the entry point.
858    if not launch_info:
859        launch_info = target.GetLaunchInfo()
860        launch_info.SetWorkingDirectory(test.get_process_working_directory())
861
862    if extra_images:
863        environ = test.registerSharedLibrariesWithTarget(target, extra_images)
864        launch_info.SetEnvironmentEntries(environ, True)
865
866    error = lldb.SBError()
867    process = target.Launch(launch_info, error)
868
869    # Unfortunate workaround for the iPhone simulator.
870    retry = SIMULATOR_RETRY
871    while (retry and error.Fail() and error.GetCString() and
872           "Unable to boot the Simulator" in error.GetCString()):
873        retry -= 1
874        print("** Simulator is unresponsive. Retrying %d more time(s)"%retry)
875        import time
876        time.sleep(60)
877        error = lldb.SBError()
878        process = target.Launch(launch_info, error)
879
880    test.assertTrue(process,
881                    "Could not create a valid process for %s: %s" %
882                    (target.GetExecutable().GetFilename(), error.GetCString()))
883    test.assertFalse(error.Fail(),
884                     "Process launch failed: %s" % (error.GetCString()))
885
886    test.assertEqual(process.GetState(), lldb.eStateStopped)
887
888    # Frame #0 should be at our breakpoint.
889    threads = get_threads_stopped_at_breakpoint(
890                process, bkpt)
891
892    num_threads = len(threads)
893    if only_one_thread:
894        test.assertEqual(num_threads, 1, "Expected 1 thread to stop at breakpoint, %d did."%(num_threads))
895    else:
896        test.assertGreater(num_threads, 0, "No threads stopped at breakpoint")
897
898    thread = threads[0]
899    return (target, process, thread, bkpt)
900
901def run_to_name_breakpoint (test, bkpt_name, launch_info = None,
902                            exe_name = "a.out",
903                            bkpt_module = None,
904                            in_cwd = True,
905                            only_one_thread = True,
906                            extra_images = None):
907    """Start up a target, using exe_name as the executable, and run it to
908       a breakpoint set by name on bkpt_name restricted to bkpt_module.
909
910       If you want to pass in launch arguments or environment
911       variables, you can optionally pass in an SBLaunchInfo.  If you
912       do that, remember to set the working directory as well.
913
914       If your executable isn't called a.out, you can pass that in.
915       And if your executable isn't in the CWD, pass in the absolute
916       path to the executable in exe_name, and set in_cwd to False.
917
918       If you need to restrict the breakpoint to a particular module,
919       pass the module name (a string not a FileSpec) in bkpt_module.  If
920       nothing is passed in setting will be unrestricted.
921
922       If the target isn't valid, the breakpoint isn't found, or hit, the
923       function will cause a testsuite failure.
924
925       If successful it returns a tuple with the target process and
926       thread that hit the breakpoint, and the breakpoint that we set
927       for you.
928
929       If only_one_thread is true, we require that there be only one
930       thread stopped at the breakpoint.  Otherwise we only require one
931       or more threads stop there.  If there are more than one, we return
932       the first thread that stopped.
933    """
934
935    target = run_to_breakpoint_make_target(test, exe_name, in_cwd)
936
937    breakpoint = target.BreakpointCreateByName(bkpt_name, bkpt_module)
938
939
940    test.assertTrue(breakpoint.GetNumLocations() > 0,
941                    "No locations found for name breakpoint: '%s'."%(bkpt_name))
942    return run_to_breakpoint_do_run(test, target, breakpoint, launch_info,
943                                    only_one_thread, extra_images)
944
945def run_to_source_breakpoint(test, bkpt_pattern, source_spec,
946                             launch_info = None, exe_name = "a.out",
947                             bkpt_module = None,
948                             in_cwd = True,
949                             only_one_thread = True,
950                             extra_images = None):
951    """Start up a target, using exe_name as the executable, and run it to
952       a breakpoint set by source regex bkpt_pattern.
953
954       The rest of the behavior is the same as run_to_name_breakpoint.
955    """
956
957    target = run_to_breakpoint_make_target(test, exe_name, in_cwd)
958    # Set the breakpoints
959    breakpoint = target.BreakpointCreateBySourceRegex(
960            bkpt_pattern, source_spec, bkpt_module)
961    test.assertTrue(breakpoint.GetNumLocations() > 0,
962        'No locations found for source breakpoint: "%s", file: "%s", dir: "%s"'
963        %(bkpt_pattern, source_spec.GetFilename(), source_spec.GetDirectory()))
964    return run_to_breakpoint_do_run(test, target, breakpoint, launch_info,
965                                    only_one_thread, extra_images)
966
967def run_to_line_breakpoint(test, source_spec, line_number, column = 0,
968                           launch_info = None, exe_name = "a.out",
969                           bkpt_module = None,
970                           in_cwd = True,
971                           only_one_thread = True,
972                           extra_images = None):
973    """Start up a target, using exe_name as the executable, and run it to
974       a breakpoint set by (source_spec, line_number(, column)).
975
976       The rest of the behavior is the same as run_to_name_breakpoint.
977    """
978
979    target = run_to_breakpoint_make_target(test, exe_name, in_cwd)
980    # Set the breakpoints
981    breakpoint = target.BreakpointCreateByLocation(
982        source_spec, line_number, column, 0, lldb.SBFileSpecList())
983    test.assertTrue(breakpoint.GetNumLocations() > 0,
984        'No locations found for line breakpoint: "%s:%d(:%d)", dir: "%s"'
985        %(source_spec.GetFilename(), line_number, column,
986          source_spec.GetDirectory()))
987    return run_to_breakpoint_do_run(test, target, breakpoint, launch_info,
988                                    only_one_thread, extra_images)
989
990
991def continue_to_breakpoint(process, bkpt):
992    """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
993    process.Continue()
994    if process.GetState() != lldb.eStateStopped:
995        return None
996    else:
997        return get_threads_stopped_at_breakpoint(process, bkpt)
998
999
1000def get_caller_symbol(thread):
1001    """
1002    Returns the symbol name for the call site of the leaf function.
1003    """
1004    depth = thread.GetNumFrames()
1005    if depth <= 1:
1006        return None
1007    caller = thread.GetFrameAtIndex(1).GetSymbol()
1008    if caller:
1009        return caller.GetName()
1010    else:
1011        return None
1012
1013
1014def get_function_names(thread):
1015    """
1016    Returns a sequence of function names from the stack frames of this thread.
1017    """
1018    def GetFuncName(i):
1019        return thread.GetFrameAtIndex(i).GetFunctionName()
1020
1021    return list(map(GetFuncName, list(range(thread.GetNumFrames()))))
1022
1023
1024def get_symbol_names(thread):
1025    """
1026    Returns a sequence of symbols for this thread.
1027    """
1028    def GetSymbol(i):
1029        return thread.GetFrameAtIndex(i).GetSymbol().GetName()
1030
1031    return list(map(GetSymbol, list(range(thread.GetNumFrames()))))
1032
1033
1034def get_pc_addresses(thread):
1035    """
1036    Returns a sequence of pc addresses for this thread.
1037    """
1038    def GetPCAddress(i):
1039        return thread.GetFrameAtIndex(i).GetPCAddress()
1040
1041    return list(map(GetPCAddress, list(range(thread.GetNumFrames()))))
1042
1043
1044def get_filenames(thread):
1045    """
1046    Returns a sequence of file names from the stack frames of this thread.
1047    """
1048    def GetFilename(i):
1049        return thread.GetFrameAtIndex(
1050            i).GetLineEntry().GetFileSpec().GetFilename()
1051
1052    return list(map(GetFilename, list(range(thread.GetNumFrames()))))
1053
1054
1055def get_line_numbers(thread):
1056    """
1057    Returns a sequence of line numbers from the stack frames of this thread.
1058    """
1059    def GetLineNumber(i):
1060        return thread.GetFrameAtIndex(i).GetLineEntry().GetLine()
1061
1062    return list(map(GetLineNumber, list(range(thread.GetNumFrames()))))
1063
1064
1065def get_module_names(thread):
1066    """
1067    Returns a sequence of module names from the stack frames of this thread.
1068    """
1069    def GetModuleName(i):
1070        return thread.GetFrameAtIndex(
1071            i).GetModule().GetFileSpec().GetFilename()
1072
1073    return list(map(GetModuleName, list(range(thread.GetNumFrames()))))
1074
1075
1076def get_stack_frames(thread):
1077    """
1078    Returns a sequence of stack frames for this thread.
1079    """
1080    def GetStackFrame(i):
1081        return thread.GetFrameAtIndex(i)
1082
1083    return list(map(GetStackFrame, list(range(thread.GetNumFrames()))))
1084
1085
1086def print_stacktrace(thread, string_buffer=False):
1087    """Prints a simple stack trace of this thread."""
1088
1089    output = SixStringIO() if string_buffer else sys.stdout
1090    target = thread.GetProcess().GetTarget()
1091
1092    depth = thread.GetNumFrames()
1093
1094    mods = get_module_names(thread)
1095    funcs = get_function_names(thread)
1096    symbols = get_symbol_names(thread)
1097    files = get_filenames(thread)
1098    lines = get_line_numbers(thread)
1099    addrs = get_pc_addresses(thread)
1100
1101    if thread.GetStopReason() != lldb.eStopReasonInvalid:
1102        desc = "stop reason=" + stop_reason_to_str(thread.GetStopReason())
1103    else:
1104        desc = ""
1105    print(
1106        "Stack trace for thread id={0:#x} name={1} queue={2} ".format(
1107            thread.GetThreadID(),
1108            thread.GetName(),
1109            thread.GetQueueName()) + desc,
1110        file=output)
1111
1112    for i in range(depth):
1113        frame = thread.GetFrameAtIndex(i)
1114        function = frame.GetFunction()
1115
1116        load_addr = addrs[i].GetLoadAddress(target)
1117        if not function:
1118            file_addr = addrs[i].GetFileAddress()
1119            start_addr = frame.GetSymbol().GetStartAddress().GetFileAddress()
1120            symbol_offset = file_addr - start_addr
1121            print(
1122                "  frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}".format(
1123                    num=i,
1124                    addr=load_addr,
1125                    mod=mods[i],
1126                    symbol=symbols[i],
1127                    offset=symbol_offset),
1128                file=output)
1129        else:
1130            print(
1131                "  frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format(
1132                    num=i,
1133                    addr=load_addr,
1134                    mod=mods[i],
1135                    func='%s [inlined]' %
1136                    funcs[i] if frame.IsInlined() else funcs[i],
1137                    file=files[i],
1138                    line=lines[i],
1139                    args=get_args_as_string(
1140                        frame,
1141                        showFuncName=False) if not frame.IsInlined() else '()'),
1142                file=output)
1143
1144    if string_buffer:
1145        return output.getvalue()
1146
1147
1148def print_stacktraces(process, string_buffer=False):
1149    """Prints the stack traces of all the threads."""
1150
1151    output = SixStringIO() if string_buffer else sys.stdout
1152
1153    print("Stack traces for " + str(process), file=output)
1154
1155    for thread in process:
1156        print(print_stacktrace(thread, string_buffer=True), file=output)
1157
1158    if string_buffer:
1159        return output.getvalue()
1160
1161
1162def expect_state_changes(test, listener, process, states, timeout=30):
1163    """Listens for state changed events on the listener and makes sure they match what we
1164    expect. Stop-and-restart events (where GetRestartedFromEvent() returns true) are ignored."""
1165
1166    for expected_state in states:
1167        def get_next_event():
1168            event = lldb.SBEvent()
1169            if not listener.WaitForEventForBroadcasterWithType(
1170                    timeout,
1171                    process.GetBroadcaster(),
1172                    lldb.SBProcess.eBroadcastBitStateChanged,
1173                    event):
1174                test.fail(
1175                    "Timed out while waiting for a transition to state %s" %
1176                    lldb.SBDebugger.StateAsCString(expected_state))
1177            return event
1178
1179        event = get_next_event()
1180        while (lldb.SBProcess.GetStateFromEvent(event) == lldb.eStateStopped and
1181                lldb.SBProcess.GetRestartedFromEvent(event)):
1182            # Ignore restarted event and the subsequent running event.
1183            event = get_next_event()
1184            test.assertEqual(
1185                lldb.SBProcess.GetStateFromEvent(event),
1186                lldb.eStateRunning,
1187                "Restarted event followed by a running event")
1188            event = get_next_event()
1189
1190        test.assertEqual(
1191            lldb.SBProcess.GetStateFromEvent(event),
1192            expected_state)
1193
1194# ===================================
1195# Utility functions related to Frames
1196# ===================================
1197
1198
1199def get_parent_frame(frame):
1200    """
1201    Returns the parent frame of the input frame object; None if not available.
1202    """
1203    thread = frame.GetThread()
1204    parent_found = False
1205    for f in thread:
1206        if parent_found:
1207            return f
1208        if f.GetFrameID() == frame.GetFrameID():
1209            parent_found = True
1210
1211    # If we reach here, no parent has been found, return None.
1212    return None
1213
1214
1215def get_args_as_string(frame, showFuncName=True):
1216    """
1217    Returns the args of the input frame object as a string.
1218    """
1219    # arguments     => True
1220    # locals        => False
1221    # statics       => False
1222    # in_scope_only => True
1223    vars = frame.GetVariables(True, False, False, True)  # type of SBValueList
1224    args = []  # list of strings
1225    for var in vars:
1226        args.append("(%s)%s=%s" % (var.GetTypeName(),
1227                                   var.GetName(),
1228                                   var.GetValue()))
1229    if frame.GetFunction():
1230        name = frame.GetFunction().GetName()
1231    elif frame.GetSymbol():
1232        name = frame.GetSymbol().GetName()
1233    else:
1234        name = ""
1235    if showFuncName:
1236        return "%s(%s)" % (name, ", ".join(args))
1237    else:
1238        return "(%s)" % (", ".join(args))
1239
1240
1241def print_registers(frame, string_buffer=False):
1242    """Prints all the register sets of the frame."""
1243
1244    output = SixStringIO() if string_buffer else sys.stdout
1245
1246    print("Register sets for " + str(frame), file=output)
1247
1248    registerSet = frame.GetRegisters()  # Return type of SBValueList.
1249    print("Frame registers (size of register set = %d):" %
1250          registerSet.GetSize(), file=output)
1251    for value in registerSet:
1252        #print(value, file=output)
1253        print("%s (number of children = %d):" %
1254              (value.GetName(), value.GetNumChildren()), file=output)
1255        for child in value:
1256            print(
1257                "Name: %s, Value: %s" %
1258                (child.GetName(),
1259                 child.GetValue()),
1260                file=output)
1261
1262    if string_buffer:
1263        return output.getvalue()
1264
1265
1266def get_registers(frame, kind):
1267    """Returns the registers given the frame and the kind of registers desired.
1268
1269    Returns None if there's no such kind.
1270    """
1271    registerSet = frame.GetRegisters()  # Return type of SBValueList.
1272    for value in registerSet:
1273        if kind.lower() in value.GetName().lower():
1274            return value
1275
1276    return None
1277
1278
1279def get_GPRs(frame):
1280    """Returns the general purpose registers of the frame as an SBValue.
1281
1282    The returned SBValue object is iterable.  An example:
1283        ...
1284        from lldbutil import get_GPRs
1285        regs = get_GPRs(frame)
1286        for reg in regs:
1287            print("%s => %s" % (reg.GetName(), reg.GetValue()))
1288        ...
1289    """
1290    return get_registers(frame, "general purpose")
1291
1292
1293def get_FPRs(frame):
1294    """Returns the floating point registers of the frame as an SBValue.
1295
1296    The returned SBValue object is iterable.  An example:
1297        ...
1298        from lldbutil import get_FPRs
1299        regs = get_FPRs(frame)
1300        for reg in regs:
1301            print("%s => %s" % (reg.GetName(), reg.GetValue()))
1302        ...
1303    """
1304    return get_registers(frame, "floating point")
1305
1306
1307def get_ESRs(frame):
1308    """Returns the exception state registers of the frame as an SBValue.
1309
1310    The returned SBValue object is iterable.  An example:
1311        ...
1312        from lldbutil import get_ESRs
1313        regs = get_ESRs(frame)
1314        for reg in regs:
1315            print("%s => %s" % (reg.GetName(), reg.GetValue()))
1316        ...
1317    """
1318    return get_registers(frame, "exception state")
1319
1320# ======================================
1321# Utility classes/functions for SBValues
1322# ======================================
1323
1324
1325class BasicFormatter(object):
1326    """The basic formatter inspects the value object and prints the value."""
1327
1328    def format(self, value, buffer=None, indent=0):
1329        if not buffer:
1330            output = SixStringIO()
1331        else:
1332            output = buffer
1333        # If there is a summary, it suffices.
1334        val = value.GetSummary()
1335        # Otherwise, get the value.
1336        if val is None:
1337            val = value.GetValue()
1338        if val is None and value.GetNumChildren() > 0:
1339            val = "%s (location)" % value.GetLocation()
1340        print("{indentation}({type}) {name} = {value}".format(
1341            indentation=' ' * indent,
1342            type=value.GetTypeName(),
1343            name=value.GetName(),
1344            value=val), file=output)
1345        return output.getvalue()
1346
1347
1348class ChildVisitingFormatter(BasicFormatter):
1349    """The child visiting formatter prints the value and its immediate children.
1350
1351    The constructor takes a keyword arg: indent_child, which defaults to 2.
1352    """
1353
1354    def __init__(self, indent_child=2):
1355        """Default indentation of 2 SPC's for the children."""
1356        self.cindent = indent_child
1357
1358    def format(self, value, buffer=None):
1359        if not buffer:
1360            output = SixStringIO()
1361        else:
1362            output = buffer
1363
1364        BasicFormatter.format(self, value, buffer=output)
1365        for child in value:
1366            BasicFormatter.format(
1367                self, child, buffer=output, indent=self.cindent)
1368
1369        return output.getvalue()
1370
1371
1372class RecursiveDecentFormatter(BasicFormatter):
1373    """The recursive decent formatter prints the value and the decendents.
1374
1375    The constructor takes two keyword args: indent_level, which defaults to 0,
1376    and indent_child, which defaults to 2.  The current indentation level is
1377    determined by indent_level, while the immediate children has an additional
1378    indentation by inden_child.
1379    """
1380
1381    def __init__(self, indent_level=0, indent_child=2):
1382        self.lindent = indent_level
1383        self.cindent = indent_child
1384
1385    def format(self, value, buffer=None):
1386        if not buffer:
1387            output = SixStringIO()
1388        else:
1389            output = buffer
1390
1391        BasicFormatter.format(self, value, buffer=output, indent=self.lindent)
1392        new_indent = self.lindent + self.cindent
1393        for child in value:
1394            if child.GetSummary() is not None:
1395                BasicFormatter.format(
1396                    self, child, buffer=output, indent=new_indent)
1397            else:
1398                if child.GetNumChildren() > 0:
1399                    rdf = RecursiveDecentFormatter(indent_level=new_indent)
1400                    rdf.format(child, buffer=output)
1401                else:
1402                    BasicFormatter.format(
1403                        self, child, buffer=output, indent=new_indent)
1404
1405        return output.getvalue()
1406
1407# ===========================================================
1408# Utility functions for path manipulation on remote platforms
1409# ===========================================================
1410
1411
1412def join_remote_paths(*paths):
1413    # TODO: update with actual platform name for remote windows once it exists
1414    if lldb.remote_platform.GetName() == 'remote-windows':
1415        return os.path.join(*paths).replace(os.path.sep, '\\')
1416    return os.path.join(*paths).replace(os.path.sep, '/')
1417
1418
1419def append_to_process_working_directory(test, *paths):
1420    remote = lldb.remote_platform
1421    if remote:
1422        return join_remote_paths(remote.GetWorkingDirectory(), *paths)
1423    return os.path.join(test.getBuildDir(), *paths)
1424
1425# ==================================================
1426# Utility functions to get the correct signal number
1427# ==================================================
1428
1429import signal
1430
1431
1432def get_signal_number(signal_name):
1433    platform = lldb.remote_platform
1434    if platform and platform.IsValid():
1435        signals = platform.GetUnixSignals()
1436        if signals.IsValid():
1437            signal_number = signals.GetSignalNumberFromName(signal_name)
1438            if signal_number > 0:
1439                return signal_number
1440    # No remote platform; fall back to using local python signals.
1441    return getattr(signal, signal_name)
1442
1443
1444class PrintableRegex(object):
1445
1446    def __init__(self, text):
1447        self.regex = re.compile(text)
1448        self.text = text
1449
1450    def match(self, str):
1451        return self.regex.match(str)
1452
1453    def __str__(self):
1454        return "%s" % (self.text)
1455
1456    def __repr__(self):
1457        return "re.compile(%s) -> %s" % (self.text, self.regex)
1458
1459
1460def skip_if_callable(test, mycallable, reason):
1461    if six.callable(mycallable):
1462        if mycallable(test):
1463            test.skipTest(reason)
1464            return True
1465    return False
1466
1467
1468def skip_if_library_missing(test, target, library):
1469    def find_library(target, library):
1470        for module in target.modules:
1471            filename = module.file.GetFilename()
1472            if isinstance(library, str):
1473                if library == filename:
1474                    return False
1475            elif hasattr(library, 'match'):
1476                if library.match(filename):
1477                    return False
1478        return True
1479
1480    def find_library_callable(test):
1481        return find_library(target, library)
1482    return skip_if_callable(
1483        test,
1484        find_library_callable,
1485        "could not find library matching '%s' in target %s" %
1486        (library,
1487         target))
1488
1489
1490def read_file_on_target(test, remote):
1491    if lldb.remote_platform:
1492        local = test.getBuildArtifact("file_from_target")
1493        error = lldb.remote_platform.Get(lldb.SBFileSpec(remote, False),
1494                    lldb.SBFileSpec(local, True))
1495        test.assertTrue(error.Success(), "Reading file {0} failed: {1}".format(remote, error))
1496    else:
1497        local = remote
1498    with open(local, 'r') as f:
1499        return f.read()
1500
1501def read_file_from_process_wd(test, name):
1502    path = append_to_process_working_directory(test, name)
1503    return read_file_on_target(test, path)
1504
1505def wait_for_file_on_target(testcase, file_path, max_attempts=6):
1506    for i in range(max_attempts):
1507        err, retcode, msg = testcase.run_platform_command("ls %s" % file_path)
1508        if err.Success() and retcode == 0:
1509            break
1510        if i < max_attempts:
1511            # Exponential backoff!
1512            import time
1513            time.sleep(pow(2, i) * 0.25)
1514    else:
1515        testcase.fail(
1516            "File %s not found even after %d attempts." %
1517            (file_path, max_attempts))
1518
1519    return read_file_on_target(testcase, file_path)
1520
1521def packetlog_get_process_info(log):
1522    """parse a gdb-remote packet log file and extract the response to qProcessInfo"""
1523    process_info = dict()
1524    with open(log, "r") as logfile:
1525        process_info_ostype = None
1526        expect_process_info_response = False
1527        for line in logfile:
1528            if expect_process_info_response:
1529                for pair in line.split(';'):
1530                    keyval = pair.split(':')
1531                    if len(keyval) == 2:
1532                        process_info[keyval[0]] = keyval[1]
1533                break
1534            if 'send packet: $qProcessInfo#' in line:
1535                expect_process_info_response = True
1536    return process_info
1537
1538def packetlog_get_dylib_info(log):
1539    """parse a gdb-remote packet log file and extract the *last* complete
1540    (=> fetch_all_solibs=true) response to jGetLoadedDynamicLibrariesInfos"""
1541    import json
1542    dylib_info = None
1543    with open(log, "r") as logfile:
1544        dylib_info = None
1545        expect_dylib_info_response = False
1546        for line in logfile:
1547            if expect_dylib_info_response:
1548                while line[0] != '$':
1549                    line = line[1:]
1550                line = line[1:]
1551                # Unescape '}'.
1552                dylib_info = json.loads(line.replace('}]','}')[:-4])
1553                expect_dylib_info_response = False
1554            if 'send packet: $jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}' in line:
1555                expect_dylib_info_response = True
1556
1557    return dylib_info
1558