summaryrefslogtreecommitdiffstats
path: root/lldb/source
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source')
-rw-r--r--lldb/source/API/SBCommandInterpreter.cpp12
-rw-r--r--lldb/source/API/SBValue.cpp22
-rw-r--r--lldb/source/Commands/CommandObjectType.cpp376
-rw-r--r--lldb/source/Core/Debugger.cpp2
-rw-r--r--lldb/source/Core/Error.cpp8
-rw-r--r--lldb/source/Core/FormatManager.cpp53
-rw-r--r--lldb/source/Core/InputReader.cpp11
-rw-r--r--lldb/source/Core/InputReaderEZ.cpp80
-rw-r--r--lldb/source/Core/StringList.cpp32
-rw-r--r--lldb/source/Core/ValueObject.cpp400
-rw-r--r--lldb/source/Interpreter/ScriptInterpreter.cpp6
-rw-r--r--lldb/source/Interpreter/ScriptInterpreterPython.cpp175
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp1
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"
OpenPOWER on IntegriCloud