[Lldb-commits] [lldb] r250773 - Added support for the "--repl" argument to LLDB.
Sean Callanan via lldb-commits
lldb-commits at lists.llvm.org
Mon Oct 19 17:23:46 PDT 2015
Author: spyffe
Date: Mon Oct 19 19:23:46 2015
New Revision: 250773
URL: http://llvm.org/viewvc/llvm-project?rev=250773&view=rev
Log:
Added support for the "--repl" argument to LLDB.
This makes LLDB launch and create a REPL, specifying no target so that the REPL
can create one for itself. Also added the "--repl-language" option, which
specifies the language to use. Plumbed the relevant arguments and errors
through the REPL creation mechanism.
Modified:
lldb/trunk/include/lldb/API/SBDebugger.h
lldb/trunk/include/lldb/Core/Debugger.h
lldb/trunk/include/lldb/Expression/REPL.h
lldb/trunk/include/lldb/Target/Target.h
lldb/trunk/include/lldb/lldb-private-interfaces.h
lldb/trunk/scripts/interface/SBDebugger.i
lldb/trunk/source/API/SBDebugger.cpp
lldb/trunk/source/Core/Debugger.cpp
lldb/trunk/source/Expression/REPL.cpp
lldb/trunk/source/Target/Target.cpp
lldb/trunk/tools/driver/Driver.cpp
lldb/trunk/tools/driver/Driver.h
Modified: lldb/trunk/include/lldb/API/SBDebugger.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBDebugger.h?rev=250773&r1=250772&r2=250773&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBDebugger.h (original)
+++ lldb/trunk/include/lldb/API/SBDebugger.h Mon Oct 19 19:23:46 2015
@@ -329,6 +329,9 @@ public:
int &num_errors,
bool &quit_requested,
bool &stopped_for_crash);
+
+ SBError
+ RunREPL (lldb::LanguageType language, const char *repl_options);
private:
friend class SBCommandInterpreter;
Modified: lldb/trunk/include/lldb/Core/Debugger.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Debugger.h?rev=250773&r1=250772&r2=250773&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Debugger.h (original)
+++ lldb/trunk/include/lldb/Core/Debugger.h Mon Oct 19 19:23:46 2015
@@ -375,6 +375,9 @@ public:
{
return m_event_handler_thread.IsJoinable();
}
+
+ Error
+ RunREPL (lldb::LanguageType language, const char *repl_options);
// This is for use in the command interpreter, when you either want the selected target, or if no target
// is present you want to prime the dummy target with entities that will be copied over to new targets.
Modified: lldb/trunk/include/lldb/Expression/REPL.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/REPL.h?rev=250773&r1=250772&r2=250773&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/REPL.h (original)
+++ lldb/trunk/include/lldb/Expression/REPL.h Mon Oct 19 19:23:46 2015
@@ -37,8 +37,26 @@ public:
virtual ~REPL();
+ //------------------------------------------------------------------
+ /// Get a REPL with an (optional) existing target, and (optional) extra arguments for the compiler.
+ ///
+ /// @param[out] error
+ /// If this language is supported but the REPL couldn't be created, this error is populated with the reason.
+ ///
+ /// @param[in] language
+ /// The language to create a REPL for.
+ ///
+ /// @param[in] target
+ /// If provided, the target to put the REPL inside.
+ ///
+ /// @param[in] repl_options
+ /// If provided, additional options for the compiler when parsing REPL expressions.
+ ///
+ /// @return
+ /// The range of the containing object in the target process.
+ //------------------------------------------------------------------
static lldb::REPLSP
- Create (lldb::LanguageType language, Target *target);
+ Create (Error &Error, lldb::LanguageType language, Target *target, const char *repl_options);
void
SetFormatOptions (const OptionGroupFormat &options)
Modified: lldb/trunk/include/lldb/Target/Target.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Target.h?rev=250773&r1=250772&r2=250773&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Target.h (original)
+++ lldb/trunk/include/lldb/Target/Target.h Mon Oct 19 19:23:46 2015
@@ -1568,7 +1568,7 @@ public:
GetSearchFilterForModuleAndCUList (const FileSpecList *containingModules, const FileSpecList *containingSourceFiles);
lldb::REPLSP
- GetREPL (lldb::LanguageType, bool can_create);
+ GetREPL (Error &err, lldb::LanguageType language, const char *repl_options, bool can_create);
protected:
//------------------------------------------------------------------
Modified: lldb/trunk/include/lldb/lldb-private-interfaces.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-private-interfaces.h?rev=250773&r1=250772&r2=250773&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-private-interfaces.h (original)
+++ lldb/trunk/include/lldb/lldb-private-interfaces.h Mon Oct 19 19:23:46 2015
@@ -49,7 +49,7 @@ namespace lldb_private
typedef lldb::InstrumentationRuntimeType (*InstrumentationRuntimeGetType) ();
typedef lldb::InstrumentationRuntimeSP (*InstrumentationRuntimeCreateInstance) (const lldb::ProcessSP &process_sp);
typedef lldb::TypeSystemSP (*TypeSystemCreateInstance) (lldb::LanguageType language, Module *module, Target *target);
- typedef lldb::REPLSP (*REPLCreateInstance) (lldb::LanguageType language, Target *target);
+ typedef lldb::REPLSP (*REPLCreateInstance) (Error &error, lldb::LanguageType language, Target *target, const char *repl_options);
typedef void (*TypeSystemEnumerateSupportedLanguages) (std::set<lldb::LanguageType> &languages_for_types, std::set<lldb::LanguageType> &languages_for_expressions);
typedef int (*ComparisonFunction)(const void *, const void *);
typedef void (*DebuggerInitializeCallback)(Debugger &debugger);
Modified: lldb/trunk/scripts/interface/SBDebugger.i
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/interface/SBDebugger.i?rev=250773&r1=250772&r2=250773&view=diff
==============================================================================
--- lldb/trunk/scripts/interface/SBDebugger.i (original)
+++ lldb/trunk/scripts/interface/SBDebugger.i Mon Oct 19 19:23:46 2015
@@ -377,6 +377,9 @@ public:
int &num_errors,
bool &quit_requested,
bool &stopped_for_crash);
+
+ lldb::SBError
+ RunREPL (lldb::LanguageType language, const char *repl_options);
}; // class SBDebugger
} // namespace lldb
Modified: lldb/trunk/source/API/SBDebugger.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBDebugger.cpp?rev=250773&r1=250772&r2=250773&view=diff
==============================================================================
--- lldb/trunk/source/API/SBDebugger.cpp (original)
+++ lldb/trunk/source/API/SBDebugger.cpp Mon Oct 19 19:23:46 2015
@@ -1000,6 +1000,17 @@ SBDebugger::RunCommandInterpreter (bool
}
}
+SBError
+SBDebugger::RunREPL (lldb::LanguageType language, const char *repl_options)
+{
+ SBError error;
+ if (m_opaque_sp)
+ error.ref() = m_opaque_sp->RunREPL(language, repl_options);
+ else
+ error.SetErrorString ("invalid debugger");
+ return error;
+}
+
void
SBDebugger::reset (const DebuggerSP &debugger_sp)
{
Modified: lldb/trunk/source/Core/Debugger.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=250773&r1=250772&r2=250773&view=diff
==============================================================================
--- lldb/trunk/source/Core/Debugger.cpp (original)
+++ lldb/trunk/source/Core/Debugger.cpp Mon Oct 19 19:23:46 2015
@@ -31,6 +31,7 @@
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/Expression/REPL.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/Terminal.h"
@@ -44,6 +45,7 @@
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/TargetList.h"
+#include "lldb/Target/Language.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
@@ -1798,3 +1800,35 @@ Debugger::GetSelectedOrDummyTarget(bool
return GetDummyTarget();
}
+Error
+Debugger::RunREPL (LanguageType language, const char *repl_options)
+{
+ Error err;
+ FileSpec repl_executable;
+ if (language == eLanguageTypeUnknown)
+ {
+ err.SetErrorString ("must specify a language for a REPL"); // TODO make it possible to specify a default language
+ return err;
+ }
+
+ Target *const target = nullptr; // passing in an empty target means the REPL must create one
+
+ REPLSP repl_sp(REPL::Create(err, language, target, repl_options));
+
+ if (!err.Success())
+ {
+ return err;
+ }
+
+ if (!repl_sp)
+ {
+ err.SetErrorStringWithFormat("couldn't find a REPL for %s", Language::GetNameForLanguageType(language));
+ return err;
+ }
+
+ repl_sp->SetCompilerOptions(repl_options);
+ repl_sp->RunLoop();
+
+ return err;
+}
+
Modified: lldb/trunk/source/Expression/REPL.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/REPL.cpp?rev=250773&r1=250772&r2=250773&view=diff
==============================================================================
--- lldb/trunk/source/Expression/REPL.cpp (original)
+++ lldb/trunk/source/Expression/REPL.cpp Mon Oct 19 19:23:46 2015
@@ -23,14 +23,14 @@
using namespace lldb_private;
lldb::REPLSP
-REPL::Create(lldb::LanguageType language, Target *target)
+REPL::Create(Error &err, lldb::LanguageType language, Target *target, const char *repl_options)
{
uint32_t idx = 0;
lldb::REPLSP ret;
while (REPLCreateInstance create_instance = PluginManager::GetREPLCreateCallbackAtIndex(idx++))
{
- ret = (*create_instance)(language, target);
+ ret = (*create_instance)(err, language, target, repl_options);
if (ret)
{
break;
Modified: lldb/trunk/source/Target/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=250773&r1=250772&r2=250773&view=diff
==============================================================================
--- lldb/trunk/source/Target/Target.cpp (original)
+++ lldb/trunk/source/Target/Target.cpp Mon Oct 19 19:23:46 2015
@@ -213,7 +213,7 @@ Target::GetProcessSP () const
}
lldb::REPLSP
-Target::GetREPL (lldb::LanguageType language, bool can_create)
+Target::GetREPL (Error &err, lldb::LanguageType language, const char *repl_options, bool can_create)
{
if (language == eLanguageTypeUnknown)
{
@@ -229,10 +229,11 @@ Target::GetREPL (lldb::LanguageType lang
if (!can_create)
{
+ err.SetErrorStringWithFormat("Couldn't find an existing REPL for %s, and can't create a new one", Language::GetNameForLanguageType(language));
return lldb::REPLSP();
}
- lldb::REPLSP ret = REPL::Create(language, this);
+ lldb::REPLSP ret = REPL::Create(err, language, this, repl_options);
if (ret)
{
@@ -240,7 +241,12 @@ Target::GetREPL (lldb::LanguageType lang
return m_repl_map[language];
}
- return nullptr;
+ if (err.Success())
+ {
+ err.SetErrorStringWithFormat("Couldn't create a REPL for %s", Language::GetNameForLanguageType(language));
+ }
+
+ return lldb::REPLSP();
}
void
Modified: lldb/trunk/tools/driver/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/Driver.cpp?rev=250773&r1=250772&r2=250773&view=diff
==============================================================================
--- lldb/trunk/tools/driver/Driver.cpp (original)
+++ lldb/trunk/tools/driver/Driver.cpp Mon Oct 19 19:23:46 2015
@@ -35,6 +35,7 @@
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBHostOS.h"
+#include "lldb/API/SBLanguageRuntime.h"
#include "lldb/API/SBListener.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBTarget.h"
@@ -132,6 +133,10 @@ static OptionDefinition g_options[] =
"extensions have been implemented." },
{ LLDB_3_TO_5, false, "debug" , 'd', no_argument , 0, eArgTypeNone,
"Tells the debugger to print out extra information for debugging itself." },
+ { LLDB_OPT_SET_7, true , "repl" , 'r', optional_argument, 0, eArgTypeNone,
+ "Runs lldb in REPL mode with a stub process." },
+ { LLDB_OPT_SET_7, true , "repl-language" , 'R', required_argument, 0, eArgTypeNone,
+ "Chooses the language for the REPL." },
{ 0, false, NULL , 0 , 0 , 0, eArgTypeNone, NULL }
};
@@ -408,6 +413,9 @@ Driver::OptionData::OptionData () :
m_print_python_path (false),
m_print_help (false),
m_wait_for(false),
+ m_repl (false),
+ m_repl_lang (eLanguageTypeUnknown),
+ m_repl_options (),
m_process_name(),
m_process_pid(LLDB_INVALID_PROCESS_ID),
m_use_external_editor(false),
@@ -769,6 +777,23 @@ Driver::ParseArgs (int argc, const char
optarg);
}
break;
+
+ case 'r':
+ m_option_data.m_repl = true;
+ if (optarg && optarg[0])
+ m_option_data.m_repl_options = optarg;
+ else
+ m_option_data.m_repl_options.clear();
+ break;
+
+ case 'R':
+ m_option_data.m_repl_lang = SBLanguageRuntime::GetLanguageTypeFromString (optarg);
+ if (m_option_data.m_repl_lang == eLanguageTypeUnknown)
+ {
+ error.SetErrorStringWithFormat ("Unrecognized language name: \"%s\"", optarg);
+ }
+ break;
+
case 's':
m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterFile, true, error);
break;
@@ -1056,96 +1081,114 @@ Driver::MainLoop ()
bool handle_events = true;
bool spawn_thread = false;
- // Check if we have any data in the commands stream, and if so, save it to a temp file
- // so we can then run the command interpreter using the file contents.
- const char *commands_data = commands_stream.GetData();
- const size_t commands_size = commands_stream.GetSize();
-
- // The command file might have requested that we quit, this variable will track that.
- bool quit_requested = false;
- bool stopped_for_crash = false;
- if (commands_data && commands_size)
- {
- int initial_commands_fds[2];
- bool success = true;
- FILE *commands_file = PrepareCommandsForSourcing (commands_data, commands_size, initial_commands_fds);
- if (commands_file)
+ if (m_option_data.m_repl)
+ {
+ const char *repl_options = NULL;
+ if (!m_option_data.m_repl_options.empty())
+ repl_options = m_option_data.m_repl_options.c_str();
+ SBError error (m_debugger.RunREPL(m_option_data.m_repl_lang, repl_options));
+ if (error.Fail())
{
- m_debugger.SetInputFileHandle (commands_file, true);
+ const char *error_cstr = error.GetCString();
+ if (error_cstr && error_cstr[0])
+ fprintf (stderr, "error: %s\n", error_cstr);
+ else
+ fprintf (stderr, "error: %u\n", error.GetError());
+ }
+ }
+ else
+ {
+ // Check if we have any data in the commands stream, and if so, save it to a temp file
+ // so we can then run the command interpreter using the file contents.
+ const char *commands_data = commands_stream.GetData();
+ const size_t commands_size = commands_stream.GetSize();
+
+ // The command file might have requested that we quit, this variable will track that.
+ bool quit_requested = false;
+ bool stopped_for_crash = false;
+ if (commands_data && commands_size)
+ {
+ int initial_commands_fds[2];
+ bool success = true;
+ FILE *commands_file = PrepareCommandsForSourcing (commands_data, commands_size, initial_commands_fds);
+ if (commands_file)
+ {
+ m_debugger.SetInputFileHandle (commands_file, true);
- // Set the debugger into Sync mode when running the command file. Otherwise command files
- // that run the target won't run in a sensible way.
- bool old_async = m_debugger.GetAsync();
- m_debugger.SetAsync(false);
- int num_errors;
-
- SBCommandInterpreterRunOptions options;
- options.SetStopOnError (true);
- if (m_option_data.m_batch)
- options.SetStopOnCrash (true);
-
- m_debugger.RunCommandInterpreter(handle_events,
- spawn_thread,
- options,
- num_errors,
- quit_requested,
- stopped_for_crash);
+ // Set the debugger into Sync mode when running the command file. Otherwise command files
+ // that run the target won't run in a sensible way.
+ bool old_async = m_debugger.GetAsync();
+ m_debugger.SetAsync(false);
+ int num_errors;
+
+ SBCommandInterpreterRunOptions options;
+ options.SetStopOnError (true);
+ if (m_option_data.m_batch)
+ options.SetStopOnCrash (true);
+
+ m_debugger.RunCommandInterpreter(handle_events,
+ spawn_thread,
+ options,
+ num_errors,
+ quit_requested,
+ stopped_for_crash);
- if (m_option_data.m_batch && stopped_for_crash && !m_option_data.m_after_crash_commands.empty())
- {
- int crash_command_fds[2];
- SBStream crash_commands_stream;
- WriteCommandsForSourcing (eCommandPlacementAfterCrash, crash_commands_stream);
- const char *crash_commands_data = crash_commands_stream.GetData();
- const size_t crash_commands_size = crash_commands_stream.GetSize();
- commands_file = PrepareCommandsForSourcing (crash_commands_data, crash_commands_size, crash_command_fds);
- if (commands_file)
+ if (m_option_data.m_batch && stopped_for_crash && !m_option_data.m_after_crash_commands.empty())
{
- bool local_quit_requested;
- bool local_stopped_for_crash;
- m_debugger.SetInputFileHandle (commands_file, true);
-
- m_debugger.RunCommandInterpreter(handle_events,
- spawn_thread,
- options,
- num_errors,
- local_quit_requested,
- local_stopped_for_crash);
- if (local_quit_requested)
- quit_requested = true;
+ int crash_command_fds[2];
+ SBStream crash_commands_stream;
+ WriteCommandsForSourcing (eCommandPlacementAfterCrash, crash_commands_stream);
+ const char *crash_commands_data = crash_commands_stream.GetData();
+ const size_t crash_commands_size = crash_commands_stream.GetSize();
+ commands_file = PrepareCommandsForSourcing (crash_commands_data, crash_commands_size, crash_command_fds);
+ if (commands_file)
+ {
+ bool local_quit_requested;
+ bool local_stopped_for_crash;
+ m_debugger.SetInputFileHandle (commands_file, true);
+
+ m_debugger.RunCommandInterpreter(handle_events,
+ spawn_thread,
+ options,
+ num_errors,
+ local_quit_requested,
+ local_stopped_for_crash);
+ if (local_quit_requested)
+ quit_requested = true;
+ }
}
+ m_debugger.SetAsync(old_async);
}
- m_debugger.SetAsync(old_async);
- }
- else
- success = false;
+ else
+ success = false;
- // Close any pipes that we still have ownership of
- CleanupAfterCommandSourcing(initial_commands_fds);
+ // Close any pipes that we still have ownership of
+ CleanupAfterCommandSourcing(initial_commands_fds);
- // Something went wrong with command pipe
- if (!success)
- {
- exit(1);
- }
+ // Something went wrong with command pipe
+ if (!success)
+ {
+ exit(1);
+ }
- }
+ }
- // Now set the input file handle to STDIN and run the command
- // interpreter again in interactive mode and let the debugger
- // take ownership of stdin
-
- bool go_interactive = true;
- if (quit_requested)
- go_interactive = false;
- else if (m_option_data.m_batch && !stopped_for_crash)
- go_interactive = false;
+ // Now set the input file handle to STDIN and run the command
+ // interpreter again in interactive mode and let the debugger
+ // take ownership of stdin
+
+ bool go_interactive = true;
+ if (quit_requested)
+ go_interactive = false;
+ else if (m_option_data.m_batch && !stopped_for_crash)
+ go_interactive = false;
- if (go_interactive)
- {
- m_debugger.SetInputFileHandle (stdin, true);
- m_debugger.RunCommandInterpreter(handle_events, spawn_thread);
+ if (go_interactive)
+ {
+ m_debugger.SetInputFileHandle (stdin, true);
+ m_debugger.RunCommandInterpreter(handle_events, spawn_thread);
+ }
}
reset_stdin_termios();
Modified: lldb/trunk/tools/driver/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/Driver.h?rev=250773&r1=250772&r2=250773&view=diff
==============================================================================
--- lldb/trunk/tools/driver/Driver.h (original)
+++ lldb/trunk/tools/driver/Driver.h Mon Oct 19 19:23:46 2015
@@ -105,6 +105,9 @@ public:
bool m_print_python_path;
bool m_print_help;
bool m_wait_for;
+ bool m_repl;
+ lldb::LanguageType m_repl_lang;
+ std::string m_repl_options;
std::string m_process_name;
lldb::pid_t m_process_pid;
bool m_use_external_editor; // FIXME: When we have set/show variables we can remove this from here.
More information about the lldb-commits
mailing list