[Lldb-commits] [lldb] r114849 - in /lldb/trunk: include/lldb/API/SBBreakpointLocation.h include/lldb/API/SBFrame.h scripts/lldb.swig source/Interpreter/ScriptInterpreterPython.cpp

Caroline Tice ctice at apple.com
Mon Sep 27 13:56:52 PDT 2010


I missed the fact that the "one-liner" breakpoint commands use a slightly different mechanism.  I'll fix that.

On Sep 27, 2010, at 12:17 PM, Johnny Chen wrote:

> Hi Caroline,
> 
> This checkin seems to break the test suite: test/breakpoint_command, and maybe others....
> 
> On Sep 27, 2010, at 11:00 AM, Caroline Tice wrote:
> 
>> Author: ctice
>> Date: Mon Sep 27 13:00:20 2010
>> New Revision: 114849
>> 
>> URL: http://llvm.org/viewvc/llvm-project?rev=114849&view=rev
>> Log:
>> Automatically wrap *all* Python code entered for a breakpoint command inside
>> an auto-generated Python function, and pass the stoppoint context frame and
>> breakpoint location as parameters to the function (named 'frame' and 'bp_loc'),
>> to be used inside the breakpoint command Python code, if desired.
>> 
>> 
>> Modified:
>>   lldb/trunk/include/lldb/API/SBBreakpointLocation.h
>>   lldb/trunk/include/lldb/API/SBFrame.h
>>   lldb/trunk/scripts/lldb.swig
>>   lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp
>> 
>> Modified: lldb/trunk/include/lldb/API/SBBreakpointLocation.h
>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBBreakpointLocation.h?rev=114849&r1=114848&r2=114849&view=diff
>> ==============================================================================
>> --- lldb/trunk/include/lldb/API/SBBreakpointLocation.h (original)
>> +++ lldb/trunk/include/lldb/API/SBBreakpointLocation.h Mon Sep 27 13:00:20 2010
>> @@ -76,6 +76,7 @@
>> 
>> private:
>>    friend class SBBreakpoint;
>> +    friend class lldb_private::ScriptInterpreterPython;
>> 
>>    SBBreakpointLocation (const lldb::BreakpointLocationSP &break_loc_sp);
>> 
>> 
>> Modified: lldb/trunk/include/lldb/API/SBFrame.h
>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBFrame.h?rev=114849&r1=114848&r2=114849&view=diff
>> ==============================================================================
>> --- lldb/trunk/include/lldb/API/SBFrame.h (original)
>> +++ lldb/trunk/include/lldb/API/SBFrame.h Mon Sep 27 13:00:20 2010
>> @@ -123,6 +123,7 @@
>> 
>> private:
>>    friend class SBThread;
>> +    friend class lldb_private::ScriptInterpreterPython;
>> 
>> #ifndef SWIG
>> 
>> 
>> Modified: lldb/trunk/scripts/lldb.swig
>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/lldb.swig?rev=114849&r1=114848&r2=114849&view=diff
>> ==============================================================================
>> --- lldb/trunk/scripts/lldb.swig (original)
>> +++ lldb/trunk/scripts/lldb.swig Mon Sep 27 13:00:20 2010
>> @@ -99,6 +99,15 @@
>> #include "lldb/API/SBType.h"
>> #include "lldb/API/SBValue.h"
>> #include "lldb/API/SBValueList.h"
>> +#include "lldb/Interpreter/ScriptInterpreterPython.h"
>> +#include "lldb/Breakpoint/Breakpoint.h"
>> +#include "lldb/Breakpoint/BreakpointLocation.h"
>> +#include "lldb/Breakpoint/StoppointCallbackContext.h"
>> +#include "lldb/Target/ExecutionContext.h"
>> +#include "lldb/Target/StackFrame.h"
>> +#include "lldb/Target/Target.h"
>> +#include "lldb/Target/Thread.h"
>> +#include "lldb/lldb-forward-rtti.h"
>> using namespace lldb_private;
>> %}
>> 
>> @@ -157,3 +166,97 @@
>> %include "lldb/lldb-types.h"
>> 
>> %include "./Python/python-extensions.swig"
>> +
>> +
>> +%wrapper %{
>> +
>> +
>> +bool
>> +ScriptInterpreterPython::BreakpointCallbackFunction (void *baton,
>> +                                                     StoppointCallbackContext *context,
>> +                                                     lldb::user_id_t break_id,
>> +                                                     lldb::user_id_t break_loc_id)
>> +{
>> +    bool ret_value = true;
>> +    
>> +    BreakpointOptions::CommandData *bp_option_data = (BreakpointOptions::CommandData *) baton;
>> +    const char *python_function_name = bp_option_data->script_source.GetStringAtIndex (0);
>> +    
>> +    if (python_function_name != NULL 
>> +        && python_function_name[0] != '\0')
>> +    {
>> +        Thread *thread = context->exe_ctx.thread;
>> +        Target *target = context->exe_ctx.target;
>> +        const lldb::StackFrameSP stop_frame_sp = thread->GetStackFrameSPForStackFramePtr (context->exe_ctx.frame);
>> +        lldb::BreakpointSP breakpoint_sp = target->GetBreakpointByID (break_id);
>> +        const lldb::BreakpointLocationSP bp_loc_sp = breakpoint_sp->FindLocationByID (break_loc_id);
>> +        
>> +        lldb::SBFrame sb_frame (stop_frame_sp);
>> +        lldb::SBBreakpointLocation sb_bp_loc (bp_loc_sp);
>> +        
>> +        if (!sb_bp_loc.IsValid() || !sb_frame.IsValid())
>> +            return ret_value;
>> +        
>> +
>> +        PyObject *Frame_PyObj = SWIG_NewPointerObj((void *) &sb_frame, SWIGTYPE_p_lldb__SBFrame, 0);
>> +        PyObject *Bp_Loc_PyObj = SWIG_NewPointerObj ((void *) &sb_bp_loc, SWIGTYPE_p_lldb__SBBreakpointLocation, 0);
>> +        
>> +        if (Frame_PyObj == NULL
>> +            || Bp_Loc_PyObj == NULL)
>> +            return ret_value;
>> +
>> +        PyObject *pmodule, *pdict, *pfunc;
>> +        PyObject *pargs, *pvalue;
>> +        
>> +        pmodule = PyImport_AddModule ("__main__");
>> +        if (pmodule != NULL)
>> +        {
>> +            pdict = PyModule_GetDict (pmodule);
>> +            if (pdict != NULL)
>> +            {
>> +                pfunc = PyObject_GetAttrString (pmodule, python_function_name);
>> +                if (pfunc && PyCallable_Check (pfunc))
>> +                {
>> +                    pargs = PyTuple_New (2);
>> +                    if (pargs == NULL)
>> +                    {
>> +                        if (PyErr_Occurred())
>> +                            PyErr_Clear();
>> +                        return ret_value;
>> +                    }
>> +                    
>> +                    PyTuple_SetItem (pargs, 0, Frame_PyObj);  // This "steals" a reference to Frame_PyObj
>> +                    PyTuple_SetItem (pargs, 1, Bp_Loc_PyObj); // This "steals" a reference to Bp_Loc_PyObj
>> +                    pvalue = PyObject_CallObject (pfunc, pargs);
>> +                    Py_DECREF (pargs);
>> +                    
>> +                    if (pvalue != NULL)
>> +                    {
>> +                        Py_DECREF (pvalue);
>> +                    }
>> +                    else if (PyErr_Occurred ())
>> +                    {
>> +                        PyErr_Clear();
>> +                    }
>> +                    Py_DECREF (pfunc);
>> +                }
>> +                else if (PyErr_Occurred())
>> +                {
>> +                    PyErr_Clear();
>> +                }
>> +            }
>> +            else if (PyErr_Occurred())
>> +            {
>> +                PyErr_Clear();
>> +            }
>> +        }
>> +        else if (PyErr_Occurred ())
>> +        {
>> +            PyErr_Clear ();
>> +        }
>> +    }
>> +
>> +    return ret_value;
>> +}
>> +
>> +%}
>> 
>> Modified: lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp?rev=114849&r1=114848&r2=114849&view=diff
>> ==============================================================================
>> --- lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp (original)
>> +++ lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp Mon Sep 27 13:00:20 2010
>> @@ -717,220 +717,44 @@
>> {
>>    static int num_created_functions = 0;
>>    user_input.RemoveBlankLines ();
>> -    int num_lines = user_input.GetSize();
>> +    int num_lines = user_input.GetSize ();
>> +    StreamString sstr;
>> 
>> -    if (num_lines == 1)
>> -    {
>> -        callback_data.AppendString (user_input.GetStringAtIndex (0));
>> -        return true;
>> -    }
>> +    // Take what the user wrote, wrap it all up inside one big auto-generated Python function, passing in the
>> +    // frame and breakpoint location as parameters to the function.
>> 
>> -    // Traverse user_input exactly once.  At each line, either copy line into new, auto-generated function, 
>> -    // increasing indentation by 5 spaces or copy it exactly as is into the user-written 
>> -    // currently-to-be-pushed-to-Python function def.  At the end of each Python function def, push the function 
>> -    // to Python, and clear the function string, to start again.  At the end of it all, if there is anything in 
>> -    // the auto-generated function, push it to Python and add the function call to it to the callback data.
>> 
>> -    bool inside_user_python_function_def = false;
>> -    std::string whitespace = " \t";
>> +    sstr.Printf ("lldb_autogen_python_bp_callback_func_%d", num_created_functions);
>> +    ++num_created_functions;
>> +    std::string auto_generated_function_name = sstr.GetData();
>> 
>> +    sstr.Clear();
>>    StringList auto_generated_function;
>> -    StringList user_defined_function;
>> 
>> -    StringList *current_function_def = &auto_generated_function;
>> -    std::string auto_generated_function_name ("lldb_autogen_python_bp_callback_func_");
>> +    // Create the function name & definition string.
>> 
>> -    for (int i = 0; i < num_lines; ++i)
>> -    {
>> -        std::string current_line (user_input.GetStringAtIndex(i));
>> -        size_t idx = current_line.find_first_of (whitespace);
>> -        if (idx != std::string::npos)
>> -        {
>> -            if (idx == 0) // line starts with indentation...
>> -            {
>> -                if (inside_user_python_function_def)
>> -                {
>> -                    // Add this line to the user's python function definition.
>> -                    current_function_def->AppendString (current_line.c_str());
>> -                }
>> -                else
>> -                {
>> -                    // Add this line to our auto-generated function; increase original indentation by 5.
>> -                    StreamString tmp_str;
>> -                    tmp_str.Printf ("     %s", current_line.c_str());
>> -                    current_function_def->AppendString (tmp_str.GetData());
>> -                }
>> -            }
>> -            else  // line does not start with indentation...
>> -            {
>> -                // First, check to see if we just finished a user-written function definition; if so,
>> -                // wrap it up and send it to Python.
>> -
>> -                if (inside_user_python_function_def && (user_defined_function.GetSize() > 0))
>> -                {
>> -                    if (! ExportFunctionDefinitionToInterpreter (user_defined_function))
>> -                    {
>> -                        // User entered incorrect Python syntax.  We should not attempt to continue.
>> -                        // Clear the callback data, and return immediately.
>> -                        callback_data.Clear();
>> -                        return false;
>> -                    }
>> -
>> -                    // User defined function was successfully sent to Python.  Clean up after it.
>> -                    user_defined_function.Clear();
>> -                    inside_user_python_function_def = false;
>> -                    current_function_def = &auto_generated_function;
>> -                }
>> -
>> -                // Next, check to see if we are at the start of a user-defined Python function.
>> -                std::string first_word = current_line.substr (0, idx);
>> -                if (first_word.compare ("def") == 0)
>> -                {
>> -                    // Start the user defined function properly:
>> -                    inside_user_python_function_def = true;
>> -                    current_function_def = &user_defined_function;
>> -                    current_function_def->AppendString (current_line.c_str());
>> -                }
>> -                else
>> -                {
>> -                    // We are in "loose" Python code that we need to collect and put into the auto-generated
>> -                    // function.
>> -                    StreamString tmp_str;
>> -                    current_function_def = &auto_generated_function;
>> -                    if (current_function_def->GetSize() == 0)
>> -                    {
>> -                        // Create the function name, and add insert the function def line.
>> -                        tmp_str.Printf ("%d", num_created_functions);
>> -                        ++num_created_functions;
>> -                        auto_generated_function_name.append (tmp_str.GetData());
>> -
>> -                        tmp_str.Clear();
>> -                        tmp_str.Printf ("def %s ():", auto_generated_function_name.c_str());
>> -                        current_function_def->AppendString (tmp_str.GetData());
>> -                    }
>> -                    tmp_str.Clear();
>> -                    
>> -                    // Indent the line an extra 5 spaces and add it to our auto-generated function.
>> -                    tmp_str.Printf ("     %s", current_line.c_str());
>> -                    current_function_def->AppendString (tmp_str.GetData());
>> -                } // else we are in loose Python code
>> -            } // else current line does not start with indentatin
>> -        }
>> -        else
>> -        {
>> -            // There was no white space on the line (and therefore no indentation either).
>> -
>> -            // First, check to see if we just finished a user-written function definition; if so,
>> -            // wrap it up and send it to Python.
>> -            
>> -            if (inside_user_python_function_def && (user_defined_function.GetSize() > 0))
>> -            {
>> -                if (! ExportFunctionDefinitionToInterpreter (user_defined_function))
>> -                {
>> -                    // User entered incorrect Python syntax.  We should not attempt to continue.
>> -                    // Clear the callback data, and return immediately.
>> -                    callback_data.Clear();
>> -                    return false;
>> -                }
>> -                
>> -                // User defined function was successfully sent to Python.  Clean up after it.
>> -                user_defined_function.Clear();
>> -                inside_user_python_function_def = false;
>> -                current_function_def = &auto_generated_function;
>> -            }
>> -            
>> -            // We cannot be at the start of a function definition (they contain white space) so we
>> -            // must have "loose" python code.
>> -            
>> -            StreamString tmp_str;
>> -            current_function_def = &auto_generated_function;
>> -            if (current_function_def->GetSize() == 0)
>> -            {
>> -                // Create the function name, and add insert the function def line.
>> -                tmp_str.Printf ("%d", num_created_functions);
>> -                ++num_created_functions;
>> -                auto_generated_function_name.append (tmp_str.GetData());
>> -                
>> -                tmp_str.Clear();
>> -                tmp_str.Printf ("def %s ():", auto_generated_function_name.c_str());
>> -                current_function_def->AppendString (tmp_str.GetData());
>> -            }
>> -            tmp_str.Clear();
>> -            
>> -            // Indent the line an extra 5 spaces and add it to our auto-generated function.
>> -            tmp_str.Printf ("     %s", current_line.c_str());
>> -            current_function_def->AppendString (tmp_str.GetData());
>> -            
>> -        } // else there was no white space on the line.
>> -    } 
>> +    sstr.Printf ("def %s (frame, bp_loc):", auto_generated_function_name.c_str());
>> +    auto_generated_function.AppendString (sstr.GetData());
>> 
>> -    // Perhaps the last line of input was also the last line of a user-defined function; if so,
>> -    // attempt to push the function down to Python.
>> +    // Wrap everything up inside the function, increasing the indentation.
>> 
>> -    if (inside_user_python_function_def && (user_defined_function.GetSize() > 0))
>> +    for (int i = 0; i < num_lines; ++i)
>>    {
>> -        if (! ExportFunctionDefinitionToInterpreter (user_defined_function))
>> -        {
>> -            callback_data.Clear();
>> -            return false;
>> -        }
>> +        sstr.Clear ();
>> +        sstr.Printf ("     %s", user_input.GetStringAtIndex (i));
>> +        auto_generated_function.AppendString (sstr.GetData());
>>    }
>> 
>> +    // Verify that the results are valid Python.
>> 
>> -    if (auto_generated_function.GetSize() > 0)
>> -    {
>> -        // Export the auto-generated function to Python.
>> -        if (ExportFunctionDefinitionToInterpreter (auto_generated_function))
>> -        {
>> -            // The export succeeded; the syntax must be ok. Generate the function call and put
>> -            // it in the callback data.
>> -            StreamString tmp_str;
>> -            tmp_str.Printf ("%s ()", auto_generated_function_name.c_str());
>> -            callback_data.AppendString (tmp_str.GetData());
>> -            return true;
>> -        }
>> -        else
>> -        {
>> -            // Syntax error!
>> -            callback_data.Clear();
>> -            return false;
>> -        }
>> -    }
>> -    else
>> +    if (!ExportFunctionDefinitionToInterpreter (auto_generated_function))
>>    {
>> -        // If there was any code, it consisted entirely of function defs, without any calls to the functions.
>> -        // No actual exectuable code was therefore generated.  (Function calls would have looked like "loose" python,
>> -        // and would have been collected into the auto-generated function.)
>>        return false;
>>    }
>> -}
>> 
>> -bool
>> -ScriptInterpreterPython::BreakpointCallbackFunction 
>> -(
>> -    void *baton, 
>> -    StoppointCallbackContext *context,
>> -    lldb::user_id_t break_id, 
>> -    lldb::user_id_t break_loc_id
>> -)
>> -{
>> -    bool ret_value = true;
>> -    bool temp_bool;
>> -
>> -    BreakpointOptions::CommandData *bp_option_data =  (BreakpointOptions::CommandData *) baton;
>> +    // Store the name of the auto-generated function to be called.
>> 
>> -    const char *python_string = bp_option_data->script_source.GetStringAtIndex(0);
>> -
>> -    if (python_string != NULL)
>> -    {
>> -        bool success = context->exe_ctx.target->GetDebugger().
>> -                                                GetCommandInterpreter().
>> -                                                GetScriptInterpreter()->ExecuteOneLineWithReturn (python_string,
>> -                                                                                             ScriptInterpreter::eBool,
>> -                                                                                             (void *) &temp_bool);
>> -        if (success)
>> -          ret_value = temp_bool;
>> -    }
>> -
>> -    return ret_value;
>> +    callback_data.AppendString (auto_generated_function_name.c_str());
>> +    return true;
>> }
>> +
>> 
>> 
>> _______________________________________________
>> lldb-commits mailing list
>> lldb-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
> 





More information about the lldb-commits mailing list