瀏覽代碼

HackStudio: Add ability to attach debugger to a running process

Itamar 2 年之前
父節點
當前提交
ff6fb2cb10

+ 27 - 11
Userland/DevTools/HackStudio/Debugger/Debugger.cpp

@@ -112,14 +112,8 @@ void Debugger::stop()
 
 void Debugger::start()
 {
-
-    auto child_setup_callback = [this]() {
-        if (m_child_setup_callback)
-            return m_child_setup_callback();
-        return ErrorOr<void> {};
-    };
-    m_debug_session = Debug::DebugSession::exec_and_attach(m_executable_path, m_source_root, move(child_setup_callback));
-    VERIFY(!!m_debug_session);
+    auto [debug_session, initial_state] = create_debug_session();
+    m_debug_session = move(debug_session);
 
     for (auto const& breakpoint : m_breakpoints) {
         dbgln("inserting breakpoint at: {}:{}", breakpoint.file_path, breakpoint.line_number);
@@ -132,14 +126,36 @@ void Debugger::start()
         }
     }
 
-    debugger_loop();
+    debugger_loop(initial_state);
+}
+
+Debugger::CreateDebugSessionResult Debugger::create_debug_session()
+{
+    if (!m_executable_path.is_null()) {
+        auto child_setup_callback = [this]() {
+            if (m_child_setup_callback)
+                return m_child_setup_callback();
+            return ErrorOr<void> {};
+        };
+        auto debug_session = Debug::DebugSession::exec_and_attach(m_executable_path, m_source_root, move(child_setup_callback));
+        VERIFY(!!debug_session);
+        return { debug_session.release_nonnull(), Debug::DebugSession::Running };
+    }
+
+    if (m_pid_to_attach.has_value()) {
+        auto debug_session = Debug::DebugSession::attach(m_pid_to_attach.value(), m_source_root);
+        VERIFY(!!debug_session);
+        return { debug_session.release_nonnull(), Debug::DebugSession::Stopped };
+    }
+
+    VERIFY_NOT_REACHED();
 }
 
-int Debugger::debugger_loop()
+int Debugger::debugger_loop(Debug::DebugSession::DesiredInitialDebugeeState initial_state)
 {
     VERIFY(m_debug_session);
 
-    m_debug_session->run(Debug::DebugSession::DesiredInitialDebugeeState::Running, [this](Debug::DebugSession::DebugBreakReason reason, Optional<PtraceRegisters> optional_regs) {
+    m_debug_session->run(initial_state, [this](Debug::DebugSession::DebugBreakReason reason, Optional<PtraceRegisters> optional_regs) {
         if (reason == Debug::DebugSession::DebugBreakReason::Exited) {
             dbgln("Program exited");
             m_on_exit_callback();

+ 9 - 1
Userland/DevTools/HackStudio/Debugger/Debugger.h

@@ -38,6 +38,7 @@ public:
 
     void set_executable_path(DeprecatedString const& path) { m_executable_path = path; }
     void set_source_root(DeprecatedString const& source_root) { m_source_root = source_root; }
+    void set_pid_to_attach(pid_t pid) { m_pid_to_attach = pid; }
 
     Debug::DebugSession* session() { return m_debug_session.ptr(); }
 
@@ -98,7 +99,7 @@ private:
     Debug::DebugInfo::SourcePosition create_source_position(DeprecatedString const& file, size_t line);
 
     void start();
-    int debugger_loop();
+    int debugger_loop(Debug::DebugSession::DesiredInitialDebugeeState);
 
     void remove_temporary_breakpoints();
     void do_step_out(PtraceRegisters const&);
@@ -106,6 +107,12 @@ private:
     void insert_temporary_breakpoint(FlatPtr address);
     void insert_temporary_breakpoint_at_return_address(PtraceRegisters const&);
 
+    struct CreateDebugSessionResult {
+        NonnullOwnPtr<Debug::DebugSession> session;
+        Debug::DebugSession::DesiredInitialDebugeeState initial_state { Debug::DebugSession::Stopped };
+    };
+    CreateDebugSessionResult create_debug_session();
+
     OwnPtr<Debug::DebugSession> m_debug_session;
     DeprecatedString m_source_root;
     DebuggingState m_state;
@@ -117,6 +124,7 @@ private:
     Vector<Debug::DebugInfo::SourcePosition> m_breakpoints;
 
     DeprecatedString m_executable_path;
+    Optional<pid_t> m_pid_to_attach;
 
     Function<HasControlPassedToUser(PtraceRegisters const&)> m_on_stopped_callback;
     Function<void()> m_on_continue_callback;

+ 15 - 0
Userland/DevTools/HackStudio/HackStudioWidget.cpp

@@ -1878,6 +1878,21 @@ void HackStudioWidget::open_coredump(DeprecatedString const& coredump_path)
     }
 }
 
+void HackStudioWidget::debug_process(pid_t pid)
+{
+    open_project("/usr/src/serenity");
+    Debugger::the().set_pid_to_attach(pid);
+
+    m_debugger_thread = Threading::Thread::construct(Debugger::start_static);
+    m_debugger_thread->start();
+    m_stop_action->set_enabled(true);
+    m_run_action->set_enabled(false);
+
+    for (auto& editor_wrapper : m_all_editor_wrappers) {
+        editor_wrapper.set_debug_mode(true);
+    }
+}
+
 void HackStudioWidget::for_each_open_file(Function<void(ProjectFile const&)> func)
 {
     for (auto& open_file : m_open_files) {

+ 1 - 0
Userland/DevTools/HackStudio/HackStudioWidget.h

@@ -76,6 +76,7 @@ public:
     };
 
     void open_coredump(DeprecatedString const& coredump_path);
+    void debug_process(pid_t pid);
     void for_each_open_file(Function<void(ProjectFile const&)>);
     bool semantic_syntax_highlighting_is_enabled() const;