Re: [Lldb-commits] [PATCH] D9404: Expression evaluation, a new ThreadPlanCallFunctionNoJIT for executing a function call on target via register manipulation
This revision was automatically updated to reflect the committed changes. Closed by commit rL242137: Expression evaluation, a new ThreadPlanCallFunctionUsingABI for executing a… (authored by EwanCrawford). Changed prior to commit: http://reviews.llvm.org/D9404?vs=29343&id=29661#toc Repository: rL LLVM http://reviews.llvm.org/D9404 Files: lldb/trunk/include/lldb/Expression/IRInterpreter.h lldb/trunk/include/lldb/Expression/IRMemoryMap.h lldb/trunk/include/lldb/Target/ABI.h lldb/trunk/include/lldb/Target/Process.h lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h lldb/trunk/include/lldb/Target/ThreadPlanCallFunctionUsingABI.h lldb/trunk/lldb.xcodeproj/project.pbxproj lldb/trunk/source/Expression/ClangExpressionParser.cpp lldb/trunk/source/Expression/ClangUserExpression.cpp lldb/trunk/source/Expression/IRInterpreter.cpp lldb/trunk/source/Expression/IRMemoryMap.cpp lldb/trunk/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp lldb/trunk/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp lldb/trunk/source/Target/CMakeLists.txt lldb/trunk/source/Target/Process.cpp lldb/trunk/source/Target/ThreadPlanCallFunction.cpp lldb/trunk/source/Target/ThreadPlanCallFunctionUsingABI.cpp lldb/trunk/test/expression_command/call-function/TestCallUserDefinedFunction.py lldb/trunk/test/expression_command/call-function/main.cpp Index: lldb/trunk/source/Target/Process.cpp === --- lldb/trunk/source/Target/Process.cpp +++ lldb/trunk/source/Target/Process.cpp @@ -754,6 +754,7 @@ m_force_next_event_delivery (false), m_last_broadcast_state (eStateInvalid), m_destroy_in_process (false), +m_can_interpret_function_calls(false), m_can_jit(eCanJITDontKnow) { CheckInWithManager (); @@ -3011,6 +3012,13 @@ m_can_jit = (can_jit ? eCanJITYes : eCanJITNo); } +void +Process::SetCanRunCode (bool can_run_code) +{ +SetCanJIT(can_run_code); +m_can_interpret_function_calls = can_run_code; +} + Error Process::DeallocateMemory (addr_t ptr) { Index: lldb/trunk/source/Target/CMakeLists.txt === --- lldb/trunk/source/Target/CMakeLists.txt +++ lldb/trunk/source/Target/CMakeLists.txt @@ -40,6 +40,7 @@ ThreadPlan.cpp ThreadPlanBase.cpp ThreadPlanCallFunction.cpp + ThreadPlanCallFunctionUsingABI.cpp ThreadPlanCallUserExpression.cpp ThreadPlanPython.cpp ThreadPlanRunToAddress.cpp Index: lldb/trunk/source/Target/ThreadPlanCallFunction.cpp === --- lldb/trunk/source/Target/ThreadPlanCallFunction.cpp +++ lldb/trunk/source/Target/ThreadPlanCallFunction.cpp @@ -147,15 +147,16 @@ m_trap_exceptions (options.GetTrapExceptions()), m_function_addr (function), m_function_sp (0), -m_return_type (return_type), m_takedown_done (false), m_should_clear_objc_exception_bp(false), m_should_clear_cxx_exception_bp (false), -m_stop_address (LLDB_INVALID_ADDRESS) +m_stop_address (LLDB_INVALID_ADDRESS), +m_return_type (return_type) { -lldb::addr_t start_load_addr; -ABI *abi; -lldb::addr_t function_load_addr; +lldb::addr_t start_load_addr = LLDB_INVALID_ADDRESS; +lldb::addr_t function_load_addr = LLDB_INVALID_ADDRESS; +ABI *abi = nullptr; + if (!ConstructorSetup (thread, abi, start_load_addr, function_load_addr)) return; @@ -171,6 +172,27 @@ m_valid = true; } +ThreadPlanCallFunction::ThreadPlanCallFunction(Thread &thread, + const Address &function, + const EvaluateExpressionOptions &options) : +ThreadPlan(ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion), +m_valid(false), +m_stop_other_threads(options.GetStopOthers()), +m_unwind_on_error(options.DoesUnwindOnError()), +m_ignore_breakpoints(options.DoesIgnoreBreakpoints()), +m_debug_execution(options.GetDebug()), +m_trap_exceptions(options.GetTrapExceptions()), +m_function_addr(function), +m_function_sp(0), +m_takedown_done(false), +m_should_clear_objc_exception_bp(false), +m_should_clear_cxx_exception_bp(false), +m_stop_address(LLDB_INVALID_ADDRESS), +m_return_type(ClangASTType()) +{ + +} + ThreadPlanCallFunction::~ThreadPlanCallFunction () { DoTakedown(PlanSucceeded()); @@ -222,13 +244,7 @@ { if (success) { -ProcessSP process_sp (m_thread.GetProcess()); -const ABI *abi = process_sp ? process_sp->GetABI().get() : NULL; -if (abi && m_return_type.IsValid()) -{ -const bool persistent = false; -m_return_valobj_sp = abi->GetReturnValueOb
Re: [Lldb-commits] [PATCH] D9404: Expression evaluation, a new ThreadPlanCallFunctionNoJIT for executing a function call on target via register manipulation
For my part that looks great. Jim > On Jul 9, 2015, at 10:03 AM, Ewan Crawford wrote: > > EwanCrawford updated this revision to Diff 29343. > EwanCrawford added a comment. > > To address that final point of not doing any code execution at all for > certain targets. I used the CanJIT() idea to create a similar > CanInterpretFunctionCalls() member function of Process. > This means that we can just pass the value of the > m_can_interpret_function_calls variable to CanInterpret() instead of the Arch > or execution context. > > Since interpreting function calls is a special case for hexagon right now the > value defaults to false, and is only set to true by the hexagon dynamic > loader. > > In the future though when more targets support this feature, > CanInterpretFunctionCalls() would be enabled by default and then specifically > disabled by targets. > Using the example of the OSX kernel, which can't do any code execution, the > patch explicitly sets jitting and interpreting function calls to false in the > dynamic loader using an added CanRunCode() function. > > > Repository: > rL LLVM > > http://reviews.llvm.org/D9404 > > Files: > include/lldb/Expression/IRInterpreter.h > include/lldb/Expression/IRMemoryMap.h > include/lldb/Target/ABI.h > include/lldb/Target/Process.h > include/lldb/Target/ThreadPlanCallFunction.h > include/lldb/Target/ThreadPlanCallFunctionUsingABI.h > lldb.xcodeproj/project.pbxproj > source/Expression/ClangExpressionParser.cpp > source/Expression/ClangUserExpression.cpp > source/Expression/IRInterpreter.cpp > source/Expression/IRMemoryMap.cpp > source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp > source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp > source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp > source/Target/CMakeLists.txt > source/Target/Process.cpp > source/Target/ThreadPlanCallFunction.cpp > source/Target/ThreadPlanCallFunctionUsingABI.cpp > test/expression_command/call-function/TestCallUserDefinedFunction.py > test/expression_command/call-function/main.cpp > > ___ lldb-commits mailing list lldb-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
Re: [Lldb-commits] [PATCH] D9404: Expression evaluation, a new ThreadPlanCallFunctionNoJIT for executing a function call on target via register manipulation
jingham added a subscriber: jingham. jingham added a comment. For my part that looks great. Jim Repository: rL LLVM http://reviews.llvm.org/D9404 ___ lldb-commits mailing list lldb-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
Re: [Lldb-commits] [PATCH] D9404: Expression evaluation, a new ThreadPlanCallFunctionNoJIT for executing a function call on target via register manipulation
EwanCrawford updated this revision to Diff 29343. EwanCrawford added a comment. To address that final point of not doing any code execution at all for certain targets. I used the CanJIT() idea to create a similar CanInterpretFunctionCalls() member function of Process. This means that we can just pass the value of the m_can_interpret_function_calls variable to CanInterpret() instead of the Arch or execution context. Since interpreting function calls is a special case for hexagon right now the value defaults to false, and is only set to true by the hexagon dynamic loader. In the future though when more targets support this feature, CanInterpretFunctionCalls() would be enabled by default and then specifically disabled by targets. Using the example of the OSX kernel, which can't do any code execution, the patch explicitly sets jitting and interpreting function calls to false in the dynamic loader using an added CanRunCode() function. Repository: rL LLVM http://reviews.llvm.org/D9404 Files: include/lldb/Expression/IRInterpreter.h include/lldb/Expression/IRMemoryMap.h include/lldb/Target/ABI.h include/lldb/Target/Process.h include/lldb/Target/ThreadPlanCallFunction.h include/lldb/Target/ThreadPlanCallFunctionUsingABI.h lldb.xcodeproj/project.pbxproj source/Expression/ClangExpressionParser.cpp source/Expression/ClangUserExpression.cpp source/Expression/IRInterpreter.cpp source/Expression/IRMemoryMap.cpp source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp source/Target/CMakeLists.txt source/Target/Process.cpp source/Target/ThreadPlanCallFunction.cpp source/Target/ThreadPlanCallFunctionUsingABI.cpp test/expression_command/call-function/TestCallUserDefinedFunction.py test/expression_command/call-function/main.cpp Index: test/expression_command/call-function/main.cpp === --- test/expression_command/call-function/main.cpp +++ test/expression_command/call-function/main.cpp @@ -1,5 +1,6 @@ #include #include +#include struct Five { @@ -14,6 +15,30 @@ return my_five; } +unsigned int +fib(unsigned int n) +{ +if (n < 2) +return n; +else +return fib(n - 1) + fib(n - 2); +} + +int +add(int a, int b) +{ +return a + b; +} + +bool +stringCompare(const char *str) +{ +if (strcmp( str, "Hello world" ) == 0) +return true; +else +return false; +} + int main (int argc, char const *argv[]) { std::string str = "Hello world"; Index: test/expression_command/call-function/TestCallUserDefinedFunction.py === --- test/expression_command/call-function/TestCallUserDefinedFunction.py +++ test/expression_command/call-function/TestCallUserDefinedFunction.py @@ -0,0 +1,68 @@ +""" +Test calling user defined functions using expression evaluation. + +Note: + LLDBs current first choice of evaluating functions is using the IR interpreter, + which is only supported on Hexagon. Otherwise JIT is used for the evaluation. + +""" + +import unittest2 +import lldb +import lldbutil +from lldbtest import * + +class ExprCommandCallUserDefinedFunction(TestBase): + +mydir = TestBase.compute_mydir(__file__) + +def setUp(self): +# Call super's setUp(). +TestBase.setUp(self) +# Find the line number to break for main.c. +self.line = line_number('main.cpp', +'// Please test these expressions while stopped at this line:') +@skipUnlessDarwin +@dsym_test +@expectedFailureDarwin("llvm.org/pr20274") # intermittent failure on MacOSX +def test_with_dsym(self): +"""Test return values of user defined function calls.""" +self.buildDsym() +self.call_function() + +@dwarf_test +@expectedFailureFreeBSD("llvm.org/pr20274") # intermittent failure +def test_with_dwarf(self): +"""Test return values of user defined function calls.""" +self.buildDwarf() +self.call_functions() + +def call_functions(self): +"""Test return values of user defined function calls.""" + +# Set breakpoint in main and run exe +self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) +lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=-1, loc_exact=True) + +self.runCmd("run", RUN_SUCCEEDED) + +# Test recursive function call. +self.expect("expr fib(5)", substrs = ['$0 = 5']) + +# Test function with more than one paramter +self.expect("expr add(4,8)", substrs = ['$1 = 12']) + +# Test nesting function calls in function paramters +self.expect("expr add(add(5,2),add(3,4))", substrs = ['$2 = 14']) +self.expect("expr add(add(5,2),fib(5))", subs
Re: [Lldb-commits] [PATCH] D9404: Expression evaluation, a new ThreadPlanCallFunctionNoJIT for executing a function call on target via register manipulation
EwanCrawford updated this revision to Diff 28959. EwanCrawford added a comment. Thanks for taking the time to have a closer look Jim. Could you expand on your last point about situations where we don't want to run the target at all, it didn't quite click. REPOSITORY rL LLVM http://reviews.llvm.org/D9404 Files: include/lldb/Expression/IRInterpreter.h include/lldb/Expression/IRMemoryMap.h include/lldb/Target/ABI.h include/lldb/Target/ThreadPlanCallFunction.h include/lldb/Target/ThreadPlanCallFunctionUsingABI.h lldb.xcodeproj/project.pbxproj source/Expression/ClangExpressionParser.cpp source/Expression/ClangUserExpression.cpp source/Expression/IRInterpreter.cpp source/Expression/IRMemoryMap.cpp source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp source/Target/CMakeLists.txt source/Target/ThreadPlanCallFunction.cpp source/Target/ThreadPlanCallFunctionUsingABI.cpp test/expression_command/call-function/TestCallUserDefinedFunction.py test/expression_command/call-function/main.cpp Index: test/expression_command/call-function/main.cpp === --- test/expression_command/call-function/main.cpp +++ test/expression_command/call-function/main.cpp @@ -1,5 +1,6 @@ #include #include +#include struct Five { @@ -14,6 +15,30 @@ return my_five; } +unsigned int +fib(unsigned int n) +{ +if (n < 2) +return n; +else +return fib(n - 1) + fib(n - 2); +} + +int +add(int a, int b) +{ +return a + b; +} + +bool +stringCompare(const char *str) +{ +if (strcmp( str, "Hello world" ) == 0) +return true; +else +return false; +} + int main (int argc, char const *argv[]) { std::string str = "Hello world"; Index: test/expression_command/call-function/TestCallUserDefinedFunction.py === --- test/expression_command/call-function/TestCallUserDefinedFunction.py +++ test/expression_command/call-function/TestCallUserDefinedFunction.py @@ -0,0 +1,68 @@ +""" +Test calling user defined functions using expression evaluation. + +Note: + LLDBs first choice method of evaluating functions is using the IR interpreter, + which is currently only supported on Hexagon. Otherwise JIT is used for the evaluation. + +""" + +import unittest2 +import lldb +import lldbutil +from lldbtest import * + +class ExprCommandCallUserDefinedFunction(TestBase): + +mydir = TestBase.compute_mydir(__file__) + +def setUp(self): +# Call super's setUp(). +TestBase.setUp(self) +# Find the line number to break for main.c. +self.line = line_number('main.cpp', +'// Please test these expressions while stopped at this line:') +@skipUnlessDarwin +@dsym_test +@expectedFailureDarwin("llvm.org/pr20274") # intermittent failure on MacOSX +def test_with_dsym(self): +"""Test return values of user defined function calls.""" +self.buildDsym() +self.call_function() + +@dwarf_test +@expectedFailureFreeBSD("llvm.org/pr20274") # intermittent failure +def test_with_dwarf(self): +"""Test return values of user defined function calls.""" +self.buildDwarf() +self.call_functions() + +def call_functions(self): +"""Test return values of user defined function calls.""" + +# Set breakpoint in main and run exe +self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) +lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=-1, loc_exact=True) + +self.runCmd("run", RUN_SUCCEEDED) + +# Test recursive function call. +self.expect("expr fib(5)", substrs = ['$0 = 5']) + +# Test function with more than one paramter +self.expect("expr add(4,8)", substrs = ['$1 = 12']) + +# Test nesting function calls in function paramters +self.expect("expr add(add(5,2),add(3,4))", substrs = ['$2 = 14']) +self.expect("expr add(add(5,2),fib(5))", substrs = ['$3 = 12']) + +# Test function with pointer paramter +self.expect("exp stringCompare((const char*) \"Hello world\")", substrs = ['$4 = true']) +self.expect("exp stringCompare((const char*) \"Hellworld\")", substrs = ['$5 = false']) + + +if __name__ == '__main__': +import atexit +lldb.SBDebugger.Initialize() +atexit.register(lambda: lldb.SBDebugger.Terminate()) +unittest2.main() Index: source/Target/ThreadPlanCallFunctionUsingABI.cpp === --- source/Target/ThreadPlanCallFunctionUsingABI.cpp +++ source/Target/ThreadPlanCallFunctionUsingABI.cpp @@ -0,0 +1,91 @@ +//===-- ThreadPlanCallFunctionUsingABI.cpp --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the Universi