1 #pragma once
2 #include "mutex.hpp"
3 #include <boost/filesystem.hpp>
4 #include <list>
5 #include <lldb/API/LLDB.h>
6 #include <thread>
7 #include <tuple>
8 
9 namespace Debug {
10   class LLDB {
11   public:
12     class Frame {
13     public:
14       uint32_t index;
15       std::string module_filename;
16       boost::filesystem::path file_path;
17       std::string function_name;
18       int line_nr;
19       int line_index;
20     };
21     class Variable {
22     public:
23       uint32_t thread_index_id;
24       uint32_t frame_index;
25       std::string name;
26       std::function<std::string()> get_value;
27       bool declaration_found;
28       boost::filesystem::path file_path;
29       int line_nr;
30       int line_index;
31     };
32 
33   private:
34     LLDB();
35     void destroy_() EXCLUDES(mutex);
36 
37     static bool initialized;
38 
39   public:
get()40     static LLDB &get() {
41       static LLDB instance;
42       return instance;
43     }
44 
45     /// Must be called before application terminates (cannot be placed in destructor sadly)
destroy()46     static void destroy() {
47       if(initialized)
48         get().destroy_();
49     }
50 
51     std::list<std::function<void(const lldb::SBProcess &)>> on_start;
52     /// The handlers are not run in the main loop.
53     std::list<std::function<void(int exit_status)>> on_exit;
54     /// The handlers are not run in the main loop.
55     std::list<std::function<void(const lldb::SBEvent &)>> on_event;
56 
57     Mutex mutex;
58 
59     void start(const std::string &command, const boost::filesystem::path &path = "",
60                const std::vector<std::pair<boost::filesystem::path, int>> &breakpoints = {},
61                const std::vector<std::string> &startup_commands = {}, const std::string &remote_host = "") EXCLUDES(mutex);
62     void continue_debug() EXCLUDES(mutex); //can't use continue as function name
63     void stop() EXCLUDES(mutex);
64     void kill() EXCLUDES(mutex);
65     void step_over() EXCLUDES(mutex);
66     void step_into() EXCLUDES(mutex);
67     void step_out() EXCLUDES(mutex);
68     std::pair<std::string, std::string> run_command(const std::string &command) EXCLUDES(mutex);
69     std::vector<Frame> get_backtrace() EXCLUDES(mutex);
70     std::vector<Variable> get_variables() EXCLUDES(mutex);
71     void select_frame(uint32_t frame_index, uint32_t thread_index_id = 0) EXCLUDES(mutex);
72 
73     /// Get value using variable name and location
74     std::string get_value(const std::string &variable_name, const boost::filesystem::path &file_path, unsigned int line_nr, unsigned int line_index) EXCLUDES(mutex);
75     /// Get value from expression
76     std::string get_value(const std::string &expression) EXCLUDES(mutex);
77     std::string get_return_value(const boost::filesystem::path &file_path, unsigned int line_nr, unsigned int line_index) EXCLUDES(mutex);
78 
79     bool is_invalid() EXCLUDES(mutex);
80     bool is_stopped() EXCLUDES(mutex);
81     bool is_running() EXCLUDES(mutex);
82 
83     void add_breakpoint(const boost::filesystem::path &file_path, int line_nr) EXCLUDES(mutex);
84     void remove_breakpoint(const boost::filesystem::path &file_path, int line_nr, int line_count) EXCLUDES(mutex);
85 
86     void write(const std::string &buffer) EXCLUDES(mutex);
87 
88   private:
89     std::tuple<std::vector<std::string>, std::string, std::vector<std::string>> parse_run_arguments(const std::string &command);
90 
91     std::unique_ptr<lldb::SBDebugger> debugger GUARDED_BY(mutex);
92     std::unique_ptr<lldb::SBListener> listener GUARDED_BY(mutex);
93     std::unique_ptr<lldb::SBProcess> process GUARDED_BY(mutex);
94     std::thread debug_thread;
95 
96     lldb::StateType state GUARDED_BY(mutex);
97 
98     size_t buffer_size;
99   };
100 } // namespace Debug
101