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