llvm-project/lldb/source/Interpreter/CommandObject.cpp

1116 lines
50 KiB
C++
Raw Normal View History

//===-- CommandObject.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/CommandObject.h"
#include <map>
#include <sstream>
#include <string>
#include <ctype.h>
#include <stdlib.h>
#include "lldb/Core/Address.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Utility/ArchSpec.h"
// These are for the Sourcename completers.
// FIXME: Make a separate file for the completers.
#include "lldb/Core/FileSpecList.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Target/Language.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
using namespace lldb;
using namespace lldb_private;
//-------------------------------------------------------------------------
// CommandObject
//-------------------------------------------------------------------------
CommandObject::CommandObject(CommandInterpreter &interpreter, llvm::StringRef name,
llvm::StringRef help, llvm::StringRef syntax, uint32_t flags)
: m_interpreter(interpreter), m_cmd_name(name),
m_cmd_help_short(), m_cmd_help_long(), m_cmd_syntax(), m_flags(flags),
m_arguments(), m_deprecated_command_override_callback(nullptr),
m_command_override_callback(nullptr), m_command_override_baton(nullptr) {
m_cmd_help_short = help;
m_cmd_syntax = syntax;
}
CommandObject::~CommandObject() {}
llvm::StringRef CommandObject::GetHelp() { return m_cmd_help_short; }
llvm::StringRef CommandObject::GetHelpLong() { return m_cmd_help_long; }
llvm::StringRef CommandObject::GetSyntax() {
if (!m_cmd_syntax.empty())
return m_cmd_syntax;
StreamString syntax_str;
syntax_str.PutCString(GetCommandName());
if (!IsDashDashCommand() && GetOptions() != nullptr)
syntax_str.PutCString(" <cmd-options>");
if (!m_arguments.empty()) {
syntax_str.PutCString(" ");
if (!IsDashDashCommand() && WantsRawCommandString() && GetOptions() &&
GetOptions()->NumCommandOptions())
syntax_str.PutCString("-- ");
GetFormattedCommandArguments(syntax_str);
}
m_cmd_syntax = syntax_str.GetString();
return m_cmd_syntax;
}
llvm::StringRef CommandObject::GetCommandName() const { return m_cmd_name; }
void CommandObject::SetCommandName(llvm::StringRef name) { m_cmd_name = name; }
void CommandObject::SetHelp(llvm::StringRef str) { m_cmd_help_short = str; }
void CommandObject::SetHelpLong(llvm::StringRef str) { m_cmd_help_long = str; }
void CommandObject::SetSyntax(llvm::StringRef str) { m_cmd_syntax = str; }
Options *CommandObject::GetOptions() {
// By default commands don't have options unless this virtual function is
// overridden by base classes.
return nullptr;
}
bool CommandObject::ParseOptions(Args &args, CommandReturnObject &result) {
// See if the subclass has options?
Options *options = GetOptions();
if (options != nullptr) {
Status error;
auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
options->NotifyOptionParsingStarting(&exe_ctx);
const bool require_validation = true;
Move option parsing out of the Args class Summary: The args class is used in plenty of places (a lot of them in the lower lldb layers) for representing a list of arguments, and most of these places don't care about option parsing. Moving the option parsing out of the class removes the largest external dependency (there are a couple more, but these are in static functions), and brings us closer to being able to move it to the Utility module). The new home for these functions is the Options class, which was already used as an argument to the parse calls, so this just inverts the dependency between the two. The functions are themselves are mainly just copied -- the biggest functional change I've made to them is to avoid modifying the input Args argument (getopt likes to permute the argument vector), as it was weird to have another class reorder the entries in Args class. So now the functions don't modify the input arguments, and (for those where it makes sense) return a new Args vector instead. I've also made the addition of a "fake arg0" (required for getopt compatibility) an implementation detail rather than a part of interface. While doing that I noticed that ParseForCompletion function was recording the option indexes in the shuffled vector, but then the consumer was looking up the entries in the unshuffled one. This manifested itself as us not being able to complete "watchpoint set variable foo --" (because getopt would move "foo" to the end). Surprisingly all other completions (e.g. "watchpoint set variable foo --w") were not affected by this. However, I couldn't find a comprehensive test for command argument completion, so I consolidated the existing tests and added a bunch of new ones. Reviewers: davide, jingham, zturner Subscribers: lldb-commits Differential Revision: https://reviews.llvm.org/D43837 llvm-svn: 327110
2018-03-09 18:39:40 +08:00
llvm::Expected<Args> args_or = options->Parse(
args, &exe_ctx, GetCommandInterpreter().GetPlatform(true),
require_validation);
Move option parsing out of the Args class Summary: The args class is used in plenty of places (a lot of them in the lower lldb layers) for representing a list of arguments, and most of these places don't care about option parsing. Moving the option parsing out of the class removes the largest external dependency (there are a couple more, but these are in static functions), and brings us closer to being able to move it to the Utility module). The new home for these functions is the Options class, which was already used as an argument to the parse calls, so this just inverts the dependency between the two. The functions are themselves are mainly just copied -- the biggest functional change I've made to them is to avoid modifying the input Args argument (getopt likes to permute the argument vector), as it was weird to have another class reorder the entries in Args class. So now the functions don't modify the input arguments, and (for those where it makes sense) return a new Args vector instead. I've also made the addition of a "fake arg0" (required for getopt compatibility) an implementation detail rather than a part of interface. While doing that I noticed that ParseForCompletion function was recording the option indexes in the shuffled vector, but then the consumer was looking up the entries in the unshuffled one. This manifested itself as us not being able to complete "watchpoint set variable foo --" (because getopt would move "foo" to the end). Surprisingly all other completions (e.g. "watchpoint set variable foo --w") were not affected by this. However, I couldn't find a comprehensive test for command argument completion, so I consolidated the existing tests and added a bunch of new ones. Reviewers: davide, jingham, zturner Subscribers: lldb-commits Differential Revision: https://reviews.llvm.org/D43837 llvm-svn: 327110
2018-03-09 18:39:40 +08:00
if (args_or) {
args = std::move(*args_or);
error = options->NotifyOptionParsingFinished(&exe_ctx);
Move option parsing out of the Args class Summary: The args class is used in plenty of places (a lot of them in the lower lldb layers) for representing a list of arguments, and most of these places don't care about option parsing. Moving the option parsing out of the class removes the largest external dependency (there are a couple more, but these are in static functions), and brings us closer to being able to move it to the Utility module). The new home for these functions is the Options class, which was already used as an argument to the parse calls, so this just inverts the dependency between the two. The functions are themselves are mainly just copied -- the biggest functional change I've made to them is to avoid modifying the input Args argument (getopt likes to permute the argument vector), as it was weird to have another class reorder the entries in Args class. So now the functions don't modify the input arguments, and (for those where it makes sense) return a new Args vector instead. I've also made the addition of a "fake arg0" (required for getopt compatibility) an implementation detail rather than a part of interface. While doing that I noticed that ParseForCompletion function was recording the option indexes in the shuffled vector, but then the consumer was looking up the entries in the unshuffled one. This manifested itself as us not being able to complete "watchpoint set variable foo --" (because getopt would move "foo" to the end). Surprisingly all other completions (e.g. "watchpoint set variable foo --w") were not affected by this. However, I couldn't find a comprehensive test for command argument completion, so I consolidated the existing tests and added a bunch of new ones. Reviewers: davide, jingham, zturner Subscribers: lldb-commits Differential Revision: https://reviews.llvm.org/D43837 llvm-svn: 327110
2018-03-09 18:39:40 +08:00
} else
error = args_or.takeError();
if (error.Success()) {
if (options->VerifyOptions(result))
return true;
} else {
const char *error_cstr = error.AsCString();
if (error_cstr) {
// We got an error string, lets use that
result.AppendError(error_cstr);
} else {
// No error string, output the usage information into result
options->GenerateOptionUsage(
result.GetErrorStream(), this,
GetCommandInterpreter().GetDebugger().GetTerminalWidth());
}
}
result.SetStatus(eReturnStatusFailed);
return false;
}
return true;
}
bool CommandObject::CheckRequirements(CommandReturnObject &result) {
Expanded the flags that can be set for a command object in lldb_private::CommandObject. This list of available flags are: enum { //---------------------------------------------------------------------- // eFlagRequiresTarget // // Ensures a valid target is contained in m_exe_ctx prior to executing // the command. If a target doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidTargetDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidTargetDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresTarget = (1u << 0), //---------------------------------------------------------------------- // eFlagRequiresProcess // // Ensures a valid process is contained in m_exe_ctx prior to executing // the command. If a process doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidProcessDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidProcessDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresProcess = (1u << 1), //---------------------------------------------------------------------- // eFlagRequiresThread // // Ensures a valid thread is contained in m_exe_ctx prior to executing // the command. If a thread doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidThreadDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidThreadDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresThread = (1u << 2), //---------------------------------------------------------------------- // eFlagRequiresFrame // // Ensures a valid frame is contained in m_exe_ctx prior to executing // the command. If a frame doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidFrameDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidFrameDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresFrame = (1u << 3), //---------------------------------------------------------------------- // eFlagRequiresRegContext // // Ensures a valid register context (from the selected frame if there // is a frame in m_exe_ctx, or from the selected thread from m_exe_ctx) // is availble from m_exe_ctx prior to executing the command. If a // target doesn't exist or is invalid, the command will fail and // CommandObject::GetInvalidRegContextDescription() will be returned as // the error. CommandObject subclasses can override the virtual function // for GetInvalidRegContextDescription() to provide custom strings when // needed. //---------------------------------------------------------------------- eFlagRequiresRegContext = (1u << 4), //---------------------------------------------------------------------- // eFlagTryTargetAPILock // // Attempts to acquire the target lock if a target is selected in the // command interpreter. If the command object fails to acquire the API // lock, the command will fail with an appropriate error message. //---------------------------------------------------------------------- eFlagTryTargetAPILock = (1u << 5), //---------------------------------------------------------------------- // eFlagProcessMustBeLaunched // // Verifies that there is a launched process in m_exe_ctx, if there // isn't, the command will fail with an appropriate error message. //---------------------------------------------------------------------- eFlagProcessMustBeLaunched = (1u << 6), //---------------------------------------------------------------------- // eFlagProcessMustBePaused // // Verifies that there is a paused process in m_exe_ctx, if there // isn't, the command will fail with an appropriate error message. //---------------------------------------------------------------------- eFlagProcessMustBePaused = (1u << 7) }; Now each command object contains a "ExecutionContext m_exe_ctx;" member variable that gets initialized prior to running the command. The validity of the target objects in m_exe_ctx are checked to ensure that any target/process/thread/frame/reg context that are required are valid prior to executing the command. Each command object also contains a Mutex::Locker m_api_locker which gets used if eFlagTryTargetAPILock is set. This centralizes a lot of checking code that was previously and inconsistently implemented across many commands. llvm-svn: 171990
2013-01-10 03:44:40 +08:00
#ifdef LLDB_CONFIGURATION_DEBUG
// Nothing should be stored in m_exe_ctx between running commands as
// m_exe_ctx has shared pointers to the target, process, thread and frame and
// we don't want any CommandObject instances to keep any of these objects
// around longer than for a single command. Every command should call
// CommandObject::Cleanup() after it has completed
assert(m_exe_ctx.GetTargetPtr() == NULL);
assert(m_exe_ctx.GetProcessPtr() == NULL);
assert(m_exe_ctx.GetThreadPtr() == NULL);
assert(m_exe_ctx.GetFramePtr() == NULL);
Expanded the flags that can be set for a command object in lldb_private::CommandObject. This list of available flags are: enum { //---------------------------------------------------------------------- // eFlagRequiresTarget // // Ensures a valid target is contained in m_exe_ctx prior to executing // the command. If a target doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidTargetDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidTargetDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresTarget = (1u << 0), //---------------------------------------------------------------------- // eFlagRequiresProcess // // Ensures a valid process is contained in m_exe_ctx prior to executing // the command. If a process doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidProcessDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidProcessDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresProcess = (1u << 1), //---------------------------------------------------------------------- // eFlagRequiresThread // // Ensures a valid thread is contained in m_exe_ctx prior to executing // the command. If a thread doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidThreadDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidThreadDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresThread = (1u << 2), //---------------------------------------------------------------------- // eFlagRequiresFrame // // Ensures a valid frame is contained in m_exe_ctx prior to executing // the command. If a frame doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidFrameDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidFrameDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresFrame = (1u << 3), //---------------------------------------------------------------------- // eFlagRequiresRegContext // // Ensures a valid register context (from the selected frame if there // is a frame in m_exe_ctx, or from the selected thread from m_exe_ctx) // is availble from m_exe_ctx prior to executing the command. If a // target doesn't exist or is invalid, the command will fail and // CommandObject::GetInvalidRegContextDescription() will be returned as // the error. CommandObject subclasses can override the virtual function // for GetInvalidRegContextDescription() to provide custom strings when // needed. //---------------------------------------------------------------------- eFlagRequiresRegContext = (1u << 4), //---------------------------------------------------------------------- // eFlagTryTargetAPILock // // Attempts to acquire the target lock if a target is selected in the // command interpreter. If the command object fails to acquire the API // lock, the command will fail with an appropriate error message. //---------------------------------------------------------------------- eFlagTryTargetAPILock = (1u << 5), //---------------------------------------------------------------------- // eFlagProcessMustBeLaunched // // Verifies that there is a launched process in m_exe_ctx, if there // isn't, the command will fail with an appropriate error message. //---------------------------------------------------------------------- eFlagProcessMustBeLaunched = (1u << 6), //---------------------------------------------------------------------- // eFlagProcessMustBePaused // // Verifies that there is a paused process in m_exe_ctx, if there // isn't, the command will fail with an appropriate error message. //---------------------------------------------------------------------- eFlagProcessMustBePaused = (1u << 7) }; Now each command object contains a "ExecutionContext m_exe_ctx;" member variable that gets initialized prior to running the command. The validity of the target objects in m_exe_ctx are checked to ensure that any target/process/thread/frame/reg context that are required are valid prior to executing the command. Each command object also contains a Mutex::Locker m_api_locker which gets used if eFlagTryTargetAPILock is set. This centralizes a lot of checking code that was previously and inconsistently implemented across many commands. llvm-svn: 171990
2013-01-10 03:44:40 +08:00
#endif
// Lock down the interpreter's execution context prior to running the command
// so we guarantee the selected target, process, thread and frame can't go
// away during the execution
m_exe_ctx = m_interpreter.GetExecutionContext();
Expanded the flags that can be set for a command object in lldb_private::CommandObject. This list of available flags are: enum { //---------------------------------------------------------------------- // eFlagRequiresTarget // // Ensures a valid target is contained in m_exe_ctx prior to executing // the command. If a target doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidTargetDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidTargetDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresTarget = (1u << 0), //---------------------------------------------------------------------- // eFlagRequiresProcess // // Ensures a valid process is contained in m_exe_ctx prior to executing // the command. If a process doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidProcessDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidProcessDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresProcess = (1u << 1), //---------------------------------------------------------------------- // eFlagRequiresThread // // Ensures a valid thread is contained in m_exe_ctx prior to executing // the command. If a thread doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidThreadDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidThreadDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresThread = (1u << 2), //---------------------------------------------------------------------- // eFlagRequiresFrame // // Ensures a valid frame is contained in m_exe_ctx prior to executing // the command. If a frame doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidFrameDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidFrameDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresFrame = (1u << 3), //---------------------------------------------------------------------- // eFlagRequiresRegContext // // Ensures a valid register context (from the selected frame if there // is a frame in m_exe_ctx, or from the selected thread from m_exe_ctx) // is availble from m_exe_ctx prior to executing the command. If a // target doesn't exist or is invalid, the command will fail and // CommandObject::GetInvalidRegContextDescription() will be returned as // the error. CommandObject subclasses can override the virtual function // for GetInvalidRegContextDescription() to provide custom strings when // needed. //---------------------------------------------------------------------- eFlagRequiresRegContext = (1u << 4), //---------------------------------------------------------------------- // eFlagTryTargetAPILock // // Attempts to acquire the target lock if a target is selected in the // command interpreter. If the command object fails to acquire the API // lock, the command will fail with an appropriate error message. //---------------------------------------------------------------------- eFlagTryTargetAPILock = (1u << 5), //---------------------------------------------------------------------- // eFlagProcessMustBeLaunched // // Verifies that there is a launched process in m_exe_ctx, if there // isn't, the command will fail with an appropriate error message. //---------------------------------------------------------------------- eFlagProcessMustBeLaunched = (1u << 6), //---------------------------------------------------------------------- // eFlagProcessMustBePaused // // Verifies that there is a paused process in m_exe_ctx, if there // isn't, the command will fail with an appropriate error message. //---------------------------------------------------------------------- eFlagProcessMustBePaused = (1u << 7) }; Now each command object contains a "ExecutionContext m_exe_ctx;" member variable that gets initialized prior to running the command. The validity of the target objects in m_exe_ctx are checked to ensure that any target/process/thread/frame/reg context that are required are valid prior to executing the command. Each command object also contains a Mutex::Locker m_api_locker which gets used if eFlagTryTargetAPILock is set. This centralizes a lot of checking code that was previously and inconsistently implemented across many commands. llvm-svn: 171990
2013-01-10 03:44:40 +08:00
const uint32_t flags = GetFlags().Get();
if (flags & (eCommandRequiresTarget | eCommandRequiresProcess |
eCommandRequiresThread | eCommandRequiresFrame |
eCommandTryTargetAPILock)) {
Expanded the flags that can be set for a command object in lldb_private::CommandObject. This list of available flags are: enum { //---------------------------------------------------------------------- // eFlagRequiresTarget // // Ensures a valid target is contained in m_exe_ctx prior to executing // the command. If a target doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidTargetDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidTargetDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresTarget = (1u << 0), //---------------------------------------------------------------------- // eFlagRequiresProcess // // Ensures a valid process is contained in m_exe_ctx prior to executing // the command. If a process doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidProcessDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidProcessDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresProcess = (1u << 1), //---------------------------------------------------------------------- // eFlagRequiresThread // // Ensures a valid thread is contained in m_exe_ctx prior to executing // the command. If a thread doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidThreadDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidThreadDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresThread = (1u << 2), //---------------------------------------------------------------------- // eFlagRequiresFrame // // Ensures a valid frame is contained in m_exe_ctx prior to executing // the command. If a frame doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidFrameDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidFrameDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresFrame = (1u << 3), //---------------------------------------------------------------------- // eFlagRequiresRegContext // // Ensures a valid register context (from the selected frame if there // is a frame in m_exe_ctx, or from the selected thread from m_exe_ctx) // is availble from m_exe_ctx prior to executing the command. If a // target doesn't exist or is invalid, the command will fail and // CommandObject::GetInvalidRegContextDescription() will be returned as // the error. CommandObject subclasses can override the virtual function // for GetInvalidRegContextDescription() to provide custom strings when // needed. //---------------------------------------------------------------------- eFlagRequiresRegContext = (1u << 4), //---------------------------------------------------------------------- // eFlagTryTargetAPILock // // Attempts to acquire the target lock if a target is selected in the // command interpreter. If the command object fails to acquire the API // lock, the command will fail with an appropriate error message. //---------------------------------------------------------------------- eFlagTryTargetAPILock = (1u << 5), //---------------------------------------------------------------------- // eFlagProcessMustBeLaunched // // Verifies that there is a launched process in m_exe_ctx, if there // isn't, the command will fail with an appropriate error message. //---------------------------------------------------------------------- eFlagProcessMustBeLaunched = (1u << 6), //---------------------------------------------------------------------- // eFlagProcessMustBePaused // // Verifies that there is a paused process in m_exe_ctx, if there // isn't, the command will fail with an appropriate error message. //---------------------------------------------------------------------- eFlagProcessMustBePaused = (1u << 7) }; Now each command object contains a "ExecutionContext m_exe_ctx;" member variable that gets initialized prior to running the command. The validity of the target objects in m_exe_ctx are checked to ensure that any target/process/thread/frame/reg context that are required are valid prior to executing the command. Each command object also contains a Mutex::Locker m_api_locker which gets used if eFlagTryTargetAPILock is set. This centralizes a lot of checking code that was previously and inconsistently implemented across many commands. llvm-svn: 171990
2013-01-10 03:44:40 +08:00
if ((flags & eCommandRequiresTarget) && !m_exe_ctx.HasTargetScope()) {
result.AppendError(GetInvalidTargetDescription());
return false;
Expanded the flags that can be set for a command object in lldb_private::CommandObject. This list of available flags are: enum { //---------------------------------------------------------------------- // eFlagRequiresTarget // // Ensures a valid target is contained in m_exe_ctx prior to executing // the command. If a target doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidTargetDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidTargetDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresTarget = (1u << 0), //---------------------------------------------------------------------- // eFlagRequiresProcess // // Ensures a valid process is contained in m_exe_ctx prior to executing // the command. If a process doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidProcessDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidProcessDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresProcess = (1u << 1), //---------------------------------------------------------------------- // eFlagRequiresThread // // Ensures a valid thread is contained in m_exe_ctx prior to executing // the command. If a thread doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidThreadDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidThreadDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresThread = (1u << 2), //---------------------------------------------------------------------- // eFlagRequiresFrame // // Ensures a valid frame is contained in m_exe_ctx prior to executing // the command. If a frame doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidFrameDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidFrameDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresFrame = (1u << 3), //---------------------------------------------------------------------- // eFlagRequiresRegContext // // Ensures a valid register context (from the selected frame if there // is a frame in m_exe_ctx, or from the selected thread from m_exe_ctx) // is availble from m_exe_ctx prior to executing the command. If a // target doesn't exist or is invalid, the command will fail and // CommandObject::GetInvalidRegContextDescription() will be returned as // the error. CommandObject subclasses can override the virtual function // for GetInvalidRegContextDescription() to provide custom strings when // needed. //---------------------------------------------------------------------- eFlagRequiresRegContext = (1u << 4), //---------------------------------------------------------------------- // eFlagTryTargetAPILock // // Attempts to acquire the target lock if a target is selected in the // command interpreter. If the command object fails to acquire the API // lock, the command will fail with an appropriate error message. //---------------------------------------------------------------------- eFlagTryTargetAPILock = (1u << 5), //---------------------------------------------------------------------- // eFlagProcessMustBeLaunched // // Verifies that there is a launched process in m_exe_ctx, if there // isn't, the command will fail with an appropriate error message. //---------------------------------------------------------------------- eFlagProcessMustBeLaunched = (1u << 6), //---------------------------------------------------------------------- // eFlagProcessMustBePaused // // Verifies that there is a paused process in m_exe_ctx, if there // isn't, the command will fail with an appropriate error message. //---------------------------------------------------------------------- eFlagProcessMustBePaused = (1u << 7) }; Now each command object contains a "ExecutionContext m_exe_ctx;" member variable that gets initialized prior to running the command. The validity of the target objects in m_exe_ctx are checked to ensure that any target/process/thread/frame/reg context that are required are valid prior to executing the command. Each command object also contains a Mutex::Locker m_api_locker which gets used if eFlagTryTargetAPILock is set. This centralizes a lot of checking code that was previously and inconsistently implemented across many commands. llvm-svn: 171990
2013-01-10 03:44:40 +08:00
}
if ((flags & eCommandRequiresProcess) && !m_exe_ctx.HasProcessScope()) {
if (!m_exe_ctx.HasTargetScope())
result.AppendError(GetInvalidTargetDescription());
else
result.AppendError(GetInvalidProcessDescription());
return false;
}
if ((flags & eCommandRequiresThread) && !m_exe_ctx.HasThreadScope()) {
if (!m_exe_ctx.HasTargetScope())
result.AppendError(GetInvalidTargetDescription());
else if (!m_exe_ctx.HasProcessScope())
result.AppendError(GetInvalidProcessDescription());
else
result.AppendError(GetInvalidThreadDescription());
return false;
}
if ((flags & eCommandRequiresFrame) && !m_exe_ctx.HasFrameScope()) {
if (!m_exe_ctx.HasTargetScope())
result.AppendError(GetInvalidTargetDescription());
else if (!m_exe_ctx.HasProcessScope())
result.AppendError(GetInvalidProcessDescription());
else if (!m_exe_ctx.HasThreadScope())
result.AppendError(GetInvalidThreadDescription());
else
result.AppendError(GetInvalidFrameDescription());
return false;
}
if ((flags & eCommandRequiresRegContext) &&
(m_exe_ctx.GetRegisterContext() == nullptr)) {
result.AppendError(GetInvalidRegContextDescription());
return false;
}
if (flags & eCommandTryTargetAPILock) {
Target *target = m_exe_ctx.GetTargetPtr();
if (target)
m_api_locker =
std::unique_lock<std::recursive_mutex>(target->GetAPIMutex());
}
}
if (GetFlags().AnySet(eCommandProcessMustBeLaunched |
eCommandProcessMustBePaused)) {
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
if (process == nullptr) {
// A process that is not running is considered paused.
if (GetFlags().Test(eCommandProcessMustBeLaunched)) {
result.AppendError("Process must exist.");
result.SetStatus(eReturnStatusFailed);
return false;
}
} else {
StateType state = process->GetState();
switch (state) {
case eStateInvalid:
case eStateSuspended:
case eStateCrashed:
case eStateStopped:
break;
case eStateConnected:
case eStateAttaching:
case eStateLaunching:
case eStateDetached:
case eStateExited:
case eStateUnloaded:
if (GetFlags().Test(eCommandProcessMustBeLaunched)) {
result.AppendError("Process must be launched.");
result.SetStatus(eReturnStatusFailed);
return false;
}
break;
case eStateRunning:
case eStateStepping:
if (GetFlags().Test(eCommandProcessMustBePaused)) {
result.AppendError("Process is running. Use 'process interrupt' to "
"pause execution.");
result.SetStatus(eReturnStatusFailed);
return false;
}
}
}
}
return true;
}
void CommandObject::Cleanup() {
m_exe_ctx.Clear();
if (m_api_locker.owns_lock())
m_api_locker.unlock();
Expanded the flags that can be set for a command object in lldb_private::CommandObject. This list of available flags are: enum { //---------------------------------------------------------------------- // eFlagRequiresTarget // // Ensures a valid target is contained in m_exe_ctx prior to executing // the command. If a target doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidTargetDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidTargetDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresTarget = (1u << 0), //---------------------------------------------------------------------- // eFlagRequiresProcess // // Ensures a valid process is contained in m_exe_ctx prior to executing // the command. If a process doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidProcessDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidProcessDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresProcess = (1u << 1), //---------------------------------------------------------------------- // eFlagRequiresThread // // Ensures a valid thread is contained in m_exe_ctx prior to executing // the command. If a thread doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidThreadDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidThreadDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresThread = (1u << 2), //---------------------------------------------------------------------- // eFlagRequiresFrame // // Ensures a valid frame is contained in m_exe_ctx prior to executing // the command. If a frame doesn't exist or is invalid, the command // will fail and CommandObject::GetInvalidFrameDescription() will be // returned as the error. CommandObject subclasses can override the // virtual function for GetInvalidFrameDescription() to provide custom // strings when needed. //---------------------------------------------------------------------- eFlagRequiresFrame = (1u << 3), //---------------------------------------------------------------------- // eFlagRequiresRegContext // // Ensures a valid register context (from the selected frame if there // is a frame in m_exe_ctx, or from the selected thread from m_exe_ctx) // is availble from m_exe_ctx prior to executing the command. If a // target doesn't exist or is invalid, the command will fail and // CommandObject::GetInvalidRegContextDescription() will be returned as // the error. CommandObject subclasses can override the virtual function // for GetInvalidRegContextDescription() to provide custom strings when // needed. //---------------------------------------------------------------------- eFlagRequiresRegContext = (1u << 4), //---------------------------------------------------------------------- // eFlagTryTargetAPILock // // Attempts to acquire the target lock if a target is selected in the // command interpreter. If the command object fails to acquire the API // lock, the command will fail with an appropriate error message. //---------------------------------------------------------------------- eFlagTryTargetAPILock = (1u << 5), //---------------------------------------------------------------------- // eFlagProcessMustBeLaunched // // Verifies that there is a launched process in m_exe_ctx, if there // isn't, the command will fail with an appropriate error message. //---------------------------------------------------------------------- eFlagProcessMustBeLaunched = (1u << 6), //---------------------------------------------------------------------- // eFlagProcessMustBePaused // // Verifies that there is a paused process in m_exe_ctx, if there // isn't, the command will fail with an appropriate error message. //---------------------------------------------------------------------- eFlagProcessMustBePaused = (1u << 7) }; Now each command object contains a "ExecutionContext m_exe_ctx;" member variable that gets initialized prior to running the command. The validity of the target objects in m_exe_ctx are checked to ensure that any target/process/thread/frame/reg context that are required are valid prior to executing the command. Each command object also contains a Mutex::Locker m_api_locker which gets used if eFlagTryTargetAPILock is set. This centralizes a lot of checking code that was previously and inconsistently implemented across many commands. llvm-svn: 171990
2013-01-10 03:44:40 +08:00
}
Refactoring for for the internal command line completion API (NFC) Summary: This patch refactors the internal completion API. It now takes (as far as possible) a single CompletionRequest object instead o half a dozen in/out/in-out parameters. The CompletionRequest contains a common superset of the different parameters as far as it makes sense. This includes the raw command line string and raw cursor position, which should make the `expr` command possible to implement (at least without hacks that reconstruct the command line from the args). This patch is not intended to change the observable behavior of lldb in any way. It's also as minimal as possible and doesn't attempt to fix all the problems the API has. Some Q&A: Q: Why is this not fixing all the problems in the completion API? A: Because is a blocker for the expr command completion which I want to get in ASAP. This is the smallest patch that unblocks the expr completion patch and which allows trivial refactoring in the future. The patch also doesn't really change the internal information flow in the API, so that hopefully saves us from ever having to revert and resubmit this humongous patch. Q: Can we merge all the copy-pasted code in the completion methods (like computing the current incomplete arg) into CompletionRequest class? A: Yes, but it's out of scope for this patch. Q: Why the `word_complete = request.GetWordComplete(); ... ` pattern? A: I don't want to add a getter that returns a reference to the internal integer. So we have to use a temporary variable and the Getter/Setter instead. We don't throw exceptions from what I can tell, so the behavior doesn't change. Q: Why are we not owning the list of matches? A: Because that's how the previous API works. But that should be fixed too (in another patch). Q: Can we make the constructor simpler and compute some of the values from the plain command? A: I think this works, but I rather want to have this in a follow up commit. Especially when making nested request it's a bit awkward that the parsed arguments behave as both input/output (as we should in theory propagate the changes on the nested request back to the parent request if we don't want to change the behavior too much). Q: Can't we pass one const request object and then just return another result object instead of mixing them together in one in/out parameter? A: It's hard to get keep the same behavior with that pattern, but I think we can also get a nice API with just a single request object. If we make all input parameters read-only, we have a clear separation between what is actually an input and what an output parameter (and hopefully we get rid of the in-out parameters). Q: Can we throw out the 'match' variables that are not implemented according to the comment? A: We currently just forward them as in the old code to the different methods, even though I think they are really not used. We can easily remove and readd them once every single completion method just takes a CompletionRequest, but for now I prefer NFC behavior from the perspective of the API user. Reviewers: davide, jingham, labath Reviewed By: jingham Subscribers: mgorny, friss, lldb-commits Differential Revision: https://reviews.llvm.org/D48796 llvm-svn: 336146
2018-07-03 05:29:56 +08:00
int CommandObject::HandleCompletion(CompletionRequest &request) {
// Default implementation of WantsCompletion() is !WantsRawCommandString().
// Subclasses who want raw command string but desire, for example, argument
// completion should override WantsCompletion() to return true, instead.
if (WantsRawCommandString() && !WantsCompletion()) {
// FIXME: Abstract telling the completion to insert the completion
// character.
return -1;
} else {
// Can we do anything generic with the options?
Options *cur_options = GetOptions();
CommandReturnObject result;
OptionElementVector opt_element_vector;
if (cur_options != nullptr) {
Refactoring for for the internal command line completion API (NFC) Summary: This patch refactors the internal completion API. It now takes (as far as possible) a single CompletionRequest object instead o half a dozen in/out/in-out parameters. The CompletionRequest contains a common superset of the different parameters as far as it makes sense. This includes the raw command line string and raw cursor position, which should make the `expr` command possible to implement (at least without hacks that reconstruct the command line from the args). This patch is not intended to change the observable behavior of lldb in any way. It's also as minimal as possible and doesn't attempt to fix all the problems the API has. Some Q&A: Q: Why is this not fixing all the problems in the completion API? A: Because is a blocker for the expr command completion which I want to get in ASAP. This is the smallest patch that unblocks the expr completion patch and which allows trivial refactoring in the future. The patch also doesn't really change the internal information flow in the API, so that hopefully saves us from ever having to revert and resubmit this humongous patch. Q: Can we merge all the copy-pasted code in the completion methods (like computing the current incomplete arg) into CompletionRequest class? A: Yes, but it's out of scope for this patch. Q: Why the `word_complete = request.GetWordComplete(); ... ` pattern? A: I don't want to add a getter that returns a reference to the internal integer. So we have to use a temporary variable and the Getter/Setter instead. We don't throw exceptions from what I can tell, so the behavior doesn't change. Q: Why are we not owning the list of matches? A: Because that's how the previous API works. But that should be fixed too (in another patch). Q: Can we make the constructor simpler and compute some of the values from the plain command? A: I think this works, but I rather want to have this in a follow up commit. Especially when making nested request it's a bit awkward that the parsed arguments behave as both input/output (as we should in theory propagate the changes on the nested request back to the parent request if we don't want to change the behavior too much). Q: Can't we pass one const request object and then just return another result object instead of mixing them together in one in/out parameter? A: It's hard to get keep the same behavior with that pattern, but I think we can also get a nice API with just a single request object. If we make all input parameters read-only, we have a clear separation between what is actually an input and what an output parameter (and hopefully we get rid of the in-out parameters). Q: Can we throw out the 'match' variables that are not implemented according to the comment? A: We currently just forward them as in the old code to the different methods, even though I think they are really not used. We can easily remove and readd them once every single completion method just takes a CompletionRequest, but for now I prefer NFC behavior from the perspective of the API user. Reviewers: davide, jingham, labath Reviewed By: jingham Subscribers: mgorny, friss, lldb-commits Differential Revision: https://reviews.llvm.org/D48796 llvm-svn: 336146
2018-07-03 05:29:56 +08:00
opt_element_vector = cur_options->ParseForCompletion(
request.GetParsedLine(), request.GetCursorIndex());
bool handled_by_options = cur_options->HandleOptionCompletion(
request, opt_element_vector, GetCommandInterpreter());
if (handled_by_options)
Narrow the CompletionRequest API to being append-only. Summary: We currently allow any completion handler to read and manipulate the list of matches we calculated so far. This leads to a few problems: Firstly, a completion handler's logic can now depend on previously calculated results by another handlers. No completion handler should have such an implicit dependency, but the current API makes it likely that this could happen (or already happens). Especially the fact that some completion handler deleted all previously calculated results can mess things up right now. Secondly, all completion handlers have knowledge about our internal data structures with this API. This makes refactoring this internal data structure much harder than it should be. Especially planned changes like the support of descriptions for completions are currently giant patches because we have to refactor every single completion handler. This patch narrows the contract the CompletionRequest has with the different handlers to: 1. A handler can suggest a completion. 2. A handler can ask how many suggestions we already have. Point 2 obviously means we still have a dependency left between the different handlers, but getting rid of this is too large to just append it to this patch. Otherwise this patch just completely hides the internal StringList to the different handlers. The CompletionRequest API now also ensures that the list of completions is unique and we don't suggest the same value multiple times to the user. This property has been so far only been ensured by the `Option` handler, but is now applied globally. This is part of this patch as the OptionHandler is no longer able to implement this functionality itself. Reviewers: jingham, davide, labath Reviewed By: davide Subscribers: lldb-commits Differential Revision: https://reviews.llvm.org/D49322 llvm-svn: 338151
2018-07-28 02:42:46 +08:00
return request.GetNumberOfMatches();
}
// If we got here, the last word is not an option or an option argument.
Refactoring for for the internal command line completion API (NFC) Summary: This patch refactors the internal completion API. It now takes (as far as possible) a single CompletionRequest object instead o half a dozen in/out/in-out parameters. The CompletionRequest contains a common superset of the different parameters as far as it makes sense. This includes the raw command line string and raw cursor position, which should make the `expr` command possible to implement (at least without hacks that reconstruct the command line from the args). This patch is not intended to change the observable behavior of lldb in any way. It's also as minimal as possible and doesn't attempt to fix all the problems the API has. Some Q&A: Q: Why is this not fixing all the problems in the completion API? A: Because is a blocker for the expr command completion which I want to get in ASAP. This is the smallest patch that unblocks the expr completion patch and which allows trivial refactoring in the future. The patch also doesn't really change the internal information flow in the API, so that hopefully saves us from ever having to revert and resubmit this humongous patch. Q: Can we merge all the copy-pasted code in the completion methods (like computing the current incomplete arg) into CompletionRequest class? A: Yes, but it's out of scope for this patch. Q: Why the `word_complete = request.GetWordComplete(); ... ` pattern? A: I don't want to add a getter that returns a reference to the internal integer. So we have to use a temporary variable and the Getter/Setter instead. We don't throw exceptions from what I can tell, so the behavior doesn't change. Q: Why are we not owning the list of matches? A: Because that's how the previous API works. But that should be fixed too (in another patch). Q: Can we make the constructor simpler and compute some of the values from the plain command? A: I think this works, but I rather want to have this in a follow up commit. Especially when making nested request it's a bit awkward that the parsed arguments behave as both input/output (as we should in theory propagate the changes on the nested request back to the parent request if we don't want to change the behavior too much). Q: Can't we pass one const request object and then just return another result object instead of mixing them together in one in/out parameter? A: It's hard to get keep the same behavior with that pattern, but I think we can also get a nice API with just a single request object. If we make all input parameters read-only, we have a clear separation between what is actually an input and what an output parameter (and hopefully we get rid of the in-out parameters). Q: Can we throw out the 'match' variables that are not implemented according to the comment? A: We currently just forward them as in the old code to the different methods, even though I think they are really not used. We can easily remove and readd them once every single completion method just takes a CompletionRequest, but for now I prefer NFC behavior from the perspective of the API user. Reviewers: davide, jingham, labath Reviewed By: jingham Subscribers: mgorny, friss, lldb-commits Differential Revision: https://reviews.llvm.org/D48796 llvm-svn: 336146
2018-07-03 05:29:56 +08:00
return HandleArgumentCompletion(request, opt_element_vector);
}
}
bool CommandObject::HelpTextContainsWord(llvm::StringRef search_word,
bool search_short_help,
bool search_long_help,
bool search_syntax,
bool search_options) {
std::string options_usage_help;
bool found_word = false;
llvm::StringRef short_help = GetHelp();
llvm::StringRef long_help = GetHelpLong();
llvm::StringRef syntax_help = GetSyntax();
if (search_short_help && short_help.contains_lower(search_word))
found_word = true;
else if (search_long_help && long_help.contains_lower(search_word))
found_word = true;
else if (search_syntax && syntax_help.contains_lower(search_word))
found_word = true;
if (!found_word && search_options && GetOptions() != nullptr) {
StreamString usage_help;
GetOptions()->GenerateOptionUsage(
usage_help, this,
GetCommandInterpreter().GetDebugger().GetTerminalWidth());
if (!usage_help.Empty()) {
llvm::StringRef usage_text = usage_help.GetString();
if (usage_text.contains_lower(search_word))
found_word = true;
}
}
return found_word;
}
bool CommandObject::ParseOptionsAndNotify(Args &args,
CommandReturnObject &result,
OptionGroupOptions &group_options,
ExecutionContext &exe_ctx) {
if (!ParseOptions(args, result))
return false;
Status error(group_options.NotifyOptionParsingFinished(&exe_ctx));
if (error.Fail()) {
result.AppendError(error.AsCString());
result.SetStatus(eReturnStatusFailed);
return false;
}
return true;
}
int CommandObject::GetNumArgumentEntries() { return m_arguments.size(); }
CommandObject::CommandArgumentEntry *
CommandObject::GetArgumentEntryAtIndex(int idx) {
if (static_cast<size_t>(idx) < m_arguments.size())
return &(m_arguments[idx]);
return nullptr;
}
const CommandObject::ArgumentTableEntry *
CommandObject::FindArgumentDataByType(CommandArgumentType arg_type) {
const ArgumentTableEntry *table = CommandObject::GetArgumentTable();
for (int i = 0; i < eArgTypeLastArg; ++i)
if (table[i].arg_type == arg_type)
return &(table[i]);
return nullptr;
}
void CommandObject::GetArgumentHelp(Stream &str, CommandArgumentType arg_type,
CommandInterpreter &interpreter) {
const ArgumentTableEntry *table = CommandObject::GetArgumentTable();
const ArgumentTableEntry *entry = &(table[arg_type]);
// The table is *supposed* to be kept in arg_type order, but someone *could*
// have messed it up...
if (entry->arg_type != arg_type)
entry = CommandObject::FindArgumentDataByType(arg_type);
if (!entry)
return;
StreamString name_str;
name_str.Printf("<%s>", entry->arg_name);
if (entry->help_function) {
llvm::StringRef help_text = entry->help_function();
if (!entry->help_function.self_formatting) {
interpreter.OutputFormattedHelpText(str, name_str.GetString(), "--",
help_text, name_str.GetSize());
} else {
interpreter.OutputHelpText(str, name_str.GetString(), "--", help_text,
name_str.GetSize());
}
} else
interpreter.OutputFormattedHelpText(str, name_str.GetString(), "--",
entry->help_text, name_str.GetSize());
}
const char *CommandObject::GetArgumentName(CommandArgumentType arg_type) {
const ArgumentTableEntry *entry =
&(CommandObject::GetArgumentTable()[arg_type]);
// The table is *supposed* to be kept in arg_type order, but someone *could*
// have messed it up...
if (entry->arg_type != arg_type)
entry = CommandObject::FindArgumentDataByType(arg_type);
if (entry)
return entry->arg_name;
return nullptr;
}
bool CommandObject::IsPairType(ArgumentRepetitionType arg_repeat_type) {
if ((arg_repeat_type == eArgRepeatPairPlain) ||
(arg_repeat_type == eArgRepeatPairOptional) ||
(arg_repeat_type == eArgRepeatPairPlus) ||
(arg_repeat_type == eArgRepeatPairStar) ||
(arg_repeat_type == eArgRepeatPairRange) ||
(arg_repeat_type == eArgRepeatPairRangeOptional))
return true;
return false;
}
static CommandObject::CommandArgumentEntry
OptSetFiltered(uint32_t opt_set_mask,
CommandObject::CommandArgumentEntry &cmd_arg_entry) {
CommandObject::CommandArgumentEntry ret_val;
for (unsigned i = 0; i < cmd_arg_entry.size(); ++i)
if (opt_set_mask & cmd_arg_entry[i].arg_opt_set_association)
ret_val.push_back(cmd_arg_entry[i]);
return ret_val;
}
// Default parameter value of opt_set_mask is LLDB_OPT_SET_ALL, which means
// take all the argument data into account. On rare cases where some argument
// sticks with certain option sets, this function returns the option set
// filtered args.
void CommandObject::GetFormattedCommandArguments(Stream &str,
uint32_t opt_set_mask) {
int num_args = m_arguments.size();
for (int i = 0; i < num_args; ++i) {
if (i > 0)
str.Printf(" ");
CommandArgumentEntry arg_entry =
opt_set_mask == LLDB_OPT_SET_ALL
? m_arguments[i]
: OptSetFiltered(opt_set_mask, m_arguments[i]);
int num_alternatives = arg_entry.size();
if ((num_alternatives == 2) && IsPairType(arg_entry[0].arg_repetition)) {
const char *first_name = GetArgumentName(arg_entry[0].arg_type);
const char *second_name = GetArgumentName(arg_entry[1].arg_type);
switch (arg_entry[0].arg_repetition) {
case eArgRepeatPairPlain:
str.Printf("<%s> <%s>", first_name, second_name);
break;
case eArgRepeatPairOptional:
str.Printf("[<%s> <%s>]", first_name, second_name);
break;
case eArgRepeatPairPlus:
str.Printf("<%s> <%s> [<%s> <%s> [...]]", first_name, second_name,
first_name, second_name);
break;
case eArgRepeatPairStar:
str.Printf("[<%s> <%s> [<%s> <%s> [...]]]", first_name, second_name,
first_name, second_name);
break;
case eArgRepeatPairRange:
str.Printf("<%s_1> <%s_1> ... <%s_n> <%s_n>", first_name, second_name,
first_name, second_name);
break;
case eArgRepeatPairRangeOptional:
str.Printf("[<%s_1> <%s_1> ... <%s_n> <%s_n>]", first_name, second_name,
first_name, second_name);
break;
// Explicitly test for all the rest of the cases, so if new types get
// added we will notice the missing case statement(s).
case eArgRepeatPlain:
case eArgRepeatOptional:
case eArgRepeatPlus:
case eArgRepeatStar:
case eArgRepeatRange:
// These should not be reached, as they should fail the IsPairType test
// above.
break;
}
} else {
StreamString names;
for (int j = 0; j < num_alternatives; ++j) {
if (j > 0)
names.Printf(" | ");
names.Printf("%s", GetArgumentName(arg_entry[j].arg_type));
}
std::string name_str = names.GetString();
switch (arg_entry[0].arg_repetition) {
case eArgRepeatPlain:
str.Printf("<%s>", name_str.c_str());
break;
case eArgRepeatPlus:
str.Printf("<%s> [<%s> [...]]", name_str.c_str(), name_str.c_str());
break;
case eArgRepeatStar:
str.Printf("[<%s> [<%s> [...]]]", name_str.c_str(), name_str.c_str());
break;
case eArgRepeatOptional:
str.Printf("[<%s>]", name_str.c_str());
break;
case eArgRepeatRange:
str.Printf("<%s_1> .. <%s_n>", name_str.c_str(), name_str.c_str());
break;
// Explicitly test for all the rest of the cases, so if new types get
// added we will notice the missing case statement(s).
case eArgRepeatPairPlain:
case eArgRepeatPairOptional:
case eArgRepeatPairPlus:
case eArgRepeatPairStar:
case eArgRepeatPairRange:
case eArgRepeatPairRangeOptional:
// These should not be hit, as they should pass the IsPairType test
// above, and control should have gone into the other branch of the if
// statement.
break;
}
}
}
}
CommandArgumentType
CommandObject::LookupArgumentName(llvm::StringRef arg_name) {
CommandArgumentType return_type = eArgTypeLastArg;
arg_name = arg_name.ltrim('<').rtrim('>');
const ArgumentTableEntry *table = GetArgumentTable();
for (int i = 0; i < eArgTypeLastArg; ++i)
if (arg_name == table[i].arg_name)
return_type = g_arguments_data[i].arg_type;
return return_type;
}
static llvm::StringRef RegisterNameHelpTextCallback() {
return "Register names can be specified using the architecture specific "
"names. "
"They can also be specified using generic names. Not all generic "
"entities have "
"registers backing them on all architectures. When they don't the "
"generic name "
"will return an error.\n"
"The generic names defined in lldb are:\n"
"\n"
"pc - program counter register\n"
"ra - return address register\n"
"fp - frame pointer register\n"
"sp - stack pointer register\n"
"flags - the flags register\n"
"arg{1-6} - integer argument passing registers.\n";
}
static llvm::StringRef BreakpointIDHelpTextCallback() {
return "Breakpoints are identified using major and minor numbers; the major "
"number corresponds to the single entity that was created with a "
"'breakpoint "
"set' command; the minor numbers correspond to all the locations that "
"were "
"actually found/set based on the major breakpoint. A full breakpoint "
"ID might "
"look like 3.14, meaning the 14th location set for the 3rd "
"breakpoint. You "
"can specify all the locations of a breakpoint by just indicating the "
"major "
"breakpoint number. A valid breakpoint ID consists either of just the "
"major "
"number, or the major number followed by a dot and the location "
"number (e.g. "
"3 or 3.2 could both be valid breakpoint IDs.)";
}
static llvm::StringRef BreakpointIDRangeHelpTextCallback() {
return "A 'breakpoint ID list' is a manner of specifying multiple "
"breakpoints. "
"This can be done through several mechanisms. The easiest way is to "
"just "
"enter a space-separated list of breakpoint IDs. To specify all the "
"breakpoint locations under a major breakpoint, you can use the major "
"breakpoint number followed by '.*', eg. '5.*' means all the "
"locations under "
"breakpoint 5. You can also indicate a range of breakpoints by using "
"<start-bp-id> - <end-bp-id>. The start-bp-id and end-bp-id for a "
"range can "
"be any valid breakpoint IDs. It is not legal, however, to specify a "
"range "
"using specific locations that cross major breakpoint numbers. I.e. "
"3.2 - 3.7"
" is legal; 2 - 5 is legal; but 3.2 - 4.4 is not legal.";
}
static llvm::StringRef BreakpointNameHelpTextCallback() {
return "A name that can be added to a breakpoint when it is created, or "
"later "
"on with the \"breakpoint name add\" command. "
"Breakpoint names can be used to specify breakpoints in all the "
"places breakpoint IDs "
"and breakpoint ID ranges can be used. As such they provide a "
"convenient way to group breakpoints, "
"and to operate on breakpoints you create without having to track the "
"breakpoint number. "
"Note, the attributes you set when using a breakpoint name in a "
"breakpoint command don't "
"adhere to the name, but instead are set individually on all the "
"breakpoints currently tagged with that "
"name. Future breakpoints "
"tagged with that name will not pick up the attributes previously "
"given using that name. "
"In order to distinguish breakpoint names from breakpoint IDs and "
"ranges, "
"names must start with a letter from a-z or A-Z and cannot contain "
"spaces, \".\" or \"-\". "
"Also, breakpoint names can only be applied to breakpoints, not to "
"breakpoint locations.";
}
static llvm::StringRef GDBFormatHelpTextCallback() {
return "A GDB format consists of a repeat count, a format letter and a size "
"letter. "
"The repeat count is optional and defaults to 1. The format letter is "
"optional "
"and defaults to the previous format that was used. The size letter "
"is optional "
"and defaults to the previous size that was used.\n"
"\n"
"Format letters include:\n"
"o - octal\n"
"x - hexadecimal\n"
"d - decimal\n"
"u - unsigned decimal\n"
"t - binary\n"
"f - float\n"
"a - address\n"
"i - instruction\n"
"c - char\n"
"s - string\n"
"T - OSType\n"
"A - float as hex\n"
"\n"
"Size letters include:\n"
"b - 1 byte (byte)\n"
"h - 2 bytes (halfword)\n"
"w - 4 bytes (word)\n"
"g - 8 bytes (giant)\n"
"\n"
"Example formats:\n"
"32xb - show 32 1 byte hexadecimal integer values\n"
"16xh - show 16 2 byte hexadecimal integer values\n"
"64 - show 64 2 byte hexadecimal integer values (format and size "
"from the last format)\n"
"dw - show 1 4 byte decimal integer value\n";
}
static llvm::StringRef FormatHelpTextCallback() {
static std::string help_text;
if (!help_text.empty())
return help_text;
StreamString sstr;
sstr << "One of the format names (or one-character names) that can be used "
"to show a variable's value:\n";
for (Format f = eFormatDefault; f < kNumFormats; f = Format(f + 1)) {
if (f != eFormatDefault)
sstr.PutChar('\n');
char format_char = FormatManager::GetFormatAsFormatChar(f);
if (format_char)
sstr.Printf("'%c' or ", format_char);
sstr.Printf("\"%s\"", FormatManager::GetFormatAsCString(f));
}
sstr.Flush();
help_text = sstr.GetString();
return help_text;
Redesign of the interaction between Python and frozen objects: - introduced two new classes ValueObjectConstResultChild and ValueObjectConstResultImpl: the first one is a ValueObjectChild obtained from a ValueObjectConstResult, the second is a common implementation backend for VOCR and VOCRCh of method calls meant to read through pointers stored in frozen objects ; now such reads transparently move from host to target as required - as a consequence of the above, removed code that made target-memory copies of expression results in several places throughout LLDB, and also removed code that enabled to recognize an expression result VO as such - introduced a new GetPointeeData() method in ValueObject that lets you read a given amount of objects of type T from a VO representing a T* or T[], and doing dereferences transparently in private layer it returns a DataExtractor ; in public layer it returns an instance of a newly created lldb::SBData - as GetPointeeData() does the right thing for both frozen and non-frozen ValueObject's, reimplemented ReadPointedString() to use it en lieu of doing the raw read itself - introduced a new GetData() method in ValueObject that lets you get a copy of the data that backs the ValueObject (for pointers, this returns the address without any previous dereferencing steps ; for arrays it actually reads the whole chunk of memory) in public layer this returns an SBData, just like GetPointeeData() - introduced a new CreateValueFromData() method in SBValue that lets you create a new SBValue from a chunk of data wrapped in an SBData the limitation to remember for this kind of SBValue is that they have no address: extracting the address-of for these objects (with any of GetAddress(), GetLoadAddress() and AddressOf()) will return invalid values - added several tests to check that "p"-ing objects (STL classes, char* and char[]) will do the right thing Solved a bug where global pointers to global variables were not dereferenced correctly for display New target setting "max-string-summary-length" gives the maximum number of characters to show in a string when summarizing it, instead of the hardcoded 128 Solved a bug where the summary for char[] and char* would not be shown if the ValueObject's were dumped via the "p" command Removed m_pointers_point_to_load_addrs from ValueObject. Introduced a new m_address_type_of_children, which each ValueObject can set to tell the address type of any pointers and/or references it creates. In the current codebase, this is load address most of the time (the only notable exception being file addresses that generate file address children UNLESS we have a live process) Updated help text for summary-string Fixed an issue in STL formatters where std::stlcontainer::iterator would match the container's synthetic children providers Edited the syntax and help for some commands to have proper argument types llvm-svn: 139160
2011-09-07 03:20:51 +08:00
}
static llvm::StringRef LanguageTypeHelpTextCallback() {
static std::string help_text;
if (!help_text.empty())
return help_text;
StreamString sstr;
sstr << "One of the following languages:\n";
Language::PrintAllLanguages(sstr, " ", "\n");
sstr.Flush();
help_text = sstr.GetString();
return help_text;
}
static llvm::StringRef SummaryStringHelpTextCallback() {
return "A summary string is a way to extract information from variables in "
"order to present them using a summary.\n"
"Summary strings contain static text, variables, scopes and control "
"sequences:\n"
" - Static text can be any sequence of non-special characters, i.e. "
"anything but '{', '}', '$', or '\\'.\n"
" - Variables are sequences of characters beginning with ${, ending "
"with } and that contain symbols in the format described below.\n"
" - Scopes are any sequence of text between { and }. Anything "
"included in a scope will only appear in the output summary if there "
"were no errors.\n"
" - Control sequences are the usual C/C++ '\\a', '\\n', ..., plus "
"'\\$', '\\{' and '\\}'.\n"
"A summary string works by copying static text verbatim, turning "
"control sequences into their character counterpart, expanding "
"variables and trying to expand scopes.\n"
"A variable is expanded by giving it a value other than its textual "
"representation, and the way this is done depends on what comes after "
"the ${ marker.\n"
"The most common sequence if ${var followed by an expression path, "
"which is the text one would type to access a member of an aggregate "
"types, given a variable of that type"
" (e.g. if type T has a member named x, which has a member named y, "
"and if t is of type T, the expression path would be .x.y and the way "
"to fit that into a summary string would be"
" ${var.x.y}). You can also use ${*var followed by an expression path "
"and in that case the object referred by the path will be "
"dereferenced before being displayed."
" If the object is not a pointer, doing so will cause an error. For "
"additional details on expression paths, you can type 'help "
"expr-path'. \n"
"By default, summary strings attempt to display the summary for any "
"variable they reference, and if that fails the value. If neither can "
"be shown, nothing is displayed."
"In a summary string, you can also use an array index [n], or a "
"slice-like range [n-m]. This can have two different meanings "
"depending on what kind of object the expression"
" path refers to:\n"
" - if it is a scalar type (any basic type like int, float, ...) the "
"expression is a bitfield, i.e. the bits indicated by the indexing "
"operator are extracted out of the number"
" and displayed as an individual variable\n"
" - if it is an array or pointer the array items indicated by the "
"indexing operator are shown as the result of the variable. if the "
"expression is an array, real array items are"
" printed; if it is a pointer, the pointer-as-array syntax is used to "
"obtain the values (this means, the latter case can have no range "
"checking)\n"
"If you are trying to display an array for which the size is known, "
"you can also use [] instead of giving an exact range. This has the "
"effect of showing items 0 thru size - 1.\n"
"Additionally, a variable can contain an (optional) format code, as "
"in ${var.x.y%code}, where code can be any of the valid formats "
"described in 'help format', or one of the"
" special symbols only allowed as part of a variable:\n"
" %V: show the value of the object by default\n"
" %S: show the summary of the object by default\n"
" %@: show the runtime-provided object description (for "
"Objective-C, it calls NSPrintForDebugger; for C/C++ it does "
"nothing)\n"
" %L: show the location of the object (memory address or a "
"register name)\n"
" %#: show the number of children of the object\n"
" %T: show the type of the object\n"
"Another variable that you can use in summary strings is ${svar . "
"This sequence works exactly like ${var, including the fact that "
"${*svar is an allowed sequence, but uses"
" the object's synthetic children provider instead of the actual "
"objects. For instance, if you are using STL synthetic children "
"providers, the following summary string would"
" count the number of actual elements stored in an std::list:\n"
"type summary add -s \"${svar%#}\" -x \"std::list<\"";
}
static llvm::StringRef ExprPathHelpTextCallback() {
return "An expression path is the sequence of symbols that is used in C/C++ "
"to access a member variable of an aggregate object (class).\n"
"For instance, given a class:\n"
" class foo {\n"
" int a;\n"
" int b; .\n"
" foo* next;\n"
" };\n"
"the expression to read item b in the item pointed to by next for foo "
"aFoo would be aFoo.next->b.\n"
"Given that aFoo could just be any object of type foo, the string "
"'.next->b' is the expression path, because it can be attached to any "
"foo instance to achieve the effect.\n"
"Expression paths in LLDB include dot (.) and arrow (->) operators, "
"and most commands using expression paths have ways to also accept "
"the star (*) operator.\n"
"The meaning of these operators is the same as the usual one given to "
"them by the C/C++ standards.\n"
"LLDB also has support for indexing ([ ]) in expression paths, and "
"extends the traditional meaning of the square brackets operator to "
"allow bitfield extraction:\n"
"for objects of native types (int, float, char, ...) saying '[n-m]' "
"as an expression path (where n and m are any positive integers, e.g. "
"[3-5]) causes LLDB to extract"
" bits n thru m from the value of the variable. If n == m, [n] is "
"also allowed as a shortcut syntax. For arrays and pointers, "
"expression paths can only contain one index"
" and the meaning of the operation is the same as the one defined by "
"C/C++ (item extraction). Some commands extend bitfield-like syntax "
"for arrays and pointers with the"
" meaning of array slicing (taking elements n thru m inside the array "
"or pointed-to memory).";
}
void CommandObject::FormatLongHelpText(Stream &output_strm,
llvm::StringRef long_help) {
CommandInterpreter &interpreter = GetCommandInterpreter();
std::stringstream lineStream(long_help);
std::string line;
while (std::getline(lineStream, line)) {
if (line.empty()) {
output_strm << "\n";
continue;
}
size_t result = line.find_first_not_of(" \t");
if (result == std::string::npos) {
result = 0;
}
std::string whitespace_prefix = line.substr(0, result);
std::string remainder = line.substr(result);
interpreter.OutputFormattedHelpText(output_strm, whitespace_prefix.c_str(),
remainder.c_str());
}
}
void CommandObject::GenerateHelpText(CommandReturnObject &result) {
GenerateHelpText(result.GetOutputStream());
result.SetStatus(eReturnStatusSuccessFinishNoResult);
}
void CommandObject::GenerateHelpText(Stream &output_strm) {
CommandInterpreter &interpreter = GetCommandInterpreter();
if (WantsRawCommandString()) {
std::string help_text(GetHelp());
help_text.append(" Expects 'raw' input (see 'help raw-input'.)");
interpreter.OutputFormattedHelpText(output_strm, "", "", help_text.c_str(),
1);
} else
interpreter.OutputFormattedHelpText(output_strm, "", "", GetHelp(), 1);
output_strm << "\nSyntax: " << GetSyntax() << "\n";
Options *options = GetOptions();
if (options != nullptr) {
options->GenerateOptionUsage(
output_strm, this,
GetCommandInterpreter().GetDebugger().GetTerminalWidth());
}
llvm::StringRef long_help = GetHelpLong();
if (!long_help.empty()) {
FormatLongHelpText(output_strm, long_help);
}
if (!IsDashDashCommand() && options && options->NumCommandOptions() > 0) {
if (WantsRawCommandString() && !WantsCompletion()) {
// Emit the message about using ' -- ' between the end of the command
// options and the raw input conditionally, i.e., only if the command
// object does not want completion.
interpreter.OutputFormattedHelpText(
output_strm, "", "",
"\nImportant Note: Because this command takes 'raw' input, if you "
"use any command options"
" you must use ' -- ' between the end of the command options and the "
"beginning of the raw input.",
1);
} else if (GetNumArgumentEntries() > 0) {
// Also emit a warning about using "--" in case you are using a command
// that takes options and arguments.
interpreter.OutputFormattedHelpText(
output_strm, "", "",
"\nThis command takes options and free-form arguments. If your "
"arguments resemble"
" option specifiers (i.e., they start with a - or --), you must use "
"' -- ' between"
" the end of the command options and the beginning of the arguments.",
1);
}
}
}
void CommandObject::AddIDsArgumentData(CommandArgumentEntry &arg,
CommandArgumentType ID,
CommandArgumentType IDRange) {
CommandArgumentData id_arg;
CommandArgumentData id_range_arg;
// Create the first variant for the first (and only) argument for this
// command.
id_arg.arg_type = ID;
id_arg.arg_repetition = eArgRepeatOptional;
// Create the second variant for the first (and only) argument for this
// command.
id_range_arg.arg_type = IDRange;
id_range_arg.arg_repetition = eArgRepeatOptional;
// The first (and only) argument for this command could be either an id or an
// id_range. Push both variants into the entry for the first argument for
// this command.
arg.push_back(id_arg);
arg.push_back(id_range_arg);
}
const char *CommandObject::GetArgumentTypeAsCString(
const lldb::CommandArgumentType arg_type) {
assert(arg_type < eArgTypeLastArg &&
"Invalid argument type passed to GetArgumentTypeAsCString");
return g_arguments_data[arg_type].arg_name;
}
const char *CommandObject::GetArgumentDescriptionAsCString(
const lldb::CommandArgumentType arg_type) {
assert(arg_type < eArgTypeLastArg &&
"Invalid argument type passed to GetArgumentDescriptionAsCString");
return g_arguments_data[arg_type].help_text;
}
Target *CommandObject::GetDummyTarget() {
return m_interpreter.GetDebugger().GetDummyTarget();
}
Target *CommandObject::GetSelectedOrDummyTarget(bool prefer_dummy) {
return m_interpreter.GetDebugger().GetSelectedOrDummyTarget(prefer_dummy);
}
Thread *CommandObject::GetDefaultThread() {
Thread *thread_to_use = m_exe_ctx.GetThreadPtr();
if (thread_to_use)
return thread_to_use;
Process *process = m_exe_ctx.GetProcessPtr();
if (!process) {
Target *target = m_exe_ctx.GetTargetPtr();
if (!target) {
target = m_interpreter.GetDebugger().GetSelectedTarget().get();
}
if (target)
process = target->GetProcessSP().get();
}
if (process)
return process->GetThreadList().GetSelectedThread().get();
else
return nullptr;
}
bool CommandObjectParsed::Execute(const char *args_string,
CommandReturnObject &result) {
bool handled = false;
Args cmd_args(args_string);
if (HasOverrideCallback()) {
Args full_args(GetCommandName());
full_args.AppendArguments(cmd_args);
handled =
InvokeOverrideCallback(full_args.GetConstArgumentVector(), result);
}
if (!handled) {
for (auto entry : llvm::enumerate(cmd_args.entries())) {
if (!entry.value().ref.empty() && entry.value().ref.front() == '`') {
cmd_args.ReplaceArgumentAtIndex(
entry.index(),
m_interpreter.ProcessEmbeddedScriptCommands(entry.value().c_str()));
}
}
if (CheckRequirements(result)) {
if (ParseOptions(cmd_args, result)) {
// Call the command-specific version of 'Execute', passing it the
// already processed arguments.
handled = DoExecute(cmd_args, result);
}
}
Cleanup();
}
return handled;
}
bool CommandObjectRaw::Execute(const char *args_string,
CommandReturnObject &result) {
bool handled = false;
if (HasOverrideCallback()) {
std::string full_command(GetCommandName());
full_command += ' ';
full_command += args_string;
const char *argv[2] = {nullptr, nullptr};
argv[0] = full_command.c_str();
handled = InvokeOverrideCallback(argv, result);
}
if (!handled) {
if (CheckRequirements(result))
handled = DoExecute(args_string, result);
Cleanup();
}
return handled;
}
static llvm::StringRef arch_helper() {
static StreamString g_archs_help;
if (g_archs_help.Empty()) {
StringList archs;
ArchSpec::ListSupportedArchNames(archs);
g_archs_help.Printf("These are the supported architecture names:\n");
archs.Join("\n", g_archs_help);
}
return g_archs_help.GetString();
}
CommandObject::ArgumentTableEntry CommandObject::g_arguments_data[] = {
// clang-format off
{ eArgTypeAddress, "address", CommandCompletions::eNoCompletion, { nullptr, false }, "A valid address in the target program's execution space." },
{ eArgTypeAddressOrExpression, "address-expression", CommandCompletions::eNoCompletion, { nullptr, false }, "An expression that resolves to an address." },
{ eArgTypeAliasName, "alias-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of an abbreviation (alias) for a debugger command." },
{ eArgTypeAliasOptions, "options-for-aliased-command", CommandCompletions::eNoCompletion, { nullptr, false }, "Command options to be used as part of an alias (abbreviation) definition. (See 'help commands alias' for more information.)" },
{ eArgTypeArchitecture, "arch", CommandCompletions::eArchitectureCompletion, { arch_helper, true }, "The architecture name, e.g. i386 or x86_64." },
{ eArgTypeBoolean, "boolean", CommandCompletions::eNoCompletion, { nullptr, false }, "A Boolean value: 'true' or 'false'" },
{ eArgTypeBreakpointID, "breakpt-id", CommandCompletions::eNoCompletion, { BreakpointIDHelpTextCallback, false }, nullptr },
{ eArgTypeBreakpointIDRange, "breakpt-id-list", CommandCompletions::eNoCompletion, { BreakpointIDRangeHelpTextCallback, false }, nullptr },
{ eArgTypeBreakpointName, "breakpoint-name", CommandCompletions::eNoCompletion, { BreakpointNameHelpTextCallback, false }, nullptr },
{ eArgTypeByteSize, "byte-size", CommandCompletions::eNoCompletion, { nullptr, false }, "Number of bytes to use." },
{ eArgTypeClassName, "class-name", CommandCompletions::eNoCompletion, { nullptr, false }, "Then name of a class from the debug information in the program." },
{ eArgTypeCommandName, "cmd-name", CommandCompletions::eNoCompletion, { nullptr, false }, "A debugger command (may be multiple words), without any options or arguments." },
{ eArgTypeCount, "count", CommandCompletions::eNoCompletion, { nullptr, false }, "An unsigned integer." },
{ eArgTypeDirectoryName, "directory", CommandCompletions::eDiskDirectoryCompletion, { nullptr, false }, "A directory name." },
{ eArgTypeDisassemblyFlavor, "disassembly-flavor", CommandCompletions::eNoCompletion, { nullptr, false }, "A disassembly flavor recognized by your disassembly plugin. Currently the only valid options are \"att\" and \"intel\" for Intel targets" },
{ eArgTypeDescriptionVerbosity, "description-verbosity", CommandCompletions::eNoCompletion, { nullptr, false }, "How verbose the output of 'po' should be." },
{ eArgTypeEndAddress, "end-address", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
{ eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
{ eArgTypeExpressionPath, "expr-path", CommandCompletions::eNoCompletion, { ExprPathHelpTextCallback, true }, nullptr },
{ eArgTypeExprFormat, "expression-format", CommandCompletions::eNoCompletion, { nullptr, false }, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]" },
{ eArgTypeFilename, "filename", CommandCompletions::eDiskFileCompletion, { nullptr, false }, "The name of a file (can include path)." },
{ eArgTypeFormat, "format", CommandCompletions::eNoCompletion, { FormatHelpTextCallback, true }, nullptr },
{ eArgTypeFrameIndex, "frame-index", CommandCompletions::eNoCompletion, { nullptr, false }, "Index into a thread's list of frames." },
{ eArgTypeFullName, "fullname", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
{ eArgTypeFunctionName, "function-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a function." },
{ eArgTypeFunctionOrSymbol, "function-or-symbol", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a function or symbol." },
{ eArgTypeGDBFormat, "gdb-format", CommandCompletions::eNoCompletion, { GDBFormatHelpTextCallback, true }, nullptr },
{ eArgTypeHelpText, "help-text", CommandCompletions::eNoCompletion, { nullptr, false }, "Text to be used as help for some other entity in LLDB" },
{ eArgTypeIndex, "index", CommandCompletions::eNoCompletion, { nullptr, false }, "An index into a list." },
{ eArgTypeLanguage, "source-language", CommandCompletions::eNoCompletion, { LanguageTypeHelpTextCallback, true }, nullptr },
{ eArgTypeLineNum, "linenum", CommandCompletions::eNoCompletion, { nullptr, false }, "Line number in a source file." },
{ eArgTypeLogCategory, "log-category", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a category within a log channel, e.g. all (try \"log list\" to see a list of all channels and their categories." },
{ eArgTypeLogChannel, "log-channel", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a log channel, e.g. process.gdb-remote (try \"log list\" to see a list of all channels and their categories)." },
{ eArgTypeMethod, "method", CommandCompletions::eNoCompletion, { nullptr, false }, "A C++ method name." },
{ eArgTypeName, "name", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
{ eArgTypeNewPathPrefix, "new-path-prefix", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
{ eArgTypeNumLines, "num-lines", CommandCompletions::eNoCompletion, { nullptr, false }, "The number of lines to use." },
{ eArgTypeNumberPerLine, "number-per-line", CommandCompletions::eNoCompletion, { nullptr, false }, "The number of items per line to display." },
{ eArgTypeOffset, "offset", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
{ eArgTypeOldPathPrefix, "old-path-prefix", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
{ eArgTypeOneLiner, "one-line-command", CommandCompletions::eNoCompletion, { nullptr, false }, "A command that is entered as a single line of text." },
{ eArgTypePath, "path", CommandCompletions::eDiskFileCompletion, { nullptr, false }, "Path." },
{ eArgTypePermissionsNumber, "perms-numeric", CommandCompletions::eNoCompletion, { nullptr, false }, "Permissions given as an octal number (e.g. 755)." },
{ eArgTypePermissionsString, "perms=string", CommandCompletions::eNoCompletion, { nullptr, false }, "Permissions given as a string value (e.g. rw-r-xr--)." },
{ eArgTypePid, "pid", CommandCompletions::eNoCompletion, { nullptr, false }, "The process ID number." },
{ eArgTypePlugin, "plugin", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
{ eArgTypeProcessName, "process-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of the process." },
{ eArgTypePythonClass, "python-class", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a Python class." },
{ eArgTypePythonFunction, "python-function", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a Python function." },
{ eArgTypePythonScript, "python-script", CommandCompletions::eNoCompletion, { nullptr, false }, "Source code written in Python." },
{ eArgTypeQueueName, "queue-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of the thread queue." },
{ eArgTypeRegisterName, "register-name", CommandCompletions::eNoCompletion, { RegisterNameHelpTextCallback, true }, nullptr },
{ eArgTypeRegularExpression, "regular-expression", CommandCompletions::eNoCompletion, { nullptr, false }, "A regular expression." },
{ eArgTypeRunArgs, "run-args", CommandCompletions::eNoCompletion, { nullptr, false }, "Arguments to be passed to the target program when it starts executing." },
{ eArgTypeRunMode, "run-mode", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
{ eArgTypeScriptedCommandSynchronicity, "script-cmd-synchronicity", CommandCompletions::eNoCompletion, { nullptr, false }, "The synchronicity to use to run scripted commands with regard to LLDB event system." },
{ eArgTypeScriptLang, "script-language", CommandCompletions::eNoCompletion, { nullptr, false }, "The scripting language to be used for script-based commands. Currently only Python is valid." },
{ eArgTypeSearchWord, "search-word", CommandCompletions::eNoCompletion, { nullptr, false }, "Any word of interest for search purposes." },
{ eArgTypeSelector, "selector", CommandCompletions::eNoCompletion, { nullptr, false }, "An Objective-C selector name." },
{ eArgTypeSettingIndex, "setting-index", CommandCompletions::eNoCompletion, { nullptr, false }, "An index into a settings variable that is an array (try 'settings list' to see all the possible settings variables and their types)." },
{ eArgTypeSettingKey, "setting-key", CommandCompletions::eNoCompletion, { nullptr, false }, "A key into a settings variables that is a dictionary (try 'settings list' to see all the possible settings variables and their types)." },
{ eArgTypeSettingPrefix, "setting-prefix", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a settable internal debugger variable up to a dot ('.'), e.g. 'target.process.'" },
{ eArgTypeSettingVariableName, "setting-variable-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a settable internal debugger variable. Type 'settings list' to see a complete list of such variables." },
{ eArgTypeShlibName, "shlib-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a shared library." },
{ eArgTypeSourceFile, "source-file", CommandCompletions::eSourceFileCompletion, { nullptr, false }, "The name of a source file.." },
{ eArgTypeSortOrder, "sort-order", CommandCompletions::eNoCompletion, { nullptr, false }, "Specify a sort order when dumping lists." },
{ eArgTypeStartAddress, "start-address", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
{ eArgTypeSummaryString, "summary-string", CommandCompletions::eNoCompletion, { SummaryStringHelpTextCallback, true }, nullptr },
{ eArgTypeSymbol, "symbol", CommandCompletions::eSymbolCompletion, { nullptr, false }, "Any symbol name (function name, variable, argument, etc.)" },
{ eArgTypeThreadID, "thread-id", CommandCompletions::eNoCompletion, { nullptr, false }, "Thread ID number." },
{ eArgTypeThreadIndex, "thread-index", CommandCompletions::eNoCompletion, { nullptr, false }, "Index into the process' list of threads." },
{ eArgTypeThreadName, "thread-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The thread's name." },
{ eArgTypeTypeName, "type-name", CommandCompletions::eNoCompletion, { nullptr, false }, "A type name." },
{ eArgTypeUnsignedInteger, "unsigned-integer", CommandCompletions::eNoCompletion, { nullptr, false }, "An unsigned integer." },
{ eArgTypeUnixSignal, "unix-signal", CommandCompletions::eNoCompletion, { nullptr, false }, "A valid Unix signal name or number (e.g. SIGKILL, KILL or 9)." },
{ eArgTypeVarName, "variable-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a variable in your program." },
{ eArgTypeValue, "value", CommandCompletions::eNoCompletion, { nullptr, false }, "A value could be anything, depending on where and how it is used." },
{ eArgTypeWidth, "width", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
{ eArgTypeNone, "none", CommandCompletions::eNoCompletion, { nullptr, false }, "No help available for this." },
{ eArgTypePlatform, "platform-name", CommandCompletions::ePlatformPluginCompletion, { nullptr, false }, "The name of an installed platform plug-in . Type 'platform list' to see a complete list of installed platforms." },
{ eArgTypeWatchpointID, "watchpt-id", CommandCompletions::eNoCompletion, { nullptr, false }, "Watchpoint IDs are positive integers." },
{ eArgTypeWatchpointIDRange, "watchpt-id-list", CommandCompletions::eNoCompletion, { nullptr, false }, "For example, '1-3' or '1 to 3'." },
{ eArgTypeWatchType, "watch-type", CommandCompletions::eNoCompletion, { nullptr, false }, "Specify the type for a watchpoint." },
{ eArgRawInput, "raw-input", CommandCompletions::eNoCompletion, { nullptr, false }, "Free-form text passed to a command without prior interpretation, allowing spaces without requiring quotes. To pass arguments and free form text put two dashes ' -- ' between the last argument and any raw input." },
{ eArgTypeCommand, "command", CommandCompletions::eNoCompletion, { nullptr, false }, "An LLDB Command line command." }
// clang-format on
};
const CommandObject::ArgumentTableEntry *CommandObject::GetArgumentTable() {
// If this assertion fires, then the table above is out of date with the
// CommandArgumentType enumeration
assert((sizeof(CommandObject::g_arguments_data) /
sizeof(CommandObject::ArgumentTableEntry)) == eArgTypeLastArg);
return CommandObject::g_arguments_data;
}