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
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev