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
* C++ warnings and errors on the fly
* C++ Fix-its
* Debug integration through lldb
* Debug integration, both local and remote, through lldb
* Automated CMake processing, including support for external libraries
* Fast C++ autocompletion
* Keyword and buffer autocompletion for other file types

2
src/CMakeLists.txt

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

14
src/config.cc

@ -99,7 +99,6 @@ void Config::retrieve_config() {
terminal.font=cfg.get<std::string>("terminal.font");
terminal.clang_format_command="clang-format";
terminal.lldb_command="lldb";
#ifdef __linux
if(terminal.clang_format_command=="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"))
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
}

1
src/config.h

@ -25,7 +25,6 @@ public:
class Terminal {
public:
std::string clang_format_command;
std::string lldb_command;
int history_size;
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>
#ifdef __APPLE__
#include <stdlib.h>
@ -29,7 +29,7 @@ void log(const char *msg, void *) {
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__
auto debugserver_path=boost::filesystem::path("/usr/local/opt/llvm/bin/debugserver");
if(boost::filesystem::exists(debugserver_path))
@ -37,12 +37,12 @@ Debug::Clang::Clang(): state(lldb::StateType::eStateInvalid), buffer_size(131072
#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,
std::function<void(int exit_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,
const std::string &plugin, const std::string &url) {
const std::string &remote_host) {
if(!debugger) {
lldb::SBDebugger::Initialize();
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;
if(!plugin.empty() && plugin!="host") {
//TODO: support other plugins as well
//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, url.c_str(), "gdb-remote", error)));
if(!remote_host.empty()) {
auto connect_string="connect://"+remote_host;
process = std::unique_ptr<lldb::SBProcess>(new lldb::SBProcess(target.ConnectRemote(*listener, connect_string.c_str(), "gdb-remote", error)));
if(error.Fail()) {
Terminal::get().async_print(std::string("Error (debug): ")+error.GetCString()+'\n', true);
if(callback)
@ -124,7 +123,7 @@ void Debug::Clang::start(const std::string &command, const boost::filesystem::pa
}
const char *empty_parameter[1];
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())
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);
if(state==lldb::StateType::eStateStopped)
process->Continue();
}
void Debug::Clang::stop() {
void Debug::LLDB::stop() {
std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateRunning) {
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);
if(process) {
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);
if(state==lldb::StateType::eStateStopped) {
process->GetSelectedThread().StepOver();
}
}
void Debug::Clang::step_into() {
void Debug::LLDB::step_into() {
std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped) {
process->GetSelectedThread().StepInto();
}
}
void Debug::Clang::step_out() {
void Debug::LLDB::step_out() {
std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped) {
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::unique_lock<std::mutex> lock(event_mutex);
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;
}
std::vector<Debug::Clang::Frame> Debug::Clang::get_backtrace() {
std::vector<Debug::LLDB::Frame> Debug::LLDB::get_backtrace() {
std::vector<Frame> backtrace;
std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped) {
@ -336,8 +335,8 @@ std::vector<Debug::Clang::Frame> Debug::Clang::get_backtrace() {
return backtrace;
}
std::vector<Debug::Clang::Variable> Debug::Clang::get_variables() {
std::vector<Debug::Clang::Variable> variables;
std::vector<Debug::LLDB::Variable> Debug::LLDB::get_variables() {
std::vector<Debug::LLDB::Variable> variables;
std::unique_lock<std::mutex> lock(event_mutex);
if(state==lldb::StateType::eStateStopped) {
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();
if(declaration.IsValid()) {
Debug::Clang::Variable variable;
Debug::LLDB::Variable variable;
variable.thread_index_id=thread.GetIndexID();
variable.frame_index=c_f;
@ -379,7 +378,7 @@ std::vector<Debug::Clang::Variable> Debug::Clang::get_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);
if(state==lldb::StateType::eStateStopped) {
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();
if(debug_thread.joinable())
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::unique_lock<std::mutex> lock(event_mutex);
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;
}
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::unique_lock<std::mutex> lock(event_mutex);
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;
}
bool Debug::Clang::is_invalid() {
bool Debug::LLDB::is_invalid() {
std::unique_lock<std::mutex> lock(event_mutex);
return state==lldb::StateType::eStateInvalid;
}
bool Debug::Clang::is_stopped() {
bool Debug::LLDB::is_stopped() {
std::unique_lock<std::mutex> lock(event_mutex);
return state==lldb::StateType::eStateStopped;
}
bool Debug::Clang::is_running() {
bool Debug::LLDB::is_running() {
std::unique_lock<std::mutex> lock(event_mutex);
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);
if(state==lldb::eStateStopped || state==lldb::eStateRunning) {
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);
if(state==lldb::eStateStopped || state==lldb::eStateRunning) {
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);
if(state==lldb::StateType::eStateRunning) {
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>
namespace Debug {
class Clang {
class LLDB {
public:
class Frame {
public:
@ -32,10 +32,10 @@ namespace Debug {
int line_index;
};
private:
Clang();
LLDB();
public:
static Clang &get() {
static Clang singleton;
static LLDB &get() {
static LLDB singleton;
return singleton;
}
@ -44,7 +44,7 @@ namespace Debug {
std::function<void(int exit_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,
const std::string &plugin="", const std::string &url="");
const std::string &remote_host="");
void continue_debug(); //can't use continue as function name
void stop();
void kill();
@ -70,8 +70,6 @@ namespace Debug {
void write(const std::string &buffer);
static std::vector<std::string> get_platform_list();
private:
std::unique_ptr<lldb::SBDebugger> debugger;
std::unique_ptr<lldb::SBListener> listener;

94
src/project.cc

@ -7,7 +7,7 @@
#include "menu.h"
#include "notebook.h"
#ifdef JUCI_ENABLE_DEBUG
#include "debug_clang.h"
#include "debug_lldb.h"
#endif
#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::unique_ptr<Project::Base> Project::current;
#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
Gtk::Label &Project::debug_status_label() {
@ -157,29 +157,28 @@ void Project::Base::debug_start() {
}
#ifdef JUCI_ENABLE_DEBUG
Project::Clang::DebugOptionsPopover::DebugOptionsPopover() : Gtk::Popover() {
auto lldb_platform_list=Debug::Clang::get_platform_list();
for(auto &platform: lldb_platform_list)
platform_list.append(platform);
if(platform_list.get_model()->children().size()>0)
platform_list.set_active(0);
url.set_sensitive(false);
platform_list.signal_changed().connect([this]() {
url.set_sensitive(platform_list.get_active_row_number()>0);
Project::Clang::DebugOptions::DebugOptions() : Base::DebugOptions() {
remote_enabled.set_active(false);
remote_enabled.set_label("Enabled");
remote_enabled.signal_clicked().connect([this] {
remote_host.set_sensitive(remote_enabled.get_active());
});
remote_host.set_sensitive(false);
remote_host.set_placeholder_text("host:port");
remote_host.signal_activate().connect([this] {
set_visible(false);
});
url.set_placeholder_text("URL");
url.set_text("connect://host:port");
cross_compiling_vbox.pack_start(platform_list, true, true);
cross_compiling_vbox.pack_end(url, true, true);
auto remote_vbox=Gtk::manage(new Gtk::VBox());
remote_vbox->pack_start(remote_enabled, true, true);
remote_vbox->pack_end(remote_host, true, true);
cross_compiling_frame.set_label("Cross Compiling");
cross_compiling_frame.add(cross_compiling_vbox);
auto remote_frame=Gtk::manage(new Gtk::Frame());
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();
set_visible(false);
}
@ -298,9 +297,9 @@ std::pair<std::string, std::string> Project::Clang::debug_get_run_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())
return &debug_options_popovers[build->project_path.string()];
return &debug_options[build->project_path.string()];
return nullptr;
}
@ -350,15 +349,12 @@ void Project::Clang::debug_start() {
if(exit_status!=EXIT_SUCCESS)
debugging=false;
else {
std::string plugin, url;
auto options_it=debug_options_popovers.find(project_path.string());
if(options_it!=debug_options_popovers.end()) {
auto plugin_selection=options_it->second.platform_list.get_active_text();
plugin=plugin_selection.substr(0, plugin_selection.find("\n"));
url=options_it->second.url.get_text();
}
std::string remote_host;
auto options_it=debug_options.find(project_path.string());
if(options_it!=debug_options.end() && options_it->second.remote_enabled.get_active())
remote_host=options_it->second.remote_host.get_text();
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;
Terminal::get().async_print(run_arguments+" returned: "+std::to_string(exit_status)+'\n');
}, [this](const std::string &status) {
@ -375,48 +371,48 @@ void Project::Clang::debug_start() {
if(auto view=Notebook::get().get_current_view())
view->get_buffer()->place_cursor(view->get_buffer()->get_insert()->get_iter());
});
}, plugin, url);
}, remote_host);
}
});
}
void Project::Clang::debug_continue() {
Debug::Clang::get().continue_debug();
Debug::LLDB::get().continue_debug();
}
void Project::Clang::debug_stop() {
if(debugging)
Debug::Clang::get().stop();
Debug::LLDB::get().stop();
}
void Project::Clang::debug_kill() {
if(debugging)
Debug::Clang::get().kill();
Debug::LLDB::get().kill();
}
void Project::Clang::debug_step_over() {
if(debugging)
Debug::Clang::get().step_over();
Debug::LLDB::get().step_over();
}
void Project::Clang::debug_step_into() {
if(debugging)
Debug::Clang::get().step_into();
Debug::LLDB::get().step_into();
}
void Project::Clang::debug_step_out() {
if(debugging)
Debug::Clang::get().step_out();
Debug::LLDB::get().step_out();
}
void Project::Clang::debug_backtrace() {
auto view=Notebook::get().get_current_view();
if(view && debugging) {
auto backtrace=Debug::Clang::get().get_backtrace();
auto backtrace=Debug::LLDB::get().get_backtrace();
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));
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)
return;
@ -447,7 +443,7 @@ void Project::Clang::debug_backtrace() {
if(!frame.file_path.empty()) {
Notebook::get().open(frame.file_path);
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->scroll_to_cursor_delayed(view, true, true);
@ -462,11 +458,11 @@ void Project::Clang::debug_backtrace() {
void Project::Clang::debug_show_variables() {
auto view=Notebook::get().get_current_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();
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)
return;
@ -482,7 +478,7 @@ void Project::Clang::debug_show_variables() {
if(!variable.file_path.empty()) {
Notebook::get().open(variable.file_path);
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->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) {
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.second, true);
}
}
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) {
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() {
return Debug::Clang::get().is_running();
return Debug::LLDB::get().is_running();
}
void Project::Clang::debug_write(const std::string &buffer) {
Debug::Clang::get().write(buffer);
Debug::LLDB::get().write(buffer);
}
void Project::Clang::debug_cancel() {
std::unique_lock<std::mutex> lock(debug_start_mutex);
Debug::Clang::get().cancel();
Debug::LLDB::get().cancel();
}
#endif

27
src/project.h

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

8
src/source_clang.cc

@ -3,7 +3,7 @@
#include "terminal.h"
#include "project_build.h"
#ifdef JUCI_ENABLE_DEBUG
#include "debug_clang.h"
#include "debug_lldb.h"
#endif
#include "info.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");
#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();
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();
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()) {
value_type="Return value";
auto cursor=token.get_cursor();
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()) {
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();
entry_it->set_placeholder_text("Debug: Set Run Arguments");
if(auto options_popover=project->debug_get_options_popover()) {
EntryBox::get().buttons.emplace_back("", [this, options_popover]() {
options_popover->set_visible(true);
if(auto options=project->debug_get_options()) {
EntryBox::get().buttons.emplace_back("", [this, options]() {
options->set_visible(true);
});
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_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](){

26
tests/lldb_test.cc

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

19
tests/stubs/config.cc

@ -1,20 +1,3 @@
#include "config.h"
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
}
Config::Config() {}

Loading…
Cancel
Save