[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