diff options
| author | Jim Ingham <jingham@apple.com> | 2014-04-02 01:04:55 +0000 |
|---|---|---|
| committer | Jim Ingham <jingham@apple.com> | 2014-04-02 01:04:55 +0000 |
| commit | d80102e4203691c31314fb3f65c5f91d86dbf06e (patch) | |
| tree | 47bf527eebc2300e2d86f96c3c85a1a021f3eac9 /lldb/source | |
| parent | 3c2b13b25825d0e8cd798e2e1e78b31f2f516d32 (diff) | |
| download | bcm5719-llvm-d80102e4203691c31314fb3f65c5f91d86dbf06e.tar.gz bcm5719-llvm-d80102e4203691c31314fb3f65c5f91d86dbf06e.zip | |
Add the ability to set python breakpoint commands from the SBBreakpoint & SBBreakpointLocation API's.
You can either provide the function name, or function body text.
Also propagate the compilation error up from where it is checked so we can report compilation errors.
<rdar://problem/9898371>
llvm-svn: 205380
Diffstat (limited to 'lldb/source')
| -rw-r--r-- | lldb/source/API/SBBreakpoint.cpp | 42 | ||||
| -rw-r--r-- | lldb/source/API/SBBreakpointLocation.cpp | 46 | ||||
| -rw-r--r-- | lldb/source/Commands/CommandObjectBreakpointCommand.cpp | 10 | ||||
| -rw-r--r-- | lldb/source/Interpreter/ScriptInterpreterPython.cpp | 86 |
4 files changed, 143 insertions, 41 deletions
diff --git a/lldb/source/API/SBBreakpoint.cpp b/lldb/source/API/SBBreakpoint.cpp index fbdc0e32f49..2c9cd12f18e 100644 --- a/lldb/source/API/SBBreakpoint.cpp +++ b/lldb/source/API/SBBreakpoint.cpp @@ -19,9 +19,12 @@ #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/Address.h" +#include "lldb/Core/Debugger.h" #include "lldb/Core/Log.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/ScriptInterpreter.h" #include "lldb/Target/Process.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" @@ -579,6 +582,45 @@ SBBreakpoint::SetCallback (BreakpointHitCallback callback, void *baton) } } +void +SBBreakpoint::SetScriptCallbackFunction (const char *callback_function_name) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + + if (log) + log->Printf ("SBBreakpoint(%p)::SetScriptCallbackFunction (callback=%s)", m_opaque_sp.get(), callback_function_name); + + if (m_opaque_sp) + { + Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); + BreakpointOptions *bp_options = m_opaque_sp->GetOptions(); + m_opaque_sp->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter()->SetBreakpointCommandCallbackFunction (bp_options, + callback_function_name); + } +} + +SBError +SBBreakpoint::SetScriptCallbackBody (const char *callback_body_text) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + + if (log) + log->Printf ("SBBreakpoint(%p)::SetScriptCallbackBody: callback body:\n%s)", m_opaque_sp.get(), callback_body_text); + + SBError sb_error; + if (m_opaque_sp) + { + Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); + BreakpointOptions *bp_options = m_opaque_sp->GetOptions(); + Error error = m_opaque_sp->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options, + callback_body_text); + sb_error.SetError(error); + } + else + sb_error.SetErrorString("invalid breakpoint"); + + return sb_error; +} lldb_private::Breakpoint * SBBreakpoint::operator->() const diff --git a/lldb/source/API/SBBreakpointLocation.cpp b/lldb/source/API/SBBreakpointLocation.cpp index 6fdf59f38b4..b2b94484f9c 100644 --- a/lldb/source/API/SBBreakpointLocation.cpp +++ b/lldb/source/API/SBBreakpointLocation.cpp @@ -17,10 +17,13 @@ #include "lldb/lldb-defines.h" #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Target/ThreadSpec.h" +#include "lldb/Core/Debugger.h" #include "lldb/Core/Log.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/ScriptInterpreter.h" +#include "lldb/Target/ThreadSpec.h" #include "lldb/Target/Target.h" #include "lldb/Target/ThreadSpec.h" @@ -160,6 +163,47 @@ SBBreakpointLocation::GetCondition () } void +SBBreakpointLocation::SetScriptCallbackFunction (const char *callback_function_name) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + + if (log) + log->Printf ("SBBreakpointLocation(%p)::SetScriptCallbackFunction (callback=%s)", m_opaque_sp.get(), callback_function_name); + + if (m_opaque_sp) + { + Mutex::Locker api_locker (m_opaque_sp->GetBreakpoint().GetTarget().GetAPIMutex()); + BreakpointOptions *bp_options = m_opaque_sp->GetLocationOptions(); + m_opaque_sp->GetBreakpoint().GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter()->SetBreakpointCommandCallbackFunction (bp_options, + callback_function_name); + + } +} + +SBError +SBBreakpointLocation::SetScriptCallbackBody (const char *callback_body_text) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + + if (log) + log->Printf ("SBBreakpoint(%p)::SetScriptCallbackBody: callback body:\n%s)", m_opaque_sp.get(), callback_body_text); + + SBError sb_error; + if (m_opaque_sp) + { + Mutex::Locker api_locker (m_opaque_sp->GetBreakpoint().GetTarget().GetAPIMutex()); + BreakpointOptions *bp_options = m_opaque_sp->GetLocationOptions(); + Error error = m_opaque_sp->GetBreakpoint().GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options, + callback_body_text); + sb_error.SetError(error); + } + else + sb_error.SetErrorString("invalid breakpoint"); + + return sb_error; +} + +void SBBreakpointLocation::SetThreadID (tid_t thread_id) { if (m_opaque_sp) diff --git a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp index 532d6cedc83..0b28cc3e2cc 100644 --- a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp +++ b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp @@ -504,16 +504,10 @@ protected: m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options, m_options.m_one_liner.c_str()); } - // Special handling for using a Python function by name - // instead of extending the breakpoint callback data structures, we just automatize - // what the user would do manually: make their breakpoint command be a function call else if (m_options.m_function_name.size()) { - std::string oneliner("return "); - oneliner += m_options.m_function_name; - oneliner += "(frame, bp_loc, internal_dict)"; - m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options, - oneliner.c_str()); + m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallbackFunction (bp_options, + m_options.m_function_name.c_str()); } else { diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp index b9723275bed..4bb247307c9 100644 --- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp +++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp @@ -254,7 +254,7 @@ ScriptInterpreterPython::IOHandlerInputComplete (IOHandler &io_handler, std::str { data_ap->user_source.SplitIntoLines(data); - if (GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source)) + if (GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source).Success()) { BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp); @@ -1083,27 +1083,39 @@ ScriptInterpreterPython::CollectDataForWatchpointCommandCallback (WatchpointOpti m_interpreter.GetPythonCommandsFromIOHandler (" ", *this, true, wp_options); } -// Set a Python one-liner as the callback for the breakpoint. void +ScriptInterpreterPython::SetBreakpointCommandCallbackFunction (BreakpointOptions *bp_options, + const char *function_name) +{ + // For now just cons up a oneliner that calls the provided function. + std::string oneliner("return "); + oneliner += function_name; + oneliner += "(frame, bp_loc, internal_dict)"; + m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options, + oneliner.c_str()); +} + +// Set a Python one-liner as the callback for the breakpoint. +Error ScriptInterpreterPython::SetBreakpointCommandCallback (BreakpointOptions *bp_options, - const char *oneliner) + const char *command_body_text) { std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::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 breakpoint 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 (GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source)) + // Split the command_body_text into lines, and pass that to GenerateBreakpointCommandCallbackData. That will + // wrap the body in an auto-generated function, and return the function name in script_source. That is what + // the callback will actually invoke. + + data_ap->user_source.SplitIntoLines(command_body_text); + Error error = GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source); + if (error.Success()) { BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp); + return error; } - - return; + else + return error; } // Set a Python one-liner as the callback for the watchpoint. @@ -1129,24 +1141,32 @@ ScriptInterpreterPython::SetWatchpointCommandCallback (WatchpointOptions *wp_opt return; } -bool +Error ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter (StringList &function_def) { // Convert StringList to one long, newline delimited, const char *. std::string function_def_string(function_def.CopyList()); - return ExecuteMultipleLines (function_def_string.c_str(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false)).Success(); + Error error = ExecuteMultipleLines (function_def_string.c_str(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false)); + return error; } -bool +Error ScriptInterpreterPython::GenerateFunction(const char *signature, const StringList &input) { + Error error; int num_lines = input.GetSize (); if (num_lines == 0) - return false; + { + error.SetErrorString ("No input data."); + return error; + } if (!signature || *signature == 0) - return false; + { + error.SetErrorString("No output function name."); + return error; + } StreamString sstr; StringList auto_generated_function; @@ -1173,11 +1193,9 @@ ScriptInterpreterPython::GenerateFunction(const char *signature, const StringLis // Verify that the results are valid Python. - if (!ExportFunctionDefinitionToInterpreter (auto_generated_function)) - return false; + error = ExportFunctionDefinitionToInterpreter (auto_generated_function); - return true; - + return error; } bool @@ -1197,7 +1215,7 @@ ScriptInterpreterPython::GenerateTypeScriptFunction (StringList &user_input, std std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_type_print_func", num_created_functions, name_token)); sstr.Printf ("def %s (valobj, internal_dict):", auto_generated_function_name.c_str()); - if (!GenerateFunction(sstr.GetData(), user_input)) + if (!GenerateFunction(sstr.GetData(), user_input).Success()) return false; // Store the name of the auto-generated function to be called. @@ -1220,7 +1238,7 @@ ScriptInterpreterPython::GenerateScriptAliasFunction (StringList &user_input, st sstr.Printf ("def %s (debugger, args, result, internal_dict):", auto_generated_function_name.c_str()); - if (!GenerateFunction(sstr.GetData(),user_input)) + if (!GenerateFunction(sstr.GetData(),user_input).Success()) return false; // Store the name of the auto-generated function to be called. @@ -1266,7 +1284,7 @@ ScriptInterpreterPython::GenerateTypeSynthClass (StringList &user_input, std::st // Verify that the results are valid Python. // (even though the method is ExportFunctionDefinitionToInterpreter, a class will actually be exported) // (TODO: rename that method to ExportDefinitionToInterpreter) - if (!ExportFunctionDefinitionToInterpreter (auto_generated_class)) + if (!ExportFunctionDefinitionToInterpreter (auto_generated_class).Success()) return false; // Store the name of the auto-generated class @@ -1668,25 +1686,29 @@ ScriptInterpreterPython::GenerateTypeSynthClass (const char* oneliner, std::stri } -bool +Error ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user_input, std::string& output) { static uint32_t num_created_functions = 0; user_input.RemoveBlankLines (); StreamString sstr; - + Error error; if (user_input.GetSize() == 0) - return false; + { + error.SetErrorString("No input data."); + return error; + } std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_bp_callback_func_",num_created_functions)); sstr.Printf ("def %s (frame, bp_loc, internal_dict):", auto_generated_function_name.c_str()); - if (!GenerateFunction(sstr.GetData(), user_input)) - return false; + error = GenerateFunction(sstr.GetData(), user_input); + if (!error.Success()) + return error; // Store the name of the auto-generated function to be called. output.assign(auto_generated_function_name); - return true; + return error; } bool @@ -1702,7 +1724,7 @@ ScriptInterpreterPython::GenerateWatchpointCommandCallbackData (StringList &user 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)) + if (!GenerateFunction(sstr.GetData(), user_input).Success()) return false; // Store the name of the auto-generated function to be called. |

