xref: /openbsd-src/gnu/llvm/lldb/packages/Python/lldbsuite/test/lldbutil.py (revision be691f3bb6417f04a68938fadbcaee2d5795e764)
1061da546Spatrick"""
2061da546SpatrickThis LLDB module contains miscellaneous utilities.
3061da546SpatrickSome of the test suite takes advantage of the utility functions defined here.
4061da546SpatrickThey can also be useful for general purpose lldb scripting.
5061da546Spatrick"""
6061da546Spatrick
7061da546Spatrickfrom __future__ import print_function
8061da546Spatrickfrom __future__ import absolute_import
9061da546Spatrick
10061da546Spatrick# System modules
11061da546Spatrickimport errno
12061da546Spatrickimport os
13061da546Spatrickimport re
14061da546Spatrickimport sys
15*be691f3bSpatrickimport subprocess
16061da546Spatrick
17061da546Spatrick# Third-party modules
18061da546Spatrickfrom six import StringIO as SixStringIO
19061da546Spatrickimport six
20061da546Spatrick
21061da546Spatrick# LLDB modules
22061da546Spatrickimport lldb
23061da546Spatrickfrom . import lldbtest_config
24*be691f3bSpatrickfrom . import configuration
25061da546Spatrick
26*be691f3bSpatrick# How often failed simulator process launches are retried.
27*be691f3bSpatrickSIMULATOR_RETRY = 3
28061da546Spatrick
29061da546Spatrick# ===================================================
30061da546Spatrick# Utilities for locating/checking executable programs
31061da546Spatrick# ===================================================
32061da546Spatrick
33061da546Spatrickdef is_exe(fpath):
34061da546Spatrick    """Returns True if fpath is an executable."""
35061da546Spatrick    return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
36061da546Spatrick
37061da546Spatrick
38061da546Spatrickdef which(program):
39061da546Spatrick    """Returns the full path to a program; None otherwise."""
40061da546Spatrick    fpath, fname = os.path.split(program)
41061da546Spatrick    if fpath:
42061da546Spatrick        if is_exe(program):
43061da546Spatrick            return program
44061da546Spatrick    else:
45061da546Spatrick        for path in os.environ["PATH"].split(os.pathsep):
46061da546Spatrick            exe_file = os.path.join(path, program)
47061da546Spatrick            if is_exe(exe_file):
48061da546Spatrick                return exe_file
49061da546Spatrick    return None
50061da546Spatrick
51061da546Spatrickdef mkdir_p(path):
52061da546Spatrick    try:
53061da546Spatrick        os.makedirs(path)
54061da546Spatrick    except OSError as e:
55061da546Spatrick        if e.errno != errno.EEXIST:
56061da546Spatrick            raise
57061da546Spatrick    if not os.path.isdir(path):
58061da546Spatrick        raise OSError(errno.ENOTDIR, "%s is not a directory"%path)
59*be691f3bSpatrick
60*be691f3bSpatrick
61*be691f3bSpatrick# ============================
62*be691f3bSpatrick# Dealing with SDK and triples
63*be691f3bSpatrick# ============================
64*be691f3bSpatrick
65*be691f3bSpatrickdef get_xcode_sdk(os, env):
66*be691f3bSpatrick    # Respect --apple-sdk <path> if it's specified. If the SDK is simply
67*be691f3bSpatrick    # mounted from some disk image, and not actually installed, this is the
68*be691f3bSpatrick    # only way to use it.
69*be691f3bSpatrick    if configuration.apple_sdk:
70*be691f3bSpatrick        return configuration.apple_sdk
71*be691f3bSpatrick    if os == "ios":
72*be691f3bSpatrick        if env == "simulator":
73*be691f3bSpatrick            return "iphonesimulator"
74*be691f3bSpatrick        if env == "macabi":
75*be691f3bSpatrick            return "macosx"
76*be691f3bSpatrick        return "iphoneos"
77*be691f3bSpatrick    elif os == "tvos":
78*be691f3bSpatrick        if env == "simulator":
79*be691f3bSpatrick            return "appletvsimulator"
80*be691f3bSpatrick        return "appletvos"
81*be691f3bSpatrick    elif os == "watchos":
82*be691f3bSpatrick        if env == "simulator":
83*be691f3bSpatrick            return "watchsimulator"
84*be691f3bSpatrick        return "watchos"
85*be691f3bSpatrick    return os
86*be691f3bSpatrick
87*be691f3bSpatrick
88*be691f3bSpatrickdef get_xcode_sdk_version(sdk):
89*be691f3bSpatrick    return subprocess.check_output(
90*be691f3bSpatrick        ['xcrun', '--sdk', sdk, '--show-sdk-version']).rstrip().decode('utf-8')
91*be691f3bSpatrick
92*be691f3bSpatrick
93*be691f3bSpatrickdef get_xcode_sdk_root(sdk):
94*be691f3bSpatrick    return subprocess.check_output(['xcrun', '--sdk', sdk, '--show-sdk-path'
95*be691f3bSpatrick                                    ]).rstrip().decode('utf-8')
96*be691f3bSpatrick
97*be691f3bSpatrick
98*be691f3bSpatrickdef get_xcode_clang(sdk):
99*be691f3bSpatrick    return subprocess.check_output(['xcrun', '-sdk', sdk, '-f', 'clang'
100*be691f3bSpatrick                                    ]).rstrip().decode("utf-8")
101*be691f3bSpatrick
102*be691f3bSpatrick
103061da546Spatrick# ===================================================
104061da546Spatrick# Disassembly for an SBFunction or an SBSymbol object
105061da546Spatrick# ===================================================
106061da546Spatrick
107061da546Spatrick
108061da546Spatrickdef disassemble(target, function_or_symbol):
109061da546Spatrick    """Disassemble the function or symbol given a target.
110061da546Spatrick
111061da546Spatrick    It returns the disassembly content in a string object.
112061da546Spatrick    """
113061da546Spatrick    buf = SixStringIO()
114061da546Spatrick    insts = function_or_symbol.GetInstructions(target)
115061da546Spatrick    for i in insts:
116061da546Spatrick        print(i, file=buf)
117061da546Spatrick    return buf.getvalue()
118061da546Spatrick
119061da546Spatrick# ==========================================================
120061da546Spatrick# Integer (byte size 1, 2, 4, and 8) to bytearray conversion
121061da546Spatrick# ==========================================================
122061da546Spatrick
123061da546Spatrick
124061da546Spatrickdef int_to_bytearray(val, bytesize):
125061da546Spatrick    """Utility function to convert an integer into a bytearray.
126061da546Spatrick
127061da546Spatrick    It returns the bytearray in the little endian format.  It is easy to get the
128061da546Spatrick    big endian format, just do ba.reverse() on the returned object.
129061da546Spatrick    """
130061da546Spatrick    import struct
131061da546Spatrick
132061da546Spatrick    if bytesize == 1:
133061da546Spatrick        return bytearray([val])
134061da546Spatrick
135061da546Spatrick    # Little endian followed by a format character.
136061da546Spatrick    template = "<%c"
137061da546Spatrick    if bytesize == 2:
138061da546Spatrick        fmt = template % 'h'
139061da546Spatrick    elif bytesize == 4:
140061da546Spatrick        fmt = template % 'i'
141061da546Spatrick    elif bytesize == 4:
142061da546Spatrick        fmt = template % 'q'
143061da546Spatrick    else:
144061da546Spatrick        return None
145061da546Spatrick
146061da546Spatrick    packed = struct.pack(fmt, val)
147061da546Spatrick    return bytearray(packed)
148061da546Spatrick
149061da546Spatrick
150061da546Spatrickdef bytearray_to_int(bytes, bytesize):
151061da546Spatrick    """Utility function to convert a bytearray into an integer.
152061da546Spatrick
153061da546Spatrick    It interprets the bytearray in the little endian format. For a big endian
154061da546Spatrick    bytearray, just do ba.reverse() on the object before passing it in.
155061da546Spatrick    """
156061da546Spatrick    import struct
157061da546Spatrick
158061da546Spatrick    if bytesize == 1:
159061da546Spatrick        return bytes[0]
160061da546Spatrick
161061da546Spatrick    # Little endian followed by a format character.
162061da546Spatrick    template = "<%c"
163061da546Spatrick    if bytesize == 2:
164061da546Spatrick        fmt = template % 'h'
165061da546Spatrick    elif bytesize == 4:
166061da546Spatrick        fmt = template % 'i'
167061da546Spatrick    elif bytesize == 4:
168061da546Spatrick        fmt = template % 'q'
169061da546Spatrick    else:
170061da546Spatrick        return None
171061da546Spatrick
172061da546Spatrick    unpacked = struct.unpack_from(fmt, bytes)
173061da546Spatrick    return unpacked[0]
174061da546Spatrick
175061da546Spatrick
176061da546Spatrick# ==============================================================
177061da546Spatrick# Get the description of an lldb object or None if not available
178061da546Spatrick# ==============================================================
179061da546Spatrickdef get_description(obj, option=None):
180061da546Spatrick    """Calls lldb_obj.GetDescription() and returns a string, or None.
181061da546Spatrick
182061da546Spatrick    For SBTarget, SBBreakpointLocation, and SBWatchpoint lldb objects, an extra
183061da546Spatrick    option can be passed in to describe the detailed level of description
184061da546Spatrick    desired:
185061da546Spatrick        o lldb.eDescriptionLevelBrief
186061da546Spatrick        o lldb.eDescriptionLevelFull
187061da546Spatrick        o lldb.eDescriptionLevelVerbose
188061da546Spatrick    """
189061da546Spatrick    method = getattr(obj, 'GetDescription')
190061da546Spatrick    if not method:
191061da546Spatrick        return None
192061da546Spatrick    tuple = (lldb.SBTarget, lldb.SBBreakpointLocation, lldb.SBWatchpoint)
193061da546Spatrick    if isinstance(obj, tuple):
194061da546Spatrick        if option is None:
195061da546Spatrick            option = lldb.eDescriptionLevelBrief
196061da546Spatrick
197061da546Spatrick    stream = lldb.SBStream()
198061da546Spatrick    if option is None:
199061da546Spatrick        success = method(stream)
200061da546Spatrick    else:
201061da546Spatrick        success = method(stream, option)
202061da546Spatrick    if not success:
203061da546Spatrick        return None
204061da546Spatrick    return stream.GetData()
205061da546Spatrick
206061da546Spatrick
207061da546Spatrick# =================================================
208061da546Spatrick# Convert some enum value to its string counterpart
209061da546Spatrick# =================================================
210061da546Spatrick
211061da546Spatrickdef state_type_to_str(enum):
212061da546Spatrick    """Returns the stateType string given an enum."""
213061da546Spatrick    if enum == lldb.eStateInvalid:
214061da546Spatrick        return "invalid"
215061da546Spatrick    elif enum == lldb.eStateUnloaded:
216061da546Spatrick        return "unloaded"
217061da546Spatrick    elif enum == lldb.eStateConnected:
218061da546Spatrick        return "connected"
219061da546Spatrick    elif enum == lldb.eStateAttaching:
220061da546Spatrick        return "attaching"
221061da546Spatrick    elif enum == lldb.eStateLaunching:
222061da546Spatrick        return "launching"
223061da546Spatrick    elif enum == lldb.eStateStopped:
224061da546Spatrick        return "stopped"
225061da546Spatrick    elif enum == lldb.eStateRunning:
226061da546Spatrick        return "running"
227061da546Spatrick    elif enum == lldb.eStateStepping:
228061da546Spatrick        return "stepping"
229061da546Spatrick    elif enum == lldb.eStateCrashed:
230061da546Spatrick        return "crashed"
231061da546Spatrick    elif enum == lldb.eStateDetached:
232061da546Spatrick        return "detached"
233061da546Spatrick    elif enum == lldb.eStateExited:
234061da546Spatrick        return "exited"
235061da546Spatrick    elif enum == lldb.eStateSuspended:
236061da546Spatrick        return "suspended"
237061da546Spatrick    else:
238061da546Spatrick        raise Exception("Unknown StateType enum")
239061da546Spatrick
240061da546Spatrick
241061da546Spatrickdef stop_reason_to_str(enum):
242061da546Spatrick    """Returns the stopReason string given an enum."""
243061da546Spatrick    if enum == lldb.eStopReasonInvalid:
244061da546Spatrick        return "invalid"
245061da546Spatrick    elif enum == lldb.eStopReasonNone:
246061da546Spatrick        return "none"
247061da546Spatrick    elif enum == lldb.eStopReasonTrace:
248061da546Spatrick        return "trace"
249061da546Spatrick    elif enum == lldb.eStopReasonBreakpoint:
250061da546Spatrick        return "breakpoint"
251061da546Spatrick    elif enum == lldb.eStopReasonWatchpoint:
252061da546Spatrick        return "watchpoint"
253061da546Spatrick    elif enum == lldb.eStopReasonExec:
254061da546Spatrick        return "exec"
255*be691f3bSpatrick    elif enum == lldb.eStopReasonFork:
256*be691f3bSpatrick        return "fork"
257*be691f3bSpatrick    elif enum == lldb.eStopReasonVFork:
258*be691f3bSpatrick        return "vfork"
259*be691f3bSpatrick    elif enum == lldb.eStopReasonVForkDone:
260*be691f3bSpatrick        return "vforkdone"
261061da546Spatrick    elif enum == lldb.eStopReasonSignal:
262061da546Spatrick        return "signal"
263061da546Spatrick    elif enum == lldb.eStopReasonException:
264061da546Spatrick        return "exception"
265061da546Spatrick    elif enum == lldb.eStopReasonPlanComplete:
266061da546Spatrick        return "plancomplete"
267061da546Spatrick    elif enum == lldb.eStopReasonThreadExiting:
268061da546Spatrick        return "threadexiting"
269061da546Spatrick    else:
270061da546Spatrick        raise Exception("Unknown StopReason enum")
271061da546Spatrick
272061da546Spatrick
273061da546Spatrickdef symbol_type_to_str(enum):
274061da546Spatrick    """Returns the symbolType string given an enum."""
275061da546Spatrick    if enum == lldb.eSymbolTypeInvalid:
276061da546Spatrick        return "invalid"
277061da546Spatrick    elif enum == lldb.eSymbolTypeAbsolute:
278061da546Spatrick        return "absolute"
279061da546Spatrick    elif enum == lldb.eSymbolTypeCode:
280061da546Spatrick        return "code"
281061da546Spatrick    elif enum == lldb.eSymbolTypeData:
282061da546Spatrick        return "data"
283061da546Spatrick    elif enum == lldb.eSymbolTypeTrampoline:
284061da546Spatrick        return "trampoline"
285061da546Spatrick    elif enum == lldb.eSymbolTypeRuntime:
286061da546Spatrick        return "runtime"
287061da546Spatrick    elif enum == lldb.eSymbolTypeException:
288061da546Spatrick        return "exception"
289061da546Spatrick    elif enum == lldb.eSymbolTypeSourceFile:
290061da546Spatrick        return "sourcefile"
291061da546Spatrick    elif enum == lldb.eSymbolTypeHeaderFile:
292061da546Spatrick        return "headerfile"
293061da546Spatrick    elif enum == lldb.eSymbolTypeObjectFile:
294061da546Spatrick        return "objectfile"
295061da546Spatrick    elif enum == lldb.eSymbolTypeCommonBlock:
296061da546Spatrick        return "commonblock"
297061da546Spatrick    elif enum == lldb.eSymbolTypeBlock:
298061da546Spatrick        return "block"
299061da546Spatrick    elif enum == lldb.eSymbolTypeLocal:
300061da546Spatrick        return "local"
301061da546Spatrick    elif enum == lldb.eSymbolTypeParam:
302061da546Spatrick        return "param"
303061da546Spatrick    elif enum == lldb.eSymbolTypeVariable:
304061da546Spatrick        return "variable"
305061da546Spatrick    elif enum == lldb.eSymbolTypeVariableType:
306061da546Spatrick        return "variabletype"
307061da546Spatrick    elif enum == lldb.eSymbolTypeLineEntry:
308061da546Spatrick        return "lineentry"
309061da546Spatrick    elif enum == lldb.eSymbolTypeLineHeader:
310061da546Spatrick        return "lineheader"
311061da546Spatrick    elif enum == lldb.eSymbolTypeScopeBegin:
312061da546Spatrick        return "scopebegin"
313061da546Spatrick    elif enum == lldb.eSymbolTypeScopeEnd:
314061da546Spatrick        return "scopeend"
315061da546Spatrick    elif enum == lldb.eSymbolTypeAdditional:
316061da546Spatrick        return "additional"
317061da546Spatrick    elif enum == lldb.eSymbolTypeCompiler:
318061da546Spatrick        return "compiler"
319061da546Spatrick    elif enum == lldb.eSymbolTypeInstrumentation:
320061da546Spatrick        return "instrumentation"
321061da546Spatrick    elif enum == lldb.eSymbolTypeUndefined:
322061da546Spatrick        return "undefined"
323061da546Spatrick
324061da546Spatrick
325061da546Spatrickdef value_type_to_str(enum):
326061da546Spatrick    """Returns the valueType string given an enum."""
327061da546Spatrick    if enum == lldb.eValueTypeInvalid:
328061da546Spatrick        return "invalid"
329061da546Spatrick    elif enum == lldb.eValueTypeVariableGlobal:
330061da546Spatrick        return "global_variable"
331061da546Spatrick    elif enum == lldb.eValueTypeVariableStatic:
332061da546Spatrick        return "static_variable"
333061da546Spatrick    elif enum == lldb.eValueTypeVariableArgument:
334061da546Spatrick        return "argument_variable"
335061da546Spatrick    elif enum == lldb.eValueTypeVariableLocal:
336061da546Spatrick        return "local_variable"
337061da546Spatrick    elif enum == lldb.eValueTypeRegister:
338061da546Spatrick        return "register"
339061da546Spatrick    elif enum == lldb.eValueTypeRegisterSet:
340061da546Spatrick        return "register_set"
341061da546Spatrick    elif enum == lldb.eValueTypeConstResult:
342061da546Spatrick        return "constant_result"
343061da546Spatrick    else:
344061da546Spatrick        raise Exception("Unknown ValueType enum")
345061da546Spatrick
346061da546Spatrick
347061da546Spatrick# ==================================================
348061da546Spatrick# Get stopped threads due to each stop reason.
349061da546Spatrick# ==================================================
350061da546Spatrick
351061da546Spatrickdef sort_stopped_threads(process,
352061da546Spatrick                         breakpoint_threads=None,
353061da546Spatrick                         crashed_threads=None,
354061da546Spatrick                         watchpoint_threads=None,
355061da546Spatrick                         signal_threads=None,
356061da546Spatrick                         exiting_threads=None,
357061da546Spatrick                         other_threads=None):
358061da546Spatrick    """ Fills array *_threads with threads stopped for the corresponding stop
359061da546Spatrick        reason.
360061da546Spatrick    """
361061da546Spatrick    for lst in [breakpoint_threads,
362061da546Spatrick                watchpoint_threads,
363061da546Spatrick                signal_threads,
364061da546Spatrick                exiting_threads,
365061da546Spatrick                other_threads]:
366061da546Spatrick        if lst is not None:
367061da546Spatrick            lst[:] = []
368061da546Spatrick
369061da546Spatrick    for thread in process:
370061da546Spatrick        dispatched = False
371061da546Spatrick        for (reason, list) in [(lldb.eStopReasonBreakpoint, breakpoint_threads),
372061da546Spatrick                               (lldb.eStopReasonException, crashed_threads),
373061da546Spatrick                               (lldb.eStopReasonWatchpoint, watchpoint_threads),
374061da546Spatrick                               (lldb.eStopReasonSignal, signal_threads),
375061da546Spatrick                               (lldb.eStopReasonThreadExiting, exiting_threads),
376061da546Spatrick                               (None, other_threads)]:
377061da546Spatrick            if not dispatched and list is not None:
378061da546Spatrick                if thread.GetStopReason() == reason or reason is None:
379061da546Spatrick                    list.append(thread)
380061da546Spatrick                    dispatched = True
381061da546Spatrick
382061da546Spatrick# ==================================================
383061da546Spatrick# Utility functions for setting breakpoints
384061da546Spatrick# ==================================================
385061da546Spatrick
386061da546Spatrickdef run_break_set_by_script(
387061da546Spatrick        test,
388061da546Spatrick        class_name,
389061da546Spatrick        extra_options=None,
390061da546Spatrick        num_expected_locations=1):
391061da546Spatrick    """Set a scripted breakpoint.  Check that it got the right number of locations."""
392061da546Spatrick    test.assertTrue(class_name is not None, "Must pass in a class name.")
393061da546Spatrick    command = "breakpoint set -P " + class_name
394061da546Spatrick    if extra_options is not None:
395061da546Spatrick        command += " " + extra_options
396061da546Spatrick
397061da546Spatrick    break_results = run_break_set_command(test, command)
398061da546Spatrick    check_breakpoint_result(test, break_results, num_locations=num_expected_locations)
399061da546Spatrick    return get_bpno_from_match(break_results)
400061da546Spatrick
401061da546Spatrickdef run_break_set_by_file_and_line(
402061da546Spatrick        test,
403061da546Spatrick        file_name,
404061da546Spatrick        line_number,
405061da546Spatrick        extra_options=None,
406061da546Spatrick        num_expected_locations=1,
407061da546Spatrick        loc_exact=False,
408061da546Spatrick        module_name=None):
409061da546Spatrick    """Set a breakpoint by file and line, returning the breakpoint number.
410061da546Spatrick
411061da546Spatrick    If extra_options is not None, then we append it to the breakpoint set command.
412061da546Spatrick
413061da546Spatrick    If num_expected_locations is -1, we check that we got AT LEAST one location. If num_expected_locations is -2, we don't
414061da546Spatrick    check the actual number at all. Otherwise, we check that num_expected_locations equals the number of locations.
415061da546Spatrick
416061da546Spatrick    If loc_exact is true, we check that there is one location, and that location must be at the input file and line number."""
417061da546Spatrick
418061da546Spatrick    if file_name is None:
419061da546Spatrick        command = 'breakpoint set -l %d' % (line_number)
420061da546Spatrick    else:
421061da546Spatrick        command = 'breakpoint set -f "%s" -l %d' % (file_name, line_number)
422061da546Spatrick
423061da546Spatrick    if module_name:
424061da546Spatrick        command += " --shlib '%s'" % (module_name)
425061da546Spatrick
426061da546Spatrick    if extra_options:
427061da546Spatrick        command += " " + extra_options
428061da546Spatrick
429061da546Spatrick    break_results = run_break_set_command(test, command)
430061da546Spatrick
431061da546Spatrick    if num_expected_locations == 1 and loc_exact:
432061da546Spatrick        check_breakpoint_result(
433061da546Spatrick            test,
434061da546Spatrick            break_results,
435061da546Spatrick            num_locations=num_expected_locations,
436061da546Spatrick            file_name=file_name,
437061da546Spatrick            line_number=line_number,
438061da546Spatrick            module_name=module_name)
439061da546Spatrick    else:
440061da546Spatrick        check_breakpoint_result(
441061da546Spatrick            test,
442061da546Spatrick            break_results,
443061da546Spatrick            num_locations=num_expected_locations)
444061da546Spatrick
445061da546Spatrick    return get_bpno_from_match(break_results)
446061da546Spatrick
447061da546Spatrick
448061da546Spatrickdef run_break_set_by_symbol(
449061da546Spatrick        test,
450061da546Spatrick        symbol,
451061da546Spatrick        extra_options=None,
452061da546Spatrick        num_expected_locations=-1,
453061da546Spatrick        sym_exact=False,
454061da546Spatrick        module_name=None):
455061da546Spatrick    """Set a breakpoint by symbol name.  Common options are the same as run_break_set_by_file_and_line.
456061da546Spatrick
457061da546Spatrick    If sym_exact is true, then the output symbol must match the input exactly, otherwise we do a substring match."""
458061da546Spatrick    command = 'breakpoint set -n "%s"' % (symbol)
459061da546Spatrick
460061da546Spatrick    if module_name:
461061da546Spatrick        command += " --shlib '%s'" % (module_name)
462061da546Spatrick
463061da546Spatrick    if extra_options:
464061da546Spatrick        command += " " + extra_options
465061da546Spatrick
466061da546Spatrick    break_results = run_break_set_command(test, command)
467061da546Spatrick
468061da546Spatrick    if num_expected_locations == 1 and sym_exact:
469061da546Spatrick        check_breakpoint_result(
470061da546Spatrick            test,
471061da546Spatrick            break_results,
472061da546Spatrick            num_locations=num_expected_locations,
473061da546Spatrick            symbol_name=symbol,
474061da546Spatrick            module_name=module_name)
475061da546Spatrick    else:
476061da546Spatrick        check_breakpoint_result(
477061da546Spatrick            test,
478061da546Spatrick            break_results,
479061da546Spatrick            num_locations=num_expected_locations)
480061da546Spatrick
481061da546Spatrick    return get_bpno_from_match(break_results)
482061da546Spatrick
483061da546Spatrick
484061da546Spatrickdef run_break_set_by_selector(
485061da546Spatrick        test,
486061da546Spatrick        selector,
487061da546Spatrick        extra_options=None,
488061da546Spatrick        num_expected_locations=-1,
489061da546Spatrick        module_name=None):
490061da546Spatrick    """Set a breakpoint by selector.  Common options are the same as run_break_set_by_file_and_line."""
491061da546Spatrick
492061da546Spatrick    command = 'breakpoint set -S "%s"' % (selector)
493061da546Spatrick
494061da546Spatrick    if module_name:
495061da546Spatrick        command += ' --shlib "%s"' % (module_name)
496061da546Spatrick
497061da546Spatrick    if extra_options:
498061da546Spatrick        command += " " + extra_options
499061da546Spatrick
500061da546Spatrick    break_results = run_break_set_command(test, command)
501061da546Spatrick
502061da546Spatrick    if num_expected_locations == 1:
503061da546Spatrick        check_breakpoint_result(
504061da546Spatrick            test,
505061da546Spatrick            break_results,
506061da546Spatrick            num_locations=num_expected_locations,
507061da546Spatrick            symbol_name=selector,
508061da546Spatrick            symbol_match_exact=False,
509061da546Spatrick            module_name=module_name)
510061da546Spatrick    else:
511061da546Spatrick        check_breakpoint_result(
512061da546Spatrick            test,
513061da546Spatrick            break_results,
514061da546Spatrick            num_locations=num_expected_locations)
515061da546Spatrick
516061da546Spatrick    return get_bpno_from_match(break_results)
517061da546Spatrick
518061da546Spatrick
519061da546Spatrickdef run_break_set_by_regexp(
520061da546Spatrick        test,
521061da546Spatrick        regexp,
522061da546Spatrick        extra_options=None,
523061da546Spatrick        num_expected_locations=-1):
524061da546Spatrick    """Set a breakpoint by regular expression match on symbol name.  Common options are the same as run_break_set_by_file_and_line."""
525061da546Spatrick
526061da546Spatrick    command = 'breakpoint set -r "%s"' % (regexp)
527061da546Spatrick    if extra_options:
528061da546Spatrick        command += " " + extra_options
529061da546Spatrick
530061da546Spatrick    break_results = run_break_set_command(test, command)
531061da546Spatrick
532061da546Spatrick    check_breakpoint_result(
533061da546Spatrick        test,
534061da546Spatrick        break_results,
535061da546Spatrick        num_locations=num_expected_locations)
536061da546Spatrick
537061da546Spatrick    return get_bpno_from_match(break_results)
538061da546Spatrick
539061da546Spatrick
540061da546Spatrickdef run_break_set_by_source_regexp(
541061da546Spatrick        test,
542061da546Spatrick        regexp,
543061da546Spatrick        extra_options=None,
544061da546Spatrick        num_expected_locations=-1):
545061da546Spatrick    """Set a breakpoint by source regular expression.  Common options are the same as run_break_set_by_file_and_line."""
546061da546Spatrick    command = 'breakpoint set -p "%s"' % (regexp)
547061da546Spatrick    if extra_options:
548061da546Spatrick        command += " " + extra_options
549061da546Spatrick
550061da546Spatrick    break_results = run_break_set_command(test, command)
551061da546Spatrick
552061da546Spatrick    check_breakpoint_result(
553061da546Spatrick        test,
554061da546Spatrick        break_results,
555061da546Spatrick        num_locations=num_expected_locations)
556061da546Spatrick
557061da546Spatrick    return get_bpno_from_match(break_results)
558061da546Spatrick
559*be691f3bSpatrickdef run_break_set_by_file_colon_line(
560*be691f3bSpatrick        test,
561*be691f3bSpatrick        specifier,
562*be691f3bSpatrick        path,
563*be691f3bSpatrick        line_number,
564*be691f3bSpatrick        column_number = 0,
565*be691f3bSpatrick        extra_options=None,
566*be691f3bSpatrick        num_expected_locations=-1):
567*be691f3bSpatrick    command = 'breakpoint set -y "%s"'%(specifier)
568*be691f3bSpatrick    if extra_options:
569*be691f3bSpatrick        command += " " + extra_options
570*be691f3bSpatrick
571*be691f3bSpatrick    print("About to run: '%s'", command)
572*be691f3bSpatrick    break_results = run_break_set_command(test, command)
573*be691f3bSpatrick    check_breakpoint_result(
574*be691f3bSpatrick        test,
575*be691f3bSpatrick        break_results,
576*be691f3bSpatrick        num_locations = num_expected_locations,
577*be691f3bSpatrick        file_name = path,
578*be691f3bSpatrick        line_number = line_number,
579*be691f3bSpatrick        column_number = column_number)
580*be691f3bSpatrick
581*be691f3bSpatrick    return get_bpno_from_match(break_results)
582061da546Spatrick
583061da546Spatrickdef run_break_set_command(test, command):
584061da546Spatrick    """Run the command passed in - it must be some break set variant - and analyze the result.
585061da546Spatrick    Returns a dictionary of information gleaned from the command-line results.
586061da546Spatrick    Will assert if the breakpoint setting fails altogether.
587061da546Spatrick
588061da546Spatrick    Dictionary will contain:
589061da546Spatrick        bpno          - breakpoint of the newly created breakpoint, -1 on error.
590061da546Spatrick        num_locations - number of locations set for the breakpoint.
591061da546Spatrick
592061da546Spatrick    If there is only one location, the dictionary MAY contain:
593061da546Spatrick        file          - source file name
594061da546Spatrick        line_no       - source line number
595*be691f3bSpatrick        column        - source column number
596061da546Spatrick        symbol        - symbol name
597061da546Spatrick        inline_symbol - inlined symbol name
598061da546Spatrick        offset        - offset from the original symbol
599061da546Spatrick        module        - module
600061da546Spatrick        address       - address at which the breakpoint was set."""
601061da546Spatrick
602061da546Spatrick    patterns = [
603061da546Spatrick        r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>[0-9]+) locations\.$",
604061da546Spatrick        r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>no) locations \(pending\)\.",
605061da546Spatrick        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]+)$",
606061da546Spatrick        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]+)$"]
607061da546Spatrick    match_object = test.match(command, patterns)
608061da546Spatrick    break_results = match_object.groupdict()
609061da546Spatrick
610061da546Spatrick    # We always insert the breakpoint number, setting it to -1 if we couldn't find it
611061da546Spatrick    # Also, make sure it gets stored as an integer.
612061da546Spatrick    if not 'bpno' in break_results:
613061da546Spatrick        break_results['bpno'] = -1
614061da546Spatrick    else:
615061da546Spatrick        break_results['bpno'] = int(break_results['bpno'])
616061da546Spatrick
617061da546Spatrick    # We always insert the number of locations
618061da546Spatrick    # If ONE location is set for the breakpoint, then the output doesn't mention locations, but it has to be 1...
619061da546Spatrick    # We also make sure it is an integer.
620061da546Spatrick
621061da546Spatrick    if not 'num_locations' in break_results:
622061da546Spatrick        num_locations = 1
623061da546Spatrick    else:
624061da546Spatrick        num_locations = break_results['num_locations']
625061da546Spatrick        if num_locations == 'no':
626061da546Spatrick            num_locations = 0
627061da546Spatrick        else:
628061da546Spatrick            num_locations = int(break_results['num_locations'])
629061da546Spatrick
630061da546Spatrick    break_results['num_locations'] = num_locations
631061da546Spatrick
632061da546Spatrick    if 'line_no' in break_results:
633061da546Spatrick        break_results['line_no'] = int(break_results['line_no'])
634061da546Spatrick
635061da546Spatrick    return break_results
636061da546Spatrick
637061da546Spatrick
638061da546Spatrickdef get_bpno_from_match(break_results):
639061da546Spatrick    return int(break_results['bpno'])
640061da546Spatrick
641061da546Spatrick
642061da546Spatrickdef check_breakpoint_result(
643061da546Spatrick        test,
644061da546Spatrick        break_results,
645061da546Spatrick        file_name=None,
646061da546Spatrick        line_number=-1,
647*be691f3bSpatrick        column_number=0,
648061da546Spatrick        symbol_name=None,
649061da546Spatrick        symbol_match_exact=True,
650061da546Spatrick        module_name=None,
651061da546Spatrick        offset=-1,
652061da546Spatrick        num_locations=-1):
653061da546Spatrick
654061da546Spatrick    out_num_locations = break_results['num_locations']
655061da546Spatrick
656061da546Spatrick    if num_locations == -1:
657061da546Spatrick        test.assertTrue(out_num_locations > 0,
658061da546Spatrick                        "Expecting one or more locations, got none.")
659061da546Spatrick    elif num_locations != -2:
660061da546Spatrick        test.assertTrue(
661061da546Spatrick            num_locations == out_num_locations,
662061da546Spatrick            "Expecting %d locations, got %d." %
663061da546Spatrick            (num_locations,
664061da546Spatrick             out_num_locations))
665061da546Spatrick
666061da546Spatrick    if file_name:
667061da546Spatrick        out_file_name = ""
668061da546Spatrick        if 'file' in break_results:
669061da546Spatrick            out_file_name = break_results['file']
670061da546Spatrick        test.assertTrue(
671061da546Spatrick            file_name.endswith(out_file_name),
672061da546Spatrick            "Breakpoint file name '%s' doesn't match resultant name '%s'." %
673061da546Spatrick            (file_name,
674061da546Spatrick             out_file_name))
675061da546Spatrick
676061da546Spatrick    if line_number != -1:
677061da546Spatrick        out_line_number = -1
678061da546Spatrick        if 'line_no' in break_results:
679061da546Spatrick            out_line_number = break_results['line_no']
680061da546Spatrick
681061da546Spatrick        test.assertTrue(
682061da546Spatrick            line_number == out_line_number,
683061da546Spatrick            "Breakpoint line number %s doesn't match resultant line %s." %
684061da546Spatrick            (line_number,
685061da546Spatrick             out_line_number))
686061da546Spatrick
687*be691f3bSpatrick    if column_number != 0:
688*be691f3bSpatrick        out_column_number = 0
689*be691f3bSpatrick        if 'column' in break_results:
690*be691f3bSpatrick            out_column_number = break_results['column']
691*be691f3bSpatrick
692*be691f3bSpatrick        test.assertTrue(
693*be691f3bSpatrick            column_number == out_column_number,
694*be691f3bSpatrick            "Breakpoint column number %s doesn't match resultant column %s." %
695*be691f3bSpatrick            (column_number,
696*be691f3bSpatrick             out_column_number))
697*be691f3bSpatrick
698061da546Spatrick    if symbol_name:
699061da546Spatrick        out_symbol_name = ""
700061da546Spatrick        # Look first for the inlined symbol name, otherwise use the symbol
701061da546Spatrick        # name:
702061da546Spatrick        if 'inline_symbol' in break_results and break_results['inline_symbol']:
703061da546Spatrick            out_symbol_name = break_results['inline_symbol']
704061da546Spatrick        elif 'symbol' in break_results:
705061da546Spatrick            out_symbol_name = break_results['symbol']
706061da546Spatrick
707061da546Spatrick        if symbol_match_exact:
708061da546Spatrick            test.assertTrue(
709061da546Spatrick                symbol_name == out_symbol_name,
710061da546Spatrick                "Symbol name '%s' doesn't match resultant symbol '%s'." %
711061da546Spatrick                (symbol_name,
712061da546Spatrick                 out_symbol_name))
713061da546Spatrick        else:
714061da546Spatrick            test.assertTrue(
715061da546Spatrick                out_symbol_name.find(symbol_name) != -
716061da546Spatrick                1,
717061da546Spatrick                "Symbol name '%s' isn't in resultant symbol '%s'." %
718061da546Spatrick                (symbol_name,
719061da546Spatrick                 out_symbol_name))
720061da546Spatrick
721061da546Spatrick    if module_name:
722061da546Spatrick        out_module_name = None
723061da546Spatrick        if 'module' in break_results:
724061da546Spatrick            out_module_name = break_results['module']
725061da546Spatrick
726061da546Spatrick        test.assertTrue(
727061da546Spatrick            module_name.find(out_module_name) != -
728061da546Spatrick            1,
729061da546Spatrick            "Symbol module name '%s' isn't in expected module name '%s'." %
730061da546Spatrick            (out_module_name,
731061da546Spatrick             module_name))
732061da546Spatrick
733061da546Spatrick# ==================================================
734061da546Spatrick# Utility functions related to Threads and Processes
735061da546Spatrick# ==================================================
736061da546Spatrick
737061da546Spatrick
738061da546Spatrickdef get_stopped_threads(process, reason):
739061da546Spatrick    """Returns the thread(s) with the specified stop reason in a list.
740061da546Spatrick
741061da546Spatrick    The list can be empty if no such thread exists.
742061da546Spatrick    """
743061da546Spatrick    threads = []
744061da546Spatrick    for t in process:
745061da546Spatrick        if t.GetStopReason() == reason:
746061da546Spatrick            threads.append(t)
747061da546Spatrick    return threads
748061da546Spatrick
749061da546Spatrick
750061da546Spatrickdef get_stopped_thread(process, reason):
751061da546Spatrick    """A convenience function which returns the first thread with the given stop
752061da546Spatrick    reason or None.
753061da546Spatrick
754061da546Spatrick    Example usages:
755061da546Spatrick
756061da546Spatrick    1. Get the stopped thread due to a breakpoint condition
757061da546Spatrick
758061da546Spatrick    ...
759061da546Spatrick        from lldbutil import get_stopped_thread
760061da546Spatrick        thread = get_stopped_thread(process, lldb.eStopReasonPlanComplete)
761061da546Spatrick        self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition")
762061da546Spatrick    ...
763061da546Spatrick
764061da546Spatrick    2. Get the thread stopped due to a breakpoint
765061da546Spatrick
766061da546Spatrick    ...
767061da546Spatrick        from lldbutil import get_stopped_thread
768061da546Spatrick        thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
769061da546Spatrick        self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint")
770061da546Spatrick    ...
771061da546Spatrick
772061da546Spatrick    """
773061da546Spatrick    threads = get_stopped_threads(process, reason)
774061da546Spatrick    if len(threads) == 0:
775061da546Spatrick        return None
776061da546Spatrick    return threads[0]
777061da546Spatrick
778061da546Spatrick
779061da546Spatrickdef get_threads_stopped_at_breakpoint_id(process, bpid):
780061da546Spatrick    """ For a stopped process returns the thread stopped at the breakpoint passed in bkpt"""
781061da546Spatrick    stopped_threads = []
782061da546Spatrick    threads = []
783061da546Spatrick
784061da546Spatrick    stopped_threads = get_stopped_threads(process, lldb.eStopReasonBreakpoint)
785061da546Spatrick
786061da546Spatrick    if len(stopped_threads) == 0:
787061da546Spatrick        return threads
788061da546Spatrick
789061da546Spatrick    for thread in stopped_threads:
790061da546Spatrick        # Make sure we've hit our breakpoint...
791061da546Spatrick        break_id = thread.GetStopReasonDataAtIndex(0)
792061da546Spatrick        if break_id == bpid:
793061da546Spatrick            threads.append(thread)
794061da546Spatrick
795061da546Spatrick    return threads
796061da546Spatrick
797061da546Spatrick
798061da546Spatrickdef get_threads_stopped_at_breakpoint(process, bkpt):
799061da546Spatrick    return get_threads_stopped_at_breakpoint_id(process, bkpt.GetID())
800061da546Spatrick
801061da546Spatrick
802061da546Spatrickdef get_one_thread_stopped_at_breakpoint_id(
803061da546Spatrick        process, bpid, require_exactly_one=True):
804061da546Spatrick    threads = get_threads_stopped_at_breakpoint_id(process, bpid)
805061da546Spatrick    if len(threads) == 0:
806061da546Spatrick        return None
807061da546Spatrick    if require_exactly_one and len(threads) != 1:
808061da546Spatrick        return None
809061da546Spatrick
810061da546Spatrick    return threads[0]
811061da546Spatrick
812061da546Spatrick
813061da546Spatrickdef get_one_thread_stopped_at_breakpoint(
814061da546Spatrick        process, bkpt, require_exactly_one=True):
815061da546Spatrick    return get_one_thread_stopped_at_breakpoint_id(
816061da546Spatrick        process, bkpt.GetID(), require_exactly_one)
817061da546Spatrick
818061da546Spatrick
819061da546Spatrickdef is_thread_crashed(test, thread):
820061da546Spatrick    """In the test suite we dereference a null pointer to simulate a crash. The way this is
821061da546Spatrick    reported depends on the platform."""
822061da546Spatrick    if test.platformIsDarwin():
823061da546Spatrick        return thread.GetStopReason(
824061da546Spatrick        ) == lldb.eStopReasonException and "EXC_BAD_ACCESS" in thread.GetStopDescription(100)
825061da546Spatrick    elif test.getPlatform() == "linux":
826061da546Spatrick        return thread.GetStopReason() == lldb.eStopReasonSignal and thread.GetStopReasonDataAtIndex(
827061da546Spatrick            0) == thread.GetProcess().GetUnixSignals().GetSignalNumberFromName("SIGSEGV")
828061da546Spatrick    elif test.getPlatform() == "windows":
829061da546Spatrick        return "Exception 0xc0000005" in thread.GetStopDescription(200)
830061da546Spatrick    else:
831061da546Spatrick        return "invalid address" in thread.GetStopDescription(100)
832061da546Spatrick
833061da546Spatrick
834061da546Spatrickdef get_crashed_threads(test, process):
835061da546Spatrick    threads = []
836061da546Spatrick    if process.GetState() != lldb.eStateStopped:
837061da546Spatrick        return threads
838061da546Spatrick    for thread in process:
839061da546Spatrick        if is_thread_crashed(test, thread):
840061da546Spatrick            threads.append(thread)
841061da546Spatrick    return threads
842061da546Spatrick
843061da546Spatrick# Helper functions for run_to_{source,name}_breakpoint:
844061da546Spatrick
845061da546Spatrickdef run_to_breakpoint_make_target(test, exe_name = "a.out", in_cwd = True):
846061da546Spatrick    if in_cwd:
847061da546Spatrick        exe = test.getBuildArtifact(exe_name)
848061da546Spatrick
849061da546Spatrick    # Create the target
850061da546Spatrick    target = test.dbg.CreateTarget(exe)
851061da546Spatrick    test.assertTrue(target, "Target: %s is not valid."%(exe_name))
852061da546Spatrick
853061da546Spatrick    # Set environment variables for the inferior.
854061da546Spatrick    if lldbtest_config.inferior_env:
855061da546Spatrick        test.runCmd('settings set target.env-vars {}'.format(
856061da546Spatrick            lldbtest_config.inferior_env))
857061da546Spatrick
858061da546Spatrick    return target
859061da546Spatrick
860061da546Spatrickdef run_to_breakpoint_do_run(test, target, bkpt, launch_info = None,
861061da546Spatrick                             only_one_thread = True, extra_images = None):
862061da546Spatrick
863061da546Spatrick    # Launch the process, and do not stop at the entry point.
864061da546Spatrick    if not launch_info:
865061da546Spatrick        launch_info = target.GetLaunchInfo()
866061da546Spatrick        launch_info.SetWorkingDirectory(test.get_process_working_directory())
867061da546Spatrick
868dda28197Spatrick    if extra_images:
869061da546Spatrick        environ = test.registerSharedLibrariesWithTarget(target, extra_images)
870061da546Spatrick        launch_info.SetEnvironmentEntries(environ, True)
871061da546Spatrick
872061da546Spatrick    error = lldb.SBError()
873061da546Spatrick    process = target.Launch(launch_info, error)
874061da546Spatrick
875*be691f3bSpatrick    # Unfortunate workaround for the iPhone simulator.
876*be691f3bSpatrick    retry = SIMULATOR_RETRY
877*be691f3bSpatrick    while (retry and error.Fail() and error.GetCString() and
878*be691f3bSpatrick           "Unable to boot the Simulator" in error.GetCString()):
879*be691f3bSpatrick        retry -= 1
880*be691f3bSpatrick        print("** Simulator is unresponsive. Retrying %d more time(s)"%retry)
881*be691f3bSpatrick        import time
882*be691f3bSpatrick        time.sleep(60)
883*be691f3bSpatrick        error = lldb.SBError()
884*be691f3bSpatrick        process = target.Launch(launch_info, error)
885*be691f3bSpatrick
886061da546Spatrick    test.assertTrue(process,
887*be691f3bSpatrick                    "Could not create a valid process for %s: %s" %
888*be691f3bSpatrick                    (target.GetExecutable().GetFilename(), error.GetCString()))
889061da546Spatrick    test.assertFalse(error.Fail(),
890061da546Spatrick                     "Process launch failed: %s" % (error.GetCString()))
891061da546Spatrick
892dda28197Spatrick    test.assertEqual(process.GetState(), lldb.eStateStopped)
893dda28197Spatrick
894061da546Spatrick    # Frame #0 should be at our breakpoint.
895061da546Spatrick    threads = get_threads_stopped_at_breakpoint(
896061da546Spatrick                process, bkpt)
897061da546Spatrick
898061da546Spatrick    num_threads = len(threads)
899061da546Spatrick    if only_one_thread:
900061da546Spatrick        test.assertEqual(num_threads, 1, "Expected 1 thread to stop at breakpoint, %d did."%(num_threads))
901061da546Spatrick    else:
902061da546Spatrick        test.assertGreater(num_threads, 0, "No threads stopped at breakpoint")
903061da546Spatrick
904061da546Spatrick    thread = threads[0]
905061da546Spatrick    return (target, process, thread, bkpt)
906061da546Spatrick
907061da546Spatrickdef run_to_name_breakpoint (test, bkpt_name, launch_info = None,
908061da546Spatrick                            exe_name = "a.out",
909061da546Spatrick                            bkpt_module = None,
910061da546Spatrick                            in_cwd = True,
911061da546Spatrick                            only_one_thread = True,
912061da546Spatrick                            extra_images = None):
913061da546Spatrick    """Start up a target, using exe_name as the executable, and run it to
914061da546Spatrick       a breakpoint set by name on bkpt_name restricted to bkpt_module.
915061da546Spatrick
916061da546Spatrick       If you want to pass in launch arguments or environment
917061da546Spatrick       variables, you can optionally pass in an SBLaunchInfo.  If you
918061da546Spatrick       do that, remember to set the working directory as well.
919061da546Spatrick
920061da546Spatrick       If your executable isn't called a.out, you can pass that in.
921061da546Spatrick       And if your executable isn't in the CWD, pass in the absolute
922061da546Spatrick       path to the executable in exe_name, and set in_cwd to False.
923061da546Spatrick
924061da546Spatrick       If you need to restrict the breakpoint to a particular module,
925061da546Spatrick       pass the module name (a string not a FileSpec) in bkpt_module.  If
926061da546Spatrick       nothing is passed in setting will be unrestricted.
927061da546Spatrick
928061da546Spatrick       If the target isn't valid, the breakpoint isn't found, or hit, the
929061da546Spatrick       function will cause a testsuite failure.
930061da546Spatrick
931061da546Spatrick       If successful it returns a tuple with the target process and
932061da546Spatrick       thread that hit the breakpoint, and the breakpoint that we set
933061da546Spatrick       for you.
934061da546Spatrick
935061da546Spatrick       If only_one_thread is true, we require that there be only one
936061da546Spatrick       thread stopped at the breakpoint.  Otherwise we only require one
937061da546Spatrick       or more threads stop there.  If there are more than one, we return
938061da546Spatrick       the first thread that stopped.
939061da546Spatrick    """
940061da546Spatrick
941061da546Spatrick    target = run_to_breakpoint_make_target(test, exe_name, in_cwd)
942061da546Spatrick
943061da546Spatrick    breakpoint = target.BreakpointCreateByName(bkpt_name, bkpt_module)
944061da546Spatrick
945061da546Spatrick
946061da546Spatrick    test.assertTrue(breakpoint.GetNumLocations() > 0,
947061da546Spatrick                    "No locations found for name breakpoint: '%s'."%(bkpt_name))
948061da546Spatrick    return run_to_breakpoint_do_run(test, target, breakpoint, launch_info,
949061da546Spatrick                                    only_one_thread, extra_images)
950061da546Spatrick
951061da546Spatrickdef run_to_source_breakpoint(test, bkpt_pattern, source_spec,
952061da546Spatrick                             launch_info = None, exe_name = "a.out",
953061da546Spatrick                             bkpt_module = None,
954061da546Spatrick                             in_cwd = True,
955061da546Spatrick                             only_one_thread = True,
956061da546Spatrick                             extra_images = None):
957061da546Spatrick    """Start up a target, using exe_name as the executable, and run it to
958061da546Spatrick       a breakpoint set by source regex bkpt_pattern.
959061da546Spatrick
960061da546Spatrick       The rest of the behavior is the same as run_to_name_breakpoint.
961061da546Spatrick    """
962061da546Spatrick
963061da546Spatrick    target = run_to_breakpoint_make_target(test, exe_name, in_cwd)
964061da546Spatrick    # Set the breakpoints
965061da546Spatrick    breakpoint = target.BreakpointCreateBySourceRegex(
966061da546Spatrick            bkpt_pattern, source_spec, bkpt_module)
967061da546Spatrick    test.assertTrue(breakpoint.GetNumLocations() > 0,
968061da546Spatrick        'No locations found for source breakpoint: "%s", file: "%s", dir: "%s"'
969061da546Spatrick        %(bkpt_pattern, source_spec.GetFilename(), source_spec.GetDirectory()))
970061da546Spatrick    return run_to_breakpoint_do_run(test, target, breakpoint, launch_info,
971061da546Spatrick                                    only_one_thread, extra_images)
972061da546Spatrick
973061da546Spatrickdef run_to_line_breakpoint(test, source_spec, line_number, column = 0,
974061da546Spatrick                           launch_info = None, exe_name = "a.out",
975061da546Spatrick                           bkpt_module = None,
976061da546Spatrick                           in_cwd = True,
977061da546Spatrick                           only_one_thread = True,
978061da546Spatrick                           extra_images = None):
979061da546Spatrick    """Start up a target, using exe_name as the executable, and run it to
980061da546Spatrick       a breakpoint set by (source_spec, line_number(, column)).
981061da546Spatrick
982061da546Spatrick       The rest of the behavior is the same as run_to_name_breakpoint.
983061da546Spatrick    """
984061da546Spatrick
985061da546Spatrick    target = run_to_breakpoint_make_target(test, exe_name, in_cwd)
986061da546Spatrick    # Set the breakpoints
987061da546Spatrick    breakpoint = target.BreakpointCreateByLocation(
988061da546Spatrick        source_spec, line_number, column, 0, lldb.SBFileSpecList())
989061da546Spatrick    test.assertTrue(breakpoint.GetNumLocations() > 0,
990061da546Spatrick        'No locations found for line breakpoint: "%s:%d(:%d)", dir: "%s"'
991061da546Spatrick        %(source_spec.GetFilename(), line_number, column,
992061da546Spatrick          source_spec.GetDirectory()))
993061da546Spatrick    return run_to_breakpoint_do_run(test, target, breakpoint, launch_info,
994061da546Spatrick                                    only_one_thread, extra_images)
995061da546Spatrick
996061da546Spatrick
997061da546Spatrickdef continue_to_breakpoint(process, bkpt):
998061da546Spatrick    """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
999061da546Spatrick    process.Continue()
1000061da546Spatrick    if process.GetState() != lldb.eStateStopped:
1001061da546Spatrick        return None
1002061da546Spatrick    else:
1003061da546Spatrick        return get_threads_stopped_at_breakpoint(process, bkpt)
1004061da546Spatrick
1005061da546Spatrick
1006061da546Spatrickdef get_caller_symbol(thread):
1007061da546Spatrick    """
1008061da546Spatrick    Returns the symbol name for the call site of the leaf function.
1009061da546Spatrick    """
1010061da546Spatrick    depth = thread.GetNumFrames()
1011061da546Spatrick    if depth <= 1:
1012061da546Spatrick        return None
1013061da546Spatrick    caller = thread.GetFrameAtIndex(1).GetSymbol()
1014061da546Spatrick    if caller:
1015061da546Spatrick        return caller.GetName()
1016061da546Spatrick    else:
1017061da546Spatrick        return None
1018061da546Spatrick
1019061da546Spatrick
1020061da546Spatrickdef get_function_names(thread):
1021061da546Spatrick    """
1022061da546Spatrick    Returns a sequence of function names from the stack frames of this thread.
1023061da546Spatrick    """
1024061da546Spatrick    def GetFuncName(i):
1025061da546Spatrick        return thread.GetFrameAtIndex(i).GetFunctionName()
1026061da546Spatrick
1027061da546Spatrick    return list(map(GetFuncName, list(range(thread.GetNumFrames()))))
1028061da546Spatrick
1029061da546Spatrick
1030061da546Spatrickdef get_symbol_names(thread):
1031061da546Spatrick    """
1032061da546Spatrick    Returns a sequence of symbols for this thread.
1033061da546Spatrick    """
1034061da546Spatrick    def GetSymbol(i):
1035061da546Spatrick        return thread.GetFrameAtIndex(i).GetSymbol().GetName()
1036061da546Spatrick
1037061da546Spatrick    return list(map(GetSymbol, list(range(thread.GetNumFrames()))))
1038061da546Spatrick
1039061da546Spatrick
1040061da546Spatrickdef get_pc_addresses(thread):
1041061da546Spatrick    """
1042061da546Spatrick    Returns a sequence of pc addresses for this thread.
1043061da546Spatrick    """
1044061da546Spatrick    def GetPCAddress(i):
1045061da546Spatrick        return thread.GetFrameAtIndex(i).GetPCAddress()
1046061da546Spatrick
1047061da546Spatrick    return list(map(GetPCAddress, list(range(thread.GetNumFrames()))))
1048061da546Spatrick
1049061da546Spatrick
1050061da546Spatrickdef get_filenames(thread):
1051061da546Spatrick    """
1052061da546Spatrick    Returns a sequence of file names from the stack frames of this thread.
1053061da546Spatrick    """
1054061da546Spatrick    def GetFilename(i):
1055061da546Spatrick        return thread.GetFrameAtIndex(
1056061da546Spatrick            i).GetLineEntry().GetFileSpec().GetFilename()
1057061da546Spatrick
1058061da546Spatrick    return list(map(GetFilename, list(range(thread.GetNumFrames()))))
1059061da546Spatrick
1060061da546Spatrick
1061061da546Spatrickdef get_line_numbers(thread):
1062061da546Spatrick    """
1063061da546Spatrick    Returns a sequence of line numbers from the stack frames of this thread.
1064061da546Spatrick    """
1065061da546Spatrick    def GetLineNumber(i):
1066061da546Spatrick        return thread.GetFrameAtIndex(i).GetLineEntry().GetLine()
1067061da546Spatrick
1068061da546Spatrick    return list(map(GetLineNumber, list(range(thread.GetNumFrames()))))
1069061da546Spatrick
1070061da546Spatrick
1071061da546Spatrickdef get_module_names(thread):
1072061da546Spatrick    """
1073061da546Spatrick    Returns a sequence of module names from the stack frames of this thread.
1074061da546Spatrick    """
1075061da546Spatrick    def GetModuleName(i):
1076061da546Spatrick        return thread.GetFrameAtIndex(
1077061da546Spatrick            i).GetModule().GetFileSpec().GetFilename()
1078061da546Spatrick
1079061da546Spatrick    return list(map(GetModuleName, list(range(thread.GetNumFrames()))))
1080061da546Spatrick
1081061da546Spatrick
1082061da546Spatrickdef get_stack_frames(thread):
1083061da546Spatrick    """
1084061da546Spatrick    Returns a sequence of stack frames for this thread.
1085061da546Spatrick    """
1086061da546Spatrick    def GetStackFrame(i):
1087061da546Spatrick        return thread.GetFrameAtIndex(i)
1088061da546Spatrick
1089061da546Spatrick    return list(map(GetStackFrame, list(range(thread.GetNumFrames()))))
1090061da546Spatrick
1091061da546Spatrick
1092061da546Spatrickdef print_stacktrace(thread, string_buffer=False):
1093061da546Spatrick    """Prints a simple stack trace of this thread."""
1094061da546Spatrick
1095061da546Spatrick    output = SixStringIO() if string_buffer else sys.stdout
1096061da546Spatrick    target = thread.GetProcess().GetTarget()
1097061da546Spatrick
1098061da546Spatrick    depth = thread.GetNumFrames()
1099061da546Spatrick
1100061da546Spatrick    mods = get_module_names(thread)
1101061da546Spatrick    funcs = get_function_names(thread)
1102061da546Spatrick    symbols = get_symbol_names(thread)
1103061da546Spatrick    files = get_filenames(thread)
1104061da546Spatrick    lines = get_line_numbers(thread)
1105061da546Spatrick    addrs = get_pc_addresses(thread)
1106061da546Spatrick
1107061da546Spatrick    if thread.GetStopReason() != lldb.eStopReasonInvalid:
1108061da546Spatrick        desc = "stop reason=" + stop_reason_to_str(thread.GetStopReason())
1109061da546Spatrick    else:
1110061da546Spatrick        desc = ""
1111061da546Spatrick    print(
1112061da546Spatrick        "Stack trace for thread id={0:#x} name={1} queue={2} ".format(
1113061da546Spatrick            thread.GetThreadID(),
1114061da546Spatrick            thread.GetName(),
1115061da546Spatrick            thread.GetQueueName()) + desc,
1116061da546Spatrick        file=output)
1117061da546Spatrick
1118061da546Spatrick    for i in range(depth):
1119061da546Spatrick        frame = thread.GetFrameAtIndex(i)
1120061da546Spatrick        function = frame.GetFunction()
1121061da546Spatrick
1122061da546Spatrick        load_addr = addrs[i].GetLoadAddress(target)
1123061da546Spatrick        if not function:
1124061da546Spatrick            file_addr = addrs[i].GetFileAddress()
1125061da546Spatrick            start_addr = frame.GetSymbol().GetStartAddress().GetFileAddress()
1126061da546Spatrick            symbol_offset = file_addr - start_addr
1127061da546Spatrick            print(
1128061da546Spatrick                "  frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}".format(
1129061da546Spatrick                    num=i,
1130061da546Spatrick                    addr=load_addr,
1131061da546Spatrick                    mod=mods[i],
1132061da546Spatrick                    symbol=symbols[i],
1133061da546Spatrick                    offset=symbol_offset),
1134061da546Spatrick                file=output)
1135061da546Spatrick        else:
1136061da546Spatrick            print(
1137061da546Spatrick                "  frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format(
1138061da546Spatrick                    num=i,
1139061da546Spatrick                    addr=load_addr,
1140061da546Spatrick                    mod=mods[i],
1141061da546Spatrick                    func='%s [inlined]' %
1142061da546Spatrick                    funcs[i] if frame.IsInlined() else funcs[i],
1143061da546Spatrick                    file=files[i],
1144061da546Spatrick                    line=lines[i],
1145061da546Spatrick                    args=get_args_as_string(
1146061da546Spatrick                        frame,
1147061da546Spatrick                        showFuncName=False) if not frame.IsInlined() else '()'),
1148061da546Spatrick                file=output)
1149061da546Spatrick
1150061da546Spatrick    if string_buffer:
1151061da546Spatrick        return output.getvalue()
1152061da546Spatrick
1153061da546Spatrick
1154061da546Spatrickdef print_stacktraces(process, string_buffer=False):
1155061da546Spatrick    """Prints the stack traces of all the threads."""
1156061da546Spatrick
1157061da546Spatrick    output = SixStringIO() if string_buffer else sys.stdout
1158061da546Spatrick
1159061da546Spatrick    print("Stack traces for " + str(process), file=output)
1160061da546Spatrick
1161061da546Spatrick    for thread in process:
1162061da546Spatrick        print(print_stacktrace(thread, string_buffer=True), file=output)
1163061da546Spatrick
1164061da546Spatrick    if string_buffer:
1165061da546Spatrick        return output.getvalue()
1166061da546Spatrick
1167061da546Spatrick
1168dda28197Spatrickdef expect_state_changes(test, listener, process, states, timeout=30):
1169061da546Spatrick    """Listens for state changed events on the listener and makes sure they match what we
1170061da546Spatrick    expect. Stop-and-restart events (where GetRestartedFromEvent() returns true) are ignored."""
1171061da546Spatrick
1172061da546Spatrick    for expected_state in states:
1173061da546Spatrick        def get_next_event():
1174061da546Spatrick            event = lldb.SBEvent()
1175061da546Spatrick            if not listener.WaitForEventForBroadcasterWithType(
1176061da546Spatrick                    timeout,
1177061da546Spatrick                    process.GetBroadcaster(),
1178061da546Spatrick                    lldb.SBProcess.eBroadcastBitStateChanged,
1179061da546Spatrick                    event):
1180061da546Spatrick                test.fail(
1181061da546Spatrick                    "Timed out while waiting for a transition to state %s" %
1182061da546Spatrick                    lldb.SBDebugger.StateAsCString(expected_state))
1183061da546Spatrick            return event
1184061da546Spatrick
1185061da546Spatrick        event = get_next_event()
1186061da546Spatrick        while (lldb.SBProcess.GetStateFromEvent(event) == lldb.eStateStopped and
1187061da546Spatrick                lldb.SBProcess.GetRestartedFromEvent(event)):
1188061da546Spatrick            # Ignore restarted event and the subsequent running event.
1189061da546Spatrick            event = get_next_event()
1190061da546Spatrick            test.assertEqual(
1191061da546Spatrick                lldb.SBProcess.GetStateFromEvent(event),
1192061da546Spatrick                lldb.eStateRunning,
1193061da546Spatrick                "Restarted event followed by a running event")
1194061da546Spatrick            event = get_next_event()
1195061da546Spatrick
1196061da546Spatrick        test.assertEqual(
1197061da546Spatrick            lldb.SBProcess.GetStateFromEvent(event),
1198061da546Spatrick            expected_state)
1199061da546Spatrick
1200061da546Spatrick# ===================================
1201061da546Spatrick# Utility functions related to Frames
1202061da546Spatrick# ===================================
1203061da546Spatrick
1204061da546Spatrick
1205061da546Spatrickdef get_parent_frame(frame):
1206061da546Spatrick    """
1207061da546Spatrick    Returns the parent frame of the input frame object; None if not available.
1208061da546Spatrick    """
1209061da546Spatrick    thread = frame.GetThread()
1210061da546Spatrick    parent_found = False
1211061da546Spatrick    for f in thread:
1212061da546Spatrick        if parent_found:
1213061da546Spatrick            return f
1214061da546Spatrick        if f.GetFrameID() == frame.GetFrameID():
1215061da546Spatrick            parent_found = True
1216061da546Spatrick
1217061da546Spatrick    # If we reach here, no parent has been found, return None.
1218061da546Spatrick    return None
1219061da546Spatrick
1220061da546Spatrick
1221061da546Spatrickdef get_args_as_string(frame, showFuncName=True):
1222061da546Spatrick    """
1223061da546Spatrick    Returns the args of the input frame object as a string.
1224061da546Spatrick    """
1225061da546Spatrick    # arguments     => True
1226061da546Spatrick    # locals        => False
1227061da546Spatrick    # statics       => False
1228061da546Spatrick    # in_scope_only => True
1229061da546Spatrick    vars = frame.GetVariables(True, False, False, True)  # type of SBValueList
1230061da546Spatrick    args = []  # list of strings
1231061da546Spatrick    for var in vars:
1232061da546Spatrick        args.append("(%s)%s=%s" % (var.GetTypeName(),
1233061da546Spatrick                                   var.GetName(),
1234061da546Spatrick                                   var.GetValue()))
1235061da546Spatrick    if frame.GetFunction():
1236061da546Spatrick        name = frame.GetFunction().GetName()
1237061da546Spatrick    elif frame.GetSymbol():
1238061da546Spatrick        name = frame.GetSymbol().GetName()
1239061da546Spatrick    else:
1240061da546Spatrick        name = ""
1241061da546Spatrick    if showFuncName:
1242061da546Spatrick        return "%s(%s)" % (name, ", ".join(args))
1243061da546Spatrick    else:
1244061da546Spatrick        return "(%s)" % (", ".join(args))
1245061da546Spatrick
1246061da546Spatrick
1247061da546Spatrickdef print_registers(frame, string_buffer=False):
1248061da546Spatrick    """Prints all the register sets of the frame."""
1249061da546Spatrick
1250061da546Spatrick    output = SixStringIO() if string_buffer else sys.stdout
1251061da546Spatrick
1252061da546Spatrick    print("Register sets for " + str(frame), file=output)
1253061da546Spatrick
1254061da546Spatrick    registerSet = frame.GetRegisters()  # Return type of SBValueList.
1255061da546Spatrick    print("Frame registers (size of register set = %d):" %
1256061da546Spatrick          registerSet.GetSize(), file=output)
1257061da546Spatrick    for value in registerSet:
1258061da546Spatrick        #print(value, file=output)
1259061da546Spatrick        print("%s (number of children = %d):" %
1260061da546Spatrick              (value.GetName(), value.GetNumChildren()), file=output)
1261061da546Spatrick        for child in value:
1262061da546Spatrick            print(
1263061da546Spatrick                "Name: %s, Value: %s" %
1264061da546Spatrick                (child.GetName(),
1265061da546Spatrick                 child.GetValue()),
1266061da546Spatrick                file=output)
1267061da546Spatrick
1268061da546Spatrick    if string_buffer:
1269061da546Spatrick        return output.getvalue()
1270061da546Spatrick
1271061da546Spatrick
1272061da546Spatrickdef get_registers(frame, kind):
1273061da546Spatrick    """Returns the registers given the frame and the kind of registers desired.
1274061da546Spatrick
1275061da546Spatrick    Returns None if there's no such kind.
1276061da546Spatrick    """
1277061da546Spatrick    registerSet = frame.GetRegisters()  # Return type of SBValueList.
1278061da546Spatrick    for value in registerSet:
1279061da546Spatrick        if kind.lower() in value.GetName().lower():
1280061da546Spatrick            return value
1281061da546Spatrick
1282061da546Spatrick    return None
1283061da546Spatrick
1284061da546Spatrick
1285061da546Spatrickdef get_GPRs(frame):
1286061da546Spatrick    """Returns the general purpose registers of the frame as an SBValue.
1287061da546Spatrick
1288061da546Spatrick    The returned SBValue object is iterable.  An example:
1289061da546Spatrick        ...
1290061da546Spatrick        from lldbutil import get_GPRs
1291061da546Spatrick        regs = get_GPRs(frame)
1292061da546Spatrick        for reg in regs:
1293061da546Spatrick            print("%s => %s" % (reg.GetName(), reg.GetValue()))
1294061da546Spatrick        ...
1295061da546Spatrick    """
1296061da546Spatrick    return get_registers(frame, "general purpose")
1297061da546Spatrick
1298061da546Spatrick
1299061da546Spatrickdef get_FPRs(frame):
1300061da546Spatrick    """Returns the floating point registers of the frame as an SBValue.
1301061da546Spatrick
1302061da546Spatrick    The returned SBValue object is iterable.  An example:
1303061da546Spatrick        ...
1304061da546Spatrick        from lldbutil import get_FPRs
1305061da546Spatrick        regs = get_FPRs(frame)
1306061da546Spatrick        for reg in regs:
1307061da546Spatrick            print("%s => %s" % (reg.GetName(), reg.GetValue()))
1308061da546Spatrick        ...
1309061da546Spatrick    """
1310061da546Spatrick    return get_registers(frame, "floating point")
1311061da546Spatrick
1312061da546Spatrick
1313061da546Spatrickdef get_ESRs(frame):
1314061da546Spatrick    """Returns the exception state registers of the frame as an SBValue.
1315061da546Spatrick
1316061da546Spatrick    The returned SBValue object is iterable.  An example:
1317061da546Spatrick        ...
1318061da546Spatrick        from lldbutil import get_ESRs
1319061da546Spatrick        regs = get_ESRs(frame)
1320061da546Spatrick        for reg in regs:
1321061da546Spatrick            print("%s => %s" % (reg.GetName(), reg.GetValue()))
1322061da546Spatrick        ...
1323061da546Spatrick    """
1324061da546Spatrick    return get_registers(frame, "exception state")
1325061da546Spatrick
1326061da546Spatrick# ======================================
1327061da546Spatrick# Utility classes/functions for SBValues
1328061da546Spatrick# ======================================
1329061da546Spatrick
1330061da546Spatrick
1331061da546Spatrickclass BasicFormatter(object):
1332061da546Spatrick    """The basic formatter inspects the value object and prints the value."""
1333061da546Spatrick
1334061da546Spatrick    def format(self, value, buffer=None, indent=0):
1335061da546Spatrick        if not buffer:
1336061da546Spatrick            output = SixStringIO()
1337061da546Spatrick        else:
1338061da546Spatrick            output = buffer
1339061da546Spatrick        # If there is a summary, it suffices.
1340061da546Spatrick        val = value.GetSummary()
1341061da546Spatrick        # Otherwise, get the value.
1342061da546Spatrick        if val is None:
1343061da546Spatrick            val = value.GetValue()
1344061da546Spatrick        if val is None and value.GetNumChildren() > 0:
1345061da546Spatrick            val = "%s (location)" % value.GetLocation()
1346061da546Spatrick        print("{indentation}({type}) {name} = {value}".format(
1347061da546Spatrick            indentation=' ' * indent,
1348061da546Spatrick            type=value.GetTypeName(),
1349061da546Spatrick            name=value.GetName(),
1350061da546Spatrick            value=val), file=output)
1351061da546Spatrick        return output.getvalue()
1352061da546Spatrick
1353061da546Spatrick
1354061da546Spatrickclass ChildVisitingFormatter(BasicFormatter):
1355061da546Spatrick    """The child visiting formatter prints the value and its immediate children.
1356061da546Spatrick
1357061da546Spatrick    The constructor takes a keyword arg: indent_child, which defaults to 2.
1358061da546Spatrick    """
1359061da546Spatrick
1360061da546Spatrick    def __init__(self, indent_child=2):
1361061da546Spatrick        """Default indentation of 2 SPC's for the children."""
1362061da546Spatrick        self.cindent = indent_child
1363061da546Spatrick
1364061da546Spatrick    def format(self, value, buffer=None):
1365061da546Spatrick        if not buffer:
1366061da546Spatrick            output = SixStringIO()
1367061da546Spatrick        else:
1368061da546Spatrick            output = buffer
1369061da546Spatrick
1370061da546Spatrick        BasicFormatter.format(self, value, buffer=output)
1371061da546Spatrick        for child in value:
1372061da546Spatrick            BasicFormatter.format(
1373061da546Spatrick                self, child, buffer=output, indent=self.cindent)
1374061da546Spatrick
1375061da546Spatrick        return output.getvalue()
1376061da546Spatrick
1377061da546Spatrick
1378061da546Spatrickclass RecursiveDecentFormatter(BasicFormatter):
1379061da546Spatrick    """The recursive decent formatter prints the value and the decendents.
1380061da546Spatrick
1381061da546Spatrick    The constructor takes two keyword args: indent_level, which defaults to 0,
1382061da546Spatrick    and indent_child, which defaults to 2.  The current indentation level is
1383061da546Spatrick    determined by indent_level, while the immediate children has an additional
1384061da546Spatrick    indentation by inden_child.
1385061da546Spatrick    """
1386061da546Spatrick
1387061da546Spatrick    def __init__(self, indent_level=0, indent_child=2):
1388061da546Spatrick        self.lindent = indent_level
1389061da546Spatrick        self.cindent = indent_child
1390061da546Spatrick
1391061da546Spatrick    def format(self, value, buffer=None):
1392061da546Spatrick        if not buffer:
1393061da546Spatrick            output = SixStringIO()
1394061da546Spatrick        else:
1395061da546Spatrick            output = buffer
1396061da546Spatrick
1397061da546Spatrick        BasicFormatter.format(self, value, buffer=output, indent=self.lindent)
1398061da546Spatrick        new_indent = self.lindent + self.cindent
1399061da546Spatrick        for child in value:
1400061da546Spatrick            if child.GetSummary() is not None:
1401061da546Spatrick                BasicFormatter.format(
1402061da546Spatrick                    self, child, buffer=output, indent=new_indent)
1403061da546Spatrick            else:
1404061da546Spatrick                if child.GetNumChildren() > 0:
1405061da546Spatrick                    rdf = RecursiveDecentFormatter(indent_level=new_indent)
1406061da546Spatrick                    rdf.format(child, buffer=output)
1407061da546Spatrick                else:
1408061da546Spatrick                    BasicFormatter.format(
1409061da546Spatrick                        self, child, buffer=output, indent=new_indent)
1410061da546Spatrick
1411061da546Spatrick        return output.getvalue()
1412061da546Spatrick
1413061da546Spatrick# ===========================================================
1414061da546Spatrick# Utility functions for path manipulation on remote platforms
1415061da546Spatrick# ===========================================================
1416061da546Spatrick
1417061da546Spatrick
1418061da546Spatrickdef join_remote_paths(*paths):
1419061da546Spatrick    # TODO: update with actual platform name for remote windows once it exists
1420061da546Spatrick    if lldb.remote_platform.GetName() == 'remote-windows':
1421061da546Spatrick        return os.path.join(*paths).replace(os.path.sep, '\\')
1422061da546Spatrick    return os.path.join(*paths).replace(os.path.sep, '/')
1423061da546Spatrick
1424061da546Spatrick
1425061da546Spatrickdef append_to_process_working_directory(test, *paths):
1426061da546Spatrick    remote = lldb.remote_platform
1427061da546Spatrick    if remote:
1428061da546Spatrick        return join_remote_paths(remote.GetWorkingDirectory(), *paths)
1429061da546Spatrick    return os.path.join(test.getBuildDir(), *paths)
1430061da546Spatrick
1431061da546Spatrick# ==================================================
1432061da546Spatrick# Utility functions to get the correct signal number
1433061da546Spatrick# ==================================================
1434061da546Spatrick
1435061da546Spatrickimport signal
1436061da546Spatrick
1437061da546Spatrick
1438061da546Spatrickdef get_signal_number(signal_name):
1439061da546Spatrick    platform = lldb.remote_platform
1440061da546Spatrick    if platform and platform.IsValid():
1441061da546Spatrick        signals = platform.GetUnixSignals()
1442061da546Spatrick        if signals.IsValid():
1443061da546Spatrick            signal_number = signals.GetSignalNumberFromName(signal_name)
1444061da546Spatrick            if signal_number > 0:
1445061da546Spatrick                return signal_number
1446061da546Spatrick    # No remote platform; fall back to using local python signals.
1447061da546Spatrick    return getattr(signal, signal_name)
1448061da546Spatrick
1449061da546Spatrick
1450061da546Spatrickclass PrintableRegex(object):
1451061da546Spatrick
1452061da546Spatrick    def __init__(self, text):
1453061da546Spatrick        self.regex = re.compile(text)
1454061da546Spatrick        self.text = text
1455061da546Spatrick
1456061da546Spatrick    def match(self, str):
1457061da546Spatrick        return self.regex.match(str)
1458061da546Spatrick
1459061da546Spatrick    def __str__(self):
1460061da546Spatrick        return "%s" % (self.text)
1461061da546Spatrick
1462061da546Spatrick    def __repr__(self):
1463061da546Spatrick        return "re.compile(%s) -> %s" % (self.text, self.regex)
1464061da546Spatrick
1465061da546Spatrick
1466061da546Spatrickdef skip_if_callable(test, mycallable, reason):
1467061da546Spatrick    if six.callable(mycallable):
1468061da546Spatrick        if mycallable(test):
1469061da546Spatrick            test.skipTest(reason)
1470061da546Spatrick            return True
1471061da546Spatrick    return False
1472061da546Spatrick
1473061da546Spatrick
1474061da546Spatrickdef skip_if_library_missing(test, target, library):
1475061da546Spatrick    def find_library(target, library):
1476061da546Spatrick        for module in target.modules:
1477061da546Spatrick            filename = module.file.GetFilename()
1478061da546Spatrick            if isinstance(library, str):
1479061da546Spatrick                if library == filename:
1480061da546Spatrick                    return False
1481061da546Spatrick            elif hasattr(library, 'match'):
1482061da546Spatrick                if library.match(filename):
1483061da546Spatrick                    return False
1484061da546Spatrick        return True
1485061da546Spatrick
1486061da546Spatrick    def find_library_callable(test):
1487061da546Spatrick        return find_library(target, library)
1488061da546Spatrick    return skip_if_callable(
1489061da546Spatrick        test,
1490061da546Spatrick        find_library_callable,
1491061da546Spatrick        "could not find library matching '%s' in target %s" %
1492061da546Spatrick        (library,
1493061da546Spatrick         target))
1494061da546Spatrick
1495061da546Spatrick
1496061da546Spatrickdef read_file_on_target(test, remote):
1497061da546Spatrick    if lldb.remote_platform:
1498061da546Spatrick        local = test.getBuildArtifact("file_from_target")
1499061da546Spatrick        error = lldb.remote_platform.Get(lldb.SBFileSpec(remote, False),
1500061da546Spatrick                    lldb.SBFileSpec(local, True))
1501061da546Spatrick        test.assertTrue(error.Success(), "Reading file {0} failed: {1}".format(remote, error))
1502061da546Spatrick    else:
1503061da546Spatrick        local = remote
1504061da546Spatrick    with open(local, 'r') as f:
1505061da546Spatrick        return f.read()
1506061da546Spatrick
1507061da546Spatrickdef read_file_from_process_wd(test, name):
1508061da546Spatrick    path = append_to_process_working_directory(test, name)
1509061da546Spatrick    return read_file_on_target(test, path)
1510061da546Spatrick
1511061da546Spatrickdef wait_for_file_on_target(testcase, file_path, max_attempts=6):
1512061da546Spatrick    for i in range(max_attempts):
1513061da546Spatrick        err, retcode, msg = testcase.run_platform_command("ls %s" % file_path)
1514061da546Spatrick        if err.Success() and retcode == 0:
1515061da546Spatrick            break
1516061da546Spatrick        if i < max_attempts:
1517061da546Spatrick            # Exponential backoff!
1518061da546Spatrick            import time
1519061da546Spatrick            time.sleep(pow(2, i) * 0.25)
1520061da546Spatrick    else:
1521061da546Spatrick        testcase.fail(
1522061da546Spatrick            "File %s not found even after %d attempts." %
1523061da546Spatrick            (file_path, max_attempts))
1524061da546Spatrick
1525061da546Spatrick    return read_file_on_target(testcase, file_path)
1526*be691f3bSpatrick
1527*be691f3bSpatrickdef packetlog_get_process_info(log):
1528*be691f3bSpatrick    """parse a gdb-remote packet log file and extract the response to qProcessInfo"""
1529*be691f3bSpatrick    process_info = dict()
1530*be691f3bSpatrick    with open(log, "r") as logfile:
1531*be691f3bSpatrick        process_info_ostype = None
1532*be691f3bSpatrick        expect_process_info_response = False
1533*be691f3bSpatrick        for line in logfile:
1534*be691f3bSpatrick            if expect_process_info_response:
1535*be691f3bSpatrick                for pair in line.split(';'):
1536*be691f3bSpatrick                    keyval = pair.split(':')
1537*be691f3bSpatrick                    if len(keyval) == 2:
1538*be691f3bSpatrick                        process_info[keyval[0]] = keyval[1]
1539*be691f3bSpatrick                break
1540*be691f3bSpatrick            if 'send packet: $qProcessInfo#' in line:
1541*be691f3bSpatrick                expect_process_info_response = True
1542*be691f3bSpatrick    return process_info
1543*be691f3bSpatrick
1544*be691f3bSpatrickdef packetlog_get_dylib_info(log):
1545*be691f3bSpatrick    """parse a gdb-remote packet log file and extract the *last* complete
1546*be691f3bSpatrick    (=> fetch_all_solibs=true) response to jGetLoadedDynamicLibrariesInfos"""
1547*be691f3bSpatrick    import json
1548*be691f3bSpatrick    dylib_info = None
1549*be691f3bSpatrick    with open(log, "r") as logfile:
1550*be691f3bSpatrick        dylib_info = None
1551*be691f3bSpatrick        expect_dylib_info_response = False
1552*be691f3bSpatrick        for line in logfile:
1553*be691f3bSpatrick            if expect_dylib_info_response:
1554*be691f3bSpatrick                while line[0] != '$':
1555*be691f3bSpatrick                    line = line[1:]
1556*be691f3bSpatrick                line = line[1:]
1557*be691f3bSpatrick                # Unescape '}'.
1558*be691f3bSpatrick                dylib_info = json.loads(line.replace('}]','}')[:-4])
1559*be691f3bSpatrick                expect_dylib_info_response = False
1560*be691f3bSpatrick            if 'send packet: $jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}' in line:
1561*be691f3bSpatrick                expect_dylib_info_response = True
1562*be691f3bSpatrick
1563*be691f3bSpatrick    return dylib_info
1564