xref: /openbsd-src/gnu/llvm/lldb/packages/Python/lldbsuite/test/lldbutil.py (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
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
12*f6aab3d8Srobertimport io
13061da546Spatrickimport os
14061da546Spatrickimport re
15061da546Spatrickimport sys
16be691f3bSpatrickimport subprocess
17*f6aab3d8Srobertfrom typing import Dict
18061da546Spatrick
19061da546Spatrick# LLDB modules
20061da546Spatrickimport lldb
21061da546Spatrickfrom . import lldbtest_config
22be691f3bSpatrickfrom . import configuration
23061da546Spatrick
24be691f3bSpatrick# How often failed simulator process launches are retried.
25be691f3bSpatrickSIMULATOR_RETRY = 3
26061da546Spatrick
27061da546Spatrick# ===================================================
28061da546Spatrick# Utilities for locating/checking executable programs
29061da546Spatrick# ===================================================
30061da546Spatrick
31061da546Spatrickdef is_exe(fpath):
32061da546Spatrick    """Returns True if fpath is an executable."""
33061da546Spatrick    return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
34061da546Spatrick
35061da546Spatrick
36061da546Spatrickdef which(program):
37061da546Spatrick    """Returns the full path to a program; None otherwise."""
38061da546Spatrick    fpath, fname = os.path.split(program)
39061da546Spatrick    if fpath:
40061da546Spatrick        if is_exe(program):
41061da546Spatrick            return program
42061da546Spatrick    else:
43061da546Spatrick        for path in os.environ["PATH"].split(os.pathsep):
44061da546Spatrick            exe_file = os.path.join(path, program)
45061da546Spatrick            if is_exe(exe_file):
46061da546Spatrick                return exe_file
47061da546Spatrick    return None
48061da546Spatrick
49061da546Spatrickdef mkdir_p(path):
50061da546Spatrick    try:
51061da546Spatrick        os.makedirs(path)
52061da546Spatrick    except OSError as e:
53061da546Spatrick        if e.errno != errno.EEXIST:
54061da546Spatrick            raise
55061da546Spatrick    if not os.path.isdir(path):
56061da546Spatrick        raise OSError(errno.ENOTDIR, "%s is not a directory"%path)
57be691f3bSpatrick
58be691f3bSpatrick
59be691f3bSpatrick# ============================
60be691f3bSpatrick# Dealing with SDK and triples
61be691f3bSpatrick# ============================
62be691f3bSpatrick
63be691f3bSpatrickdef get_xcode_sdk(os, env):
64be691f3bSpatrick    # Respect --apple-sdk <path> if it's specified. If the SDK is simply
65be691f3bSpatrick    # mounted from some disk image, and not actually installed, this is the
66be691f3bSpatrick    # only way to use it.
67be691f3bSpatrick    if configuration.apple_sdk:
68be691f3bSpatrick        return configuration.apple_sdk
69be691f3bSpatrick    if os == "ios":
70be691f3bSpatrick        if env == "simulator":
71be691f3bSpatrick            return "iphonesimulator"
72be691f3bSpatrick        if env == "macabi":
73be691f3bSpatrick            return "macosx"
74be691f3bSpatrick        return "iphoneos"
75be691f3bSpatrick    elif os == "tvos":
76be691f3bSpatrick        if env == "simulator":
77be691f3bSpatrick            return "appletvsimulator"
78be691f3bSpatrick        return "appletvos"
79be691f3bSpatrick    elif os == "watchos":
80be691f3bSpatrick        if env == "simulator":
81be691f3bSpatrick            return "watchsimulator"
82be691f3bSpatrick        return "watchos"
83be691f3bSpatrick    return os
84be691f3bSpatrick
85be691f3bSpatrick
86be691f3bSpatrickdef get_xcode_sdk_version(sdk):
87be691f3bSpatrick    return subprocess.check_output(
88be691f3bSpatrick        ['xcrun', '--sdk', sdk, '--show-sdk-version']).rstrip().decode('utf-8')
89be691f3bSpatrick
90be691f3bSpatrick
91be691f3bSpatrickdef get_xcode_sdk_root(sdk):
92be691f3bSpatrick    return subprocess.check_output(['xcrun', '--sdk', sdk, '--show-sdk-path'
93be691f3bSpatrick                                    ]).rstrip().decode('utf-8')
94be691f3bSpatrick
95be691f3bSpatrick
96be691f3bSpatrickdef get_xcode_clang(sdk):
97be691f3bSpatrick    return subprocess.check_output(['xcrun', '-sdk', sdk, '-f', 'clang'
98be691f3bSpatrick                                    ]).rstrip().decode("utf-8")
99be691f3bSpatrick
100be691f3bSpatrick
101061da546Spatrick# ===================================================
102061da546Spatrick# Disassembly for an SBFunction or an SBSymbol object
103061da546Spatrick# ===================================================
104061da546Spatrick
105061da546Spatrick
106061da546Spatrickdef disassemble(target, function_or_symbol):
107061da546Spatrick    """Disassemble the function or symbol given a target.
108061da546Spatrick
109061da546Spatrick    It returns the disassembly content in a string object.
110061da546Spatrick    """
111*f6aab3d8Srobert    buf = io.StringIO()
112061da546Spatrick    insts = function_or_symbol.GetInstructions(target)
113061da546Spatrick    for i in insts:
114061da546Spatrick        print(i, file=buf)
115061da546Spatrick    return buf.getvalue()
116061da546Spatrick
117061da546Spatrick# ==========================================================
118061da546Spatrick# Integer (byte size 1, 2, 4, and 8) to bytearray conversion
119061da546Spatrick# ==========================================================
120061da546Spatrick
121061da546Spatrick
122061da546Spatrickdef int_to_bytearray(val, bytesize):
123061da546Spatrick    """Utility function to convert an integer into a bytearray.
124061da546Spatrick
125061da546Spatrick    It returns the bytearray in the little endian format.  It is easy to get the
126061da546Spatrick    big endian format, just do ba.reverse() on the returned object.
127061da546Spatrick    """
128061da546Spatrick    import struct
129061da546Spatrick
130061da546Spatrick    if bytesize == 1:
131061da546Spatrick        return bytearray([val])
132061da546Spatrick
133061da546Spatrick    # Little endian followed by a format character.
134061da546Spatrick    template = "<%c"
135061da546Spatrick    if bytesize == 2:
136061da546Spatrick        fmt = template % 'h'
137061da546Spatrick    elif bytesize == 4:
138061da546Spatrick        fmt = template % 'i'
139061da546Spatrick    elif bytesize == 4:
140061da546Spatrick        fmt = template % 'q'
141061da546Spatrick    else:
142061da546Spatrick        return None
143061da546Spatrick
144061da546Spatrick    packed = struct.pack(fmt, val)
145061da546Spatrick    return bytearray(packed)
146061da546Spatrick
147061da546Spatrick
148061da546Spatrickdef bytearray_to_int(bytes, bytesize):
149061da546Spatrick    """Utility function to convert a bytearray into an integer.
150061da546Spatrick
151061da546Spatrick    It interprets the bytearray in the little endian format. For a big endian
152061da546Spatrick    bytearray, just do ba.reverse() on the object before passing it in.
153061da546Spatrick    """
154061da546Spatrick    import struct
155061da546Spatrick
156061da546Spatrick    if bytesize == 1:
157061da546Spatrick        return bytes[0]
158061da546Spatrick
159061da546Spatrick    # Little endian followed by a format character.
160061da546Spatrick    template = "<%c"
161061da546Spatrick    if bytesize == 2:
162061da546Spatrick        fmt = template % 'h'
163061da546Spatrick    elif bytesize == 4:
164061da546Spatrick        fmt = template % 'i'
165061da546Spatrick    elif bytesize == 4:
166061da546Spatrick        fmt = template % 'q'
167061da546Spatrick    else:
168061da546Spatrick        return None
169061da546Spatrick
170061da546Spatrick    unpacked = struct.unpack_from(fmt, bytes)
171061da546Spatrick    return unpacked[0]
172061da546Spatrick
173061da546Spatrick
174061da546Spatrick# ==============================================================
175061da546Spatrick# Get the description of an lldb object or None if not available
176061da546Spatrick# ==============================================================
177061da546Spatrickdef get_description(obj, option=None):
178061da546Spatrick    """Calls lldb_obj.GetDescription() and returns a string, or None.
179061da546Spatrick
180061da546Spatrick    For SBTarget, SBBreakpointLocation, and SBWatchpoint lldb objects, an extra
181061da546Spatrick    option can be passed in to describe the detailed level of description
182061da546Spatrick    desired:
183061da546Spatrick        o lldb.eDescriptionLevelBrief
184061da546Spatrick        o lldb.eDescriptionLevelFull
185061da546Spatrick        o lldb.eDescriptionLevelVerbose
186061da546Spatrick    """
187061da546Spatrick    method = getattr(obj, 'GetDescription')
188061da546Spatrick    if not method:
189061da546Spatrick        return None
190061da546Spatrick    tuple = (lldb.SBTarget, lldb.SBBreakpointLocation, lldb.SBWatchpoint)
191061da546Spatrick    if isinstance(obj, tuple):
192061da546Spatrick        if option is None:
193061da546Spatrick            option = lldb.eDescriptionLevelBrief
194061da546Spatrick
195061da546Spatrick    stream = lldb.SBStream()
196061da546Spatrick    if option is None:
197061da546Spatrick        success = method(stream)
198061da546Spatrick    else:
199061da546Spatrick        success = method(stream, option)
200061da546Spatrick    if not success:
201061da546Spatrick        return None
202061da546Spatrick    return stream.GetData()
203061da546Spatrick
204061da546Spatrick
205061da546Spatrick# =================================================
206061da546Spatrick# Convert some enum value to its string counterpart
207061da546Spatrick# =================================================
208061da546Spatrick
209*f6aab3d8Srobertdef _enum_names(prefix: str) -> Dict[int, str]:
210*f6aab3d8Srobert    """Generate a mapping of enum value to name, for the enum prefix."""
211*f6aab3d8Srobert    suffix_start = len(prefix)
212*f6aab3d8Srobert    return {
213*f6aab3d8Srobert        getattr(lldb, attr): attr[suffix_start:].lower()
214*f6aab3d8Srobert        for attr in dir(lldb)
215*f6aab3d8Srobert        if attr.startswith(prefix)
216*f6aab3d8Srobert    }
217*f6aab3d8Srobert
218*f6aab3d8Srobert
219*f6aab3d8Srobert_STATE_NAMES = _enum_names(prefix="eState")
220*f6aab3d8Srobert
221*f6aab3d8Srobertdef state_type_to_str(enum: int) -> str:
222061da546Spatrick    """Returns the stateType string given an enum."""
223*f6aab3d8Srobert    name = _STATE_NAMES.get(enum)
224*f6aab3d8Srobert    if name:
225*f6aab3d8Srobert        return name
226*f6aab3d8Srobert    raise Exception(f"Unknown StateType enum: {enum}")
227061da546Spatrick
228061da546Spatrick
229*f6aab3d8Srobert_STOP_REASON_NAMES = _enum_names(prefix="eStopReason")
230*f6aab3d8Srobert
231*f6aab3d8Srobertdef stop_reason_to_str(enum: int) -> str:
232061da546Spatrick    """Returns the stopReason string given an enum."""
233*f6aab3d8Srobert    name = _STOP_REASON_NAMES.get(enum)
234*f6aab3d8Srobert    if name:
235*f6aab3d8Srobert        return name
236*f6aab3d8Srobert    raise Exception(f"Unknown StopReason enum: {enum}")
237061da546Spatrick
238061da546Spatrick
239*f6aab3d8Srobert_SYMBOL_TYPE_NAMES = _enum_names(prefix="eSymbolType")
240*f6aab3d8Srobert
241*f6aab3d8Srobertdef symbol_type_to_str(enum: int) -> str:
242061da546Spatrick    """Returns the symbolType string given an enum."""
243*f6aab3d8Srobert    name = _SYMBOL_TYPE_NAMES.get(enum)
244*f6aab3d8Srobert    if name:
245*f6aab3d8Srobert        return name
246*f6aab3d8Srobert    raise Exception(f"Unknown SymbolType enum: {enum}")
247061da546Spatrick
248061da546Spatrick
249*f6aab3d8Srobert_VALUE_TYPE_NAMES = _enum_names(prefix="eValueType")
250*f6aab3d8Srobert
251*f6aab3d8Srobertdef value_type_to_str(enum: int) -> str:
252061da546Spatrick    """Returns the valueType string given an enum."""
253*f6aab3d8Srobert    name = _VALUE_TYPE_NAMES.get(enum)
254*f6aab3d8Srobert    if name:
255*f6aab3d8Srobert        return name
256*f6aab3d8Srobert    raise Exception(f"Unknown ValueType enum: {enum}")
257061da546Spatrick
258061da546Spatrick
259061da546Spatrick# ==================================================
260061da546Spatrick# Get stopped threads due to each stop reason.
261061da546Spatrick# ==================================================
262061da546Spatrick
263061da546Spatrickdef sort_stopped_threads(process,
264061da546Spatrick                         breakpoint_threads=None,
265061da546Spatrick                         crashed_threads=None,
266061da546Spatrick                         watchpoint_threads=None,
267061da546Spatrick                         signal_threads=None,
268061da546Spatrick                         exiting_threads=None,
269061da546Spatrick                         other_threads=None):
270061da546Spatrick    """ Fills array *_threads with threads stopped for the corresponding stop
271061da546Spatrick        reason.
272061da546Spatrick    """
273061da546Spatrick    for lst in [breakpoint_threads,
274061da546Spatrick                watchpoint_threads,
275061da546Spatrick                signal_threads,
276061da546Spatrick                exiting_threads,
277061da546Spatrick                other_threads]:
278061da546Spatrick        if lst is not None:
279061da546Spatrick            lst[:] = []
280061da546Spatrick
281061da546Spatrick    for thread in process:
282061da546Spatrick        dispatched = False
283061da546Spatrick        for (reason, list) in [(lldb.eStopReasonBreakpoint, breakpoint_threads),
284061da546Spatrick                               (lldb.eStopReasonException, crashed_threads),
285061da546Spatrick                               (lldb.eStopReasonWatchpoint, watchpoint_threads),
286061da546Spatrick                               (lldb.eStopReasonSignal, signal_threads),
287061da546Spatrick                               (lldb.eStopReasonThreadExiting, exiting_threads),
288061da546Spatrick                               (None, other_threads)]:
289061da546Spatrick            if not dispatched and list is not None:
290061da546Spatrick                if thread.GetStopReason() == reason or reason is None:
291061da546Spatrick                    list.append(thread)
292061da546Spatrick                    dispatched = True
293061da546Spatrick
294061da546Spatrick# ==================================================
295061da546Spatrick# Utility functions for setting breakpoints
296061da546Spatrick# ==================================================
297061da546Spatrick
298061da546Spatrickdef run_break_set_by_script(
299061da546Spatrick        test,
300061da546Spatrick        class_name,
301061da546Spatrick        extra_options=None,
302061da546Spatrick        num_expected_locations=1):
303061da546Spatrick    """Set a scripted breakpoint.  Check that it got the right number of locations."""
304061da546Spatrick    test.assertTrue(class_name is not None, "Must pass in a class name.")
305061da546Spatrick    command = "breakpoint set -P " + class_name
306061da546Spatrick    if extra_options is not None:
307061da546Spatrick        command += " " + extra_options
308061da546Spatrick
309061da546Spatrick    break_results = run_break_set_command(test, command)
310061da546Spatrick    check_breakpoint_result(test, break_results, num_locations=num_expected_locations)
311061da546Spatrick    return get_bpno_from_match(break_results)
312061da546Spatrick
313061da546Spatrickdef run_break_set_by_file_and_line(
314061da546Spatrick        test,
315061da546Spatrick        file_name,
316061da546Spatrick        line_number,
317061da546Spatrick        extra_options=None,
318061da546Spatrick        num_expected_locations=1,
319061da546Spatrick        loc_exact=False,
320061da546Spatrick        module_name=None):
321061da546Spatrick    """Set a breakpoint by file and line, returning the breakpoint number.
322061da546Spatrick
323061da546Spatrick    If extra_options is not None, then we append it to the breakpoint set command.
324061da546Spatrick
325061da546Spatrick    If num_expected_locations is -1, we check that we got AT LEAST one location. If num_expected_locations is -2, we don't
326061da546Spatrick    check the actual number at all. Otherwise, we check that num_expected_locations equals the number of locations.
327061da546Spatrick
328061da546Spatrick    If loc_exact is true, we check that there is one location, and that location must be at the input file and line number."""
329061da546Spatrick
330061da546Spatrick    if file_name is None:
331061da546Spatrick        command = 'breakpoint set -l %d' % (line_number)
332061da546Spatrick    else:
333061da546Spatrick        command = 'breakpoint set -f "%s" -l %d' % (file_name, line_number)
334061da546Spatrick
335061da546Spatrick    if module_name:
336061da546Spatrick        command += " --shlib '%s'" % (module_name)
337061da546Spatrick
338061da546Spatrick    if extra_options:
339061da546Spatrick        command += " " + extra_options
340061da546Spatrick
341061da546Spatrick    break_results = run_break_set_command(test, command)
342061da546Spatrick
343061da546Spatrick    if num_expected_locations == 1 and loc_exact:
344061da546Spatrick        check_breakpoint_result(
345061da546Spatrick            test,
346061da546Spatrick            break_results,
347061da546Spatrick            num_locations=num_expected_locations,
348061da546Spatrick            file_name=file_name,
349061da546Spatrick            line_number=line_number,
350061da546Spatrick            module_name=module_name)
351061da546Spatrick    else:
352061da546Spatrick        check_breakpoint_result(
353061da546Spatrick            test,
354061da546Spatrick            break_results,
355061da546Spatrick            num_locations=num_expected_locations)
356061da546Spatrick
357061da546Spatrick    return get_bpno_from_match(break_results)
358061da546Spatrick
359061da546Spatrick
360061da546Spatrickdef run_break_set_by_symbol(
361061da546Spatrick        test,
362061da546Spatrick        symbol,
363061da546Spatrick        extra_options=None,
364061da546Spatrick        num_expected_locations=-1,
365061da546Spatrick        sym_exact=False,
366061da546Spatrick        module_name=None):
367061da546Spatrick    """Set a breakpoint by symbol name.  Common options are the same as run_break_set_by_file_and_line.
368061da546Spatrick
369061da546Spatrick    If sym_exact is true, then the output symbol must match the input exactly, otherwise we do a substring match."""
370061da546Spatrick    command = 'breakpoint set -n "%s"' % (symbol)
371061da546Spatrick
372061da546Spatrick    if module_name:
373061da546Spatrick        command += " --shlib '%s'" % (module_name)
374061da546Spatrick
375061da546Spatrick    if extra_options:
376061da546Spatrick        command += " " + extra_options
377061da546Spatrick
378061da546Spatrick    break_results = run_break_set_command(test, command)
379061da546Spatrick
380061da546Spatrick    if num_expected_locations == 1 and sym_exact:
381061da546Spatrick        check_breakpoint_result(
382061da546Spatrick            test,
383061da546Spatrick            break_results,
384061da546Spatrick            num_locations=num_expected_locations,
385061da546Spatrick            symbol_name=symbol,
386061da546Spatrick            module_name=module_name)
387061da546Spatrick    else:
388061da546Spatrick        check_breakpoint_result(
389061da546Spatrick            test,
390061da546Spatrick            break_results,
391061da546Spatrick            num_locations=num_expected_locations)
392061da546Spatrick
393061da546Spatrick    return get_bpno_from_match(break_results)
394061da546Spatrick
395061da546Spatrick
396061da546Spatrickdef run_break_set_by_selector(
397061da546Spatrick        test,
398061da546Spatrick        selector,
399061da546Spatrick        extra_options=None,
400061da546Spatrick        num_expected_locations=-1,
401061da546Spatrick        module_name=None):
402061da546Spatrick    """Set a breakpoint by selector.  Common options are the same as run_break_set_by_file_and_line."""
403061da546Spatrick
404061da546Spatrick    command = 'breakpoint set -S "%s"' % (selector)
405061da546Spatrick
406061da546Spatrick    if module_name:
407061da546Spatrick        command += ' --shlib "%s"' % (module_name)
408061da546Spatrick
409061da546Spatrick    if extra_options:
410061da546Spatrick        command += " " + extra_options
411061da546Spatrick
412061da546Spatrick    break_results = run_break_set_command(test, command)
413061da546Spatrick
414061da546Spatrick    if num_expected_locations == 1:
415061da546Spatrick        check_breakpoint_result(
416061da546Spatrick            test,
417061da546Spatrick            break_results,
418061da546Spatrick            num_locations=num_expected_locations,
419061da546Spatrick            symbol_name=selector,
420061da546Spatrick            symbol_match_exact=False,
421061da546Spatrick            module_name=module_name)
422061da546Spatrick    else:
423061da546Spatrick        check_breakpoint_result(
424061da546Spatrick            test,
425061da546Spatrick            break_results,
426061da546Spatrick            num_locations=num_expected_locations)
427061da546Spatrick
428061da546Spatrick    return get_bpno_from_match(break_results)
429061da546Spatrick
430061da546Spatrick
431061da546Spatrickdef run_break_set_by_regexp(
432061da546Spatrick        test,
433061da546Spatrick        regexp,
434061da546Spatrick        extra_options=None,
435061da546Spatrick        num_expected_locations=-1):
436061da546Spatrick    """Set a breakpoint by regular expression match on symbol name.  Common options are the same as run_break_set_by_file_and_line."""
437061da546Spatrick
438061da546Spatrick    command = 'breakpoint set -r "%s"' % (regexp)
439061da546Spatrick    if extra_options:
440061da546Spatrick        command += " " + extra_options
441061da546Spatrick
442061da546Spatrick    break_results = run_break_set_command(test, command)
443061da546Spatrick
444061da546Spatrick    check_breakpoint_result(
445061da546Spatrick        test,
446061da546Spatrick        break_results,
447061da546Spatrick        num_locations=num_expected_locations)
448061da546Spatrick
449061da546Spatrick    return get_bpno_from_match(break_results)
450061da546Spatrick
451061da546Spatrick
452061da546Spatrickdef run_break_set_by_source_regexp(
453061da546Spatrick        test,
454061da546Spatrick        regexp,
455061da546Spatrick        extra_options=None,
456061da546Spatrick        num_expected_locations=-1):
457061da546Spatrick    """Set a breakpoint by source regular expression.  Common options are the same as run_break_set_by_file_and_line."""
458061da546Spatrick    command = 'breakpoint set -p "%s"' % (regexp)
459061da546Spatrick    if extra_options:
460061da546Spatrick        command += " " + extra_options
461061da546Spatrick
462061da546Spatrick    break_results = run_break_set_command(test, command)
463061da546Spatrick
464061da546Spatrick    check_breakpoint_result(
465061da546Spatrick        test,
466061da546Spatrick        break_results,
467061da546Spatrick        num_locations=num_expected_locations)
468061da546Spatrick
469061da546Spatrick    return get_bpno_from_match(break_results)
470061da546Spatrick
471be691f3bSpatrickdef run_break_set_by_file_colon_line(
472be691f3bSpatrick        test,
473be691f3bSpatrick        specifier,
474be691f3bSpatrick        path,
475be691f3bSpatrick        line_number,
476be691f3bSpatrick        column_number = 0,
477be691f3bSpatrick        extra_options=None,
478be691f3bSpatrick        num_expected_locations=-1):
479be691f3bSpatrick    command = 'breakpoint set -y "%s"'%(specifier)
480be691f3bSpatrick    if extra_options:
481be691f3bSpatrick        command += " " + extra_options
482be691f3bSpatrick
483be691f3bSpatrick    print("About to run: '%s'", command)
484be691f3bSpatrick    break_results = run_break_set_command(test, command)
485be691f3bSpatrick    check_breakpoint_result(
486be691f3bSpatrick        test,
487be691f3bSpatrick        break_results,
488be691f3bSpatrick        num_locations = num_expected_locations,
489be691f3bSpatrick        file_name = path,
490be691f3bSpatrick        line_number = line_number,
491be691f3bSpatrick        column_number = column_number)
492be691f3bSpatrick
493be691f3bSpatrick    return get_bpno_from_match(break_results)
494061da546Spatrick
495061da546Spatrickdef run_break_set_command(test, command):
496061da546Spatrick    """Run the command passed in - it must be some break set variant - and analyze the result.
497061da546Spatrick    Returns a dictionary of information gleaned from the command-line results.
498061da546Spatrick    Will assert if the breakpoint setting fails altogether.
499061da546Spatrick
500061da546Spatrick    Dictionary will contain:
501061da546Spatrick        bpno          - breakpoint of the newly created breakpoint, -1 on error.
502061da546Spatrick        num_locations - number of locations set for the breakpoint.
503061da546Spatrick
504061da546Spatrick    If there is only one location, the dictionary MAY contain:
505061da546Spatrick        file          - source file name
506061da546Spatrick        line_no       - source line number
507be691f3bSpatrick        column        - source column number
508061da546Spatrick        symbol        - symbol name
509061da546Spatrick        inline_symbol - inlined symbol name
510061da546Spatrick        offset        - offset from the original symbol
511061da546Spatrick        module        - module
512061da546Spatrick        address       - address at which the breakpoint was set."""
513061da546Spatrick
514061da546Spatrick    patterns = [
515061da546Spatrick        r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>[0-9]+) locations\.$",
516061da546Spatrick        r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>no) locations \(pending\)\.",
517061da546Spatrick        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]+)$",
518061da546Spatrick        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]+)$"]
519061da546Spatrick    match_object = test.match(command, patterns)
520061da546Spatrick    break_results = match_object.groupdict()
521061da546Spatrick
522061da546Spatrick    # We always insert the breakpoint number, setting it to -1 if we couldn't find it
523061da546Spatrick    # Also, make sure it gets stored as an integer.
524061da546Spatrick    if not 'bpno' in break_results:
525061da546Spatrick        break_results['bpno'] = -1
526061da546Spatrick    else:
527061da546Spatrick        break_results['bpno'] = int(break_results['bpno'])
528061da546Spatrick
529061da546Spatrick    # We always insert the number of locations
530061da546Spatrick    # If ONE location is set for the breakpoint, then the output doesn't mention locations, but it has to be 1...
531061da546Spatrick    # We also make sure it is an integer.
532061da546Spatrick
533061da546Spatrick    if not 'num_locations' in break_results:
534061da546Spatrick        num_locations = 1
535061da546Spatrick    else:
536061da546Spatrick        num_locations = break_results['num_locations']
537061da546Spatrick        if num_locations == 'no':
538061da546Spatrick            num_locations = 0
539061da546Spatrick        else:
540061da546Spatrick            num_locations = int(break_results['num_locations'])
541061da546Spatrick
542061da546Spatrick    break_results['num_locations'] = num_locations
543061da546Spatrick
544061da546Spatrick    if 'line_no' in break_results:
545061da546Spatrick        break_results['line_no'] = int(break_results['line_no'])
546061da546Spatrick
547061da546Spatrick    return break_results
548061da546Spatrick
549061da546Spatrick
550061da546Spatrickdef get_bpno_from_match(break_results):
551061da546Spatrick    return int(break_results['bpno'])
552061da546Spatrick
553061da546Spatrick
554061da546Spatrickdef check_breakpoint_result(
555061da546Spatrick        test,
556061da546Spatrick        break_results,
557061da546Spatrick        file_name=None,
558061da546Spatrick        line_number=-1,
559be691f3bSpatrick        column_number=0,
560061da546Spatrick        symbol_name=None,
561061da546Spatrick        symbol_match_exact=True,
562061da546Spatrick        module_name=None,
563061da546Spatrick        offset=-1,
564061da546Spatrick        num_locations=-1):
565061da546Spatrick
566061da546Spatrick    out_num_locations = break_results['num_locations']
567061da546Spatrick
568061da546Spatrick    if num_locations == -1:
569061da546Spatrick        test.assertTrue(out_num_locations > 0,
570061da546Spatrick                        "Expecting one or more locations, got none.")
571061da546Spatrick    elif num_locations != -2:
572061da546Spatrick        test.assertTrue(
573061da546Spatrick            num_locations == out_num_locations,
574061da546Spatrick            "Expecting %d locations, got %d." %
575061da546Spatrick            (num_locations,
576061da546Spatrick             out_num_locations))
577061da546Spatrick
578061da546Spatrick    if file_name:
579061da546Spatrick        out_file_name = ""
580061da546Spatrick        if 'file' in break_results:
581061da546Spatrick            out_file_name = break_results['file']
582061da546Spatrick        test.assertTrue(
583061da546Spatrick            file_name.endswith(out_file_name),
584061da546Spatrick            "Breakpoint file name '%s' doesn't match resultant name '%s'." %
585061da546Spatrick            (file_name,
586061da546Spatrick             out_file_name))
587061da546Spatrick
588061da546Spatrick    if line_number != -1:
589061da546Spatrick        out_line_number = -1
590061da546Spatrick        if 'line_no' in break_results:
591061da546Spatrick            out_line_number = break_results['line_no']
592061da546Spatrick
593061da546Spatrick        test.assertTrue(
594061da546Spatrick            line_number == out_line_number,
595061da546Spatrick            "Breakpoint line number %s doesn't match resultant line %s." %
596061da546Spatrick            (line_number,
597061da546Spatrick             out_line_number))
598061da546Spatrick
599be691f3bSpatrick    if column_number != 0:
600be691f3bSpatrick        out_column_number = 0
601be691f3bSpatrick        if 'column' in break_results:
602be691f3bSpatrick            out_column_number = break_results['column']
603be691f3bSpatrick
604be691f3bSpatrick        test.assertTrue(
605be691f3bSpatrick            column_number == out_column_number,
606be691f3bSpatrick            "Breakpoint column number %s doesn't match resultant column %s." %
607be691f3bSpatrick            (column_number,
608be691f3bSpatrick             out_column_number))
609be691f3bSpatrick
610061da546Spatrick    if symbol_name:
611061da546Spatrick        out_symbol_name = ""
612061da546Spatrick        # Look first for the inlined symbol name, otherwise use the symbol
613061da546Spatrick        # name:
614061da546Spatrick        if 'inline_symbol' in break_results and break_results['inline_symbol']:
615061da546Spatrick            out_symbol_name = break_results['inline_symbol']
616061da546Spatrick        elif 'symbol' in break_results:
617061da546Spatrick            out_symbol_name = break_results['symbol']
618061da546Spatrick
619061da546Spatrick        if symbol_match_exact:
620061da546Spatrick            test.assertTrue(
621061da546Spatrick                symbol_name == out_symbol_name,
622061da546Spatrick                "Symbol name '%s' doesn't match resultant symbol '%s'." %
623061da546Spatrick                (symbol_name,
624061da546Spatrick                 out_symbol_name))
625061da546Spatrick        else:
626061da546Spatrick            test.assertTrue(
627061da546Spatrick                out_symbol_name.find(symbol_name) != -
628061da546Spatrick                1,
629061da546Spatrick                "Symbol name '%s' isn't in resultant symbol '%s'." %
630061da546Spatrick                (symbol_name,
631061da546Spatrick                 out_symbol_name))
632061da546Spatrick
633061da546Spatrick    if module_name:
634061da546Spatrick        out_module_name = None
635061da546Spatrick        if 'module' in break_results:
636061da546Spatrick            out_module_name = break_results['module']
637061da546Spatrick
638061da546Spatrick        test.assertTrue(
639061da546Spatrick            module_name.find(out_module_name) != -
640061da546Spatrick            1,
641061da546Spatrick            "Symbol module name '%s' isn't in expected module name '%s'." %
642061da546Spatrick            (out_module_name,
643061da546Spatrick             module_name))
644061da546Spatrick
645*f6aab3d8Srobertdef check_breakpoint(
646*f6aab3d8Srobert            test,
647*f6aab3d8Srobert            bpno,
648*f6aab3d8Srobert            expected_locations = None,
649*f6aab3d8Srobert            expected_resolved_count = None,
650*f6aab3d8Srobert            expected_hit_count = None,
651*f6aab3d8Srobert            location_id = None,
652*f6aab3d8Srobert            expected_location_resolved = True,
653*f6aab3d8Srobert            expected_location_hit_count = None):
654*f6aab3d8Srobert    """
655*f6aab3d8Srobert    Test breakpoint or breakpoint location.
656*f6aab3d8Srobert    Breakpoint resolved count is always checked. If not specified the assumption is that all locations
657*f6aab3d8Srobert    should be resolved.
658*f6aab3d8Srobert    To test a breakpoint location, breakpoint number (bpno) and location_id must be set. In this case
659*f6aab3d8Srobert    the resolved count for a breakpoint is not tested by default. The location is expected to be resolved,
660*f6aab3d8Srobert    unless expected_location_resolved is set to False.
661*f6aab3d8Srobert    test - test context
662*f6aab3d8Srobert    bpno - breakpoint number to test
663*f6aab3d8Srobert    expected_locations - expected number of locations for this breakpoint. If 'None' this parameter is not tested.
664*f6aab3d8Srobert    expected_resolved_count - expected resolved locations number for the breakpoint.  If 'None' - all locations should be resolved.
665*f6aab3d8Srobert    expected_hit_count - expected hit count for this breakpoint. If 'None' this parameter is not tested.
666*f6aab3d8Srobert    location_id - If not 'None' sets the location ID for the breakpoint to test.
667*f6aab3d8Srobert    expected_location_resolved - Extected resolved status for the location_id (True/False). Default - True.
668*f6aab3d8Srobert    expected_location_hit_count - Expected hit count for the breakpoint at location_id. Must be set if the location_id parameter is set.
669*f6aab3d8Srobert    """
670*f6aab3d8Srobert
671*f6aab3d8Srobert    if isinstance(test.target, lldb.SBTarget):
672*f6aab3d8Srobert        target = test.target
673*f6aab3d8Srobert    else:
674*f6aab3d8Srobert        target = test.target()
675*f6aab3d8Srobert    bkpt = target.FindBreakpointByID(bpno)
676*f6aab3d8Srobert
677*f6aab3d8Srobert    test.assertTrue(bkpt.IsValid(), "Breakpoint is not valid.")
678*f6aab3d8Srobert
679*f6aab3d8Srobert    if expected_locations is not None:
680*f6aab3d8Srobert        test.assertEquals(expected_locations, bkpt.GetNumLocations())
681*f6aab3d8Srobert
682*f6aab3d8Srobert    if expected_resolved_count is not None:
683*f6aab3d8Srobert        test.assertEquals(expected_resolved_count, bkpt.GetNumResolvedLocations())
684*f6aab3d8Srobert    else:
685*f6aab3d8Srobert        expected_resolved_count = bkpt.GetNumLocations()
686*f6aab3d8Srobert        if location_id is None:
687*f6aab3d8Srobert            test.assertEquals(expected_resolved_count, bkpt.GetNumResolvedLocations())
688*f6aab3d8Srobert
689*f6aab3d8Srobert    if expected_hit_count is not None:
690*f6aab3d8Srobert        test.assertEquals(expected_hit_count, bkpt.GetHitCount())
691*f6aab3d8Srobert
692*f6aab3d8Srobert    if location_id is not None:
693*f6aab3d8Srobert        loc_bkpt = bkpt.FindLocationByID(location_id)
694*f6aab3d8Srobert        test.assertTrue(loc_bkpt.IsValid(), "Breakpoint location is not valid.")
695*f6aab3d8Srobert        test.assertEquals(loc_bkpt.IsResolved(), expected_location_resolved)
696*f6aab3d8Srobert        if expected_location_hit_count is not None:
697*f6aab3d8Srobert            test.assertEquals(expected_location_hit_count, loc_bkpt.GetHitCount())
698*f6aab3d8Srobert
699*f6aab3d8Srobert
700*f6aab3d8Srobert
701061da546Spatrick# ==================================================
702061da546Spatrick# Utility functions related to Threads and Processes
703061da546Spatrick# ==================================================
704061da546Spatrick
705061da546Spatrick
706061da546Spatrickdef get_stopped_threads(process, reason):
707061da546Spatrick    """Returns the thread(s) with the specified stop reason in a list.
708061da546Spatrick
709061da546Spatrick    The list can be empty if no such thread exists.
710061da546Spatrick    """
711061da546Spatrick    threads = []
712061da546Spatrick    for t in process:
713061da546Spatrick        if t.GetStopReason() == reason:
714061da546Spatrick            threads.append(t)
715061da546Spatrick    return threads
716061da546Spatrick
717061da546Spatrick
718061da546Spatrickdef get_stopped_thread(process, reason):
719061da546Spatrick    """A convenience function which returns the first thread with the given stop
720061da546Spatrick    reason or None.
721061da546Spatrick
722061da546Spatrick    Example usages:
723061da546Spatrick
724061da546Spatrick    1. Get the stopped thread due to a breakpoint condition
725061da546Spatrick
726061da546Spatrick    ...
727061da546Spatrick        from lldbutil import get_stopped_thread
728061da546Spatrick        thread = get_stopped_thread(process, lldb.eStopReasonPlanComplete)
729061da546Spatrick        self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition")
730061da546Spatrick    ...
731061da546Spatrick
732061da546Spatrick    2. Get the thread stopped due to a breakpoint
733061da546Spatrick
734061da546Spatrick    ...
735061da546Spatrick        from lldbutil import get_stopped_thread
736061da546Spatrick        thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
737061da546Spatrick        self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint")
738061da546Spatrick    ...
739061da546Spatrick
740061da546Spatrick    """
741061da546Spatrick    threads = get_stopped_threads(process, reason)
742061da546Spatrick    if len(threads) == 0:
743061da546Spatrick        return None
744061da546Spatrick    return threads[0]
745061da546Spatrick
746061da546Spatrick
747061da546Spatrickdef get_threads_stopped_at_breakpoint_id(process, bpid):
748061da546Spatrick    """ For a stopped process returns the thread stopped at the breakpoint passed in bkpt"""
749061da546Spatrick    stopped_threads = []
750061da546Spatrick    threads = []
751061da546Spatrick
752061da546Spatrick    stopped_threads = get_stopped_threads(process, lldb.eStopReasonBreakpoint)
753061da546Spatrick
754061da546Spatrick    if len(stopped_threads) == 0:
755061da546Spatrick        return threads
756061da546Spatrick
757061da546Spatrick    for thread in stopped_threads:
758061da546Spatrick        # Make sure we've hit our breakpoint...
759061da546Spatrick        break_id = thread.GetStopReasonDataAtIndex(0)
760061da546Spatrick        if break_id == bpid:
761061da546Spatrick            threads.append(thread)
762061da546Spatrick
763061da546Spatrick    return threads
764061da546Spatrick
765061da546Spatrick
766061da546Spatrickdef get_threads_stopped_at_breakpoint(process, bkpt):
767061da546Spatrick    return get_threads_stopped_at_breakpoint_id(process, bkpt.GetID())
768061da546Spatrick
769061da546Spatrick
770061da546Spatrickdef get_one_thread_stopped_at_breakpoint_id(
771061da546Spatrick        process, bpid, require_exactly_one=True):
772061da546Spatrick    threads = get_threads_stopped_at_breakpoint_id(process, bpid)
773061da546Spatrick    if len(threads) == 0:
774061da546Spatrick        return None
775061da546Spatrick    if require_exactly_one and len(threads) != 1:
776061da546Spatrick        return None
777061da546Spatrick
778061da546Spatrick    return threads[0]
779061da546Spatrick
780061da546Spatrick
781061da546Spatrickdef get_one_thread_stopped_at_breakpoint(
782061da546Spatrick        process, bkpt, require_exactly_one=True):
783061da546Spatrick    return get_one_thread_stopped_at_breakpoint_id(
784061da546Spatrick        process, bkpt.GetID(), require_exactly_one)
785061da546Spatrick
786061da546Spatrick
787061da546Spatrickdef is_thread_crashed(test, thread):
788061da546Spatrick    """In the test suite we dereference a null pointer to simulate a crash. The way this is
789061da546Spatrick    reported depends on the platform."""
790061da546Spatrick    if test.platformIsDarwin():
791061da546Spatrick        return thread.GetStopReason(
792061da546Spatrick        ) == lldb.eStopReasonException and "EXC_BAD_ACCESS" in thread.GetStopDescription(100)
793061da546Spatrick    elif test.getPlatform() == "linux":
794061da546Spatrick        return thread.GetStopReason() == lldb.eStopReasonSignal and thread.GetStopReasonDataAtIndex(
795061da546Spatrick            0) == thread.GetProcess().GetUnixSignals().GetSignalNumberFromName("SIGSEGV")
796061da546Spatrick    elif test.getPlatform() == "windows":
797061da546Spatrick        return "Exception 0xc0000005" in thread.GetStopDescription(200)
798061da546Spatrick    else:
799061da546Spatrick        return "invalid address" in thread.GetStopDescription(100)
800061da546Spatrick
801061da546Spatrick
802061da546Spatrickdef get_crashed_threads(test, process):
803061da546Spatrick    threads = []
804061da546Spatrick    if process.GetState() != lldb.eStateStopped:
805061da546Spatrick        return threads
806061da546Spatrick    for thread in process:
807061da546Spatrick        if is_thread_crashed(test, thread):
808061da546Spatrick            threads.append(thread)
809061da546Spatrick    return threads
810061da546Spatrick
811061da546Spatrick# Helper functions for run_to_{source,name}_breakpoint:
812061da546Spatrick
813061da546Spatrickdef run_to_breakpoint_make_target(test, exe_name = "a.out", in_cwd = True):
814061da546Spatrick    if in_cwd:
815061da546Spatrick        exe = test.getBuildArtifact(exe_name)
816061da546Spatrick
817061da546Spatrick    # Create the target
818061da546Spatrick    target = test.dbg.CreateTarget(exe)
819061da546Spatrick    test.assertTrue(target, "Target: %s is not valid."%(exe_name))
820061da546Spatrick
821061da546Spatrick    # Set environment variables for the inferior.
822061da546Spatrick    if lldbtest_config.inferior_env:
823061da546Spatrick        test.runCmd('settings set target.env-vars {}'.format(
824061da546Spatrick            lldbtest_config.inferior_env))
825061da546Spatrick
826061da546Spatrick    return target
827061da546Spatrick
828061da546Spatrickdef run_to_breakpoint_do_run(test, target, bkpt, launch_info = None,
829061da546Spatrick                             only_one_thread = True, extra_images = None):
830061da546Spatrick
831061da546Spatrick    # Launch the process, and do not stop at the entry point.
832061da546Spatrick    if not launch_info:
833061da546Spatrick        launch_info = target.GetLaunchInfo()
834061da546Spatrick        launch_info.SetWorkingDirectory(test.get_process_working_directory())
835061da546Spatrick
836dda28197Spatrick    if extra_images:
837061da546Spatrick        environ = test.registerSharedLibrariesWithTarget(target, extra_images)
838061da546Spatrick        launch_info.SetEnvironmentEntries(environ, True)
839061da546Spatrick
840061da546Spatrick    error = lldb.SBError()
841061da546Spatrick    process = target.Launch(launch_info, error)
842061da546Spatrick
843be691f3bSpatrick    # Unfortunate workaround for the iPhone simulator.
844be691f3bSpatrick    retry = SIMULATOR_RETRY
845be691f3bSpatrick    while (retry and error.Fail() and error.GetCString() and
846be691f3bSpatrick           "Unable to boot the Simulator" in error.GetCString()):
847be691f3bSpatrick        retry -= 1
848be691f3bSpatrick        print("** Simulator is unresponsive. Retrying %d more time(s)"%retry)
849be691f3bSpatrick        import time
850be691f3bSpatrick        time.sleep(60)
851be691f3bSpatrick        error = lldb.SBError()
852be691f3bSpatrick        process = target.Launch(launch_info, error)
853be691f3bSpatrick
854061da546Spatrick    test.assertTrue(process,
855be691f3bSpatrick                    "Could not create a valid process for %s: %s" %
856be691f3bSpatrick                    (target.GetExecutable().GetFilename(), error.GetCString()))
857061da546Spatrick    test.assertFalse(error.Fail(),
858061da546Spatrick                     "Process launch failed: %s" % (error.GetCString()))
859061da546Spatrick
860*f6aab3d8Srobert    def processStateInfo(process):
861*f6aab3d8Srobert        info = "state: {}".format(state_type_to_str(process.state))
862*f6aab3d8Srobert        if process.state == lldb.eStateExited:
863*f6aab3d8Srobert            info += ", exit code: {}".format(process.GetExitStatus())
864*f6aab3d8Srobert            if process.exit_description:
865*f6aab3d8Srobert                info += ", exit description: '{}'".format(process.exit_description)
866*f6aab3d8Srobert        stdout = process.GetSTDOUT(999)
867*f6aab3d8Srobert        if stdout:
868*f6aab3d8Srobert            info += ", stdout: '{}'".format(stdout)
869*f6aab3d8Srobert        stderr = process.GetSTDERR(999)
870*f6aab3d8Srobert        if stderr:
871*f6aab3d8Srobert            info += ", stderr: '{}'".format(stderr)
872*f6aab3d8Srobert        return info
873*f6aab3d8Srobert
874*f6aab3d8Srobert    if process.state != lldb.eStateStopped:
875*f6aab3d8Srobert        test.fail("Test process is not stopped at breakpoint: {}".format(processStateInfo(process)))
876dda28197Spatrick
877061da546Spatrick    # Frame #0 should be at our breakpoint.
878061da546Spatrick    threads = get_threads_stopped_at_breakpoint(
879061da546Spatrick                process, bkpt)
880061da546Spatrick
881061da546Spatrick    num_threads = len(threads)
882061da546Spatrick    if only_one_thread:
883061da546Spatrick        test.assertEqual(num_threads, 1, "Expected 1 thread to stop at breakpoint, %d did."%(num_threads))
884061da546Spatrick    else:
885061da546Spatrick        test.assertGreater(num_threads, 0, "No threads stopped at breakpoint")
886061da546Spatrick
887061da546Spatrick    thread = threads[0]
888061da546Spatrick    return (target, process, thread, bkpt)
889061da546Spatrick
890061da546Spatrickdef run_to_name_breakpoint (test, bkpt_name, launch_info = None,
891061da546Spatrick                            exe_name = "a.out",
892061da546Spatrick                            bkpt_module = None,
893061da546Spatrick                            in_cwd = True,
894061da546Spatrick                            only_one_thread = True,
895061da546Spatrick                            extra_images = None):
896061da546Spatrick    """Start up a target, using exe_name as the executable, and run it to
897061da546Spatrick       a breakpoint set by name on bkpt_name restricted to bkpt_module.
898061da546Spatrick
899061da546Spatrick       If you want to pass in launch arguments or environment
900061da546Spatrick       variables, you can optionally pass in an SBLaunchInfo.  If you
901061da546Spatrick       do that, remember to set the working directory as well.
902061da546Spatrick
903061da546Spatrick       If your executable isn't called a.out, you can pass that in.
904061da546Spatrick       And if your executable isn't in the CWD, pass in the absolute
905061da546Spatrick       path to the executable in exe_name, and set in_cwd to False.
906061da546Spatrick
907061da546Spatrick       If you need to restrict the breakpoint to a particular module,
908061da546Spatrick       pass the module name (a string not a FileSpec) in bkpt_module.  If
909061da546Spatrick       nothing is passed in setting will be unrestricted.
910061da546Spatrick
911061da546Spatrick       If the target isn't valid, the breakpoint isn't found, or hit, the
912061da546Spatrick       function will cause a testsuite failure.
913061da546Spatrick
914061da546Spatrick       If successful it returns a tuple with the target process and
915061da546Spatrick       thread that hit the breakpoint, and the breakpoint that we set
916061da546Spatrick       for you.
917061da546Spatrick
918061da546Spatrick       If only_one_thread is true, we require that there be only one
919061da546Spatrick       thread stopped at the breakpoint.  Otherwise we only require one
920061da546Spatrick       or more threads stop there.  If there are more than one, we return
921061da546Spatrick       the first thread that stopped.
922061da546Spatrick    """
923061da546Spatrick
924061da546Spatrick    target = run_to_breakpoint_make_target(test, exe_name, in_cwd)
925061da546Spatrick
926061da546Spatrick    breakpoint = target.BreakpointCreateByName(bkpt_name, bkpt_module)
927061da546Spatrick
928061da546Spatrick
929061da546Spatrick    test.assertTrue(breakpoint.GetNumLocations() > 0,
930061da546Spatrick                    "No locations found for name breakpoint: '%s'."%(bkpt_name))
931061da546Spatrick    return run_to_breakpoint_do_run(test, target, breakpoint, launch_info,
932061da546Spatrick                                    only_one_thread, extra_images)
933061da546Spatrick
934061da546Spatrickdef run_to_source_breakpoint(test, bkpt_pattern, source_spec,
935061da546Spatrick                             launch_info = None, exe_name = "a.out",
936061da546Spatrick                             bkpt_module = None,
937061da546Spatrick                             in_cwd = True,
938061da546Spatrick                             only_one_thread = True,
939*f6aab3d8Srobert                             extra_images = None,
940*f6aab3d8Srobert                             has_locations_before_run = True):
941061da546Spatrick    """Start up a target, using exe_name as the executable, and run it to
942061da546Spatrick       a breakpoint set by source regex bkpt_pattern.
943061da546Spatrick
944061da546Spatrick       The rest of the behavior is the same as run_to_name_breakpoint.
945061da546Spatrick    """
946061da546Spatrick
947061da546Spatrick    target = run_to_breakpoint_make_target(test, exe_name, in_cwd)
948061da546Spatrick    # Set the breakpoints
949061da546Spatrick    breakpoint = target.BreakpointCreateBySourceRegex(
950061da546Spatrick            bkpt_pattern, source_spec, bkpt_module)
951*f6aab3d8Srobert    if has_locations_before_run:
952061da546Spatrick        test.assertTrue(breakpoint.GetNumLocations() > 0,
953061da546Spatrick                        'No locations found for source breakpoint: "%s", file: "%s", dir: "%s"'
954061da546Spatrick                        %(bkpt_pattern, source_spec.GetFilename(), source_spec.GetDirectory()))
955061da546Spatrick    return run_to_breakpoint_do_run(test, target, breakpoint, launch_info,
956061da546Spatrick                                    only_one_thread, extra_images)
957061da546Spatrick
958061da546Spatrickdef run_to_line_breakpoint(test, source_spec, line_number, column = 0,
959061da546Spatrick                           launch_info = None, exe_name = "a.out",
960061da546Spatrick                           bkpt_module = None,
961061da546Spatrick                           in_cwd = True,
962061da546Spatrick                           only_one_thread = True,
963061da546Spatrick                           extra_images = None):
964061da546Spatrick    """Start up a target, using exe_name as the executable, and run it to
965061da546Spatrick       a breakpoint set by (source_spec, line_number(, column)).
966061da546Spatrick
967061da546Spatrick       The rest of the behavior is the same as run_to_name_breakpoint.
968061da546Spatrick    """
969061da546Spatrick
970061da546Spatrick    target = run_to_breakpoint_make_target(test, exe_name, in_cwd)
971061da546Spatrick    # Set the breakpoints
972061da546Spatrick    breakpoint = target.BreakpointCreateByLocation(
973061da546Spatrick        source_spec, line_number, column, 0, lldb.SBFileSpecList())
974061da546Spatrick    test.assertTrue(breakpoint.GetNumLocations() > 0,
975061da546Spatrick        'No locations found for line breakpoint: "%s:%d(:%d)", dir: "%s"'
976061da546Spatrick        %(source_spec.GetFilename(), line_number, column,
977061da546Spatrick          source_spec.GetDirectory()))
978061da546Spatrick    return run_to_breakpoint_do_run(test, target, breakpoint, launch_info,
979061da546Spatrick                                    only_one_thread, extra_images)
980061da546Spatrick
981061da546Spatrick
982061da546Spatrickdef continue_to_breakpoint(process, bkpt):
983061da546Spatrick    """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
984061da546Spatrick    process.Continue()
985061da546Spatrick    if process.GetState() != lldb.eStateStopped:
986061da546Spatrick        return None
987061da546Spatrick    else:
988061da546Spatrick        return get_threads_stopped_at_breakpoint(process, bkpt)
989061da546Spatrick
990061da546Spatrick
991*f6aab3d8Srobertdef continue_to_source_breakpoint(test, process, bkpt_pattern, source_spec):
992*f6aab3d8Srobert    """
993*f6aab3d8Srobert    Sets a breakpoint set by source regex bkpt_pattern, continues the process, and deletes the breakpoint again.
994*f6aab3d8Srobert    Otherwise the same as `continue_to_breakpoint`
995*f6aab3d8Srobert    """
996*f6aab3d8Srobert    breakpoint = process.target.BreakpointCreateBySourceRegex(
997*f6aab3d8Srobert            bkpt_pattern, source_spec, None)
998*f6aab3d8Srobert    test.assertTrue(breakpoint.GetNumLocations() > 0,
999*f6aab3d8Srobert                    'No locations found for source breakpoint: "%s", file: "%s", dir: "%s"'
1000*f6aab3d8Srobert                    %(bkpt_pattern, source_spec.GetFilename(), source_spec.GetDirectory()))
1001*f6aab3d8Srobert    stopped_threads = continue_to_breakpoint(process, breakpoint)
1002*f6aab3d8Srobert    process.target.BreakpointDelete(breakpoint.GetID())
1003*f6aab3d8Srobert    return stopped_threads
1004*f6aab3d8Srobert
1005*f6aab3d8Srobert
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
1095*f6aab3d8Srobert    output = io.StringIO() 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
1157*f6aab3d8Srobert    output = io.StringIO() 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
1200*f6aab3d8Srobertdef start_listening_from(broadcaster, event_mask):
1201*f6aab3d8Srobert    """Creates a listener for a specific event mask and add it to the source broadcaster."""
1202*f6aab3d8Srobert
1203*f6aab3d8Srobert    listener = lldb.SBListener("lldb.test.listener")
1204*f6aab3d8Srobert    broadcaster.AddListener(listener, event_mask)
1205*f6aab3d8Srobert    return listener
1206*f6aab3d8Srobert
1207*f6aab3d8Srobertdef fetch_next_event(test, listener, broadcaster, timeout=10):
1208*f6aab3d8Srobert    """Fetch one event from the listener and return it if it matches the provided broadcaster.
1209*f6aab3d8Srobert    Fails otherwise."""
1210*f6aab3d8Srobert
1211*f6aab3d8Srobert    event = lldb.SBEvent()
1212*f6aab3d8Srobert
1213*f6aab3d8Srobert    if listener.WaitForEvent(timeout, event):
1214*f6aab3d8Srobert        if event.BroadcasterMatchesRef(broadcaster):
1215*f6aab3d8Srobert            return event
1216*f6aab3d8Srobert
1217*f6aab3d8Srobert        test.fail("received event '%s' from unexpected broadcaster '%s'." %
1218*f6aab3d8Srobert                  (event.GetDescription(), event.GetBroadcaster().GetName()))
1219*f6aab3d8Srobert
1220*f6aab3d8Srobert    test.fail("couldn't fetch an event before reaching the timeout.")
1221*f6aab3d8Srobert
1222*f6aab3d8Srobert
1223061da546Spatrick# ===================================
1224061da546Spatrick# Utility functions related to Frames
1225061da546Spatrick# ===================================
1226061da546Spatrick
1227061da546Spatrick
1228061da546Spatrickdef get_parent_frame(frame):
1229061da546Spatrick    """
1230061da546Spatrick    Returns the parent frame of the input frame object; None if not available.
1231061da546Spatrick    """
1232061da546Spatrick    thread = frame.GetThread()
1233061da546Spatrick    parent_found = False
1234061da546Spatrick    for f in thread:
1235061da546Spatrick        if parent_found:
1236061da546Spatrick            return f
1237061da546Spatrick        if f.GetFrameID() == frame.GetFrameID():
1238061da546Spatrick            parent_found = True
1239061da546Spatrick
1240061da546Spatrick    # If we reach here, no parent has been found, return None.
1241061da546Spatrick    return None
1242061da546Spatrick
1243061da546Spatrick
1244061da546Spatrickdef get_args_as_string(frame, showFuncName=True):
1245061da546Spatrick    """
1246061da546Spatrick    Returns the args of the input frame object as a string.
1247061da546Spatrick    """
1248061da546Spatrick    # arguments     => True
1249061da546Spatrick    # locals        => False
1250061da546Spatrick    # statics       => False
1251061da546Spatrick    # in_scope_only => True
1252061da546Spatrick    vars = frame.GetVariables(True, False, False, True)  # type of SBValueList
1253061da546Spatrick    args = []  # list of strings
1254061da546Spatrick    for var in vars:
1255061da546Spatrick        args.append("(%s)%s=%s" % (var.GetTypeName(),
1256061da546Spatrick                                   var.GetName(),
1257061da546Spatrick                                   var.GetValue()))
1258061da546Spatrick    if frame.GetFunction():
1259061da546Spatrick        name = frame.GetFunction().GetName()
1260061da546Spatrick    elif frame.GetSymbol():
1261061da546Spatrick        name = frame.GetSymbol().GetName()
1262061da546Spatrick    else:
1263061da546Spatrick        name = ""
1264061da546Spatrick    if showFuncName:
1265061da546Spatrick        return "%s(%s)" % (name, ", ".join(args))
1266061da546Spatrick    else:
1267061da546Spatrick        return "(%s)" % (", ".join(args))
1268061da546Spatrick
1269061da546Spatrick
1270061da546Spatrickdef print_registers(frame, string_buffer=False):
1271061da546Spatrick    """Prints all the register sets of the frame."""
1272061da546Spatrick
1273*f6aab3d8Srobert    output = io.StringIO() if string_buffer else sys.stdout
1274061da546Spatrick
1275061da546Spatrick    print("Register sets for " + str(frame), file=output)
1276061da546Spatrick
1277061da546Spatrick    registerSet = frame.GetRegisters()  # Return type of SBValueList.
1278061da546Spatrick    print("Frame registers (size of register set = %d):" %
1279061da546Spatrick          registerSet.GetSize(), file=output)
1280061da546Spatrick    for value in registerSet:
1281061da546Spatrick        #print(value, file=output)
1282061da546Spatrick        print("%s (number of children = %d):" %
1283061da546Spatrick              (value.GetName(), value.GetNumChildren()), file=output)
1284061da546Spatrick        for child in value:
1285061da546Spatrick            print(
1286061da546Spatrick                "Name: %s, Value: %s" %
1287061da546Spatrick                (child.GetName(),
1288061da546Spatrick                 child.GetValue()),
1289061da546Spatrick                file=output)
1290061da546Spatrick
1291061da546Spatrick    if string_buffer:
1292061da546Spatrick        return output.getvalue()
1293061da546Spatrick
1294061da546Spatrick
1295061da546Spatrickdef get_registers(frame, kind):
1296061da546Spatrick    """Returns the registers given the frame and the kind of registers desired.
1297061da546Spatrick
1298061da546Spatrick    Returns None if there's no such kind.
1299061da546Spatrick    """
1300061da546Spatrick    registerSet = frame.GetRegisters()  # Return type of SBValueList.
1301061da546Spatrick    for value in registerSet:
1302061da546Spatrick        if kind.lower() in value.GetName().lower():
1303061da546Spatrick            return value
1304061da546Spatrick
1305061da546Spatrick    return None
1306061da546Spatrick
1307061da546Spatrick
1308061da546Spatrickdef get_GPRs(frame):
1309061da546Spatrick    """Returns the general purpose registers of the frame as an SBValue.
1310061da546Spatrick
1311061da546Spatrick    The returned SBValue object is iterable.  An example:
1312061da546Spatrick        ...
1313061da546Spatrick        from lldbutil import get_GPRs
1314061da546Spatrick        regs = get_GPRs(frame)
1315061da546Spatrick        for reg in regs:
1316061da546Spatrick            print("%s => %s" % (reg.GetName(), reg.GetValue()))
1317061da546Spatrick        ...
1318061da546Spatrick    """
1319061da546Spatrick    return get_registers(frame, "general purpose")
1320061da546Spatrick
1321061da546Spatrick
1322061da546Spatrickdef get_FPRs(frame):
1323061da546Spatrick    """Returns the floating point registers of the frame as an SBValue.
1324061da546Spatrick
1325061da546Spatrick    The returned SBValue object is iterable.  An example:
1326061da546Spatrick        ...
1327061da546Spatrick        from lldbutil import get_FPRs
1328061da546Spatrick        regs = get_FPRs(frame)
1329061da546Spatrick        for reg in regs:
1330061da546Spatrick            print("%s => %s" % (reg.GetName(), reg.GetValue()))
1331061da546Spatrick        ...
1332061da546Spatrick    """
1333061da546Spatrick    return get_registers(frame, "floating point")
1334061da546Spatrick
1335061da546Spatrick
1336061da546Spatrickdef get_ESRs(frame):
1337061da546Spatrick    """Returns the exception state registers of the frame as an SBValue.
1338061da546Spatrick
1339061da546Spatrick    The returned SBValue object is iterable.  An example:
1340061da546Spatrick        ...
1341061da546Spatrick        from lldbutil import get_ESRs
1342061da546Spatrick        regs = get_ESRs(frame)
1343061da546Spatrick        for reg in regs:
1344061da546Spatrick            print("%s => %s" % (reg.GetName(), reg.GetValue()))
1345061da546Spatrick        ...
1346061da546Spatrick    """
1347061da546Spatrick    return get_registers(frame, "exception state")
1348061da546Spatrick
1349061da546Spatrick# ======================================
1350061da546Spatrick# Utility classes/functions for SBValues
1351061da546Spatrick# ======================================
1352061da546Spatrick
1353061da546Spatrick
1354061da546Spatrickclass BasicFormatter(object):
1355061da546Spatrick    """The basic formatter inspects the value object and prints the value."""
1356061da546Spatrick
1357061da546Spatrick    def format(self, value, buffer=None, indent=0):
1358061da546Spatrick        if not buffer:
1359*f6aab3d8Srobert            output = io.StringIO()
1360061da546Spatrick        else:
1361061da546Spatrick            output = buffer
1362061da546Spatrick        # If there is a summary, it suffices.
1363061da546Spatrick        val = value.GetSummary()
1364061da546Spatrick        # Otherwise, get the value.
1365061da546Spatrick        if val is None:
1366061da546Spatrick            val = value.GetValue()
1367061da546Spatrick        if val is None and value.GetNumChildren() > 0:
1368061da546Spatrick            val = "%s (location)" % value.GetLocation()
1369061da546Spatrick        print("{indentation}({type}) {name} = {value}".format(
1370061da546Spatrick            indentation=' ' * indent,
1371061da546Spatrick            type=value.GetTypeName(),
1372061da546Spatrick            name=value.GetName(),
1373061da546Spatrick            value=val), file=output)
1374061da546Spatrick        return output.getvalue()
1375061da546Spatrick
1376061da546Spatrick
1377061da546Spatrickclass ChildVisitingFormatter(BasicFormatter):
1378061da546Spatrick    """The child visiting formatter prints the value and its immediate children.
1379061da546Spatrick
1380061da546Spatrick    The constructor takes a keyword arg: indent_child, which defaults to 2.
1381061da546Spatrick    """
1382061da546Spatrick
1383061da546Spatrick    def __init__(self, indent_child=2):
1384061da546Spatrick        """Default indentation of 2 SPC's for the children."""
1385061da546Spatrick        self.cindent = indent_child
1386061da546Spatrick
1387061da546Spatrick    def format(self, value, buffer=None):
1388061da546Spatrick        if not buffer:
1389*f6aab3d8Srobert            output = io.StringIO()
1390061da546Spatrick        else:
1391061da546Spatrick            output = buffer
1392061da546Spatrick
1393061da546Spatrick        BasicFormatter.format(self, value, buffer=output)
1394061da546Spatrick        for child in value:
1395061da546Spatrick            BasicFormatter.format(
1396061da546Spatrick                self, child, buffer=output, indent=self.cindent)
1397061da546Spatrick
1398061da546Spatrick        return output.getvalue()
1399061da546Spatrick
1400061da546Spatrick
1401061da546Spatrickclass RecursiveDecentFormatter(BasicFormatter):
1402061da546Spatrick    """The recursive decent formatter prints the value and the decendents.
1403061da546Spatrick
1404061da546Spatrick    The constructor takes two keyword args: indent_level, which defaults to 0,
1405061da546Spatrick    and indent_child, which defaults to 2.  The current indentation level is
1406061da546Spatrick    determined by indent_level, while the immediate children has an additional
1407061da546Spatrick    indentation by inden_child.
1408061da546Spatrick    """
1409061da546Spatrick
1410061da546Spatrick    def __init__(self, indent_level=0, indent_child=2):
1411061da546Spatrick        self.lindent = indent_level
1412061da546Spatrick        self.cindent = indent_child
1413061da546Spatrick
1414061da546Spatrick    def format(self, value, buffer=None):
1415061da546Spatrick        if not buffer:
1416*f6aab3d8Srobert            output = io.StringIO()
1417061da546Spatrick        else:
1418061da546Spatrick            output = buffer
1419061da546Spatrick
1420061da546Spatrick        BasicFormatter.format(self, value, buffer=output, indent=self.lindent)
1421061da546Spatrick        new_indent = self.lindent + self.cindent
1422061da546Spatrick        for child in value:
1423061da546Spatrick            if child.GetSummary() is not None:
1424061da546Spatrick                BasicFormatter.format(
1425061da546Spatrick                    self, child, buffer=output, indent=new_indent)
1426061da546Spatrick            else:
1427061da546Spatrick                if child.GetNumChildren() > 0:
1428061da546Spatrick                    rdf = RecursiveDecentFormatter(indent_level=new_indent)
1429061da546Spatrick                    rdf.format(child, buffer=output)
1430061da546Spatrick                else:
1431061da546Spatrick                    BasicFormatter.format(
1432061da546Spatrick                        self, child, buffer=output, indent=new_indent)
1433061da546Spatrick
1434061da546Spatrick        return output.getvalue()
1435061da546Spatrick
1436061da546Spatrick# ===========================================================
1437061da546Spatrick# Utility functions for path manipulation on remote platforms
1438061da546Spatrick# ===========================================================
1439061da546Spatrick
1440061da546Spatrick
1441061da546Spatrickdef join_remote_paths(*paths):
1442061da546Spatrick    # TODO: update with actual platform name for remote windows once it exists
1443061da546Spatrick    if lldb.remote_platform.GetName() == 'remote-windows':
1444061da546Spatrick        return os.path.join(*paths).replace(os.path.sep, '\\')
1445061da546Spatrick    return os.path.join(*paths).replace(os.path.sep, '/')
1446061da546Spatrick
1447061da546Spatrick
1448061da546Spatrickdef append_to_process_working_directory(test, *paths):
1449061da546Spatrick    remote = lldb.remote_platform
1450061da546Spatrick    if remote:
1451061da546Spatrick        return join_remote_paths(remote.GetWorkingDirectory(), *paths)
1452061da546Spatrick    return os.path.join(test.getBuildDir(), *paths)
1453061da546Spatrick
1454061da546Spatrick# ==================================================
1455061da546Spatrick# Utility functions to get the correct signal number
1456061da546Spatrick# ==================================================
1457061da546Spatrick
1458061da546Spatrickimport signal
1459061da546Spatrick
1460061da546Spatrick
1461061da546Spatrickdef get_signal_number(signal_name):
1462061da546Spatrick    platform = lldb.remote_platform
1463061da546Spatrick    if platform and platform.IsValid():
1464061da546Spatrick        signals = platform.GetUnixSignals()
1465061da546Spatrick        if signals.IsValid():
1466061da546Spatrick            signal_number = signals.GetSignalNumberFromName(signal_name)
1467061da546Spatrick            if signal_number > 0:
1468061da546Spatrick                return signal_number
1469061da546Spatrick    # No remote platform; fall back to using local python signals.
1470061da546Spatrick    return getattr(signal, signal_name)
1471061da546Spatrick
1472*f6aab3d8Srobertdef get_actions_for_signal(testcase, signal_name, from_target=False, expected_absent=False):
1473*f6aab3d8Srobert    """Returns a triple of (pass, stop, notify)"""
1474*f6aab3d8Srobert    return_obj = lldb.SBCommandReturnObject()
1475*f6aab3d8Srobert    command = "process handle {0}".format(signal_name)
1476*f6aab3d8Srobert    if from_target:
1477*f6aab3d8Srobert        command += " -t"
1478*f6aab3d8Srobert    testcase.dbg.GetCommandInterpreter().HandleCommand(
1479*f6aab3d8Srobert        command, return_obj)
1480*f6aab3d8Srobert    match = re.match(
1481*f6aab3d8Srobert        'NAME *PASS *STOP *NOTIFY.*(false|true|not set) *(false|true|not set) *(false|true|not set)',
1482*f6aab3d8Srobert        return_obj.GetOutput(),
1483*f6aab3d8Srobert        re.IGNORECASE | re.DOTALL)
1484*f6aab3d8Srobert    if match and expected_absent:
1485*f6aab3d8Srobert        testcase.fail('Signal "{0}" was supposed to be absent'.format(signal_name))
1486*f6aab3d8Srobert    if not match:
1487*f6aab3d8Srobert        if expected_absent:
1488*f6aab3d8Srobert            return (None, None, None)
1489*f6aab3d8Srobert        testcase.fail('Unable to retrieve default signal disposition.')
1490*f6aab3d8Srobert    return (match.group(1), match.group(2), match.group(3))
1491*f6aab3d8Srobert
1492*f6aab3d8Srobert
1493*f6aab3d8Srobert
1494*f6aab3d8Srobertdef set_actions_for_signal(testcase, signal_name, pass_action, stop_action, notify_action, expect_success=True):
1495*f6aab3d8Srobert        return_obj = lldb.SBCommandReturnObject()
1496*f6aab3d8Srobert        command = "process handle {0}".format(signal_name)
1497*f6aab3d8Srobert        if pass_action != None:
1498*f6aab3d8Srobert            command += " -p {0}".format(pass_action)
1499*f6aab3d8Srobert        if stop_action != None:
1500*f6aab3d8Srobert            command += " -s {0}".format(stop_action)
1501*f6aab3d8Srobert        if notify_action != None:
1502*f6aab3d8Srobert            command +=" -n {0}".format(notify_action)
1503*f6aab3d8Srobert
1504*f6aab3d8Srobert        testcase.dbg.GetCommandInterpreter().HandleCommand(command, return_obj)
1505*f6aab3d8Srobert        testcase.assertEqual(expect_success,
1506*f6aab3d8Srobert            return_obj.Succeeded(),
1507*f6aab3d8Srobert            "Setting signal handling for {0} worked as expected".format(signal_name))
1508061da546Spatrick
1509061da546Spatrickclass PrintableRegex(object):
1510061da546Spatrick
1511061da546Spatrick    def __init__(self, text):
1512061da546Spatrick        self.regex = re.compile(text)
1513061da546Spatrick        self.text = text
1514061da546Spatrick
1515061da546Spatrick    def match(self, str):
1516061da546Spatrick        return self.regex.match(str)
1517061da546Spatrick
1518061da546Spatrick    def __str__(self):
1519061da546Spatrick        return "%s" % (self.text)
1520061da546Spatrick
1521061da546Spatrick    def __repr__(self):
1522061da546Spatrick        return "re.compile(%s) -> %s" % (self.text, self.regex)
1523061da546Spatrick
1524061da546Spatrick
1525061da546Spatrickdef skip_if_callable(test, mycallable, reason):
1526*f6aab3d8Srobert    if callable(mycallable):
1527061da546Spatrick        if mycallable(test):
1528061da546Spatrick            test.skipTest(reason)
1529061da546Spatrick            return True
1530061da546Spatrick    return False
1531061da546Spatrick
1532061da546Spatrick
1533061da546Spatrickdef skip_if_library_missing(test, target, library):
1534061da546Spatrick    def find_library(target, library):
1535061da546Spatrick        for module in target.modules:
1536061da546Spatrick            filename = module.file.GetFilename()
1537061da546Spatrick            if isinstance(library, str):
1538061da546Spatrick                if library == filename:
1539061da546Spatrick                    return False
1540061da546Spatrick            elif hasattr(library, 'match'):
1541061da546Spatrick                if library.match(filename):
1542061da546Spatrick                    return False
1543061da546Spatrick        return True
1544061da546Spatrick
1545061da546Spatrick    def find_library_callable(test):
1546061da546Spatrick        return find_library(target, library)
1547061da546Spatrick    return skip_if_callable(
1548061da546Spatrick        test,
1549061da546Spatrick        find_library_callable,
1550061da546Spatrick        "could not find library matching '%s' in target %s" %
1551061da546Spatrick        (library,
1552061da546Spatrick         target))
1553061da546Spatrick
1554061da546Spatrick
1555061da546Spatrickdef read_file_on_target(test, remote):
1556061da546Spatrick    if lldb.remote_platform:
1557061da546Spatrick        local = test.getBuildArtifact("file_from_target")
1558061da546Spatrick        error = lldb.remote_platform.Get(lldb.SBFileSpec(remote, False),
1559061da546Spatrick                    lldb.SBFileSpec(local, True))
1560061da546Spatrick        test.assertTrue(error.Success(), "Reading file {0} failed: {1}".format(remote, error))
1561061da546Spatrick    else:
1562061da546Spatrick        local = remote
1563061da546Spatrick    with open(local, 'r') as f:
1564061da546Spatrick        return f.read()
1565061da546Spatrick
1566061da546Spatrickdef read_file_from_process_wd(test, name):
1567061da546Spatrick    path = append_to_process_working_directory(test, name)
1568061da546Spatrick    return read_file_on_target(test, path)
1569061da546Spatrick
1570061da546Spatrickdef wait_for_file_on_target(testcase, file_path, max_attempts=6):
1571061da546Spatrick    for i in range(max_attempts):
1572061da546Spatrick        err, retcode, msg = testcase.run_platform_command("ls %s" % file_path)
1573061da546Spatrick        if err.Success() and retcode == 0:
1574061da546Spatrick            break
1575061da546Spatrick        if i < max_attempts:
1576061da546Spatrick            # Exponential backoff!
1577061da546Spatrick            import time
1578061da546Spatrick            time.sleep(pow(2, i) * 0.25)
1579061da546Spatrick    else:
1580061da546Spatrick        testcase.fail(
1581061da546Spatrick            "File %s not found even after %d attempts." %
1582061da546Spatrick            (file_path, max_attempts))
1583061da546Spatrick
1584061da546Spatrick    return read_file_on_target(testcase, file_path)
1585be691f3bSpatrick
1586be691f3bSpatrickdef packetlog_get_process_info(log):
1587be691f3bSpatrick    """parse a gdb-remote packet log file and extract the response to qProcessInfo"""
1588be691f3bSpatrick    process_info = dict()
1589be691f3bSpatrick    with open(log, "r") as logfile:
1590be691f3bSpatrick        process_info_ostype = None
1591be691f3bSpatrick        expect_process_info_response = False
1592be691f3bSpatrick        for line in logfile:
1593be691f3bSpatrick            if expect_process_info_response:
1594be691f3bSpatrick                for pair in line.split(';'):
1595be691f3bSpatrick                    keyval = pair.split(':')
1596be691f3bSpatrick                    if len(keyval) == 2:
1597be691f3bSpatrick                        process_info[keyval[0]] = keyval[1]
1598be691f3bSpatrick                break
1599be691f3bSpatrick            if 'send packet: $qProcessInfo#' in line:
1600be691f3bSpatrick                expect_process_info_response = True
1601be691f3bSpatrick    return process_info
1602be691f3bSpatrick
1603be691f3bSpatrickdef packetlog_get_dylib_info(log):
1604be691f3bSpatrick    """parse a gdb-remote packet log file and extract the *last* complete
1605be691f3bSpatrick    (=> fetch_all_solibs=true) response to jGetLoadedDynamicLibrariesInfos"""
1606be691f3bSpatrick    import json
1607be691f3bSpatrick    dylib_info = None
1608be691f3bSpatrick    with open(log, "r") as logfile:
1609be691f3bSpatrick        dylib_info = None
1610be691f3bSpatrick        expect_dylib_info_response = False
1611be691f3bSpatrick        for line in logfile:
1612be691f3bSpatrick            if expect_dylib_info_response:
1613be691f3bSpatrick                while line[0] != '$':
1614be691f3bSpatrick                    line = line[1:]
1615be691f3bSpatrick                line = line[1:]
1616be691f3bSpatrick                # Unescape '}'.
1617be691f3bSpatrick                dylib_info = json.loads(line.replace('}]','}')[:-4])
1618be691f3bSpatrick                expect_dylib_info_response = False
1619be691f3bSpatrick            if 'send packet: $jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}' in line:
1620be691f3bSpatrick                expect_dylib_info_response = True
1621be691f3bSpatrick
1622be691f3bSpatrick    return dylib_info
1623