lldbtest.py revision 73a8710e6c7bceda0abeacea054c4aa6d5572d44
1""" 2LLDB module which provides the abstract base class of lldb test case. 3 4The concrete subclass can override lldbtest.TesBase in order to inherit the 5common behavior for unitest.TestCase.setUp/tearDown implemented in this file. 6 7The subclass should override the attribute mydir in order for the python runtime 8to locate the individual test cases when running as part of a large test suite 9or when running each test case as a separate python invocation. 10 11./dotest.py provides a test driver which sets up the environment to run the 12entire test suite. Users who want to run a test case on its own can specify the 13LLDB_TEST and PYTHONPATH environment variables, for example: 14 15$ export LLDB_TEST=$PWD 16$ export PYTHONPATH=/Volumes/data/lldb/svn/trunk/build/Debug/LLDB.framework/Resources/Python:$LLDB_TEST:$LLDB_TEST/plugins 17$ echo $LLDB_TEST 18/Volumes/data/lldb/svn/trunk/test 19$ echo $PYTHONPATH 20/Volumes/data/lldb/svn/trunk/build/Debug/LLDB.framework/Resources/Python:/Volumes/data/lldb/svn/trunk/test:/Volumes/data/lldb/svn/trunk/test/plugins 21$ python function_types/TestFunctionTypes.py 22. 23---------------------------------------------------------------------- 24Ran 1 test in 0.363s 25 26OK 27$ LLDB_COMMAND_TRACE=YES python array_types/TestArrayTypes.py 28 29... 30 31runCmd: breakpoint set -f main.c -l 42 32output: Breakpoint created: 1: file ='main.c', line = 42, locations = 1 33 34runCmd: run 35output: Launching '/Volumes/data/lldb/svn/trunk/test/array_types/a.out' (x86_64) 36 37... 38 39runCmd: frame variable strings 40output: (char *[4]) strings = { 41 (char *) strings[0] = 0x0000000100000f0c "Hello", 42 (char *) strings[1] = 0x0000000100000f12 "Hola", 43 (char *) strings[2] = 0x0000000100000f17 "Bonjour", 44 (char *) strings[3] = 0x0000000100000f1f "Guten Tag" 45} 46 47runCmd: frame variable char_16 48output: (char [16]) char_16 = { 49 (char) char_16[0] = 'H', 50 (char) char_16[1] = 'e', 51 (char) char_16[2] = 'l', 52 (char) char_16[3] = 'l', 53 (char) char_16[4] = 'o', 54 (char) char_16[5] = ' ', 55 (char) char_16[6] = 'W', 56 (char) char_16[7] = 'o', 57 (char) char_16[8] = 'r', 58 (char) char_16[9] = 'l', 59 (char) char_16[10] = 'd', 60 (char) char_16[11] = '\n', 61 (char) char_16[12] = '\0', 62 (char) char_16[13] = '\0', 63 (char) char_16[14] = '\0', 64 (char) char_16[15] = '\0' 65} 66 67runCmd: frame variable ushort_matrix 68output: (unsigned short [2][3]) ushort_matrix = { 69 (unsigned short [3]) ushort_matrix[0] = { 70 (unsigned short) ushort_matrix[0][0] = 0x0001, 71 (unsigned short) ushort_matrix[0][1] = 0x0002, 72 (unsigned short) ushort_matrix[0][2] = 0x0003 73 }, 74 (unsigned short [3]) ushort_matrix[1] = { 75 (unsigned short) ushort_matrix[1][0] = 0x000b, 76 (unsigned short) ushort_matrix[1][1] = 0x0016, 77 (unsigned short) ushort_matrix[1][2] = 0x0021 78 } 79} 80 81runCmd: frame variable long_6 82output: (long [6]) long_6 = { 83 (long) long_6[0] = 1, 84 (long) long_6[1] = 2, 85 (long) long_6[2] = 3, 86 (long) long_6[3] = 4, 87 (long) long_6[4] = 5, 88 (long) long_6[5] = 6 89} 90 91. 92---------------------------------------------------------------------- 93Ran 1 test in 0.349s 94 95OK 96$ 97""" 98 99import os, sys, traceback 100import re 101from subprocess import * 102import StringIO 103import time 104import types 105import unittest2 106import lldb 107 108# See also dotest.parseOptionsAndInitTestdirs(), where the environment variables 109# LLDB_COMMAND_TRACE and LLDB_NO_CLEANUP are set from '-t' and '-r dir' options. 110 111# By default, traceAlways is False. 112if "LLDB_COMMAND_TRACE" in os.environ and os.environ["LLDB_COMMAND_TRACE"]=="YES": 113 traceAlways = True 114else: 115 traceAlways = False 116 117# By default, doCleanup is True. 118if "LLDB_DO_CLEANUP" in os.environ and os.environ["LLDB_DO_CLEANUP"]=="NO": 119 doCleanup = False 120else: 121 doCleanup = True 122 123 124# 125# Some commonly used assert messages. 126# 127 128COMMAND_FAILED_AS_EXPECTED = "Command has failed as expected" 129 130CURRENT_EXECUTABLE_SET = "Current executable set successfully" 131 132PROCESS_IS_VALID = "Process is valid" 133 134PROCESS_KILLED = "Process is killed successfully" 135 136RUN_SUCCEEDED = "Process is launched successfully" 137 138RUN_COMPLETED = "Process exited successfully" 139 140BACKTRACE_DISPLAYED_CORRECTLY = "Backtrace displayed correctly" 141 142BREAKPOINT_CREATED = "Breakpoint created successfully" 143 144BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully" 145 146BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit cout = 1" 147 148BREAKPOINT_HIT_TWICE = "Breakpoint resolved with hit cout = 2" 149 150BREAKPOINT_HIT_THRICE = "Breakpoint resolved with hit cout = 3" 151 152STEP_OUT_SUCCEEDED = "Thread step-out succeeded" 153 154STOPPED_DUE_TO_BREAKPOINT = "Process state is stopped due to breakpoint" 155 156STOPPED_DUE_TO_SIGNAL = "Process state is stopped due to signal" 157 158STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in" 159 160DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly" 161 162VALID_BREAKPOINT = "Got a valid breakpoint" 163 164VALID_FILESPEC = "Got a valid filespec" 165 166VALID_PROCESS = "Got a valid process" 167 168VALID_TARGET = "Got a valid target" 169 170VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly" 171 172 173# 174# And a generic "Command '%s' returns successfully" message generator. 175# 176def CMD_MSG(str, exe): 177 if exe: 178 return "Command '%s' returns successfully" % str 179 else: 180 return "'%s' compares successfully" % str 181 182# 183# And a generic "Value of setting '%s' is correct" message generator. 184# 185def SETTING_MSG(setting): 186 return "Value of setting '%s' is correct" % setting 187 188# 189# Returns an env variable array from the os.environ map object. 190# 191def EnvArray(): 192 return map(lambda k,v: k+"="+v, os.environ.keys(), os.environ.values()) 193 194def line_number(filename, string_to_match): 195 """Helper function to return the line number of the first matched string.""" 196 with open(filename, 'r') as f: 197 for i, line in enumerate(f): 198 if line.find(string_to_match) != -1: 199 # Found our match. 200 return i+1 201 return -1 202 203def pointer_size(): 204 """Return the pointer size of the host system.""" 205 import ctypes 206 a_pointer = ctypes.c_void_p(0xffff) 207 return 8 * ctypes.sizeof(a_pointer) 208 209 210class recording(StringIO.StringIO): 211 """ 212 A nice little context manager for recording the debugger interactions into 213 our session object. If trace flag is ON, it also emits the interactions 214 into the stderr. 215 """ 216 def __init__(self, test, trace): 217 """Create a StringIO instance; record the session obj and trace flag.""" 218 StringIO.StringIO.__init__(self) 219 self.session = test.session if test else None 220 self.trace = trace 221 222 def __enter__(self): 223 """ 224 Context management protocol on entry to the body of the with statement. 225 Just return the StringIO object. 226 """ 227 return self 228 229 def __exit__(self, type, value, tb): 230 """ 231 Context management protocol on exit from the body of the with statement. 232 If trace is ON, it emits the recordings into stderr. Always add the 233 recordings to our session object. And close the StringIO object, too. 234 """ 235 if self.trace: 236 print >> sys.stderr, self.getvalue() 237 if self.session: 238 print >> self.session, self.getvalue() 239 self.close() 240 241# From 2.7's subprocess.check_output() convenience function. 242def system(*popenargs, **kwargs): 243 r"""Run command with arguments and return its output as a byte string. 244 245 If the exit code was non-zero it raises a CalledProcessError. The 246 CalledProcessError object will have the return code in the returncode 247 attribute and output in the output attribute. 248 249 The arguments are the same as for the Popen constructor. Example: 250 251 >>> check_output(["ls", "-l", "/dev/null"]) 252 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n' 253 254 The stdout argument is not allowed as it is used internally. 255 To capture standard error in the result, use stderr=STDOUT. 256 257 >>> check_output(["/bin/sh", "-c", 258 ... "ls -l non_existent_file ; exit 0"], 259 ... stderr=STDOUT) 260 'ls: non_existent_file: No such file or directory\n' 261 """ 262 263 # Assign the sender object to variable 'test' and remove it from kwargs. 264 test = kwargs.pop('sender', None) 265 266 if 'stdout' in kwargs: 267 raise ValueError('stdout argument not allowed, it will be overridden.') 268 process = Popen(stdout=PIPE, *popenargs, **kwargs) 269 output, error = process.communicate() 270 retcode = process.poll() 271 272 with recording(test, traceAlways) as sbuf: 273 if isinstance(popenargs, types.StringTypes): 274 args = [popenargs] 275 else: 276 args = list(popenargs) 277 print >> sbuf 278 print >> sbuf, "os command:", args 279 print >> sbuf, "stdout:", output 280 print >> sbuf, "stderr:", error 281 print >> sbuf, "retcode:", retcode 282 print >> sbuf 283 284 if retcode: 285 cmd = kwargs.get("args") 286 if cmd is None: 287 cmd = popenargs[0] 288 raise CalledProcessError(retcode, cmd) 289 return output 290 291class TestBase(unittest2.TestCase): 292 """This LLDB abstract base class is meant to be subclassed.""" 293 294 @classmethod 295 def skipLongRunningTest(cls): 296 """ 297 By default, we skip long running test case. 298 This can be overridden by passing '-l' to the test driver (dotest.py). 299 """ 300 if "LLDB_SKIP_LONG_RUNNING_TEST" in os.environ and "NO" == os.environ["LLDB_SKIP_LONG_RUNNING_TEST"]: 301 return False 302 else: 303 return True 304 305 # The concrete subclass should override this attribute. 306 mydir = None 307 308 # State pertaining to the inferior process, if any. 309 # This reflects inferior process started through the command interface with 310 # either the lldb "run" or "process launch" command. 311 # See also self.runCmd(). 312 runStarted = False 313 314 # Maximum allowed attempts when launching the inferior process. 315 # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable. 316 maxLaunchCount = 3; 317 318 # Time to wait before the next launching attempt in second(s). 319 # Can be overridden by the LLDB_TIME_WAIT_NEXT_LAUNCH environment variable. 320 timeWait = 1.0; 321 322 # Keep track of the old current working directory. 323 oldcwd = None 324 325 @classmethod 326 def setUpClass(cls): 327 """ 328 Python unittest framework class setup fixture. 329 Do current directory manipulation. 330 """ 331 332 # Fail fast if 'mydir' attribute is not overridden. 333 if not cls.mydir or len(cls.mydir) == 0: 334 raise Exception("Subclasses must override the 'mydir' attribute.") 335 # Save old working directory. 336 cls.oldcwd = os.getcwd() 337 338 # Change current working directory if ${LLDB_TEST} is defined. 339 # See also dotest.py which sets up ${LLDB_TEST}. 340 if ("LLDB_TEST" in os.environ): 341 if traceAlways: 342 print >> sys.stderr, "Change dir to:", os.path.join(os.environ["LLDB_TEST"], cls.mydir) 343 os.chdir(os.path.join(os.environ["LLDB_TEST"], cls.mydir)) 344 345 @classmethod 346 def tearDownClass(cls): 347 """ 348 Python unittest framework class teardown fixture. 349 Do class-wide cleanup. 350 """ 351 352 if doCleanup: 353 # First, let's do the platform-specific cleanup. 354 module = __import__(sys.platform) 355 if not module.cleanup(): 356 raise Exception("Don't know how to do cleanup") 357 358 # Subclass might have specific cleanup function defined. 359 if getattr(cls, "classCleanup", None): 360 if traceAlways: 361 print >> sys.stderr, "Call class-specific cleanup function for class:", cls 362 try: 363 cls.classCleanup() 364 except: 365 exc_type, exc_value, exc_tb = sys.exc_info() 366 traceback.print_exception(exc_type, exc_value, exc_tb) 367 368 # Restore old working directory. 369 if traceAlways: 370 print >> sys.stderr, "Restore dir to:", cls.oldcwd 371 os.chdir(cls.oldcwd) 372 373 def setUp(self): 374 #import traceback 375 #traceback.print_stack() 376 377 if ("LLDB_WAIT_BETWEEN_TEST_CASES" in os.environ and 378 os.environ["LLDB_WAIT_BETWEEN_TEST_CASES"] == 'YES'): 379 time.sleep(0.5) 380 381 if "LLDB_MAX_LAUNCH_COUNT" in os.environ: 382 self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"]) 383 384 if "LLDB_TIME_WAIT_NEXT_LAUNCH" in os.environ: 385 self.timeWait = float(os.environ["LLDB_TIME_WAIT_NEXT_LAUNCH"]) 386 387 # Create the debugger instance if necessary. 388 try: 389 self.dbg = lldb.DBG 390 except AttributeError: 391 self.dbg = lldb.SBDebugger.Create() 392 393 if not self.dbg.IsValid(): 394 raise Exception('Invalid debugger instance') 395 396 # We want our debugger to be synchronous. 397 self.dbg.SetAsync(False) 398 399 # There is no process associated with the debugger as yet. 400 # See also self.tearDown() where it checks whether self.process has a 401 # valid reference and calls self.process.Kill() to kill the process. 402 self.process = None 403 404 # Retrieve the associated command interpreter instance. 405 self.ci = self.dbg.GetCommandInterpreter() 406 if not self.ci: 407 raise Exception('Could not get the command interpreter') 408 409 # And the result object. 410 self.res = lldb.SBCommandReturnObject() 411 412 # These are for customized teardown cleanup. 413 self.dict = None 414 self.doTearDownCleanup = False 415 416 # Create a string buffer to record the session info, to be dumped into a 417 # test case specific file if test failure is encountered. 418 self.session = StringIO.StringIO() 419 420 # Optimistically set self.__errored__ and self.__failed__ to False 421 # initially. If the test errored/failed, the session info 422 # (self.session) is then dumped into a session specific file for 423 # diagnosis. 424 self.__errored__ = False 425 self.__failed__ = False 426 427 # See addTearDownHook(self, hook) which allows the client to add a hook 428 # function to be run during tearDown() time. 429 self.hooks = [] 430 431 def markError(self): 432 """Callback invoked when we (the test case instance) errored.""" 433 self.__errored__ = True 434 with recording(self, False) as sbuf: 435 # False because there's no need to write "ERROR" to the stderr twice. 436 # Once by the Python unittest framework, and a second time by us. 437 print >> sbuf, "ERROR" 438 439 def markFailure(self): 440 """Callback invoked when we (the test case instance) failed.""" 441 self.__failed__ = True 442 with recording(self, False) as sbuf: 443 # False because there's no need to write "FAIL" to the stderr twice. 444 # Once by the Python unittest framework, and a second time by us. 445 print >> sbuf, "FAIL" 446 447 def dumpSessionInfo(self): 448 """ 449 Dump the debugger interactions leading to a test error/failure. This 450 allows for more convenient postmortem analysis. 451 """ 452 for test, err in lldb.test_result.errors: 453 if test is self: 454 print >> self.session, err 455 for test, err in lldb.test_result.failures: 456 if test is self: 457 print >> self.session, err 458 459 dname = os.path.join(os.environ["LLDB_TEST"], 460 os.environ["LLDB_TIMESTAMP"]) 461 if not os.path.isdir(dname): 462 os.mkdir(dname) 463 fname = os.path.join(dname, "%s.log" % self.id()) 464 with open(fname, "w") as f: 465 print >> f, self.session.getvalue() 466 467 def setTearDownCleanup(self, dictionary=None): 468 """Register a cleanup action at tearDown() time with a dictinary""" 469 self.dict = dictionary 470 self.doTearDownCleanup = True 471 472 def addTearDownHook(self, hook): 473 """ 474 Add a function to be run during tearDown() time. 475 476 Hooks are executed in a first come first serve manner. 477 """ 478 if callable(hook): 479 with recording(self, traceAlways) as sbuf: 480 import inspect 481 print >> sbuf, "Adding tearDown hook:", inspect.getsource(hook) 482 self.hooks.append(hook) 483 484 def tearDown(self): 485 #import traceback 486 #traceback.print_stack() 487 488 # Check and run any hook functions. 489 for hook in self.hooks: 490 with recording(self, traceAlways) as sbuf: 491 import inspect 492 print >> sbuf, "Executing tearDown hook:", inspect.getsource(hook) 493 hook() 494 495 # Terminate the current process being debugged, if any. 496 if self.runStarted: 497 self.runCmd("process kill", PROCESS_KILLED, check=False) 498 elif self.process and self.process.IsValid(): 499 rc = self.invoke(self.process, "Kill") 500 self.assertTrue(rc.Success(), PROCESS_KILLED) 501 del self.process 502 503 del self.dbg 504 del self.hooks 505 506 # Perform registered teardown cleanup. 507 if doCleanup and self.doTearDownCleanup: 508 module = __import__(sys.platform) 509 if not module.cleanup(self, dictionary=self.dict): 510 raise Exception("Don't know how to do cleanup") 511 512 # See also LLDBTestResult (dotest.py) which is a singlton class derived 513 # from TextTestResult and overwrites addError()/addFailure() methods to 514 # allow us to to check the error/failure status here. 515 if self.__errored__ or self.__failed__: 516 self.dumpSessionInfo() 517 518 def runCmd(self, cmd, msg=None, check=True, trace=False, setCookie=True): 519 """ 520 Ask the command interpreter to handle the command and then check its 521 return status. 522 """ 523 # Fail fast if 'cmd' is not meaningful. 524 if not cmd or len(cmd) == 0: 525 raise Exception("Bad 'cmd' parameter encountered") 526 527 trace = (True if traceAlways else trace) 528 529 running = (cmd.startswith("run") or cmd.startswith("process launch")) 530 531 for i in range(self.maxLaunchCount if running else 1): 532 self.ci.HandleCommand(cmd, self.res) 533 534 with recording(self, trace) as sbuf: 535 print >> sbuf, "runCmd:", cmd 536 if not check: 537 print >> sbuf, "check of return status not required" 538 if self.res.Succeeded(): 539 print >> sbuf, "output:", self.res.GetOutput() 540 else: 541 print >> sbuf, "runCmd failed!" 542 print >> sbuf, self.res.GetError() 543 544 if running: 545 # For process launch, wait some time before possible next try. 546 time.sleep(self.timeWait) 547 548 if self.res.Succeeded(): 549 break 550 elif running: 551 with recording(self, True) as sbuf: 552 print >> sbuf, "Command '" + cmd + "' failed!" 553 554 # Modify runStarted only if "run" or "process launch" was encountered. 555 if running: 556 self.runStarted = running and setCookie 557 558 if check: 559 self.assertTrue(self.res.Succeeded(), 560 msg if msg else CMD_MSG(cmd, True)) 561 562 def expect(self, str, msg=None, patterns=None, startstr=None, substrs=None, trace=False, error=False, matching=True, exe=True): 563 """ 564 Similar to runCmd; with additional expect style output matching ability. 565 566 Ask the command interpreter to handle the command and then check its 567 return status. The 'msg' parameter specifies an informational assert 568 message. We expect the output from running the command to start with 569 'startstr', matches the substrings contained in 'substrs', and regexp 570 matches the patterns contained in 'patterns'. 571 572 If the keyword argument error is set to True, it signifies that the API 573 client is expecting the command to fail. In this case, the error stream 574 from running the command is retrieved and compared against the golden 575 input, instead. 576 577 If the keyword argument matching is set to False, it signifies that the API 578 client is expecting the output of the command not to match the golden 579 input. 580 581 Finally, the required argument 'str' represents the lldb command to be 582 sent to the command interpreter. In case the keyword argument 'exe' is 583 set to False, the 'str' is treated as a string to be matched/not-matched 584 against the golden input. 585 """ 586 trace = (True if traceAlways else trace) 587 588 if exe: 589 # First run the command. If we are expecting error, set check=False. 590 self.runCmd(str, trace = (True if trace else False), check = not error) 591 592 # Then compare the output against expected strings. 593 output = self.res.GetError() if error else self.res.GetOutput() 594 595 # If error is True, the API client expects the command to fail! 596 if error: 597 self.assertFalse(self.res.Succeeded(), 598 "Command '" + str + "' is expected to fail!") 599 else: 600 # No execution required, just compare str against the golden input. 601 output = str 602 with recording(self, trace) as sbuf: 603 print >> sbuf, "looking at:", output 604 605 # The heading says either "Expecting" or "Not expecting". 606 heading = "Expecting" if matching else "Not expecting" 607 608 # Start from the startstr, if specified. 609 # If there's no startstr, set the initial state appropriately. 610 matched = output.startswith(startstr) if startstr else (True if matching else False) 611 612 if startstr: 613 with recording(self, trace) as sbuf: 614 print >> sbuf, "%s start string: %s" % (heading, startstr) 615 print >> sbuf, "Matched" if matched else "Not matched" 616 617 # Look for sub strings, if specified. 618 keepgoing = matched if matching else not matched 619 if substrs and keepgoing: 620 for str in substrs: 621 matched = output.find(str) != -1 622 with recording(self, trace) as sbuf: 623 print >> sbuf, "%s sub string: %s" % (heading, str) 624 print >> sbuf, "Matched" if matched else "Not matched" 625 keepgoing = matched if matching else not matched 626 if not keepgoing: 627 break 628 629 # Search for regular expression patterns, if specified. 630 keepgoing = matched if matching else not matched 631 if patterns and keepgoing: 632 for pattern in patterns: 633 # Match Objects always have a boolean value of True. 634 matched = bool(re.search(pattern, output)) 635 with recording(self, trace) as sbuf: 636 print >> sbuf, "%s pattern: %s" % (heading, pattern) 637 print >> sbuf, "Matched" if matched else "Not matched" 638 keepgoing = matched if matching else not matched 639 if not keepgoing: 640 break 641 642 self.assertTrue(matched if matching else not matched, 643 msg if msg else CMD_MSG(str, exe)) 644 645 def invoke(self, obj, name, trace=False): 646 """Use reflection to call a method dynamically with no argument.""" 647 trace = (True if traceAlways else trace) 648 649 method = getattr(obj, name) 650 import inspect 651 self.assertTrue(inspect.ismethod(method), 652 name + "is a method name of object: " + str(obj)) 653 result = method() 654 with recording(self, trace) as sbuf: 655 print >> sbuf, str(method) + ":", result 656 return result 657 658 def breakAfterLaunch(self, process, func, trace=False): 659 """ 660 Perform some dancees after LaunchProcess() to break at func name. 661 662 Return True if we can successfully break at the func name in due time. 663 """ 664 trace = (True if traceAlways else trace) 665 666 count = 0 667 while True: 668 # The stop reason of the thread should be breakpoint. 669 thread = process.GetThreadAtIndex(0) 670 SR = thread.GetStopReason() 671 with recording(self, trace) as sbuf: 672 print >> sbuf, "StopReason =", StopReasonString(SR) 673 674 if SR == StopReasonEnum("Breakpoint"): 675 frame = thread.GetFrameAtIndex(0) 676 name = frame.GetFunction().GetName() 677 with recording(self, trace) as sbuf: 678 print >> sbuf, "function =", name 679 if (name == func): 680 # We got what we want; now break out of the loop. 681 return True 682 683 # The inferior is in a transient state; continue the process. 684 time.sleep(1.0) 685 with recording(self, trace) as sbuf: 686 print >> sbuf, "Continuing the process:", process 687 process.Continue() 688 689 count = count + 1 690 if count == 15: 691 with recording(self, trace) as sbuf: 692 print >> sbuf, "Reached 15 iterations, giving up..." 693 # Enough iterations already, break out of the loop. 694 return False 695 696 # End of while loop. 697 698 699 def buildDefault(self, architecture=None, compiler=None, dictionary=None): 700 """Platform specific way to build the default binaries.""" 701 module = __import__(sys.platform) 702 if not module.buildDefault(self, architecture, compiler, dictionary): 703 raise Exception("Don't know how to build default binary") 704 705 def buildDsym(self, architecture=None, compiler=None, dictionary=None): 706 """Platform specific way to build binaries with dsym info.""" 707 module = __import__(sys.platform) 708 if not module.buildDsym(self, architecture, compiler, dictionary): 709 raise Exception("Don't know how to build binary with dsym") 710 711 def buildDwarf(self, architecture=None, compiler=None, dictionary=None): 712 """Platform specific way to build binaries with dwarf maps.""" 713 module = __import__(sys.platform) 714 if not module.buildDwarf(self, architecture, compiler, dictionary): 715 raise Exception("Don't know how to build binary with dwarf") 716 717 def DebugSBValue(self, frame, val): 718 """Debug print a SBValue object, if traceAlways is True.""" 719 if not traceAlways: 720 return 721 722 err = sys.stderr 723 err.write(val.GetName() + ":\n") 724 err.write('\t' + "TypeName -> " + val.GetTypeName() + '\n') 725 err.write('\t' + "ByteSize -> " + str(val.GetByteSize()) + '\n') 726 err.write('\t' + "NumChildren -> " + str(val.GetNumChildren()) + '\n') 727 err.write('\t' + "Value -> " + str(val.GetValue(frame)) + '\n') 728 err.write('\t' + "Summary -> " + str(val.GetSummary(frame)) + '\n') 729 err.write('\t' + "IsPtrType -> " + str(val.TypeIsPtrType()) + '\n') 730 err.write('\t' + "Location -> " + val.GetLocation(frame) + '\n') 731 732