diff options
author | Aidan Dodds <aidan@codeplay.com> | 2016-11-03 13:20:37 +0000 |
---|---|---|
committer | Aidan Dodds <aidan@codeplay.com> | 2016-11-03 13:20:37 +0000 |
commit | 21fed052e029f1484b3c11245bbe376737422db7 (patch) | |
tree | a2d49db06d17599f41aa103fe3f08aa22fe6d6bb /lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp | |
parent | 8b70e2631c6ab4259a4aa9e797c99132fb66e79b (diff) | |
download | bcm5719-llvm-21fed052e029f1484b3c11245bbe376737422db7.tar.gz bcm5719-llvm-21fed052e029f1484b3c11245bbe376737422db7.zip |
[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
Diffstat (limited to 'lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp')
-rw-r--r-- | lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp | 349 |
1 files changed, 345 insertions, 4 deletions
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( |