[Renderscript] Add commands for scriptgroup interaction.

This commit hooks the nofity function that signals script group
compilation.  By tracking scriptgroups compiled at runtine, users
are able to place breakpoints by script group name.  Breakpoints
will be placed on the kernels forming the group.

llvm-svn: 285902
This commit is contained in:
Aidan Dodds 2016-11-03 13:20:37 +00:00
parent 8b70e2631c
commit 21fed052e0
5 changed files with 610 additions and 4 deletions

View File

@ -2,6 +2,7 @@ add_lldb_library(lldbPluginRenderScriptRuntime
RenderScriptRuntime.cpp
RenderScriptExpressionOpts.cpp
RenderScriptx86ABIFixups.cpp
RenderScriptScriptGroup.cpp
)
if(NOT LLDB_BUILT_STANDALONE)

View File

@ -14,6 +14,7 @@
// Project includes
#include "RenderScriptRuntime.h"
#include "RenderScriptScriptGroup.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/ConstString.h"
@ -31,11 +32,13 @@
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
@ -475,6 +478,26 @@ bool ParseCoordinate(llvm::StringRef coord_s, RSCoordinate &coord) {
return get_index(0, coord.x) && get_index(1, coord.y) &&
get_index(2, coord.z);
}
bool SkipPrologue(lldb::ModuleSP &module, Address &addr) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
SymbolContext sc;
uint32_t resolved_flags =
module->ResolveSymbolContextForAddress(addr, eSymbolContextFunction, sc);
if (resolved_flags & eSymbolContextFunction) {
if (sc.function) {
const uint32_t offset = sc.function->GetPrologueByteSize();
ConstString name = sc.GetFunctionName();
if (offset)
addr.Slide(offset);
if (log)
log->Printf("%s: Prologue offset for %s is %" PRIu32, __FUNCTION__,
name.AsCString(), offset);
}
return true;
} else
return false;
}
} // anonymous namespace
// The ScriptDetails class collects data associated with a single script
@ -872,6 +895,80 @@ RSReduceBreakpointResolver::SearchCallback(lldb_private::SearchFilter &filter,
return eCallbackReturnContinue;
}
Searcher::CallbackReturn RSScriptGroupBreakpointResolver::SearchCallback(
SearchFilter &filter, SymbolContext &context, Address *addr,
bool containing) {
if (!m_breakpoint)
return eCallbackReturnContinue;
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
ModuleSP &module = context.module_sp;
if (!module || !IsRenderScriptScriptModule(module))
return Searcher::eCallbackReturnContinue;
std::vector<std::string> names;
m_breakpoint->GetNames(names);
if (names.empty())
return eCallbackReturnContinue;
for (auto &name : names) {
const RSScriptGroupDescriptorSP sg = FindScriptGroup(ConstString(name));
if (!sg) {
if (log)
log->Printf("%s: could not find script group for %s", __FUNCTION__,
name.c_str());
continue;
}
if (log)
log->Printf("%s: Found ScriptGroup for %s", __FUNCTION__, name.c_str());
for (const RSScriptGroupDescriptor::Kernel &k : sg->m_kernels) {
if (log) {
log->Printf("%s: Adding breakpoint for %s", __FUNCTION__,
k.m_name.AsCString());
log->Printf("%s: Kernel address 0x%" PRIx64, __FUNCTION__, k.m_addr);
}
const lldb_private::Symbol *sym =
module->FindFirstSymbolWithNameAndType(k.m_name, eSymbolTypeCode);
if (!sym) {
if (log)
log->Printf("%s: Unable to find symbol for %s", __FUNCTION__,
k.m_name.AsCString());
continue;
}
if (log) {
log->Printf("%s: Found symbol name is %s", __FUNCTION__,
sym->GetName().AsCString());
}
auto address = sym->GetAddress();
if (!SkipPrologue(module, address)) {
if (log)
log->Printf("%s: Error trying to skip prologue", __FUNCTION__);
}
bool new_bp;
m_breakpoint->AddLocation(address, &new_bp);
if (log)
log->Printf("%s: Placed %sbreakpoint on %s", __FUNCTION__,
new_bp ? "new " : "", k.m_name.AsCString());
// exit after placing the first breakpoint if we do not intend to stop
// on all kernels making up this script group
if (!m_stop_on_all)
break;
}
}
return eCallbackReturnContinue;
}
void RenderScriptRuntime::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(),
"RenderScript language support", CreateInstance,
@ -1006,7 +1103,15 @@ const RenderScriptRuntime::HookDefn RenderScriptRuntime::s_runtimeHookDefns[] =
"10AllocationE",
0, RenderScriptRuntime::eModuleKindDriver,
&lldb_private::RenderScriptRuntime::CaptureAllocationDestroy},
};
// renderscript script groups
{"rsdDebugHintScriptGroup2", "_ZN7android12renderscript21debugHintScrip"
"tGroup2EPKcjPKPFvPK24RsExpandKernelDriver"
"InfojjjEj",
"_ZN7android12renderscript21debugHintScriptGroup2EPKcjPKPFvPK24RsExpan"
"dKernelDriverInfojjjEj",
0, RenderScriptRuntime::eModuleKindImpl,
&lldb_private::RenderScriptRuntime::CaptureDebugHintScriptGroup2}};
const size_t RenderScriptRuntime::s_runtimeHookCount =
sizeof(s_runtimeHookDefns) / sizeof(s_runtimeHookDefns[0]);
@ -1039,6 +1144,154 @@ void RenderScriptRuntime::HookCallback(RuntimeHook *hook,
}
}
void RenderScriptRuntime::CaptureDebugHintScriptGroup2(
RuntimeHook *hook_info, ExecutionContext &context) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
enum {
eGroupName = 0,
eGroupNameSize,
eKernel,
eKernelCount,
};
std::array<ArgItem, 4> args{{
{ArgItem::ePointer, 0}, // const char *groupName
{ArgItem::eInt32, 0}, // const uint32_t groupNameSize
{ArgItem::ePointer, 0}, // const ExpandFuncTy *kernel
{ArgItem::eInt32, 0}, // const uint32_t kernelCount
}};
if (!GetArgs(context, args.data(), args.size())) {
if (log)
log->Printf("%s - Error while reading the function parameters",
__FUNCTION__);
return;
} else if (log) {
log->Printf("%s - groupName : 0x%" PRIx64, __FUNCTION__,
addr_t(args[eGroupName]));
log->Printf("%s - groupNameSize: %" PRIu64, __FUNCTION__,
uint64_t(args[eGroupNameSize]));
log->Printf("%s - kernel : 0x%" PRIx64, __FUNCTION__,
addr_t(args[eKernel]));
log->Printf("%s - kernelCount : %" PRIu64, __FUNCTION__,
uint64_t(args[eKernelCount]));
}
// parse script group name
ConstString group_name;
{
Error err;
const uint64_t len = uint64_t(args[eGroupNameSize]);
std::unique_ptr<char[]> buffer(new char[uint32_t(len + 1)]);
m_process->ReadMemory(addr_t(args[eGroupName]), buffer.get(), len, err);
buffer.get()[len] = '\0';
if (!err.Success()) {
if (log)
log->Printf("Error reading scriptgroup name from target");
return;
} else {
if (log)
log->Printf("Extracted scriptgroup name %s", buffer.get());
}
// write back the script group name
group_name.SetCString(buffer.get());
}
// create or access existing script group
RSScriptGroupDescriptorSP group;
{
// search for existing script group
for (auto sg : m_scriptGroups) {
if (sg->m_name == group_name) {
group = sg;
break;
}
}
if (!group) {
group.reset(new RSScriptGroupDescriptor);
group->m_name = group_name;
m_scriptGroups.push_back(group);
} else {
// already have this script group
if (log)
log->Printf("Attempt to add duplicate script group %s",
group_name.AsCString());
return;
}
}
assert(group);
const uint32_t target_ptr_size = m_process->GetAddressByteSize();
std::vector<addr_t> kernels;
// parse kernel addresses in script group
for (uint64_t i = 0; i < uint64_t(args[eKernelCount]); ++i) {
RSScriptGroupDescriptor::Kernel kernel;
// extract script group kernel addresses from the target
const addr_t ptr_addr = addr_t(args[eKernel]) + i * target_ptr_size;
uint64_t kernel_addr = 0;
Error err;
size_t read =
m_process->ReadMemory(ptr_addr, &kernel_addr, target_ptr_size, err);
if (!err.Success() || read != target_ptr_size) {
if (log)
log->Printf("Error parsing kernel address %" PRIu64 " in script group",
i);
return;
}
if (log)
log->Printf("Extracted scriptgroup kernel address - 0x%" PRIx64,
kernel_addr);
kernel.m_addr = kernel_addr;
// try to resolve the associated kernel name
if (!ResolveKernelName(kernel.m_addr, kernel.m_name)) {
if (log)
log->Printf("Parsed scriptgroup kernel %" PRIu64 " - 0x%" PRIx64, i,
kernel_addr);
return;
}
// try to find the non '.expand' function
{
const llvm::StringRef expand(".expand");
const llvm::StringRef name_ref = kernel.m_name.GetStringRef();
if (name_ref.endswith(expand)) {
const ConstString base_kernel(name_ref.drop_back(expand.size()));
// verify this function is a valid kernel
if (IsKnownKernel(base_kernel)) {
kernel.m_name = base_kernel;
if (log)
log->Printf("%s - found non expand version '%s'", __FUNCTION__,
base_kernel.GetCString());
}
}
}
// add to a list of script group kernels we know about
group->m_kernels.push_back(kernel);
}
// Resolve any pending scriptgroup breakpoints
{
Target &target = m_process->GetTarget();
const BreakpointList &list = target.GetBreakpointList();
const size_t num_breakpoints = list.GetSize();
if (log)
log->Printf("Resolving %zu breakpoints", num_breakpoints);
for (size_t i = 0; i < num_breakpoints; ++i) {
const BreakpointSP bp = list.GetBreakpointAtIndex(i);
if (bp) {
if (bp->MatchesName(group_name.AsCString())) {
if (log)
log->Printf("Found breakpoint with name %s",
group_name.AsCString());
bp->ResolveBreakpoint();
}
}
}
}
}
void RenderScriptRuntime::CaptureScriptInvokeForEachMulti(
RuntimeHook *hook, ExecutionContext &exe_ctx) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
@ -1332,7 +1585,7 @@ void RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module,
}
Target &target = GetProcess()->GetTarget();
llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine();
const llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine();
if (machine != llvm::Triple::ArchType::x86 &&
machine != llvm::Triple::ArchType::arm &&
@ -1345,7 +1598,11 @@ void RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module,
return;
}
uint32_t target_ptr_size = target.GetArchitecture().GetAddressByteSize();
const uint32_t target_ptr_size =
target.GetArchitecture().GetAddressByteSize();
std::array<bool, s_runtimeHookCount> hook_placed;
hook_placed.fill(false);
for (size_t idx = 0; idx < s_runtimeHookCount; idx++) {
const HookDefn *hook_defn = &s_runtimeHookDefns[idx];
@ -1393,6 +1650,20 @@ void RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module,
module->GetFileSpec().GetFilename().AsCString(),
(uint64_t)hook_defn->version, (uint64_t)addr);
}
hook_placed[idx] = true;
}
// log any unhooked function
if (log) {
for (size_t i = 0; i < hook_placed.size(); ++i) {
if (hook_placed[i])
continue;
const HookDefn &hook_defn = s_runtimeHookDefns[i];
if (hook_defn.kind != kind)
continue;
log->Printf("%s - function %s was not hooked", __FUNCTION__,
hook_defn.name);
}
}
}
@ -2594,7 +2865,10 @@ bool RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp) {
break;
}
case eModuleKindImpl: {
m_libRSCpuRef = module_sp;
if (!m_libRSCpuRef) {
m_libRSCpuRef = module_sp;
LoadRuntimeHooks(m_libRSCpuRef, RenderScriptRuntime::eModuleKindImpl);
}
break;
}
case eModuleKindLibRS: {
@ -3535,6 +3809,45 @@ bool RenderScriptRuntime::PlaceBreakpointOnKernel(TargetSP target,
return true;
}
BreakpointSP
RenderScriptRuntime::CreateScriptGroupBreakpoint(const ConstString &name,
bool stop_on_all) {
Log *log(
GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
if (!m_filtersp) {
if (log)
log->Printf("%s - error, no breakpoint search filter set.", __FUNCTION__);
return nullptr;
}
BreakpointResolverSP resolver_sp(new RSScriptGroupBreakpointResolver(
nullptr, name, m_scriptGroups, stop_on_all));
BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(
m_filtersp, resolver_sp, false, false, false);
// Give RS breakpoints a specific name, so the user can manipulate them as a
// group.
Error err;
if (!bp->AddName(name.AsCString(), err))
if (log)
log->Printf("%s - error setting break name, '%s'.", __FUNCTION__,
err.AsCString());
// ask the breakpoint to resolve itself
bp->ResolveBreakpoint();
return bp;
}
bool RenderScriptRuntime::PlaceBreakpointOnScriptGroup(TargetSP target,
Stream &strm,
const ConstString &name,
bool multi) {
InitSearchFilter(target);
BreakpointSP bp = CreateScriptGroupBreakpoint(name, multi);
if (bp)
bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false);
return bool(bp);
}
bool RenderScriptRuntime::PlaceBreakpointOnReduction(TargetSP target,
Stream &messages,
const char *reduce_name,
@ -3617,6 +3930,32 @@ RenderScriptRuntime::CreateAllocation(addr_t address) {
return m_allocations.back().get();
}
bool RenderScriptRuntime::ResolveKernelName(lldb::addr_t kernel_addr,
ConstString &name) {
Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS);
Target &target = GetProcess()->GetTarget();
Address resolved;
// RenderScript module
if (!target.GetSectionLoadList().ResolveLoadAddress(kernel_addr, resolved)) {
if (log)
log->Printf("%s: unable to resolve 0x%" PRIx64 " to a loaded symbol",
__FUNCTION__, kernel_addr);
return false;
}
Symbol *sym = resolved.CalculateSymbolContextSymbol();
if (!sym)
return false;
name = sym->GetName();
assert(IsRenderScriptModule(resolved.CalculateSymbolContextModule()));
if (log)
log->Printf("%s: 0x%" PRIx64 " resolved to the symbol '%s'", __FUNCTION__,
kernel_addr, name.GetCString());
return true;
}
void RSModuleDescriptor::Dump(Stream &strm) const {
int indent = strm.GetIndentLevel();
@ -4636,6 +4975,8 @@ public:
"allocation",
CommandObjectSP(
new CommandObjectRenderScriptRuntimeAllocation(interpreter)));
LoadSubCommand("scriptgroup",
NewCommandObjectRenderScriptScriptGroup(interpreter));
LoadSubCommand(
"reduction",
CommandObjectSP(

View File

@ -36,10 +36,13 @@ class RSModuleDescriptor;
struct RSGlobalDescriptor;
struct RSKernelDescriptor;
struct RSReductionDescriptor;
struct RSScriptGroupDescriptor;
typedef std::shared_ptr<RSModuleDescriptor> RSModuleDescriptorSP;
typedef std::shared_ptr<RSGlobalDescriptor> RSGlobalDescriptorSP;
typedef std::shared_ptr<RSKernelDescriptor> RSKernelDescriptorSP;
typedef std::shared_ptr<RSScriptGroupDescriptor> RSScriptGroupDescriptorSP;
struct RSCoordinate {
uint32_t x, y, z;
@ -227,6 +230,61 @@ public:
std::string m_resname;
};
struct RSScriptGroupDescriptor {
struct Kernel {
ConstString m_name;
lldb::addr_t m_addr;
};
ConstString m_name;
std::vector<Kernel> m_kernels;
};
typedef std::vector<RSScriptGroupDescriptorSP> RSScriptGroupList;
class RSScriptGroupBreakpointResolver : public BreakpointResolver {
public:
RSScriptGroupBreakpointResolver(Breakpoint *bp, const ConstString &name,
const RSScriptGroupList &groups,
bool stop_on_all)
: BreakpointResolver(bp, BreakpointResolver::NameResolver),
m_group_name(name), m_script_groups(groups),
m_stop_on_all(stop_on_all) {}
void GetDescription(Stream *strm) override {
if (strm)
strm->Printf("RenderScript ScriptGroup breakpoint for '%s'",
m_group_name.AsCString());
}
void Dump(Stream *s) const override {}
Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
SymbolContext &context, Address *addr,
bool containing) override;
Searcher::Depth GetDepth() override { return Searcher::eDepthModule; }
lldb::BreakpointResolverSP
CopyForBreakpoint(Breakpoint &breakpoint) override {
lldb::BreakpointResolverSP ret_sp(new RSScriptGroupBreakpointResolver(
&breakpoint, m_group_name, m_script_groups, m_stop_on_all));
return ret_sp;
}
protected:
const RSScriptGroupDescriptorSP
FindScriptGroup(const ConstString &name) const {
for (auto sg : m_script_groups) {
if (ConstString::Compare(sg->m_name, name) == 0)
return sg;
}
return RSScriptGroupDescriptorSP();
}
ConstString m_group_name;
const RSScriptGroupList &m_script_groups;
bool m_stop_on_all;
};
} // namespace lldb_renderscript
class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime {
@ -304,6 +362,9 @@ public:
const lldb_renderscript::RSCoordinate *coords = nullptr,
int kernel_types = ~(0));
bool PlaceBreakpointOnScriptGroup(lldb::TargetSP target, Stream &strm,
const ConstString &name, bool stop_on_all);
void SetBreakAllKernels(bool do_break, lldb::TargetSP target);
void Status(Stream &strm) const;
@ -320,6 +381,18 @@ public:
void Initiate();
const lldb_renderscript::RSScriptGroupList &GetScriptGroups() const {
return m_scriptGroups;
};
bool IsKnownKernel(const ConstString &name) {
for (const auto &module : m_rsmodules)
for (const auto &kernel : module->m_kernels)
if (kernel.m_name == name)
return true;
return false;
}
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@ -330,11 +403,15 @@ public:
static bool GetKernelCoordinate(lldb_renderscript::RSCoordinate &coord,
Thread *thread_ptr);
bool ResolveKernelName(lldb::addr_t kernel_address, ConstString &name);
protected:
struct ScriptDetails;
struct AllocationDetails;
struct Element;
lldb_renderscript::RSScriptGroupList m_scriptGroups;
void InitSearchFilter(lldb::TargetSP target) {
if (!m_filtersp)
m_filtersp.reset(new SearchFilterForUnconstrainedSearches(target));
@ -349,6 +426,9 @@ protected:
bool EvalRSExpression(const char *expression, StackFrame *frame_ptr,
uint64_t *result);
lldb::BreakpointSP CreateScriptGroupBreakpoint(const ConstString &name,
bool multi);
lldb::BreakpointSP CreateKernelBreakpoint(const ConstString &name);
lldb::BreakpointSP CreateReductionBreakpoint(const ConstString &name,
@ -416,6 +496,10 @@ private:
void HookCallback(RuntimeHook *hook_info, ExecutionContext &context);
// Callback function when 'debugHintScriptGroup2' executes on the target.
void CaptureDebugHintScriptGroup2(RuntimeHook *hook_info,
ExecutionContext &context);
void CaptureScriptInit(RuntimeHook *hook_info, ExecutionContext &context);
void CaptureAllocationInit(RuntimeHook *hook_info, ExecutionContext &context);

View File

@ -0,0 +1,162 @@
//===-- RenderScriptScriptGroup.cpp -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "RenderScriptRuntime.h"
#include "RenderScriptScriptGroup.h"
using namespace lldb;
using namespace lldb_private;
using namespace lldb_renderscript;
class CommandObjectRenderScriptScriptGroupBreakpointSet
: public CommandObjectParsed {
public:
CommandObjectRenderScriptScriptGroupBreakpointSet(
CommandInterpreter &interpreter)
: CommandObjectParsed(
interpreter, "renderscript scriptgroup breakpoint set",
"Place a breakpoint on all kernels forming a script group.",
"renderscript scriptgroup breakpoint set <group_name>",
eCommandRequiresProcess | eCommandProcessMustBeLaunched) {}
~CommandObjectRenderScriptScriptGroupBreakpointSet() override = default;
bool DoExecute(Args &command, CommandReturnObject &result) override {
Stream &stream = result.GetOutputStream();
RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
eLanguageTypeExtRenderScript));
assert(runtime);
auto &target = m_exe_ctx.GetTargetSP();
bool stop_on_all = false;
const llvm::StringRef long_stop_all("--stop-on-all"), short_stop_all("-a");
std::vector<ConstString> sites;
sites.reserve(command.GetArgumentCount());
for (size_t i = 0; i < command.GetArgumentCount(); ++i) {
const auto arg = command.GetArgumentAtIndex(i);
if (long_stop_all == arg || short_stop_all == arg)
stop_on_all = true;
else
sites.push_back(ConstString(arg));
}
for (const auto &name : sites) {
runtime->PlaceBreakpointOnScriptGroup(target, stream, name, stop_on_all);
}
result.SetStatus(eReturnStatusSuccessFinishResult);
return true;
}
};
class CommandObjectRenderScriptScriptGroupBreakpoint
: public CommandObjectMultiword {
public:
CommandObjectRenderScriptScriptGroupBreakpoint(
CommandInterpreter &interpreter)
: CommandObjectMultiword(
interpreter, "renderscript scriptgroup breakpoint",
"Renderscript scriptgroup breakpoint interaction.",
"renderscript scriptgroup breakpoint set [--stop-on-all/-a]"
"<scriptgroup name> ...",
eCommandRequiresProcess | eCommandProcessMustBeLaunched) {
LoadSubCommand(
"set",
CommandObjectSP(new CommandObjectRenderScriptScriptGroupBreakpointSet(
interpreter)));
}
~CommandObjectRenderScriptScriptGroupBreakpoint() override = default;
};
class CommandObjectRenderScriptScriptGroupList : public CommandObjectParsed {
public:
CommandObjectRenderScriptScriptGroupList(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "renderscript scriptgroup list",
"List all currently discovered script groups.",
"renderscript scriptgroup list",
eCommandRequiresProcess |
eCommandProcessMustBeLaunched) {}
~CommandObjectRenderScriptScriptGroupList() override = default;
bool DoExecute(Args &command, CommandReturnObject &result) override {
Stream &stream = result.GetOutputStream();
RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
eLanguageTypeExtRenderScript));
assert(runtime);
const RSScriptGroupList &groups = runtime->GetScriptGroups();
// print script group count
stream.Printf("%" PRIu64 " script %s", uint64_t(groups.size()),
(groups.size() == 1) ? "group" : "groups");
stream.EOL();
// print script group details
stream.IndentMore();
for (const RSScriptGroupDescriptorSP &g : groups) {
if (g) {
stream.Indent();
// script group name
stream.Printf("%s", g->m_name.AsCString());
stream.EOL();
// print out the kernels
stream.IndentMore();
for (const auto &k : g->m_kernels) {
stream.Indent();
stream.Printf(". %s", k.m_name.AsCString());
stream.EOL();
}
stream.IndentLess();
}
}
stream.IndentLess();
result.SetStatus(eReturnStatusSuccessFinishResult);
return true;
}
};
class CommandObjectRenderScriptScriptGroup : public CommandObjectMultiword {
public:
CommandObjectRenderScriptScriptGroup(CommandInterpreter &interpreter)
: CommandObjectMultiword(interpreter, "renderscript scriptgroup",
"Command set for interacting with scriptgroups.",
nullptr, eCommandRequiresProcess |
eCommandProcessMustBeLaunched) {
LoadSubCommand(
"breakpoint",
CommandObjectSP(
new CommandObjectRenderScriptScriptGroupBreakpoint(interpreter)));
LoadSubCommand(
"list", CommandObjectSP(
new CommandObjectRenderScriptScriptGroupList(interpreter)));
}
~CommandObjectRenderScriptScriptGroup() override = default;
};
lldb::CommandObjectSP NewCommandObjectRenderScriptScriptGroup(
lldb_private::CommandInterpreter &interpreter) {
return CommandObjectSP(new CommandObjectRenderScriptScriptGroup(interpreter));
}

View File

@ -0,0 +1,18 @@
//===-- RenderScriptScriptGroup.h -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_RenderScriptScriptGroup_h_
#define liblldb_RenderScriptScriptGroup_h_
#include "lldb/Interpreter/CommandInterpreter.h"
lldb::CommandObjectSP NewCommandObjectRenderScriptScriptGroup(
lldb_private::CommandInterpreter &interpreter);
#endif // liblldb_RenderScriptScriptGroup_h_