forked from OSchip/llvm-project
RenderScript pending kernel breakpoints.
Currently the RS breakpoint command can only find a kernel if it's in an already loaded RS module. This patch allows users to set pending breakpoints on RenderScript kernels which will be loaded in the future. Implemented by creating a RS breakpoint resolver, to limit search scope to only RS modules. Reviewed by: clayborg, jingham Subscribers: lldb-commits, ADodds, domipheus Differential Revision: http://reviews.llvm.org/D12360 llvm-svn: 246842
This commit is contained in:
parent
2cf87a895d
commit
9815658332
|
@ -30,6 +30,7 @@
|
|||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
using namespace lldb_renderscript;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Static Functions
|
||||
|
@ -44,6 +45,47 @@ RenderScriptRuntime::CreateInstance(Process *process, lldb::LanguageType languag
|
|||
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 <name>.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 @@ RenderScriptRuntime::DumpKernels(Stream &strm) const
|
|||
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;
|
||||
SearchFilterSP filter_sp(new SearchFilterForUnconstrainedSearches(target));
|
||||
|
||||
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 <name>.expand and emit a warning.
|
||||
BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, kernel_name));
|
||||
|
||||
const Symbol* kernel_sym = module->m_module->FindFirstSymbolWithNameAndType(kernel_name, eSymbolTypeCode);
|
||||
BreakpointSP bp = target->CreateBreakpoint(filter_sp, resolver_sp, false, false, false);
|
||||
if (bp)
|
||||
bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
kernels_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!kernels_found)
|
||||
{
|
||||
error.SetErrorString("kernel name not found");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1037,7 +1035,7 @@ class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectPar
|
|||
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 <kernel_name>",
|
||||
eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
|
||||
{
|
||||
}
|
||||
|
@ -1054,7 +1052,8 @@ class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectPar
|
|||
(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())
|
||||
{
|
||||
|
|
|
@ -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<RSModuleDescriptor> RSModuleDescriptorSP;
|
|||
typedef std::shared_ptr<RSGlobalDescriptor> RSGlobalDescriptorSP;
|
||||
typedef std::shared_ptr<RSKernelDescriptor> 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 @@ class RSModuleDescriptor
|
|||
std::string m_resname;
|
||||
};
|
||||
|
||||
} // end lldb_renderscript namespace
|
||||
|
||||
class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
|
||||
{
|
||||
public:
|
||||
|
@ -147,7 +198,7 @@ class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
|
|||
|
||||
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 @@ class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
|
|||
|
||||
protected:
|
||||
|
||||
void FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp);
|
||||
void FixupScriptDetails(lldb_renderscript::RSModuleDescriptorSP rsmodule_sp);
|
||||
|
||||
void LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind);
|
||||
|
||||
|
@ -200,10 +251,10 @@ class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
|
|||
lldb::ModuleSP m_libRS;
|
||||
lldb::ModuleSP m_libRSDriver;
|
||||
lldb::ModuleSP m_libRSCpuRef;
|
||||
std::vector<RSModuleDescriptorSP> m_rsmodules;
|
||||
std::vector<lldb_renderscript::RSModuleDescriptorSP> m_rsmodules;
|
||||
std::vector<ScriptDetails> m_scripts;
|
||||
|
||||
std::map<lldb::addr_t, RSModuleDescriptorSP> m_scriptMappings;
|
||||
std::map<lldb::addr_t, lldb_renderscript::RSModuleDescriptorSP> m_scriptMappings;
|
||||
std::map<lldb::addr_t, RuntimeHookSP> m_runtimeHooks;
|
||||
|
||||
bool m_initiated;
|
||||
|
|
Loading…
Reference in New Issue