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,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)

View File

@ -0,0 +1,31 @@
#include <thread>
#include "lldb/API/LLDB.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBTarget.h"
using namespace lldb;
int main (int argc, char **argv)
{
// We are expecting the program path and a path to an executable to load
if (argc != 2)
return 1;
const char *program_file = argv[1];
SBDebugger::Initialize();
SBDebugger debugger = SBDebugger::Create(false);
auto lambda = [&](){
SBError error;
SBTarget target = debugger.CreateTarget(program_file, nullptr, nullptr,
false, error);
};
// Create 3 targets at the same time and make sure we don't crash.
std::thread thread1(lambda);
std::thread thread2(lambda);
std::thread thread3(lambda);
thread1.join();
thread2.join();
thread3.join();
SBDebugger::Terminate();
return 0;
}

View File

@ -0,0 +1,9 @@
LEVEL = ../../make
ENABLE_THREADS := YES
CXX_SOURCES := main.cpp
include $(LEVEL)/Makefile.rules
clean::
rm -rf $(wildcard *.o *.d *.dSYM)

View File

@ -0,0 +1,108 @@
"""Test the lldb public C++ api breakpoint callbacks."""
from __future__ import print_function
# __package__ = "lldbsuite.test"
import os
import re
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
import subprocess
class SBBreakpointCallbackCase(TestBase):
def setUp(self):
TestBase.setUp(self)
self.generateSource('driver.cpp')
self.generateSource('listener_test.cpp')
self.generateSource('test_breakpoint_callback.cpp')
self.generateSource('test_listener_event_description.cpp')
self.generateSource('test_listener_event_process_state.cpp')
self.generateSource('test_listener_resume.cpp')
mydir = TestBase.compute_mydir(__file__)
@skipIfRemote
@skipIfNoSBHeaders
# clang-cl does not support throw or catch (llvm.org/pr24538)
@skipIfWindows
def test_breakpoint_callback(self):
"""Test the that SBBreakpoint callback is invoked when a breakpoint is hit. """
self.build_and_test('driver.cpp test_breakpoint_callback.cpp',
'test_breakpoint_callback')
@skipIfRemote
@skipIfNoSBHeaders
# clang-cl does not support throw or catch (llvm.org/pr24538)
@skipIfWindows
@expectedFlakeyFreeBSD
def test_sb_api_listener_event_description(self):
""" Test the description of an SBListener breakpoint event is valid."""
self.build_and_test(
'driver.cpp listener_test.cpp test_listener_event_description.cpp',
'test_listener_event_description')
pass
@skipIfRemote
@skipIfNoSBHeaders
# clang-cl does not support throw or catch (llvm.org/pr24538)
@skipIfWindows
@expectedFlakeyFreeBSD
def test_sb_api_listener_event_process_state(self):
""" Test that a registered SBListener receives events when a process
changes state.
"""
self.build_and_test(
'driver.cpp listener_test.cpp test_listener_event_process_state.cpp',
'test_listener_event_process_state')
pass
@skipIfRemote
@skipIfNoSBHeaders
# clang-cl does not support throw or catch (llvm.org/pr24538)
@skipIfWindows
@expectedFlakeyFreeBSD
@expectedFailureAll(oslist=["linux"])
def test_sb_api_listener_resume(self):
""" Test that a process can be resumed from a non-main thread. """
self.build_and_test(
'driver.cpp listener_test.cpp test_listener_resume.cpp',
'test_listener_resume')
pass
def build_and_test(self, sources, test_name, args=None):
""" Build LLDB test from sources, and run expecting 0 exit code """
# These tests link against host lldb API.
# Compiler's target triple must match liblldb triple
# because remote is disabled, we can assume that the os is the same
# still need to check architecture
if self.getLldbArchitecture() != self.getArchitecture():
self.skipTest(
"This test is only run if the target arch is the same as the lldb binary arch")
self.inferior = 'inferior_program'
self.buildProgram('inferior.cpp', self.inferior)
self.addTearDownHook(lambda: os.remove(self.inferior))
self.buildDriver(sources, test_name)
self.addTearDownHook(lambda: os.remove(test_name))
test_exe = os.path.join(os.getcwd(), test_name)
self.signBinary(test_exe)
exe = [test_exe, self.inferior]
env = {self.dylibPath: self.getLLDBLibraryEnvVal()}
if self.TraceOn():
print("Running test %s" % " ".join(exe))
check_call(exe, env=env)
else:
with open(os.devnull, 'w') as fnull:
check_call(exe, env=env, stdout=fnull, stderr=fnull)
def build_program(self, sources, program):
return self.buildDriver(sources, program)

View File

@ -0,0 +1,68 @@
#ifndef LLDB_TEST_API_COMMON_H
#define LLDB_TEST_API_COMMON_H
#include <condition_variable>
#include <chrono>
#include <exception>
#include <iostream>
#include <mutex>
#include <string>
#include <queue>
#include <unistd.h>
/// Simple exception class with a message
struct Exception : public std::exception
{
std::string s;
Exception(std::string ss) : s(ss) {}
virtual ~Exception() throw () { }
const char* what() const throw() { return s.c_str(); }
};
// Synchronized data structure for listener to send events through
template<typename T>
class multithreaded_queue {
std::condition_variable m_condition;
std::mutex m_mutex;
std::queue<T> m_data;
bool m_notified;
public:
void push(T e) {
std::lock_guard<std::mutex> lock(m_mutex);
m_data.push(e);
m_notified = true;
m_condition.notify_all();
}
T pop(int timeout_seconds, bool &success) {
int count = 0;
while (count < timeout_seconds) {
std::unique_lock<std::mutex> lock(m_mutex);
if (!m_data.empty()) {
m_notified = false;
T ret = m_data.front();
m_data.pop();
success = true;
return ret;
} else if (!m_notified)
m_condition.wait_for(lock, std::chrono::seconds(1));
count ++;
}
success = false;
return T();
}
};
/// Allocates a char buffer with the current working directory
inline char* get_working_dir() {
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
return getwd(0);
#else
return get_current_dir_name();
#endif
}
#endif // LLDB_TEST_API_COMMON_H

View File

@ -0,0 +1,48 @@
/// LLDB C API Test Driver
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
#if !defined(_MSC_VER)
#include <signal.h>
#endif
%include_SB_APIs%
#include "common.h"
using namespace std;
using namespace lldb;
void test(SBDebugger &dbg, std::vector<string> args);
int main(int argc, char** argv) {
// Ignore SIGPIPE. The lldb driver does this as well,
// because we seem to get spurious SIGPIPES on some
// Unixen that take the driver down.
#if !defined(_MSC_VER)
signal(SIGPIPE, SIG_IGN);
#endif
int code = 0;
SBDebugger::Initialize();
SBDebugger dbg = SBDebugger::Create();
try {
if (!dbg.IsValid())
throw Exception("invalid debugger");
vector<string> args(argv + 1, argv + argc);
test(dbg, args);
} catch (Exception &e) {
cout << "ERROR: " << e.what() << endl;
code = 1;
}
SBDebugger::Destroy(dbg);
return code;
}

View File

@ -0,0 +1,17 @@
#include <iostream>
using namespace std;
int next() {
static int i = 0;
cout << "incrementing " << i << endl;
return ++i;
}
int main() {
int i = 0;
while (i < 5)
i = next();
return 0;
}

View File

@ -0,0 +1,74 @@
// LLDB test snippet that registers a listener with a process that hits
// a breakpoint.
#include <atomic>
#include <iostream>
#include <string>
#include <thread>
#include <vector>
%include_SB_APIs%
#include "common.h"
using namespace lldb;
using namespace std;
void listener_func();
void check_listener(SBDebugger &dbg);
// Listener thread and related variables
atomic<bool> g_done;
SBListener g_listener("test-listener");
thread g_listener_thread;
void shutdown_listener() {
g_done.store(true);
if (g_listener_thread.joinable())
g_listener_thread.join();
}
void test(SBDebugger &dbg, std::vector<string> args) {
try {
g_done.store(false);
SBTarget target = dbg.CreateTarget(args.at(0).c_str());
if (!target.IsValid()) throw Exception("invalid target");
SBBreakpoint breakpoint = target.BreakpointCreateByName("next");
if (!breakpoint.IsValid()) throw Exception("invalid breakpoint");
std::unique_ptr<char> working_dir(get_working_dir());
SBError error;
SBProcess process = target.Launch(g_listener,
0, 0, 0, 0, 0,
working_dir.get(),
0,
false,
error);
if (!error.Success())
throw Exception("Error launching process.");
/* FIXME: the approach below deadlocks
SBProcess process = target.LaunchSimple (0, 0, working_dir.get());
// get debugger listener (which is attached to process by default)
g_listener = dbg.GetListener();
*/
// FIXME: because a listener is attached to the process at launch-time,
// registering the listener below results in two listeners being attached,
// which is not supported by LLDB.
// register listener
// process.GetBroadcaster().AddListener(g_listener,
// SBProcess::eBroadcastBitStateChanged);
// start listener thread
g_listener_thread = thread(listener_func);
check_listener(dbg);
} catch (Exception &e) {
shutdown_listener();
throw e;
}
shutdown_listener();
}

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