Skip to content

Commit

Permalink
Implement SymbolService::getLLDBTarget()
Browse files Browse the repository at this point in the history
  • Loading branch information
ttreyer committed Dec 19, 2023
1 parent 1d752ca commit 0c3dde8
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 6 deletions.
1 change: 1 addition & 0 deletions oi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ add_library(symbol_service
SymbolService.cpp
)
target_link_libraries(symbol_service
LLDB
drgn_utils

Boost::headers
Expand Down
71 changes: 67 additions & 4 deletions oi/SymbolService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <cassert>
#include <cstring>
#include <fstream>
#include <lldb/API/LLDB.h>

#include "oi/DrgnUtils.h"
#include "oi/OIParser.h"
Expand Down Expand Up @@ -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()) {
Expand All @@ -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());
Expand All @@ -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 {
Expand Down Expand Up @@ -432,7 +443,12 @@ std::optional<std::string> 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;
}

Expand Down Expand Up @@ -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<pid_t>(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<fs::path>(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.
Expand Down
12 changes: 10 additions & 2 deletions oi/SymbolService.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
#pragma once

#include <filesystem>
#include <lldb/API/SBDebugger.h>
#include <lldb/API/SBTarget.h>
#include <lldb/API/SBType.h>
#include <memory>
#include <optional>
#include <string>
Expand All @@ -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<std::string> locateBuildID();
std::optional<SymbolInfo> locateSymbol(const std::string&,
Expand All @@ -70,8 +75,11 @@ class SymbolService {

private:
std::variant<pid_t, std::filesystem::path> target;
Backend backend;
struct Dwfl* dwfl{nullptr};
struct drgn_program* prog{nullptr};
lldb::SBDebugger lldbDebugger{};
lldb::SBTarget lldbTarget{};

bool loadModules();
bool loadModulesFromPid(pid_t);
Expand Down

0 comments on commit 0c3dde8

Please sign in to comment.