This revision was automatically updated to reflect the committed changes.
Closed by commit rL248149: Groundwork for better tracking of renderscript 
allocations and scripts (authored by EwanCrawford).

Changed prior to commit:
  http://reviews.llvm.org/D12936?vs=34996&id=35224#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D12936

Files:
  
lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
  
lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h

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
@@ -32,6 +32,126 @@
 using namespace lldb_private;
 using namespace lldb_renderscript;
 
+namespace {
+
+// The empirical_type adds a basic level of validation to arbitrary data
+// allowing us to track if data has been discovered and stored or not.
+// An empirical_type will be marked as valid only if it has been explicitly assigned to.
+template <typename type_t>
+class empirical_type
+{
+  public:
+    // Ctor. Contents is invalid when constructed.
+    empirical_type()
+        : valid(false)
+    {}
+
+    // Return true and copy contents to out if valid, else return false.
+    bool get(type_t& out) const
+    {
+        if (valid)
+            out = data;
+        return valid;
+    }
+
+    // Return a pointer to the contents or nullptr if it was not valid.
+    const type_t* get() const
+    {
+        return valid ? &data : nullptr;
+    }
+
+    // Assign data explicitly.
+    void set(const type_t in)
+    {
+        data = in;
+        valid = true;
+    }
+
+    // Mark contents as invalid.
+    void invalidate()
+    {
+        valid = false;
+    }
+
+    // Returns true if this type contains valid data.
+    bool isValid() const
+    {
+        return valid;
+    }
+
+    // Assignment operator.
+    empirical_type<type_t>& operator = (const type_t in)
+    {
+        set(in);
+        return *this;
+    }
+
+    // Dereference operator returns contents.
+    // Warning: Will assert if not valid so use only when you know data is valid.
+    const type_t& operator * () const
+    {
+        assert(valid);
+        return data;
+    }
+
+  protected:
+    bool valid;
+    type_t data;
+};
+
+} // namespace {}
+
+// The ScriptDetails class collects data associated with a single script instance.
+struct RenderScriptRuntime::ScriptDetails
+{
+    ~ScriptDetails() {};
+
+    enum ScriptType
+    {
+        eScript,
+        eScriptC
+    };
+
+    // The derived type of the script.
+    empirical_type<ScriptType> type;
+    // The name of the original source file.
+    empirical_type<std::string> resName;
+    // Path to script .so file on the device.
+    empirical_type<std::string> scriptDyLib;
+    // Directory where kernel objects are cached on device.
+    empirical_type<std::string> cacheDir;
+    // Pointer to the context which owns this script.
+    empirical_type<lldb::addr_t> context;
+    // Pointer to the script object itself.
+    empirical_type<lldb::addr_t> script;
+};
+
+// This AllocationDetails class collects data associated with a single
+// allocation instance.
+struct RenderScriptRuntime::AllocationDetails
+{
+    ~AllocationDetails () {};
+
+    enum DataType
+    {
+        eInt,
+    };
+
+    enum Dimension
+    {
+        e1d,
+        e2d,
+        e3d,
+        eCubeMap,
+    };
+
+    empirical_type<DataType> type;
+    empirical_type<Dimension> dimension;
+    empirical_type<lldb::addr_t> address;
+    empirical_type<lldb::addr_t> dataPtr;
+    empirical_type<lldb::addr_t> context;
+};
+
 //------------------------------------------------------------------
 // Static Functions
 //------------------------------------------------------------------
@@ -484,6 +604,10 @@
     if (log)
         log->Printf ("RenderScriptRuntime::CaptureAllocationInit1 - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .",
                         rs_context_u64, rs_alloc_u64, rs_forceZero_u64);
+
+    AllocationDetails* alloc = LookUpAllocation(rs_alloc_u64, true);
+    if (alloc)
+        alloc->context = rs_context_u64;
 }
 
 void 
@@ -541,14 +665,15 @@
         StreamString strm;
         strm.Printf("librs.%s.so", resname.c_str());
 
-        ScriptDetails script;
-        script.cachedir = cachedir;
-        script.resname = resname;
-        script.scriptDyLib.assign(strm.GetData());
-        script.script = (addr_t) rs_script_u64;
-        script.context = (addr_t) rs_context_u64;
-
-        m_scripts.push_back(script);
+        ScriptDetails* script = LookUpScript(rs_script_u64, true);
+        if (script)
+        {
+            script->type = ScriptDetails::eScriptC;
+            script->cacheDir = cachedir;
+            script->resName = resname;
+            script->scriptDyLib = strm.GetData();
+            script->context = addr_t(rs_context_u64);
+        }
 
         if (log)
             log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - '%s' tagged with context 0x%" PRIx64 " and script 0x%" PRIx64 ".",
@@ -561,7 +686,6 @@
 
 }
 
-
 void
 RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind)
 {
@@ -642,35 +766,51 @@
 
     const ModuleSP module = rsmodule_sp->m_module;
     const FileSpec& file = module->GetPlatformFileSpec();
-    
-    for (const auto &rs_script : m_scripts)
-    {
-        if (file.GetFilename() == ConstString(rs_script.scriptDyLib.c_str()))
+
+    // Iterate over all of the scripts that we currently know of.
+    // Note: We cant push or pop to m_scripts here or it may invalidate rs_script.
+    for (const auto & rs_script : m_scripts)
+    {
+        // Extract the expected .so file path for this script.
+        std::string dylib;
+        if (!rs_script->scriptDyLib.get(dylib))
+            continue;
+
+        // Only proceed if the module that has loaded corresponds to this script.
+        if (file.GetFilename() != ConstString(dylib.c_str()))
+            continue;
+
+        // Obtain the script address which we use as a key.
+        lldb::addr_t script;
+        if (!rs_script->script.get(script))
+            continue;
+
+        // If we have a script mapping for the current script.
+        if (m_scriptMappings.find(script) != m_scriptMappings.end())
         {
-            if (m_scriptMappings.find( rs_script.script ) != m_scriptMappings.end())
-            {
-                if (m_scriptMappings[rs_script.script] != rsmodule_sp)
-                {
-                    if (log)
-                    {
-                        log->Printf ("RenderScriptRuntime::FixupScriptDetails - Error: script %" PRIx64 " wants reassigned to new rsmodule '%s'.", 
-                                     (uint64_t)rs_script.script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
-                    }
-                }
-            }
-            else
+            // if the module we have stored is different to the one we just received.
+            if (m_scriptMappings[script] != rsmodule_sp)
             {
-                m_scriptMappings[rs_script.script] = rsmodule_sp;
-                rsmodule_sp->m_resname = rs_script.resname;
                 if (log)
-                {
-                    log->Printf ("RenderScriptRuntime::FixupScriptDetails - script %" PRIx64 " associated with rsmodule '%s'.", 
-                                    (uint64_t)rs_script.script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
-                }
+                    log->Printf ("RenderScriptRuntime::FixupScriptDetails - Error: script %" PRIx64 " wants reassigned to new rsmodule '%s'.",
+                                    (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
             }
         }
+        // We don't have a script mapping for the current script.
+        else
+        {
+            // Obtain the script resource name.
+            std::string resName;
+            if (rs_script->resName.get(resName))
+                // Set the modules resource name.
+                rsmodule_sp->m_resname = resName;
+            // Add Script/Module pair to map.
+            m_scriptMappings[script] = rsmodule_sp;
+            if (log)
+                log->Printf ("RenderScriptRuntime::FixupScriptDetails - script %" PRIx64 " associated with rsmodule '%s'.",
+                                (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
+        }
     }
-    
 }
 
 bool
@@ -922,15 +1062,21 @@
 
     std::map<addr_t, uint64_t> contextReferences;
 
-    for (const auto &script : m_scripts)
+    // Iterate over all of the currently discovered scripts.
+    // Note: We cant push or pop from m_scripts inside this loop or it may invalidate script.
+    for (const auto & script : m_scripts)
     {
-        if (contextReferences.find(script.context) != contextReferences.end())
+        if (!script->context.isValid())
+            continue;
+        lldb::addr_t context = *script->context;
+
+        if (contextReferences.find(context) != contextReferences.end())
         {
-            contextReferences[script.context]++;
+            contextReferences[context]++;
         }
         else
         {
-            contextReferences[script.context] = 1;
+            contextReferences[context] = 1;
         }
     }
 
@@ -1065,6 +1211,44 @@
     strm.IndentLess();
 }
 
+RenderScriptRuntime::ScriptDetails*
+RenderScriptRuntime::LookUpScript(addr_t address, bool create)
+{
+    for (const auto & s : m_scripts)
+    {
+        if (s->script.isValid())
+            if (*s->script == address)
+                return s.get();
+    }
+    if (create)
+    {
+        std::unique_ptr<ScriptDetails> s(new ScriptDetails);
+        s->script = address;
+        m_scripts.push_back(std::move(s));
+        return s.get();
+    }
+    return nullptr;
+}
+
+RenderScriptRuntime::AllocationDetails*
+RenderScriptRuntime::LookUpAllocation(addr_t address, bool create)
+{
+    for (const auto & a : m_allocations)
+    {
+        if (a->address.isValid())
+            if (*a->address == address)
+                return a.get();
+    }
+    if (create)
+    {
+        std::unique_ptr<AllocationDetails> a(new AllocationDetails);
+        a->address = address;
+        m_allocations.push_back(std::move(a));
+        return a.get();
+    }
+    return nullptr;
+}
+
 void
 RSModuleDescriptor::Dump(Stream &strm) const
 {
@@ -1482,3 +1666,4 @@
     return command_object;
 }
 
+RenderScriptRuntime::~RenderScriptRuntime() = default;
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
@@ -150,8 +150,7 @@
         eModuleKindKernelObj
     };
 
-
-    ~RenderScriptRuntime() {}
+    ~RenderScriptRuntime();
 
     //------------------------------------------------------------------
     // Static Functions
@@ -253,20 +252,16 @@
     
     typedef std::shared_ptr<RuntimeHook> RuntimeHookSP;
 
-    struct ScriptDetails
-    {
-        std::string resname;
-        std::string scriptDyLib;
-        std::string cachedir;
-        lldb::addr_t context;
-        lldb::addr_t script;
-    };
+    struct ScriptDetails;
+    struct AllocationDetails;
 
     lldb::ModuleSP m_libRS;
     lldb::ModuleSP m_libRSDriver;
     lldb::ModuleSP m_libRSCpuRef;
     std::vector<lldb_renderscript::RSModuleDescriptorSP> m_rsmodules;
-    std::vector<ScriptDetails> m_scripts;
+
+    std::vector<std::unique_ptr<ScriptDetails>> m_scripts;
+    std::vector<std::unique_ptr<AllocationDetails>> m_allocations;
 
     std::map<lldb::addr_t, lldb_renderscript::RSModuleDescriptorSP> m_scriptMappings;
     std::map<lldb::addr_t, RuntimeHookSP> m_runtimeHooks;
@@ -293,6 +288,17 @@
     void CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionContext& context);
     void CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionContext& context);
 
+    // Search for a script detail object using a target address.
+    // If a script does not currently exist this function will return nullptr.
+    // If 'create' is true and there is no previous script with this address,
+    // then a new Script detail object will be created for this address and returned.
+    ScriptDetails* LookUpScript(lldb::addr_t address, bool create);
+
+    // Search for a previously saved allocation detail object using a target address.
+    // If an allocation does not exist for this address then nullptr will be returned.
+    // If 'create' is true and there is no previous allocation then a new allocation
+    // detail object will be created for this address and returned.
+    AllocationDetails* LookUpAllocation(lldb::addr_t address, bool create);
 };
 
 } // namespace lldb_private
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to