diff options
author | Johnny Chen <johnny.chen@apple.com> | 2012-08-09 23:09:42 +0000 |
---|---|---|
committer | Johnny Chen <johnny.chen@apple.com> | 2012-08-09 23:09:42 +0000 |
commit | e9a5627e7ae21d10049352e196ff7469a40c6d06 (patch) | |
tree | 97ada238546a6071edbdf67f1ba78bc41ca7f6f0 /lldb/source/Interpreter/ScriptInterpreterPython.cpp | |
parent | 637ff0cc0fc79bdd6ccea856835f278e89f79b67 (diff) | |
download | bcm5719-llvm-e9a5627e7ae21d10049352e196ff7469a40c6d06.tar.gz bcm5719-llvm-e9a5627e7ae21d10049352e196ff7469a40c6d06.zip |
rdar://problem/11457143 [ER] need "watchpoint command ..."
Add 'watchpoint command add/delete/list' to lldb, plus two .py test files.
llvm-svn: 161638
Diffstat (limited to 'lldb/source/Interpreter/ScriptInterpreterPython.cpp')
-rw-r--r-- | lldb/source/Interpreter/ScriptInterpreterPython.cpp | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp index 8d935dda92e..1e555c4cae6 100644 --- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp +++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp @@ -31,6 +31,7 @@ #include "lldb/API/SBValue.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" +#include "lldb/Breakpoint/WatchpointOptions.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Timer.h" #include "lldb/Host/Host.h" @@ -44,6 +45,7 @@ using namespace lldb_private; static ScriptInterpreter::SWIGInitCallback g_swig_init_callback = NULL; static ScriptInterpreter::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = NULL; +static ScriptInterpreter::SWIGWatchpointCallbackFunction g_swig_watchpoint_callback = NULL; static ScriptInterpreter::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = NULL; static ScriptInterpreter::SWIGPythonCreateSyntheticProvider g_swig_synthetic_script = NULL; static ScriptInterpreter::SWIGPythonCalculateNumChildren g_swig_calc_children = NULL; @@ -69,6 +71,15 @@ LLDBSwigPythonBreakpointCallbackFunction ); extern "C" bool +LLDBSwigPythonWatchpointCallbackFunction +( + const char *python_function_name, + const char *session_dictionary_name, + const lldb::StackFrameSP& sb_frame, + const lldb::WatchpointSP& sb_wp + ); + +extern "C" bool LLDBSwigPythonCallTypeScript ( const char *python_function_name, @@ -1388,6 +1399,112 @@ ScriptInterpreterPython::GenerateBreakpointOptionsCommandCallback return bytes_len; } +size_t +ScriptInterpreterPython::GenerateWatchpointOptionsCommandCallback +( + void *baton, + InputReader &reader, + InputReaderAction notification, + const char *bytes, + size_t bytes_len +) +{ + static StringList commands_in_progress; + + StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream(); + bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); + + switch (notification) + { + case eInputReaderActivate: + { + commands_in_progress.Clear(); + if (!batch_mode) + { + out_stream->Printf ("%s\n", g_reader_instructions); + if (reader.GetPrompt()) + out_stream->Printf ("%s", reader.GetPrompt()); + out_stream->Flush (); + } + } + break; + + case eInputReaderDeactivate: + break; + + case eInputReaderReactivate: + if (reader.GetPrompt() && !batch_mode) + { + out_stream->Printf ("%s", reader.GetPrompt()); + out_stream->Flush (); + } + break; + + case eInputReaderAsynchronousOutputWritten: + break; + + case eInputReaderGotToken: + { + std::string temp_string (bytes, bytes_len); + commands_in_progress.AppendString (temp_string.c_str()); + if (!reader.IsDone() && reader.GetPrompt() && !batch_mode) + { + out_stream->Printf ("%s", reader.GetPrompt()); + out_stream->Flush (); + } + } + break; + + case eInputReaderEndOfFile: + case eInputReaderInterrupt: + // Control-c (SIGINT) & control-d both mean finish & exit. + reader.SetIsDone(true); + + // Control-c (SIGINT) ALSO means cancel; do NOT create a breakpoint command. + if (notification == eInputReaderInterrupt) + commands_in_progress.Clear(); + + // Fall through here... + + case eInputReaderDone: + { + WatchpointOptions *wp_options = (WatchpointOptions *)baton; + std::auto_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData()); + data_ap->user_source.AppendList (commands_in_progress); + if (data_ap.get()) + { + ScriptInterpreter *interpreter = reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); + if (interpreter) + { + if (interpreter->GenerateWatchpointCommandCallbackData (data_ap->user_source, + data_ap->script_source)) + { + BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release())); + wp_options->SetCallback (ScriptInterpreterPython::WatchpointCallbackFunction, baton_sp); + } + else if (!batch_mode) + { + out_stream->Printf ("Warning: No command attached to breakpoint.\n"); + out_stream->Flush(); + } + } + else + { + if (!batch_mode) + { + out_stream->Printf ("Warning: Unable to find script intepreter; no command attached to breakpoint.\n"); + out_stream->Flush(); + } + } + } + } + break; + + } + + return bytes_len; +} + void ScriptInterpreterPython::CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options, CommandReturnObject &result) @@ -1421,6 +1538,39 @@ ScriptInterpreterPython::CollectDataForBreakpointCommandCallback (BreakpointOpti } } +void +ScriptInterpreterPython::CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options, + CommandReturnObject &result) +{ + Debugger &debugger = GetCommandInterpreter().GetDebugger(); + + InputReaderSP reader_sp (new InputReader (debugger)); + + if (reader_sp) + { + Error err = reader_sp->Initialize ( + ScriptInterpreterPython::GenerateWatchpointOptionsCommandCallback, + wp_options, // baton + eInputReaderGranularityLine, // token size, for feeding data to callback function + "DONE", // end token + "> ", // prompt + true); // echo input + + if (err.Success()) + debugger.PushInputReader (reader_sp); + else + { + result.AppendError (err.AsCString()); + result.SetStatus (eReturnStatusFailed); + } + } + else + { + result.AppendError("out of memory"); + result.SetStatus (eReturnStatusFailed); + } +} + // Set a Python one-liner as the callback for the breakpoint. void ScriptInterpreterPython::SetBreakpointCommandCallback (BreakpointOptions *bp_options, @@ -1433,6 +1583,7 @@ ScriptInterpreterPython::SetBreakpointCommandCallback (BreakpointOptions *bp_opt // while the latter is used for Python to interpret during the actual callback. data_ap->user_source.AppendString (oneliner); + data_ap->script_source.assign (oneliner); if (GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source)) { @@ -1443,6 +1594,29 @@ ScriptInterpreterPython::SetBreakpointCommandCallback (BreakpointOptions *bp_opt return; } +// Set a Python one-liner as the callback for the watchpoint. +void +ScriptInterpreterPython::SetWatchpointCommandCallback (WatchpointOptions *wp_options, + const char *oneliner) +{ + std::auto_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData()); + + // It's necessary to set both user_source and script_source to the oneliner. + // The former is used to generate callback description (as in watchpoint command list) + // while the latter is used for Python to interpret during the actual callback. + + data_ap->user_source.AppendString (oneliner); + data_ap->script_source.assign (oneliner); + + if (GenerateWatchpointCommandCallbackData (data_ap->user_source, data_ap->script_source)) + { + BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release())); + wp_options->SetCallback (ScriptInterpreterPython::WatchpointCallbackFunction, baton_sp); + } + + return; +} + bool ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter (StringList &function_def) { @@ -1662,6 +1836,27 @@ ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user } bool +ScriptInterpreterPython::GenerateWatchpointCommandCallbackData (StringList &user_input, std::string& output) +{ + static uint32_t num_created_functions = 0; + user_input.RemoveBlankLines (); + StreamString sstr; + + if (user_input.GetSize() == 0) + return false; + + std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_wp_callback_func_",num_created_functions)); + sstr.Printf ("def %s (frame, wp, internal_dict):", auto_generated_function_name.c_str()); + + if (!GenerateFunction(sstr.GetData(), user_input)) + return false; + + // Store the name of the auto-generated function to be called. + output.assign(auto_generated_function_name); + return true; +} + +bool ScriptInterpreterPython::GetScriptedSummary (const char *python_function_name, lldb::ValueObjectSP valobj, lldb::ScriptInterpreterObjectSP& callee_wrapper_sp, @@ -1764,6 +1959,59 @@ ScriptInterpreterPython::BreakpointCallbackFunction return true; } +bool +ScriptInterpreterPython::WatchpointCallbackFunction +( + void *baton, + StoppointCallbackContext *context, + user_id_t watch_id +) +{ + WatchpointOptions::CommandData *wp_option_data = (WatchpointOptions::CommandData *) baton; + const char *python_function_name = wp_option_data->script_source.c_str(); + + if (!context) + return true; + + ExecutionContext exe_ctx (context->exe_ctx_ref); + Target *target = exe_ctx.GetTargetPtr(); + + if (!target) + return true; + + Debugger &debugger = target->GetDebugger(); + ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); + ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter; + + if (!script_interpreter) + return true; + + if (python_function_name != NULL + && python_function_name[0] != '\0') + { + const StackFrameSP stop_frame_sp (exe_ctx.GetFrameSP()); + WatchpointSP wp_sp = target->GetWatchpointList().FindByID (watch_id); + if (wp_sp) + { + if (stop_frame_sp && wp_sp) + { + bool ret_val = true; + { + Locker py_lock(python_interpreter); + ret_val = g_swig_watchpoint_callback (python_function_name, + python_interpreter->m_dictionary_name.c_str(), + stop_frame_sp, + wp_sp); + } + return ret_val; + } + } + } + // We currently always true so we stop in case anything goes wrong when + // trying to call the script function + return true; +} + lldb::thread_result_t ScriptInterpreterPython::RunEmbeddedPythonInterpreter (lldb::thread_arg_t baton) { @@ -2176,6 +2424,7 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback python_swig_ini { g_swig_init_callback = python_swig_init_callback; g_swig_breakpoint_callback = LLDBSwigPythonBreakpointCallbackFunction; + g_swig_watchpoint_callback = LLDBSwigPythonWatchpointCallbackFunction; g_swig_typescript_callback = LLDBSwigPythonCallTypeScript; g_swig_synthetic_script = LLDBSwigPythonCreateSyntheticProvider; g_swig_calc_children = LLDBSwigPython_CalculateNumChildren; |