Browse Source

Work in progress, a somewhat usable debugger now implemented

merge-requests/365/head
eidheim 10 years ago
parent
commit
a6b19c9dbd
  1. 51
      src/debug.cc
  2. 4
      src/debug.h
  3. 1
      src/files.h
  4. 9
      src/menu.cc
  5. 7
      src/window.cc

51
src/debug.cc

@ -17,7 +17,7 @@ void log(const char *msg, void *) {
cout << "debugger log: " << msg << endl; cout << "debugger log: " << msg << endl;
} }
Debug::Debug() { Debug::Debug(): stopped(false) {
lldb::SBDebugger::Initialize(); lldb::SBDebugger::Initialize();
debugger=lldb::SBDebugger::Create(true, log, nullptr); debugger=lldb::SBDebugger::Create(true, log, nullptr);
@ -36,7 +36,7 @@ void Debug::start(const boost::filesystem::path &project_path, const boost::file
for(auto &breakpoint: breakpoints[project_path.string()]) { for(auto &breakpoint: breakpoints[project_path.string()]) {
if(!(target.BreakpointCreateByLocation(breakpoint.first.c_str(), breakpoint.second)).IsValid()) { if(!(target.BreakpointCreateByLocation(breakpoint.first.c_str(), breakpoint.second)).IsValid()) {
cerr << "Error: Could not create breakpoint at: " << breakpoint.first << ":" << breakpoint.second << endl; //TODO: fix output to terminal instead cerr << "Error: Could not create breakpoint at: " << breakpoint.first << ":" << breakpoint.second << endl; //TODO: output to terminal instead
return; return;
} }
else else
@ -44,20 +44,22 @@ void Debug::start(const boost::filesystem::path &project_path, const boost::file
} }
lldb::SBError error; lldb::SBError error;
auto process = target.Launch(listener, nullptr, nullptr, nullptr, nullptr, nullptr, path.string().c_str(), lldb::eLaunchFlagNone, false, error); process = std::unique_ptr<lldb::SBProcess>(new lldb::SBProcess(target.Launch(listener, nullptr, nullptr, nullptr, nullptr, nullptr, path.string().c_str(), lldb::eLaunchFlagNone, false, error)));
if(error.Fail()) { if(error.Fail()) {
cerr << "Error (debug): " << error.GetCString() << endl; //TODO: output to terminal instead cerr << "Error (debug): " << error.GetCString() << endl; //TODO: output to terminal instead
return; return;
} }
//Wait till stopped. TODO: add check if process.GetStateFromEvent(event)==lldb::StateType::eStateStopped after
lldb::SBEvent event; lldb::SBEvent event;
while(listener.WaitForEvent(3, event) && process.GetStateFromEvent(event)!=lldb::StateType::eStateStopped) {} while(true) {
if(listener.WaitForEvent(3, event)) {
cout << "NumThreads: " << process.GetNumThreads() << endl; auto state=process->GetStateFromEvent(event);
for(uint32_t thread_index_id=0;thread_index_id<process.GetNumThreads();thread_index_id++) { bool expected=false;
auto thread=process.GetThreadAtIndex(thread_index_id); if(state==lldb::StateType::eStateStopped && stopped.compare_exchange_strong(expected, true)) {
cout << "NumThreads: " << process->GetNumThreads() << endl;
for(uint32_t thread_index_id=0;thread_index_id<process->GetNumThreads();thread_index_id++) {
auto thread=process->GetThreadAtIndex(thread_index_id);
cout << "NumFrames: " << thread.GetNumFrames() << endl; cout << "NumFrames: " << thread.GetNumFrames() << endl;
for(uint32_t frame_index=0;frame_index<thread.GetNumFrames();frame_index++) { for(uint32_t frame_index=0;frame_index<thread.GetNumFrames();frame_index++) {
auto frame=thread.GetFrameAtIndex(frame_index); auto frame=thread.GetFrameAtIndex(frame_index);
@ -65,22 +67,39 @@ void Debug::start(const boost::filesystem::path &project_path, const boost::file
cout << "variables.GetSize(): " << values.GetSize() << endl; cout << "variables.GetSize(): " << values.GetSize() << endl;
for(uint32_t value_index=0;value_index<values.GetSize();value_index++) { for(uint32_t value_index=0;value_index<values.GetSize();value_index++) {
auto value=values.GetValueAtIndex(value_index); auto value=values.GetValueAtIndex(value_index);
//cout << value.GetName() << ": " << value.GetValue() << endl;
lldb::SBStream stream; lldb::SBStream stream;
value.GetDescription(stream); value.GetDescription(stream);
cout << stream.GetData(); cout << stream.GetData();
} }
} }
} }
}
process.Continue(); else if(state==lldb::StateType::eStateExited) {
auto exit_status=process->GetExitStatus();
//Get exit status. TODO: add check if process.GetStateFromEvent(event)==lldb::StateType::eStateExited after
while(listener.WaitForEvent(3, event) && process.GetStateFromEvent(event)!=lldb::StateType::eStateExited) {}
auto exit_status=process.GetExitStatus();
if(callback) if(callback)
callback(exit_status); callback(exit_status);
process.reset();
stopped=false;
return;
}
else if(state==lldb::StateType::eStateCrashed) {
if(callback)
callback(-1);
process.reset();
stopped=false;
return;
}
}
this_thread::sleep_for(std::chrono::milliseconds(200));
}
}); });
debug_thread.detach(); debug_thread.detach();
} }
void Debug::continue_debug() {
bool expected=true;
if(stopped.compare_exchange_strong(expected, false))
process->Continue();
}

4
src/debug.h

@ -4,6 +4,7 @@
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <unordered_map> #include <unordered_map>
#include "lldb/API/SBDebugger.h" #include "lldb/API/SBDebugger.h"
#include "lldb/API/SBProcess.h"
class Debug { class Debug {
private: private:
@ -15,11 +16,14 @@ public:
} }
void start(const boost::filesystem::path &project_path, const boost::filesystem::path &executable, const boost::filesystem::path &path="", std::function<void(int exit_status)> callback=nullptr); void start(const boost::filesystem::path &project_path, const boost::filesystem::path &executable, const boost::filesystem::path &path="", std::function<void(int exit_status)> callback=nullptr);
void continue_debug(); //can't use continue as function name
std::unordered_map<std::string, std::vector<std::pair<std::string, int> > > breakpoints; std::unordered_map<std::string, std::vector<std::pair<std::string, int> > > breakpoints;
private: private:
lldb::SBDebugger debugger; lldb::SBDebugger debugger;
std::unique_ptr<lldb::SBProcess> process;
std::atomic<bool> stopped;
}; };
#endif #endif

1
src/files.h

@ -99,6 +99,7 @@ const std::string configjson =
" \"kill_last_running\": \"<primary>Escape\",\n" " \"kill_last_running\": \"<primary>Escape\",\n"
" \"force_kill_last_running\": \"<primary><shift>Escape\",\n" " \"force_kill_last_running\": \"<primary><shift>Escape\",\n"
" \"debug_start\": \"<primary>y\",\n" " \"debug_start\": \"<primary>y\",\n"
" \"debug_continue\": \"<primary><shift>y\",\n"
" \"debug_toggle_breakpoint\": \"<primary>b\",\n" " \"debug_toggle_breakpoint\": \"<primary>b\",\n"
#ifdef __linux #ifdef __linux
" \"next_tab\": \"<primary>Tab\",\n" " \"next_tab\": \"<primary>Tab\",\n"

9
src/menu.cc

@ -276,6 +276,15 @@ Menu::Menu() {
" <attribute name='action'>app.debug_start</attribute>" " <attribute name='action'>app.debug_start</attribute>"
+accels["debug_start"]+ //For Ubuntu... +accels["debug_start"]+ //For Ubuntu...
" </item>" " </item>"
" </section>"
" <section>"
" <item>"
" <attribute name='label' translatable='yes'>_Continue</attribute>"
" <attribute name='action'>app.debug_continue</attribute>"
+accels["debug_continue"]+ //For Ubuntu...
" </item>"
" </section>"
" <section>"
" <item>" " <item>"
" <attribute name='label' translatable='yes'>_Toggle _Breakpoint</attribute>" " <attribute name='label' translatable='yes'>_Toggle _Breakpoint</attribute>"
" <attribute name='action'>app.debug_toggle_breakpoint</attribute>" " <attribute name='action'>app.debug_toggle_breakpoint</attribute>"

7
src/window.cc

@ -6,7 +6,7 @@
//#include "api.h" //#include "api.h"
#include "dialogs.h" #include "dialogs.h"
#include "filesystem.h" #include "filesystem.h"
#include "debug.h" //TODO: remove #include "debug.h"
namespace sigc { namespace sigc {
#ifndef SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE #ifndef SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE
@ -695,6 +695,11 @@ void Window::set_menu_actions() {
auto mark=view->get_source_buffer()->create_source_mark("breakpoint", view->get_buffer()->get_insert()->get_iter()); auto mark=view->get_source_buffer()->create_source_mark("breakpoint", view->get_buffer()->get_insert()->get_iter());
} }
}); });
menu.add_action("debug_continue", [this]() {
if(notebook.get_current_page()!=-1) {
Debug::get().continue_debug();
}
});
menu.add_action("next_tab", [this]() { menu.add_action("next_tab", [this]() {
if(notebook.get_current_page()!=-1) { if(notebook.get_current_page()!=-1) {

Loading…
Cancel
Save