Skip to content

[lldb/Commands] Add scripting template list command with auto discovery #97273

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions lldb/include/lldb/Core/PluginManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define LLDB_CORE_PLUGINMANAGER_H

#include "lldb/Core/Architecture.h"
#include "lldb/Interpreter/Interfaces/ScriptedInterfaceUsages.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/FileSpec.h"
Expand Down Expand Up @@ -487,6 +488,25 @@ class PluginManager {

static LanguageSet GetAllTypeSystemSupportedLanguagesForExpressions();

// Scripted Interface
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description,
ScriptedInterfaceCreateInstance create_callback,
lldb::ScriptLanguage language,
ScriptedInterfaceUsages usages);

static bool UnregisterPlugin(ScriptedInterfaceCreateInstance create_callback);

static uint32_t GetNumScriptedInterfaces();

static llvm::StringRef GetScriptedInterfaceNameAtIndex(uint32_t idx);

static llvm::StringRef GetScriptedInterfaceDescriptionAtIndex(uint32_t idx);

static lldb::ScriptLanguage GetScriptedInterfaceLanguageAtIndex(uint32_t idx);

static ScriptedInterfaceUsages
GetScriptedInterfaceUsagesAtIndex(uint32_t idx);

// REPL
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description,
REPLCreateInstance create_callback,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#ifndef LLDB_INTERPRETER_INTERFACES_SCRIPTEDINTERFACE_H
#define LLDB_INTERPRETER_INTERFACES_SCRIPTEDINTERFACE_H

#include "ScriptedInterfaceUsages.h"

#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
Expand Down Expand Up @@ -68,6 +70,11 @@ class ScriptedInterface {
return true;
}

static bool CreateInstance(lldb::ScriptLanguage language,
ScriptedInterfaceUsages usages) {
return false;
}

protected:
StructuredData::GenericSP m_object_instance_sp;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//===-- ScriptedInterfaceUsages.h ---------------------------- -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLDB_INTERPRETER_SCRIPTEDINTERFACEUSAGES_H
#define LLDB_INTERPRETER_SCRIPTEDINTERFACEUSAGES_H

#include "lldb/lldb-types.h"

#include "lldb/Utility/Stream.h"
#include "llvm/ADT/StringRef.h"

namespace lldb_private {
class ScriptedInterfaceUsages {
public:
ScriptedInterfaceUsages() = default;
ScriptedInterfaceUsages(const std::vector<llvm::StringRef> ci_usages,
const std::vector<llvm::StringRef> sbapi_usages)
: m_command_interpreter_usages(ci_usages), m_sbapi_usages(sbapi_usages) {}

const std::vector<llvm::StringRef> &GetCommandInterpreterUsages() const {
return m_command_interpreter_usages;
}

const std::vector<llvm::StringRef> &GetSBAPIUsages() const {
return m_sbapi_usages;
}

enum class UsageKind { CommandInterpreter, API };

void Dump(Stream &s, UsageKind kind) const;

private:
std::vector<llvm::StringRef> m_command_interpreter_usages;
std::vector<llvm::StringRef> m_sbapi_usages;
};
} // namespace lldb_private

#endif // LLDB_INTERPRETER_SCRIPTEDINTERFACEUSAGES_H
3 changes: 3 additions & 0 deletions lldb/include/lldb/lldb-private-interfaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class Value;
} // namespace llvm

namespace lldb_private {
class ScriptedInterfaceUsages;
typedef lldb::ABISP (*ABICreateInstance)(lldb::ProcessSP process_sp,
const ArchSpec &arch);
typedef std::unique_ptr<Architecture> (*ArchitectureCreateInstance)(
Expand Down Expand Up @@ -124,6 +125,8 @@ typedef lldb::REPLSP (*REPLCreateInstance)(Status &error,
lldb::LanguageType language,
Debugger *debugger, Target *target,
const char *repl_options);
typedef bool (*ScriptedInterfaceCreateInstance)(lldb::ScriptLanguage language,
ScriptedInterfaceUsages usages);
typedef int (*ComparisonFunction)(const void *, const void *);
typedef void (*DebuggerInitializeCallback)(Debugger &debugger);
/// Trace
Expand Down
126 changes: 124 additions & 2 deletions lldb/source/Commands/CommandObjectScripting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@

#include "CommandObjectScripting.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandOptionArgumentTable.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/Interfaces/ScriptedInterfaceUsages.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Utility/Args.h"
Expand Down Expand Up @@ -127,9 +129,126 @@ class CommandObjectScriptingRun : public CommandObjectRaw {
CommandOptions m_options;
};

#pragma mark CommandObjectMultiwordScripting
#define LLDB_OPTIONS_scripting_template_list
#include "CommandOptions.inc"

class CommandObjectScriptingTemplateList : public CommandObjectParsed {
public:
CommandObjectScriptingTemplateList(CommandInterpreter &interpreter)
: CommandObjectParsed(
interpreter, "scripting template list",
"List all the available scripting extension templates. ",
"scripting template list [--language <scripting-language> --]") {}

~CommandObjectScriptingTemplateList() override = default;

Options *GetOptions() override { return &m_options; }

class CommandOptions : public Options {
public:
CommandOptions() = default;
~CommandOptions() override = default;
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
ExecutionContext *execution_context) override {
Status error;
const int short_option = m_getopt_table[option_idx].val;

// CommandObjectMultiwordScripting
switch (short_option) {
case 'l':
m_language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum(
option_arg, GetDefinitions()[option_idx].enum_values,
eScriptLanguageNone, error);
if (!error.Success())
error.SetErrorStringWithFormatv(
"unrecognized value for language '{0}'", option_arg);
break;
default:
llvm_unreachable("Unimplemented option");
}

return error;
}

void OptionParsingStarting(ExecutionContext *execution_context) override {
m_language = lldb::eScriptLanguageDefault;
}

llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
return llvm::ArrayRef(g_scripting_template_list_options);
}

lldb::ScriptLanguage m_language = lldb::eScriptLanguageDefault;
};

protected:
void DoExecute(Args &command, CommandReturnObject &result) override {
Stream &s = result.GetOutputStream();
s.Printf("Available scripted extension templates:");

auto print_field = [&s](llvm::StringRef key, llvm::StringRef value) {
if (!value.empty()) {
s.IndentMore();
s.Indent();
s << key << ": " << value << '\n';
s.IndentLess();
}
};

size_t num_listed_interface = 0;
size_t num_templates = PluginManager::GetNumScriptedInterfaces();
for (size_t i = 0; i < num_templates; i++) {
llvm::StringRef plugin_name =
PluginManager::GetScriptedInterfaceNameAtIndex(i);
if (plugin_name.empty())
break;

lldb::ScriptLanguage lang =
PluginManager::GetScriptedInterfaceLanguageAtIndex(i);
if (lang != m_options.m_language)
continue;

if (!num_listed_interface)
s.EOL();

num_listed_interface++;

llvm::StringRef desc =
PluginManager::GetScriptedInterfaceDescriptionAtIndex(i);
ScriptedInterfaceUsages usages =
PluginManager::GetScriptedInterfaceUsagesAtIndex(i);

print_field("Name", plugin_name);
print_field("Language", ScriptInterpreter::LanguageToString(lang));
print_field("Description", desc);
usages.Dump(s, ScriptedInterfaceUsages::UsageKind::API);
usages.Dump(s, ScriptedInterfaceUsages::UsageKind::CommandInterpreter);

if (i != num_templates - 1)
s.EOL();
}

if (!num_listed_interface)
s << " None\n";
}

private:
CommandOptions m_options;
};

class CommandObjectMultiwordScriptingTemplate : public CommandObjectMultiword {
public:
CommandObjectMultiwordScriptingTemplate(CommandInterpreter &interpreter)
: CommandObjectMultiword(
interpreter, "scripting template",
"Commands for operating on the scripting templates.",
"scripting template [<subcommand-options>]") {
LoadSubCommand(
"list",
CommandObjectSP(new CommandObjectScriptingTemplateList(interpreter)));
}

~CommandObjectMultiwordScriptingTemplate() override = default;
};

CommandObjectMultiwordScripting::CommandObjectMultiwordScripting(
CommandInterpreter &interpreter)
Expand All @@ -139,6 +258,9 @@ CommandObjectMultiwordScripting::CommandObjectMultiwordScripting(
"scripting <subcommand> [<subcommand-options>]") {
LoadSubCommand("run",
CommandObjectSP(new CommandObjectScriptingRun(interpreter)));
LoadSubCommand("template",
CommandObjectSP(
new CommandObjectMultiwordScriptingTemplate(interpreter)));
}

CommandObjectMultiwordScripting::~CommandObjectMultiwordScripting() = default;
6 changes: 6 additions & 0 deletions lldb/source/Commands/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,12 @@ let Command = "scripting run" in {
" language. If none is specific the default scripting language is used.">;
}

let Command = "scripting template list" in {
def scripting_template_list_language : Option<"language", "l">,
EnumArg<"ScriptLang">, Desc<"Specify the scripting "
" language. If none is specified the default scripting language is used.">;
}

let Command = "source info" in {
def source_info_count : Option<"count", "c">, Arg<"Count">,
Desc<"The number of line entries to display.">;
Expand Down
65 changes: 65 additions & 0 deletions lldb/source/Core/PluginManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1505,6 +1505,70 @@ LanguageSet PluginManager::GetAllTypeSystemSupportedLanguagesForExpressions() {
return all;
}

#pragma mark ScriptedInterfaces

struct ScriptedInterfaceInstance
: public PluginInstance<ScriptedInterfaceCreateInstance> {
ScriptedInterfaceInstance(llvm::StringRef name, llvm::StringRef description,
ScriptedInterfaceCreateInstance create_callback,
lldb::ScriptLanguage language,
ScriptedInterfaceUsages usages)
: PluginInstance<ScriptedInterfaceCreateInstance>(name, description,
create_callback),
language(language), usages(usages) {}

lldb::ScriptLanguage language;
ScriptedInterfaceUsages usages;
};

typedef PluginInstances<ScriptedInterfaceInstance> ScriptedInterfaceInstances;

static ScriptedInterfaceInstances &GetScriptedInterfaceInstances() {
static ScriptedInterfaceInstances g_instances;
return g_instances;
}

bool PluginManager::RegisterPlugin(
llvm::StringRef name, llvm::StringRef description,
ScriptedInterfaceCreateInstance create_callback,
lldb::ScriptLanguage language, ScriptedInterfaceUsages usages) {
return GetScriptedInterfaceInstances().RegisterPlugin(
name, description, create_callback, language, usages);
}

bool PluginManager::UnregisterPlugin(
ScriptedInterfaceCreateInstance create_callback) {
return GetScriptedInterfaceInstances().UnregisterPlugin(create_callback);
}

uint32_t PluginManager::GetNumScriptedInterfaces() {
return GetScriptedInterfaceInstances().GetInstances().size();
}

llvm::StringRef PluginManager::GetScriptedInterfaceNameAtIndex(uint32_t index) {
return GetScriptedInterfaceInstances().GetNameAtIndex(index);
}

llvm::StringRef
PluginManager::GetScriptedInterfaceDescriptionAtIndex(uint32_t index) {
return GetScriptedInterfaceInstances().GetDescriptionAtIndex(index);
}

lldb::ScriptLanguage
PluginManager::GetScriptedInterfaceLanguageAtIndex(uint32_t idx) {
const auto &instances = GetScriptedInterfaceInstances().GetInstances();
return idx < instances.size() ? instances[idx].language
: ScriptLanguage::eScriptLanguageNone;
}

ScriptedInterfaceUsages
PluginManager::GetScriptedInterfaceUsagesAtIndex(uint32_t idx) {
const auto &instances = GetScriptedInterfaceInstances().GetInstances();
if (idx >= instances.size())
return {};
return instances[idx].usages;
}

#pragma mark REPL

struct REPLInstance : public PluginInstance<REPLCreateInstance> {
Expand Down Expand Up @@ -1565,6 +1629,7 @@ void PluginManager::DebuggerInitialize(Debugger &debugger) {
GetOperatingSystemInstances().PerformDebuggerCallback(debugger);
GetStructuredDataPluginInstances().PerformDebuggerCallback(debugger);
GetTracePluginInstances().PerformDebuggerCallback(debugger);
GetScriptedInterfaceInstances().PerformDebuggerCallback(debugger);
}

// This is the preferred new way to register plugin specific settings. e.g.
Expand Down
4 changes: 4 additions & 0 deletions lldb/source/Interpreter/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ lldb_tablegen(InterpreterPropertiesEnum.inc -gen-lldb-property-enum-defs
SOURCE InterpreterProperties.td
TARGET LLDBInterpreterPropertiesEnumGen)

add_subdirectory(Interfaces)

add_lldb_library(lldbInterpreter NO_PLUGIN_DEPENDENCIES
CommandAlias.cpp
CommandHistory.cpp
Expand Down Expand Up @@ -54,6 +56,7 @@ add_lldb_library(lldbInterpreter NO_PLUGIN_DEPENDENCIES
ScriptInterpreter.cpp

LINK_LIBS
lldbInterpreterInterfaces
lldbCommands
lldbCore
lldbDataFormatters
Expand All @@ -66,6 +69,7 @@ add_lldb_library(lldbInterpreter NO_PLUGIN_DEPENDENCIES
)

add_dependencies(lldbInterpreter
lldbInterpreterInterfaces
LLDBInterpreterPropertiesGen
LLDBInterpreterPropertiesEnumGen)

10 changes: 10 additions & 0 deletions lldb/source/Interpreter/Interfaces/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
add_lldb_library(lldbInterpreterInterfaces NO_PLUGIN_DEPENDENCIES
ScriptedInterfaceUsages.cpp

LINK_LIBS
lldbUtility

LINK_COMPONENTS
Support
)

Loading
Loading