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