Files
clang-p2996/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
Enrico Granata e87764f247 Add support for custom commands to set flags on themselves
This works for Python commands defined via a class (implement get_flags on your class) and C++ plugin commands (which can call SBCommand::GetFlags()/SetFlags())

Flags allow features such as not letting the command run if there's no target, or if the process is not stopped, ...
Commands could always check for these things themselves, but having these accessible via flags makes custom commands more consistent with built-in ones

llvm-svn: 238286
2015-05-27 05:04:35 +00:00

434 lines
12 KiB
C++

//===-- RenderScriptRuntime.cpp ---------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "RenderScriptRuntime.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/Symbol/Symbol.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
using namespace lldb;
using namespace lldb_private;
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
LanguageRuntime *
RenderScriptRuntime::CreateInstance(Process *process, lldb::LanguageType language)
{
if (language == eLanguageTypeExtRenderScript)
return new RenderScriptRuntime(process);
else
return NULL;
}
void
RenderScriptRuntime::Initialize()
{
PluginManager::RegisterPlugin(GetPluginNameStatic(), "RenderScript language support", CreateInstance);
}
void
RenderScriptRuntime::Terminate()
{
PluginManager::UnregisterPlugin(CreateInstance);
}
lldb_private::ConstString
RenderScriptRuntime::GetPluginNameStatic()
{
static ConstString g_name("renderscript");
return g_name;
}
RenderScriptRuntime::ModuleKind
RenderScriptRuntime::GetModuleKind(const lldb::ModuleSP &module_sp)
{
if (module_sp)
{
// Is this a module containing renderscript kernels?
const Symbol *info_sym = module_sp->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData);
if (info_sym)
{
return eModuleKindKernelObj;
}
}
return eModuleKindIgnored;
}
bool
RenderScriptRuntime::IsRenderScriptModule(const lldb::ModuleSP &module_sp)
{
return GetModuleKind(module_sp) != eModuleKindIgnored;
}
void
RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list )
{
Mutex::Locker locker (module_list.GetMutex ());
size_t num_modules = module_list.GetSize();
for (size_t i = 0; i < num_modules; i++)
{
auto mod = module_list.GetModuleAtIndex (i);
if (IsRenderScriptModule (mod))
{
LoadModule(mod);
}
}
}
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
lldb_private::ConstString
RenderScriptRuntime::GetPluginName()
{
return GetPluginNameStatic();
}
uint32_t
RenderScriptRuntime::GetPluginVersion()
{
return 1;
}
bool
RenderScriptRuntime::IsVTableName(const char *name)
{
return false;
}
bool
RenderScriptRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
TypeAndOrName &class_type_or_name, Address &address)
{
return false;
}
bool
RenderScriptRuntime::CouldHaveDynamicValue(ValueObject &in_value)
{
return false;
}
lldb::BreakpointResolverSP
RenderScriptRuntime::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp)
{
BreakpointResolverSP resolver_sp;
return resolver_sp;
}
bool
RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp)
{
if (module_sp)
{
for (const auto &rs_module : m_rsmodules)
{
if (rs_module.m_module == module_sp)
return false;
}
bool module_loaded = false;
switch (GetModuleKind(module_sp))
{
case eModuleKindKernelObj:
{
RSModuleDescriptor module_desc(module_sp);
if (module_desc.ParseRSInfo())
{
m_rsmodules.push_back(module_desc);
module_loaded = true;
}
break;
}
case eModuleKindDriver:
case eModuleKindImpl:
case eModuleKindLibRS:
default:
break;
}
if (module_loaded)
Update();
return module_loaded;
}
return false;
}
void
RenderScriptRuntime::Update()
{
if (m_rsmodules.size() > 0)
{
if (!m_initiated)
{
Initiate();
}
}
}
// The maximum line length of an .rs.info packet
#define MAXLINE 500
// The .rs.info symbol in renderscript modules contains a string which needs to be parsed.
// The string is basic and is parsed on a line by line basis.
bool
RSModuleDescriptor::ParseRSInfo()
{
const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData);
if (info_sym)
{
const addr_t addr = info_sym->GetAddress().GetFileAddress();
const addr_t size = info_sym->GetByteSize();
const FileSpec fs = m_module->GetFileSpec();
DataBufferSP buffer = fs.ReadFileContents(addr, size);
if (!buffer)
return false;
std::string info((const char *)buffer->GetBytes());
std::vector<std::string> info_lines;
size_t lpos = info.find_first_of("\n");
while (lpos != std::string::npos)
{
info_lines.push_back(info.substr(0, lpos));
info = info.substr(lpos + 1);
lpos = info.find_first_of("\n");
}
size_t offset = 0;
while (offset < info_lines.size())
{
std::string line = info_lines[offset];
// Parse directives
uint32_t numDefns = 0;
if (sscanf(line.c_str(), "exportVarCount: %u", &numDefns) == 1)
{
while (numDefns--)
m_globals.push_back(RSGlobalDescriptor(*this, info_lines[++offset].c_str()));
}
else if (sscanf(line.c_str(), "exportFuncCount: %u", &numDefns) == 1)
{
}
else if (sscanf(line.c_str(), "exportForEachCount: %u", &numDefns) == 1)
{
char name[MAXLINE];
while (numDefns--)
{
uint32_t slot = 0;
name[0] = '\0';
if (sscanf(info_lines[++offset].c_str(), "%u - %s", &slot, &name[0]) == 2)
{
m_kernels.push_back(RSKernelDescriptor(*this, name, slot));
}
}
}
else if (sscanf(line.c_str(), "objectSlotCount: %u", &numDefns) == 1)
{
}
offset++;
}
return m_kernels.size() > 0;
}
return false;
}
bool
RenderScriptRuntime::ProbeModules(const ModuleList module_list)
{
bool rs_found = false;
size_t num_modules = module_list.GetSize();
for (size_t i = 0; i < num_modules; i++)
{
auto module = module_list.GetModuleAtIndex(i);
rs_found |= LoadModule(module);
}
return rs_found;
}
void
RenderScriptRuntime::DumpModules(Stream &strm) const
{
strm.Printf("RenderScript Modules:");
strm.EOL();
strm.IndentMore();
for (const auto &module : m_rsmodules)
{
module.Dump(strm);
}
strm.IndentLess();
}
void
RSModuleDescriptor::Dump(Stream &strm) const
{
strm.Indent();
m_module->GetFileSpec().Dump(&strm);
strm.EOL();
strm.IndentMore();
strm.Indent();
strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size()));
strm.EOL();
strm.IndentMore();
for (const auto &global : m_globals)
{
global.Dump(strm);
}
strm.IndentLess();
strm.Indent();
strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size()));
strm.EOL();
strm.IndentMore();
for (const auto &kernel : m_kernels)
{
kernel.Dump(strm);
}
strm.IndentLess(4);
}
void
RSGlobalDescriptor::Dump(Stream &strm) const
{
strm.Indent(m_name.AsCString());
strm.EOL();
}
void
RSKernelDescriptor::Dump(Stream &strm) const
{
strm.Indent(m_name.AsCString());
strm.EOL();
}
class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed
{
private:
public:
CommandObjectRenderScriptRuntimeModuleProbe(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "renderscript module probe",
"Initiates a Probe of all loaded modules for kernels and other renderscript objects.",
"renderscript module probe",
eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBeLaunched)
{
}
~CommandObjectRenderScriptRuntimeModuleProbe() {}
bool
DoExecute(Args &command, CommandReturnObject &result)
{
const size_t argc = command.GetArgumentCount();
if (argc == 0)
{
Target *target = m_exe_ctx.GetTargetPtr();
RenderScriptRuntime *runtime =
(RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
auto module_list = target->GetImages();
bool new_rs_details = runtime->ProbeModules(module_list);
if (new_rs_details)
{
result.AppendMessage("New renderscript modules added to runtime model.");
}
result.SetStatus(eReturnStatusSuccessFinishResult);
return true;
}
result.AppendErrorWithFormat("'%s' takes no arguments", m_cmd_name.c_str());
result.SetStatus(eReturnStatusFailed);
return false;
}
};
class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed
{
private:
public:
CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "renderscript module dump",
"Dumps renderscript specific information for all modules.", "renderscript module dump",
eCommandRequiresProcess | eCommandProcessMustBeLaunched)
{
}
~CommandObjectRenderScriptRuntimeModuleDump() {}
bool
DoExecute(Args &command, CommandReturnObject &result)
{
RenderScriptRuntime *runtime =
(RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
runtime->DumpModules(result.GetOutputStream());
result.SetStatus(eReturnStatusSuccessFinishResult);
return true;
}
};
class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword
{
private:
public:
CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter)
: CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with renderscript modules.",
NULL)
{
LoadSubCommand("probe", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleProbe(interpreter)));
LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(interpreter)));
}
~CommandObjectRenderScriptRuntimeModule() {}
};
class CommandObjectRenderScriptRuntime : public CommandObjectMultiword
{
public:
CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter)
: CommandObjectMultiword(interpreter, "renderscript", "A set of commands for operating on renderscript.",
"renderscript <subcommand> [<subcommand-options>]")
{
LoadSubCommand("module", CommandObjectSP(new CommandObjectRenderScriptRuntimeModule(interpreter)));
}
~CommandObjectRenderScriptRuntime() {}
};
void
RenderScriptRuntime::Initiate()
{
assert(!m_initiated);
Process* process = GetProcess();
if (process)
{
CommandInterpreter &interpreter = process->GetTarget().GetDebugger().GetCommandInterpreter();
m_initiated = interpreter.AddCommand("renderscript", CommandObjectSP(
new CommandObjectRenderScriptRuntime(interpreter)), true);
}
}
RenderScriptRuntime::RenderScriptRuntime(Process *process)
: lldb_private::CPPLanguageRuntime(process), m_initiated(false)
{
}