aboutsummaryrefslogtreecommitdiff
path: root/src/debugger/debugger.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/debugger/debugger.cpp')
-rw-r--r--src/debugger/debugger.cpp77
1 files changed, 77 insertions, 0 deletions
diff --git a/src/debugger/debugger.cpp b/src/debugger/debugger.cpp
index cd1eac1..97af0e1 100644
--- a/src/debugger/debugger.cpp
+++ b/src/debugger/debugger.cpp
@@ -7,6 +7,8 @@
#include <algorithm>
#include <array>
+#include <cctype>
+#include <cstdio>
#include <set>
#include <source_location>
@@ -87,6 +89,79 @@ namespace Hsdbg
return text != nullptr && text[0] != '\0' ? std::string(text) : std::string(fallback);
}
+ // runs a command and hands back its stdout, trimmed; empty if it could
+ // not be spawned (used to ask the toolchain where it lives)
+ auto capture_command(const char* command) -> std::string
+ {
+#ifdef HSDBG_WINDOWS
+ FILE* pipe = _popen(command, "r");
+#else
+ FILE* pipe = popen(command, "r");
+#endif
+ if (pipe == nullptr)
+ return {};
+
+ std::string output;
+ std::array<char, 256> chunk{};
+
+ while (std::fgets(chunk.data(), static_cast<int>(chunk.size()), pipe) != nullptr)
+ output += chunk.data();
+
+#ifdef HSDBG_WINDOWS
+ _pclose(pipe);
+#else
+ pclose(pipe);
+#endif
+
+ while (!output.empty() && std::isspace(static_cast<unsigned char>(output.back())) != 0)
+ output.pop_back();
+
+ return output;
+ }
+
+ // rust ships lldb data formatters (the same ones rust-lldb sources) that
+ // teach lldb how to print String, Vec, Option, enums and friends. without
+ // them those show as raw structs, so pull them in if a toolchain is around.
+ // harmless for c/c++ targets, and a no-op if lldb has no python scripting
+ auto load_rust_formatters(lldb::SBDebugger& debugger) -> void
+ {
+ const std::string sysroot = capture_command("rustc --print sysroot 2>/dev/null");
+
+ if (sysroot.empty())
+ return;
+
+ const std::filesystem::path etc =
+ std::filesystem::path(sysroot) / "lib" / "rustlib" / "etc";
+
+ std::error_code error;
+ if (!std::filesystem::exists(etc / "lldb_commands", error))
+ return;
+
+ lldb::SBCommandInterpreter interpreter = debugger.GetCommandInterpreter();
+ lldb::SBCommandReturnObject result;
+
+ const std::string import =
+ std::format("command script import \"{}\"", (etc / "lldb_lookup.py").string());
+ interpreter.HandleCommand(import.c_str(), result);
+
+ if (!result.Succeeded())
+ {
+ Log::warn("debugger: rust formatters unavailable ({})",
+ text_or(result.GetError(), "lldb has no python scripting"));
+ return;
+ }
+
+ const std::string source =
+ std::format("command source \"{}\"", (etc / "lldb_commands").string());
+ interpreter.HandleCommand(source.c_str(), result);
+
+ if (result.Succeeded())
+ Log::info("debugger: loaded rust type formatters from {}", etc.string());
+ else
+ Log::warn("debugger: could not load rust formatters ({})",
+ text_or(result.GetError(), "unknown error"));
+ }
+
auto path_of(lldb::SBFileSpec spec) -> std::filesystem::path
{
if (!spec.IsValid())
@@ -463,6 +538,8 @@ namespace Hsdbg
m_session->listener = lldb::SBListener("hsdbg");
Log::info("debugger: {}", lldb::SBDebugger::GetVersionString());
+
+ load_rust_formatters(m_session->debugger);
}
Debugger::~Debugger()