diff --git a/oi/CMakeLists.txt b/oi/CMakeLists.txt index 3754f413..c6112001 100644 --- a/oi/CMakeLists.txt +++ b/oi/CMakeLists.txt @@ -17,6 +17,7 @@ add_library(symbol_service SymbolService.cpp ) target_link_libraries(symbol_service + LLDB drgn_utils Boost::headers diff --git a/oi/SymbolService.cpp b/oi/SymbolService.cpp index 59853879..21eff2d9 100644 --- a/oi/SymbolService.cpp +++ b/oi/SymbolService.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include "oi/DrgnUtils.h" #include "oi/OIParser.h" @@ -106,7 +107,8 @@ static bool isExecutableAddr( return it != end(exeAddrs) && addr >= it->first; } -SymbolService::SymbolService(pid_t pid) : target{pid} { +SymbolService::SymbolService(pid_t pid, Backend back) + : target{pid}, backend{back} { // Update target processes memory map LoadExecutableAddressRange(pid, executableAddrs); if (!loadModules()) { @@ -115,8 +117,8 @@ SymbolService::SymbolService(pid_t pid) : target{pid} { } } -SymbolService::SymbolService(fs::path executablePath) - : target{std::move(executablePath)} { +SymbolService::SymbolService(fs::path executablePath, Backend back) + : target{std::move(executablePath)}, backend{back} { if (!loadModules()) { throw std::runtime_error("Failed to load modules for executable " + executablePath.string()); @@ -131,6 +133,15 @@ SymbolService::~SymbolService() { if (prog != nullptr) { drgn_program_destroy(prog); } + + if (lldbTarget) { + lldbDebugger.DeleteTarget(lldbTarget); + } + + if (lldbDebugger) { + lldb::SBDebugger::Destroy(lldbDebugger); + lldb::SBDebugger::Terminate(); + } } struct ModParams { @@ -432,7 +443,12 @@ std::optional SymbolService::locateBuildID() { struct drgn_program* SymbolService::getDrgnProgram() { if (hardDisableDrgn) { - LOG(ERROR) << "drgn is disabled, refusing to initialize"; + LOG(ERROR) << "drgn/LLDB is disabled, refusing to initialize"; + return nullptr; + } + + if (backend != Backend::DRGN) { + LOG(ERROR) << "drgn is not the selected backend, refusing to initialize"; return nullptr; } @@ -484,6 +500,53 @@ struct drgn_program* SymbolService::getDrgnProgram() { return prog; } +lldb::SBTarget SymbolService::getLLDBTarget() { + if (hardDisableDrgn) { + LOG(ERROR) << "drgn/LLDB is disabled, refusing to initialize"; + return lldb::SBTarget(); + } + + if (backend != Backend::LLDB) { + LOG(ERROR) << "LLDB is not the selected backend, refusing to initialize"; + return lldb::SBTarget(); + } + + bool success = false; + + lldb::SBDebugger::Initialize(); + lldbDebugger = lldb::SBDebugger::Create(false); + BOOST_SCOPE_EXIT_ALL(&) { + if (!success) { + lldb::SBDebugger::Destroy(lldbDebugger); + lldb::SBDebugger::Terminate(); + } + }; + + switch (target.index()) { + case 0: { + auto pid = std::get(target); + lldbTarget = lldbDebugger.FindTargetWithProcessID(pid); + if (!lldbTarget) { + LOG(ERROR) << "Failed to find target with PID " << pid; + return lldb::SBTarget(); + } + break; + } + case 1: { + auto path = std::get(target); + lldbTarget = lldbDebugger.CreateTarget(path.c_str()); + if (!lldbTarget) { + LOG(ERROR) << "Failed to create target from " << path; + return lldb::SBTarget(); + } + break; + } + } + + success = true; + return lldbTarget; +} + /* * Although 'parseFormalParam' has an all-encompassing sounding name, its sole * task is to extract the location information for this parameter if any exist. diff --git a/oi/SymbolService.h b/oi/SymbolService.h index e12c93a0..ee0a593f 100644 --- a/oi/SymbolService.h +++ b/oi/SymbolService.h @@ -16,6 +16,9 @@ #pragma once #include +#include +#include +#include #include #include #include @@ -38,14 +41,16 @@ struct SymbolInfo { }; class SymbolService { + enum class Backend { DRGN, LLDB }; public: - SymbolService(pid_t); - SymbolService(std::filesystem::path); + SymbolService(pid_t, Backend = Backend::DRGN); + SymbolService(std::filesystem::path, Backend = Backend::DRGN); SymbolService(const SymbolService&) = delete; SymbolService& operator=(const SymbolService&) = delete; ~SymbolService(); struct drgn_program* getDrgnProgram(); + lldb::SBTarget getLLDBTarget(); std::optional locateBuildID(); std::optional locateSymbol(const std::string&, @@ -70,8 +75,11 @@ class SymbolService { private: std::variant target; + Backend backend; struct Dwfl* dwfl{nullptr}; struct drgn_program* prog{nullptr}; + lldb::SBDebugger lldbDebugger{}; + lldb::SBTarget lldbTarget{}; bool loadModules(); bool loadModulesFromPid(pid_t);