summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp')
-rw-r--r--lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp349
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(
OpenPOWER on IntegriCloud