Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@ -0,0 +1,33 @@
LLDB_LEVEL := ..
include $(LLDB_LEVEL)/Makefile
.PHONY: programs
all:: check-local
#----------------------------------------------------------------------
# Make all of the test programs
#----------------------------------------------------------------------
programs:
find . -type d -depth 1 | xargs -J % find % \
-name Makefile \
-exec echo \; \
-exec echo make -f '{}' \; \
-execdir make \;
#----------------------------------------------------------------------
# Clean all of the test programs
#----------------------------------------------------------------------
clean::
find . -type d -depth 1 | xargs -J % find % \
-name Makefile \
-exec echo \; \
-exec echo make -f '{}' clean \; \
-execdir make clean \;
#----------------------------------------------------------------------
# Run the tests
#----------------------------------------------------------------------
check-local::
rm -rf lldb-test-traces
python $(PROJ_SRC_DIR)/dotest.py --executable $(ToolDir)/lldb -q -s lldb-test-traces -u CXXFLAGS -u CFLAGS -C $(subst ccache,,$(CC))

View File

@ -0,0 +1,173 @@
This README file describes the files and directories related to the Python test
suite under the current 'test' directory.
o dotest.py
Provides the test driver for the test suite. To invoke it, cd to the 'test'
directory and issue the './dotest.py' command or './dotest.py -v' for more
verbose output. '.dotest.py -h' prints out the help messge.
A specific naming pattern is followed by the .py script under the 'test'
directory in order to be recognized by 'dotest.py' test driver as a module
which implements a test case, namely, Test*.py.
Some example usages:
1. ./dotest.py -v . 2> ~/Developer/Log/lldbtest.log0
This runs the test suite and directs the run log to a file.
2. LLDB_LOG=/tmp/lldb.log GDB_REMOTE_LOG=/tmp/gdb-remote.log ./dotest.py -v . 2> ~/Developer/Log/lldbtest.log
This runs the test suite, with logging turned on for the lldb as well as
the process.gdb-remote channels and directs the run log to a file.
o lldbtest.py
Provides an abstract base class of lldb test case named 'TestBase', which in
turn inherits from Python's unittest.TestCase. The concrete subclass can
override lldbtest.TestBase in order to inherit the common behavior for
unittest.TestCase.setUp/tearDown implemented in this file.
To provide a test case, the concrete subclass provides methods whose names
start with the letters test. For more details about the Python's unittest
framework, go to http://docs.python.org/library/unittest.html.
./command_source/TestCommandSource.py provides a simple example of test case
which overrides lldbtest.TestBase to exercise the lldb's 'command source'
command. The subclass should override the attribute 'mydir' in order for the
runtime to locate the individual test cases when running as part of a large
test suite or when running each test case as a separate Python invocation.
The doc string provides more details about the setup required for running a
test case on its own. To run the whole test suite, 'dotest.py' is all you
need to do.
o subdirectories of 'test'
Most of them predate the introduction of the python test suite and contain
example C/C++/ObjC source files which get compiled into executables which are
to be exercised by the debugger.
For such subdirectory which has an associated Test*.py file, it was added as
part of the Python-based test suite to test lldb functionality.
Some of the subdirectories, for example, the 'help' subdirectory, do not have
C/C++/ObjC source files; they were created to house the Python test case which
does not involve lldb reading in an executable file at all.
The sample_test directory contains examples of both a full and an "inline"
testcase that run a process to a breakpoint and check a local variable. These
are convenient starting points for adding new tests.
o make directory
Contains Makefile.rules, which can be utilized by test cases to write Makefile
based rules to build binaries for the inferiors.
By default, the built executable name is a.out, which can be overwritten by
specifying your EXE make variable, via the Makefile under the specific test
directory or via supplying a Python dictionary to the build method in your
Python test script. An example of the latter can be found in
test/lang/objc/radar-9691614/TestObjCMethodReturningBOOL.py, where:
def test_method_ret_BOOL_with_dsym(self):
"""Test that objective-c method returning BOOL works correctly."""
d = {'EXE': self.exe_name}
self.buildDsym(dictionary=d)
self.setTearDownCleanup(dictionary=d)
self.objc_method_ret_BOOL(self.exe_name)
def test_method_ret_BOOL_with_dwarf(self):
"""Test that objective-c method returning BOOL works correctly."""
d = {'EXE': self.exe_name}
self.buildDwarf(dictionary=d)
self.setTearDownCleanup(dictionary=d)
self.objc_method_ret_BOOL(self.exe_name)
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
# We'll use the test method name as the exe_name.
self.exe_name = self.testMethodName
# Find the line number to break inside main().
self.main_source = "main.m"
self.line = line_number(self.main_source, '// Set breakpoint here.')
The exe names for the two test methods are equal to the test method names and
are therefore guaranteed different.
o plugins directory
Contains platform specific plugin to build binaries with dsym/dwarf debugging
info. Other platform specific functionalities may be added in the future.
o unittest2 directory
Many new features were added to unittest in Python 2.7, including test
discovery. unittest2 allows you to use these features with earlier versions of
Python.
It currently has unittest2 0.5.1 from http://pypi.python.org/pypi/unittest2.
Version 0.5.1 of unittest2 has feature parity with unittest in Python 2.7
final. If you want to ensure that your tests run identically under unittest2
and unittest in Python 2.7 you should use unittest2 0.5.1.
Later versions of unittest2 include changes in unittest made in Python 3.2 and
onwards after the release of Python 2.7.
o dotest.pl
In case you wonder, there is also a 'dotest.pl' perl script file. It was
created to visit each Python test case under the specified directory and
invoke Python's builtin unittest.main() on each test case.
It does not take advantage of the test runner and test suite functionality
provided by Python's unitest framework. Its existence is because we want a
different way of running the whole test suite. As lldb and the Python test
suite become more reliable, we don't expect to be using 'dotest.pl' anymore.
Note: dotest.pl has been moved to the attic directory.
o Profiling dotest.py runs
I used the following command line thingy to do the profiling on a SnowLeopard
machine:
$ DOTEST_PROFILE=YES DOTEST_SCRIPT_DIR=/Volumes/data/lldb/svn/trunk/test /System/Library/Frameworks/Python.framework/Versions/Current/lib/python2.6/cProfile.py -o my.profile ./dotest.py -v -w 2> ~/Developer/Log/lldbtest.log
After that, I used the pstats.py module to browse the statistics:
$ python /System/Library/Frameworks/Python.framework/Versions/Current/lib/python2.6/pstats.py my.profile
o Writing test cases:
We strongly prefer writing test cases using the SB API's rather than the runCmd & expect.
Unless you are actually testing some feature of the command line, please don't write
command based tests. For historical reasons there are plenty of examples of tests in the
test suite that use runCmd where they shouldn't, but don't copy them, copy the plenty that
do use the SB API's instead.
The reason for this is that our policy is that we will maintain compatibility with the
SB API's. But we don't make any similar guarantee about the details of command result format.
If your test is using the command line, it is going to have to check against the command result
text, and you either end up writing your check pattern by checking as little as possible so
you won't be exposed to random changes in the text; in which case you can end up missing some
failure, or you test too much and it means irrelevant changes break your tests.
However, if you use the Python API's it is possible to check all the results you want
to check in a very explicit way, which makes the tests much more robust.
Even if you are testing that a command-line command does some specific thing, it is still
better in general to use the SB API's to drive to the point where you want to run the test,
then use SBInterpreter::HandleCommand to run the command. You get the full result text
from the command in the command return object, and all the part where you are driving the
debugger to the point you want to test will be more robust.
The sample_test directory contains a standard and an "inline" test that are good starting
points for writing a new test.
o Attaching in test cases:
If you need to attach to inferiors in your tests, you must make sure the inferior calls
lldb_enable_attach(), before the debugger attempts to attach. This function performs any
platform-specific processing needed to enable attaching to this process (e.g., on Linux, we
execute prctl(PR_SET_TRACER) syscall to disable protections present in some Linux systems).

View File

@ -0,0 +1,7 @@
# Module level initialization for the `lldbsuite.test` module.
from __future__ import absolute_import
from . import dotest
run_suite = dotest.run_suite

View File

@ -0,0 +1,4 @@
LEVEL = ../../make
CXX_SOURCES := main.cpp
include $(LEVEL)/Makefile.rules

View File

@ -0,0 +1,47 @@
"""
Verify the default cache line size for android targets
"""
from __future__ import print_function
import os
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
class DefaultCacheLineSizeTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
@skipUnlessPlatform(['android'])
def test_cache_line_size(self):
self.build(dictionary=self.getBuildFlags())
exe = os.path.join(os.getcwd(), "a.out")
target = self.dbg.CreateTarget(exe)
self.assertTrue(target and target.IsValid(), "Target is valid")
breakpoint = target.BreakpointCreateByName("main")
self.assertTrue(
breakpoint and breakpoint.IsValid(),
"Breakpoint is valid")
# Run the program.
process = target.LaunchSimple(
None, None, self.get_process_working_directory())
self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID)
self.assertEqual(
process.GetState(),
lldb.eStateStopped,
PROCESS_STOPPED)
# check the setting value
self.expect(
"settings show target.process.memory-cache-line-size",
patterns=[" = 2048"])
# Run to completion.
process.Continue()
self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED)

View File

@ -0,0 +1,13 @@
//===-- main.cpp ------------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
int main ()
{
return 0;
}

View File

@ -0,0 +1,5 @@
LEVEL = ../../make
CXX_SOURCES := main.cpp
include $(LEVEL)/Makefile.rules

View File

@ -0,0 +1,68 @@
"""Test the integrity of the lldb public api directory containing SB*.h headers.
There should be nothing unwanted there and a simpe main.cpp which includes SB*.h
should compile and link with the LLDB framework."""
from __future__ import print_function
import os
import re
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
class SBDirCheckerCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
def setUp(self):
TestBase.setUp(self)
self.source = 'main.cpp'
self.exe_name = 'a.out'
self.generateSource(self.source)
@skipIfNoSBHeaders
def test_sb_api_directory(self):
"""Test the SB API directory and make sure there's no unwanted stuff."""
# Only proceed if this is an Apple OS, "x86_64", and local platform.
if not (self.platformIsDarwin() and self.getArchitecture() == "x86_64"):
self.skipTest("This test is only for LLDB.framework built 64-bit")
if self.getArchitecture() == "i386":
self.skipTest(
"LLDB is 64-bit and cannot be linked to 32-bit test program.")
self.buildDriver(self.source, self.exe_name)
self.sanity_check_executable(self.exe_name)
def sanity_check_executable(self, exe_name):
"""Sanity check executable compiled from the auto-generated program."""
exe = os.path.join(os.getcwd(), exe_name)
self.runCmd("file %s" % exe, CURRENT_EXECUTABLE_SET)
self.line_to_break = line_number(
self.source, '// Set breakpoint here.')
env_cmd = "settings set target.env-vars %s=%s" % (
self.dylibPath, self.getLLDBLibraryEnvVal())
if self.TraceOn():
print("Set environment to: ", env_cmd)
self.runCmd(env_cmd)
self.addTearDownHook(
lambda: self.dbg.HandleCommand(
"settings remove target.env-vars %s" %
self.dylibPath))
lldbutil.run_break_set_by_file_and_line(
self, self.source, self.line_to_break, num_expected_locations=-1)
self.runCmd("run", RUN_SUCCEEDED)
# The stop reason of the thread should be breakpoint.
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
substrs=['stopped',
'stop reason = breakpoint'])
self.runCmd('frame variable')

View File

@ -0,0 +1,24 @@
//===-- main.cpp ------------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <stdio.h>
%include_SB_APIs%
using namespace lldb;
int
main(int argc, char const *argv[])
{
SBDebugger::Initialize();
SBDebugger dbg = SBDebugger::Create();
printf("Hello SBDebugger %llu\n", dbg.GetID()); // Set breakpoint here.
SBDebugger::Terminate();
return 0;
}

View File

@ -0,0 +1,6 @@
LEVEL = ../../make
C_SOURCES := main.c
include $(LEVEL)/Makefile.rules

View File

@ -0,0 +1,71 @@
"""
Test that we can listen to modules loaded events.
"""
from __future__ import print_function
import copy
import os
import time
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
import six
class ListenToModuleLoadedEvents (TestBase):
mydir = TestBase.compute_mydir(__file__)
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
self.build()
def test_receiving_breakpoint_added(self):
"""Test that we get breakpoint added events, waiting on event classes on the debugger"""
my_listener = lldb.SBListener("test_listener")
my_listener.StartListeningForEventClass(
self.dbg,
lldb.SBTarget.GetBroadcasterClassName(),
lldb.SBTarget.eBroadcastBitBreakpointChanged)
exe = os.path.join(os.getcwd(), "a.out")
target = self.dbg.CreateTarget(exe)
bkpt = target.BreakpointCreateByName("main")
event = lldb.SBEvent()
my_listener.WaitForEvent(1, event)
self.assertTrue(event.IsValid(), "Got a valid event.")
self.assertTrue(
lldb.SBBreakpoint.EventIsBreakpointEvent(event),
"It is a breakpoint event.")
self.assertTrue(lldb.SBBreakpoint.GetBreakpointEventTypeFromEvent(
event) == lldb.eBreakpointEventTypeAdded, "It is a breakpoint added event.")
self.assertTrue(
bkpt == lldb.SBBreakpoint.GetBreakpointFromEvent(event),
"It is our breakpoint.")
# Now make sure if we stop listening for events we don't get them:
my_listener.StopListeningForEventClass(
self.dbg,
lldb.SBTarget.GetBroadcasterClassName(),
lldb.SBTarget.eBroadcastBitBreakpointChanged)
my_listener.StopListeningForEvents(
target.GetBroadcaster(),
lldb.SBTarget.eBroadcastBitBreakpointChanged)
bkpt2 = target.BreakpointCreateByName("main")
my_listener.WaitForEvent(1, event)
self.assertTrue(
not event.IsValid(),
"We don't get events we aren't listening to.")

View File

@ -0,0 +1,7 @@
#include <stdio.h>
int
main()
{
printf ("Hello there.\n");
}

View File

@ -0,0 +1,8 @@
LEVEL = ../../make
MAKE_DSYM := NO
ENABLE_THREADS := YES
CXX_SOURCES := multi-process-driver.cpp testprog.cpp
include $(LEVEL)/Makefile.rules

View File

@ -0,0 +1,54 @@
"""Test the lldb public C++ api when doing multiple debug sessions simultaneously."""
from __future__ import print_function
import os
import re
import subprocess
import sys
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
class TestMultipleSimultaneousDebuggers(TestBase):
mydir = TestBase.compute_mydir(__file__)
@skipIfNoSBHeaders
@expectedFailureAll(bugnumber="rdar://30564102")
@expectedFailureAll(
archs="i[3-6]86",
bugnumber="multi-process-driver.cpp creates an x64 target")
@expectedFailureAll(
oslist=[
"windows",
"linux",
"freebsd"],
bugnumber="llvm.org/pr20282")
def test_multiple_debuggers(self):
env = {self.dylibPath: self.getLLDBLibraryEnvVal()}
self.driver_exe = os.path.join(os.getcwd(), "multi-process-driver")
self.buildDriver('multi-process-driver.cpp', self.driver_exe)
self.addTearDownHook(lambda: os.remove(self.driver_exe))
self.signBinary(self.driver_exe)
self.inferior_exe = os.path.join(os.getcwd(), "testprog")
self.buildDriver('testprog.cpp', self.inferior_exe)
self.addTearDownHook(lambda: os.remove(self.inferior_exe))
# check_call will raise a CalledProcessError if multi-process-driver doesn't return
# exit code 0 to indicate success. We can let this exception go - the test harness
# will recognize it as a test failure.
if self.TraceOn():
print("Running test %s" % self.driver_exe)
check_call([self.driver_exe, self.inferior_exe], env=env)
else:
with open(os.devnull, 'w') as fnull:
check_call([self.driver_exe, self.inferior_exe],
env=env, stdout=fnull, stderr=fnull)

View File

@ -0,0 +1,287 @@
// This program creates NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS of pthreads,
// creates an lldb Debugger on each thread, creates targets, inserts two
// breakpoints, runs to the first breakpoint, backtraces, runs to the second
// breakpoint, backtraces, kills the inferior process, closes down the
// debugger.
// The main thread keeps track of which pthreads have completed and which
// pthreads have completed successfully, and exits when all pthreads have
// completed successfully, or our time limit has been exceeded.
// This test file helps to uncover race conditions and locking mistakes
// that are hit when lldb is being used to debug multiple processes
// simultaneously.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lldb/API/LLDB.h"
#include "lldb/API/SBCommandInterpreter.h"
#include "lldb/API/SBCommandReturnObject.h"
#include "lldb/API/SBDebugger.h"
#include <chrono>
#include <thread>
#define NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS 10
#define DEBUG 0
using namespace lldb;
bool *completed_threads_array = 0;
bool *successful_threads_array = 0;
const char *inferior_process_name = "testprog";
bool
wait_for_stop_event (SBProcess process, SBListener listener)
{
bool stopped = false;
while (!stopped)
{
SBEvent event;
bool waitfor_ret = listener.WaitForEvent (2, event);
if (event.GetType() == SBProcess::eBroadcastBitStateChanged)
{
if (process.GetState() == StateType::eStateStopped
|| process.GetState() == StateType::eStateCrashed
|| process.GetState() == StateType::eStateDetached
|| process.GetState() == StateType::eStateExited)
{
stopped = true;
}
}
}
return stopped;
}
bool
walk_stack_to_main (SBThread thread)
{
if (thread.IsValid() == 0)
{
return false;
}
bool found_main = false;
uint32_t curr_frame = 0;
const uint32_t framecount = thread.GetNumFrames();
while (!found_main && curr_frame < framecount)
{
SBFrame frame = thread.GetFrameAtIndex (curr_frame);
if (strcmp (frame.GetFunctionName(), "main") == 0)
{
found_main = true;
break;
}
curr_frame += 1;
}
return found_main;
}
void *do_one_debugger (void *in)
{
uint64_t threadnum = (uint64_t) in;
#if defined (__APPLE__)
char *threadname;
asprintf (&threadname, "thread #%lld", threadnum);
pthread_setname_np (threadname);
free (threadname);
#endif
#if DEBUG == 1
printf ("#%lld: Starting debug session\n", threadnum);
#endif
SBDebugger debugger = lldb::SBDebugger::Create (false);
if (debugger.IsValid ())
{
debugger.SetAsync (true);
SBTarget target = debugger.CreateTargetWithFileAndArch(inferior_process_name, "x86_64");
SBCommandInterpreter command_interp = debugger.GetCommandInterpreter();
if (target.IsValid())
{
SBBreakpoint bar_br = target.BreakpointCreateByName ("bar", "testprog");
if (!bar_br.IsValid())
{
printf ("#%lld: failed to set breakpoint on bar, exiting.\n", threadnum);
exit (1);
}
SBBreakpoint foo_br = target.BreakpointCreateByName ("foo", "testprog");
if (!foo_br.IsValid())
{
printf ("#%lld: Failed to set breakpoint on foo()\n", threadnum);
}
SBLaunchInfo launch_info (NULL);
SBError error;
SBProcess process = target.Launch (launch_info, error);
if (process.IsValid())
{
SBListener listener = debugger.GetListener();
SBBroadcaster broadcaster = process.GetBroadcaster();
uint32_t rc = broadcaster.AddListener (listener, SBProcess::eBroadcastBitStateChanged);
if (rc == 0)
{
printf ("adding listener failed\n");
exit (1);
}
wait_for_stop_event (process, listener);
if (!walk_stack_to_main (process.GetThreadAtIndex(0)))
{
printf ("#%lld: backtrace while @ foo() failed\n", threadnum);
completed_threads_array[threadnum] = true;
return (void *) 1;
}
if (strcmp (process.GetThreadAtIndex(0).GetFrameAtIndex(0).GetFunctionName(), "foo") != 0)
{
#if DEBUG == 1
printf ("#%lld: First breakpoint did not stop at foo(), instead stopped at '%s'\n", threadnum, process.GetThreadAtIndex(0).GetFrameAtIndex(0).GetFunctionName());
#endif
completed_threads_array[threadnum] = true;
return (void*) 1;
}
process.Continue();
wait_for_stop_event (process, listener);
if (process.GetState() == StateType::eStateExited)
{
printf ("#%lld: Process exited\n", threadnum);
completed_threads_array[threadnum] = true;
return (void *) 1;
}
if (!walk_stack_to_main (process.GetThreadAtIndex(0)))
{
printf ("#%lld: backtrace while @ bar() failed\n", threadnum);
completed_threads_array[threadnum] = true;
return (void *) 1;
}
if (strcmp (process.GetThreadAtIndex(0).GetFrameAtIndex(0).GetFunctionName(), "bar") != 0)
{
printf ("#%lld: First breakpoint did not stop at bar()\n", threadnum);
completed_threads_array[threadnum] = true;
return (void*) 1;
}
process.Kill();
wait_for_stop_event (process, listener);
SBDebugger::Destroy(debugger);
#if DEBUG == 1
printf ("#%lld: All good!\n", threadnum);
#endif
successful_threads_array[threadnum] = true;
completed_threads_array[threadnum] = true;
return (void*) 0;
}
else
{
printf("#%lld: process failed to launch\n", threadnum);
successful_threads_array[threadnum] = false;
completed_threads_array[threadnum] = true;
return (void*) 0;
}
}
else
{
printf ("#%lld: did not get valid target\n", threadnum);
successful_threads_array[threadnum] = false;
completed_threads_array[threadnum] = true;
return (void*) 0;
}
}
else
{
printf ("#%lld: did not get debugger\n", threadnum);
successful_threads_array[threadnum] = false;
completed_threads_array[threadnum] = true;
return (void*) 0;
}
completed_threads_array[threadnum] = true;
return (void*) 1;
}
int main (int argc, char **argv)
{
#if !defined(_MSC_VER)
signal(SIGPIPE, SIG_IGN);
#endif
SBDebugger::Initialize();
completed_threads_array = (bool *) malloc (sizeof (bool) * NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
memset (completed_threads_array, 0, sizeof (bool) * NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
successful_threads_array = (bool *) malloc (sizeof (bool) * NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
memset (successful_threads_array, 0, sizeof (bool) * NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
if (argc > 1 && argv[1] != NULL)
{
inferior_process_name = argv[1];
}
std::thread threads[NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS];
for (uint64_t i = 0; i< NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS; i++)
{
threads[i] = std::move(std::thread(do_one_debugger, (void*)i));
}
int max_time_to_wait = 20; // 20 iterations, or 60 seconds
int iter = 0;
while (1)
{
std::this_thread::sleep_for(std::chrono::seconds(3));
bool all_done = true;
int successful_threads = 0;
int total_completed_threads = 0;
for (uint64_t i = 0; i < NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS; i++)
{
if (successful_threads_array[i] == true)
successful_threads++;
if (completed_threads_array[i] == true)
total_completed_threads++;
if (completed_threads_array[i] == false)
{
all_done = false;
}
}
if (all_done)
{
#if DEBUG == 1
printf ("All threads completed.\n");
printf ("%d threads completed successfully out of %d\n", successful_threads, NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
#endif
SBDebugger::Terminate();
exit(0);
}
else
{
#if DEBUG == 1
printf ("%d threads completed so far (%d successfully), out of %d\n", total_completed_threads, successful_threads, NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
#endif
}
if (iter++ == max_time_to_wait)
{
printf ("reached maximum timeout but only %d threads have completed so far (%d successfully), out of %d. Exiting.\n", total_completed_threads, successful_threads, NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
break;
}
}
SBDebugger::Terminate();
exit (1);
}

View File

@ -0,0 +1,12 @@
int bar ()
{
return 5;
}
int foo ()
{
return bar() + 5;
}
int main ()
{
return foo();
}

View File

@ -0,0 +1,8 @@
LEVEL = ../../make
MAKE_DSYM := NO
ENABLE_THREADS := YES
CXX_SOURCES := main.cpp
include $(LEVEL)/Makefile.rules

View File

@ -0,0 +1,44 @@
"""Test the lldb public C++ api when creating multiple targets simultaneously."""
from __future__ import print_function
import os
import re
import subprocess
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
class TestMultipleTargets(TestBase):
mydir = TestBase.compute_mydir(__file__)
NO_DEBUG_INFO_TESTCASE = True
@skipIfNoSBHeaders
@skipIfHostIncompatibleWithRemote
@expectedFailureAll(
oslist=["windows", "freebsd"],
bugnumber="llvm.org/pr20282")
def test_multiple_targets(self):
env = {self.dylibPath: self.getLLDBLibraryEnvVal()}
self.driver_exe = os.path.join(os.getcwd(), "multi-target")
self.buildDriver('main.cpp', self.driver_exe)
self.addTearDownHook(lambda: os.remove(self.driver_exe))
self.signBinary(self.driver_exe)
# check_call will raise a CalledProcessError if multi-process-driver doesn't return
# exit code 0 to indicate success. We can let this exception go - the test harness
# will recognize it as a test failure.
if self.TraceOn():
print("Running test %s" % self.driver_exe)
check_call([self.driver_exe, self.driver_exe], env=env)
else:
with open(os.devnull, 'w') as fnull:
check_call([self.driver_exe, self.driver_exe],
env=env, stdout=fnull, stderr=fnull)

Some files were not shown because too many files have changed in this diff Show More