diff options
Diffstat (limited to 'lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime')
5 files changed, 610 insertions, 4 deletions
diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/CMakeLists.txt b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/CMakeLists.txt index fb06604c6af..0b19dba5ab6 100644 --- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/CMakeLists.txt +++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/CMakeLists.txt @@ -2,6 +2,7 @@ add_lldb_library(lldbPluginRenderScriptRuntime RenderScriptRuntime.cpp RenderScriptExpressionOpts.cpp RenderScriptx86ABIFixups.cpp + RenderScriptScriptGroup.cpp ) if(NOT LLDB_BUILT_STANDALONE) diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp index 0ee6b4c1ef0..d92f10014d1 100644 --- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp @@ -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( diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h index 41b9d9a0bac..a1211a2814b 100644 --- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h +++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h @@ -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); diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp new file mode 100644 index 00000000000..a8202dd0881 --- /dev/null +++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp @@ -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)); +} diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.h b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.h new file mode 100644 index 00000000000..5c5608c9986 --- /dev/null +++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.h @@ -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_ |