diff options
Diffstat (limited to 'lldb/source/Interpreter')
-rw-r--r-- | lldb/source/Interpreter/CommandObject.cpp | 44 | ||||
-rw-r--r-- | lldb/source/Interpreter/ScriptInterpreterPython.cpp | 245 |
2 files changed, 112 insertions, 177 deletions
diff --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp index 1607d8e11c2..b1eafd5e30f 100644 --- a/lldb/source/Interpreter/CommandObject.cpp +++ b/lldb/source/Interpreter/CommandObject.cpp @@ -697,8 +697,8 @@ SummaryStringHelpTextCallback() "A variable is expanded by giving it a value other than its textual representation, and the way this is done depends on what comes after the ${ marker.\n" "The most common sequence if ${var followed by an expression path, which is the text one would type to access a member of an aggregate types, given a variable of that type" " (e.g. if type T has a member named x, which has a member named y, and if t is of type T, the expression path would be .x.y and the way to fit that into a summary string would be" - " ${var.x.y}). In expression paths you can use either . or -> without any difference in meaning. You can also use ${*var followed by an expression path and in that case" - " the object referred by the path will be dereferenced before being displayed. If the object is not a pointer, doing so will cause an error.\n" + " ${var.x.y}). You can also use ${*var followed by an expression path and in that case the object referred by the path will be dereferenced before being displayed." + " If the object is not a pointer, doing so will cause an error. For additional details on expression paths, you can type 'help expr-path'. \n" "By default, summary strings attempt to display the summary for any variable they reference, and if that fails the value. If neither can be shown, nothing is displayed." "In a summary string, you can also use an array index [n], or a slice-like range [n-m]. This can have two different meanings depending on what kind of object the expression" " path refers to:\n" @@ -706,7 +706,41 @@ SummaryStringHelpTextCallback() " and displayed as an individual variable\n" " - if it is an array or pointer the array items indicated by the indexing operator are shown as the result of the variable. if the expression is an array, real array items are" " printed; if it is a pointer, the pointer-as-array syntax is used to obtain the values (this means, the latter case can have no range checking)\n" - "If you are trying to display an array for which the size is known, you can also use [] instead of giving an exact range. This has the effect of showing items 0 thru size - 1."; + "If you are trying to display an array for which the size is known, you can also use [] instead of giving an exact range. This has the effect of showing items 0 thru size - 1.\n" + "Additionally, a variable can contain an (optional) format code, as in ${var.x.y%code}, where code can be any of the valid formats described in 'help format', or one of the" + " special symbols only allowed as part of a variable:\n" + " %V: show the value of the object by default\n" + " %S: show the summary of the object by default\n" + " %@: show the runtime-provided object description (for Objective-C, it calls NSPrintForDebugger; for C/C++ it does nothing)\n" + " %L: show the location of the object (memory address or a register name)\n" + " %#: show the number of children of the object\n" + " %T: show the type of the object\n" + "Another variable that you can use in summary strings is ${svar . This sequence works exactly like ${var, including the fact that ${*svar is an allowed sequence, but uses" + " the object's synthetic children provider instead of the actual objects. For instance, if you are using STL synthetic children providers, the following summary string would" + " count the number of actual elements stored in an std::list:\n" + "type summary add -s \"${svar%#}\" -x \"std::list<\""; +} + +static const char * +ExprPathHelpTextCallback() +{ + return + "An expression path is the sequence of symbols that is used in C/C++ to access a member variable of an aggregate object (class).\n" + "For instance, given a class:\n" + " class foo {\n" + " int a;\n" + " int b; .\n" + " foo* next;\n" + " };\n" + "the expression to read item b in the item pointed to by next for foo aFoo would be aFoo.next->b.\n" + "Given that aFoo could just be any object of type foo, the string '.next->b' is the expression path, because it can be attached to any foo instance to achieve the effect.\n" + "Expression paths in LLDB include dot (.) and arrow (->) operators, and most commands using expression paths have ways to also accept the star (*) operator.\n" + "The meaning of these operators is the same as the usual one given to them by the C/C++ standards.\n" + "LLDB also has support for indexing ([ ]) in expression paths, and extends the traditional meaning of the square brackets operator to allow bitfield extraction:\n" + "for objects of native types (int, float, char, ...) saying '[n-m]' as an expression path (where n and m are any positive integers, e.g. [3-5]) causes LLDB to extract" + " bits n thru m from the value of the variable. If n == m, [n] is also allowed as a shortcut syntax. For arrays and pointers, expression paths can only contain one index" + " and the meaning of the operation is the same as the one defined by C/C++ (item extraction). Some commands extend bitfield-like syntax for arrays and pointers with the" + " meaning of array slicing (taking elements n thru m inside the array or pointed-to memory)."; } const char * @@ -742,6 +776,7 @@ CommandObject::g_arguments_data[] = { eArgTypeCount, "count", CommandCompletions::eNoCompletion, { NULL, false }, "An unsigned integer." }, { eArgTypeEndAddress, "end-address", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, { eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, + { eArgTypeExpressionPath, "expr-path", CommandCompletions::eNoCompletion, { ExprPathHelpTextCallback, true }, NULL }, { eArgTypeExprFormat, "expression-format", CommandCompletions::eNoCompletion, { NULL, false }, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]" }, { eArgTypeFilename, "filename", CommandCompletions::eDiskFileCompletion, { NULL, false }, "The name of a file (can include path)." }, { eArgTypeFormat, "format", CommandCompletions::eNoCompletion, { FormatHelpTextCallback, true }, NULL }, @@ -764,6 +799,9 @@ CommandObject::g_arguments_data[] = { eArgTypePid, "pid", CommandCompletions::eNoCompletion, { NULL, false }, "The process ID number." }, { eArgTypePlugin, "plugin", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, { eArgTypeProcessName, "process-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of the process." }, + { eArgTypePythonClass, "python-class", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a Python class." }, + { eArgTypePythonFunction, "python-function", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a Python function." }, + { eArgTypePythonScript, "python-script", CommandCompletions::eNoCompletion, { NULL, false }, "Source code written in Python." }, { eArgTypeQueueName, "queue-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of the thread queue." }, { eArgTypeRegisterName, "register-name", CommandCompletions::eNoCompletion, { NULL, false }, "A register name." }, { eArgTypeRegularExpression, "regular-expression", CommandCompletions::eNoCompletion, { NULL, false }, "A regular expression." }, diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp index 0f508de7c5d..bbaa8b9ad06 100644 --- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp +++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp @@ -18,9 +18,7 @@ #include <string> -#include "lldb/API/SBFrame.h" -#include "lldb/API/SBBreakpointLocation.h" -#include "lldb/API/SBCommandReturnObject.h" +#include "lldb/API/SBValue.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Timer.h" @@ -90,6 +88,36 @@ ReleasePythonLock () PythonMutexPredicate().SetValue (LLDB_INVALID_THREAD_ID, eBroadcastAlways); } +ScriptInterpreterPython::Locker::Locker (ScriptInterpreterPython *pi, + FILE* tmp_fh, + bool ns) : + m_need_session(ns), + m_release_lock(false), + m_python_interpreter(pi), + m_tmp_fh(tmp_fh) +{ + // if Enter/LeaveSession() must be called, then m_python_interpreter must be != NULL + assert(m_need_session && m_python_interpreter); + if (!CurrentThreadHasPythonLock()) + { + while (!GetPythonLock (1)) + if (tmp_fh) + fprintf (tmp_fh, + "Python interpreter locked on another thread; waiting to acquire lock...\n"); + m_release_lock = true; + } + if (m_need_session) + m_python_interpreter->EnterSession (); +} + +ScriptInterpreterPython::Locker::~Locker() +{ + if (m_need_session) + m_python_interpreter->LeaveSession (); + if (m_release_lock) + ReleasePythonLock (); +} + ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interpreter) : ScriptInterpreter (interpreter, eScriptLanguagePython), m_embedded_python_pty (), @@ -226,21 +254,10 @@ ScriptInterpreterPython::ResetOutputFileHandle (FILE *fh) m_dbg_stdout = fh; FILE *tmp_fh = (m_dbg_stdout ? m_dbg_stdout : stdout); - if (!CurrentThreadHasPythonLock ()) - { - while (!GetPythonLock (1)) - fprintf (tmp_fh, "Python interpreter locked on another thread; waiting to acquire lock...\n"); - EnterSession (); - m_new_sysout = PyFile_FromFile (m_dbg_stdout, (char *) "", (char *) "w", _check_and_flush); - LeaveSession (); - ReleasePythonLock (); - } - else - { - EnterSession (); - m_new_sysout = PyFile_FromFile (m_dbg_stdout, (char *) "", (char *) "w", _check_and_flush); - LeaveSession (); - } + + Locker py_lock(this, tmp_fh); + + m_new_sysout = PyFile_FromFile (m_dbg_stdout, (char *) "", (char *) "w", _check_and_flush); } void @@ -1400,25 +1417,12 @@ ScriptInterpreterPython::CreateSyntheticScriptedProvider (std::string class_name void* ret_val; FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) + { - python_interpreter->EnterSession (); + Locker py_lock(this, tmp_fh); ret_val = g_swig_synthetic_script (class_name, python_interpreter->m_dictionary_name.c_str(), valobj); - python_interpreter->LeaveSession (); - } - else - { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); - ret_val = g_swig_synthetic_script (class_name, - python_interpreter->m_dictionary_name.c_str(), - valobj); - python_interpreter->LeaveSession (); - ReleasePythonLock (); } return ret_val; @@ -1526,25 +1530,12 @@ ScriptInterpreterPython::CallPythonScriptFunction (const char *python_function_n && *python_function_name) { FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) + { - python_interpreter->EnterSession (); + Locker py_lock(python_interpreter, tmp_fh); ret_val = g_swig_typescript_callback (python_function_name, python_interpreter->m_dictionary_name.c_str(), valobj); - python_interpreter->LeaveSession (); - } - else - { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); - ret_val = g_swig_typescript_callback (python_function_name, - python_interpreter->m_dictionary_name.c_str(), - valobj); - python_interpreter->LeaveSession (); - ReleasePythonLock (); } } else @@ -1595,27 +1586,13 @@ ScriptInterpreterPython::BreakpointCallbackFunction { bool ret_val = true; FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) - { - python_interpreter->EnterSession (); - ret_val = g_swig_breakpoint_callback (python_function_name, - python_interpreter->m_dictionary_name.c_str(), - stop_frame_sp, - bp_loc_sp); - python_interpreter->LeaveSession (); - } - else + { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); + Locker py_lock(python_interpreter, tmp_fh); ret_val = g_swig_breakpoint_callback (python_function_name, python_interpreter->m_dictionary_name.c_str(), stop_frame_sp, bp_loc_sp); - python_interpreter->LeaveSession (); - ReleasePythonLock (); } return ret_val; } @@ -1758,55 +1735,47 @@ ScriptInterpreterPython::CalculateNumChildren (void *implementor) uint32_t ret_val = 0; FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) - { - python_interpreter->EnterSession (); - ret_val = g_swig_calc_children (implementor); - python_interpreter->LeaveSession (); - } - else + { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); + Locker py_lock(python_interpreter, tmp_fh); ret_val = g_swig_calc_children (implementor); - python_interpreter->LeaveSession (); - ReleasePythonLock (); } return ret_val; } -void* +lldb::ValueObjectSP ScriptInterpreterPython::GetChildAtIndex (void *implementor, uint32_t idx) { if (!implementor) - return 0; + return lldb::ValueObjectSP(); - if (!g_swig_get_child_index) - return 0; + if (!g_swig_get_child_index || !g_swig_cast_to_sbvalue) + return lldb::ValueObjectSP(); ScriptInterpreterPython *python_interpreter = this; - void* ret_val = NULL; + void* child_ptr = NULL; + lldb::SBValue* value_sb = NULL; + lldb::ValueObjectSP ret_val; FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) - { - python_interpreter->EnterSession (); - ret_val = g_swig_get_child_index (implementor,idx); - python_interpreter->LeaveSession (); - } - else + { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); - ret_val = g_swig_get_child_index (implementor,idx); - python_interpreter->LeaveSession (); - ReleasePythonLock (); + Locker py_lock(python_interpreter, tmp_fh); + child_ptr = g_swig_get_child_index (implementor,idx); + if (child_ptr != NULL && child_ptr != Py_None) + { + value_sb = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr); + if (value_sb == NULL) + Py_XDECREF(child_ptr); + else + ret_val = value_sb->get_sp(); + } + else + { + Py_XDECREF(child_ptr); + } } return ret_val; @@ -1826,21 +1795,10 @@ ScriptInterpreterPython::GetIndexOfChildWithName (void *implementor, const char* int ret_val = UINT32_MAX; FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) - { - python_interpreter->EnterSession (); - ret_val = g_swig_get_index_child (implementor, child_name); - python_interpreter->LeaveSession (); - } - else + { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); + Locker py_lock(python_interpreter, tmp_fh); ret_val = g_swig_get_index_child (implementor, child_name); - python_interpreter->LeaveSession (); - ReleasePythonLock (); } return ret_val; @@ -1858,60 +1816,15 @@ ScriptInterpreterPython::UpdateSynthProviderInstance (void* implementor) ScriptInterpreterPython *python_interpreter = this; FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) - { - python_interpreter->EnterSession (); - g_swig_update_provider (implementor); - python_interpreter->LeaveSession (); - } - else + { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); + Locker py_lock(python_interpreter, tmp_fh); g_swig_update_provider (implementor); - python_interpreter->LeaveSession (); - ReleasePythonLock (); } return; } -lldb::SBValue* -ScriptInterpreterPython::CastPyObjectToSBValue (void* data) -{ - if (!data) - return NULL; - - if (!g_swig_cast_to_sbvalue) - return NULL; - - ScriptInterpreterPython *python_interpreter = this; - - lldb::SBValue* ret_val = NULL; - - FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) - { - python_interpreter->EnterSession (); - ret_val = g_swig_cast_to_sbvalue (data); - python_interpreter->LeaveSession (); - } - else - { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); - ret_val = g_swig_cast_to_sbvalue (data); - python_interpreter->LeaveSession (); - ReleasePythonLock (); - } - - return ret_val; -} - bool ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function, const char* args, @@ -1939,31 +1852,15 @@ ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function, std::string err_msg; FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) - { - python_interpreter->EnterSession (); - ret_val = g_swig_call_command (impl_function, - python_interpreter->m_dictionary_name.c_str(), - debugger_sp, - args, - err_msg, - cmd_retobj); - python_interpreter->LeaveSession (); - } - else + { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); + Locker py_lock(python_interpreter, tmp_fh); ret_val = g_swig_call_command (impl_function, python_interpreter->m_dictionary_name.c_str(), debugger_sp, args, err_msg, cmd_retobj); - python_interpreter->LeaveSession (); - ReleasePythonLock (); } if (!ret_val) |