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,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();
}

View File

@ -0,0 +1,49 @@
// LLDB C++ API Test: verify that the function registered with
// SBBreakpoint.SetCallback() is invoked when a breakpoint is hit.
#include <mutex>
#include <iostream>
#include <vector>
#include <string>
%include_SB_APIs%
#include "common.h"
using namespace std;
using namespace lldb;
mutex g_mutex;
condition_variable g_condition;
int g_breakpoint_hit_count = 0;
bool BPCallback (void *baton,
SBProcess &process,
SBThread &thread,
SBBreakpointLocation &location) {
lock_guard<mutex> lock(g_mutex);
g_breakpoint_hit_count += 1;
g_condition.notify_all();
return true;
}
void test(SBDebugger &dbg, vector<string> args) {
dbg.SetAsync(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");
breakpoint.SetCallback(BPCallback, 0);
std::unique_ptr<char> working_dir(get_working_dir());
SBProcess process = target.LaunchSimple (0, 0, working_dir.get());
{
unique_lock<mutex> lock(g_mutex);
g_condition.wait_for(lock, chrono::seconds(5));
if (g_breakpoint_hit_count != 1)
throw Exception("Breakpoint hit count expected to be 1");
}
}

View File

@ -0,0 +1,97 @@
// LLDB C++ API Test: verify the event description that is received by an
// SBListener object registered with a process with a breakpoint.
#include <atomic>
#include <array>
#include <iostream>
#include <string>
#include <thread>
%include_SB_APIs%
#include "common.h"
using namespace lldb;
using namespace std;
// listener thread control
extern atomic<bool> g_done;
extern SBListener g_listener;
multithreaded_queue<string> g_event_descriptions;
string g_error_desc;
void listener_func() {
while (!g_done) {
SBEvent event;
bool got_event = g_listener.WaitForEvent(1, event);
if (got_event) {
if (!event.IsValid())
throw Exception("event is not valid in listener thread");
SBStream description;
event.GetDescription(description);
string str(description.GetData());
g_event_descriptions.push(str);
}
}
}
bool check_state(string &state, string &desc, bool got_description)
{
g_error_desc.clear();
if(!got_description)
{
g_error_desc.append("Did not get expected event description");
return false;
}
if (desc.find("state-changed") == desc.npos)
g_error_desc.append("Event description incorrect: missing 'state-changed' ");
if (desc.find("pid = ") == desc.npos)
g_error_desc.append("Event description incorrect: missing process pid ");
string state_search_str = "state = " + state;
if (desc.find(state_search_str) == desc.npos)
{
string errString = ("Event description incorrect: expected state "
+ state
+ " but desc was "
+ desc);
g_error_desc.append(errString);
}
if (g_error_desc.length() > 0)
return false;
cout << "check_state: " << state << " OK\n";
return true;
}
void check_listener(SBDebugger &dbg)
{
bool got_description;
string state;
// check for "launching" state, this may or may not be present
string desc = g_event_descriptions.pop(5, got_description);
state = "launching";
if (check_state(state, desc, got_description))
{
// found a 'launching' state, pop next one from queue
desc = g_event_descriptions.pop(5, got_description);
}
state = "running";
if( !check_state(state, desc, got_description) )
throw Exception(g_error_desc);
desc = g_event_descriptions.pop(5, got_description);
state = "stopped";
if( !check_state(state, desc, got_description) )
throw Exception(g_error_desc);
}

View File

@ -0,0 +1,63 @@
// LLDB C++ API Test: verify the event description as obtained by calling
// SBEvent::GetCStringFromEvent that is received by an
// SBListener object registered with a process with a breakpoint.
#include <atomic>
#include <iostream>
#include <string>
#include <thread>
%include_SB_APIs%
#include "common.h"
using namespace lldb;
using namespace std;
// listener thread control
extern atomic<bool> g_done;
multithreaded_queue<string> g_frame_functions;
extern SBListener g_listener;
void listener_func() {
while (!g_done) {
SBEvent event;
bool got_event = g_listener.WaitForEvent(1, event);
if (got_event) {
if (!event.IsValid())
throw Exception("event is not valid in listener thread");
// send process description
SBProcess process = SBProcess::GetProcessFromEvent(event);
if (!process.IsValid())
throw Exception("process is not valid");
if (SBProcess::GetStateFromEvent(event) != lldb::eStateStopped || SBProcess::GetRestartedFromEvent(event))
continue; // Only interested in "stopped" events.
SBStream description;
for (int i = 0; i < process.GetNumThreads(); ++i) {
// send each thread description
SBThread thread = process.GetThreadAtIndex(i);
// send each frame function name
uint32_t num_frames = thread.GetNumFrames();
for(int j = 0; j < num_frames; ++j) {
const char* function_name = thread.GetFrameAtIndex(j).GetSymbol().GetName();
if (function_name)
g_frame_functions.push(string(function_name));
}
}
}
}
}
void check_listener(SBDebugger &dbg) {
// check thread description
bool got_description = false;
string func_name = g_frame_functions.pop(5, got_description);
if(got_description == false)
throw Exception("Expected at least one frame function");
}

View File

@ -0,0 +1,53 @@
// LLDB C++ API Test: verify the event description as obtained by calling
// SBEvent::GetCStringFromEvent that is received by an
// SBListener object registered with a process with a breakpoint.
#include <atomic>
#include <iostream>
#include <string>
#include <thread>
%include_SB_APIs%
#include "common.h"
using namespace lldb;
using namespace std;
// listener thread control
extern atomic<bool> g_done;
// used by listener thread to communicate a successful process continue command
// back to the checking thread.
multithreaded_queue<bool> g_process_started;
extern SBListener g_listener;
void listener_func() {
while (!g_done) {
SBEvent event;
bool got_event = g_listener.WaitForEvent(1, event);
if (got_event) {
if (!event.IsValid())
throw Exception("event is not valid in listener thread");
SBProcess process = SBProcess::GetProcessFromEvent(event);
if (process.GetState() == eStateStopped) {
SBError error = process.Continue();
if (!error.Success())
throw Exception(string("Cannot continue process from listener thread: ")
+ error.GetCString());
g_process_started.push(true);
}
}
}
}
void check_listener(SBDebugger &dbg) {
bool got_message = false;
while (!got_message)
g_process_started.pop(5, got_message);
g_done = true;
}