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 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits