Index: lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h =================================================================== --- lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h +++ lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h @@ -22,6 +22,9 @@ namespace lldb_private { +namespace lldb_renderscript +{ + typedef uint32_t RSSlot; class RSModuleDescriptor; struct RSGlobalDescriptor; @@ -31,7 +34,53 @@ typedef std::shared_ptr RSGlobalDescriptorSP; typedef std::shared_ptr RSKernelDescriptorSP; +// Breakpoint Resolvers decide where a breakpoint is placed, +// so having our own allows us to limit the search scope to RS kernel modules. +// As well as check for .expand kernels as a fallback. +class RSBreakpointResolver : public BreakpointResolver +{ + public: + + RSBreakpointResolver(Breakpoint *bkpt, ConstString name): + BreakpointResolver (bkpt, BreakpointResolver::NameResolver), + m_kernel_name(name) + { + } + + void + GetDescription(Stream *strm) override + { + if (strm) + strm->Printf("RenderScript kernel breakpoint for '%s'", m_kernel_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 RSBreakpointResolver(&breakpoint, m_kernel_name)); + return ret_sp; + } + + protected: + ConstString m_kernel_name; +}; struct RSKernelDescriptor { @@ -86,6 +135,8 @@ std::string m_resname; }; +} // end lldb_renderscript namespace + class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime { public: @@ -147,7 +198,7 @@ void DumpKernels(Stream &strm) const; - void AttemptBreakpointAtKernelName(Stream &strm, const char *name, Error &error); + void AttemptBreakpointAtKernelName(Stream &strm, const char *name, Error &error, lldb::TargetSP target); void Status(Stream &strm) const; @@ -163,7 +214,7 @@ protected: - void FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp); + void FixupScriptDetails(lldb_renderscript::RSModuleDescriptorSP rsmodule_sp); void LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind); @@ -200,10 +251,10 @@ lldb::ModuleSP m_libRS; lldb::ModuleSP m_libRSDriver; lldb::ModuleSP m_libRSCpuRef; - std::vector m_rsmodules; + std::vector m_rsmodules; std::vector m_scripts; - std::map m_scriptMappings; + std::map m_scriptMappings; std::map m_runtimeHooks; bool m_initiated; Index: lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp =================================================================== --- lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp +++ lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp @@ -30,6 +30,7 @@ using namespace lldb; using namespace lldb_private; +using namespace lldb_renderscript; //------------------------------------------------------------------ // Static Functions @@ -44,6 +45,47 @@ return NULL; } +// Callback with a module to search for matching symbols. +// We first check that the module contains RS kernels. +// Then look for a symbol which matches our kernel name. +// The breakpoint address is finally set using the address of this symbol. +Searcher::CallbackReturn +RSBreakpointResolver::SearchCallback(SearchFilter &filter, + SymbolContext &context, + Address*, + bool) +{ + ModuleSP module = context.module_sp; + + if (!module) + return Searcher::eCallbackReturnContinue; + + // Is this a module containing renderscript kernels? + if (nullptr == module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData)) + return Searcher::eCallbackReturnContinue; + + // Attempt to set a breakpoint on the kernel name symbol within the module library. + // If it's not found, it's likely debug info is unavailable - try to set a + // breakpoint on .expand. + + const Symbol* kernel_sym = module->FindFirstSymbolWithNameAndType(m_kernel_name, eSymbolTypeCode); + if (!kernel_sym) + { + std::string kernel_name_expanded(m_kernel_name.AsCString()); + kernel_name_expanded.append(".expand"); + kernel_sym = module->FindFirstSymbolWithNameAndType(ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode); + } + + if (kernel_sym) + { + Address bp_addr = kernel_sym->GetAddress(); + if (filter.AddressPasses(bp_addr)) + m_breakpoint->AddLocation(bp_addr); + } + + return Searcher::eCallbackReturnContinue; +} + void RenderScriptRuntime::Initialize() { @@ -767,68 +809,24 @@ strm.IndentLess(); } -void -RenderScriptRuntime::AttemptBreakpointAtKernelName(Stream &strm, const char* name, Error& error) +void +RenderScriptRuntime::AttemptBreakpointAtKernelName(Stream &strm, const char* name, Error& error, TargetSP target) { - if (!name) + if (!name) { error.SetErrorString("invalid kernel name"); return; } - bool kernels_found = false; - ConstString kernel_name(name); - for (const auto &module : m_rsmodules) - { - for (const auto &kernel : module->m_kernels) - { - if (kernel.m_name == kernel_name) - { - //Attempt to set a breakpoint on this symbol, within the module library - //If it's not found, it's likely debug info is unavailable - set a - //breakpoint on .expand and emit a warning. - - const Symbol* kernel_sym = module->m_module->FindFirstSymbolWithNameAndType(kernel_name, eSymbolTypeCode); - - if (!kernel_sym) - { - std::string kernel_name_expanded(name); - kernel_name_expanded.append(".expand"); - kernel_sym = module->m_module->FindFirstSymbolWithNameAndType(ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode); - - if (kernel_sym) - { - strm.Printf("Kernel '%s' could not be found, but expansion exists. ", name); - strm.Printf("Breakpoint placed on expanded kernel. Have you compiled in debug mode?"); - strm.EOL(); - } - else - { - error.SetErrorStringWithFormat("Could not locate symbols for loaded kernel '%s'.", name); - return; - } - } - - addr_t bp_addr = kernel_sym->GetLoadAddress(&GetProcess()->GetTarget()); - if (bp_addr == LLDB_INVALID_ADDRESS) - { - error.SetErrorStringWithFormat("Could not locate load address for symbols of kernel '%s'.", name); - return; - } + SearchFilterSP filter_sp(new SearchFilterForUnconstrainedSearches(target)); - BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(bp_addr, false, false); - strm.Printf("Breakpoint %" PRIu64 ": kernel '%s' within script '%s'", (uint64_t)bp->GetID(), name, module->m_resname.c_str()); - strm.EOL(); + ConstString kernel_name(name); + BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, kernel_name)); - kernels_found = true; - } - } - } + BreakpointSP bp = target->CreateBreakpoint(filter_sp, resolver_sp, false, false, false); + if (bp) + bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false); - if (!kernels_found) - { - error.SetErrorString("kernel name not found"); - } return; } @@ -1037,7 +1035,7 @@ public: CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "renderscript kernel breakpoint", - "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint", + "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint ", eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) { } @@ -1054,7 +1052,8 @@ (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); Error error; - runtime->AttemptBreakpointAtKernelName(result.GetOutputStream(), command.GetArgumentAtIndex(0), error); + runtime->AttemptBreakpointAtKernelName(result.GetOutputStream(), command.GetArgumentAtIndex(0), + error, m_exe_ctx.GetTargetSP()); if (error.Success()) {