[Lldb-commits] [lldb] r263995 - Collect IRExecutionUnits as part of persistent expression state.

Sean Callanan via lldb-commits lldb-commits at lists.llvm.org
Mon Mar 21 15:23:38 PDT 2016


Author: spyffe
Date: Mon Mar 21 17:23:38 2016
New Revision: 263995

URL: http://llvm.org/viewvc/llvm-project?rev=263995&view=rev
Log:
Collect IRExecutionUnits as part of persistent expression state.

IRExecutionUnits contain code and data that persistent declarations can
depend on.  In order to keep them alive and provide for lookup of these
symbols, we now allow any PersistentExpressionState to keep a list of
execution units.  Then, when doing symbol lookup on behalf of an 
expression, any IRExecutionUnit can consult the persistent expression
states on a particular Target to find the appropriate symbol.

<rdar://problem/22864976>

Modified:
    lldb/trunk/include/lldb/Expression/ExpressionVariable.h
    lldb/trunk/include/lldb/Expression/IRExecutionUnit.h
    lldb/trunk/source/Expression/ExpressionVariable.cpp
    lldb/trunk/source/Expression/IRExecutionUnit.cpp
    lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
    lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h

Modified: lldb/trunk/include/lldb/Expression/ExpressionVariable.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ExpressionVariable.h?rev=263995&r1=263994&r2=263995&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ExpressionVariable.h (original)
+++ lldb/trunk/include/lldb/Expression/ExpressionVariable.h Mon Mar 21 17:23:38 2016
@@ -16,6 +16,8 @@
 #include <vector>
 
 // Other libraries and framework includes
+#include "llvm/ADT/DenseMap.h"
+
 // Project includes
 #include "lldb/lldb-public.h"
 #include "lldb/Core/ConstString.h"
@@ -309,10 +311,19 @@ public:
     RemovePersistentVariable (lldb::ExpressionVariableSP variable) = 0;
     
     virtual lldb::addr_t
-    LookupSymbol (const ConstString &name) = 0;
+    LookupSymbol (const ConstString &name);
+    
+    void
+    RegisterExecutionUnit (lldb::IRExecutionUnitSP &execution_unit_sp);
     
 private:
     LLVMCastKind m_kind;
+    
+    typedef std::set<lldb::IRExecutionUnitSP>               ExecutionUnitSet;
+    ExecutionUnitSet                                        m_execution_units;              ///< The execution units that contain valuable symbols.
+    
+    typedef llvm::DenseMap<const char *, lldb::addr_t>      SymbolMap;
+    SymbolMap                                               m_symbol_map;                   ///< The addresses of the symbols in m_execution_units.
 };
     
 } // namespace lldb_private

Modified: lldb/trunk/include/lldb/Expression/IRExecutionUnit.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/IRExecutionUnit.h?rev=263995&r1=263994&r2=263995&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/IRExecutionUnit.h (original)
+++ lldb/trunk/include/lldb/Expression/IRExecutionUnit.h Mon Mar 21 17:23:38 2016
@@ -79,7 +79,12 @@ public:
     /// Destructor
     //------------------------------------------------------------------
     ~IRExecutionUnit() override;
-        
+    
+    ConstString GetFunctionName()
+    {
+        return m_name;
+    }
+    
     llvm::Module *
     GetModule()
     {
@@ -136,6 +141,79 @@ public:
         
     lldb::addr_t
     FindSymbol(const ConstString &name);
+    
+    void
+    GetStaticInitializers(std::vector <lldb::addr_t> &static_initializers);
+    
+    //----------------------------------------------------------------------
+    /// @class JittedFunction IRExecutionUnit.h "lldb/Expression/IRExecutionUnit.h"
+    /// @brief Encapsulates a single function that has been generated by the JIT.
+    ///
+    /// Functions that have been generated by the JIT are first resident in the
+    /// local process, and then placed in the target process.  JittedFunction
+    /// represents a function possibly resident in both.
+    //----------------------------------------------------------------------
+    struct JittedEntity {
+        ConstString m_name;             ///< The function's name
+        lldb::addr_t m_local_addr;      ///< The address of the function in LLDB's memory
+        lldb::addr_t m_remote_addr;     ///< The address of the function in the target's memory
+        
+        //------------------------------------------------------------------
+        /// Constructor
+        ///
+        /// Initializes class variabes.
+        ///
+        /// @param[in] name
+        ///     The name of the function.
+        ///
+        /// @param[in] local_addr
+        ///     The address of the function in LLDB, or LLDB_INVALID_ADDRESS if
+        ///     it is not present in LLDB's memory.
+        ///
+        /// @param[in] remote_addr
+        ///     The address of the function in the target, or LLDB_INVALID_ADDRESS
+        ///     if it is not present in the target's memory.
+        //------------------------------------------------------------------
+        JittedEntity (const char *name,
+                      lldb::addr_t local_addr = LLDB_INVALID_ADDRESS,
+                      lldb::addr_t remote_addr = LLDB_INVALID_ADDRESS) :
+        m_name (name),
+        m_local_addr (local_addr),
+        m_remote_addr (remote_addr)
+        {
+        }
+    };
+    
+    struct JittedFunction : JittedEntity
+    {
+        bool m_external;
+        JittedFunction (const char *name,
+                        bool external,
+                        lldb::addr_t local_addr = LLDB_INVALID_ADDRESS,
+                        lldb::addr_t remote_addr = LLDB_INVALID_ADDRESS) :
+        JittedEntity (name, local_addr, remote_addr),
+        m_external(external)
+        {}
+    };
+    
+    struct JittedGlobalVariable : JittedEntity
+    {
+        JittedGlobalVariable (const char *name,
+                              lldb::addr_t local_addr = LLDB_INVALID_ADDRESS,
+                              lldb::addr_t remote_addr = LLDB_INVALID_ADDRESS) :
+        JittedEntity (name, local_addr, remote_addr)
+        {}
+    };
+    
+    const std::vector<JittedFunction> &GetJittedFunctions()
+    {
+        return m_jitted_functions;
+    }
+    
+    const std::vector<JittedGlobalVariable> &GetJittedGlobalVariables()
+    {
+        return m_jitted_global_variables;
+    }
 
 private:
     //------------------------------------------------------------------
@@ -225,6 +303,10 @@ private:
     FindInRuntimes(const std::vector<SearchSpec> &specs,
                    const lldb_private::SymbolContext &sc);
     
+    lldb::addr_t
+    FindInUserDefinedSymbols(const std::vector<SearchSpec> &specs,
+                             const lldb_private::SymbolContext &sc);
+    
     void
     ReportSymbolLookupError(const ConstString &name);
 
@@ -309,45 +391,6 @@ private:
         IRExecutionUnit                    &m_parent;           ///< The execution unit this is a proxy for.
     };
     
-    //----------------------------------------------------------------------
-    /// @class JittedFunction IRExecutionUnit.h "lldb/Expression/IRExecutionUnit.h"
-    /// @brief Encapsulates a single function that has been generated by the JIT.
-    ///
-    /// Functions that have been generated by the JIT are first resident in the
-    /// local process, and then placed in the target process.  JittedFunction
-    /// represents a function possibly resident in both.
-    //----------------------------------------------------------------------
-    struct JittedFunction {
-        std::string m_name;             ///< The function's name
-        lldb::addr_t m_local_addr;      ///< The address of the function in LLDB's memory
-        lldb::addr_t m_remote_addr;     ///< The address of the function in the target's memory
-        
-        //------------------------------------------------------------------
-        /// Constructor
-        ///
-        /// Initializes class variables.
-        ///
-        /// @param[in] name
-        ///     The name of the function.
-        ///
-        /// @param[in] local_addr
-        ///     The address of the function in LLDB, or LLDB_INVALID_ADDRESS if
-        ///     it is not present in LLDB's memory.
-        ///
-        /// @param[in] remote_addr
-        ///     The address of the function in the target, or LLDB_INVALID_ADDRESS
-        ///     if it is not present in the target's memory.
-        //------------------------------------------------------------------
-        JittedFunction (const char *name,
-                        lldb::addr_t local_addr = LLDB_INVALID_ADDRESS,
-                        lldb::addr_t remote_addr = LLDB_INVALID_ADDRESS) :
-            m_name (name),
-            m_local_addr (local_addr),
-            m_remote_addr (remote_addr)
-        {
-        }
-    };
-    
     static const unsigned eSectionIDInvalid = (unsigned)-1;
     
     //----------------------------------------------------------------------
@@ -398,6 +441,9 @@ private:
         void dump (Log *log);
     };
     
+    bool
+    CommitOneAllocation (lldb::ProcessSP &process_sp, Error &error, AllocationRecord &record);
+    
     typedef std::vector<AllocationRecord>   RecordVector;
     RecordVector                            m_records;
 
@@ -406,7 +452,8 @@ private:
     std::unique_ptr<llvm::Module>            m_module_ap;            ///< Holder for the module until it's been handed off
     llvm::Module                           *m_module;               ///< Owned by the execution engine
     std::vector<std::string>                m_cpu_features;
-    llvm::SmallVector<JittedFunction, 1>    m_jitted_functions;     ///< A vector of all functions that have been JITted into machine code
+    std::vector<JittedFunction>             m_jitted_functions;     ///< A vector of all functions that have been JITted into machine code
+    std::vector<JittedGlobalVariable>       m_jitted_global_variables; ///< A vector of all functions that have been JITted into machine code
     const ConstString                       m_name;
     SymbolContext                           m_sym_ctx;              ///< Used for symbol lookups
     std::vector<ConstString>                m_failed_lookups;
@@ -417,6 +464,12 @@ private:
     lldb::addr_t                            m_function_end_load_addr;
     
     bool                                    m_strip_underscore;     ///< True for platforms where global symbols have a _ prefix
+    bool                                    m_reported_allocations; ///< True after allocations have been reported.  It is possible that
+                                                                    ///< sections will be allocated when this is true, in which case they weren't
+                                                                    ///< depended on by any function.  (Top-level code defining a variable, but
+                                                                    ///< defining no functions using that variable, would do this.)  If this
+                                                                    ///< is true, any allocations need to be committed immediately -- no
+                                                                    ///< opportunity for relocation.
 };
 
 } // namespace lldb_private

Modified: lldb/trunk/source/Expression/ExpressionVariable.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ExpressionVariable.cpp?rev=263995&r1=263994&r2=263995&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ExpressionVariable.cpp (original)
+++ lldb/trunk/source/Expression/ExpressionVariable.cpp Mon Mar 21 17:23:38 2016
@@ -7,7 +7,9 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "lldb/Core/Log.h"
 #include "lldb/Expression/ExpressionVariable.h"
+#include "lldb/Expression/IRExecutionUnit.h"
 
 using namespace lldb_private;
 
@@ -34,3 +36,55 @@ ExpressionVariable::GetValueBytes()
 PersistentExpressionState::~PersistentExpressionState ()
 {
 }
+
+lldb::addr_t
+PersistentExpressionState::LookupSymbol (const ConstString &name)
+{
+    SymbolMap::iterator si = m_symbol_map.find(name.GetCString());
+    
+    if (si != m_symbol_map.end())
+        return si->second;
+    else
+        return LLDB_INVALID_ADDRESS;
+}
+
+
+void
+PersistentExpressionState::RegisterExecutionUnit (lldb::IRExecutionUnitSP &execution_unit_sp)
+{
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+    
+    m_execution_units.insert(execution_unit_sp);
+    
+    if (log)
+        log->Printf ("Registering JITted Functions:\n");
+    
+    for (const IRExecutionUnit::JittedFunction &jitted_function : execution_unit_sp->GetJittedFunctions())
+    {
+        if (jitted_function.m_external &&
+            jitted_function.m_name != execution_unit_sp->GetFunctionName() &&
+            jitted_function.m_remote_addr != LLDB_INVALID_ADDRESS)
+        {
+            m_symbol_map[jitted_function.m_name.GetCString()] = jitted_function.m_remote_addr;
+            if (log)
+                log->Printf ("  Function: %s at 0x%" PRIx64 ".", jitted_function.m_name.GetCString(), jitted_function.m_remote_addr);
+        }
+    }
+    
+    if (log)
+        log->Printf ("Registering JIIted Symbols:\n");
+    
+    for (const IRExecutionUnit::JittedGlobalVariable &global_var : execution_unit_sp->GetJittedGlobalVariables())
+    {
+        if (global_var.m_remote_addr != LLDB_INVALID_ADDRESS)
+        {
+            // Demangle the name before inserting it, so that lookups by the ConstStr of the demangled name
+            // will find the mangled one (needed for looking up metadata pointers.)
+            Mangled mangler(global_var.m_name);
+            mangler.GetDemangledName(lldb::eLanguageTypeUnknown);
+            m_symbol_map[global_var.m_name.GetCString()] = global_var.m_remote_addr;
+            if (log)
+                log->Printf ("  Symbol: %s at 0x%" PRIx64 ".", global_var.m_name.GetCString(), global_var.m_remote_addr);
+        }
+    }
+}

Modified: lldb/trunk/source/Expression/IRExecutionUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRExecutionUnit.cpp?rev=263995&r1=263994&r2=263995&view=diff
==============================================================================
--- lldb/trunk/source/Expression/IRExecutionUnit.cpp (original)
+++ lldb/trunk/source/Expression/IRExecutionUnit.cpp Mon Mar 21 17:23:38 2016
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/IR/Constants.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/SourceMgr.h"
@@ -28,6 +29,7 @@
 #include "lldb/Target/ExecutionContext.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Utility/LLDBAssert.h"
 
 #include "lldb/../../source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
 
@@ -48,7 +50,8 @@ IRExecutionUnit::IRExecutionUnit (std::u
     m_sym_ctx(sym_ctx),
     m_did_jit(false),
     m_function_load_addr(LLDB_INVALID_ADDRESS),
-    m_function_end_load_addr(LLDB_INVALID_ADDRESS)
+    m_function_end_load_addr(LLDB_INVALID_ADDRESS),
+    m_reported_allocations(false)
 {
 }
 
@@ -122,7 +125,7 @@ IRExecutionUnit::DisassembleFunction (St
 
     for (JittedFunction &function : m_jitted_functions)
     {
-        if (strstr(function.m_name.c_str(), m_name.AsCString()))
+        if (function.m_name.AsCString() != m_name.AsCString())
         {
             func_local_addr = function.m_local_addr;
             func_remote_addr = function.m_remote_addr;
@@ -285,7 +288,6 @@ IRExecutionUnit::GetRunnableInfo(Error &
     }
 
     llvm::Triple triple(m_module->getTargetTriple());
-    llvm::Function *function = m_module->getFunction (m_name.AsCString());
     llvm::Reloc::Model relocModel;
     llvm::CodeModel::Model codeModel;
 
@@ -340,34 +342,69 @@ IRExecutionUnit::GetRunnableInfo(Error &
 
     m_execution_engine_ap->DisableLazyCompilation();
 
-    // We don't actually need the function pointer here, this just forces it to get resolved.
-
-    void *fun_ptr = m_execution_engine_ap->getPointerToFunction(function);
-
-    if (!error.Success())
+    for (llvm::Function &function : *m_module)
     {
-        // We got an error through our callback!
-        return;
+        if (function.isDeclaration())
+            continue;
+        
+        const bool external = function.hasExternalLinkage() || function.hasLinkOnceODRLinkage();
+        
+        void *fun_ptr = m_execution_engine_ap->getPointerToFunction(&function);
+        
+        if (!error.Success())
+        {
+            // We got an error through our callback!
+            return;
+        }
+        
+        if (!fun_ptr)
+        {
+            error.SetErrorToGenericError();
+            error.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", function.getName().str().c_str());
+            return;
+        }
+        m_jitted_functions.push_back (JittedFunction(function.getName().str().c_str(), external, (lldb::addr_t)fun_ptr));
     }
 
-    if (!function)
+    CommitAllocations(process_sp);
+    ReportAllocations(*m_execution_engine_ap);
+    
+    // We have to do this after calling ReportAllocations because for the MCJIT, getGlobalValueAddress
+    // will cause the JIT to perform all relocations.  That can only be done once, and has to happen
+    // after we do the remapping from local -> remote.
+    // That means we don't know the local address of the Variables, but we don't need that for anything,
+    // so that's okay.
+    
+    std::function<void (llvm::GlobalValue &)> RegisterOneValue = [this] (llvm::GlobalValue &val) {
+        if (val.hasExternalLinkage() && !val.isDeclaration())
+        {
+            uint64_t var_ptr_addr = m_execution_engine_ap->getGlobalValueAddress(val.getName().str());
+            
+            lldb::addr_t remote_addr = GetRemoteAddressForLocal(var_ptr_addr);
+            
+            // This is a really unfortunae API that sometimes returns local addresses and sometimes returns remote addresses, based on whether
+            // the variable was relocated during ReportAllocations or not.
+            
+            if (remote_addr == LLDB_INVALID_ADDRESS)
+            {
+                remote_addr = var_ptr_addr;
+            }
+                
+            if (var_ptr_addr != 0)
+                m_jitted_global_variables.push_back (JittedGlobalVariable (val.getName().str().c_str(), LLDB_INVALID_ADDRESS, remote_addr));
+        }
+    };
+    
+    for (llvm::GlobalVariable &global_var : m_module->getGlobalList())
     {
-        error.SetErrorToGenericError();
-        error.SetErrorStringWithFormat("Couldn't find '%s' in the JITted module", m_name.AsCString());
-        return;
+        RegisterOneValue(global_var);
     }
-
-    if (!fun_ptr)
+    
+    for (llvm::GlobalAlias &global_alias : m_module->getAliasList())
     {
-        error.SetErrorToGenericError();
-        error.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", m_name.AsCString());
-        return;
+        RegisterOneValue(global_alias);
     }
 
-    m_jitted_functions.push_back (JittedFunction(m_name.AsCString(), (lldb::addr_t)fun_ptr));
-
-    CommitAllocations(process_sp);
-    ReportAllocations(*m_execution_engine_ap);
     WriteData(process_sp);
 
     if (m_failed_lookups.size())
@@ -401,7 +438,7 @@ IRExecutionUnit::GetRunnableInfo(Error &
     {
         jitted_function.m_remote_addr = GetRemoteAddressForLocal (jitted_function.m_local_addr);
 
-        if (!jitted_function.m_name.compare(m_name.AsCString()))
+        if (!m_name.IsEmpty() && jitted_function.m_name == m_name)
         {
             AddrRange func_range = GetRemoteRangeForLocal(jitted_function.m_local_addr);
             m_function_end_load_addr = func_range.first + func_range.second;
@@ -612,6 +649,14 @@ IRExecutionUnit::MemoryManager::allocate
         log->Printf("IRExecutionUnit::allocateCodeSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p",
                     (uint64_t)Size, Alignment, SectionID, (void *)return_value);
     }
+    
+    if (m_parent.m_reported_allocations)
+    {
+        Error err;
+        lldb::ProcessSP process_sp = m_parent.GetBestExecutionContextScope()->CalculateProcess();
+        
+        m_parent.CommitOneAllocation(process_sp, err, m_parent.m_records.back());
+    }
 
     return return_value;
 }
@@ -642,6 +687,14 @@ IRExecutionUnit::MemoryManager::allocate
         log->Printf("IRExecutionUnit::allocateDataSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p",
                     (uint64_t)Size, Alignment, SectionID, (void *)return_value);
     }
+    
+    if (m_parent.m_reported_allocations)
+    {
+        Error err;
+        lldb::ProcessSP process_sp = m_parent.GetBestExecutionContextScope()->CalculateProcess();
+        
+        m_parent.CommitOneAllocation(process_sp, err, m_parent.m_records.back());
+    }
 
     return return_value;
 }
@@ -931,6 +984,22 @@ IRExecutionUnit::FindInRuntimes(const st
 }
 
 lldb::addr_t
+IRExecutionUnit::FindInUserDefinedSymbols(const std::vector<SearchSpec> &specs, const lldb_private::SymbolContext &sc)
+{
+    lldb::TargetSP target_sp = sc.target_sp;
+    
+    for (const SearchSpec &spec : specs)
+    {
+        lldb::addr_t symbol_load_addr = target_sp->GetPersistentSymbol(spec.name);
+        
+        if (symbol_load_addr != LLDB_INVALID_ADDRESS)
+            return symbol_load_addr;
+    }
+    
+    return LLDB_INVALID_ADDRESS;
+}
+
+lldb::addr_t
 IRExecutionUnit::FindSymbol(const lldb_private::ConstString &name)
 {
     std::vector<SearchSpec> candidate_C_names;
@@ -943,6 +1012,9 @@ IRExecutionUnit::FindSymbol(const lldb_p
         ret = FindInRuntimes(candidate_C_names, m_sym_ctx);
 
     if (ret == LLDB_INVALID_ADDRESS)
+        ret = FindInUserDefinedSymbols(candidate_C_names, m_sym_ctx);
+
+    if (ret == LLDB_INVALID_ADDRESS)
     {
         CollectCandidateCPlusPlusNames(candidate_CPlusPlus_names, candidate_C_names, m_sym_ctx);
         ret = FindInSymbols(candidate_CPlusPlus_names, m_sym_ctx);
@@ -951,6 +1023,42 @@ IRExecutionUnit::FindSymbol(const lldb_p
     return ret;
 }
 
+void
+IRExecutionUnit::GetStaticInitializers(std::vector <lldb::addr_t> &static_initializers)
+{
+    if (llvm::GlobalVariable *global_ctors = m_module->getNamedGlobal("llvm.global_ctors"))
+    {
+        if (llvm::ConstantArray *ctor_array = llvm::dyn_cast<llvm::ConstantArray>(global_ctors->getInitializer()))
+        {
+            for (llvm::Use &ctor_use : ctor_array->operands())
+            {
+                if (llvm::ConstantStruct *ctor_struct = llvm::dyn_cast<llvm::ConstantStruct>(ctor_use))
+                {
+                    lldbassert(ctor_struct->getNumOperands() == 3); // this is standardized
+                    if (llvm::Function *ctor_function = llvm::dyn_cast<llvm::Function>(ctor_struct->getOperand(1)))
+                    {
+                        ctor_function->dump();
+
+                        ConstString ctor_function_name_cs(ctor_function->getName().str());
+                        
+                        for (JittedFunction &jitted_function : m_jitted_functions)
+                        {
+                            if (ctor_function_name_cs == jitted_function.m_name)
+                            {
+                                if (jitted_function.m_remote_addr != LLDB_INVALID_ADDRESS)
+                                {
+                                    static_initializers.push_back(jitted_function.m_remote_addr);
+                                }
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
 uint64_t
 IRExecutionUnit::MemoryManager::getSymbolAddress(const std::string &Name)
 {
@@ -1039,19 +1147,17 @@ IRExecutionUnit::GetRemoteRangeForLocal
 }
 
 bool
-IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp)
+IRExecutionUnit::CommitOneAllocation (lldb::ProcessSP &process_sp,
+                                      Error &error,
+                                      AllocationRecord &record)
 {
-    bool ret = true;
-
-    lldb_private::Error err;
-
-    for (AllocationRecord &record : m_records)
+    if (record.m_process_address != LLDB_INVALID_ADDRESS)
+    {
+        return true;
+    }
+    
+    switch (record.m_sect_type)
     {
-        if (record.m_process_address != LLDB_INVALID_ADDRESS)
-            continue;
-
-        switch (record.m_sect_type)
-        {
         case lldb::eSectionTypeInvalid:
         case lldb::eSectionTypeDWARFDebugAbbrev:
         case lldb::eSectionTypeDWARFDebugAddr:
@@ -1070,7 +1176,7 @@ IRExecutionUnit::CommitAllocations (lldb
         case lldb::eSectionTypeDWARFAppleTypes:
         case lldb::eSectionTypeDWARFAppleNamespaces:
         case lldb::eSectionTypeDWARFAppleObjC:
-            err.Clear();
+            error.Clear();
             break;
         default:
             const bool zero_memory = false;
@@ -1079,13 +1185,26 @@ IRExecutionUnit::CommitAllocations (lldb
                                                record.m_permissions,
                                                eAllocationPolicyProcessOnly,
                                                zero_memory,
-                                               err);
+                                               error);
             break;
-        }
+    }
+    
+    return error.Success();
+}
 
-        if (!err.Success())
+bool
+IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp)
+{
+    bool ret = true;
+
+    lldb_private::Error err;
+
+    for (AllocationRecord &record : m_records)
+    {
+        ret = CommitOneAllocation(process_sp, err, record);
+        
+        if (!ret)
         {
-            ret = false;
             break;
         }
     }
@@ -1108,6 +1227,8 @@ IRExecutionUnit::CommitAllocations (lldb
 void
 IRExecutionUnit::ReportAllocations (llvm::ExecutionEngine &engine)
 {
+    m_reported_allocations = true;
+    
     for (AllocationRecord &record : m_records)
     {
         if (record.m_process_address == LLDB_INVALID_ADDRESS)

Modified: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp?rev=263995&r1=263994&r2=263995&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp (original)
+++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp Mon Mar 21 17:23:38 2016
@@ -80,6 +80,7 @@
 #include "lldb/Target/ObjCLanguageRuntime.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadPlanCallFunction.h"
 #include "lldb/Utility/LLDBAssert.h"
 
 using namespace clang;
@@ -214,6 +215,56 @@ private:
     std::shared_ptr<clang::TextDiagnosticBuffer> m_passthrough;
 };
 
+class LoggingDiagnosticConsumer : public clang::DiagnosticConsumer
+{
+public:
+    LoggingDiagnosticConsumer ()
+    {
+        m_log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
+        m_passthrough.reset(new clang::TextDiagnosticBuffer);
+    }
+    
+    LoggingDiagnosticConsumer (const std::shared_ptr<clang::TextDiagnosticBuffer> &passthrough)
+    {
+        m_log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
+        m_passthrough = passthrough;
+    }
+    
+    void HandleDiagnostic (DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info)
+    {
+        if (m_log)
+        {
+            llvm::SmallVector<char, 32> diag_str;
+            Info.FormatDiagnostic(diag_str);
+            diag_str.push_back('\0');
+            const char *data = diag_str.data();
+            m_log->Printf("[clang] COMPILER DIAGNOSTIC: %s", data);
+
+            lldbassert(Info.getID() != clang::diag::err_unsupported_ast_node && "'log enable lldb expr' to investigate.");
+        }
+        
+        m_passthrough->HandleDiagnostic(DiagLevel, Info);
+    }
+    
+    void FlushDiagnostics (DiagnosticsEngine &Diags)
+    {
+        m_passthrough->FlushDiagnostics(Diags);
+    }
+    
+    DiagnosticConsumer *clone (DiagnosticsEngine &Diags) const
+    {
+        return new LoggingDiagnosticConsumer (m_passthrough);
+    }
+    
+    clang::TextDiagnosticBuffer *GetPassthrough()
+    {
+        return m_passthrough.get();
+    }
+private:
+    Log * m_log;
+    std::shared_ptr<clang::TextDiagnosticBuffer> m_passthrough;
+};
+
 //===----------------------------------------------------------------------===//
 // Implementation of ClangExpressionParser
 //===----------------------------------------------------------------------===//
@@ -769,3 +820,51 @@ ClangExpressionParser::PrepareForExecuti
 
     return err;
 }
+
+Error
+ClangExpressionParser::RunStaticInitializers (lldb::IRExecutionUnitSP &execution_unit_sp,
+                                              ExecutionContext &exe_ctx)
+{
+    Error err;
+    
+    lldbassert(execution_unit_sp.get());
+    lldbassert(exe_ctx.HasThreadScope());
+    
+    if (!execution_unit_sp.get())
+    {
+        err.SetErrorString ("can't run static initializers for a NULL execution unit");
+        return err;
+    }
+    
+    if (!exe_ctx.HasThreadScope())
+    {
+        err.SetErrorString ("can't run static initializers without a thread");
+        return err;
+    }
+    
+    std::vector<lldb::addr_t> static_initializers;
+    
+    execution_unit_sp->GetStaticInitializers(static_initializers);
+    
+    for (lldb::addr_t static_initializer : static_initializers)
+    {
+        EvaluateExpressionOptions options;
+                
+        lldb::ThreadPlanSP call_static_initializer(new ThreadPlanCallFunction(exe_ctx.GetThreadRef(),
+                                                                              Address(static_initializer),
+                                                                              CompilerType(),
+                                                                              llvm::ArrayRef<lldb::addr_t>(),
+                                                                              options));
+        
+        DiagnosticManager execution_errors;
+        lldb::ExpressionResults results = exe_ctx.GetThreadRef().GetProcess()->RunThreadPlan(exe_ctx, call_static_initializer, options, execution_errors);
+        
+        if (results != lldb::eExpressionCompleted)
+        {
+            err.SetErrorStringWithFormat ("couldn't run static initializer: %s", execution_errors.GetString().c_str());
+            return err;
+        }
+    }
+    
+    return err;
+}

Modified: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h?rev=263995&r1=263994&r2=263995&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h (original)
+++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h Mon Mar 21 17:23:38 2016
@@ -118,6 +118,22 @@ public:
                          ExecutionContext &exe_ctx,
                          bool &can_interpret,
                          lldb_private::ExecutionPolicy execution_policy) override;
+    
+    //------------------------------------------------------------------
+    /// Run all static initializers for an execution unit.
+    ///
+    /// @param[in] execution_unit_sp
+    ///     The execution unit.
+    ///
+    /// @param[in] exe_ctx
+    ///     The execution context to use when running them.  Thread can't be null.
+    ///
+    /// @return
+    ///     The error code indicating the 
+    //------------------------------------------------------------------
+    Error
+    RunStaticInitializers (lldb::IRExecutionUnitSP &execution_unit_sp,
+                           ExecutionContext &exe_ctx);
         
 private:
     std::unique_ptr<llvm::LLVMContext>       m_llvm_context;         ///< The LLVM context to generate IR into




More information about the lldb-commits mailing list