Update patch:

- Fix test_lldbmi_setargs test and enable it.
- Set arguments directly to target (don't save it in SessionInfo)


http://reviews.llvm.org/D6965

Files:
  include/lldb/API/SBArgs.h
  include/lldb/API/SBDefines.h
  include/lldb/API/SBTarget.h
  source/API/CMakeLists.txt
  source/API/SBArgs.cpp
  source/API/SBTarget.cpp
  test/tools/lldb-mi/TestMiProgramArgs.py
  tools/lldb-mi/MICmdArgValListOfN.h
  tools/lldb-mi/MICmdCmdExec.cpp
  tools/lldb-mi/MICmdCmdExec.h
  tools/lldb-mi/MICmdCommands.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/lldb/API/SBArgs.h
===================================================================
--- include/lldb/API/SBArgs.h
+++ include/lldb/API/SBArgs.h
@@ -0,0 +1,83 @@
+//===-- SBArgs.h ------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SBArgs_h_
+#define LLDB_SBArgs_h_
+
+#include "lldb/API/SBDefines.h"
+
+namespace lldb {
+
+class SBArgs
+{
+public:
+    SBArgs ();
+
+    SBArgs (bool force_create);
+
+    SBArgs (const SBArgs &rhs);
+
+    ~SBArgs ();
+
+    const lldb::SBArgs &
+    operator = (const lldb::SBArgs &rhs);
+
+    bool
+    IsValid () const;
+
+    size_t
+    GetArgumentCount () const;
+
+    const char *
+    GetArgumentAtIndex (size_t idx) const;
+
+    char **
+    GetArgumentVector ();
+
+    const char **
+    GetConstArgumentVector () const;
+
+    const char *
+    AppendArgument (const char *arg_cstr);
+
+    void
+    Clear ();
+
+protected:
+
+    friend class SBTarget;
+
+    lldb_private::Args *
+    get ();
+
+    const lldb_private::Args *
+    get () const;
+
+    lldb_private::Args *
+    operator -> ();
+
+    const lldb_private::Args &
+    operator * () const;
+
+    lldb_private::Args &
+    ref ();
+
+    void
+    SetArgs (const lldb_private::Args &lldb_args);
+
+private:
+    std::unique_ptr<lldb_private::Args> m_opaque_ap;
+
+    void
+    CreateIfNeeded ();
+};
+
+} // namespace lldb
+
+#endif // LLDB_SBArgs_h_
Index: include/lldb/API/SBDefines.h
===================================================================
--- include/lldb/API/SBDefines.h
+++ include/lldb/API/SBDefines.h
@@ -29,6 +29,7 @@
 namespace lldb {
 
 class LLDB_API SBAddress;
+class LLDB_API SBArgs;
 class LLDB_API SBBlock;
 class LLDB_API SBBreakpoint;
 class LLDB_API SBBreakpointLocation;
Index: include/lldb/API/SBTarget.h
===================================================================
--- include/lldb/API/SBTarget.h
+++ include/lldb/API/SBTarget.h
@@ -1047,7 +1047,13 @@
 
     lldb::addr_t
     GetStackRedZoneSize();
-    
+
+    lldb::SBArgs
+    GetRunArguments () const;
+
+    bool
+    SetRunArguments (const lldb::SBArgs &args);
+
 protected:
     friend class SBAddress;
     friend class SBBlock;
Index: source/API/CMakeLists.txt
===================================================================
--- source/API/CMakeLists.txt
+++ source/API/CMakeLists.txt
@@ -5,6 +5,7 @@
 # well (where appropriate).
 add_lldb_library(lldbAPI
   SBAddress.cpp
+  SBArgs.cpp
   SBBlock.cpp
   SBBreakpoint.cpp
   SBBreakpointLocation.cpp
Index: source/API/SBArgs.cpp
===================================================================
--- source/API/SBArgs.cpp
+++ source/API/SBArgs.cpp
@@ -0,0 +1,153 @@
+//===-- SBArgs.cpp -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBArgs.h"
+#include "lldb/Interpreter/Args.h"
+
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+SBArgs::SBArgs () :
+    m_opaque_ap ()
+{
+}
+
+SBArgs::SBArgs (bool force_create) :
+    m_opaque_ap ()
+{
+    if (force_create)
+        m_opaque_ap.reset (new Args());
+}
+
+SBArgs::SBArgs (const SBArgs &rhs) :
+    m_opaque_ap ()
+{
+    if (rhs.IsValid())
+        m_opaque_ap.reset (new Args(*rhs));
+}
+
+SBArgs::~SBArgs ()
+{
+}
+
+const SBArgs &
+SBArgs::operator = (const SBArgs &rhs)
+{
+    if (rhs.IsValid())
+    {
+        if (m_opaque_ap.get())
+            *m_opaque_ap = *rhs;
+        else
+            m_opaque_ap.reset (new Args(*rhs));
+    }
+    else
+        m_opaque_ap.reset();
+
+    return *this;
+}
+
+bool
+SBArgs::IsValid () const
+{
+    return m_opaque_ap.get() != NULL;
+}
+
+void
+SBArgs::SetArgs (const Args &lldb_args)
+{
+    CreateIfNeeded ();
+    *m_opaque_ap = lldb_args;
+}
+
+size_t
+SBArgs::GetArgumentCount () const
+{
+    if (m_opaque_ap.get())
+        return m_opaque_ap->GetArgumentCount();
+    return 0;
+}
+
+const char *
+SBArgs::GetArgumentAtIndex (size_t idx) const
+{
+    if (m_opaque_ap)
+        return m_opaque_ap->GetArgumentAtIndex(idx);
+    return NULL;
+}
+
+char **
+SBArgs::GetArgumentVector ()
+{
+    if (m_opaque_ap)
+        return m_opaque_ap->GetArgumentVector();
+    return NULL;
+}
+
+const char **
+SBArgs::GetConstArgumentVector () const
+{
+    if (m_opaque_ap)
+        return m_opaque_ap->GetConstArgumentVector();
+    return NULL;
+}
+
+const char *
+SBArgs::AppendArgument (const char *arg_cstr)
+{
+    CreateIfNeeded ();
+    return m_opaque_ap->AppendArgument(arg_cstr);
+}
+
+void
+SBArgs::Clear ()
+{
+    if (m_opaque_ap)
+        m_opaque_ap->Clear();
+}
+
+Args *
+SBArgs::get ()
+{
+    return m_opaque_ap.get();
+}
+
+const Args *
+SBArgs::get () const
+{
+    return m_opaque_ap.get();
+}
+
+Args *
+SBArgs::operator -> ()
+{
+    return m_opaque_ap.get();
+}
+
+const Args &
+SBArgs::operator * () const
+{
+    // Be sure to call "IsValid()" before calling this function or it will crash
+    return *m_opaque_ap;
+}
+
+Args &
+SBArgs::ref ()
+{
+    CreateIfNeeded();
+    return *m_opaque_ap;
+}
+
+void
+SBArgs::CreateIfNeeded ()
+{
+    if (m_opaque_ap.get() == NULL)
+        m_opaque_ap.reset(new Args());
+}
Index: source/API/SBTarget.cpp
===================================================================
--- source/API/SBTarget.cpp
+++ source/API/SBTarget.cpp
@@ -13,6 +13,7 @@
 
 #include "lldb/lldb-public.h"
 
+#include "lldb/API/SBArgs.h"
 #include "lldb/API/SBDebugger.h"
 #include "lldb/API/SBBreakpoint.h"
 #include "lldb/API/SBExpressionOptions.h"
@@ -2929,3 +2930,29 @@
     return 0;
 }
 
+SBArgs
+SBTarget::GetRunArguments () const
+{
+    SBArgs sb_args;
+    TargetSP target_sp(GetSP());
+    if (target_sp)
+    {
+        Args args;
+        if (m_opaque_sp->GetRunArguments(args))
+            sb_args.SetArgs(args);
+    }
+    return sb_args;
+}
+
+bool
+SBTarget::SetRunArguments (const SBArgs &args)
+{
+    bool result = false;
+    TargetSP target_sp(GetSP());
+    if (target_sp && args.IsValid())
+    {
+        m_opaque_sp->SetRunArguments(*args.get());
+        result = true;
+    }
+    return result;
+}
Index: test/tools/lldb-mi/TestMiProgramArgs.py
===================================================================
--- test/tools/lldb-mi/TestMiProgramArgs.py
+++ test/tools/lldb-mi/TestMiProgramArgs.py
@@ -22,10 +22,9 @@
         except:
             pass
 
-    @unittest2.skip("lldb-mi can't pass params to app.")
     @lldbmi_test
-    def test_lldbmi_paramargs(self):
-        """Test that 'lldb-mi --interpreter' can pass arguments to the app."""
+    def test_lldbmi_clearargs(self):
+        """Test that 'lldb-mi --interpreter' can reset previously set args using -exec-arguments."""
         import pexpect
         self.buildDefault()
 
@@ -39,36 +38,98 @@
                 child.logfile_send = f_send
                 child.logfile_read = f_read
 
-                child.sendline("-file-exec-and-symbols " + self.myexe)
+                # Load executable
+                child.sendline("-file-exec-and-symbols %s" % (self.myexe))
                 child.expect("\^done")
 
-                child.sendline("settings set target.run-args l") #FIXME: args not passed
-                #child.sendline("-exec-arguments l") #FIXME: not recognized and hung lldb-mi
+                # Set arguments
+                child.sendline("-exec-arguments foo bar baz")
+                child.expect("\^done")
+                child.sendline("-exec-arguments")
+                child.expect("\^done")
 
-                #run to main
+                # Run to main
                 child.sendline("-break-insert -f main")
                 child.expect("\^done,bkpt={number=\"1\"")
                 child.sendline("-exec-run")
                 child.expect("\^running")
                 child.expect("\*stopped,reason=\"breakpoint-hit\"")
 
-                #check argc to see if arg passed
+                # Check argc to see if arg passed
                 child.sendline("-data-evaluate-expression argc")
-                child.expect("value=\"2\"")
+                child.expect("\^done,value=\"1\"")
 
-                #set BP on code which is only executed if "l" was passed correctly (marked BP_argtest)
-                self.line = line_number('main.c', '//BP_argtest')
-                child.sendline("-break-insert main.c:%d" % self.line)
-                child.expect("\^done,bkpt={number=\"2\"")
-                child.sendline("-exec-continue")
+        # Now that the necessary logging is done, restore logfile to None to
+        # stop further logging.
+        child.logfile_send = None
+        child.logfile_read = None
+
+        with open('child_send.txt', 'r') as fs:
+            if self.TraceOn():
+                print "\n\nContents of child_send.txt:"
+                print fs.read()
+        with open('child_read.txt', 'r') as fr:
+            from_child = fr.read()
+            if self.TraceOn():
+                print "\n\nContents of child_read.txt:"
+                print from_child
+
+    @lldbmi_test
+    def test_lldbmi_setargs(self):
+        """Test that 'lldb-mi --interpreter' can pass args using -exec-arguments."""
+        import pexpect
+        self.buildDefault()
+
+        # So that the child gets torn down after the test.
+        self.child = pexpect.spawn('%s --interpreter' % (self.lldbMiExec))
+        child = self.child
+        child.setecho(True)
+        # Turn on logging for input/output to/from the child.
+        with open('child_send.txt', 'w') as f_send:
+            with open('child_read.txt', 'w') as f_read:
+                child.logfile_send = f_send
+                child.logfile_read = f_read
+
+                # Load executable
+                child.sendline("-file-exec-and-symbols %s" % (self.myexe))
+                child.expect("\^done")
+
+                # Set arguments
+                child.sendline("-exec-arguments --arg1 \"2nd arg\" third_arg fourth=\"4th arg\"")
+                child.expect("\^done")
+
+                # Run to main
+                child.sendline("-break-insert -f main")
+                child.expect("\^done,bkpt={number=\"1\"")
+                child.sendline("-exec-run")
                 child.expect("\^running")
                 child.expect("\*stopped,reason=\"breakpoint-hit\"")
 
+                # Check argc and argv to see if arg passed
+                child.sendline("-data-evaluate-expression argc")
+                child.expect("\^done,value=\"5\"")
+                #child.sendline("-data-evaluate-expression argv[1]")
+                #child.expect("\^done,value=\"--arg1\"")
+                child.sendline("-interpreter-exec command \"print argv[1]\"")
+                child.expect("\"--arg1\"")
+                #child.sendline("-data-evaluate-expression argv[2]")
+                #child.expect("\^done,value=\"2nd arg\"")
+                child.sendline("-interpreter-exec command \"print argv[2]\"")
+                child.expect("\"2nd arg\"")
+                #child.sendline("-data-evaluate-expression argv[3]")
+                #child.expect("\^done,value=\"third_arg\"")
+                child.sendline("-interpreter-exec command \"print argv[3]\"")
+                child.expect("\"third_arg\"")
+                #child.sendline("-data-evaluate-expression argv[4]")
+                #child.expect("\^done,value=\"fourth=\\\\\\\"4th arg\\\\\\\"\"")
+                child.sendline("-interpreter-exec command \"print argv[4]\"")
+                child.expect_exact("\"fourth=\\\"4th arg\\\"\"")
+
         # Now that the necessary logging is done, restore logfile to None to
         # stop further logging.
         child.logfile_send = None
         child.logfile_read = None
-        
+
         with open('child_send.txt', 'r') as fs:
             if self.TraceOn():
                 print "\n\nContents of child_send.txt:"
Index: tools/lldb-mi/MICmdArgValListOfN.h
===================================================================
--- tools/lldb-mi/MICmdArgValListOfN.h
+++ tools/lldb-mi/MICmdArgValListOfN.h
@@ -56,7 +56,7 @@
                                    const ArgValType_e veType);
     //
     const VecArgObjPtr_t &GetExpectedOptions(void) const;
-    template <class T1, typename T2> bool GetExpectedOption(T2 &vrwValue) const;
+    template <class T1, typename T2> bool GetExpectedOption(T2 &vrwValue, const VecArgObjPtr_t::size_type vnAt = 0) const;
 
     // Overridden:
   public:
@@ -76,6 +76,7 @@
 //          parsed from the command's options string.
 // Type:    Template method.
 // Args:    vrwValue    - (W) Templated type return value.
+//          vnAt        - (R) Value at the specific position.
 //          T1          - The argument value's class type of the data hold in the list of options.
 //          T2          - The type pf the variable which holds the value wanted.
 // Return:  MIstatus::success - Functional succeeded.
@@ -84,10 +85,13 @@
 //--
 template <class T1, typename T2>
 bool
-CMICmdArgValListOfN::GetExpectedOption(T2 &vrwValue) const
+CMICmdArgValListOfN::GetExpectedOption(T2 &vrwValue, const VecArgObjPtr_t::size_type vnAt) const
 {
     const VecArgObjPtr_t &rVecOptions(GetExpectedOptions());
-    VecArgObjPtr_t::const_iterator it2 = rVecOptions.begin();
+    if (rVecOptions.size() <= vnAt)
+        return MIstatus::failure;
+
+    VecArgObjPtr_t::const_iterator it2 = rVecOptions.begin() + vnAt;
     if (it2 != rVecOptions.end())
     {
         const T1 *pOption = static_cast<T1 *>(*it2);
Index: tools/lldb-mi/MICmdCmdExec.cpp
===================================================================
--- tools/lldb-mi/MICmdCmdExec.cpp
+++ tools/lldb-mi/MICmdCmdExec.cpp
@@ -18,6 +18,7 @@
 //              CMICmdCmdExecStepInstruction    implementation.
 //              CMICmdCmdExecFinish             implementation.
 //              CMICmdCmdExecInterrupt          implementation.
+//              CMICmdCmdExecArguments          implementation.
 //
 // Environment: Compilers:  Visual C++ 12.
 //                          gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
@@ -27,6 +28,7 @@
 //--
 
 // Third Party Headers:
+#include <lldb/API/SBArgs.h>
 #include <lldb/API/SBCommandInterpreter.h>
 #include <lldb/API/SBProcess.h>
 #include <lldb/API/SBStream.h>
@@ -90,8 +92,10 @@
     CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
     lldb::SBError error;
     lldb::SBStream errMsg;
-    uint32_t launch_flags = lldb::LaunchFlags::eLaunchFlagDebug;
-    lldb::SBProcess process = rSessionInfo.m_lldbTarget.Launch(rSessionInfo.m_rLlldbListener, nullptr, nullptr, nullptr, nullptr, nullptr,
+    const uint32_t launch_flags = lldb::LaunchFlags::eLaunchFlagDebug;
+    lldb::SBProcess process = rSessionInfo.m_lldbTarget.Launch(rSessionInfo.m_rLlldbListener,
+                                                               rSessionInfo.m_lldbTarget.GetRunArguments().GetConstArgumentVector(),
+                                                               nullptr, nullptr, nullptr, nullptr,
                                                                nullptr, launch_flags, false, error);
 
     if ((!process.IsValid()) || (error.Fail()))
@@ -1019,3 +1023,120 @@
 {
     return new CMICmdCmdExecInterrupt();
 }
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdExecArguments constructor.
+// Type:    Method.
+// Args:    None.
+// Return:  None.
+// Throws:  None.
+//--
+CMICmdCmdExecArguments::CMICmdCmdExecArguments(void)
+    : m_constStrArgArguments("arguments")
+{
+    // Command factory matches this name with that received from the stdin stream
+    m_strMiCmd = "exec-arguments";
+
+    // Required by the CMICmdFactory when registering *this command
+    m_pSelfCreatorFn = &CMICmdCmdExecArguments::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdExecArguments destructor.
+// Type:    Overrideable.
+// Args:    None.
+// Return:  None.
+// Throws:  None.
+//--
+CMICmdCmdExecArguments::~CMICmdCmdExecArguments(void)
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+//          arguments to extract values for each of those arguments.
+// Type:    Overridden.
+// Args:    None.
+// Return:  MIstatus::success - Function succeeded.
+//          MIstatus::failure - Function failed.
+// Throws:  None.
+//--
+bool
+CMICmdCmdExecArguments::ParseArgs(void)
+{
+    bool bOk = m_setCmdArgs.Add(
+        *(new CMICmdArgValListOfN(m_constStrArgArguments, false, true, CMICmdArgValListBase::eArgValType_StringAnything)));
+    return (bOk && ParseValidateCmdOptions());
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+//          The command is likely to communicate with the LLDB SBDebugger in here.
+// Type:    Overridden.
+// Args:    None.
+// Return:  MIstatus::success - Function succeeded.
+//          MIstatus::failure - Function failed.
+// Throws:  None.
+//--
+bool
+CMICmdCmdExecArguments::Execute(void)
+{
+    CMICMDBASE_GETOPTION(pArgArguments, ListOfN, m_constStrArgArguments);
+
+    lldb::SBArgs sbArgs(true);
+    CMIUtilString strArg;
+    size_t nArgIndex = 0;
+    while (pArgArguments->GetExpectedOption<CMICmdArgValString, CMIUtilString>(strArg, nArgIndex))
+    {
+        sbArgs.AppendArgument(strArg.c_str());
+        ++nArgIndex;
+    }
+
+    CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
+    lldb::SBTarget sbTarget = rSessionInfo.m_lldbTarget;
+    if (!sbTarget.IsValid())
+    {
+        SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_CURRENT), m_cmdData.strMiCmd.c_str()));
+        return MIstatus::failure;
+    }
+
+    sbTarget.SetRunArguments(sbArgs);
+
+    return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+//          for the work carried out in the Execute().
+// Type:    Overridden.
+// Args:    None.
+// Return:  MIstatus::success - Function succeeded.
+//          MIstatus::failure - Function failed.
+// Throws:  None.
+//--
+bool
+CMICmdCmdExecArguments::Acknowledge(void)
+{
+    const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
+    m_miResultRecord = miRecordResult;
+
+    return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+//          calls this function to create an instance of *this command.
+// Type:    Static method.
+// Args:    None.
+// Return:  CMICmdBase * - Pointer to a new command.
+// Throws:  None.
+//--
+CMICmdBase *
+CMICmdCmdExecArguments::CreateSelf(void)
+{
+    return new CMICmdCmdExecArguments();
+}
Index: tools/lldb-mi/MICmdCmdExec.h
===================================================================
--- tools/lldb-mi/MICmdCmdExec.h
+++ tools/lldb-mi/MICmdCmdExec.h
@@ -18,6 +18,7 @@
 //              CMICmdCmdExecStepInstruction    interface.
 //              CMICmdCmdExecFinish             interface.
 //              CMICmdCmdExecInterrupt          interface.
+//              CMICmdCmdExecArguments          interface.
 //
 //              To implement new MI commands derive a new command class from the command base
 //              class. To enable the new command for interpretation add the new command class
@@ -307,3 +308,35 @@
   private:
     lldb::SBCommandReturnObject m_lldbResult;
 };
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+//          *this class implements MI command "exec-arguments".
+// Gotchas: None.
+// Authors: Ilia Kirianovskii 25/11/2014.
+// Changes: None.
+//--
+class CMICmdCmdExecArguments : public CMICmdBase
+{
+    // Statics:
+  public:
+    // Required by the CMICmdFactory when registering *this command
+    static CMICmdBase *CreateSelf(void);
+
+    // Methods:
+  public:
+    /* ctor */ CMICmdCmdExecArguments(void);
+
+    // Overridden:
+  public:
+    // From CMICmdInvoker::ICmd
+    virtual bool Execute(void);
+    virtual bool Acknowledge(void);
+    virtual bool ParseArgs(void);
+    // From CMICmnBase
+    /* dtor */ virtual ~CMICmdCmdExecArguments(void);
+
+    // Attributes:
+  private:
+    const CMIUtilString m_constStrArgArguments;
+};
Index: tools/lldb-mi/MICmdCommands.cpp
===================================================================
--- tools/lldb-mi/MICmdCommands.cpp
+++ tools/lldb-mi/MICmdCommands.cpp
@@ -98,6 +98,7 @@
     bOk &= Register<CMICmdCmdDataWriteMemory>();
     bOk &= Register<CMICmdCmdEnablePrettyPrinting>();
     bOk &= Register<CMICmdCmdEnvironmentCd>();
+    bOk &= Register<CMICmdCmdExecArguments>();
     bOk &= Register<CMICmdCmdExecContinue>();
     bOk &= Register<CMICmdCmdExecInterrupt>();
     bOk &= Register<CMICmdCmdExecFinish>();
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits

Reply via email to