diff options
Diffstat (limited to 'lldb/source')
-rw-r--r-- | lldb/source/API/SBCommandInterpreter.cpp | 12 | ||||
-rw-r--r-- | lldb/source/API/SBValue.cpp | 22 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectType.cpp | 376 | ||||
-rw-r--r-- | lldb/source/Core/Debugger.cpp | 2 | ||||
-rw-r--r-- | lldb/source/Core/Error.cpp | 8 | ||||
-rw-r--r-- | lldb/source/Core/FormatManager.cpp | 53 | ||||
-rw-r--r-- | lldb/source/Core/InputReader.cpp | 11 | ||||
-rw-r--r-- | lldb/source/Core/InputReaderEZ.cpp | 80 | ||||
-rw-r--r-- | lldb/source/Core/StringList.cpp | 32 | ||||
-rw-r--r-- | lldb/source/Core/ValueObject.cpp | 400 | ||||
-rw-r--r-- | lldb/source/Interpreter/ScriptInterpreter.cpp | 6 | ||||
-rw-r--r-- | lldb/source/Interpreter/ScriptInterpreterPython.cpp | 175 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp | 1 |
13 files changed, 935 insertions, 243 deletions
diff --git a/lldb/source/API/SBCommandInterpreter.cpp b/lldb/source/API/SBCommandInterpreter.cpp index 0f1914b6f95..97b93141e7d 100644 --- a/lldb/source/API/SBCommandInterpreter.cpp +++ b/lldb/source/API/SBCommandInterpreter.cpp @@ -314,6 +314,15 @@ LLDBSwigPythonBreakpointCallbackFunction const lldb::BreakpointLocationSP& sb_bp_loc ); +extern "C" std::string +LLDBSwigPythonCallTypeScript +( + const char *python_function_name, + const char *session_dictionary_name, + const lldb::ValueObjectSP& valobj_sp +); + + extern "C" void init_lldb(void); void @@ -324,6 +333,7 @@ SBCommandInterpreter::InitializeSWIG () { g_initialized = true; ScriptInterpreter::InitializeInterpreter (init_lldb, - LLDBSwigPythonBreakpointCallbackFunction); + LLDBSwigPythonBreakpointCallbackFunction, + LLDBSwigPythonCallTypeScript); } } diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp index e51919cacca..aeabb1740bf 100644 --- a/lldb/source/API/SBValue.cpp +++ b/lldb/source/API/SBValue.cpp @@ -472,6 +472,28 @@ SBValue::GetChildMemberWithName (const char *name, lldb::DynamicValueType use_dy return sb_value; } +lldb::SBValue +SBValue::GetValueForExpressionPath(const char* expr_path) +{ + lldb::ValueObjectSP child_sp; + if (m_opaque_sp) + { + if (m_opaque_sp->GetUpdatePoint().GetTarget()) + { + Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex()); + // using default values for all the fancy options, just do it if you can + child_sp = m_opaque_sp->GetValueForExpressionPath(expr_path); + } + } + + SBValue sb_value (child_sp); + + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + if (log) + log->Printf ("SBValue(%p)::GetValueForExpressionPath (expr_path=\"%s\") => SBValue(%p)", m_opaque_sp.get(), expr_path, sb_value.get()); + + return sb_value; +} uint32_t SBValue::GetNumChildren () diff --git a/lldb/source/Commands/CommandObjectType.cpp b/lldb/source/Commands/CommandObjectType.cpp index c0ffddb62ae..b1e7c12bf46 100644 --- a/lldb/source/Commands/CommandObjectType.cpp +++ b/lldb/source/Commands/CommandObjectType.cpp @@ -15,8 +15,10 @@ #include "lldb/Core/ConstString.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/FormatManager.h" +#include "lldb/Core/InputReaderEZ.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/State.h" +#include "lldb/Core/StringList.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandObject.h" #include "lldb/Interpreter/CommandReturnObject.h" @@ -416,6 +418,162 @@ CommandObjectTypeFormatList_LoopCallback ( // CommandObjectTypeSummaryAdd //------------------------------------------------------------------------- +class ScriptAddOptions +{ + +public: + + bool m_skip_pointers; + bool m_skip_references; + bool m_cascade; + bool m_callback_is_synchronous; + StringList m_target_types; + StringList m_user_source; + + ScriptAddOptions(bool p, + bool r, + bool c) : + m_skip_pointers(p), + m_skip_references(r), + m_cascade(c), + m_target_types(), + m_user_source() + { + } + + typedef lldb::SharedPtr<ScriptAddOptions>::Type SharedPointer; + +}; + +static const char *g_reader_instructions = "Enter your Python command(s). Type 'DONE' to end."; + +class TypeScriptAddInputReader : public InputReaderEZ +{ +private: + DISALLOW_COPY_AND_ASSIGN (TypeScriptAddInputReader); +public: + TypeScriptAddInputReader(Debugger& debugger) : + InputReaderEZ(debugger) + {} + + virtual + ~TypeScriptAddInputReader() + { + } + + virtual void ActivateHandler(HandlerData& data) + { + StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); + bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); + if (!batch_mode) + { + out_stream->Printf ("%s\n", g_reader_instructions); + if (data.reader.GetPrompt()) + out_stream->Printf ("%s", data.reader.GetPrompt()); + out_stream->Flush(); + } + } + + virtual void ReactivateHandler(HandlerData& data) + { + StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); + bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); + if (data.reader.GetPrompt() && !batch_mode) + { + out_stream->Printf ("%s", data.reader.GetPrompt()); + out_stream->Flush(); + } + } + virtual void GotTokenHandler(HandlerData& data) + { + StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); + bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); + if (data.bytes && data.bytes_len && data.baton) + { + ((ScriptAddOptions*)data.baton)->m_user_source.AppendString(data.bytes, data.bytes_len); + } + if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode) + { + out_stream->Printf ("%s", data.reader.GetPrompt()); + out_stream->Flush(); + } + } + virtual void InterruptHandler(HandlerData& data) + { + StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); + bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); + data.reader.SetIsDone (true); + if (!batch_mode) + { + out_stream->Printf ("Warning: No command attached to breakpoint.\n"); + out_stream->Flush(); + } + } + virtual void EOFHandler(HandlerData& data) + { + data.reader.SetIsDone (true); + } + virtual void DoneHandler(HandlerData& data) + { + StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); + ScriptAddOptions *options_ptr = ((ScriptAddOptions*)data.baton); + if (!options_ptr) + { + out_stream->Printf ("Internal error #1: no script attached.\n"); + out_stream->Flush(); + return; + } + + ScriptAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope + + ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); + if (!interpreter) + { + out_stream->Printf ("Internal error #2: no script attached.\n"); + out_stream->Flush(); + return; + } + StringList funct_name_sl; + if (!interpreter->GenerateTypeScriptFunction (options->m_user_source, + funct_name_sl)) + { + out_stream->Printf ("Internal error #3: no script attached.\n"); + out_stream->Flush(); + return; + } + if (funct_name_sl.GetSize() == 0) + { + out_stream->Printf ("Internal error #4: no script attached.\n"); + out_stream->Flush(); + return; + } + const char *funct_name = funct_name_sl.GetStringAtIndex(0); + if (!funct_name || !funct_name[0]) + { + out_stream->Printf ("Internal error #5: no script attached.\n"); + out_stream->Flush(); + return; + } + // now I have a valid function name, let's add this as script for every type in the list + + SummaryFormatSP script_format; + script_format.reset(new ScriptSummaryFormat(options->m_cascade, + options->m_skip_pointers, + options->m_skip_references, + true, + true, + false, + std::string(funct_name), + options->m_user_source.CopyList(" "))); + + for (int i = 0; i < options->m_target_types.GetSize(); i++) + { + const char *type_name = options->m_target_types.GetStringAtIndex(i); + Debugger::SummaryFormats::Add(ConstString(type_name), script_format); + } + } +}; + class CommandObjectTypeSummaryAdd : public CommandObject { @@ -471,6 +629,17 @@ private: case 'n': m_name = new ConstString(option_arg); break; + case 's': + m_python_script = std::string(option_arg); + m_is_add_script = true; + break; + case 'F': + m_python_function = std::string(option_arg); + m_is_add_script = true; + break; + case 'P': + m_is_add_script = true; + break; default: error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); break; @@ -490,6 +659,9 @@ private: m_skip_pointers = false; m_regex = false; m_name = NULL; + m_python_script = ""; + m_python_function = ""; + m_is_add_script = false; } const OptionDefinition* @@ -513,6 +685,9 @@ private: bool m_regex; std::string m_format_string; ConstString* m_name; + std::string m_python_script; + std::string m_python_function; + bool m_is_add_script; }; CommandOptions m_options; @@ -601,9 +776,170 @@ public: { } + void + CollectPythonScript + ( + ScriptAddOptions *options, + CommandReturnObject &result + ) + { + InputReaderSP reader_sp (new TypeScriptAddInputReader(m_interpreter.GetDebugger())); + if (reader_sp && options) + { + + Error err (reader_sp->Initialize (options)); + if (err.Success()) + { + m_interpreter.GetDebugger().PushInputReader (reader_sp); + result.SetStatus (eReturnStatusSuccessFinishNoResult); + } + else + { + result.AppendError (err.AsCString()); + result.SetStatus (eReturnStatusFailed); + } + } + else + { + result.AppendError("out of memory"); + result.SetStatus (eReturnStatusFailed); + } + + } + bool Execute (Args& command, CommandReturnObject &result) { + if (m_options.m_is_add_script) + return Execute_ScriptSummary(command, result); + else + return Execute_StringSummary(command, result); + } + + bool + Execute_ScriptSummary (Args& command, CommandReturnObject &result) + { + const size_t argc = command.GetArgumentCount(); + + if (argc < 1) + { + result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (!m_options.m_python_function.empty()) // we have a Python function ready to use + { + ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); + if (!interpreter) + { + result.AppendError ("Internal error #1N: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); + return false; + } + const char *funct_name = m_options.m_python_function.c_str(); + if (!funct_name || !funct_name[0]) + { + result.AppendError ("Internal error #2N: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); + return false; + } + // now I have a valid function name, let's add this as script for every type in the list + + SummaryFormatSP script_format; + script_format.reset(new ScriptSummaryFormat(m_options.m_cascade, + m_options.m_skip_pointers, + m_options.m_skip_references, + true, + true, + false, + std::string(funct_name), + " " + m_options.m_python_function + "(valobj,dict)")); + + for (int i = 0; i < command.GetArgumentCount(); i++) + { + const char *type_name = command.GetArgumentAtIndex(i); + Debugger::SummaryFormats::Add(ConstString(type_name), script_format); + } + } + else if (m_options.m_python_script.empty()) // use an InputReader to grab Python code from the user + { + ScriptAddOptions *options = new ScriptAddOptions(m_options.m_skip_pointers, + m_options.m_skip_references, + m_options.m_cascade); + + for(int i = 0; i < argc; i++) { + const char* typeA = command.GetArgumentAtIndex(i); + if (typeA && *typeA) + options->m_target_types << typeA; + else + { + result.AppendError("empty typenames not allowed"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + + CollectPythonScript(options,result); + return result.Succeeded(); + } + else // we have a quick 1-line script, just use it + { + ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); + if (!interpreter) + { + result.AppendError ("Internal error #1Q: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); + return false; + } + StringList funct_sl; + funct_sl << m_options.m_python_script.c_str(); + StringList funct_name_sl; + if (!interpreter->GenerateTypeScriptFunction (funct_sl, + funct_name_sl)) + { + result.AppendError ("Internal error #2Q: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); + return false; + } + if (funct_name_sl.GetSize() == 0) + { + result.AppendError ("Internal error #3Q: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); + return false; + } + const char *funct_name = funct_name_sl.GetStringAtIndex(0); + if (!funct_name || !funct_name[0]) + { + result.AppendError ("Internal error #4Q: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); + return false; + } + // now I have a valid function name, let's add this as script for every type in the list + + ScriptFormatSP script_format; + script_format.reset(new ScriptSummaryFormat(m_options.m_cascade, + m_options.m_skip_pointers, + m_options.m_skip_references, + true, + true, + false, + std::string(funct_name), + " " + m_options.m_python_script)); + + for (int i = 0; i < command.GetArgumentCount(); i++) + { + const char *type_name = command.GetArgumentAtIndex(i); + Debugger::SummaryFormats::Add(ConstString(type_name), script_format); + } + } + + return result.Succeeded(); + } + + bool + Execute_StringSummary (Args& command, CommandReturnObject &result) + { const size_t argc = command.GetArgumentCount(); if (argc < 1 && !m_options.m_name) @@ -624,11 +960,13 @@ public: Error error; - SummaryFormat::SharedPointer entry(new SummaryFormat(format_cstr,m_options.m_cascade, - m_options.m_no_children,m_options.m_no_value, - m_options.m_one_liner, - m_options.m_skip_pointers, - m_options.m_skip_references)); + SummaryFormat::SharedPointer entry(new StringSummaryFormat(m_options.m_cascade, + m_options.m_skip_pointers, + m_options.m_skip_references, + m_options.m_no_children, + m_options.m_no_value, + m_options.m_one_liner, + format_cstr)); if (error.Fail()) { @@ -698,6 +1036,9 @@ CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] = { LLDB_OPT_SET_2 , true, "format-string", 'f', required_argument, NULL, 0, eArgTypeSummaryString, "Format string used to display text and object contents."}, { LLDB_OPT_SET_2, false, "expand", 'e', no_argument, NULL, 0, eArgTypeBoolean, "Expand aggregate data types to show children on separate lines."}, { LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeName, "A name for this summary string."}, + { LLDB_OPT_SET_3, false, "python-script", 's', required_argument, NULL, 0, eArgTypeName, "Give a one-liner Python script as part of the command."}, + { LLDB_OPT_SET_3, false, "python-function", 'F', required_argument, NULL, 0, eArgTypeName, "Give the name of a Python function to use for this type."}, + { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeName, "Input Python code to use for this type manually."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -808,8 +1149,8 @@ public: // CommandObjectTypeSummaryList //------------------------------------------------------------------------- -bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, const char* type, const SummaryFormat::SharedPointer& entry); -bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SummaryFormat::SharedPointer& entry); +bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, const char* type, const StringSummaryFormat::SharedPointer& entry); +bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const StringSummaryFormat::SharedPointer& entry); class CommandObjectTypeSummaryList; @@ -912,16 +1253,7 @@ private: CommandReturnObject *result) { if (regex == NULL || regex->Execute(type)) - { - result->GetOutputStream().Printf ("%s: `%s`%s%s%s%s%s%s\n", type, - entry->m_format.c_str(), - entry->m_cascades ? "" : " (not cascading)", - entry->m_dont_show_children ? "" : " (show children)", - entry->m_dont_show_value ? " (hide value)" : "", - entry->m_show_members_oneliner ? " (one-line printout)" : "", - entry->m_skip_pointers ? " (skip pointers)" : "", - entry->m_skip_references ? " (skip references)" : ""); - } + result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str()); return true; } @@ -951,8 +1283,6 @@ CommandObjectTypeRXSummaryList_LoopCallback ( } - - class CommandObjectTypeFormat : public CommandObjectMultiword { public: @@ -983,10 +1313,10 @@ public: "A set of commands for editing variable summary display options", "type summary [<sub-command-options>] ") { - LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter))); - LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter))); - LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter))); - LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSummaryList (interpreter))); + LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter))); + LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter))); + LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter))); + LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSummaryList (interpreter))); } diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 2c36dbb8c66..029a1d85b53 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -733,6 +733,8 @@ ScanFormatDescriptor(const char* var_name_begin, // if this is a V, print the value using the default format if (*format_name == 'V') *val_obj_display = ValueObject::eDisplayValue; + if (*format_name == 'L') + *val_obj_display = ValueObject::eDisplayLocation; } // a good custom format tells us to print the value using it else diff --git a/lldb/source/Core/Error.cpp b/lldb/source/Core/Error.cpp index 6e21fe7ee2b..61faca464b7 100644 --- a/lldb/source/Core/Error.cpp +++ b/lldb/source/Core/Error.cpp @@ -51,6 +51,14 @@ Error::Error (const Error &rhs) : { } +Error::Error (const char* err_str): + m_code (0), + m_type (eErrorTypeInvalid), + m_string () +{ + SetErrorString(err_str); +} + //---------------------------------------------------------------------- // Assignment operator //---------------------------------------------------------------------- diff --git a/lldb/source/Core/FormatManager.cpp b/lldb/source/Core/FormatManager.cpp index 040b9cd9ebd..7be3791adbb 100644 --- a/lldb/source/Core/FormatManager.cpp +++ b/lldb/source/Core/FormatManager.cpp @@ -14,6 +14,8 @@ // Other libraries and framework includes // Project includes +#include "lldb/Core/Debugger.h" + using namespace lldb; using namespace lldb_private; @@ -217,3 +219,54 @@ FormatManager::GetSingleItemFormat(lldb::Format vector_format) return lldb::eFormatInvalid; } } + +std::string +StringSummaryFormat::FormatObject(lldb::ValueObjectSP object) +{ + if (!object.get()) + return "NULL"; + + StreamString s; + ExecutionContext exe_ctx; + object->GetExecutionContextScope()->CalculateExecutionContext(exe_ctx); + SymbolContext sc; + if (exe_ctx.frame) + sc = exe_ctx.frame->GetSymbolContext(lldb::eSymbolContextEverything); + + if (m_show_members_oneliner) + { + const uint32_t num_children = object->GetNumChildren(); + if (num_children) + { + s.PutChar('('); + + for (uint32_t idx=0; idx<num_children; ++idx) + { + lldb::ValueObjectSP child_sp(object->GetChildAtIndex(idx, true)); + if (child_sp.get()) + { + if (idx) + s.PutCString(", "); + s.PutCString(child_sp.get()->GetName().AsCString()); + s.PutChar('='); + s.PutCString(child_sp.get()->GetPrintableRepresentation()); + } + } + + s.PutChar(')'); + + return s.GetString(); + } + else + return ""; + + } + else + { + if (Debugger::FormatPrompt(m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, NULL, object.get())) + return s.GetString(); + else + return ""; + } +} + diff --git a/lldb/source/Core/InputReader.cpp b/lldb/source/Core/InputReader.cpp index c6e90eb54d7..84cd0a15f84 100644 --- a/lldb/source/Core/InputReader.cpp +++ b/lldb/source/Core/InputReader.cpp @@ -370,3 +370,14 @@ InputReader::GranularityAsCString (lldb::InputReaderGranularity granularity) return unknown_state_string; } +bool +InputReader::HandlerData::GetBatchMode() +{ + return reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); +} + +lldb::StreamSP +InputReader::HandlerData::GetOutStream() +{ + return reader.GetDebugger().GetAsyncOutputStream(); +}
\ No newline at end of file diff --git a/lldb/source/Core/InputReaderEZ.cpp b/lldb/source/Core/InputReaderEZ.cpp new file mode 100644 index 00000000000..839d744a5ac --- /dev/null +++ b/lldb/source/Core/InputReaderEZ.cpp @@ -0,0 +1,80 @@ +//===-- InputReaderEZ.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <string> + +#include "lldb/Core/InputReaderEZ.h" + +#include "lldb/Core/Debugger.h" +#include "lldb/Interpreter/CommandInterpreter.h" + +using namespace lldb; +using namespace lldb_private; + +size_t +InputReaderEZ::Callback_Impl(void *baton, + InputReader &reader, + lldb::InputReaderAction notification, + const char *bytes, + size_t bytes_len) + +{ + HandlerData hand_data(reader, + bytes, + bytes_len, + baton); + + switch (notification) + { + case eInputReaderActivate: + reader.ActivateHandler(hand_data); + break; + case eInputReaderDeactivate: + reader.DeactivateHandler(hand_data); + break; + case eInputReaderReactivate: + reader.ReactivateHandler(hand_data); + break; + case eInputReaderAsynchronousOutputWritten: + reader.AsynchronousOutputWrittenHandler(hand_data); + break; + case eInputReaderGotToken: + reader.GotTokenHandler(hand_data); + break; + case eInputReaderInterrupt: + reader.InterruptHandler(hand_data); + break; + case eInputReaderEndOfFile: + reader.EOFHandler(hand_data); + break; + case eInputReaderDone: + reader.DoneHandler(hand_data); + break; + } + return bytes_len; +} + +Error +InputReaderEZ::Initialize(void* baton, + lldb::InputReaderGranularity token_size, + const char* end_token, + const char *prompt, + bool echo) +{ + return InputReader::Initialize(Callback_Impl, + baton, + token_size, + end_token, + prompt, + echo); +} + +InputReaderEZ::~InputReaderEZ () +{ +}
\ No newline at end of file diff --git a/lldb/source/Core/StringList.cpp b/lldb/source/Core/StringList.cpp index d3392623083..fbe0cfef157 100644 --- a/lldb/source/Core/StringList.cpp +++ b/lldb/source/Core/StringList.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include "lldb/Core/StringList.h" + +#include "lldb/Core/StreamString.h" #include "lldb/Host/FileSpec.h" #include <string> @@ -205,3 +207,33 @@ StringList::RemoveBlankLines () idx++; } } + +std::string +StringList::CopyList(const char* item_preamble, + const char* items_sep) +{ + StreamString strm; + for (int i = 0; i < GetSize(); i++) + { + if (i && items_sep && items_sep[0]) + strm << items_sep; + if (item_preamble) + strm << item_preamble; + strm << GetStringAtIndex(i); + } + return std::string(strm.GetData()); +} + +StringList& +StringList::operator << (const char* str) +{ + AppendString(str); + return *this; +} + +StringList& +StringList::operator << (StringList strings) +{ + AppendList(strings); + return *this; +}
\ No newline at end of file diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index d8e0e0f8ef8..ca0b0aca0c6 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -29,6 +29,8 @@ #include "lldb/Host/Endian.h" +#include "lldb/Interpreter/ScriptInterpreterPython.h" + #include "lldb/Symbol/ClangASTType.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/Type.h" @@ -79,8 +81,8 @@ ValueObject::ValueObject (ValueObject &parent) : m_is_array_item_for_pointer(false), m_is_bitfield_for_scalar(false), m_last_format_mgr_revision(0), - m_last_summary_format(), m_last_value_format(), + m_last_summary_format(), m_forced_summary_format(), m_dump_printable_counter(0) { @@ -118,8 +120,8 @@ ValueObject::ValueObject (ExecutionContextScope *exe_scope) : m_is_array_item_for_pointer(false), m_is_bitfield_for_scalar(false), m_last_format_mgr_revision(0), - m_last_summary_format(), m_last_value_format(), + m_last_summary_format(), m_forced_summary_format(), m_dump_printable_counter(0) { @@ -164,10 +166,9 @@ ValueObject::UpdateValueIfNeeded (bool update_format) m_old_value_str.swap (m_value_str); m_value_str.clear(); } - m_location_str.clear(); - m_summary_str.clear(); - m_object_desc_str.clear(); + ClearUserVisibleData(); + const bool value_was_valid = GetValueIsValid(); SetValueDidChange (false); @@ -204,15 +205,15 @@ ValueObject::UpdateFormatsIfNeeded() if (m_last_format_mgr_revision != Debugger::ValueFormats::GetCurrentRevision()) { if (m_last_summary_format.get()) - m_last_summary_format.reset((SummaryFormat*)NULL); + m_last_summary_format.reset((StringSummaryFormat*)NULL); if (m_last_value_format.get()) m_last_value_format.reset((ValueFormat*)NULL); Debugger::ValueFormats::Get(*this, m_last_value_format); if (!Debugger::SummaryFormats::Get(*this, m_last_summary_format)) Debugger::RegexSummaryFormats::Get(*this, m_last_summary_format); m_last_format_mgr_revision = Debugger::ValueFormats::GetCurrentRevision(); - m_value_str.clear(); - m_summary_str.clear(); + + ClearUserVisibleData(); } } @@ -507,221 +508,177 @@ ValueObject::GetSummaryAsCString () { if (m_summary_str.empty()) { - SummaryFormat* summary_format = GetSummaryFormat().get(); + SummaryFormat *summary_format = GetSummaryFormat().get(); if (summary_format) { - StreamString s; - ExecutionContext exe_ctx; - this->GetExecutionContextScope()->CalculateExecutionContext(exe_ctx); - SymbolContext sc; - if (exe_ctx.frame) - sc = exe_ctx.frame->GetSymbolContext(eSymbolContextEverything); - - if (summary_format->m_show_members_oneliner) - { - const uint32_t num_children = GetNumChildren(); - if (num_children) - { - - s.PutChar('('); - - for (uint32_t idx=0; idx<num_children; ++idx) - { - ValueObjectSP child_sp(GetChildAtIndex(idx, true)); - if (child_sp.get()) - { - if (idx) - s.PutCString(", "); - s.PutCString(child_sp.get()->GetName().AsCString()); - s.PutChar('='); - s.PutCString(child_sp.get()->GetPrintableRepresentation()); - } - } - - s.PutChar(')'); - - m_summary_str.swap(s.GetString()); - return m_summary_str.c_str(); - } - else - return "()"; - - } - else - { - if (Debugger::FormatPrompt(summary_format->m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, NULL, this)) - { - m_summary_str.swap(s.GetString()); - return m_summary_str.c_str(); - } - else - return NULL; - } + m_summary_str = summary_format->FormatObject(GetSP()); } - - clang_type_t clang_type = GetClangType(); - - // See if this is a pointer to a C string? - if (clang_type) + else { - StreamString sstr; - clang_type_t elem_or_pointee_clang_type; - const Flags type_flags (ClangASTContext::GetTypeInfo (clang_type, - GetClangAST(), - &elem_or_pointee_clang_type)); - - ExecutionContextScope *exe_scope = GetExecutionContextScope(); - if (exe_scope) + clang_type_t clang_type = GetClangType(); + + // See if this is a pointer to a C string? + if (clang_type) { - if (type_flags.AnySet (ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer) && - ClangASTContext::IsCharType (elem_or_pointee_clang_type)) + StreamString sstr; + clang_type_t elem_or_pointee_clang_type; + const Flags type_flags (ClangASTContext::GetTypeInfo (clang_type, + GetClangAST(), + &elem_or_pointee_clang_type)); + + ExecutionContextScope *exe_scope = GetExecutionContextScope(); + if (exe_scope) { - Target *target = exe_scope->CalculateTarget(); - if (target != NULL) + if (type_flags.AnySet (ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer) && + ClangASTContext::IsCharType (elem_or_pointee_clang_type)) { - lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS; - AddressType cstr_address_type = eAddressTypeInvalid; - - size_t cstr_len = 0; - bool capped_data = false; - if (type_flags.Test (ClangASTContext::eTypeIsArray)) + Target *target = exe_scope->CalculateTarget(); + if (target != NULL) { - // We have an array - cstr_len = ClangASTContext::GetArraySize (clang_type); - if (cstr_len > 512) // TODO: make cap a setting + lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS; + AddressType cstr_address_type = eAddressTypeInvalid; + + size_t cstr_len = 0; + bool capped_data = false; + if (type_flags.Test (ClangASTContext::eTypeIsArray)) { + // We have an array cstr_len = ClangASTContext::GetArraySize (clang_type); if (cstr_len > 512) // TODO: make cap a setting { - capped_data = true; - cstr_len = 512; + cstr_len = ClangASTContext::GetArraySize (clang_type); + if (cstr_len > 512) // TODO: make cap a setting + { + capped_data = true; + cstr_len = 512; + } } + cstr_address = GetAddressOf (cstr_address_type, true); } - cstr_address = GetAddressOf (cstr_address_type, true); - } - else - { - // We have a pointer - cstr_address = GetPointerValue (cstr_address_type, true); - } - if (cstr_address != LLDB_INVALID_ADDRESS) - { - Address cstr_so_addr (NULL, cstr_address); - DataExtractor data; - size_t bytes_read = 0; - std::vector<char> data_buffer; - Error error; - bool prefer_file_cache = false; - if (cstr_len > 0) + else { - data_buffer.resize(cstr_len); - data.SetData (&data_buffer.front(), data_buffer.size(), lldb::endian::InlHostByteOrder()); - bytes_read = target->ReadMemory (cstr_so_addr, - prefer_file_cache, - &data_buffer.front(), - cstr_len, - error); - if (bytes_read > 0) - { - sstr << '"'; - data.Dump (&sstr, - 0, // Start offset in "data" - eFormatCharArray, // Print as characters - 1, // Size of item (1 byte for a char!) - bytes_read, // How many bytes to print? - UINT32_MAX, // num per line - LLDB_INVALID_ADDRESS,// base address - 0, // bitfield bit size - 0); // bitfield bit offset - if (capped_data) - sstr << "..."; - sstr << '"'; - } + // We have a pointer + cstr_address = GetPointerValue (cstr_address_type, true); } - else + if (cstr_address != LLDB_INVALID_ADDRESS) { - const size_t k_max_buf_size = 256; - data_buffer.resize (k_max_buf_size + 1); - // NULL terminate in case we don't get the entire C string - data_buffer.back() = '\0'; - - sstr << '"'; - - data.SetData (&data_buffer.front(), data_buffer.size(), endian::InlHostByteOrder()); - while ((bytes_read = target->ReadMemory (cstr_so_addr, - prefer_file_cache, - &data_buffer.front(), - k_max_buf_size, - error)) > 0) + Address cstr_so_addr (NULL, cstr_address); + DataExtractor data; + size_t bytes_read = 0; + std::vector<char> data_buffer; + Error error; + bool prefer_file_cache = false; + if (cstr_len > 0) { - size_t len = strlen(&data_buffer.front()); - if (len == 0) - break; - if (len > bytes_read) - len = bytes_read; - - data.Dump (&sstr, - 0, // Start offset in "data" - eFormatCharArray, // Print as characters - 1, // Size of item (1 byte for a char!) - len, // How many bytes to print? - UINT32_MAX, // num per line - LLDB_INVALID_ADDRESS,// base address - 0, // bitfield bit size - 0); // bitfield bit offset - - if (len < k_max_buf_size) - break; - cstr_so_addr.Slide (k_max_buf_size); + data_buffer.resize(cstr_len); + data.SetData (&data_buffer.front(), data_buffer.size(), lldb::endian::InlHostByteOrder()); + bytes_read = target->ReadMemory (cstr_so_addr, + prefer_file_cache, + &data_buffer.front(), + cstr_len, + error); + if (bytes_read > 0) + { + sstr << '"'; + data.Dump (&sstr, + 0, // Start offset in "data" + eFormatCharArray, // Print as characters + 1, // Size of item (1 byte for a char!) + bytes_read, // How many bytes to print? + UINT32_MAX, // num per line + LLDB_INVALID_ADDRESS,// base address + 0, // bitfield bit size + 0); // bitfield bit offset + if (capped_data) + sstr << "..."; + sstr << '"'; + } + } + else + { + const size_t k_max_buf_size = 256; + data_buffer.resize (k_max_buf_size + 1); + // NULL terminate in case we don't get the entire C string + data_buffer.back() = '\0'; + + sstr << '"'; + + data.SetData (&data_buffer.front(), data_buffer.size(), endian::InlHostByteOrder()); + while ((bytes_read = target->ReadMemory (cstr_so_addr, + prefer_file_cache, + &data_buffer.front(), + k_max_buf_size, + error)) > 0) + { + size_t len = strlen(&data_buffer.front()); + if (len == 0) + break; + if (len > bytes_read) + len = bytes_read; + + data.Dump (&sstr, + 0, // Start offset in "data" + eFormatCharArray, // Print as characters + 1, // Size of item (1 byte for a char!) + len, // How many bytes to print? + UINT32_MAX, // num per line + LLDB_INVALID_ADDRESS,// base address + 0, // bitfield bit size + 0); // bitfield bit offset + + if (len < k_max_buf_size) + break; + cstr_so_addr.Slide (k_max_buf_size); + } + sstr << '"'; } - sstr << '"'; } } + + if (sstr.GetSize() > 0) + m_summary_str.assign (sstr.GetData(), sstr.GetSize()); } - - if (sstr.GetSize() > 0) - m_summary_str.assign (sstr.GetData(), sstr.GetSize()); - } - else if (ClangASTContext::IsFunctionPointerType (clang_type)) - { - AddressType func_ptr_address_type = eAddressTypeInvalid; - lldb::addr_t func_ptr_address = GetPointerValue (func_ptr_address_type, true); - - if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS) + else if (ClangASTContext::IsFunctionPointerType (clang_type)) { - switch (func_ptr_address_type) - { - case eAddressTypeInvalid: - case eAddressTypeFile: - break; + AddressType func_ptr_address_type = eAddressTypeInvalid; + lldb::addr_t func_ptr_address = GetPointerValue (func_ptr_address_type, true); - case eAddressTypeLoad: + if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS) + { + switch (func_ptr_address_type) { - Address so_addr; - Target *target = exe_scope->CalculateTarget(); - if (target && target->GetSectionLoadList().IsEmpty() == false) + case eAddressTypeInvalid: + case eAddressTypeFile: + break; + + case eAddressTypeLoad: { - if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr)) + Address so_addr; + Target *target = exe_scope->CalculateTarget(); + if (target && target->GetSectionLoadList().IsEmpty() == false) { - so_addr.Dump (&sstr, - exe_scope, - Address::DumpStyleResolvedDescription, - Address::DumpStyleSectionNameOffset); + if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr)) + { + so_addr.Dump (&sstr, + exe_scope, + Address::DumpStyleResolvedDescription, + Address::DumpStyleSectionNameOffset); + } } } - } - break; + break; - case eAddressTypeHost: - break; + case eAddressTypeHost: + break; + } + } + if (sstr.GetSize() > 0) + { + m_summary_str.assign (1, '('); + m_summary_str.append (sstr.GetData(), sstr.GetSize()); + m_summary_str.append (1, ')'); } - } - if (sstr.GetSize() > 0) - { - m_summary_str.assign (1, '('); - m_summary_str.append (sstr.GetData(), sstr.GetSize()); - m_summary_str.append (1, ')'); } } } @@ -960,34 +917,35 @@ ValueObject::GetValueAsCString () clang_type_t clang_type = GetClangType (); if (clang_type) { - StreamString sstr; - Format format = GetFormat(); - if (format == eFormatDefault) + if (m_last_value_format) { - if (m_last_value_format) - format = m_last_value_format->m_format; - else - // force the system into using unsigned integers for bitfields - format = (m_is_bitfield_for_scalar ? eFormatUnsigned : - ClangASTType::GetFormat(clang_type)); + m_value_str = m_last_value_format->FormatObject(GetSP()); } - - if (ClangASTType::DumpTypeValue (GetClangAST(), // The clang AST - clang_type, // The clang type to display - &sstr, - format, // Format to display this type with - m_data, // Data to extract from - 0, // Byte offset into "m_data" - GetByteSize(), // Byte size of item in "m_data" - GetBitfieldBitSize(), // Bitfield bit size - GetBitfieldBitOffset())) // Bitfield bit offset - m_value_str.swap(sstr.GetString()); else { - m_error.SetErrorStringWithFormat ("unsufficient data for value (only %u of %u bytes available)", - m_data.GetByteSize(), - GetByteSize()); - m_value_str.clear(); + StreamString sstr; + Format format = GetFormat(); + if (format == eFormatDefault) + format = (m_is_bitfield_for_scalar ? eFormatUnsigned : + ClangASTType::GetFormat(clang_type)); + + if (ClangASTType::DumpTypeValue (GetClangAST(), // The clang AST + clang_type, // The clang type to display + &sstr, + format, // Format to display this type with + m_data, // Data to extract from + 0, // Byte offset into "m_data" + GetByteSize(), // Byte size of item in "m_data" + GetBitfieldBitSize(), // Bitfield bit size + GetBitfieldBitOffset())) // Bitfield bit offset + m_value_str.swap(sstr.GetString()); + else + { + m_error.SetErrorStringWithFormat ("unsufficient data for value (only %u of %u bytes available)", + m_data.GetByteSize(), + GetByteSize()); + m_value_str.clear(); + } } } } @@ -1046,6 +1004,9 @@ ValueObject::GetPrintableRepresentation(ValueObjectRepresentationStyle val_obj_d case eDisplayLanguageSpecific: return_value = GetObjectDescription(); break; + case eDisplayLocation: + return_value = GetLocationAsCString(); + break; } // this code snippet might lead to endless recursion, thus we use a RefCounter here to @@ -3221,3 +3182,12 @@ ValueObject::EvaluationPoint::SetContext (ExecutionContextScope *exe_scope) return needs_update; } + +void +ValueObject::ClearUserVisibleData() +{ + m_location_str.clear(); + m_value_str.clear(); + m_summary_str.clear(); + m_object_desc_str.clear(); +}
\ No newline at end of file diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp index 7011c2e7f2b..294aeec3517 100644 --- a/lldb/source/Interpreter/ScriptInterpreter.cpp +++ b/lldb/source/Interpreter/ScriptInterpreter.cpp @@ -92,10 +92,12 @@ ScriptInterpreter::LanguageToString (lldb::ScriptLanguage language) void ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_callback, - SWIGBreakpointCallbackFunction python_swig_breakpoint_callback) + SWIGBreakpointCallbackFunction python_swig_breakpoint_callback, + SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback) { ScriptInterpreterPython::InitializeInterpreter (python_swig_init_callback, - python_swig_breakpoint_callback); + python_swig_breakpoint_callback, + python_swig_typescript_callback); } void diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp index 610c019cb33..57a5929fc58 100644 --- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp +++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp @@ -34,6 +34,7 @@ using namespace lldb_private; static ScriptInterpreter::SWIGInitCallback g_swig_init_callback = NULL; static ScriptInterpreter::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = NULL; +static ScriptInterpreter::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = NULL; static int @@ -1140,6 +1141,117 @@ ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter (StringList &func return ExecuteMultipleLines (function_def_string.c_str()); } +// TODO move both GenerateTypeScriptFunction and GenerateBreakpointCommandCallbackData to actually +// use this code to generate their functions +bool +ScriptInterpreterPython::GenerateFunction(std::string& signature, StringList &input, StringList &output) +{ + int num_lines = input.GetSize (); + if (num_lines == 0) + return false; + StreamString sstr; + StringList auto_generated_function; + auto_generated_function.AppendString (signature.c_str()); + auto_generated_function.AppendString (" global_dict = globals()"); // Grab the global dictionary + auto_generated_function.AppendString (" new_keys = dict.keys()"); // Make a list of keys in the session dict + auto_generated_function.AppendString (" old_keys = global_dict.keys()"); // Save list of keys in global dict + auto_generated_function.AppendString (" global_dict.update (dict)"); // Add the session dictionary to the + // global dictionary. + + // Wrap everything up inside the function, increasing the indentation. + + for (int i = 0; i < num_lines; ++i) + { + sstr.Clear (); + sstr.Printf (" %s", input.GetStringAtIndex (i)); + auto_generated_function.AppendString (sstr.GetData()); + } + auto_generated_function.AppendString (" for key in new_keys:"); // Iterate over all the keys from session dict + auto_generated_function.AppendString (" dict[key] = global_dict[key]"); // Update session dict values + auto_generated_function.AppendString (" if key not in old_keys:"); // If key was not originally in global dict + auto_generated_function.AppendString (" del global_dict[key]"); // ...then remove key/value from global dict + + // Verify that the results are valid Python. + + if (!ExportFunctionDefinitionToInterpreter (auto_generated_function)) + return false; + + return true; + +} + +// this implementation is identical to GenerateBreakpointCommandCallbackData (apart from the name +// given to generated functions, of course) +bool +ScriptInterpreterPython::GenerateTypeScriptFunction (StringList &user_input, StringList &output) +{ + static int num_created_functions = 0; + user_input.RemoveBlankLines (); + int num_lines = user_input.GetSize (); + StreamString sstr; + + // Check to see if we have any data; if not, just return. + if (user_input.GetSize() == 0) + return false; + + // Take what the user wrote, wrap it all up inside one big auto-generated Python function, passing in the + // ValueObject as parameter to the function. + + sstr.Printf ("lldb_autogen_python_type_print_func_%d", num_created_functions); + ++num_created_functions; + std::string auto_generated_function_name = sstr.GetData(); + + sstr.Clear(); + StringList auto_generated_function; + + // Create the function name & definition string. + + sstr.Printf ("def %s (valobj, dict):", auto_generated_function_name.c_str()); + auto_generated_function.AppendString (sstr.GetData()); + + // Pre-pend code for setting up the session dictionary. + + auto_generated_function.AppendString (" global_dict = globals()"); // Grab the global dictionary + auto_generated_function.AppendString (" new_keys = dict.keys()"); // Make a list of keys in the session dict + auto_generated_function.AppendString (" old_keys = global_dict.keys()"); // Save list of keys in global dict + auto_generated_function.AppendString (" global_dict.update (dict)"); // Add the session dictionary to the + // global dictionary. + + // Wrap everything up inside the function, increasing the indentation. + + for (int i = 0; i < num_lines; ++i) + { + sstr.Clear (); + sstr.Printf (" %s", user_input.GetStringAtIndex (i)); + auto_generated_function.AppendString (sstr.GetData()); + } + + // Append code to clean up the global dictionary and update the session dictionary (all updates in the function + // got written to the values in the global dictionary, not the session dictionary). + + auto_generated_function.AppendString (" for key in new_keys:"); // Iterate over all the keys from session dict + auto_generated_function.AppendString (" dict[key] = global_dict[key]"); // Update session dict values + auto_generated_function.AppendString (" if key not in old_keys:"); // If key was not originally in global dict + auto_generated_function.AppendString (" del global_dict[key]"); // ...then remove key/value from global dict + + // Verify that the results are valid Python. + + if (!ExportFunctionDefinitionToInterpreter (auto_generated_function)) + return false; + + // Store the name of the auto-generated function to be called. + + output.AppendString (auto_generated_function_name.c_str()); + return true; +} + +bool +ScriptInterpreterPython::GenerateTypeScriptFunction (const char* oneliner, StringList &output) +{ + StringList input(oneliner); + return GenerateTypeScriptFunction(input, output); +} + bool ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user_input, StringList &callback_data) { @@ -1206,6 +1318,63 @@ ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user return true; } +std::string +ScriptInterpreterPython::CallPythonScriptFunction (const char *python_function_name, + lldb::ValueObjectSP valobj) +{ + + if (!python_function_name || !(*python_function_name)) + return "<no function>"; + + if (!valobj.get()) + return "<no object>"; + + Target *target = valobj->GetUpdatePoint().GetTarget(); + + if (!target) + return "<no target>"; + + Debugger &debugger = target->GetDebugger(); + ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); + ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter; + + if (!script_interpreter) + return "<no python>"; + + std::string ret_val; + + if (python_function_name + && *python_function_name) + { + FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); + if (CurrentThreadHasPythonLock()) + { + python_interpreter->EnterSession (); + 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 + return "<no function name>"; + + return ret_val; + +} + bool ScriptInterpreterPython::BreakpointCallbackFunction ( @@ -1399,10 +1568,12 @@ ScriptInterpreterPython::RunEmbeddedPythonInterpreter (lldb::thread_arg_t baton) void ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback python_swig_init_callback, - SWIGBreakpointCallbackFunction python_swig_breakpoint_callback) + SWIGBreakpointCallbackFunction python_swig_breakpoint_callback, + SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback) { g_swig_init_callback = python_swig_init_callback; - g_swig_breakpoint_callback = python_swig_breakpoint_callback; + g_swig_breakpoint_callback = python_swig_breakpoint_callback; + g_swig_typescript_callback = python_swig_typescript_callback; } void diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index 0619c107655..9712d6f2ccd 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -19,6 +19,7 @@ #include "lldb/Core/Log.h" #include "lldb/Core/State.h" #include "lldb/Core/StreamString.h" +#include "lldb/Host/Endian.h" #include "lldb/Host/Host.h" #include "lldb/Host/TimeValue.h" #include "lldb/Target/Process.h" |