Browse Source

Debug cleanup

merge-requests/365/head
eidheim 10 years ago
parent
commit
3467c152c3
  1. 2
      README.md
  2. 2
      src/CMakeLists.txt
  3. 14
      src/config.cc
  4. 1
      src/config.h
  5. 91
      src/debug_lldb.cc
  6. 12
      src/debug_lldb.h
  7. 94
      src/project.cc
  8. 27
      src/project.h
  9. 8
      src/source_clang.cc
  10. 8
      src/window.cc
  11. 26
      tests/lldb_test.cc
  12. 19
      tests/stubs/config.cc

2
README.md

@ -13,7 +13,7 @@ towards libclang with speed and ease of use in mind.
* Syntax highlighting for more than 100 different file types * Syntax highlighting for more than 100 different file types
* C++ warnings and errors on the fly * C++ warnings and errors on the fly
* C++ Fix-its * C++ Fix-its
* Debug integration through lldb * Debug integration, both local and remote, through lldb
* Automated CMake processing, including support for external libraries * Automated CMake processing, including support for external libraries
* Fast C++ autocompletion * Fast C++ autocompletion
* Keyword and buffer autocompletion for other file types * Keyword and buffer autocompletion for other file types

2
src/CMakeLists.txt

@ -79,7 +79,7 @@ set(project_shared_files
) )
if(LIBLLDB_FOUND) if(LIBLLDB_FOUND)
list(APPEND project_shared_files debug_clang.cc) list(APPEND project_shared_files debug_lldb.cc)
endif() endif()
if(MSYS) if(MSYS)

14
src/config.cc

@ -99,7 +99,6 @@ void Config::retrieve_config() {
terminal.font=cfg.get<std::string>("terminal.font"); terminal.font=cfg.get<std::string>("terminal.font");
terminal.clang_format_command="clang-format"; terminal.clang_format_command="clang-format";
terminal.lldb_command="lldb";
#ifdef __linux #ifdef __linux
if(terminal.clang_format_command=="clang-format" && if(terminal.clang_format_command=="clang-format" &&
!boost::filesystem::exists("/usr/bin/clang-format") && !boost::filesystem::exists("/usr/local/bin/clang-format")) { !boost::filesystem::exists("/usr/bin/clang-format") && !boost::filesystem::exists("/usr/local/bin/clang-format")) {
@ -114,19 +113,6 @@ void Config::retrieve_config() {
else if(boost::filesystem::exists("/usr/bin/clang-format-3.5")) else if(boost::filesystem::exists("/usr/bin/clang-format-3.5"))
terminal.clang_format_command="/usr/bin/clang-format-3.5"; terminal.clang_format_command="/usr/bin/clang-format-3.5";
} }
if(terminal.lldb_command=="lldb" &&
!boost::filesystem::exists("/usr/bin/lldb") && !boost::filesystem::exists("/usr/local/bin/lldb")) {
if(boost::filesystem::exists("/usr/bin/lldb-3.9"))
terminal.lldb_command="/usr/bin/lldb-3.9";
else if(boost::filesystem::exists("/usr/bin/lldb-3.8"))
terminal.lldb_command="/usr/bin/lldb-3.8";
else if(boost::filesystem::exists("/usr/bin/lldb-3.7"))
terminal.lldb_command="/usr/bin/lldb-3.7";
else if(boost::filesystem::exists("/usr/bin/lldb-3.6"))
terminal.lldb_command="/usr/bin/lldb-3.6";
else if(boost::filesystem::exists("/usr/bin/lldb-3.5"))
terminal.lldb_command="/usr/bin/lldb-3.5";
}
#endif #endif
} }

1
src/config.h

@ -25,7 +25,6 @@ public:
class Terminal { class Terminal {
public: public:
std::string clang_format_command; std::string clang_format_command;
std::string lldb_command;
int history_size; int history_size;
std::string font; std::string font;

91
src/debug_clang.cc → src/debug_lldb.cc

@ -1,4 +1,4 @@
#include "debug_clang.h" #include "debug_lldb.h"
#include <stdio.h> #include <stdio.h>
#ifdef __APPLE__ #ifdef __APPLE__
#include <stdlib.h> #include <stdlib.h>
@ -29,7 +29,7 @@ void log(const char *msg, void *) {
std::cout << "debugger log: " << msg << std::endl; std::cout << "debugger log: " << msg << std::endl;
} }
Debug::Clang::Clang(): state(lldb::StateType::eStateInvalid), buffer_size(131072) { Debug::LLDB::LLDB(): state(lldb::StateType::eStateInvalid), buffer_size(131072) {
#ifdef __APPLE__ #ifdef __APPLE__
auto debugserver_path=boost::filesystem::path("/usr/local/opt/llvm/bin/debugserver"); auto debugserver_path=boost::filesystem::path("/usr/local/opt/llvm/bin/debugserver");
if(boost::filesystem::exists(debugserver_path)) if(boost::filesystem::exists(debugserver_path))
@ -37,12 +37,12 @@ Debug::Clang::Clang(): state(lldb::StateType::eStateInvalid), buffer_size(131072
#endif #endif
} }
void Debug::Clang::start(const std::string &command, const boost::filesystem::path &path, void Debug::LLDB::start(const std::string &command, const boost::filesystem::path &path,
const std::vector<std::pair<boost::filesystem::path, int> > &breakpoints, const std::vector<std::pair<boost::filesystem::path, int> > &breakpoints,
std::function<void(int exit_status)> callback, std::function<void(int exit_status)> callback,
std::function<void(const std::string &status)> status_callback, std::function<void(const std::string &status)> status_callback,
std::function<void(const boost::filesystem::path &file_path, int line_nr, int line_index)> stop_callback, std::function<void(const boost::filesystem::path &file_path, int line_nr, int line_index)> stop_callback,
const std::string &plugin, const std::string &url) { const std::string &remote_host) {
if(!debugger) { if(!debugger) {
lldb::SBDebugger::Initialize(); lldb::SBDebugger::Initialize();
debugger=std::unique_ptr<lldb::SBDebugger>(new lldb::SBDebugger(lldb::SBDebugger::Create(true, log, nullptr))); debugger=std::unique_ptr<lldb::SBDebugger>(new lldb::SBDebugger(lldb::SBDebugger::Create(true, log, nullptr)));
@ -101,10 +101,9 @@ void Debug::Clang::start(const std::string &command, const boost::filesystem::pa
} }
lldb::SBError error; lldb::SBError error;
if(!plugin.empty() && plugin!="host") { if(!remote_host.empty()) {
//TODO: support other plugins as well auto connect_string="connect://"+remote_host;
//Plugin names for SBTarget::ConnectRemote does not seem to correspond to the ones from running "platform list" in lldb process = std::unique_ptr<lldb::SBProcess>(new lldb::SBProcess(target.ConnectRemote(*listener, connect_string.c_str(), "gdb-remote", error)));
process = std::unique_ptr<lldb::SBProcess>(new lldb::SBProcess(target.ConnectRemote(*listener, url.c_str(), "gdb-remote", error)));
if(error.Fail()) { if(error.Fail()) {
Terminal::get().async_print(std::string("Error (debug): ")+error.GetCString()+'\n', true); Terminal::get().async_print(std::string("Error (debug): ")+error.GetCString()+'\n', true);
if(callback) if(callback)
@ -124,7 +123,7 @@ void Debug::Clang::start(const std::string &command, const boost::filesystem::pa
} }
const char *empty_parameter[1]; const char *empty_parameter[1];
empty_parameter[0]=nullptr; empty_parameter[0]=nullptr;
process->RemoteLaunch(empty_parameter, empty_parameter, nullptr, nullptr, nullptr, nullptr, lldb::eLaunchFlagNone, false, error); process->RemoteLaunch(argv, empty_parameter, nullptr, nullptr, nullptr, nullptr, lldb::eLaunchFlagNone, false, error);
if(!error.Fail()) if(!error.Fail())
process->Continue(); process->Continue();
} }
@ -243,13 +242,13 @@ void Debug::Clang::start(const std::string &command, const boost::filesystem::pa
}); });
} }
void Debug::Clang::continue_debug() { void Debug::LLDB::continue_debug() {
std::unique_lock<std::mutex> lock(event_mutex); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped) if(state==lldb::StateType::eStateStopped)
process->Continue(); process->Continue();
} }
void Debug::Clang::stop() { void Debug::LLDB::stop() {
std::unique_lock<std::mutex> lock(event_mutex); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateRunning) { if(state==lldb::StateType::eStateRunning) {
auto error=process->Stop(); auto error=process->Stop();
@ -258,7 +257,7 @@ void Debug::Clang::stop() {
} }
} }
void Debug::Clang::kill() { void Debug::LLDB::kill() {
std::unique_lock<std::mutex> lock(event_mutex); std::unique_lock<std::mutex> lock(event_mutex);
if(process) { if(process) {
auto error=process->Kill(); auto error=process->Kill();
@ -267,28 +266,28 @@ void Debug::Clang::kill() {
} }
} }
void Debug::Clang::step_over() { void Debug::LLDB::step_over() {
std::unique_lock<std::mutex> lock(event_mutex); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped) { if(state==lldb::StateType::eStateStopped) {
process->GetSelectedThread().StepOver(); process->GetSelectedThread().StepOver();
} }
} }
void Debug::Clang::step_into() { void Debug::LLDB::step_into() {
std::unique_lock<std::mutex> lock(event_mutex); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped) { if(state==lldb::StateType::eStateStopped) {
process->GetSelectedThread().StepInto(); process->GetSelectedThread().StepInto();
} }
} }
void Debug::Clang::step_out() { void Debug::LLDB::step_out() {
std::unique_lock<std::mutex> lock(event_mutex); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped) { if(state==lldb::StateType::eStateStopped) {
process->GetSelectedThread().StepOut(); process->GetSelectedThread().StepOut();
} }
} }
std::pair<std::string, std::string> Debug::Clang::run_command(const std::string &command) { std::pair<std::string, std::string> Debug::LLDB::run_command(const std::string &command) {
std::pair<std::string, std::string> command_return; std::pair<std::string, std::string> command_return;
std::unique_lock<std::mutex> lock(event_mutex); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped || state==lldb::StateType::eStateRunning) { if(state==lldb::StateType::eStateStopped || state==lldb::StateType::eStateRunning) {
@ -300,7 +299,7 @@ std::pair<std::string, std::string> Debug::Clang::run_command(const std::string
return command_return; return command_return;
} }
std::vector<Debug::Clang::Frame> Debug::Clang::get_backtrace() { std::vector<Debug::LLDB::Frame> Debug::LLDB::get_backtrace() {
std::vector<Frame> backtrace; std::vector<Frame> backtrace;
std::unique_lock<std::mutex> lock(event_mutex); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped) { if(state==lldb::StateType::eStateStopped) {
@ -336,8 +335,8 @@ std::vector<Debug::Clang::Frame> Debug::Clang::get_backtrace() {
return backtrace; return backtrace;
} }
std::vector<Debug::Clang::Variable> Debug::Clang::get_variables() { std::vector<Debug::LLDB::Variable> Debug::LLDB::get_variables() {
std::vector<Debug::Clang::Variable> variables; std::vector<Debug::LLDB::Variable> variables;
std::unique_lock<std::mutex> lock(event_mutex); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped) { if(state==lldb::StateType::eStateStopped) {
for(uint32_t c_t=0;c_t<process->GetNumThreads();c_t++) { for(uint32_t c_t=0;c_t<process->GetNumThreads();c_t++) {
@ -351,7 +350,7 @@ std::vector<Debug::Clang::Variable> Debug::Clang::get_variables() {
auto declaration=value.GetDeclaration(); auto declaration=value.GetDeclaration();
if(declaration.IsValid()) { if(declaration.IsValid()) {
Debug::Clang::Variable variable; Debug::LLDB::Variable variable;
variable.thread_index_id=thread.GetIndexID(); variable.thread_index_id=thread.GetIndexID();
variable.frame_index=c_f; variable.frame_index=c_f;
@ -379,7 +378,7 @@ std::vector<Debug::Clang::Variable> Debug::Clang::get_variables() {
return variables; return variables;
} }
void Debug::Clang::select_frame(uint32_t frame_index, uint32_t thread_index_id) { void Debug::LLDB::select_frame(uint32_t frame_index, uint32_t thread_index_id) {
std::unique_lock<std::mutex> lock(event_mutex); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped) { if(state==lldb::StateType::eStateStopped) {
if(thread_index_id!=0) if(thread_index_id!=0)
@ -388,13 +387,13 @@ void Debug::Clang::select_frame(uint32_t frame_index, uint32_t thread_index_id)
} }
} }
void Debug::Clang::cancel() { void Debug::LLDB::cancel() {
kill(); kill();
if(debug_thread.joinable()) if(debug_thread.joinable())
debug_thread.join(); debug_thread.join();
} }
std::string Debug::Clang::get_value(const std::string &variable, const boost::filesystem::path &file_path, unsigned int line_nr, unsigned int line_index) { std::string Debug::LLDB::get_value(const std::string &variable, const boost::filesystem::path &file_path, unsigned int line_nr, unsigned int line_index) {
std::string variable_value; std::string variable_value;
std::unique_lock<std::mutex> lock(event_mutex); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped) { if(state==lldb::StateType::eStateStopped) {
@ -435,7 +434,7 @@ std::string Debug::Clang::get_value(const std::string &variable, const boost::fi
return variable_value; return variable_value;
} }
std::string Debug::Clang::get_return_value(const boost::filesystem::path &file_path, unsigned int line_nr, unsigned int line_index) { std::string Debug::LLDB::get_return_value(const boost::filesystem::path &file_path, unsigned int line_nr, unsigned int line_index) {
std::string return_value; std::string return_value;
std::unique_lock<std::mutex> lock(event_mutex); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped) { if(state==lldb::StateType::eStateStopped) {
@ -458,22 +457,22 @@ std::string Debug::Clang::get_return_value(const boost::filesystem::path &file_p
return return_value; return return_value;
} }
bool Debug::Clang::is_invalid() { bool Debug::LLDB::is_invalid() {
std::unique_lock<std::mutex> lock(event_mutex); std::unique_lock<std::mutex> lock(event_mutex);
return state==lldb::StateType::eStateInvalid; return state==lldb::StateType::eStateInvalid;
} }
bool Debug::Clang::is_stopped() { bool Debug::LLDB::is_stopped() {
std::unique_lock<std::mutex> lock(event_mutex); std::unique_lock<std::mutex> lock(event_mutex);
return state==lldb::StateType::eStateStopped; return state==lldb::StateType::eStateStopped;
} }
bool Debug::Clang::is_running() { bool Debug::LLDB::is_running() {
std::unique_lock<std::mutex> lock(event_mutex); std::unique_lock<std::mutex> lock(event_mutex);
return state==lldb::StateType::eStateRunning; return state==lldb::StateType::eStateRunning;
} }
void Debug::Clang::add_breakpoint(const boost::filesystem::path &file_path, int line_nr) { void Debug::LLDB::add_breakpoint(const boost::filesystem::path &file_path, int line_nr) {
std::unique_lock<std::mutex> lock(event_mutex); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::eStateStopped || state==lldb::eStateRunning) { if(state==lldb::eStateStopped || state==lldb::eStateRunning) {
if(!(process->GetTarget().BreakpointCreateByLocation(file_path.string().c_str(), line_nr)).IsValid()) if(!(process->GetTarget().BreakpointCreateByLocation(file_path.string().c_str(), line_nr)).IsValid())
@ -481,7 +480,7 @@ void Debug::Clang::add_breakpoint(const boost::filesystem::path &file_path, int
} }
} }
void Debug::Clang::remove_breakpoint(const boost::filesystem::path &file_path, int line_nr, int line_count) { void Debug::LLDB::remove_breakpoint(const boost::filesystem::path &file_path, int line_nr, int line_count) {
std::unique_lock<std::mutex> lock(event_mutex); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::eStateStopped || state==lldb::eStateRunning) { if(state==lldb::eStateStopped || state==lldb::eStateRunning) {
auto target=process->GetTarget(); auto target=process->GetTarget();
@ -506,41 +505,9 @@ void Debug::Clang::remove_breakpoint(const boost::filesystem::path &file_path, i
} }
} }
void Debug::Clang::write(const std::string &buffer) { void Debug::LLDB::write(const std::string &buffer) {
std::unique_lock<std::mutex> lock(event_mutex); std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateRunning) { if(state==lldb::StateType::eStateRunning) {
process->PutSTDIN(buffer.c_str(), buffer.size()); process->PutSTDIN(buffer.c_str(), buffer.size());
} }
} }
std::vector<std::string> Debug::Clang::get_platform_list() {
//Could not find a way to do this through liblldb
static std::vector<std::string> platform_list;
if(!platform_list.empty())
return platform_list;
std::stringstream stream;
Process process(Config::get().terminal.lldb_command, "", [&stream](const char *bytes, size_t n) {
stream.write(bytes, n);
}, [](const char *bytes, size_t n) {}, true);
process.write("platform list");
process.close_stdin();
auto exit_status=process.get_exit_status();
if(exit_status!=0) {
Terminal::get().print("Error (debug): "+Config::get().terminal.lldb_command+" returned "+std::to_string(exit_status)+'\n', true);
return {};
}
std::string line;
while(std::getline(stream, line)) {
//TODO: support other plugins as well
if(line.find("host")==0 || line.find("remote-gdb-server")==0) {
size_t pos;
if((pos=line.find(": "))!=std::string::npos) {
line.replace(pos, 2, "\n");
platform_list.emplace_back(line);
}
}
}
return platform_list;
}

12
src/debug_clang.h → src/debug_lldb.h

@ -10,7 +10,7 @@
#include <mutex> #include <mutex>
namespace Debug { namespace Debug {
class Clang { class LLDB {
public: public:
class Frame { class Frame {
public: public:
@ -32,10 +32,10 @@ namespace Debug {
int line_index; int line_index;
}; };
private: private:
Clang(); LLDB();
public: public:
static Clang &get() { static LLDB &get() {
static Clang singleton; static LLDB singleton;
return singleton; return singleton;
} }
@ -44,7 +44,7 @@ namespace Debug {
std::function<void(int exit_status)> callback=nullptr, std::function<void(int exit_status)> callback=nullptr,
std::function<void(const std::string &status)> status_callback=nullptr, std::function<void(const std::string &status)> status_callback=nullptr,
std::function<void(const boost::filesystem::path &file_path, int line_nr, int line_index)> stop_callback=nullptr, std::function<void(const boost::filesystem::path &file_path, int line_nr, int line_index)> stop_callback=nullptr,
const std::string &plugin="", const std::string &url=""); const std::string &remote_host="");
void continue_debug(); //can't use continue as function name void continue_debug(); //can't use continue as function name
void stop(); void stop();
void kill(); void kill();
@ -70,8 +70,6 @@ namespace Debug {
void write(const std::string &buffer); void write(const std::string &buffer);
static std::vector<std::string> get_platform_list();
private: private:
std::unique_ptr<lldb::SBDebugger> debugger; std::unique_ptr<lldb::SBDebugger> debugger;
std::unique_ptr<lldb::SBListener> listener; std::unique_ptr<lldb::SBListener> listener;

94
src/project.cc

@ -7,7 +7,7 @@
#include "menu.h" #include "menu.h"
#include "notebook.h" #include "notebook.h"
#ifdef JUCI_ENABLE_DEBUG #ifdef JUCI_ENABLE_DEBUG
#include "debug_clang.h" #include "debug_lldb.h"
#endif #endif
#include "info.h" #include "info.h"
@ -19,7 +19,7 @@ std::atomic<bool> Project::debugging(false);
std::pair<boost::filesystem::path, std::pair<int, int> > Project::debug_stop; std::pair<boost::filesystem::path, std::pair<int, int> > Project::debug_stop;
std::unique_ptr<Project::Base> Project::current; std::unique_ptr<Project::Base> Project::current;
#ifdef JUCI_ENABLE_DEBUG #ifdef JUCI_ENABLE_DEBUG
std::unordered_map<std::string, Project::Clang::DebugOptionsPopover> Project::Clang::debug_options_popovers; std::unordered_map<std::string, Project::Clang::DebugOptions> Project::Clang::debug_options;
#endif #endif
Gtk::Label &Project::debug_status_label() { Gtk::Label &Project::debug_status_label() {
@ -157,29 +157,28 @@ void Project::Base::debug_start() {
} }
#ifdef JUCI_ENABLE_DEBUG #ifdef JUCI_ENABLE_DEBUG
Project::Clang::DebugOptionsPopover::DebugOptionsPopover() : Gtk::Popover() { Project::Clang::DebugOptions::DebugOptions() : Base::DebugOptions() {
auto lldb_platform_list=Debug::Clang::get_platform_list(); remote_enabled.set_active(false);
for(auto &platform: lldb_platform_list) remote_enabled.set_label("Enabled");
platform_list.append(platform); remote_enabled.signal_clicked().connect([this] {
if(platform_list.get_model()->children().size()>0) remote_host.set_sensitive(remote_enabled.get_active());
platform_list.set_active(0); });
url.set_sensitive(false); remote_host.set_sensitive(false);
platform_list.signal_changed().connect([this]() { remote_host.set_placeholder_text("host:port");
url.set_sensitive(platform_list.get_active_row_number()>0); remote_host.signal_activate().connect([this] {
set_visible(false);
}); });
url.set_placeholder_text("URL"); auto remote_vbox=Gtk::manage(new Gtk::VBox());
url.set_text("connect://host:port"); remote_vbox->pack_start(remote_enabled, true, true);
remote_vbox->pack_end(remote_host, true, true);
cross_compiling_vbox.pack_start(platform_list, true, true);
cross_compiling_vbox.pack_end(url, true, true);
cross_compiling_frame.set_label("Cross Compiling"); auto remote_frame=Gtk::manage(new Gtk::Frame());
cross_compiling_frame.add(cross_compiling_vbox); remote_frame->set_label("Remote Debugging");
remote_frame->add(*remote_vbox);
vbox.pack_start(cross_compiling_frame, true, true); vbox.pack_end(*remote_frame, true, true);
add(vbox);
show_all(); show_all();
set_visible(false); set_visible(false);
} }
@ -298,9 +297,9 @@ std::pair<std::string, std::string> Project::Clang::debug_get_run_arguments() {
return {project_path, arguments}; return {project_path, arguments};
} }
Gtk::Popover *Project::Clang::debug_get_options_popover() { Gtk::Popover *Project::Clang::debug_get_options() {
if(!build->project_path.empty()) if(!build->project_path.empty())
return &debug_options_popovers[build->project_path.string()]; return &debug_options[build->project_path.string()];
return nullptr; return nullptr;
} }
@ -350,15 +349,12 @@ void Project::Clang::debug_start() {
if(exit_status!=EXIT_SUCCESS) if(exit_status!=EXIT_SUCCESS)
debugging=false; debugging=false;
else { else {
std::string plugin, url; std::string remote_host;
auto options_it=debug_options_popovers.find(project_path.string()); auto options_it=debug_options.find(project_path.string());
if(options_it!=debug_options_popovers.end()) { if(options_it!=debug_options.end() && options_it->second.remote_enabled.get_active())
auto plugin_selection=options_it->second.platform_list.get_active_text(); remote_host=options_it->second.remote_host.get_text();
plugin=plugin_selection.substr(0, plugin_selection.find("\n"));
url=options_it->second.url.get_text();
}
std::unique_lock<std::mutex> lock(debug_start_mutex); std::unique_lock<std::mutex> lock(debug_start_mutex);
Debug::Clang::get().start(run_arguments, project_path, *breakpoints, [this, run_arguments](int exit_status){ Debug::LLDB::get().start(run_arguments, project_path, *breakpoints, [this, run_arguments](int exit_status){
debugging=false; debugging=false;
Terminal::get().async_print(run_arguments+" returned: "+std::to_string(exit_status)+'\n'); Terminal::get().async_print(run_arguments+" returned: "+std::to_string(exit_status)+'\n');
}, [this](const std::string &status) { }, [this](const std::string &status) {
@ -375,48 +371,48 @@ void Project::Clang::debug_start() {
if(auto view=Notebook::get().get_current_view()) if(auto view=Notebook::get().get_current_view())
view->get_buffer()->place_cursor(view->get_buffer()->get_insert()->get_iter()); view->get_buffer()->place_cursor(view->get_buffer()->get_insert()->get_iter());
}); });
}, plugin, url); }, remote_host);
} }
}); });
} }
void Project::Clang::debug_continue() { void Project::Clang::debug_continue() {
Debug::Clang::get().continue_debug(); Debug::LLDB::get().continue_debug();
} }
void Project::Clang::debug_stop() { void Project::Clang::debug_stop() {
if(debugging) if(debugging)
Debug::Clang::get().stop(); Debug::LLDB::get().stop();
} }
void Project::Clang::debug_kill() { void Project::Clang::debug_kill() {
if(debugging) if(debugging)
Debug::Clang::get().kill(); Debug::LLDB::get().kill();
} }
void Project::Clang::debug_step_over() { void Project::Clang::debug_step_over() {
if(debugging) if(debugging)
Debug::Clang::get().step_over(); Debug::LLDB::get().step_over();
} }
void Project::Clang::debug_step_into() { void Project::Clang::debug_step_into() {
if(debugging) if(debugging)
Debug::Clang::get().step_into(); Debug::LLDB::get().step_into();
} }
void Project::Clang::debug_step_out() { void Project::Clang::debug_step_out() {
if(debugging) if(debugging)
Debug::Clang::get().step_out(); Debug::LLDB::get().step_out();
} }
void Project::Clang::debug_backtrace() { void Project::Clang::debug_backtrace() {
auto view=Notebook::get().get_current_view(); auto view=Notebook::get().get_current_view();
if(view && debugging) { if(view && debugging) {
auto backtrace=Debug::Clang::get().get_backtrace(); auto backtrace=Debug::LLDB::get().get_backtrace();
auto iter=view->get_iter_for_dialog(); auto iter=view->get_iter_for_dialog();
view->selection_dialog=std::unique_ptr<SelectionDialog>(new SelectionDialog(*view, view->get_buffer()->create_mark(iter), true, true)); view->selection_dialog=std::unique_ptr<SelectionDialog>(new SelectionDialog(*view, view->get_buffer()->create_mark(iter), true, true));
auto rows=std::make_shared<std::unordered_map<std::string, Debug::Clang::Frame> >(); auto rows=std::make_shared<std::unordered_map<std::string, Debug::LLDB::Frame> >();
if(backtrace.size()==0) if(backtrace.size()==0)
return; return;
@ -447,7 +443,7 @@ void Project::Clang::debug_backtrace() {
if(!frame.file_path.empty()) { if(!frame.file_path.empty()) {
Notebook::get().open(frame.file_path); Notebook::get().open(frame.file_path);
if(auto view=Notebook::get().get_current_view()) { if(auto view=Notebook::get().get_current_view()) {
Debug::Clang::get().select_frame(frame.index); Debug::LLDB::get().select_frame(frame.index);
view->place_cursor_at_line_index(frame.line_nr-1, frame.line_index-1); view->place_cursor_at_line_index(frame.line_nr-1, frame.line_index-1);
view->scroll_to_cursor_delayed(view, true, true); view->scroll_to_cursor_delayed(view, true, true);
@ -462,11 +458,11 @@ void Project::Clang::debug_backtrace() {
void Project::Clang::debug_show_variables() { void Project::Clang::debug_show_variables() {
auto view=Notebook::get().get_current_view(); auto view=Notebook::get().get_current_view();
if(debugging && view) { if(debugging && view) {
auto variables=Debug::Clang::get().get_variables(); auto variables=Debug::LLDB::get().get_variables();
auto iter=view->get_iter_for_dialog(); auto iter=view->get_iter_for_dialog();
view->selection_dialog=std::unique_ptr<SelectionDialog>(new SelectionDialog(*view, view->get_buffer()->create_mark(iter), true, true)); view->selection_dialog=std::unique_ptr<SelectionDialog>(new SelectionDialog(*view, view->get_buffer()->create_mark(iter), true, true));
auto rows=std::make_shared<std::unordered_map<std::string, Debug::Clang::Variable> >(); auto rows=std::make_shared<std::unordered_map<std::string, Debug::LLDB::Variable> >();
if(variables.size()==0) if(variables.size()==0)
return; return;
@ -482,7 +478,7 @@ void Project::Clang::debug_show_variables() {
if(!variable.file_path.empty()) { if(!variable.file_path.empty()) {
Notebook::get().open(variable.file_path); Notebook::get().open(variable.file_path);
if(auto view=Notebook::get().get_current_view()) { if(auto view=Notebook::get().get_current_view()) {
Debug::Clang::get().select_frame(variable.frame_index, variable.thread_index_id); Debug::LLDB::get().select_frame(variable.frame_index, variable.thread_index_id);
view->place_cursor_at_line_index(variable.line_nr-1, variable.line_index-1); view->place_cursor_at_line_index(variable.line_nr-1, variable.line_index-1);
view->scroll_to_cursor_delayed(view, true, true); view->scroll_to_cursor_delayed(view, true, true);
@ -533,31 +529,31 @@ void Project::Clang::debug_show_variables() {
void Project::Clang::debug_run_command(const std::string &command) { void Project::Clang::debug_run_command(const std::string &command) {
if(debugging) { if(debugging) {
auto command_return=Debug::Clang::get().run_command(command); auto command_return=Debug::LLDB::get().run_command(command);
Terminal::get().async_print(command_return.first); Terminal::get().async_print(command_return.first);
Terminal::get().async_print(command_return.second, true); Terminal::get().async_print(command_return.second, true);
} }
} }
void Project::Clang::debug_add_breakpoint(const boost::filesystem::path &file_path, int line_nr) { void Project::Clang::debug_add_breakpoint(const boost::filesystem::path &file_path, int line_nr) {
Debug::Clang::get().add_breakpoint(file_path, line_nr); Debug::LLDB::get().add_breakpoint(file_path, line_nr);
} }
void Project::Clang::debug_remove_breakpoint(const boost::filesystem::path &file_path, int line_nr, int line_count) { void Project::Clang::debug_remove_breakpoint(const boost::filesystem::path &file_path, int line_nr, int line_count) {
Debug::Clang::get().remove_breakpoint(file_path, line_nr, line_count); Debug::LLDB::get().remove_breakpoint(file_path, line_nr, line_count);
} }
bool Project::Clang::debug_is_running() { bool Project::Clang::debug_is_running() {
return Debug::Clang::get().is_running(); return Debug::LLDB::get().is_running();
} }
void Project::Clang::debug_write(const std::string &buffer) { void Project::Clang::debug_write(const std::string &buffer) {
Debug::Clang::get().write(buffer); Debug::LLDB::get().write(buffer);
} }
void Project::Clang::debug_cancel() { void Project::Clang::debug_cancel() {
std::unique_lock<std::mutex> lock(debug_start_mutex); std::unique_lock<std::mutex> lock(debug_start_mutex);
Debug::Clang::get().cancel(); Debug::LLDB::get().cancel();
} }
#endif #endif

27
src/project.h

@ -26,6 +26,15 @@ namespace Project {
void debug_update_status(const std::string &debug_status); void debug_update_status(const std::string &debug_status);
class Base { class Base {
protected:
#ifdef JUCI_ENABLE_DEBUG
class DebugOptions : public Gtk::Popover {
public:
DebugOptions() : Gtk::Popover() { add(vbox); }
protected:
Gtk::VBox vbox;
};
#endif
public: public:
Base(std::unique_ptr<Build> &&build): build(std::move(build)) {} Base(std::unique_ptr<Build> &&build): build(std::move(build)) {}
virtual ~Base() {} virtual ~Base() {}
@ -37,7 +46,7 @@ namespace Project {
virtual void compile_and_run(); virtual void compile_and_run();
virtual std::pair<std::string, std::string> debug_get_run_arguments(); virtual std::pair<std::string, std::string> debug_get_run_arguments();
virtual Gtk::Popover *debug_get_options_popover() { return nullptr; } virtual Gtk::Popover *debug_get_options() { return nullptr; }
Tooltips debug_variable_tooltips; Tooltips debug_variable_tooltips;
virtual void debug_start(); virtual void debug_start();
virtual void debug_continue() {} virtual void debug_continue() {}
@ -58,17 +67,13 @@ namespace Project {
class Clang : public Base { class Clang : public Base {
#ifdef JUCI_ENABLE_DEBUG #ifdef JUCI_ENABLE_DEBUG
class DebugOptionsPopover : public Gtk::Popover { class DebugOptions : public Base::DebugOptions {
public: public:
DebugOptionsPopover(); DebugOptions();
Gtk::ComboBoxText platform_list; Gtk::CheckButton remote_enabled;
Gtk::Entry url; Gtk::Entry remote_host;
private:
Gtk::VBox vbox;
Gtk::Frame cross_compiling_frame;
Gtk::VBox cross_compiling_vbox;
}; };
static std::unordered_map<std::string, DebugOptionsPopover> debug_options_popovers; static std::unordered_map<std::string, DebugOptions> debug_options;
#endif #endif
Dispatcher dispatcher; Dispatcher dispatcher;
@ -83,7 +88,7 @@ namespace Project {
std::mutex debug_start_mutex; std::mutex debug_start_mutex;
#ifdef JUCI_ENABLE_DEBUG #ifdef JUCI_ENABLE_DEBUG
std::pair<std::string, std::string> debug_get_run_arguments() override; std::pair<std::string, std::string> debug_get_run_arguments() override;
Gtk::Popover *debug_get_options_popover() override; Gtk::Popover *debug_get_options() override;
void debug_start() override; void debug_start() override;
void debug_continue() override; void debug_continue() override;
void debug_stop() override; void debug_stop() override;

8
src/source_clang.cc

@ -3,7 +3,7 @@
#include "terminal.h" #include "terminal.h"
#include "project_build.h" #include "project_build.h"
#ifdef JUCI_ENABLE_DEBUG #ifdef JUCI_ENABLE_DEBUG
#include "debug_clang.h" #include "debug_lldb.h"
#endif #endif
#include "info.h" #include "info.h"
#include "dialogs.h" #include "dialogs.h"
@ -430,7 +430,7 @@ void Source::ClangViewParse::show_type_tooltips(const Gdk::Rectangle &rectangle)
tooltip_buffer->insert_with_tag(tooltip_buffer->get_insert()->get_iter(), "\n\n"+brief_comment, "def:note"); tooltip_buffer->insert_with_tag(tooltip_buffer->get_insert()->get_iter(), "\n\n"+brief_comment, "def:note");
#ifdef JUCI_ENABLE_DEBUG #ifdef JUCI_ENABLE_DEBUG
if(Debug::Clang::get().is_stopped()) { if(Debug::LLDB::get().is_stopped()) {
auto location=token.get_cursor().get_referenced().get_source_location(); auto location=token.get_cursor().get_referenced().get_source_location();
Glib::ustring value_type="Value"; Glib::ustring value_type="Value";
@ -452,12 +452,12 @@ void Source::ClangViewParse::show_type_tooltips(const Gdk::Rectangle &rectangle)
} }
auto spelling=get_buffer()->get_text(start, end).raw(); auto spelling=get_buffer()->get_text(start, end).raw();
Glib::ustring debug_value=Debug::Clang::get().get_value(spelling, location.get_path(), location.get_offset().line, location.get_offset().index); Glib::ustring debug_value=Debug::LLDB::get().get_value(spelling, location.get_path(), location.get_offset().line, location.get_offset().index);
if(debug_value.empty()) { if(debug_value.empty()) {
value_type="Return value"; value_type="Return value";
auto cursor=token.get_cursor(); auto cursor=token.get_cursor();
auto offsets=cursor.get_source_range().get_offsets(); auto offsets=cursor.get_source_range().get_offsets();
debug_value=Debug::Clang::get().get_return_value(cursor.get_source_location().get_path(), offsets.first.line, offsets.first.index); debug_value=Debug::LLDB::get().get_return_value(cursor.get_source_location().get_path(), offsets.first.line, offsets.first.index);
} }
if(!debug_value.empty()) { if(!debug_value.empty()) {
size_t pos=debug_value.find(" = "); size_t pos=debug_value.find(" = ");

8
src/window.cc

@ -721,14 +721,14 @@ void Window::set_menu_actions() {
auto entry_it=EntryBox::get().entries.begin(); auto entry_it=EntryBox::get().entries.begin();
entry_it->set_placeholder_text("Debug: Set Run Arguments"); entry_it->set_placeholder_text("Debug: Set Run Arguments");
if(auto options_popover=project->debug_get_options_popover()) { if(auto options=project->debug_get_options()) {
EntryBox::get().buttons.emplace_back("", [this, options_popover]() { EntryBox::get().buttons.emplace_back("", [this, options]() {
options_popover->set_visible(true); options->set_visible(true);
}); });
EntryBox::get().buttons.back().set_image_from_icon_name("preferences-system"); EntryBox::get().buttons.back().set_image_from_icon_name("preferences-system");
EntryBox::get().buttons.back().set_always_show_image(true); EntryBox::get().buttons.back().set_always_show_image(true);
EntryBox::get().buttons.back().set_tooltip_text("Additional Options"); EntryBox::get().buttons.back().set_tooltip_text("Additional Options");
options_popover->set_relative_to(EntryBox::get().buttons.back()); options->set_relative_to(EntryBox::get().buttons.back());
} }
EntryBox::get().buttons.emplace_back("Debug: set run arguments", [this, entry_it](){ EntryBox::get().buttons.emplace_back("Debug: set run arguments", [this, entry_it](){

26
tests/lldb_test.cc

@ -1,5 +1,5 @@
#include <glib.h> #include <glib.h>
#include "debug_clang.h" #include "debug_lldb.h"
#include <thread> #include <thread>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <atomic> #include <atomic>
@ -20,7 +20,7 @@ int main() {
int exit_status; int exit_status;
std::atomic<int> line_nr(0); std::atomic<int> line_nr(0);
std::thread debug_thread([&] { std::thread debug_thread([&] {
Debug::Clang::get().start(exec_path.string(), "", breakpoints, [&](int exit_status_){ Debug::LLDB::get().start(exec_path.string(), "", breakpoints, [&](int exit_status_){
exit_status=exit_status_; exit_status=exit_status_;
exited=true; exited=true;
}, [](const std::string &status) { }, [](const std::string &status) {
@ -38,36 +38,34 @@ int main() {
} }
else if(line_nr>0) { else if(line_nr>0) {
for(;;) { for(;;) {
if(Debug::Clang::get().is_stopped()) if(Debug::LLDB::get().is_stopped())
break; break;
std::this_thread::sleep_for(std::chrono::milliseconds(100)); std::this_thread::sleep_for(std::chrono::milliseconds(100));
} }
g_assert_cmpint(line_nr, ==, 2); g_assert_cmpint(line_nr, ==, 2);
g_assert(Debug::Clang::get().get_backtrace().size()>0); g_assert(Debug::LLDB::get().get_backtrace().size()>0);
auto variables=Debug::Clang::get().get_variables(); auto variables=Debug::LLDB::get().get_variables();
g_assert_cmpstr(variables.at(0).name.c_str(), ==, "an_int"); g_assert_cmpstr(variables.at(0).name.c_str(), ==, "an_int");
line_nr=0; line_nr=0;
Debug::Clang::get().step_over(); Debug::LLDB::get().step_over();
for(;;) { for(;;) {
if(line_nr>0 && Debug::Clang::get().is_stopped()) if(line_nr>0 && Debug::LLDB::get().is_stopped())
break; break;
std::this_thread::sleep_for(std::chrono::milliseconds(100)); std::this_thread::sleep_for(std::chrono::milliseconds(100));
} }
g_assert_cmpint(line_nr, ==, 3); g_assert_cmpint(line_nr, ==, 3);
g_assert(Debug::Clang::get().get_backtrace().size()>0); g_assert(Debug::LLDB::get().get_backtrace().size()>0);
variables=Debug::Clang::get().get_variables(); variables=Debug::LLDB::get().get_variables();
g_assert_cmpstr(variables.at(0).name.c_str(), ==, "an_int"); g_assert_cmpstr(variables.at(0).name.c_str(), ==, "an_int");
auto value=Debug::Clang::get().get_value("an_int", source_path, 2, 7); auto value=Debug::LLDB::get().get_value("an_int", source_path, 2, 7);
g_assert_cmpuint(value.size(), >, 16); g_assert_cmpuint(value.size(), >, 16);
auto value_substr=value.substr(0, 16); auto value_substr=value.substr(0, 16);
g_assert_cmpstr(value_substr.c_str(), ==, "(int) an_int = 1"); g_assert_cmpstr(value_substr.c_str(), ==, "(int) an_int = 1");
line_nr=0; line_nr=0;
Debug::Clang::get().continue_debug(); Debug::LLDB::get().continue_debug();
} }
std::this_thread::sleep_for(std::chrono::milliseconds(10)); std::this_thread::sleep_for(std::chrono::milliseconds(10));
} }
Debug::Clang::get().cancel(); Debug::LLDB::get().cancel();
g_assert_cmpuint(Debug::Clang::get_platform_list().size(), >, 0);
} }

19
tests/stubs/config.cc

@ -1,20 +1,3 @@
#include "config.h" #include "config.h"
Config::Config() { Config::Config() {}
terminal.lldb_command="lldb";
#ifdef __linux
if(terminal.lldb_command=="lldb" &&
!boost::filesystem::exists("/usr/bin/lldb") && !boost::filesystem::exists("/usr/local/bin/lldb")) {
if(boost::filesystem::exists("/usr/bin/lldb-3.9"))
terminal.lldb_command="/usr/bin/lldb-3.9";
else if(boost::filesystem::exists("/usr/bin/lldb-3.8"))
terminal.lldb_command="/usr/bin/lldb-3.8";
else if(boost::filesystem::exists("/usr/bin/lldb-3.7"))
terminal.lldb_command="/usr/bin/lldb-3.7";
else if(boost::filesystem::exists("/usr/bin/lldb-3.6"))
terminal.lldb_command="/usr/bin/lldb-3.6";
else if(boost::filesystem::exists("/usr/bin/lldb-3.5"))
terminal.lldb_command="/usr/bin/lldb-3.5";
}
#endif
}

Loading…
Cancel
Save