[Lldb-commits] [lldb] r212500 - Invalidate process UID/GID-related command options on Windows.

Zachary Turner zturner at google.com
Mon Jul 7 16:54:51 PDT 2014


Author: zturner
Date: Mon Jul  7 18:54:51 2014
New Revision: 212500

URL: http://llvm.org/viewvc/llvm-project?rev=212500&view=rev
Log:
Invalidate process UID/GID-related command options on Windows.

Windows uses a different process security model and does not have
a concept of process UID or GID.  This patch makes these options
invalid on Windows.  Attempting to specify these options when the
current platform is Windows will generate an error.

Reviewed by: Jim Ingham
Differential Revision: http://reviews.llvm.org/D4373

Added:
    lldb/trunk/include/lldb/Interpreter/CommandOptionValidators.h
    lldb/trunk/source/Interpreter/CommandOptionValidators.cpp
Modified:
    lldb/trunk/include/lldb/Host/OptionParser.h
    lldb/trunk/include/lldb/Interpreter/Options.h
    lldb/trunk/include/lldb/lldb-private-types.h
    lldb/trunk/source/Commands/CommandObjectPlatform.cpp
    lldb/trunk/source/Interpreter/Args.cpp
    lldb/trunk/source/Interpreter/CMakeLists.txt
    lldb/trunk/source/Interpreter/Options.cpp

Modified: lldb/trunk/include/lldb/Host/OptionParser.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/OptionParser.h?rev=212500&r1=212499&r2=212500&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/OptionParser.h (original)
+++ lldb/trunk/include/lldb/Host/OptionParser.h Mon Jul  7 18:54:51 2014
@@ -16,18 +16,17 @@ struct option;
 
 namespace lldb_private {
 
-typedef struct Option
+struct OptionDefinition;
+
+struct Option
 {
-    // name of long option
-    const char *name;
-    // one of no_argument, required_argument, and optional_argument:
-    // whether option takes an argument
-    int has_arg;
+    // The definition of the option that this refers to.
+    const OptionDefinition *definition;
     // if not NULL, set *flag to val when option found
     int *flag;
     // if flag not NULL, value to set *flag to; else return value
     int val;
-} Option;
+};
 
 class OptionParser
 {

Added: lldb/trunk/include/lldb/Interpreter/CommandOptionValidators.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/CommandOptionValidators.h?rev=212500&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/CommandOptionValidators.h (added)
+++ lldb/trunk/include/lldb/Interpreter/CommandOptionValidators.h Mon Jul  7 18:54:51 2014
@@ -0,0 +1,30 @@
+//===-- CommandOptionValidators.h -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandOptionValidators_h_
+#define liblldb_CommandOptionValidators_h_
+
+#include "lldb/lldb-private-types.h"
+
+namespace lldb_private {
+
+class Platform;
+class ExecutionContext;
+
+class PosixPlatformCommandOptionValidator : public OptionValidator
+{
+    virtual bool IsValid(Platform &platform, ExecutionContext &target) const;
+    virtual const char* ShortConditionString() const;
+    virtual const char* LongConditionString() const;
+};
+
+} // namespace lldb_private
+
+
+#endif  // liblldb_CommandOptionValidators_h_

Modified: lldb/trunk/include/lldb/Interpreter/Options.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/Options.h?rev=212500&r1=212499&r2=212500&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/Options.h (original)
+++ lldb/trunk/include/lldb/Interpreter/Options.h Mon Jul  7 18:54:51 2014
@@ -159,7 +159,7 @@ public:
 
     void
     OutputFormattedUsageText (Stream &strm,
-                              const char *text,
+                              const OptionDefinition &option_def,
                               uint32_t output_max_columns);
 
     void
@@ -301,6 +301,12 @@ public:
                                     int max_return_elements,
                                     bool &word_complete,
                                     StringList &matches);
+
+    CommandInterpreter&
+    GetInterpreter()
+    {
+        return m_interpreter;
+    }
     
 protected:
     // This is a set of options expressed as indexes into the options table for this Option.

Modified: lldb/trunk/include/lldb/lldb-private-types.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-private-types.h?rev=212500&r1=212499&r2=212500&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-private-types.h (original)
+++ lldb/trunk/include/lldb/lldb-private-types.h Mon Jul  7 18:54:51 2014
@@ -16,6 +16,9 @@
 
 namespace lldb_private
 {
+    class Platform;
+    class ExecutionContext;
+
     //----------------------------------------------------------------------
     // Every register is described in detail including its name, alternate
     // name (optional), encoding, size in bytes and the default display
@@ -55,11 +58,12 @@ namespace lldb_private
     struct OptionValidator
     {
         virtual ~OptionValidator() { }
-        virtual bool IsValid() const = 0;
-        virtual const char * ValidConditionString() const = 0;
+        virtual bool IsValid(Platform &platform, ExecutionContext &target) const = 0;
+        virtual const char * ShortConditionString() const = 0;
+        virtual const char * LongConditionString() const = 0;
     };
     
-    typedef struct
+    struct OptionDefinition
     {
         uint32_t usage_mask;                     // Used to mark options that can be used together.  If (1 << n & usage_mask) != 0
                                                  // then this option belongs to option set n.
@@ -73,7 +77,7 @@ namespace lldb_private
         lldb::CommandArgumentType argument_type; // Type of argument this option takes
         const char *usage_text;                  // Full text explaining what this options does and what (if any) argument to
                                                  // pass it.
-    } OptionDefinition;
+    };
 
 } // namespace lldb_private
 

Modified: lldb/trunk/source/Commands/CommandObjectPlatform.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectPlatform.cpp?rev=212500&r1=212499&r2=212500&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectPlatform.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectPlatform.cpp Mon Jul  7 18:54:51 2014
@@ -21,6 +21,7 @@
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Interpreter/Args.h"
 #include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandOptionValidators.h"
 #include "lldb/Interpreter/CommandReturnObject.h"
 #include "lldb/Interpreter/OptionGroupFile.h"
 #include "lldb/Interpreter/OptionGroupPlatform.h"
@@ -1644,6 +1645,11 @@ protected:
     CommandOptions m_options;
 };
 
+namespace
+{
+    PosixPlatformCommandOptionValidator g_posix_validator;
+}
+
 OptionDefinition
 CommandObjectPlatformProcessList::CommandOptions::g_option_table[] =
 {
@@ -1654,10 +1660,10 @@ CommandObjectPlatformProcessList::Comman
 { LLDB_OPT_SET_5            , true , "contains"   , 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName      , "Find processes with executable basenames that contain a string." },
 { LLDB_OPT_SET_6            , true , "regex"      , 'r', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeRegularExpression, "Find processes with executable basenames that match a regular expression." },
 { LLDB_OPT_SET_FROM_TO(2, 6), false, "parent"     , 'P', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePid              , "Find processes that have a matching parent process ID." },
-{ LLDB_OPT_SET_FROM_TO(2, 6), false, "uid"        , 'u', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching user ID." },
-{ LLDB_OPT_SET_FROM_TO(2, 6), false, "euid"       , 'U', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching effective user ID." },
-{ LLDB_OPT_SET_FROM_TO(2, 6), false, "gid"        , 'g', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching group ID." },
-{ LLDB_OPT_SET_FROM_TO(2, 6), false, "egid"       , 'G', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching effective group ID." },
+{ LLDB_OPT_SET_FROM_TO(2, 6), false, "uid"        , 'u', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching user ID." },
+{ LLDB_OPT_SET_FROM_TO(2, 6), false, "euid"       , 'U', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching effective user ID." },
+{ LLDB_OPT_SET_FROM_TO(2, 6), false, "gid"        , 'g', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching group ID." },
+{ LLDB_OPT_SET_FROM_TO(2, 6), false, "egid"       , 'G', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching effective group ID." },
 { LLDB_OPT_SET_FROM_TO(2, 6), false, "arch"       , 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeArchitecture     , "Find processes that have a matching architecture." },
 { LLDB_OPT_SET_FROM_TO(1, 6), false, "show-args"  , 'A', OptionParser::eNoArgument      , NULL, NULL, 0, eArgTypeNone             , "Show process arguments instead of the process executable basename." },
 { LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose"    , 'v', OptionParser::eNoArgument      , NULL, NULL, 0, eArgTypeNone             , "Enable verbose output." },

Modified: lldb/trunk/source/Interpreter/Args.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/Args.cpp?rev=212500&r1=212499&r2=212500&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/Args.cpp (original)
+++ lldb/trunk/source/Interpreter/Args.cpp Mon Jul  7 18:54:51 2014
@@ -20,6 +20,7 @@
 #include "lldb/Core/StreamString.h"
 #include "lldb/DataFormatters/FormatManager.h"
 #include "lldb/Interpreter/Options.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Interpreter/CommandReturnObject.h"
 #include "lldb/Target/Process.h"
 //#include "lldb/Target/RegisterContext.h"
@@ -627,14 +628,14 @@ Args::ParseOptions (Options &options)
         return error;
     }
 
-    for (int i=0; long_options[i].name != nullptr; ++i)
+    for (int i=0; long_options[i].definition != nullptr; ++i)
     {
         if (long_options[i].flag == nullptr)
         {
             if (isprint8(long_options[i].val))
             {
                 sstr << (char)long_options[i].val;
-                switch (long_options[i].has_arg)
+                switch (long_options[i].definition->option_has_arg)
                 {
                 default:
                 case OptionParser::eNoArgument:                       break;
@@ -673,7 +674,7 @@ Args::ParseOptions (Options &options)
         if (long_options_index == -1)
         {
             for (int i=0;
-                 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
+                 long_options[i].definition || long_options[i].flag || long_options[i].val;
                  ++i)
             {
                 if (long_options[i].val == val)
@@ -686,8 +687,18 @@ Args::ParseOptions (Options &options)
         // Call the callback with the option
         if (long_options_index >= 0)
         {
-            error = options.SetOptionValue(long_options_index,
-                                           long_options[long_options_index].has_arg == OptionParser::eNoArgument ? nullptr : OptionParser::GetOptionArgument());
+            const OptionDefinition *def = long_options[long_options_index].definition;
+            CommandInterpreter &interpreter = options.GetInterpreter();
+            OptionValidator *validator = def->validator;
+            if (validator && !validator->IsValid(*interpreter.GetPlatform(true), interpreter.GetExecutionContext()))
+            {
+                error.SetErrorStringWithFormat("Option \"%s\" invalid.  %s", def->long_option, def->validator->LongConditionString());
+            }
+            else
+            {
+                error = options.SetOptionValue(long_options_index,
+                                               (def->option_has_arg == OptionParser::eNoArgument) ? nullptr : OptionParser::GetOptionArgument());
+            }
         }
         else
         {
@@ -1222,7 +1233,7 @@ Args::FindArgumentIndexForOption (Option
     char short_buffer[3];
     char long_buffer[255];
     ::snprintf (short_buffer, sizeof (short_buffer), "-%c", long_options[long_options_index].val);
-    ::snprintf (long_buffer, sizeof (long_buffer),  "--%s", long_options[long_options_index].name);
+    ::snprintf (long_buffer, sizeof (long_buffer),  "--%s", long_options[long_options_index].definition->long_option);
     size_t end = GetArgumentCount ();
     size_t idx = 0;
     while (idx < end)
@@ -1278,12 +1289,12 @@ Args::ParseAliasOptions (Options &option
         return;
     }
 
-    for (i = 0; long_options[i].name != nullptr; ++i)
+    for (i = 0; long_options[i].definition != nullptr; ++i)
     {
         if (long_options[i].flag == nullptr)
         {
             sstr << (char) long_options[i].val;
-            switch (long_options[i].has_arg)
+            switch (long_options[i].definition->option_has_arg)
             {
                 default:
                 case OptionParser::eNoArgument:
@@ -1328,7 +1339,7 @@ Args::ParseAliasOptions (Options &option
         if (long_options_index == -1)
         {
             for (int j = 0;
-                 long_options[j].name || long_options[j].has_arg || long_options[j].flag || long_options[j].val;
+                 long_options[j].definition || long_options[j].flag || long_options[j].val;
                  ++j)
             {
                 if (long_options[j].val == val)
@@ -1344,8 +1355,10 @@ Args::ParseAliasOptions (Options &option
         {
             StreamString option_str;
             option_str.Printf ("-%c", val);
+            const OptionDefinition *def = long_options[long_options_index].definition;
+            int has_arg = (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
 
-            switch (long_options[long_options_index].has_arg)
+            switch (has_arg)
             {
             case OptionParser::eNoArgument:
                 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()), 
@@ -1410,7 +1423,7 @@ Args::ParseAliasOptions (Options &option
                         raw_input_string.erase (pos, strlen (tmp_arg));
                 }
                 ReplaceArgumentAtIndex (idx, "");
-                if ((long_options[long_options_index].has_arg != OptionParser::eNoArgument)
+                if ((long_options[long_options_index].definition->option_has_arg != OptionParser::eNoArgument)
                     && (OptionParser::GetOptionArgument() != nullptr)
                     && (idx+1 < GetArgumentCount())
                     && (strcmp (OptionParser::GetOptionArgument(), GetArgumentAtIndex(idx+1)) == 0))
@@ -1453,12 +1466,12 @@ Args::ParseArgsForCompletion
     // to suppress error messages.
 
     sstr << ":";
-    for (int i = 0; long_options[i].name != nullptr; ++i)
+    for (int i = 0; long_options[i].definition != nullptr; ++i)
     {
         if (long_options[i].flag == nullptr)
         {
             sstr << (char) long_options[i].val;
-            switch (long_options[i].has_arg)
+            switch (long_options[i].definition->option_has_arg)
             {
                 default:
                 case OptionParser::eNoArgument:
@@ -1555,7 +1568,7 @@ Args::ParseArgsForCompletion
         if (long_options_index == -1)
         {
             for (int j = 0;
-                 long_options[j].name || long_options[j].has_arg || long_options[j].flag || long_options[j].val;
+                 long_options[j].definition || long_options[j].flag || long_options[j].val;
                  ++j)
             {
                 if (long_options[j].val == val)
@@ -1581,7 +1594,9 @@ Args::ParseArgsForCompletion
                 }
             }
 
-            switch (long_options[long_options_index].has_arg)
+            const OptionDefinition *def = long_options[long_options_index].definition;
+            int has_arg = (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
+            switch (has_arg)
             {
             case OptionParser::eNoArgument:
                 option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 1, 0));

Modified: lldb/trunk/source/Interpreter/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CMakeLists.txt?rev=212500&r1=212499&r2=212500&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CMakeLists.txt (original)
+++ lldb/trunk/source/Interpreter/CMakeLists.txt Mon Jul  7 18:54:51 2014
@@ -7,6 +7,7 @@ add_lldb_library(lldbInterpreter
   CommandObject.cpp
   CommandObjectRegexCommand.cpp
   CommandObjectScript.cpp
+  CommandOptionValidators.cpp
   CommandReturnObject.cpp
   OptionGroupArchitecture.cpp
   OptionGroupBoolean.cpp

Added: lldb/trunk/source/Interpreter/CommandOptionValidators.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandOptionValidators.cpp?rev=212500&view=auto
==============================================================================
--- lldb/trunk/source/Interpreter/CommandOptionValidators.cpp (added)
+++ lldb/trunk/source/Interpreter/CommandOptionValidators.cpp Mon Jul  7 18:54:51 2014
@@ -0,0 +1,39 @@
+//===-- CommandOptionValidators.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/Interpreter/CommandOptionValidators.h"
+
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Target/Platform.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+bool PosixPlatformCommandOptionValidator::IsValid(Platform &platform, ExecutionContext &target) const
+{
+    llvm::Triple::OSType os = platform.GetSystemArchitecture().GetTriple().getOS();
+    switch (os)
+    {
+    // Are there any other platforms that are not POSIX-compatible?
+    case llvm::Triple::Win32:
+        return false;
+    default:
+        return true;
+    }
+}
+
+const char* PosixPlatformCommandOptionValidator::ShortConditionString() const 
+{ 
+    return "POSIX"; 
+}
+
+const char* PosixPlatformCommandOptionValidator::LongConditionString() const 
+{ 
+    return "Option only valid for POSIX-compliant hosts."; 
+}

Modified: lldb/trunk/source/Interpreter/Options.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/Options.cpp?rev=212500&r1=212499&r2=212500&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/Options.cpp (original)
+++ lldb/trunk/source/Interpreter/Options.cpp Mon Jul  7 18:54:51 2014
@@ -277,8 +277,7 @@ Options::GetLongOptions ()
         {
             const int short_opt = opt_defs[i].short_option;
 
-            m_getopt_table[i].name    = opt_defs[i].long_option;
-            m_getopt_table[i].has_arg = opt_defs[i].option_has_arg;
+            m_getopt_table[i].definition = &opt_defs[i];
             m_getopt_table[i].flag    = nullptr;
             m_getopt_table[i].val     = short_opt;
 
@@ -297,7 +296,7 @@ Options::GetLongOptions ()
                                 opt_defs[i].long_option,
                                 short_opt,
                                 pos->second,
-                                m_getopt_table[pos->second].name,
+                                m_getopt_table[pos->second].definition->long_option,
                                 opt_defs[i].long_option);
                 else
                     Host::SystemLog (Host::eSystemLogError, "option[%u] --%s has a short option 0x%x that conflicts with option[%u] --%s, short option won't be used for --%s\n",
@@ -305,17 +304,16 @@ Options::GetLongOptions ()
                                 opt_defs[i].long_option,
                                 short_opt,
                                 pos->second,
-                                m_getopt_table[pos->second].name,
+                                m_getopt_table[pos->second].definition->long_option,
                                 opt_defs[i].long_option);
             }
         }
 
         //getopt_long_only requires a NULL final entry in the table:
 
-        m_getopt_table[i].name    = nullptr;
-        m_getopt_table[i].has_arg = 0;
-        m_getopt_table[i].flag    = nullptr;
-        m_getopt_table[i].val     = 0;
+        m_getopt_table[i].definition    = nullptr;
+        m_getopt_table[i].flag          = nullptr;
+        m_getopt_table[i].val           = 0;
     }
 
     if (m_getopt_table.empty())
@@ -336,18 +334,29 @@ void
 Options::OutputFormattedUsageText
 (
     Stream &strm,
-    const char *text,
+    const OptionDefinition &option_def,
     uint32_t output_max_columns
 )
 {
-    int len = strlen (text);
+    std::string actual_text;
+    if (option_def.validator)
+    {
+        const char *condition = option_def.validator->ShortConditionString();
+        if (condition)
+        {
+            actual_text = "[";
+            actual_text.append(condition);
+            actual_text.append("] ");
+        }
+    }
+    actual_text.append(option_def.usage_text);
 
     // Will it all fit on one line?
 
-    if (static_cast<uint32_t>(len + strm.GetIndentLevel()) < output_max_columns)
+    if (static_cast<uint32_t>(actual_text.length() + strm.GetIndentLevel()) < output_max_columns)
     {
         // Output it as a single line.
-        strm.Indent (text);
+        strm.Indent (actual_text.c_str());
         strm.EOL();
     }
     else
@@ -357,13 +366,13 @@ Options::OutputFormattedUsageText
         int text_width = output_max_columns - strm.GetIndentLevel() - 1;
         int start = 0;
         int end = start;
-        int final_end = strlen (text);
+        int final_end = actual_text.length();
         int sub_len;
 
         while (end < final_end)
         {
             // Don't start the 'text' on a space, since we're already outputting the indentation.
-            while ((start < final_end) && (text[start] == ' '))
+            while ((start < final_end) && (actual_text[start] == ' '))
                 start++;
 
             end = start + text_width;
@@ -373,7 +382,7 @@ Options::OutputFormattedUsageText
             {
                 // If we're not at the end of the text, make sure we break the line on white space.
                 while (end > start
-                       && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
+                       && actual_text[end] != ' ' && actual_text[end] != '\t' && actual_text[end] != '\n')
                     end--;
             }
 
@@ -383,7 +392,7 @@ Options::OutputFormattedUsageText
             strm.Indent();
             assert (start < final_end);
             assert (start + sub_len <= final_end);
-            strm.Write(text + start, sub_len);
+            strm.Write(actual_text.c_str() + start, sub_len);
             start = end + 1;
         }
         strm.EOL();
@@ -630,7 +639,7 @@ Options::GenerateOptionUsage
     strm.Printf ("\n\n");
 
     // Now print out all the detailed information about the various options:  long form, short form and help text:
-    //   --long_name <argument>  ( -short <argument> )
+    //   -short <argument> ( --long_name <argument> )
     //   help text
 
     // This variable is used to keep track of which options' info we've printed out, because some options can be in
@@ -683,7 +692,7 @@ Options::GenerateOptionUsage
         
         if (opt_defs[i].usage_text)
             OutputFormattedUsageText (strm,
-                                      opt_defs[i].usage_text,
+                                      opt_defs[i],
                                       screen_width);
         if (opt_defs[i].enum_values != nullptr)
         {





More information about the lldb-commits mailing list