Oke got that figured out. Attached patch works perfectly and stores the cached functions in the Target. I've managed to make the changes in existing classes minimal by creating a ClangFunction subclass.
comments welcome. -- Carlo Kok RemObjects Software
Index: include/lldb/API/SBExpressionOptions.h =================================================================== --- include/lldb/API/SBExpressionOptions.h (revision 219490) +++ include/lldb/API/SBExpressionOptions.h (working copy) @@ -118,6 +118,8 @@ friend class SBFrame; friend class SBValue; friend class SBTarget; + friend class SBTypeMemberFunction; + friend class SBFunction; private: // This auto_pointer is made in the constructor and is always valid. Index: include/lldb/API/SBFrame.h =================================================================== --- include/lldb/API/SBFrame.h (revision 219490) +++ include/lldb/API/SBFrame.h (working copy) @@ -210,6 +210,8 @@ friend class SBInstruction; friend class SBThread; friend class SBValue; + friend class SBTypeMemberFunction; + friend class SBFunction; #ifndef LLDB_DISABLE_PYTHON friend class lldb_private::ScriptInterpreterPython; #endif Index: include/lldb/API/SBFunction.h =================================================================== --- include/lldb/API/SBFunction.h (revision 219490) +++ include/lldb/API/SBFunction.h (working copy) @@ -68,6 +68,13 @@ bool GetDescription (lldb::SBStream &description); + lldb::SBValue ExecuteFunction(lldb::SBFrame &frame, + lldb::SBValueList arguments, + lldb::SBStream &errors, + lldb::SBExpressionOptions options, + bool reusable); + + void RemoveReusableFunction (lldb::SBTarget &target); protected: lldb_private::Function * Index: include/lldb/API/SBTarget.h =================================================================== --- include/lldb/API/SBTarget.h (revision 219490) +++ include/lldb/API/SBTarget.h (working copy) @@ -942,6 +942,7 @@ friend class SBSourceManager; friend class SBSymbol; friend class SBValue; + friend class SBTypeMemberFunction; //------------------------------------------------------------------ // Constructors are private, use static Target::Create function to Index: include/lldb/API/SBType.h =================================================================== --- include/lldb/API/SBType.h (revision 219490) +++ include/lldb/API/SBType.h (working copy) @@ -104,7 +104,15 @@ bool GetDescription (lldb::SBStream &description, lldb::DescriptionLevel description_level); - + + lldb::SBValue ExecuteFunction (lldb::SBFrame &frame, + lldb::SBValue self, + lldb::SBValueList arguments, + lldb::SBStream &errors, + lldb::SBExpressionOptions options, + bool reusable); + + void RemoveReusableFunction(lldb::SBTarget& target); protected: friend class SBType; Index: include/lldb/Expression/ClangFunction.h =================================================================== --- include/lldb/Expression/ClangFunction.h (revision 219490) +++ include/lldb/Expression/ClangFunction.h (working copy) @@ -23,6 +23,7 @@ #include "lldb/Core/ValueObjectList.h" #include "lldb/Expression/ClangExpression.h" #include "lldb/Target/Process.h" +#include "lldb/Target/ExecutionContext.h" namespace lldb_private { @@ -133,7 +134,7 @@ /// @return /// The number of errors. //------------------------------------------------------------------ - unsigned + virtual unsigned CompileFunction (Stream &errors); //------------------------------------------------------------------ @@ -406,7 +407,13 @@ { return m_arg_values; } -private: + + Address + GetFunctionAddress() const + { + return m_function_addr; + } +protected: //------------------------------------------------------------------ // For ClangFunction only //------------------------------------------------------------------ @@ -443,6 +450,76 @@ bool m_JITted; ///< True if the wrapper function has already been JIT-compiled. }; +class ClangFunctionWithDeclMap : public ClangFunction +{ +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] exe_scope + /// An execution context scope that gets us at least a target and + /// process. + /// + /// @param[in] function_ptr + /// The default function to be called. Can be overridden using + /// WriteFunctionArguments(). + /// + /// @param[in] ast_context + /// The AST context to evaluate argument types in. + /// + /// @param[in] arg_value_list + /// The default values to use when calling this function. Can + /// be overridden using WriteFunctionArguments(). + //------------------------------------------------------------------ + ClangFunctionWithDeclMap (ExecutionContextScope &exe_scope, + Function &function_ptr, + ClangASTContext *ast_context, + const ValueList &arg_value_list, + const char *name); + + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] exe_scope + /// An execution context scope that gets us at least a target and + /// process. + /// + /// @param[in] ast_context + /// The AST context to evaluate argument types in. + /// + /// @param[in] return_qualtype + /// An opaque Clang QualType for the function result. Should be + /// defined in ast_context. + /// + /// @param[in] function_address + /// The address of the function to call. + /// + /// @param[in] arg_value_list + /// The default values to use when calling this function. Can + /// be overridden using WriteFunctionArguments(). + //------------------------------------------------------------------ + ClangFunctionWithDeclMap (ExecutionContextScope &exe_scope, + const ClangASTType &return_type, + const Address& function_address, + const ValueList &arg_value_list, + const char *name); + + ClangExpressionDeclMap * + DeclMap () + { + return m_expr_decl_map.get(); + } + + unsigned + CompileFunction (Stream &errors); + +private: + ExecutionContext m_context; + std::shared_ptr<Materializer> m_materializer; + std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map; ///< The map to use when parsing the expression. + +}; + } // Namespace lldb_private #endif // lldb_ClangFunction_h_ Index: include/lldb/Target/ObjCLanguageRuntime.h =================================================================== --- include/lldb/Target/ObjCLanguageRuntime.h (revision 219490) +++ include/lldb/Target/ObjCLanguageRuntime.h (working copy) @@ -510,6 +510,11 @@ { m_negative_complete_class_cache.clear(); } + + + lldb::addr_t + GetSelectorFor(const ConstString& value, ExecutionContextScope *exe_scope); + protected: //------------------------------------------------------------------ @@ -607,11 +612,13 @@ typedef std::multimap<uint32_t, ObjCISA> HashToISAMap; typedef ISAToDescriptorMap::iterator ISAToDescriptorIterator; typedef HashToISAMap::iterator HashToISAIterator; + typedef std::map<ConstString, lldb::addr_t> SelectorMap; MsgImplMap m_impl_cache; LazyBool m_has_new_literals_and_indexing; ISAToDescriptorMap m_isa_to_descriptor; HashToISAMap m_hash_to_isa_map; + SelectorMap m_selector_map; protected: uint32_t m_isa_to_descriptor_stop_id; Index: include/lldb/Target/Target.h =================================================================== --- include/lldb/Target/Target.h (revision 219490) +++ include/lldb/Target/Target.h (working copy) @@ -1345,6 +1345,25 @@ lldb::SearchFilterSP GetSearchFilterForModuleAndCUList (const FileSpecList *containingModules, const FileSpecList *containingSourceFiles); + std::shared_ptr<ClangFunction>& GetOrAddClangFunction (Function* func) + { + return m_clang_functions[func]; + } + + std::shared_ptr<ClangFunction>& GetOrAddClangFunction (TypeMemberFunctionImpl* func) + { + return m_clang_functions[func]; + } + + void RemoveClangFunction (Function* func) + { + m_clang_functions.erase (func); + } + + void RemoveClangFunction (TypeMemberFunctionImpl* func) + { + m_clang_functions.erase (func); + } protected: //------------------------------------------------------------------ // Member variables. @@ -1378,6 +1397,9 @@ lldb::user_id_t m_stop_hook_next_id; bool m_valid; bool m_suppress_stop_hooks; + typedef std::map<void*, std::shared_ptr<ClangFunction>> ClangFunctionCollection; + ClangFunctionCollection m_clang_functions; + static void ImageSearchPathsChanged (const PathMappingList &path_list, Index: scripts/Python/interface/SBFunction.i =================================================================== --- scripts/Python/interface/SBFunction.i (revision 219490) +++ scripts/Python/interface/SBFunction.i (working copy) @@ -85,7 +85,15 @@ bool GetDescription (lldb::SBStream &description); - + + lldb::SBValue ExecuteFunction(lldb::SBFrame &frame, + lldb::SBValueList arguments, + lldb::SBStream &errors, + lldb::SBExpressionOptions options, + bool reusable); + + void RemoveReusableFunction (lldb::SBTarget &target); + bool operator == (const lldb::SBFunction &rhs) const; Index: scripts/Python/interface/SBType.i =================================================================== --- scripts/Python/interface/SBType.i (revision 219490) +++ scripts/Python/interface/SBType.i (working copy) @@ -101,7 +101,15 @@ bool GetDescription (lldb::SBStream &description, lldb::DescriptionLevel description_level); - + + lldb::SBValue ExecuteFunction (lldb::SBFrame &frame, + lldb::SBValue self, + lldb::SBValueList arguments, + lldb::SBStream &errors, + lldb::SBExpressionOptions options, + bool reusable); + + void RemoveReusableFunction(lldb::SBTarget& target); protected: lldb::TypeMemberFunctionImplSP m_opaque_sp; }; Index: source/API/SBFunction.cpp =================================================================== --- source/API/SBFunction.cpp (revision 219490) +++ source/API/SBFunction.cpp (working copy) @@ -18,6 +18,12 @@ #include "lldb/Symbol/Type.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Target.h" +#include "lldb/API/SBExpressionOptions.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/API/SBFrame.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Expression/ClangFunction.h" using namespace lldb; using namespace lldb_private; @@ -229,3 +235,79 @@ +lldb::SBValue SBFunction::ExecuteFunction(lldb::SBFrame &frame, + lldb::SBValueList arguments, + lldb::SBStream &errors, + lldb::SBExpressionOptions options, + bool reusable) +{ + if (!m_opaque_ptr) + { + errors->PutCString("no value"); + return SBValue(); + } + + ExecutionContext exe_ctx = frame.GetFrameSP(); + + if (!exe_ctx.GetFrameSP()) + { + errors->PutCString("no frame"); + return SBValue(); + } + + ValueList args; + for (int i = 0; i < arguments.GetSize(); i++) + { + const ValueObjectSP value = arguments.GetValueAtIndex(i).GetSP(); + value->UpdateValueIfNeeded(); + args.PushValue(value->GetValue()); + } + //arguments. + + std::shared_ptr<ClangFunction>& func = exe_ctx.GetTargetPtr ()->GetOrAddClangFunction (m_opaque_ptr); + + if (!func) + { + func.reset (new ClangFunctionWithDeclMap (*frame.GetFrameSP (), + m_opaque_ptr->GetClangType ().GetFunctionReturnType (), + m_opaque_ptr->GetAddressRange ().GetBaseAddress (), + args, + m_opaque_ptr->GetName ().GetCString ())); + + if (func->CompileFunction (*errors.get ())) + return SBValue (); + + if (!func->WriteFunctionWrapper (exe_ctx, *errors.get ())) + return SBValue (); + } + errors.Clear (); + + lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; + if (!func->WriteFunctionArguments (exe_ctx, args_addr, + func->GetFunctionAddress (), args, *errors.get ())) + { + return SBValue (); + } + + Value res; + if (func->ExecuteFunction (exe_ctx, &args_addr, *options.get (), *errors.get (), res)) + { + func->DeallocateFunctionResults (exe_ctx, args_addr); + if (!reusable) + exe_ctx.GetTargetPtr ()->RemoveClangFunction (m_opaque_ptr); + return SBValue (); + } + + SBValue results = ValueObjectConstResult::Create (exe_ctx.GetThreadPtr(), res, ConstString ("<evaluation result>")); + + func->DeallocateFunctionResults (exe_ctx, args_addr); + if (!reusable) + exe_ctx.GetTargetPtr ()->RemoveClangFunction (m_opaque_ptr); + return results; +} + +void SBFunction::RemoveReusableFunction (lldb::SBTarget &target) +{ + if (target.m_opaque_sp) + target.m_opaque_sp->RemoveClangFunction (m_opaque_ptr); +} \ No newline at end of file Index: source/API/SBType.cpp =================================================================== --- source/API/SBType.cpp (revision 219490) +++ source/API/SBType.cpp (working copy) @@ -17,6 +17,22 @@ #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ClangASTType.h" #include "lldb/Symbol/Type.h" +#include "lldb/API/SBValue.h" +#include "lldb/API/SBValueList.h" +#include "lldb/API/SBExpressionOptions.h" +#include "lldb/API/SBError.h" +#include "lldb/API/SBFrame.h" +#include "lldb/Expression/ClangFunction.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/API/SBValueList.h" +#include "lldb/Target/Thread.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Target/Target.h" +#include "lldb/Symbol/Symbol.h" +#include "lldb/API/SBTarget.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/ObjCLanguageRuntime.h" #include "clang/AST/Decl.h" @@ -821,3 +837,106 @@ { return *m_opaque_sp.get(); } + +void SBTypeMemberFunction::RemoveReusableFunction (lldb::SBTarget& target) +{ + if (target.m_opaque_sp) + target.m_opaque_sp->RemoveClangFunction (m_opaque_sp.get ()); +} + +lldb::SBValue SBTypeMemberFunction::ExecuteFunction (lldb::SBFrame &frame, + lldb::SBValue self, + lldb::SBValueList arguments, + lldb::SBStream &errors, + lldb::SBExpressionOptions options, + bool reusable) +{ + if (!m_opaque_sp) + { + errors->PutCString ("no value"); + return SBValue (); + } + if (!self.IsValid ()) + { + errors->PutCString ("No self"); + return SBValue (); + } + + if (!frame.GetFrameSP ()) + { + errors->PutCString ("no frame"); + return SBValue (); + } + + ExecutionContext exe_ctx; + frame.GetFrameSP ()->CalculateExecutionContext (exe_ctx); + + TypeMemberFunctionImpl& val = *m_opaque_sp.get (); + + ValueList args; + ClangASTContext* ast = exe_ctx.GetTargetPtr ()->GetScratchClangASTContext (); + ClangASTType pointertype = ast->GetCStringType (true); + ValueObjectSP selfptr = self.GetSP ()->Cast (pointertype); + selfptr->UpdateValueIfNeeded (); + args.PushValue (selfptr->GetValue ()); + + uint64_t sel = exe_ctx.GetProcessPtr ()->GetObjCLanguageRuntime ()->GetSelectorFor (ConstString (m_opaque_sp->GetName ()), exe_ctx.GetFramePtr ()); + Value selectorvalue (ast->GetPointerByteSize () == 4 ? Scalar ((uint32_t)sel) : Scalar (sel)); + selectorvalue.SetClangType (pointertype); + args.PushValue (selectorvalue); + + + for (int i = 0; i < arguments.GetSize (); i++) { + const ValueObjectSP value = arguments.GetValueAtIndex (i).GetSP (); + value->UpdateValueIfNeeded (); + args.PushValue (value->GetValue ()); + } + + std::shared_ptr<ClangFunction>& func = exe_ctx.GetTargetPtr ()->GetOrAddClangFunction (m_opaque_sp.get ()); + + if (!func) + { + SymbolContextList sclist; + exe_ctx.GetTargetPtr ()->GetImages ().FindFunctions (ConstString ("objc_msgSend"), eFunctionNameTypeAny, + true, false, true, sclist); + if (!sclist.GetSize ()) { + errors->PutCString ("Cannot find msgSend"); + return SBValue (); + } + Address* msgsend_address = &sclist[0].symbol->GetAddress (); + func.reset (new ClangFunctionWithDeclMap (*frame.GetFrameSP (), + m_opaque_sp->GetReturnType (), + *msgsend_address, + args, + m_opaque_sp->GetName ().GetCString ())); + + + if (func->CompileFunction (*errors.get ())) + return SBValue (); + + if (!func->WriteFunctionWrapper (exe_ctx, *errors.get ())) + return SBValue (); + } + errors.Clear (); + + lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; + if (!func->WriteFunctionArguments (exe_ctx, args_addr, + func->GetFunctionAddress (), args, *errors.get ())) + { + return SBValue (); + } + + Value res; + if (func->ExecuteFunction (exe_ctx, &args_addr, *options.get (), *errors.get (), res)) + { + func->DeallocateFunctionResults (exe_ctx, args_addr); + if (!reusable) + exe_ctx.GetTargetPtr ()->RemoveClangFunction (m_opaque_sp.get ()); + return SBValue (); + } + + func->DeallocateFunctionResults (exe_ctx, args_addr); + if (!reusable) + exe_ctx.GetTargetPtr ()->RemoveClangFunction (m_opaque_sp.get ()); + return ValueObjectConstResult::Create (exe_ctx.GetThreadPtr (), res, ConstString ("<evaluation result>")); +} Index: source/Expression/ClangFunction.cpp =================================================================== --- source/Expression/ClangFunction.cpp (revision 219490) +++ source/Expression/ClangFunction.cpp (working copy) @@ -43,6 +43,7 @@ #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlan.h" #include "lldb/Target/ThreadPlanCallFunction.h" +#include "lldb/Expression/ClangExpressionDeclMap.h" using namespace lldb_private; @@ -594,3 +595,48 @@ return m_struct_extractor.get(); } + + +ClangFunctionWithDeclMap::ClangFunctionWithDeclMap (ExecutionContextScope &exe_scope, + Function &function_ptr, + ClangASTContext *ast_context, + const ValueList &arg_value_list, + const char *name) + : ClangFunction (exe_scope, function_ptr, ast_context, arg_value_list, name) +{ + exe_scope.CalculateExecutionContext (m_context); + // ClangASTSource depends on the struct name starting with $ for external lookups + m_wrapper_struct_name = "$__lldb_caller_struct"; +} + +ClangFunctionWithDeclMap::ClangFunctionWithDeclMap (ExecutionContextScope &exe_scope, + const ClangASTType &return_type, + const Address& function_address, + const ValueList &arg_value_list, + const char *name) + + : ClangFunction (exe_scope, return_type, function_address, arg_value_list, name) +{ + exe_scope.CalculateExecutionContext (m_context); + // ClangASTSource depends on the struct name starting with $ for external lookups + m_wrapper_struct_name = "$__lldb_caller_struct"; +} + + +unsigned ClangFunctionWithDeclMap::CompileFunction (Stream &errors) +{ + if (!m_materializer) + m_materializer.reset (new Materializer ()); + + if (!m_expr_decl_map) + m_expr_decl_map.reset (new ClangExpressionDeclMap (false, m_context)); + + if (!m_expr_decl_map->WillParse (m_context, m_materializer.get ())) + { + errors.PutCString ("Could not materialize"); + return 1; + } + unsigned res = ClangFunction::CompileFunction (errors); + + return res; +} \ No newline at end of file Index: source/Target/ObjCLanguageRuntime.cpp =================================================================== --- source/Target/ObjCLanguageRuntime.cpp (revision 219490) +++ source/Target/ObjCLanguageRuntime.cpp (working copy) @@ -19,6 +19,7 @@ #include "lldb/Symbol/TypeList.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Target.h" +#include "lldb/Core/ValueObjectConstResult.h" #include "llvm/ADT/StringRef.h" @@ -626,3 +627,22 @@ { return nullptr; } + +lldb::addr_t +ObjCLanguageRuntime::GetSelectorFor (const ConstString& value, ExecutionContextScope *exe_scope) +{ + auto res = m_selector_map.find (value); + if (res != m_selector_map.end ()) + return res->second; + + ValueList args; + std::string selector; + selector = selector + "((void* (*)(char*))sel_registerName)(\"" + value.AsCString () + "\")"; + ValueObjectSP selectorptr; + exe_scope->CalculateTarget ()->EvaluateExpression (selector.c_str (), exe_scope->CalculateStackFrame ().get (), selectorptr); + + addr_t result = selectorptr->GetValueAsUnsigned (0); + if (result) + m_selector_map[value] = result; + return result; +} \ No newline at end of file
_______________________________________________ lldb-dev mailing list lldb-dev@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev