diff options
Diffstat (limited to 'lldb/source/Commands')
57 files changed, 1821 insertions, 1033 deletions
diff --git a/lldb/source/Commands/CommandCompletions.cpp b/lldb/source/Commands/CommandCompletions.cpp index d9bee66b442a..48df77357201 100644 --- a/lldb/source/Commands/CommandCompletions.cpp +++ b/lldb/source/Commands/CommandCompletions.cpp @@ -1,4 +1,4 @@ -//===-- CommandCompletions.cpp ----------------------------------*- C++ -*-===// +//===-- CommandCompletions.cpp --------------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -18,6 +18,7 @@  #include "lldb/Interpreter/OptionValueProperties.h"  #include "lldb/Symbol/CompileUnit.h"  #include "lldb/Symbol/Variable.h" +#include "lldb/Target/RegisterContext.h"  #include "lldb/Utility/FileSpec.h"  #include "lldb/Utility/StreamString.h"  #include "lldb/Utility/TildeExpressionResolver.h" @@ -27,19 +28,17 @@  using namespace lldb_private; -CommandCompletions::CommonCompletionElement -    CommandCompletions::g_common_completions[] = { -        {eCustomCompletion, nullptr}, -        {eSourceFileCompletion, CommandCompletions::SourceFiles}, -        {eDiskFileCompletion, CommandCompletions::DiskFiles}, -        {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories}, -        {eSymbolCompletion, CommandCompletions::Symbols}, -        {eModuleCompletion, CommandCompletions::Modules}, -        {eSettingsNameCompletion, CommandCompletions::SettingsNames}, -        {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames}, -        {eArchitectureCompletion, CommandCompletions::ArchitectureNames}, -        {eVariablePathCompletion, CommandCompletions::VariablePath}, -        {eNoCompletion, nullptr} // This one has to be last in the list. +// This is the command completion callback that is used to complete the +// argument of the option it is bound to (in the OptionDefinition table +// below). +typedef void (*CompletionCallback)(CommandInterpreter &interpreter, +                                   CompletionRequest &request, +                                   // A search filter to limit the search... +                                   lldb_private::SearchFilter *searcher); + +struct CommonCompletionElement { +  uint32_t type; +  CompletionCallback callback;  };  bool CommandCompletions::InvokeCommonCompletionCallbacks( @@ -47,27 +46,245 @@ bool CommandCompletions::InvokeCommonCompletionCallbacks(      CompletionRequest &request, SearchFilter *searcher) {    bool handled = false; -  if (completion_mask & eCustomCompletion) -    return false; +  const CommonCompletionElement common_completions[] = { +      {eSourceFileCompletion, CommandCompletions::SourceFiles}, +      {eDiskFileCompletion, CommandCompletions::DiskFiles}, +      {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories}, +      {eSymbolCompletion, CommandCompletions::Symbols}, +      {eModuleCompletion, CommandCompletions::Modules}, +      {eSettingsNameCompletion, CommandCompletions::SettingsNames}, +      {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames}, +      {eArchitectureCompletion, CommandCompletions::ArchitectureNames}, +      {eVariablePathCompletion, CommandCompletions::VariablePath}, +      {eRegisterCompletion, CommandCompletions::Registers}, +      {eBreakpointCompletion, CommandCompletions::Breakpoints}, +      {eProcessPluginCompletion, CommandCompletions::ProcessPluginNames}, +      {eNoCompletion, nullptr} // This one has to be last in the list. +  };    for (int i = 0;; i++) { -    if (g_common_completions[i].type == eNoCompletion) +    if (common_completions[i].type == eNoCompletion)        break; -    else if ((g_common_completions[i].type & completion_mask) == -                 g_common_completions[i].type && -             g_common_completions[i].callback != nullptr) { +    else if ((common_completions[i].type & completion_mask) == +                 common_completions[i].type && +             common_completions[i].callback != nullptr) {        handled = true; -      g_common_completions[i].callback(interpreter, request, searcher); +      common_completions[i].callback(interpreter, request, searcher);      }    }    return handled;  } +namespace { +// The Completer class is a convenient base class for building searchers that +// go along with the SearchFilter passed to the standard Completer functions. +class Completer : public Searcher { +public: +  Completer(CommandInterpreter &interpreter, CompletionRequest &request) +      : m_interpreter(interpreter), m_request(request) {} + +  ~Completer() override = default; + +  CallbackReturn SearchCallback(SearchFilter &filter, SymbolContext &context, +                                Address *addr) override = 0; + +  lldb::SearchDepth GetDepth() override = 0; + +  virtual void DoCompletion(SearchFilter *filter) = 0; + +protected: +  CommandInterpreter &m_interpreter; +  CompletionRequest &m_request; + +private: +  Completer(const Completer &) = delete; +  const Completer &operator=(const Completer &) = delete; +}; +} // namespace + +// SourceFileCompleter implements the source file completer +namespace { +class SourceFileCompleter : public Completer { +public: +  SourceFileCompleter(CommandInterpreter &interpreter, +                      CompletionRequest &request) +      : Completer(interpreter, request), m_matching_files() { +    FileSpec partial_spec(m_request.GetCursorArgumentPrefix()); +    m_file_name = partial_spec.GetFilename().GetCString(); +    m_dir_name = partial_spec.GetDirectory().GetCString(); +  } + +  lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthCompUnit; } + +  Searcher::CallbackReturn SearchCallback(SearchFilter &filter, +                                          SymbolContext &context, +                                          Address *addr) override { +    if (context.comp_unit != nullptr) { +      const char *cur_file_name = +          context.comp_unit->GetPrimaryFile().GetFilename().GetCString(); +      const char *cur_dir_name = +          context.comp_unit->GetPrimaryFile().GetDirectory().GetCString(); + +      bool match = false; +      if (m_file_name && cur_file_name && +          strstr(cur_file_name, m_file_name) == cur_file_name) +        match = true; + +      if (match && m_dir_name && cur_dir_name && +          strstr(cur_dir_name, m_dir_name) != cur_dir_name) +        match = false; + +      if (match) { +        m_matching_files.AppendIfUnique(context.comp_unit->GetPrimaryFile()); +      } +    } +    return Searcher::eCallbackReturnContinue; +  } + +  void DoCompletion(SearchFilter *filter) override { +    filter->Search(*this); +    // Now convert the filelist to completions: +    for (size_t i = 0; i < m_matching_files.GetSize(); i++) { +      m_request.AddCompletion( +          m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString()); +    } +  } + +private: +  FileSpecList m_matching_files; +  const char *m_file_name; +  const char *m_dir_name; + +  SourceFileCompleter(const SourceFileCompleter &) = delete; +  const SourceFileCompleter &operator=(const SourceFileCompleter &) = delete; +}; +} // namespace + +static bool regex_chars(const char comp) { +  return llvm::StringRef("[](){}+.*|^$\\?").contains(comp); +} + +namespace { +class SymbolCompleter : public Completer { + +public: +  SymbolCompleter(CommandInterpreter &interpreter, CompletionRequest &request) +      : Completer(interpreter, request) { +    std::string regex_str; +    if (!m_request.GetCursorArgumentPrefix().empty()) { +      regex_str.append("^"); +      regex_str.append(std::string(m_request.GetCursorArgumentPrefix())); +    } else { +      // Match anything since the completion string is empty +      regex_str.append("."); +    } +    std::string::iterator pos = +        find_if(regex_str.begin() + 1, regex_str.end(), regex_chars); +    while (pos < regex_str.end()) { +      pos = regex_str.insert(pos, '\\'); +      pos = find_if(pos + 2, regex_str.end(), regex_chars); +    } +    m_regex = RegularExpression(regex_str); +  } + +  lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthModule; } + +  Searcher::CallbackReturn SearchCallback(SearchFilter &filter, +                                          SymbolContext &context, +                                          Address *addr) override { +    if (context.module_sp) { +      SymbolContextList sc_list; +      const bool include_symbols = true; +      const bool include_inlines = true; +      context.module_sp->FindFunctions(m_regex, include_symbols, +                                       include_inlines, sc_list); + +      SymbolContext sc; +      // Now add the functions & symbols to the list - only add if unique: +      for (uint32_t i = 0; i < sc_list.GetSize(); i++) { +        if (sc_list.GetContextAtIndex(i, sc)) { +          ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled); +          // Ensure that the function name matches the regex. This is more than +          // a sanity check. It is possible that the demangled function name +          // does not start with the prefix, for example when it's in an +          // anonymous namespace. +          if (!func_name.IsEmpty() && m_regex.Execute(func_name.GetStringRef())) +            m_match_set.insert(func_name); +        } +      } +    } +    return Searcher::eCallbackReturnContinue; +  } + +  void DoCompletion(SearchFilter *filter) override { +    filter->Search(*this); +    collection::iterator pos = m_match_set.begin(), end = m_match_set.end(); +    for (pos = m_match_set.begin(); pos != end; pos++) +      m_request.AddCompletion((*pos).GetCString()); +  } + +private: +  RegularExpression m_regex; +  typedef std::set<ConstString> collection; +  collection m_match_set; + +  SymbolCompleter(const SymbolCompleter &) = delete; +  const SymbolCompleter &operator=(const SymbolCompleter &) = delete; +}; +} // namespace + +namespace { +class ModuleCompleter : public Completer { +public: +  ModuleCompleter(CommandInterpreter &interpreter, CompletionRequest &request) +      : Completer(interpreter, request) { +    FileSpec partial_spec(m_request.GetCursorArgumentPrefix()); +    m_file_name = partial_spec.GetFilename().GetCString(); +    m_dir_name = partial_spec.GetDirectory().GetCString(); +  } + +  lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthModule; } + +  Searcher::CallbackReturn SearchCallback(SearchFilter &filter, +                                          SymbolContext &context, +                                          Address *addr) override { +    if (context.module_sp) { +      const char *cur_file_name = +          context.module_sp->GetFileSpec().GetFilename().GetCString(); +      const char *cur_dir_name = +          context.module_sp->GetFileSpec().GetDirectory().GetCString(); + +      bool match = false; +      if (m_file_name && cur_file_name && +          strstr(cur_file_name, m_file_name) == cur_file_name) +        match = true; + +      if (match && m_dir_name && cur_dir_name && +          strstr(cur_dir_name, m_dir_name) != cur_dir_name) +        match = false; + +      if (match) { +        m_request.AddCompletion(cur_file_name); +      } +    } +    return Searcher::eCallbackReturnContinue; +  } + +  void DoCompletion(SearchFilter *filter) override { filter->Search(*this); } + +private: +  const char *m_file_name; +  const char *m_dir_name; + +  ModuleCompleter(const ModuleCompleter &) = delete; +  const ModuleCompleter &operator=(const ModuleCompleter &) = delete; +}; +} // namespace +  void CommandCompletions::SourceFiles(CommandInterpreter &interpreter,                                       CompletionRequest &request,                                       SearchFilter *searcher) { -  // Find some way to switch "include support files..." -  SourceFileCompleter completer(interpreter, false, request); +  SourceFileCompleter completer(interpreter, request);    if (searcher == nullptr) {      lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); @@ -295,7 +512,7 @@ void CommandCompletions::SettingsNames(CommandInterpreter &interpreter,      if (properties_sp) {        StreamString strm;        properties_sp->DumpValue(nullptr, strm, OptionValue::eDumpOptionName); -      const std::string &str = strm.GetString(); +      const std::string &str = std::string(strm.GetString());        g_property_names.SplitIntoLines(str.c_str(), str.size());      }    } @@ -323,185 +540,57 @@ void CommandCompletions::VariablePath(CommandInterpreter &interpreter,    Variable::AutoComplete(interpreter.GetExecutionContext(), request);  } -CommandCompletions::Completer::Completer(CommandInterpreter &interpreter, -                                         CompletionRequest &request) -    : m_interpreter(interpreter), m_request(request) {} - -CommandCompletions::Completer::~Completer() = default; - -// SourceFileCompleter - -CommandCompletions::SourceFileCompleter::SourceFileCompleter( -    CommandInterpreter &interpreter, bool include_support_files, -    CompletionRequest &request) -    : CommandCompletions::Completer(interpreter, request), -      m_include_support_files(include_support_files), m_matching_files() { -  FileSpec partial_spec(m_request.GetCursorArgumentPrefix()); -  m_file_name = partial_spec.GetFilename().GetCString(); -  m_dir_name = partial_spec.GetDirectory().GetCString(); -} - -lldb::SearchDepth CommandCompletions::SourceFileCompleter::GetDepth() { -  return lldb::eSearchDepthCompUnit; -} - -Searcher::CallbackReturn -CommandCompletions::SourceFileCompleter::SearchCallback(SearchFilter &filter, -                                                        SymbolContext &context, -                                                        Address *addr) { -  if (context.comp_unit != nullptr) { -    if (m_include_support_files) { -      FileSpecList supporting_files = context.comp_unit->GetSupportFiles(); -      for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++) { -        const FileSpec &sfile_spec = -            supporting_files.GetFileSpecAtIndex(sfiles); -        const char *sfile_file_name = sfile_spec.GetFilename().GetCString(); -        const char *sfile_dir_name = sfile_spec.GetFilename().GetCString(); -        bool match = false; -        if (m_file_name && sfile_file_name && -            strstr(sfile_file_name, m_file_name) == sfile_file_name) -          match = true; -        if (match && m_dir_name && sfile_dir_name && -            strstr(sfile_dir_name, m_dir_name) != sfile_dir_name) -          match = false; - -        if (match) { -          m_matching_files.AppendIfUnique(sfile_spec); -        } -      } -    } else { -      const char *cur_file_name = -          context.comp_unit->GetPrimaryFile().GetFilename().GetCString(); -      const char *cur_dir_name = -          context.comp_unit->GetPrimaryFile().GetDirectory().GetCString(); - -      bool match = false; -      if (m_file_name && cur_file_name && -          strstr(cur_file_name, m_file_name) == cur_file_name) -        match = true; - -      if (match && m_dir_name && cur_dir_name && -          strstr(cur_dir_name, m_dir_name) != cur_dir_name) -        match = false; - -      if (match) { -        m_matching_files.AppendIfUnique(context.comp_unit->GetPrimaryFile()); -      } -    } -  } -  return Searcher::eCallbackReturnContinue; -} - -void CommandCompletions::SourceFileCompleter::DoCompletion( -    SearchFilter *filter) { -  filter->Search(*this); -  // Now convert the filelist to completions: -  for (size_t i = 0; i < m_matching_files.GetSize(); i++) { -    m_request.AddCompletion( -        m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString()); +void CommandCompletions::Registers(CommandInterpreter &interpreter, +                                   CompletionRequest &request, +                                   SearchFilter *searcher) { +  std::string reg_prefix = ""; +  if (request.GetCursorArgumentPrefix().startswith("$")) +    reg_prefix = "$"; + +  RegisterContext *reg_ctx = +      interpreter.GetExecutionContext().GetRegisterContext(); +  const size_t reg_num = reg_ctx->GetRegisterCount(); +  for (size_t reg_idx = 0; reg_idx < reg_num; ++reg_idx) { +    const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_idx); +    request.TryCompleteCurrentArg(reg_prefix + reg_info->name, +                                  reg_info->alt_name);    }  } -// SymbolCompleter - -static bool regex_chars(const char comp) { -  return llvm::StringRef("[](){}+.*|^$\\?").contains(comp); -} +void CommandCompletions::Breakpoints(CommandInterpreter &interpreter, +                                     CompletionRequest &request, +                                     SearchFilter *searcher) { +  lldb::TargetSP target = interpreter.GetDebugger().GetSelectedTarget(); +  if (!target) +    return; -CommandCompletions::SymbolCompleter::SymbolCompleter( -    CommandInterpreter &interpreter, CompletionRequest &request) -    : CommandCompletions::Completer(interpreter, request) { -  std::string regex_str; -  if (!m_request.GetCursorArgumentPrefix().empty()) { -    regex_str.append("^"); -    regex_str.append(m_request.GetCursorArgumentPrefix()); -  } else { -    // Match anything since the completion string is empty -    regex_str.append("."); -  } -  std::string::iterator pos = -      find_if(regex_str.begin() + 1, regex_str.end(), regex_chars); -  while (pos < regex_str.end()) { -    pos = regex_str.insert(pos, '\\'); -    pos = find_if(pos + 2, regex_str.end(), regex_chars); -  } -  m_regex = RegularExpression(regex_str); -} +  const BreakpointList &breakpoints = target->GetBreakpointList(); -lldb::SearchDepth CommandCompletions::SymbolCompleter::GetDepth() { -  return lldb::eSearchDepthModule; -} +  std::unique_lock<std::recursive_mutex> lock; +  target->GetBreakpointList().GetListMutex(lock); -Searcher::CallbackReturn CommandCompletions::SymbolCompleter::SearchCallback( -    SearchFilter &filter, SymbolContext &context, Address *addr) { -  if (context.module_sp) { -    SymbolContextList sc_list; -    const bool include_symbols = true; -    const bool include_inlines = true; -    context.module_sp->FindFunctions(m_regex, include_symbols, include_inlines, -                                     sc_list); - -    SymbolContext sc; -    // Now add the functions & symbols to the list - only add if unique: -    for (uint32_t i = 0; i < sc_list.GetSize(); i++) { -      if (sc_list.GetContextAtIndex(i, sc)) { -        ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled); -        // Ensure that the function name matches the regex. This is more than a -        // sanity check. It is possible that the demangled function name does -        // not start with the prefix, for example when it's in an anonymous -        // namespace. -        if (!func_name.IsEmpty() && m_regex.Execute(func_name.GetStringRef())) -          m_match_set.insert(func_name); -      } -    } -  } -  return Searcher::eCallbackReturnContinue; -} +  size_t num_breakpoints = breakpoints.GetSize(); +  if (num_breakpoints == 0) +    return; -void CommandCompletions::SymbolCompleter::DoCompletion(SearchFilter *filter) { -  filter->Search(*this); -  collection::iterator pos = m_match_set.begin(), end = m_match_set.end(); -  for (pos = m_match_set.begin(); pos != end; pos++) -    m_request.AddCompletion((*pos).GetCString()); -} +  for (size_t i = 0; i < num_breakpoints; ++i) { +    lldb::BreakpointSP bp = breakpoints.GetBreakpointAtIndex(i); -// ModuleCompleter -CommandCompletions::ModuleCompleter::ModuleCompleter( -    CommandInterpreter &interpreter, CompletionRequest &request) -    : CommandCompletions::Completer(interpreter, request) { -  FileSpec partial_spec(m_request.GetCursorArgumentPrefix()); -  m_file_name = partial_spec.GetFilename().GetCString(); -  m_dir_name = partial_spec.GetDirectory().GetCString(); -} +    StreamString s; +    bp->GetDescription(&s, lldb::eDescriptionLevelBrief); +    llvm::StringRef bp_info = s.GetString(); -lldb::SearchDepth CommandCompletions::ModuleCompleter::GetDepth() { -  return lldb::eSearchDepthModule; -} +    const size_t colon_pos = bp_info.find_first_of(':'); +    if (colon_pos != llvm::StringRef::npos) +      bp_info = bp_info.drop_front(colon_pos + 2); -Searcher::CallbackReturn CommandCompletions::ModuleCompleter::SearchCallback( -    SearchFilter &filter, SymbolContext &context, Address *addr) { -  if (context.module_sp) { -    const char *cur_file_name = -        context.module_sp->GetFileSpec().GetFilename().GetCString(); -    const char *cur_dir_name = -        context.module_sp->GetFileSpec().GetDirectory().GetCString(); - -    bool match = false; -    if (m_file_name && cur_file_name && -        strstr(cur_file_name, m_file_name) == cur_file_name) -      match = true; - -    if (match && m_dir_name && cur_dir_name && -        strstr(cur_dir_name, m_dir_name) != cur_dir_name) -      match = false; - -    if (match) { -      m_request.AddCompletion(cur_file_name); -    } +    request.TryCompleteCurrentArg(std::to_string(bp->GetID()), bp_info);    } -  return Searcher::eCallbackReturnContinue;  } -void CommandCompletions::ModuleCompleter::DoCompletion(SearchFilter *filter) { -  filter->Search(*this); -} +void CommandCompletions::ProcessPluginNames(CommandInterpreter &interpreter, +                                            CompletionRequest &request, +                                            SearchFilter *searcher) { +  PluginManager::AutoCompleteProcessName(request.GetCursorArgumentPrefix(), +                                         request); +}
\ No newline at end of file diff --git a/lldb/source/Commands/CommandObjectApropos.cpp b/lldb/source/Commands/CommandObjectApropos.cpp index 15a20737273d..6e1e1f061733 100644 --- a/lldb/source/Commands/CommandObjectApropos.cpp +++ b/lldb/source/Commands/CommandObjectApropos.cpp @@ -1,5 +1,4 @@ -//===-- CommandObjectApropos.cpp ---------------------------------*- C++ -//-*-===// +//===-- CommandObjectApropos.cpp ------------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Commands/CommandObjectApropos.h b/lldb/source/Commands/CommandObjectApropos.h index 37d86b17d1a2..042753f24032 100644 --- a/lldb/source/Commands/CommandObjectApropos.h +++ b/lldb/source/Commands/CommandObjectApropos.h @@ -7,8 +7,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectApropos_h_ -#define liblldb_CommandObjectApropos_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTAPROPOS_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTAPROPOS_H  #include "lldb/Interpreter/CommandObject.h" @@ -28,4 +28,4 @@ protected:  } // namespace lldb_private -#endif // liblldb_CommandObjectApropos_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTAPROPOS_H diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp index 7c4c50ecf3f9..be7ef8a1b60b 100644 --- a/lldb/source/Commands/CommandObjectBreakpoint.cpp +++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===// +//===-- CommandObjectBreakpoint.cpp ---------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -70,7 +70,7 @@ public:        m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);        break;      case 'C': -      m_commands.push_back(option_arg); +      m_commands.push_back(std::string(option_arg));        break;      case 'd':        m_bp_opts.SetEnabled(false); @@ -270,11 +270,11 @@ public:          break;        case 'b': -        m_func_names.push_back(option_arg); +        m_func_names.push_back(std::string(option_arg));          m_func_name_type_mask |= eFunctionNameTypeBase;          break; -      case 'C': +      case 'u':          if (option_arg.getAsInteger(0, m_column))            error.SetErrorStringWithFormat("invalid column number: %s",                                           option_arg.str().c_str()); @@ -320,7 +320,7 @@ public:          break;        case 'F': -        m_func_names.push_back(option_arg); +        m_func_names.push_back(std::string(option_arg));          m_func_name_type_mask |= eFunctionNameTypeFull;          break; @@ -383,18 +383,18 @@ public:        }        case 'M': -        m_func_names.push_back(option_arg); +        m_func_names.push_back(std::string(option_arg));          m_func_name_type_mask |= eFunctionNameTypeMethod;          break;        case 'n': -        m_func_names.push_back(option_arg); +        m_func_names.push_back(std::string(option_arg));          m_func_name_type_mask |= eFunctionNameTypeAuto;          break;        case 'N': {          if (BreakpointID::StringIsBreakpointName(option_arg, error)) -          m_breakpoint_names.push_back(option_arg); +          m_breakpoint_names.push_back(std::string(option_arg));          else            error.SetErrorStringWithFormat("Invalid breakpoint name: %s",                                           option_arg.str().c_str()); @@ -415,11 +415,11 @@ public:          break;        case 'p': -        m_source_text_regexp.assign(option_arg); +        m_source_text_regexp.assign(std::string(option_arg));          break;        case 'r': -        m_func_regexp.assign(option_arg); +        m_func_regexp.assign(std::string(option_arg));          break;        case 's': @@ -427,7 +427,7 @@ public:          break;        case 'S': -        m_func_names.push_back(option_arg); +        m_func_names.push_back(std::string(option_arg));          m_func_name_type_mask |= eFunctionNameTypeSelector;          break; @@ -441,7 +441,7 @@ public:        } break;        case 'X': -        m_source_regex_func_names.insert(option_arg); +        m_source_regex_func_names.insert(std::string(option_arg));          break;        default: @@ -620,8 +620,16 @@ protected:        RegularExpression regexp(m_options.m_func_regexp);        if (llvm::Error err = regexp.GetError()) {          result.AppendErrorWithFormat( -            "Function name regular expression could not be compiled: \"%s\"", +            "Function name regular expression could not be compiled: %s",              llvm::toString(std::move(err)).c_str()); +        // Check if the incorrect regex looks like a globbing expression and +        // warn the user about it. +        if (!m_options.m_func_regexp.empty()) { +          if (m_options.m_func_regexp[0] == '*' || +              m_options.m_func_regexp[0] == '?') +            result.AppendWarning( +                "Function name regex does not accept glob patterns."); +        }          result.SetStatus(eReturnStatusFailed);          return false;        } @@ -811,6 +819,14 @@ public:    ~CommandObjectBreakpointModify() override = default; +  void +  HandleArgumentCompletion(CompletionRequest &request, +                           OptionElementVector &opt_element_vector) override { +    CommandCompletions::InvokeCommonCompletionCallbacks( +        GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, +        request, nullptr); +  } +    Options *GetOptions() override { return &m_options; }  protected: @@ -877,6 +893,14 @@ public:    ~CommandObjectBreakpointEnable() override = default; +  void +  HandleArgumentCompletion(CompletionRequest &request, +                           OptionElementVector &opt_element_vector) override { +    CommandCompletions::InvokeCommonCompletionCallbacks( +        GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, +        request, nullptr); +  } +  protected:    bool DoExecute(Args &command, CommandReturnObject &result) override {      Target &target = GetSelectedOrDummyTarget(); @@ -985,6 +1009,14 @@ the second re-enables the first location.");    ~CommandObjectBreakpointDisable() override = default; +  void +  HandleArgumentCompletion(CompletionRequest &request, +                           OptionElementVector &opt_element_vector) override { +    CommandCompletions::InvokeCommonCompletionCallbacks( +        GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, +        request, nullptr); +  } +  protected:    bool DoExecute(Args &command, CommandReturnObject &result) override {      Target &target = GetSelectedOrDummyTarget(); @@ -1231,7 +1263,7 @@ public:        switch (short_option) {        case 'f': -        m_filename.assign(option_arg); +        m_filename.assign(std::string(option_arg));          break;        case 'l': @@ -1363,6 +1395,14 @@ public:    ~CommandObjectBreakpointDelete() override = default; +  void +  HandleArgumentCompletion(CompletionRequest &request, +                           OptionElementVector &opt_element_vector) override { +    CommandCompletions::InvokeCommonCompletionCallbacks( +        GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, +        request, nullptr); +  } +    Options *GetOptions() override { return &m_options; }    class CommandOptions : public Options { @@ -1730,6 +1770,14 @@ public:    ~CommandObjectBreakpointNameAdd() override = default; +  void +  HandleArgumentCompletion(CompletionRequest &request, +                           OptionElementVector &opt_element_vector) override { +    CommandCompletions::InvokeCommonCompletionCallbacks( +        GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, +        request, nullptr); +  } +    Options *GetOptions() override { return &m_option_group; }  protected: @@ -1809,6 +1857,14 @@ public:    ~CommandObjectBreakpointNameDelete() override = default; +  void +  HandleArgumentCompletion(CompletionRequest &request, +                           OptionElementVector &opt_element_vector) override { +    CommandCompletions::InvokeCommonCompletionCallbacks( +        GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, +        request, nullptr); +  } +    Options *GetOptions() override { return &m_option_group; }  protected: @@ -1978,14 +2034,7 @@ public:                              "Read and set the breakpoints previously saved to "                              "a file with \"breakpoint write\".  ",                              nullptr), -        m_options() { -    CommandArgumentEntry arg; -    CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, -                                      eArgTypeBreakpointIDRange); -    // Add the entry for the first argument for this command to the object's -    // arguments vector. -    m_arguments.push_back(arg); -  } +        m_options() {}    ~CommandObjectBreakpointRead() override = default; @@ -2004,7 +2053,7 @@ public:        switch (short_option) {        case 'f': -        m_filename.assign(option_arg); +        m_filename.assign(std::string(option_arg));          break;        case 'N': {          Status name_error; @@ -2013,7 +2062,7 @@ public:            error.SetErrorStringWithFormat("Invalid breakpoint name: %s",                                           name_error.AsCString());          } -        m_names.push_back(option_arg); +        m_names.push_back(std::string(option_arg));          break;        }        default: @@ -2107,6 +2156,14 @@ public:    ~CommandObjectBreakpointWrite() override = default; +  void +  HandleArgumentCompletion(CompletionRequest &request, +                           OptionElementVector &opt_element_vector) override { +    CommandCompletions::InvokeCommonCompletionCallbacks( +        GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, +        request, nullptr); +  } +    Options *GetOptions() override { return &m_options; }    class CommandOptions : public Options { @@ -2122,7 +2179,7 @@ public:        switch (short_option) {        case 'f': -        m_filename.assign(option_arg); +        m_filename.assign(std::string(option_arg));          break;        case 'a':          m_append = true; diff --git a/lldb/source/Commands/CommandObjectBreakpoint.h b/lldb/source/Commands/CommandObjectBreakpoint.h index b29bbc0a74fa..6625652b260b 100644 --- a/lldb/source/Commands/CommandObjectBreakpoint.h +++ b/lldb/source/Commands/CommandObjectBreakpoint.h @@ -6,9 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectBreakpoint_h_ -#define liblldb_CommandObjectBreakpoint_h_ - +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTBREAKPOINT_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTBREAKPOINT_H  #include "lldb/Breakpoint/BreakpointName.h"  #include "lldb/Interpreter/CommandObjectMultiword.h" @@ -46,4 +45,4 @@ private:  } // namespace lldb_private -#endif // liblldb_CommandObjectBreakpoint_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTBREAKPOINT_H diff --git a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp index bbd2ca570126..45df86589011 100644 --- a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp +++ b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectBreakpointCommand.cpp ----------------------*- C++ -*-===// +//===-- CommandObjectBreakpointCommand.cpp --------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -292,7 +292,7 @@ are no syntax errors may indicate that a function was declared but never called.        switch (short_option) {        case 'o':          m_use_one_liner = true; -        m_one_liner = option_arg; +        m_one_liner = std::string(option_arg);          break;        case 's': diff --git a/lldb/source/Commands/CommandObjectBreakpointCommand.h b/lldb/source/Commands/CommandObjectBreakpointCommand.h index fb246d47abfd..cb516d76ea37 100644 --- a/lldb/source/Commands/CommandObjectBreakpointCommand.h +++ b/lldb/source/Commands/CommandObjectBreakpointCommand.h @@ -6,8 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectBreakpointCommand_h_ -#define liblldb_CommandObjectBreakpointCommand_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTBREAKPOINTCOMMAND_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTBREAKPOINTCOMMAND_H  #include "lldb/Interpreter/CommandObjectMultiword.h" @@ -24,4 +24,4 @@ public:  } // namespace lldb_private -#endif // liblldb_CommandObjectBreakpointCommand_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTBREAKPOINTCOMMAND_H diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp index 388db6fad631..d77e69c6f6a6 100644 --- a/lldb/source/Commands/CommandObjectCommands.cpp +++ b/lldb/source/Commands/CommandObjectCommands.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectCommands.cpp -------------------------------*- C++ -*-===// +//===-- CommandObjectCommands.cpp -----------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -527,14 +527,13 @@ protected:      m_option_group.NotifyOptionParsingStarting(&exe_ctx);      OptionsWithRaw args_with_suffix(raw_command_line); -    const char *remainder = args_with_suffix.GetRawPart().c_str();      if (args_with_suffix.HasArgs())        if (!ParseOptionsAndNotify(args_with_suffix.GetArgs(), result,                                   m_option_group, exe_ctx))          return false; -    llvm::StringRef raw_command_string(remainder); +    llvm::StringRef raw_command_string = args_with_suffix.GetRawPart();      Args args(raw_command_string);      if (args.GetArgumentCount() < 2) { @@ -652,8 +651,8 @@ protected:      }      // Save these in std::strings since we're going to shift them off. -    const std::string alias_command(args[0].ref()); -    const std::string actual_command(args[1].ref()); +    const std::string alias_command(std::string(args[0].ref())); +    const std::string actual_command(std::string(args[1].ref()));      args.Shift(); // Shift the alias command word off the argument vector.      args.Shift(); // Shift the old command word off the argument vector. @@ -1007,7 +1006,7 @@ protected:            *this, nullptr));        if (io_handler_sp) { -        debugger.PushIOHandler(io_handler_sp); +        debugger.RunIOHandlerAsync(io_handler_sp);          result.SetStatus(eReturnStatusSuccessFinishNoResult);        }      } else { @@ -1114,12 +1113,12 @@ protected:      }      if (!check_only) { -      std::string regex(regex_sed.substr(first_separator_char_pos + 1, -                                         second_separator_char_pos - -                                             first_separator_char_pos - 1)); -      std::string subst(regex_sed.substr(second_separator_char_pos + 1, -                                         third_separator_char_pos - -                                             second_separator_char_pos - 1)); +      std::string regex(std::string(regex_sed.substr( +          first_separator_char_pos + 1, +          second_separator_char_pos - first_separator_char_pos - 1))); +      std::string subst(std::string(regex_sed.substr( +          second_separator_char_pos + 1, +          third_separator_char_pos - second_separator_char_pos - 1)));        m_regex_cmd_up->AddRegexCommand(regex.c_str(), subst.c_str());      }      return error; @@ -1150,10 +1149,10 @@ private:        switch (short_option) {        case 'h': -        m_help.assign(option_arg); +        m_help.assign(std::string(option_arg));          break;        case 's': -        m_syntax.assign(option_arg); +        m_syntax.assign(std::string(option_arg));          break;        default:          llvm_unreachable("Unimplemented option"); @@ -1171,14 +1170,9 @@ private:        return llvm::makeArrayRef(g_regex_options);      } -    // TODO: Convert these functions to return StringRefs. -    const char *GetHelp() { -      return (m_help.empty() ? nullptr : m_help.c_str()); -    } +    llvm::StringRef GetHelp() { return m_help; } -    const char *GetSyntax() { -      return (m_syntax.empty() ? nullptr : m_syntax.c_str()); -    } +    llvm::StringRef GetSyntax() { return m_syntax; }    protected:      // Instance variables to hold the values for command options. @@ -1526,15 +1520,15 @@ protected:        switch (short_option) {        case 'f':          if (!option_arg.empty()) -          m_funct_name = option_arg; +          m_funct_name = std::string(option_arg);          break;        case 'c':          if (!option_arg.empty()) -          m_class_name = option_arg; +          m_class_name = std::string(option_arg);          break;        case 'h':          if (!option_arg.empty()) -          m_short_help = option_arg; +          m_short_help = std::string(option_arg);          break;        case 's':          m_synchronicity = @@ -1627,7 +1621,6 @@ protected:      io_handler.SetIsDone(true);    } -protected:    bool DoExecute(Args &command, CommandReturnObject &result) override {      if (GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) {        result.AppendError("only scripting language supported for scripted " @@ -1643,7 +1636,7 @@ protected:      }      // Store the options in case we get multi-line input -    m_cmd_name = command[0].ref(); +    m_cmd_name = std::string(command[0].ref());      m_short_help.assign(m_options.m_short_help);      m_synchronicity = m_options.m_synchronicity; @@ -1773,6 +1766,16 @@ public:    ~CommandObjectCommandsScriptDelete() override = default; +  void +  HandleArgumentCompletion(CompletionRequest &request, +                           OptionElementVector &opt_element_vector) override { +    if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0) +      return; + +    for (const auto &c : m_interpreter.GetUserCommands()) +      request.TryCompleteCurrentArg(c.first, c.second->GetHelp()); +  } +  protected:    bool DoExecute(Args &command, CommandReturnObject &result) override { diff --git a/lldb/source/Commands/CommandObjectCommands.h b/lldb/source/Commands/CommandObjectCommands.h index dcf02f3a7da9..f418e5ba779b 100644 --- a/lldb/source/Commands/CommandObjectCommands.h +++ b/lldb/source/Commands/CommandObjectCommands.h @@ -7,8 +7,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectCommands_h_ -#define liblldb_CommandObjectCommands_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTCOMMANDS_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTCOMMANDS_H  #include "lldb/Interpreter/CommandObjectMultiword.h" @@ -25,4 +25,4 @@ public:  } // namespace lldb_private -#endif // liblldb_CommandObjectCommands_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTCOMMANDS_H diff --git a/lldb/source/Commands/CommandObjectDisassemble.cpp b/lldb/source/Commands/CommandObjectDisassemble.cpp index 63679e996e70..cf4d8ed04f81 100644 --- a/lldb/source/Commands/CommandObjectDisassemble.cpp +++ b/lldb/source/Commands/CommandObjectDisassemble.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectDisassemble.cpp ----------------------------*- C++ -*-===// +//===-- CommandObjectDisassemble.cpp --------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -21,8 +21,9 @@  #include "lldb/Target/StackFrame.h"  #include "lldb/Target/Target.h" -#define DEFAULT_DISASM_BYTE_SIZE 32 -#define DEFAULT_DISASM_NUM_INS 4 +static constexpr unsigned default_disasm_byte_size = 32; +static constexpr unsigned default_disasm_num_ins = 4; +static constexpr unsigned large_function_threshold = 8000;  using namespace lldb;  using namespace lldb_private; @@ -83,7 +84,7 @@ Status CommandObjectDisassemble::CommandOptions::SetOptionValue(    } break;    case 'n': -    func_name.assign(option_arg); +    func_name.assign(std::string(option_arg));      some_location_specified = true;      break; @@ -101,7 +102,7 @@ Status CommandObjectDisassemble::CommandOptions::SetOptionValue(      break;    case 'P': -    plugin_name.assign(option_arg); +    plugin_name.assign(std::string(option_arg));      break;    case 'F': { @@ -111,7 +112,7 @@ Status CommandObjectDisassemble::CommandOptions::SetOptionValue(                            llvm::Triple::x86 ||                        target_sp->GetArchitecture().GetTriple().getArch() ==                            llvm::Triple::x86_64)) { -      flavor_string.assign(option_arg); +      flavor_string.assign(std::string(option_arg));      } else        error.SetErrorStringWithFormat("Disassembler flavors are currently only "                                       "supported for x86 and x86_64 targets."); @@ -143,6 +144,10 @@ Status CommandObjectDisassemble::CommandOptions::SetOptionValue(      }    } break; +  case '\x01': +    force = true; +    break; +    default:      llvm_unreachable("Unimplemented option");    } @@ -186,6 +191,7 @@ void CommandObjectDisassemble::CommandOptions::OptionParsingStarting(    arch.Clear();    some_location_specified = false; +  force = false;  }  Status CommandObjectDisassemble::CommandOptions::OptionParsingFinished( @@ -214,6 +220,194 @@ CommandObjectDisassemble::CommandObjectDisassemble(  CommandObjectDisassemble::~CommandObjectDisassemble() = default; +llvm::Error CommandObjectDisassemble::CheckRangeSize(const AddressRange &range, +                                                     llvm::StringRef what) { +  if (m_options.num_instructions > 0 || m_options.force || +      range.GetByteSize() < large_function_threshold) +    return llvm::Error::success(); +  StreamString msg; +  msg << "Not disassembling " << what << " because it is very large "; +  range.Dump(&msg, &GetSelectedTarget(), Address::DumpStyleLoadAddress, +             Address::DumpStyleFileAddress); +  msg << ". To disassemble specify an instruction count limit, start/stop " +         "addresses or use the --force option."; +  return llvm::createStringError(llvm::inconvertibleErrorCode(), +                                 msg.GetString()); +} + +llvm::Expected<std::vector<AddressRange>> +CommandObjectDisassemble::GetContainingAddressRanges() { +  std::vector<AddressRange> ranges; +  const auto &get_range = [&](Address addr) { +    ModuleSP module_sp(addr.GetModule()); +    SymbolContext sc; +    bool resolve_tail_call_address = true; +    addr.GetModule()->ResolveSymbolContextForAddress( +        addr, eSymbolContextEverything, sc, resolve_tail_call_address); +    if (sc.function || sc.symbol) { +      AddressRange range; +      sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, +                         false, range); +      ranges.push_back(range); +    } +  }; + +  Target &target = GetSelectedTarget(); +  if (!target.GetSectionLoadList().IsEmpty()) { +    Address symbol_containing_address; +    if (target.GetSectionLoadList().ResolveLoadAddress( +            m_options.symbol_containing_addr, symbol_containing_address)) { +      get_range(symbol_containing_address); +    } +  } else { +    for (lldb::ModuleSP module_sp : target.GetImages().Modules()) { +      Address file_address; +      if (module_sp->ResolveFileAddress(m_options.symbol_containing_addr, +                                        file_address)) { +        get_range(file_address); +      } +    } +  } + +  if (ranges.empty()) { +    return llvm::createStringError( +        llvm::inconvertibleErrorCode(), +        "Could not find function bounds for address 0x%" PRIx64, +        m_options.symbol_containing_addr); +  } + +  if (llvm::Error err = CheckRangeSize(ranges[0], "the function")) +    return std::move(err); +  return ranges; +} + +llvm::Expected<std::vector<AddressRange>> +CommandObjectDisassemble::GetCurrentFunctionRanges() { +  StackFrame *frame = m_exe_ctx.GetFramePtr(); +  if (!frame) { +    return llvm::createStringError(llvm::inconvertibleErrorCode(), +                                   "Cannot disassemble around the current " +                                   "function without a selected frame.\n"); +  } +  SymbolContext sc( +      frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); +  AddressRange range; +  if (sc.function) +    range = sc.function->GetAddressRange(); +  else if (sc.symbol && sc.symbol->ValueIsAddress()) { +    range = {sc.symbol->GetAddress(), sc.symbol->GetByteSize()}; +  } else +    range = {frame->GetFrameCodeAddress(), default_disasm_byte_size}; + +  if (llvm::Error err = CheckRangeSize(range, "the current function")) +    return std::move(err); +  return std::vector<AddressRange>{range}; +} + +llvm::Expected<std::vector<AddressRange>> +CommandObjectDisassemble::GetCurrentLineRanges() { +  StackFrame *frame = m_exe_ctx.GetFramePtr(); +  if (!frame) { +    return llvm::createStringError(llvm::inconvertibleErrorCode(), +                                   "Cannot disassemble around the current " +                                   "line without a selected frame.\n"); +  } + +  LineEntry pc_line_entry( +      frame->GetSymbolContext(eSymbolContextLineEntry).line_entry); +  if (pc_line_entry.IsValid()) +    return std::vector<AddressRange>{pc_line_entry.range}; + +  // No line entry, so just disassemble around the current pc +  m_options.show_mixed = false; +  return GetPCRanges(); +} + +llvm::Expected<std::vector<AddressRange>> +CommandObjectDisassemble::GetNameRanges(CommandReturnObject &result) { +  ConstString name(m_options.func_name.c_str()); +  const bool include_symbols = true; +  const bool include_inlines = true; + +  // Find functions matching the given name. +  SymbolContextList sc_list; +  GetSelectedTarget().GetImages().FindFunctions( +      name, eFunctionNameTypeAuto, include_symbols, include_inlines, sc_list); + +  std::vector<AddressRange> ranges; +  llvm::Error range_errs = llvm::Error::success(); +  AddressRange range; +  const uint32_t scope = +      eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol; +  const bool use_inline_block_range = true; +  for (SymbolContext sc : sc_list.SymbolContexts()) { +    for (uint32_t range_idx = 0; +         sc.GetAddressRange(scope, range_idx, use_inline_block_range, range); +         ++range_idx) { +      if (llvm::Error err = CheckRangeSize(range, "a range")) +        range_errs = joinErrors(std::move(range_errs), std::move(err)); +      else +        ranges.push_back(range); +    } +  } +  if (ranges.empty()) { +    if (range_errs) +      return std::move(range_errs); +    return llvm::createStringError(llvm::inconvertibleErrorCode(), +                                   "Unable to find symbol with name '%s'.\n", +                                   name.GetCString()); +  } +  if (range_errs) +    result.AppendWarning(toString(std::move(range_errs))); +  return ranges; +} + +llvm::Expected<std::vector<AddressRange>> +CommandObjectDisassemble::GetPCRanges() { +  StackFrame *frame = m_exe_ctx.GetFramePtr(); +  if (!frame) { +    return llvm::createStringError(llvm::inconvertibleErrorCode(), +                                   "Cannot disassemble around the current " +                                   "PC without a selected frame.\n"); +  } + +  if (m_options.num_instructions == 0) { +    // Disassembling at the PC always disassembles some number of +    // instructions (not the whole function). +    m_options.num_instructions = default_disasm_num_ins; +  } +  return std::vector<AddressRange>{{frame->GetFrameCodeAddress(), 0}}; +} + +llvm::Expected<std::vector<AddressRange>> +CommandObjectDisassemble::GetStartEndAddressRanges() { +  addr_t size = 0; +  if (m_options.end_addr != LLDB_INVALID_ADDRESS) { +    if (m_options.end_addr <= m_options.start_addr) { +      return llvm::createStringError(llvm::inconvertibleErrorCode(), +                                     "End address before start address."); +    } +    size = m_options.end_addr - m_options.start_addr; +  } +  return std::vector<AddressRange>{{Address(m_options.start_addr), size}}; +} + +llvm::Expected<std::vector<AddressRange>> +CommandObjectDisassemble::GetRangesForSelectedMode( +    CommandReturnObject &result) { +  if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS) +    return CommandObjectDisassemble::GetContainingAddressRanges(); +  if (m_options.current_function) +    return CommandObjectDisassemble::GetCurrentFunctionRanges(); +  if (m_options.frame_line) +    return CommandObjectDisassemble::GetCurrentLineRanges(); +  if (!m_options.func_name.empty()) +    return CommandObjectDisassemble::GetNameRanges(result); +  if (m_options.start_addr != LLDB_INVALID_ADDRESS) +    return CommandObjectDisassemble::GetStartEndAddressRanges(); +  return CommandObjectDisassemble::GetPCRanges(); +} +  bool CommandObjectDisassemble::DoExecute(Args &command,                                           CommandReturnObject &result) {    Target *target = &GetSelectedTarget(); @@ -281,238 +475,44 @@ bool CommandObjectDisassemble::DoExecute(Args &command,    if (m_options.raw)      options |= Disassembler::eOptionRawOuput; -  if (!m_options.func_name.empty()) { -    ConstString name(m_options.func_name.c_str()); +  llvm::Expected<std::vector<AddressRange>> ranges = +      GetRangesForSelectedMode(result); +  if (!ranges) { +    result.AppendError(toString(ranges.takeError())); +    result.SetStatus(eReturnStatusFailed); +    return result.Succeeded(); +  } +  bool print_sc_header = ranges->size() > 1; +  for (AddressRange cur_range : *ranges) { +    Disassembler::Limit limit; +    if (m_options.num_instructions == 0) { +      limit = {Disassembler::Limit::Bytes, cur_range.GetByteSize()}; +      if (limit.value == 0) +        limit.value = default_disasm_byte_size; +    } else { +      limit = {Disassembler::Limit::Instructions, m_options.num_instructions}; +    }      if (Disassembler::Disassemble(              GetDebugger(), m_options.arch, plugin_name, flavor_string, -            m_exe_ctx, name, -            nullptr, // Module * -            m_options.num_instructions, m_options.show_mixed, +            m_exe_ctx, cur_range.GetBaseAddress(), limit, m_options.show_mixed,              m_options.show_mixed ? m_options.num_lines_context : 0, options,              result.GetOutputStream())) {        result.SetStatus(eReturnStatusSuccessFinishResult);      } else { -      result.AppendErrorWithFormat("Unable to find symbol with name '%s'.\n", -                                   name.GetCString()); -      result.SetStatus(eReturnStatusFailed); -    } -  } else { -    std::vector<AddressRange> ranges; -    AddressRange range; -    StackFrame *frame = m_exe_ctx.GetFramePtr(); -    if (m_options.frame_line) { -      if (frame == nullptr) { -        result.AppendError("Cannot disassemble around the current line without " -                           "a selected frame.\n"); -        result.SetStatus(eReturnStatusFailed); -        return false; -      } -      LineEntry pc_line_entry( -          frame->GetSymbolContext(eSymbolContextLineEntry).line_entry); -      if (pc_line_entry.IsValid()) { -        range = pc_line_entry.range; -      } else { -        m_options.at_pc = -            true; // No line entry, so just disassemble around the current pc -        m_options.show_mixed = false; -      } -    } else if (m_options.current_function) { -      if (frame == nullptr) { -        result.AppendError("Cannot disassemble around the current function " -                           "without a selected frame.\n"); -        result.SetStatus(eReturnStatusFailed); -        return false; -      } -      Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol; -      if (symbol) { -        range.GetBaseAddress() = symbol->GetAddress(); -        range.SetByteSize(symbol->GetByteSize()); -      } -    } - -    // Did the "m_options.frame_line" find a valid range already? If so skip -    // the rest... -    if (range.GetByteSize() == 0) { -      if (m_options.at_pc) { -        if (frame == nullptr) { -          result.AppendError("Cannot disassemble around the current PC without " -                             "a selected frame.\n"); -          result.SetStatus(eReturnStatusFailed); -          return false; -        } -        range.GetBaseAddress() = frame->GetFrameCodeAddress(); -        if (m_options.num_instructions == 0) { -          // Disassembling at the PC always disassembles some number of -          // instructions (not the whole function). -          m_options.num_instructions = DEFAULT_DISASM_NUM_INS; -        } -        ranges.push_back(range); +      if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS) { +        result.AppendErrorWithFormat( +            "Failed to disassemble memory in function at 0x%8.8" PRIx64 ".\n", +            m_options.symbol_containing_addr);        } else { -        range.GetBaseAddress().SetOffset(m_options.start_addr); -        if (range.GetBaseAddress().IsValid()) { -          if (m_options.end_addr != LLDB_INVALID_ADDRESS) { -            if (m_options.end_addr <= m_options.start_addr) { -              result.AppendErrorWithFormat( -                  "End address before start address.\n"); -              result.SetStatus(eReturnStatusFailed); -              return false; -            } -            range.SetByteSize(m_options.end_addr - m_options.start_addr); -          } -          ranges.push_back(range); -        } else { -          if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS && -              target) { -            if (!target->GetSectionLoadList().IsEmpty()) { -              bool failed = false; -              Address symbol_containing_address; -              if (target->GetSectionLoadList().ResolveLoadAddress( -                      m_options.symbol_containing_addr, -                      symbol_containing_address)) { -                ModuleSP module_sp(symbol_containing_address.GetModule()); -                SymbolContext sc; -                bool resolve_tail_call_address = true; // PC can be one past the -                                                       // address range of the -                                                       // function. -                module_sp->ResolveSymbolContextForAddress( -                    symbol_containing_address, eSymbolContextEverything, sc, -                    resolve_tail_call_address); -                if (sc.function || sc.symbol) { -                  sc.GetAddressRange(eSymbolContextFunction | -                                         eSymbolContextSymbol, -                                     0, false, range); -                } else { -                  failed = true; -                } -              } else { -                failed = true; -              } -              if (failed) { -                result.AppendErrorWithFormat( -                    "Could not find function bounds for address 0x%" PRIx64 -                    "\n", -                    m_options.symbol_containing_addr); -                result.SetStatus(eReturnStatusFailed); -                return false; -              } -              ranges.push_back(range); -            } else { -              for (lldb::ModuleSP module_sp : target->GetImages().Modules()) { -                lldb::addr_t file_addr = m_options.symbol_containing_addr; -                Address file_address; -                if (module_sp->ResolveFileAddress(file_addr, file_address)) { -                  SymbolContext sc; -                  bool resolve_tail_call_address = true; // PC can be one past -                                                         // the address range of -                                                         // the function. -                  module_sp->ResolveSymbolContextForAddress( -                      file_address, eSymbolContextEverything, sc, -                      resolve_tail_call_address); -                  if (sc.function || sc.symbol) { -                    sc.GetAddressRange(eSymbolContextFunction | -                                           eSymbolContextSymbol, -                                       0, false, range); -                    ranges.push_back(range); -                  } -                } -              } -            } -          } -        } -      } -    } else -      ranges.push_back(range); - -    if (m_options.num_instructions != 0) { -      if (ranges.empty()) { -        // The default action is to disassemble the current frame function. -        if (frame) { -          SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | -                                                   eSymbolContextSymbol)); -          if (sc.function) -            range.GetBaseAddress() = -                sc.function->GetAddressRange().GetBaseAddress(); -          else if (sc.symbol && sc.symbol->ValueIsAddress()) -            range.GetBaseAddress() = sc.symbol->GetAddress(); -          else -            range.GetBaseAddress() = frame->GetFrameCodeAddress(); -        } - -        if (!range.GetBaseAddress().IsValid()) { -          result.AppendError("invalid frame"); -          result.SetStatus(eReturnStatusFailed); -          return false; -        } -      } - -      bool print_sc_header = ranges.size() > 1; -      for (AddressRange cur_range : ranges) { -        if (Disassembler::Disassemble( -                GetDebugger(), m_options.arch, plugin_name, flavor_string, -                m_exe_ctx, cur_range.GetBaseAddress(), -                m_options.num_instructions, m_options.show_mixed, -                m_options.show_mixed ? m_options.num_lines_context : 0, options, -                result.GetOutputStream())) { -          result.SetStatus(eReturnStatusSuccessFinishResult); -        } else { -          if (m_options.start_addr != LLDB_INVALID_ADDRESS) -            result.AppendErrorWithFormat( -                "Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", -                m_options.start_addr); -          else if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS) -            result.AppendErrorWithFormat( -                "Failed to disassemble memory in function at 0x%8.8" PRIx64 -                ".\n", -                m_options.symbol_containing_addr); -          result.SetStatus(eReturnStatusFailed); -        } -      } -      if (print_sc_header) -        result.AppendMessage("\n"); -    } else { -      if (ranges.empty()) { -        // The default action is to disassemble the current frame function. -        if (frame) { -          SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | -                                                   eSymbolContextSymbol)); -          if (sc.function) -            range = sc.function->GetAddressRange(); -          else if (sc.symbol && sc.symbol->ValueIsAddress()) { -            range.GetBaseAddress() = sc.symbol->GetAddress(); -            range.SetByteSize(sc.symbol->GetByteSize()); -          } else -            range.GetBaseAddress() = frame->GetFrameCodeAddress(); -        } else { -          result.AppendError("invalid frame"); -          result.SetStatus(eReturnStatusFailed); -          return false; -        } -        ranges.push_back(range); -      } - -      bool print_sc_header = ranges.size() > 1; -      for (AddressRange cur_range : ranges) { -        if (cur_range.GetByteSize() == 0) -          cur_range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE); - -        if (Disassembler::Disassemble( -                GetDebugger(), m_options.arch, plugin_name, flavor_string, -                m_exe_ctx, cur_range, m_options.num_instructions, -                m_options.show_mixed, -                m_options.show_mixed ? m_options.num_lines_context : 0, options, -                result.GetOutputStream())) { -          result.SetStatus(eReturnStatusSuccessFinishResult); -        } else { -          result.AppendErrorWithFormat( -              "Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", -              cur_range.GetBaseAddress().GetLoadAddress(target)); -          result.SetStatus(eReturnStatusFailed); -        } -        if (print_sc_header) -          result.AppendMessage("\n"); +        result.AppendErrorWithFormat( +            "Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", +            cur_range.GetBaseAddress().GetLoadAddress(target));        } +      result.SetStatus(eReturnStatusFailed);      } +    if (print_sc_header) +      result.GetOutputStream() << "\n";    }    return result.Succeeded(); diff --git a/lldb/source/Commands/CommandObjectDisassemble.h b/lldb/source/Commands/CommandObjectDisassemble.h index 70193e914c7f..340bf648de17 100644 --- a/lldb/source/Commands/CommandObjectDisassemble.h +++ b/lldb/source/Commands/CommandObjectDisassemble.h @@ -6,8 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectDisassemble_h_ -#define liblldb_CommandObjectDisassemble_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTDISASSEMBLE_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTDISASSEMBLE_H  #include "lldb/Interpreter/CommandObject.h"  #include "lldb/Interpreter/Options.h" @@ -62,6 +62,7 @@ public:                                    // "at_pc".  This should be set      // in SetOptionValue if anything the selects a location is set.      lldb::addr_t symbol_containing_addr; +    bool force = false;    };    CommandObjectDisassemble(CommandInterpreter &interpreter); @@ -73,9 +74,22 @@ public:  protected:    bool DoExecute(Args &command, CommandReturnObject &result) override; +  llvm::Expected<std::vector<AddressRange>> +  GetRangesForSelectedMode(CommandReturnObject &result); + +  llvm::Expected<std::vector<AddressRange>> GetContainingAddressRanges(); +  llvm::Expected<std::vector<AddressRange>> GetCurrentFunctionRanges(); +  llvm::Expected<std::vector<AddressRange>> GetCurrentLineRanges(); +  llvm::Expected<std::vector<AddressRange>> +  GetNameRanges(CommandReturnObject &result); +  llvm::Expected<std::vector<AddressRange>> GetPCRanges(); +  llvm::Expected<std::vector<AddressRange>> GetStartEndAddressRanges(); + +  llvm::Error CheckRangeSize(const AddressRange &range, llvm::StringRef what); +    CommandOptions m_options;  };  } // namespace lldb_private -#endif // liblldb_CommandObjectDisassemble_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTDISASSEMBLE_H diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index db90dde98eff..b23adb087b49 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectExpression.cpp -----------------------------*- C++ -*-===// +//===-- CommandObjectExpression.cpp ---------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -311,7 +311,12 @@ void CommandObjectExpression::HandleCompletion(CompletionRequest &request) {      target = &GetDummyTarget();    unsigned cursor_pos = request.GetRawCursorPos(); -  llvm::StringRef code = request.GetRawLine(); +  // Get the full user input including the suffix. The suffix is necessary +  // as OptionsWithRaw will use it to detect if the cursor is cursor is in the +  // argument part of in the raw input part of the arguments. If we cut of +  // of the suffix then "expr -arg[cursor] --" would interpret the "-arg" as +  // the raw input (as the "--" is hidden in the suffix). +  llvm::StringRef code = request.GetRawLineWithUnusedSuffix();    const std::size_t original_code_size = code.size(); @@ -357,29 +362,13 @@ CanBeUsedForElementCountPrinting(ValueObject &valobj) {    return Status();  } -bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr, -                                                 Stream *output_stream, -                                                 Stream *error_stream, -                                                 CommandReturnObject *result) { -  // Don't use m_exe_ctx as this might be called asynchronously after the -  // command object DoExecute has finished when doing multi-line expression -  // that use an input reader... -  ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); - -  Target *target = exe_ctx.GetTargetPtr(); - -  if (!target) -    target = &GetDummyTarget(); - -  lldb::ValueObjectSP result_valobj_sp; -  bool keep_in_memory = true; -  StackFrame *frame = exe_ctx.GetFramePtr(); - +EvaluateExpressionOptions +CommandObjectExpression::GetEvalOptions(const Target &target) {    EvaluateExpressionOptions options;    options.SetCoerceToId(m_varobj_options.use_objc);    options.SetUnwindOnError(m_command_options.unwind_on_error);    options.SetIgnoreBreakpoints(m_command_options.ignore_breakpoints); -  options.SetKeepInMemory(keep_in_memory); +  options.SetKeepInMemory(true);    options.SetUseDynamic(m_varobj_options.use_dynamic);    options.SetTryAllThreads(m_command_options.try_all_threads);    options.SetDebug(m_command_options.debug); @@ -391,11 +380,12 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,    bool auto_apply_fixits;    if (m_command_options.auto_apply_fixits == eLazyBoolCalculate) -    auto_apply_fixits = target->GetEnableAutoApplyFixIts(); +    auto_apply_fixits = target.GetEnableAutoApplyFixIts();    else      auto_apply_fixits = m_command_options.auto_apply_fixits == eLazyBoolYes;    options.SetAutoApplyFixIts(auto_apply_fixits); +  options.SetRetriesWithFixIts(target.GetNumberOfRetriesWithFixits());    if (m_command_options.top_level)      options.SetExecutionPolicy(eExecutionPolicyTopLevel); @@ -410,17 +400,36 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,      options.SetTimeout(std::chrono::microseconds(m_command_options.timeout));    else      options.SetTimeout(llvm::None); +  return options; +} +bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr, +                                                 Stream &output_stream, +                                                 Stream &error_stream, +                                                 CommandReturnObject &result) { +  // Don't use m_exe_ctx as this might be called asynchronously after the +  // command object DoExecute has finished when doing multi-line expression +  // that use an input reader... +  ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); + +  Target *target = exe_ctx.GetTargetPtr(); + +  if (!target) +    target = &GetDummyTarget(); + +  lldb::ValueObjectSP result_valobj_sp; +  StackFrame *frame = exe_ctx.GetFramePtr(); + +  const EvaluateExpressionOptions options = GetEvalOptions(*target);    ExpressionResults success = target->EvaluateExpression(        expr, frame, result_valobj_sp, options, &m_fixed_expression);    // We only tell you about the FixIt if we applied it.  The compiler errors    // will suggest the FixIt if it parsed. -  if (error_stream && !m_fixed_expression.empty() && -      target->GetEnableNotifyAboutFixIts()) { +  if (!m_fixed_expression.empty() && target->GetEnableNotifyAboutFixIts()) {      if (success == eExpressionCompleted) -      error_stream->Printf("  Fix-it applied, fixed expression was: \n    %s\n", -                           m_fixed_expression.c_str()); +      error_stream.Printf("  Fix-it applied, fixed expression was: \n    %s\n", +                          m_fixed_expression.c_str());    }    if (result_valobj_sp) { @@ -434,10 +443,10 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,          if (m_varobj_options.elem_count > 0) {            Status error(CanBeUsedForElementCountPrinting(*result_valobj_sp));            if (error.Fail()) { -            result->AppendErrorWithFormat( +            result.AppendErrorWithFormat(                  "expression cannot be used with --element-count %s\n",                  error.AsCString("")); -            result->SetStatus(eReturnStatusFailed); +            result.SetStatus(eReturnStatusFailed);              return false;            }          } @@ -447,41 +456,39 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,          options.SetVariableFormatDisplayLanguage(              result_valobj_sp->GetPreferredDisplayLanguage()); -        result_valobj_sp->Dump(*output_stream, options); +        result_valobj_sp->Dump(output_stream, options); -        if (result) -          result->SetStatus(eReturnStatusSuccessFinishResult); +        result.SetStatus(eReturnStatusSuccessFinishResult);        }      } else {        if (result_valobj_sp->GetError().GetError() ==            UserExpression::kNoResult) {          if (format != eFormatVoid && GetDebugger().GetNotifyVoid()) { -          error_stream->PutCString("(void)\n"); +          error_stream.PutCString("(void)\n");          } -        if (result) -          result->SetStatus(eReturnStatusSuccessFinishResult); +        result.SetStatus(eReturnStatusSuccessFinishResult);        } else {          const char *error_cstr = result_valobj_sp->GetError().AsCString();          if (error_cstr && error_cstr[0]) {            const size_t error_cstr_len = strlen(error_cstr);            const bool ends_with_newline = error_cstr[error_cstr_len - 1] == '\n';            if (strstr(error_cstr, "error:") != error_cstr) -            error_stream->PutCString("error: "); -          error_stream->Write(error_cstr, error_cstr_len); +            error_stream.PutCString("error: "); +          error_stream.Write(error_cstr, error_cstr_len);            if (!ends_with_newline) -            error_stream->EOL(); +            error_stream.EOL();          } else { -          error_stream->PutCString("error: unknown error\n"); +          error_stream.PutCString("error: unknown error\n");          } -        if (result) -          result->SetStatus(eReturnStatusFailed); +        result.SetStatus(eReturnStatusFailed);        }      }    } -  return true; +  return (success != eExpressionSetupError && +          success != eExpressionParseError);  }  void CommandObjectExpression::IOHandlerInputComplete(IOHandler &io_handler, @@ -493,7 +500,9 @@ void CommandObjectExpression::IOHandlerInputComplete(IOHandler &io_handler,    StreamFileSP output_sp = io_handler.GetOutputStreamFileSP();    StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); -  EvaluateExpression(line.c_str(), output_sp.get(), error_sp.get()); +  CommandReturnObject return_obj( +      GetCommandInterpreter().GetDebugger().GetUseColor()); +  EvaluateExpression(line.c_str(), *output_sp, *error_sp, return_obj);    if (output_sp)      output_sp->Flush();    if (error_sp) @@ -535,7 +544,7 @@ void CommandObjectExpression::GetMultilineExpression() {          "Enter expressions, then terminate with an empty line to evaluate:\n");      output_sp->Flush();    } -  debugger.PushIOHandler(io_handler_sp); +  debugger.RunIOHandlerAsync(io_handler_sp);  }  static EvaluateExpressionOptions @@ -622,10 +631,8 @@ bool CommandObjectExpression::DoExecute(llvm::StringRef command,            }            IOHandlerSP io_handler_sp(repl_sp->GetIOHandler()); -            io_handler_sp->SetIsDone(false); - -          debugger.PushIOHandler(io_handler_sp); +          debugger.RunIOHandlerAsync(io_handler_sp);          } else {            repl_error.SetErrorStringWithFormat(                "Couldn't create a REPL for %s", @@ -643,8 +650,8 @@ bool CommandObjectExpression::DoExecute(llvm::StringRef command,    }    Target &target = GetSelectedOrDummyTarget(); -  if (EvaluateExpression(expr, &(result.GetOutputStream()), -                         &(result.GetErrorStream()), &result)) { +  if (EvaluateExpression(expr, result.GetOutputStream(), +                         result.GetErrorStream(), result)) {      if (!m_fixed_expression.empty() && target.GetEnableNotifyAboutFixIts()) {        CommandHistory &history = m_interpreter.GetCommandHistory(); @@ -654,7 +661,7 @@ bool CommandObjectExpression::DoExecute(llvm::StringRef command,        std::string fixed_command("expression ");        if (args.HasArgs()) {          // Add in any options that might have been in the original command: -        fixed_command.append(args.GetArgStringWithDelimiter()); +        fixed_command.append(std::string(args.GetArgStringWithDelimiter()));          fixed_command.append(m_fixed_expression);        } else          fixed_command.append(m_fixed_expression); diff --git a/lldb/source/Commands/CommandObjectExpression.h b/lldb/source/Commands/CommandObjectExpression.h index de159863b43a..1e59cbc14528 100644 --- a/lldb/source/Commands/CommandObjectExpression.h +++ b/lldb/source/Commands/CommandObjectExpression.h @@ -6,15 +6,17 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectExpression_h_ -#define liblldb_CommandObjectExpression_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTEXPRESSION_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTEXPRESSION_H  #include "lldb/Core/IOHandler.h"  #include "lldb/Interpreter/CommandObject.h"  #include "lldb/Interpreter/OptionGroupBoolean.h"  #include "lldb/Interpreter/OptionGroupFormat.h"  #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" +#include "lldb/Target/Target.h"  #include "lldb/lldb-private-enumerations.h" +  namespace lldb_private {  class CommandObjectExpression : public CommandObjectRaw, @@ -65,9 +67,22 @@ protected:    bool DoExecute(llvm::StringRef command, CommandReturnObject &result) override; -  bool EvaluateExpression(llvm::StringRef expr, Stream *output_stream, -                          Stream *error_stream, -                          CommandReturnObject *result = nullptr); +  /// Return the appropriate expression options used for evaluating the +  /// expression in the given target. +  EvaluateExpressionOptions GetEvalOptions(const Target &target); + +  /// Evaluates the given expression. +  /// \param output_stream The stream to which the evaluation result will be +  ///                      printed. +  /// \param error_stream Contains error messages that should be displayed to +  ///                     the user in case the evaluation fails. +  /// \param result A CommandReturnObject which status will be set to the +  ///               appropriate value depending on evaluation success and +  ///               whether the expression produced any result. +  /// \return Returns true iff the expression was successfully evaluated, +  ///         executed and the result could be printed to the output stream. +  bool EvaluateExpression(llvm::StringRef expr, Stream &output_stream, +                          Stream &error_stream, CommandReturnObject &result);    void GetMultilineExpression(); @@ -83,4 +98,4 @@ protected:  } // namespace lldb_private -#endif // liblldb_CommandObjectExpression_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTEXPRESSION_H diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp index 50d5c751de5c..6ebad9b5c488 100644 --- a/lldb/source/Commands/CommandObjectFrame.cpp +++ b/lldb/source/Commands/CommandObjectFrame.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectFrame.cpp ----------------------------------*- C++ -*-===// +//===-- CommandObjectFrame.cpp --------------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -12,7 +12,6 @@  #include "lldb/DataFormatters/ValueObjectPrinter.h"  #include "lldb/Host/Config.h"  #include "lldb/Host/OptionParser.h" -#include "lldb/Host/StringConvert.h"  #include "lldb/Interpreter/CommandInterpreter.h"  #include "lldb/Interpreter/CommandReturnObject.h"  #include "lldb/Interpreter/OptionGroupFormat.h" @@ -172,8 +171,7 @@ protected:                       Stream &stream) -> bool {        const ValueObject::GetExpressionPathFormat format = ValueObject::            GetExpressionPathFormat::eGetExpressionPathFormatHonorPointers; -      const bool qualify_cxx_base_classes = false; -      valobj_sp->GetExpressionPath(stream, qualify_cxx_base_classes, format); +      valobj_sp->GetExpressionPath(stream, format);        stream.PutCString(" =");        return true;      }; @@ -187,7 +185,6 @@ protected:      return true;    } -protected:    CommandOptions m_options;  }; @@ -291,6 +288,22 @@ public:    ~CommandObjectFrameSelect() override = default; +  void +  HandleArgumentCompletion(CompletionRequest &request, +                           OptionElementVector &opt_element_vector) override { +    if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0) +      return; + +    lldb::ThreadSP thread_sp = m_exe_ctx.GetThreadSP(); +    const uint32_t frame_num = thread_sp->GetStackFrameCount(); +    for (uint32_t i = 0; i < frame_num; ++i) { +      lldb::StackFrameSP frame_sp = thread_sp->GetStackFrameAtIndex(i); +      StreamString strm; +      frame_sp->Dump(&strm, false, true); +      request.TryCompleteCurrentArg(std::to_string(i), strm.GetString()); +    } +  } +    Options *GetOptions() override { return &m_options; }  protected: @@ -380,7 +393,6 @@ protected:      return result.Succeeded();    } -protected:    CommandOptions m_options;  }; @@ -715,7 +727,6 @@ protected:      return res;    } -protected:    OptionGroupOptions m_option_group;    OptionGroupVariable m_option_variable;    OptionGroupFormat m_option_format; @@ -747,7 +758,7 @@ private:          m_module = std::string(option_arg);          break;        case 'n': -        m_function = std::string(option_arg); +        m_symbols.push_back(std::string(option_arg));          break;        case 'x':          m_regex = true; @@ -761,7 +772,7 @@ private:      void OptionParsingStarting(ExecutionContext *execution_context) override {        m_module = ""; -      m_function = ""; +      m_symbols.clear();        m_class_name = "";        m_regex = false;      } @@ -773,7 +784,7 @@ private:      // Instance variables to hold the values for command options.      std::string m_class_name;      std::string m_module; -    std::string m_function; +    std::vector<std::string> m_symbols;      bool m_regex;    }; @@ -855,9 +866,18 @@ bool CommandObjectFrameRecognizerAdd::DoExecute(Args &command,      return false;    } -  if (m_options.m_function.empty()) { -    result.AppendErrorWithFormat("%s needs a function name (-n argument).\n", -                                 m_cmd_name.c_str()); +  if (m_options.m_symbols.empty()) { +    result.AppendErrorWithFormat( +        "%s needs at least one symbol name (-n argument).\n", +        m_cmd_name.c_str()); +    result.SetStatus(eReturnStatusFailed); +    return false; +  } + +  if (m_options.m_regex && m_options.m_symbols.size() > 1) { +    result.AppendErrorWithFormat( +        "%s needs only one symbol regular expression (-n argument).\n", +        m_cmd_name.c_str());      result.SetStatus(eReturnStatusFailed);      return false;    } @@ -877,12 +897,13 @@ bool CommandObjectFrameRecognizerAdd::DoExecute(Args &command,      auto module =          RegularExpressionSP(new RegularExpression(m_options.m_module));      auto func = -        RegularExpressionSP(new RegularExpression(m_options.m_function)); +        RegularExpressionSP(new RegularExpression(m_options.m_symbols.front()));      StackFrameRecognizerManager::AddRecognizer(recognizer_sp, module, func);    } else {      auto module = ConstString(m_options.m_module); -    auto func = ConstString(m_options.m_function); -    StackFrameRecognizerManager::AddRecognizer(recognizer_sp, module, func); +    std::vector<ConstString> symbols(m_options.m_symbols.begin(), +                                     m_options.m_symbols.end()); +    StackFrameRecognizerManager::AddRecognizer(recognizer_sp, module, symbols);    }  #endif @@ -914,6 +935,33 @@ public:    ~CommandObjectFrameRecognizerDelete() override = default; +  void +  HandleArgumentCompletion(CompletionRequest &request, +                           OptionElementVector &opt_element_vector) override { +    if (request.GetCursorIndex() != 0) +      return; + +    StackFrameRecognizerManager::ForEach( +        [&request](uint32_t rid, std::string rname, std::string module, +                   llvm::ArrayRef<lldb_private::ConstString> symbols, +                   bool regexp) { +          StreamString strm; +          if (rname.empty()) +            rname = "(internal)"; + +          strm << rname; +          if (!module.empty()) +            strm << ", module " << module; +          if (!symbols.empty()) +            for (auto &symbol : symbols) +              strm << ", symbol " << symbol; +          if (regexp) +            strm << " (regexp)"; + +          request.TryCompleteCurrentArg(std::to_string(rid), strm.GetString()); +        }); +  } +  protected:    bool DoExecute(Args &command, CommandReturnObject &result) override {      if (command.GetArgumentCount() == 0) { @@ -937,8 +985,13 @@ protected:        return false;      } -    uint32_t recognizer_id = -        StringConvert::ToUInt32(command.GetArgumentAtIndex(0), 0, 0); +    uint32_t recognizer_id; +    if (!llvm::to_integer(command.GetArgumentAtIndex(0), recognizer_id)) { +      result.AppendErrorWithFormat("'%s' is not a valid recognizer id.\n", +                                   command.GetArgumentAtIndex(0)); +      result.SetStatus(eReturnStatusFailed); +      return false; +    }      StackFrameRecognizerManager::RemoveRecognizerWithID(recognizer_id);      result.SetStatus(eReturnStatusSuccessFinishResult); @@ -959,14 +1012,26 @@ protected:    bool DoExecute(Args &command, CommandReturnObject &result) override {      bool any_printed = false;      StackFrameRecognizerManager::ForEach( -        [&result, &any_printed](uint32_t recognizer_id, std::string name, -                                std::string function, std::string symbol, -                                bool regexp) { -          if (name == "") +        [&result, &any_printed]( +            uint32_t recognizer_id, std::string name, std::string module, +            llvm::ArrayRef<ConstString> symbols, bool regexp) { +          Stream &stream = result.GetOutputStream(); + +          if (name.empty())              name = "(internal)"; -          result.GetOutputStream().Printf( -              "%d: %s, module %s, function %s%s\n", recognizer_id, name.c_str(), -              function.c_str(), symbol.c_str(), regexp ? " (regexp)" : ""); + +          stream << std::to_string(recognizer_id) << ": " << name; +          if (!module.empty()) +            stream << ", module " << module; +          if (!symbols.empty()) +            for (auto &symbol : symbols) +              stream << ", symbol " << symbol; +          if (regexp) +            stream << " (regexp)"; + +          stream.EOL(); +          stream.Flush(); +            any_printed = true;          }); @@ -1006,6 +1071,15 @@ public:  protected:    bool DoExecute(Args &command, CommandReturnObject &result) override { +    const char *frame_index_str = command.GetArgumentAtIndex(0); +    uint32_t frame_index; +    if (!llvm::to_integer(frame_index_str, frame_index)) { +      result.AppendErrorWithFormat("'%s' is not a valid frame index.", +                                   frame_index_str); +      result.SetStatus(eReturnStatusFailed); +      return false; +    } +      Process *process = m_exe_ctx.GetProcessPtr();      if (process == nullptr) {        result.AppendError("no process"); @@ -1025,8 +1099,6 @@ protected:        return false;      } -    uint32_t frame_index = -        StringConvert::ToUInt32(command.GetArgumentAtIndex(0), 0, 0);      StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_index);      if (!frame_sp) {        result.AppendErrorWithFormat("no frame with index %u", frame_index); diff --git a/lldb/source/Commands/CommandObjectFrame.h b/lldb/source/Commands/CommandObjectFrame.h index b2378f14290d..71cb94aa8f5a 100644 --- a/lldb/source/Commands/CommandObjectFrame.h +++ b/lldb/source/Commands/CommandObjectFrame.h @@ -6,8 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectFrame_h_ -#define liblldb_CommandObjectFrame_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTFRAME_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTFRAME_H  #include "lldb/Interpreter/CommandObjectMultiword.h" @@ -24,4 +24,4 @@ public:  } // namespace lldb_private -#endif // liblldb_CommandObjectFrame_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTFRAME_H diff --git a/lldb/source/Commands/CommandObjectGUI.cpp b/lldb/source/Commands/CommandObjectGUI.cpp index 67ddc68a169e..3f45a26de228 100644 --- a/lldb/source/Commands/CommandObjectGUI.cpp +++ b/lldb/source/Commands/CommandObjectGUI.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectGUI.cpp ------------------------------------*- C++ -*-===// +//===-- CommandObjectGUI.cpp ----------------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -35,7 +35,7 @@ bool CommandObjectGUI::DoExecute(Args &args, CommandReturnObject &result) {          input.GetIsInteractive()) {        IOHandlerSP io_handler_sp(new IOHandlerCursesGUI(debugger));        if (io_handler_sp) -        debugger.PushIOHandler(io_handler_sp); +        debugger.RunIOHandlerAsync(io_handler_sp);        result.SetStatus(eReturnStatusSuccessFinishResult);      } else {        result.AppendError("the gui command requires an interactive terminal."); @@ -47,7 +47,7 @@ bool CommandObjectGUI::DoExecute(Args &args, CommandReturnObject &result) {    }    return true;  #else -  result.AppendError("lldb was not build with gui support"); +  result.AppendError("lldb was not built with gui support");    return false;  #endif  } diff --git a/lldb/source/Commands/CommandObjectGUI.h b/lldb/source/Commands/CommandObjectGUI.h index a19aad18ec35..49bad49a957d 100644 --- a/lldb/source/Commands/CommandObjectGUI.h +++ b/lldb/source/Commands/CommandObjectGUI.h @@ -6,8 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectGUI_h_ -#define liblldb_CommandObjectGUI_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTGUI_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTGUI_H  #include "lldb/Interpreter/CommandObject.h" @@ -27,4 +27,4 @@ protected:  } // namespace lldb_private -#endif // liblldb_CommandObjectGUI_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTGUI_H diff --git a/lldb/source/Commands/CommandObjectHelp.cpp b/lldb/source/Commands/CommandObjectHelp.cpp index 6e908dc496a0..6dc1868a2aff 100644 --- a/lldb/source/Commands/CommandObjectHelp.cpp +++ b/lldb/source/Commands/CommandObjectHelp.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectHelp.cpp -----------------------------------*- C++ -*-===// +//===-- CommandObjectHelp.cpp ---------------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -107,7 +107,7 @@ bool CommandObjectHelp::DoExecute(Args &command, CommandReturnObject &result) {        // object that corresponds to the help command entered.        std::string sub_command;        for (auto &entry : command.entries().drop_front()) { -        sub_command = entry.ref(); +        sub_command = std::string(entry.ref());          matches.Clear();          if (sub_cmd_obj->IsAlias())            sub_cmd_obj = diff --git a/lldb/source/Commands/CommandObjectHelp.h b/lldb/source/Commands/CommandObjectHelp.h index 52a00ac79ff9..8f45db55666e 100644 --- a/lldb/source/Commands/CommandObjectHelp.h +++ b/lldb/source/Commands/CommandObjectHelp.h @@ -6,8 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectHelp_h_ -#define liblldb_CommandObjectHelp_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTHELP_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTHELP_H  #include "lldb/Host/OptionParser.h"  #include "lldb/Interpreter/CommandObject.h" @@ -84,4 +84,4 @@ private:  } // namespace lldb_private -#endif // liblldb_CommandObjectHelp_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTHELP_H diff --git a/lldb/source/Commands/CommandObjectLanguage.cpp b/lldb/source/Commands/CommandObjectLanguage.cpp index 35ce6e3193e8..e6d22ec4ae40 100644 --- a/lldb/source/Commands/CommandObjectLanguage.cpp +++ b/lldb/source/Commands/CommandObjectLanguage.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectLanguage.cpp -------------------------------*- C++ -*-===// +//===-- CommandObjectLanguage.cpp -----------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Commands/CommandObjectLanguage.h b/lldb/source/Commands/CommandObjectLanguage.h index 47079e219d03..7a280902a07e 100644 --- a/lldb/source/Commands/CommandObjectLanguage.h +++ b/lldb/source/Commands/CommandObjectLanguage.h @@ -6,8 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectLanguage_h_ -#define liblldb_CommandObjectLanguage_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTLANGUAGE_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTLANGUAGE_H  #include "lldb/Interpreter/CommandObjectMultiword.h" @@ -23,4 +23,4 @@ protected:  };  } // namespace lldb_private -#endif // liblldb_CommandObjectLanguage_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTLANGUAGE_H diff --git a/lldb/source/Commands/CommandObjectLog.cpp b/lldb/source/Commands/CommandObjectLog.cpp index 9bf0b30bc152..4016b07c91ed 100644 --- a/lldb/source/Commands/CommandObjectLog.cpp +++ b/lldb/source/Commands/CommandObjectLog.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectLog.cpp ------------------------------------*- C++ -*-===// +//===-- CommandObjectLog.cpp ----------------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -156,7 +156,7 @@ protected:      }      // Store into a std::string since we're about to shift the channel off. -    const std::string channel = args[0].ref(); +    const std::string channel = std::string(args[0].ref());      args.Shift(); // Shift off the channel      char log_file[PATH_MAX];      if (m_options.log_file) @@ -229,7 +229,7 @@ protected:        return false;      } -    const std::string channel = args[0].ref(); +    const std::string channel = std::string(args[0].ref());      args.Shift(); // Shift off the channel      if (channel == "all") {        Log::DisableAllLogChannels(); @@ -298,61 +298,170 @@ protected:    }  }; -class CommandObjectLogTimer : public CommandObjectParsed { +class CommandObjectLogTimerEnable : public CommandObjectParsed {  public:    // Constructors and Destructors -  CommandObjectLogTimer(CommandInterpreter &interpreter) -      : CommandObjectParsed(interpreter, "log timers", -                            "Enable, disable, dump, and reset LLDB internal " -                            "performance timers.", -                            "log timers < enable <depth> | disable | dump | " -                            "increment <bool> | reset >") {} +  CommandObjectLogTimerEnable(CommandInterpreter &interpreter) +      : CommandObjectParsed(interpreter, "log timers enable", +                            "enable LLDB internal performance timers", +                            "log timers enable <depth>") { +    CommandArgumentEntry arg; +    CommandArgumentData depth_arg; -  ~CommandObjectLogTimer() override = default; +    // Define the first (and only) variant of this arg. +    depth_arg.arg_type = eArgTypeCount; +    depth_arg.arg_repetition = eArgRepeatOptional; + +    // There is only one variant this argument could be; put it into the +    // argument entry. +    arg.push_back(depth_arg); + +    // Push the data for the first argument into the m_arguments vector. +    m_arguments.push_back(arg); +  } + +  ~CommandObjectLogTimerEnable() override = default; + +protected: +  bool DoExecute(Args &args, CommandReturnObject &result) override { +    result.SetStatus(eReturnStatusFailed); + +    if (args.GetArgumentCount() == 0) { +      Timer::SetDisplayDepth(UINT32_MAX); +      result.SetStatus(eReturnStatusSuccessFinishNoResult); +    } else if (args.GetArgumentCount() == 1) { +      uint32_t depth; +      if (args[0].ref().consumeInteger(0, depth)) { +        result.AppendError( +            "Could not convert enable depth to an unsigned integer."); +      } else { +        Timer::SetDisplayDepth(depth); +        result.SetStatus(eReturnStatusSuccessFinishNoResult); +      } +    } + +    if (!result.Succeeded()) { +      result.AppendError("Missing subcommand"); +      result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str()); +    } +    return result.Succeeded(); +  } +}; + +class CommandObjectLogTimerDisable : public CommandObjectParsed { +public: +  // Constructors and Destructors +  CommandObjectLogTimerDisable(CommandInterpreter &interpreter) +      : CommandObjectParsed(interpreter, "log timers disable", +                            "disable LLDB internal performance timers", +                            nullptr) {} + +  ~CommandObjectLogTimerDisable() override = default; + +protected: +  bool DoExecute(Args &args, CommandReturnObject &result) override { +    Timer::DumpCategoryTimes(&result.GetOutputStream()); +    Timer::SetDisplayDepth(0); +    result.SetStatus(eReturnStatusSuccessFinishResult); + +    if (!result.Succeeded()) { +      result.AppendError("Missing subcommand"); +      result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str()); +    } +    return result.Succeeded(); +  } +}; + +class CommandObjectLogTimerDump : public CommandObjectParsed { +public: +  // Constructors and Destructors +  CommandObjectLogTimerDump(CommandInterpreter &interpreter) +      : CommandObjectParsed(interpreter, "log timers dump", +                            "dump LLDB internal performance timers", nullptr) {} + +  ~CommandObjectLogTimerDump() override = default; + +protected: +  bool DoExecute(Args &args, CommandReturnObject &result) override { +    Timer::DumpCategoryTimes(&result.GetOutputStream()); +    result.SetStatus(eReturnStatusSuccessFinishResult); + +    if (!result.Succeeded()) { +      result.AppendError("Missing subcommand"); +      result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str()); +    } +    return result.Succeeded(); +  } +}; + +class CommandObjectLogTimerReset : public CommandObjectParsed { +public: +  // Constructors and Destructors +  CommandObjectLogTimerReset(CommandInterpreter &interpreter) +      : CommandObjectParsed(interpreter, "log timers reset", +                            "reset LLDB internal performance timers", nullptr) { +  } + +  ~CommandObjectLogTimerReset() override = default; + +protected: +  bool DoExecute(Args &args, CommandReturnObject &result) override { +    Timer::ResetCategoryTimes(); +    result.SetStatus(eReturnStatusSuccessFinishResult); + +    if (!result.Succeeded()) { +      result.AppendError("Missing subcommand"); +      result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str()); +    } +    return result.Succeeded(); +  } +}; + +class CommandObjectLogTimerIncrement : public CommandObjectParsed { +public: +  // Constructors and Destructors +  CommandObjectLogTimerIncrement(CommandInterpreter &interpreter) +      : CommandObjectParsed(interpreter, "log timers increment", +                            "increment LLDB internal performance timers", +                            "log timers increment <bool>") { +    CommandArgumentEntry arg; +    CommandArgumentData bool_arg; + +    // Define the first (and only) variant of this arg. +    bool_arg.arg_type = eArgTypeBoolean; +    bool_arg.arg_repetition = eArgRepeatPlain; + +    // There is only one variant this argument could be; put it into the +    // argument entry. +    arg.push_back(bool_arg); + +    // Push the data for the first argument into the m_arguments vector. +    m_arguments.push_back(arg); +  } + +  ~CommandObjectLogTimerIncrement() override = default; + +  void +  HandleArgumentCompletion(CompletionRequest &request, +                           OptionElementVector &opt_element_vector) override { +    request.TryCompleteCurrentArg("true"); +    request.TryCompleteCurrentArg("false"); +  }  protected:    bool DoExecute(Args &args, CommandReturnObject &result) override {      result.SetStatus(eReturnStatusFailed);      if (args.GetArgumentCount() == 1) { -      auto sub_command = args[0].ref(); +      bool success; +      bool increment = +          OptionArgParser::ToBoolean(args[0].ref(), false, &success); -      if (sub_command.equals_lower("enable")) { -        Timer::SetDisplayDepth(UINT32_MAX); +      if (success) { +        Timer::SetQuiet(!increment);          result.SetStatus(eReturnStatusSuccessFinishNoResult); -      } else if (sub_command.equals_lower("disable")) { -        Timer::DumpCategoryTimes(&result.GetOutputStream()); -        Timer::SetDisplayDepth(0); -        result.SetStatus(eReturnStatusSuccessFinishResult); -      } else if (sub_command.equals_lower("dump")) { -        Timer::DumpCategoryTimes(&result.GetOutputStream()); -        result.SetStatus(eReturnStatusSuccessFinishResult); -      } else if (sub_command.equals_lower("reset")) { -        Timer::ResetCategoryTimes(); -        result.SetStatus(eReturnStatusSuccessFinishResult); -      } -    } else if (args.GetArgumentCount() == 2) { -      auto sub_command = args[0].ref(); -      auto param = args[1].ref(); - -      if (sub_command.equals_lower("enable")) { -        uint32_t depth; -        if (param.consumeInteger(0, depth)) { -          result.AppendError( -              "Could not convert enable depth to an unsigned integer."); -        } else { -          Timer::SetDisplayDepth(depth); -          result.SetStatus(eReturnStatusSuccessFinishNoResult); -        } -      } else if (sub_command.equals_lower("increment")) { -        bool success; -        bool increment = OptionArgParser::ToBoolean(param, false, &success); -        if (success) { -          Timer::SetQuiet(!increment); -          result.SetStatus(eReturnStatusSuccessFinishNoResult); -        } else -          result.AppendError("Could not convert increment value to boolean."); -      } +      } else +        result.AppendError("Could not convert increment value to boolean.");      }      if (!result.Succeeded()) { @@ -363,6 +472,30 @@ protected:    }  }; +class CommandObjectLogTimer : public CommandObjectMultiword { +public: +  CommandObjectLogTimer(CommandInterpreter &interpreter) +      : CommandObjectMultiword(interpreter, "log timers", +                               "Enable, disable, dump, and reset LLDB internal " +                               "performance timers.", +                               "log timers < enable <depth> | disable | dump | " +                               "increment <bool> | reset >") { +    LoadSubCommand("enable", CommandObjectSP( +                                 new CommandObjectLogTimerEnable(interpreter))); +    LoadSubCommand("disable", CommandObjectSP(new CommandObjectLogTimerDisable( +                                  interpreter))); +    LoadSubCommand("dump", +                   CommandObjectSP(new CommandObjectLogTimerDump(interpreter))); +    LoadSubCommand( +        "reset", CommandObjectSP(new CommandObjectLogTimerReset(interpreter))); +    LoadSubCommand( +        "increment", +        CommandObjectSP(new CommandObjectLogTimerIncrement(interpreter))); +  } + +  ~CommandObjectLogTimer() override = default; +}; +  CommandObjectLog::CommandObjectLog(CommandInterpreter &interpreter)      : CommandObjectMultiword(interpreter, "log",                               "Commands controlling LLDB internal logging.", diff --git a/lldb/source/Commands/CommandObjectLog.h b/lldb/source/Commands/CommandObjectLog.h index eae41bf6b8d1..8dc3f1b7b9e9 100644 --- a/lldb/source/Commands/CommandObjectLog.h +++ b/lldb/source/Commands/CommandObjectLog.h @@ -6,9 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectLog_h_ -#define liblldb_CommandObjectLog_h_ - +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTLOG_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTLOG_H  #include "lldb/Interpreter/CommandObjectMultiword.h" @@ -25,9 +24,10 @@ public:  private:    // For CommandObjectLog only -  DISALLOW_COPY_AND_ASSIGN(CommandObjectLog); +  CommandObjectLog(const CommandObjectLog &) = delete; +  const CommandObjectLog &operator=(const CommandObjectLog &) = delete;  };  } // namespace lldb_private -#endif // liblldb_CommandObjectLog_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTLOG_H diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp index e497b5246b8d..474c37710149 100644 --- a/lldb/source/Commands/CommandObjectMemory.cpp +++ b/lldb/source/Commands/CommandObjectMemory.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectMemory.cpp ---------------------------------*- C++ -*-===// +//===-- CommandObjectMemory.cpp -------------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Commands/CommandObjectMemory.h b/lldb/source/Commands/CommandObjectMemory.h index f94cdf3287aa..5f7f6bb30b88 100644 --- a/lldb/source/Commands/CommandObjectMemory.h +++ b/lldb/source/Commands/CommandObjectMemory.h @@ -6,8 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectMemory_h_ -#define liblldb_CommandObjectMemory_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTMEMORY_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTMEMORY_H  #include "lldb/Interpreter/CommandObjectMultiword.h" @@ -22,4 +22,4 @@ public:  } // namespace lldb_private -#endif // liblldb_CommandObjectMemory_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTMEMORY_H diff --git a/lldb/source/Commands/CommandObjectMultiword.cpp b/lldb/source/Commands/CommandObjectMultiword.cpp index 67225d3d6b8d..9033cfebf46b 100644 --- a/lldb/source/Commands/CommandObjectMultiword.cpp +++ b/lldb/source/Commands/CommandObjectMultiword.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectMultiword.cpp ------------------------------*- C++ -*-===// +//===-- CommandObjectMultiword.cpp ----------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -32,7 +32,7 @@ CommandObjectSP CommandObjectMultiword::GetSubcommandSP(llvm::StringRef sub_cmd,    CommandObject::CommandMap::iterator pos;    if (!m_subcommand_dict.empty()) { -    pos = m_subcommand_dict.find(sub_cmd); +    pos = m_subcommand_dict.find(std::string(sub_cmd));      if (pos != m_subcommand_dict.end()) {        // An exact match; append the sub_cmd to the 'matches' string list.        if (matches) @@ -50,7 +50,7 @@ CommandObjectSP CommandObjectMultiword::GetSubcommandSP(llvm::StringRef sub_cmd,          // function, since I now know I have an exact match...          sub_cmd = matches->GetStringAtIndex(0); -        pos = m_subcommand_dict.find(sub_cmd); +        pos = m_subcommand_dict.find(std::string(sub_cmd));          if (pos != m_subcommand_dict.end())            return_cmd_sp = pos->second;        } @@ -74,9 +74,9 @@ bool CommandObjectMultiword::LoadSubCommand(llvm::StringRef name,    CommandMap::iterator pos;    bool success = true; -  pos = m_subcommand_dict.find(name); +  pos = m_subcommand_dict.find(std::string(name));    if (pos == m_subcommand_dict.end()) { -    m_subcommand_dict[name] = cmd_obj; +    m_subcommand_dict[std::string(name)] = cmd_obj;    } else      success = false; @@ -130,9 +130,9 @@ bool CommandObjectMultiword::Execute(const char *args_string,      error_msg.assign("invalid command ");    error_msg.append("'"); -  error_msg.append(GetCommandName()); +  error_msg.append(std::string(GetCommandName()));    error_msg.append(" "); -  error_msg.append(sub_command); +  error_msg.append(std::string(sub_command));    error_msg.append("'.");    if (num_subcmd_matches > 0) { @@ -165,15 +165,14 @@ void CommandObjectMultiword::GenerateHelpText(Stream &output_stream) {      std::string indented_command("    ");      indented_command.append(pos->first);      if (pos->second->WantsRawCommandString()) { -      std::string help_text(pos->second->GetHelp()); +      std::string help_text(std::string(pos->second->GetHelp()));        help_text.append("  Expects 'raw' input (see 'help raw-input'.)"); -      m_interpreter.OutputFormattedHelpText(output_stream, -                                            indented_command.c_str(), "--", -                                            help_text.c_str(), max_len); +      m_interpreter.OutputFormattedHelpText(output_stream, indented_command, +                                            "--", help_text, max_len);      } else -      m_interpreter.OutputFormattedHelpText(output_stream, -                                            indented_command.c_str(), "--", -                                            pos->second->GetHelp(), max_len); +      m_interpreter.OutputFormattedHelpText(output_stream, indented_command, +                                            "--", pos->second->GetHelp(), +                                            max_len);    }    output_stream.PutCString("\nFor more help on any particular subcommand, type " diff --git a/lldb/source/Commands/CommandObjectPlatform.cpp b/lldb/source/Commands/CommandObjectPlatform.cpp index 10e6a4aa1793..fcc8af6f915c 100644 --- a/lldb/source/Commands/CommandObjectPlatform.cpp +++ b/lldb/source/Commands/CommandObjectPlatform.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectPlatform.cpp -------------------------------*- C++ -*-===// +//===-- CommandObjectPlatform.cpp -----------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -11,7 +11,6 @@  #include "lldb/Core/Module.h"  #include "lldb/Core/PluginManager.h"  #include "lldb/Host/OptionParser.h" -#include "lldb/Host/StringConvert.h"  #include "lldb/Interpreter/CommandInterpreter.h"  #include "lldb/Interpreter/CommandOptionValidators.h"  #include "lldb/Interpreter/CommandReturnObject.h" @@ -133,7 +132,8 @@ public:    uint32_t m_permissions;  private: -  DISALLOW_COPY_AND_ASSIGN(OptionPermissions); +  OptionPermissions(const OptionPermissions &) = delete; +  const OptionPermissions &operator=(const OptionPermissions &) = delete;  };  // "platform select <platform-name>" @@ -421,7 +421,6 @@ protected:      return &m_options;    } -protected:    OptionGroupOptions m_options;    OptionGroupFile m_option_working_dir;  }; @@ -546,8 +545,13 @@ public:      if (platform_sp) {        std::string cmd_line;        args.GetCommandString(cmd_line); -      const lldb::user_id_t fd = -          StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX); +      lldb::user_id_t fd; +      if (!llvm::to_integer(cmd_line, fd)) { +        result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.\n", +                                      cmd_line); +        result.SetStatus(eReturnStatusFailed); +        return result.Succeeded(); +      }        Status error;        bool success = platform_sp->CloseFile(fd, error);        if (success) { @@ -586,8 +590,13 @@ public:      if (platform_sp) {        std::string cmd_line;        args.GetCommandString(cmd_line); -      const lldb::user_id_t fd = -          StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX); +      lldb::user_id_t fd; +      if (!llvm::to_integer(cmd_line, fd)) { +        result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.\n", +                                      cmd_line); +        result.SetStatus(eReturnStatusFailed); +        return result.Succeeded(); +      }        std::string buffer(m_options.m_count, 0);        Status error;        uint32_t retcode = platform_sp->ReadFile( @@ -674,8 +683,13 @@ public:        std::string cmd_line;        args.GetCommandString(cmd_line);        Status error; -      const lldb::user_id_t fd = -          StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX); +      lldb::user_id_t fd; +      if (!llvm::to_integer(cmd_line, fd)) { +        result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.", +                                      cmd_line); +        result.SetStatus(eReturnStatusFailed); +        return result.Succeeded(); +      }        uint32_t retcode =            platform_sp->WriteFile(fd, m_options.m_offset, &m_options.m_data[0],                                   m_options.m_data.size(), error); @@ -709,7 +723,7 @@ protected:                                           option_arg.str().c_str());          break;        case 'd': -        m_data.assign(option_arg); +        m_data.assign(std::string(option_arg));          break;        default:          llvm_unreachable("Unimplemented option"); @@ -758,7 +772,9 @@ public:  private:    // For CommandObjectPlatform only -  DISALLOW_COPY_AND_ASSIGN(CommandObjectPlatformFile); +  CommandObjectPlatformFile(const CommandObjectPlatformFile &) = delete; +  const CommandObjectPlatformFile & +  operator=(const CommandObjectPlatformFile &) = delete;  };  // "platform get-file remote-file-path host-file-path" @@ -1020,7 +1036,6 @@ protected:      return result.Succeeded();    } -protected:    ProcessLaunchCommandOptions m_options;  }; @@ -1128,7 +1143,7 @@ protected:                ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,                                                     m_options.verbose);                for (uint32_t i = 0; i < matches; ++i) { -                proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow( +                proc_infos[i].DumpAsTableRow(                      ostrm, platform_sp->GetUserIDResolver(),                      m_options.show_args, m_options.verbose);                } @@ -1462,12 +1477,12 @@ public:          match_info.SetNameMatchType(NameMatch::StartsWith);        }        platform_sp->FindProcesses(match_info, process_infos); -      const uint32_t num_matches = process_infos.GetSize(); +      const uint32_t num_matches = process_infos.size();        if (num_matches == 0)          return;        for (uint32_t i = 0; i < num_matches; ++i) { -        request.AddCompletion(process_infos.GetProcessNameAtIndex(i)); +        request.AddCompletion(process_infos[i].GetNameAsStringRef());        }        return;      } @@ -1541,7 +1556,9 @@ public:  private:    // For CommandObjectPlatform only -  DISALLOW_COPY_AND_ASSIGN(CommandObjectPlatformProcess); +  CommandObjectPlatformProcess(const CommandObjectPlatformProcess &) = delete; +  const CommandObjectPlatformProcess & +  operator=(const CommandObjectPlatformProcess &) = delete;  };  // "platform shell" @@ -1567,6 +1584,9 @@ public:        const char short_option = (char)GetDefinitions()[option_idx].short_option;        switch (short_option) { +      case 'h': +        m_use_host_platform = true; +        break;        case 't':          uint32_t timeout_sec;          if (option_arg.getAsInteger(10, timeout_sec)) @@ -1574,7 +1594,7 @@ public:                "could not convert \"%s\" to a numeric value.",                option_arg.str().c_str());          else -          timeout = std::chrono::seconds(timeout_sec); +          m_timeout = std::chrono::seconds(timeout_sec);          break;        default:          llvm_unreachable("Unimplemented option"); @@ -1583,9 +1603,13 @@ public:        return error;      } -    void OptionParsingStarting(ExecutionContext *execution_context) override {} +    void OptionParsingStarting(ExecutionContext *execution_context) override { +      m_timeout.reset(); +      m_use_host_platform = false; +    } -    Timeout<std::micro> timeout = std::chrono::seconds(10); +    Timeout<std::micro> m_timeout = std::chrono::seconds(10); +    bool m_use_host_platform;    };    CommandObjectPlatformShell(CommandInterpreter &interpreter) @@ -1609,6 +1633,7 @@ public:        return true;      } +    const bool is_alias = !raw_command_line.contains("platform");      OptionsWithRaw args(raw_command_line);      const char *expr = args.GetRawPart().c_str(); @@ -1616,8 +1641,16 @@ public:        if (!ParseOptions(args.GetArgs(), result))          return false; +    if (args.GetRawPart().empty()) { +      result.GetOutputStream().Printf("%s <shell-command>\n", +                                      is_alias ? "shell" : "platform shell"); +      return false; +    } +      PlatformSP platform_sp( -        GetDebugger().GetPlatformList().GetSelectedPlatform()); +        m_options.m_use_host_platform +            ? Platform::GetHostPlatform() +            : GetDebugger().GetPlatformList().GetSelectedPlatform());      Status error;      if (platform_sp) {        FileSpec working_dir{}; @@ -1625,7 +1658,7 @@ public:        int status = -1;        int signo = -1;        error = (platform_sp->RunShellCommand(expr, working_dir, &status, &signo, -                                            &output, m_options.timeout)); +                                            &output, m_options.m_timeout));        if (!output.empty())          result.GetOutputStream().PutCString(output);        if (status > 0) { diff --git a/lldb/source/Commands/CommandObjectPlatform.h b/lldb/source/Commands/CommandObjectPlatform.h index 45e4a41c5b20..86f55c7d9b08 100644 --- a/lldb/source/Commands/CommandObjectPlatform.h +++ b/lldb/source/Commands/CommandObjectPlatform.h @@ -6,8 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectPlatform_h_ -#define liblldb_CommandObjectPlatform_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTPLATFORM_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTPLATFORM_H  #include "lldb/Interpreter/CommandObjectMultiword.h" @@ -22,9 +22,11 @@ public:    ~CommandObjectPlatform() override;  private: -  DISALLOW_COPY_AND_ASSIGN(CommandObjectPlatform); +  CommandObjectPlatform(const CommandObjectPlatform &) = delete; +  const CommandObjectPlatform & +  operator=(const CommandObjectPlatform &) = delete;  };  } // namespace lldb_private -#endif // liblldb_CommandObjectPlatform_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTPLATFORM_H diff --git a/lldb/source/Commands/CommandObjectPlugin.cpp b/lldb/source/Commands/CommandObjectPlugin.cpp index 6fcb64f207b2..98a212eef0fa 100644 --- a/lldb/source/Commands/CommandObjectPlugin.cpp +++ b/lldb/source/Commands/CommandObjectPlugin.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectPlugin.cpp ---------------------------------*- C++ -*-===// +//===-- CommandObjectPlugin.cpp -------------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Commands/CommandObjectPlugin.h b/lldb/source/Commands/CommandObjectPlugin.h index 94cea7db4111..6db9f0a40a40 100644 --- a/lldb/source/Commands/CommandObjectPlugin.h +++ b/lldb/source/Commands/CommandObjectPlugin.h @@ -6,8 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectPlugin_h_ -#define liblldb_CommandObjectPlugin_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTPLUGIN_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTPLUGIN_H  #include "lldb/Interpreter/CommandObjectMultiword.h" @@ -22,4 +22,4 @@ public:  } // namespace lldb_private -#endif // liblldb_CommandObjectPlugin_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTPLUGIN_H diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp index d825647728f8..f86779d85b5f 100644 --- a/lldb/source/Commands/CommandObjectProcess.cpp +++ b/lldb/source/Commands/CommandObjectProcess.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectProcess.cpp --------------------------------*- C++ -*-===// +//===-- CommandObjectProcess.cpp ------------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -13,7 +13,6 @@  #include "lldb/Core/Module.h"  #include "lldb/Core/PluginManager.h"  #include "lldb/Host/OptionParser.h" -#include "lldb/Host/StringConvert.h"  #include "lldb/Interpreter/CommandInterpreter.h"  #include "lldb/Interpreter/CommandReturnObject.h"  #include "lldb/Interpreter/OptionArgParser.h" @@ -249,7 +248,6 @@ protected:      return result.Succeeded();    } -protected:    ProcessLaunchCommandOptions m_options;  }; @@ -325,34 +323,38 @@ public:        int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;        int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; -      // We are only completing the name option for now... - -      // Are we in the name? -      if (GetDefinitions()[opt_defs_index].short_option != 'n') -        return; - -      // Look to see if there is a -P argument provided, and if so use that -      // plugin, otherwise use the default plugin. - -      const char *partial_name = nullptr; -      partial_name = request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos); +      switch (GetDefinitions()[opt_defs_index].short_option) { +      case 'n': { +        // Look to see if there is a -P argument provided, and if so use that +        // plugin, otherwise use the default plugin. + +        const char *partial_name = nullptr; +        partial_name = request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos); + +        PlatformSP platform_sp(interpreter.GetPlatform(true)); +        if (!platform_sp) +          return; +        ProcessInstanceInfoList process_infos; +        ProcessInstanceInfoMatch match_info; +        if (partial_name) { +          match_info.GetProcessInfo().GetExecutableFile().SetFile( +              partial_name, FileSpec::Style::native); +          match_info.SetNameMatchType(NameMatch::StartsWith); +        } +        platform_sp->FindProcesses(match_info, process_infos); +        const size_t num_matches = process_infos.size(); +        if (num_matches == 0) +          return; +        for (size_t i = 0; i < num_matches; ++i) { +          request.AddCompletion(process_infos[i].GetNameAsStringRef()); +        } +      } break; -      PlatformSP platform_sp(interpreter.GetPlatform(true)); -      if (!platform_sp) -        return; -      ProcessInstanceInfoList process_infos; -      ProcessInstanceInfoMatch match_info; -      if (partial_name) { -        match_info.GetProcessInfo().GetExecutableFile().SetFile( -            partial_name, FileSpec::Style::native); -        match_info.SetNameMatchType(NameMatch::StartsWith); -      } -      platform_sp->FindProcesses(match_info, process_infos); -      const size_t num_matches = process_infos.GetSize(); -      if (num_matches == 0) -        return; -      for (size_t i = 0; i < num_matches; ++i) { -        request.AddCompletion(process_infos.GetProcessNameAtIndex(i)); +      case 'P': +        CommandCompletions::InvokeCommonCompletionCallbacks( +            interpreter, CommandCompletions::eProcessPluginCompletion, request, +            nullptr); +        break;        }      } @@ -759,7 +761,7 @@ public:        switch (short_option) {        case 'p': -        plugin_name.assign(option_arg); +        plugin_name.assign(std::string(option_arg));          break;        default: @@ -818,9 +820,15 @@ protected:      Status error;      Debugger &debugger = GetDebugger();      PlatformSP platform_sp = m_interpreter.GetPlatform(true); -    ProcessSP process_sp = platform_sp->ConnectProcess( -        command.GetArgumentAtIndex(0), plugin_name, debugger, -        debugger.GetSelectedTarget().get(), error); +    ProcessSP process_sp = +        debugger.GetAsyncExecution() +            ? platform_sp->ConnectProcess( +                  command.GetArgumentAtIndex(0), plugin_name, debugger, +                  debugger.GetSelectedTarget().get(), error) +            : platform_sp->ConnectProcessSynchronous( +                  command.GetArgumentAtIndex(0), plugin_name, debugger, +                  result.GetOutputStream(), debugger.GetSelectedTarget().get(), +                  error);      if (error.Fail() || process_sp == nullptr) {        result.AppendError(error.AsCString("Error connecting to the process"));        result.SetStatus(eReturnStatusFailed); @@ -1034,6 +1042,20 @@ public:    ~CommandObjectProcessSignal() override = default; +  void +  HandleArgumentCompletion(CompletionRequest &request, +                           OptionElementVector &opt_element_vector) override { +    if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0) +      return; + +    UnixSignalsSP signals = m_exe_ctx.GetProcessPtr()->GetUnixSignals(); +    int signo = signals->GetFirstSignalNumber(); +    while (signo != LLDB_INVALID_SIGNAL_NUMBER) { +      request.AddCompletion(signals->GetSignalAsCString(signo), ""); +      signo = signals->GetNextSignalNumber(signo); +    } +  } +  protected:    bool DoExecute(Args &command, CommandReturnObject &result) override {      Process *process = m_exe_ctx.GetProcessPtr(); @@ -1042,10 +1064,10 @@ protected:        int signo = LLDB_INVALID_SIGNAL_NUMBER;        const char *signal_name = command.GetArgumentAtIndex(0); -      if (::isxdigit(signal_name[0])) -        signo = -            StringConvert::ToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0); -      else +      if (::isxdigit(signal_name[0])) { +        if (!llvm::to_integer(signal_name, signo)) +          signo = LLDB_INVALID_SIGNAL_NUMBER; +      } else          signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name);        if (signo == LLDB_INVALID_SIGNAL_NUMBER) { @@ -1201,6 +1223,8 @@ protected:  // CommandObjectProcessStatus  #pragma mark CommandObjectProcessStatus +#define LLDB_OPTIONS_process_status +#include "CommandOptions.inc"  class CommandObjectProcessStatus : public CommandObjectParsed {  public: @@ -1209,13 +1233,57 @@ public:              interpreter, "process status",              "Show status and stop location for the current target process.",              "process status", -            eCommandRequiresProcess | eCommandTryTargetAPILock) {} +            eCommandRequiresProcess | eCommandTryTargetAPILock), +        m_options() {}    ~CommandObjectProcessStatus() override = default; +  Options *GetOptions() override { return &m_options; } + +  class CommandOptions : public Options { +  public: +    CommandOptions() : Options(), m_verbose(false) {} + +    ~CommandOptions() override = default; + +    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, +                          ExecutionContext *execution_context) override { +      const int short_option = m_getopt_table[option_idx].val; + +      switch (short_option) { +      case 'v': +        m_verbose = true; +        break; +      default: +        llvm_unreachable("Unimplemented option"); +      } + +      return {}; +    } + +    void OptionParsingStarting(ExecutionContext *execution_context) override { +      m_verbose = false; +    } + +    llvm::ArrayRef<OptionDefinition> GetDefinitions() override { +      return llvm::makeArrayRef(g_process_status_options); +    } + +    // Instance variables to hold the values for command options. +    bool m_verbose; +  }; + +protected:    bool DoExecute(Args &command, CommandReturnObject &result) override {      Stream &strm = result.GetOutputStream();      result.SetStatus(eReturnStatusSuccessFinishNoResult); + +    if (command.GetArgumentCount()) { +      result.AppendError("'process status' takes no arguments"); +      result.SetStatus(eReturnStatusFailed); +      return result.Succeeded(); +    } +      // No need to check "process" for validity as eCommandRequiresProcess      // ensures it is valid      Process *process = m_exe_ctx.GetProcessPtr(); @@ -1227,8 +1295,37 @@ public:      process->GetStatus(strm);      process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame,                               num_frames, num_frames_with_source, stop_format); + +    if (m_options.m_verbose) { +      PlatformSP platform_sp = process->GetTarget().GetPlatform(); +      if (!platform_sp) { +        result.AppendError("Couldn'retrieve the target's platform"); +        result.SetStatus(eReturnStatusFailed); +        return result.Succeeded(); +      } + +      auto expected_crash_info = +          platform_sp->FetchExtendedCrashInformation(*process); + +      if (!expected_crash_info) { +        result.AppendError(llvm::toString(expected_crash_info.takeError())); +        result.SetStatus(eReturnStatusFailed); +        return result.Succeeded(); +      } + +      StructuredData::DictionarySP crash_info_sp = *expected_crash_info; + +      if (crash_info_sp) { +        strm.PutCString("Extended Crash Information:\n"); +        crash_info_sp->Dump(strm); +      } +    } +      return result.Succeeded();    } + +private: +  CommandOptions m_options;  };  // CommandObjectProcessHandle @@ -1252,13 +1349,13 @@ public:        switch (short_option) {        case 's': -        stop = option_arg; +        stop = std::string(option_arg);          break;        case 'n': -        notify = option_arg; +        notify = std::string(option_arg);          break;        case 'p': -        pass = option_arg; +        pass = std::string(option_arg);          break;        default:          llvm_unreachable("Unimplemented option"); @@ -1318,7 +1415,8 @@ public:        real_value = 0;      else {        // If the value isn't 'true' or 'false', it had better be 0 or 1. -      real_value = StringConvert::ToUInt32(option.c_str(), 3); +      if (!llvm::to_integer(option, real_value)) +        real_value = 3;        if (real_value != 0 && real_value != 1)          okay = false;      } diff --git a/lldb/source/Commands/CommandObjectProcess.h b/lldb/source/Commands/CommandObjectProcess.h index 3b1ff26dbb05..55d445142e72 100644 --- a/lldb/source/Commands/CommandObjectProcess.h +++ b/lldb/source/Commands/CommandObjectProcess.h @@ -6,8 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectProcess_h_ -#define liblldb_CommandObjectProcess_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTPROCESS_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTPROCESS_H  #include "lldb/Interpreter/CommandObjectMultiword.h" @@ -24,4 +24,4 @@ public:  } // namespace lldb_private -#endif // liblldb_CommandObjectProcess_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTPROCESS_H diff --git a/lldb/source/Commands/CommandObjectQuit.cpp b/lldb/source/Commands/CommandObjectQuit.cpp index 70ee336f8a1b..d0c7bbd3abf8 100644 --- a/lldb/source/Commands/CommandObjectQuit.cpp +++ b/lldb/source/Commands/CommandObjectQuit.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectQuit.cpp -----------------------------------*- C++ -*-===// +//===-- CommandObjectQuit.cpp ---------------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Commands/CommandObjectQuit.h b/lldb/source/Commands/CommandObjectQuit.h index 458ef2456fca..ccbd863cd6f5 100644 --- a/lldb/source/Commands/CommandObjectQuit.h +++ b/lldb/source/Commands/CommandObjectQuit.h @@ -6,8 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectQuit_h_ -#define liblldb_CommandObjectQuit_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTQUIT_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTQUIT_H  #include "lldb/Interpreter/CommandObject.h" @@ -29,4 +29,4 @@ protected:  } // namespace lldb_private -#endif // liblldb_CommandObjectQuit_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTQUIT_H diff --git a/lldb/source/Commands/CommandObjectRegister.cpp b/lldb/source/Commands/CommandObjectRegister.cpp index 523b32a996b2..56e8c3fb4b84 100644 --- a/lldb/source/Commands/CommandObjectRegister.cpp +++ b/lldb/source/Commands/CommandObjectRegister.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectRegister.cpp -------------------------------*- C++ -*-===// +//===-- CommandObjectRegister.cpp -----------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -70,6 +70,17 @@ public:    ~CommandObjectRegisterRead() override = default; +  void +  HandleArgumentCompletion(CompletionRequest &request, +                           OptionElementVector &opt_element_vector) override { +    if (!m_exe_ctx.HasProcessScope()) +      return; + +    CommandCompletions::InvokeCommonCompletionCallbacks( +        GetCommandInterpreter(), CommandCompletions::eRegisterCompletion, +        request, nullptr); +  } +    Options *GetOptions() override { return &m_option_group; }    bool DumpRegister(const ExecutionContext &exe_ctx, Stream &strm, @@ -323,6 +334,17 @@ public:    ~CommandObjectRegisterWrite() override = default; +  void +  HandleArgumentCompletion(CompletionRequest &request, +                           OptionElementVector &opt_element_vector) override { +    if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0) +      return; + +    CommandCompletions::InvokeCommonCompletionCallbacks( +        GetCommandInterpreter(), CommandCompletions::eRegisterCompletion, +        request, nullptr); +  } +  protected:    bool DoExecute(Args &command, CommandReturnObject &result) override {      DataExtractor reg_data; diff --git a/lldb/source/Commands/CommandObjectRegister.h b/lldb/source/Commands/CommandObjectRegister.h index 6fc47cf386a3..671ffc570147 100644 --- a/lldb/source/Commands/CommandObjectRegister.h +++ b/lldb/source/Commands/CommandObjectRegister.h @@ -6,8 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectRegister_h_ -#define liblldb_CommandObjectRegister_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTREGISTER_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTREGISTER_H  #include "lldb/Interpreter/CommandObjectMultiword.h" @@ -24,9 +24,11 @@ public:  private:    // For CommandObjectRegister only -  DISALLOW_COPY_AND_ASSIGN(CommandObjectRegister); +  CommandObjectRegister(const CommandObjectRegister &) = delete; +  const CommandObjectRegister & +  operator=(const CommandObjectRegister &) = delete;  };  } // namespace lldb_private -#endif // liblldb_CommandObjectRegister_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTREGISTER_H diff --git a/lldb/source/Commands/CommandObjectReproducer.cpp b/lldb/source/Commands/CommandObjectReproducer.cpp index d15f622314d9..104130b70b2b 100644 --- a/lldb/source/Commands/CommandObjectReproducer.cpp +++ b/lldb/source/Commands/CommandObjectReproducer.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectReproducer.cpp -----------------------------*- C++ -*-===// +//===-- CommandObjectReproducer.cpp ---------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -8,13 +8,14 @@  #include "CommandObjectReproducer.h" +#include "lldb/Host/HostInfo.h"  #include "lldb/Host/OptionParser.h" -#include "lldb/Utility/GDBRemote.h" -#include "lldb/Utility/Reproducer.h" -  #include "lldb/Interpreter/CommandInterpreter.h"  #include "lldb/Interpreter/CommandReturnObject.h"  #include "lldb/Interpreter/OptionArgParser.h" +#include "lldb/Utility/GDBRemote.h" +#include "lldb/Utility/ProcessInfo.h" +#include "lldb/Utility/Reproducer.h"  #include <csignal> @@ -27,6 +28,7 @@ enum ReproducerProvider {    eReproducerProviderCommands,    eReproducerProviderFiles,    eReproducerProviderGDB, +  eReproducerProviderProcessInfo,    eReproducerProviderVersion,    eReproducerProviderWorkingDirectory,    eReproducerProviderNone @@ -49,6 +51,11 @@ static constexpr OptionEnumValueElement g_reproducer_provider_type[] = {          "GDB Remote Packets",      },      { +        eReproducerProviderProcessInfo, +        "processes", +        "Process Info", +    }, +    {          eReproducerProviderVersion,          "version",          "Version", @@ -97,6 +104,24 @@ static constexpr OptionEnumValues ReproducerSignalType() {  #define LLDB_OPTIONS_reproducer_xcrash  #include "CommandOptions.inc" +template <typename T> +llvm::Expected<T> static ReadFromYAML(StringRef filename) { +  auto error_or_file = MemoryBuffer::getFile(filename); +  if (auto err = error_or_file.getError()) { +    return errorCodeToError(err); +  } + +  T t; +  yaml::Input yin((*error_or_file)->getBuffer()); +  yin >> t; + +  if (auto err = yin.error()) { +    return errorCodeToError(err); +  } + +  return t; +} +  class CommandObjectReproducerGenerate : public CommandObjectParsed {  public:    CommandObjectReproducerGenerate(CommandInterpreter &interpreter) @@ -258,6 +283,18 @@ protected:        result.GetOutputStream() << "Reproducer is off.\n";      } +    if (r.IsCapturing() || r.IsReplaying()) { +      result.GetOutputStream() +          << "Path: " << r.GetReproducerPath().GetPath() << '\n'; +    } + +    // Auto generate is hidden unless enabled because this is mostly for +    // development and testing. +    if (Generator *g = r.GetGenerator()) { +      if (g->IsAutoGenerate()) +        result.GetOutputStream() << "Auto generate: on\n"; +    } +      result.SetStatus(eReturnStatusSuccessFinishResult);      return result.Succeeded();    } @@ -410,8 +447,8 @@ protected:            repro::MultiLoader<repro::CommandProvider>::Create(loader);        if (!multi_loader) {          SetError(result, -                 make_error<StringError>(llvm::inconvertibleErrorCode(), -                                         "Unable to create command loader.")); +                 make_error<StringError>("Unable to create command loader.", +                                         llvm::inconvertibleErrorCode()));          return false;        } @@ -436,26 +473,52 @@ protected:        std::unique_ptr<repro::MultiLoader<repro::GDBRemoteProvider>>            multi_loader =                repro::MultiLoader<repro::GDBRemoteProvider>::Create(loader); + +      if (!multi_loader) { +        SetError(result, +                 make_error<StringError>("Unable to create GDB loader.", +                                         llvm::inconvertibleErrorCode())); +        return false; +      } +        llvm::Optional<std::string> gdb_file;        while ((gdb_file = multi_loader->GetNextFile())) { -        auto error_or_file = MemoryBuffer::getFile(*gdb_file); -        if (auto err = error_or_file.getError()) { -          SetError(result, errorCodeToError(err)); +        if (llvm::Expected<std::vector<GDBRemotePacket>> packets = +                ReadFromYAML<std::vector<GDBRemotePacket>>(*gdb_file)) { +          for (GDBRemotePacket &packet : *packets) { +            packet.Dump(result.GetOutputStream()); +          } +        } else { +          SetError(result, packets.takeError());            return false;          } +      } + +      result.SetStatus(eReturnStatusSuccessFinishResult); +      return true; +    } +    case eReproducerProviderProcessInfo: { +      std::unique_ptr<repro::MultiLoader<repro::ProcessInfoProvider>> +          multi_loader = +              repro::MultiLoader<repro::ProcessInfoProvider>::Create(loader); -        std::vector<GDBRemotePacket> packets; -        yaml::Input yin((*error_or_file)->getBuffer()); -        yin >> packets; +      if (!multi_loader) { +        SetError(result, make_error<StringError>( +                             llvm::inconvertibleErrorCode(), +                             "Unable to create process info loader.")); +        return false; +      } -        if (auto err = yin.error()) { -          SetError(result, errorCodeToError(err)); +      llvm::Optional<std::string> process_file; +      while ((process_file = multi_loader->GetNextFile())) { +        if (llvm::Expected<ProcessInstanceInfoList> infos = +                ReadFromYAML<ProcessInstanceInfoList>(*process_file)) { +          for (ProcessInstanceInfo info : *infos) +            info.Dump(result.GetOutputStream(), HostInfo::GetUserIDResolver()); +        } else { +          SetError(result, infos.takeError());            return false;          } - -        for (GDBRemotePacket &packet : packets) { -          packet.Dump(result.GetOutputStream()); -        }        }        result.SetStatus(eReturnStatusSuccessFinishResult); diff --git a/lldb/source/Commands/CommandObjectReproducer.h b/lldb/source/Commands/CommandObjectReproducer.h index 8a85c21d6510..bdee8053549f 100644 --- a/lldb/source/Commands/CommandObjectReproducer.h +++ b/lldb/source/Commands/CommandObjectReproducer.h @@ -6,8 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectReproducer_h_ -#define liblldb_CommandObjectReproducer_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTREPRODUCER_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTREPRODUCER_H  #include "lldb/Interpreter/CommandObjectMultiword.h" @@ -24,4 +24,4 @@ public:  } // namespace lldb_private -#endif // liblldb_CommandObjectReproducer_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTREPRODUCER_H diff --git a/lldb/source/Commands/CommandObjectSettings.cpp b/lldb/source/Commands/CommandObjectSettings.cpp index 95f79f45e22b..87e0352636e1 100644 --- a/lldb/source/Commands/CommandObjectSettings.cpp +++ b/lldb/source/Commands/CommandObjectSettings.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectSettings.cpp -------------------------------*- C++ -*-===// +//===-- CommandObjectSettings.cpp -----------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -343,7 +343,7 @@ public:        switch (short_option) {        case 'f': -        m_filename.assign(option_arg); +        m_filename.assign(std::string(option_arg));          break;        case 'a':          m_append = true; @@ -444,7 +444,7 @@ public:        switch (short_option) {        case 'f': -        m_filename.assign(option_arg); +        m_filename.assign(std::string(option_arg));          break;        default:          llvm_unreachable("Unimplemented option"); @@ -531,10 +531,8 @@ protected:      if (argc > 0) {        const bool dump_qualified_name = true; -      // TODO: Convert to StringRef based enumeration.  Requires converting -      // GetPropertyAtPath first. -      for (size_t i = 0; i < argc; ++i) { -        const char *property_path = args.GetArgumentAtIndex(i); +      for (const Args::ArgEntry &arg : args) { +        const char *property_path = arg.c_str();          const Property *property =              GetDebugger().GetValueProperties()->GetPropertyAtPath( @@ -1043,13 +1041,16 @@ protected:  };  // CommandObjectSettingsClear +#define LLDB_OPTIONS_settings_clear +#include "CommandOptions.inc"  class CommandObjectSettingsClear : public CommandObjectParsed {  public:    CommandObjectSettingsClear(CommandInterpreter &interpreter)        : CommandObjectParsed(              interpreter, "settings clear", -            "Clear a debugger setting array, dictionary, or string.", nullptr) { +            "Clear a debugger setting array, dictionary, or string. " +            "If '-a' option is specified, it clears all settings.", nullptr) {      CommandArgumentEntry arg;      CommandArgumentData var_name_arg; @@ -1077,11 +1078,53 @@ public:            request, nullptr);    } +   Options *GetOptions() override { return &m_options; } + +  class CommandOptions : public Options { +  public: +    CommandOptions() = default; + +    ~CommandOptions() override = default; + +    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, +                          ExecutionContext *execution_context) override { +      const int short_option = m_getopt_table[option_idx].val; +      switch (short_option) { +      case 'a': +        m_clear_all = true; +        break; +      default: +        llvm_unreachable("Unimplemented option"); +      } +      return Status(); +    } + +    void OptionParsingStarting(ExecutionContext *execution_context) override { +      m_clear_all = false; +    } + +    llvm::ArrayRef<OptionDefinition> GetDefinitions() override { +      return llvm::makeArrayRef(g_settings_clear_options); +    } + +    bool m_clear_all = false; +  }; +  protected:    bool DoExecute(Args &command, CommandReturnObject &result) override {      result.SetStatus(eReturnStatusSuccessFinishNoResult);      const size_t argc = command.GetArgumentCount(); +    if (m_options.m_clear_all) { +      if (argc != 0) { +        result.AppendError("'settings clear --all' doesn't take any arguments"); +        result.SetStatus(eReturnStatusFailed); +        return false; +      } +      GetDebugger().GetValueProperties()->Clear(); +      return result.Succeeded(); +    } +      if (argc != 1) {        result.AppendError("'settings clear' takes exactly one argument");        result.SetStatus(eReturnStatusFailed); @@ -1106,6 +1149,9 @@ protected:      return result.Succeeded();    } + +  private: +    CommandOptions m_options;  };  // CommandObjectMultiwordSettings diff --git a/lldb/source/Commands/CommandObjectSettings.h b/lldb/source/Commands/CommandObjectSettings.h index 4db0ca1f83f8..31ec1d3bef16 100644 --- a/lldb/source/Commands/CommandObjectSettings.h +++ b/lldb/source/Commands/CommandObjectSettings.h @@ -6,8 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectSettings_h_ -#define liblldb_CommandObjectSettings_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTSETTINGS_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTSETTINGS_H  #include "lldb/Interpreter/CommandObjectMultiword.h" @@ -24,4 +24,4 @@ public:  } // namespace lldb_private -#endif // liblldb_CommandObjectSettings_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTSETTINGS_H diff --git a/lldb/source/Commands/CommandObjectSource.cpp b/lldb/source/Commands/CommandObjectSource.cpp index 19a554fb290a..1ccfd3a5166f 100644 --- a/lldb/source/Commands/CommandObjectSource.cpp +++ b/lldb/source/Commands/CommandObjectSource.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectSource.cpp ---------------------------------*- C++ -*-===// +//===-- CommandObjectSource.cpp -------------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -63,11 +63,11 @@ class CommandObjectSourceInfo : public CommandObjectParsed {          break;        case 'f': -        file_name = option_arg; +        file_name = std::string(option_arg);          break;        case 'n': -        symbol_name = option_arg; +        symbol_name = std::string(option_arg);          break;        case 'a': { @@ -646,11 +646,11 @@ class CommandObjectSourceList : public CommandObjectParsed {          break;        case 'f': -        file_name = option_arg; +        file_name = std::string(option_arg);          break;        case 'n': -        symbol_name = option_arg; +        symbol_name = std::string(option_arg);          break;        case 'a': { diff --git a/lldb/source/Commands/CommandObjectSource.h b/lldb/source/Commands/CommandObjectSource.h index a4b8823a4fa9..f2117bd6ca3f 100644 --- a/lldb/source/Commands/CommandObjectSource.h +++ b/lldb/source/Commands/CommandObjectSource.h @@ -7,8 +7,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectSource_h_ -#define liblldb_CommandObjectSource_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTSOURCE_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTSOURCE_H  #include "lldb/Interpreter/CommandObjectMultiword.h" @@ -25,4 +25,4 @@ public:  } // namespace lldb_private -#endif // liblldb_CommandObjectSource_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTSOURCE_H diff --git a/lldb/source/Commands/CommandObjectStats.cpp b/lldb/source/Commands/CommandObjectStats.cpp index eeec4a8d3e77..6b06581f5a8f 100644 --- a/lldb/source/Commands/CommandObjectStats.cpp +++ b/lldb/source/Commands/CommandObjectStats.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectStats.cpp ----------------------------------*- C++ -*-===// +//===-- CommandObjectStats.cpp --------------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Commands/CommandObjectStats.h b/lldb/source/Commands/CommandObjectStats.h index 593c4521e175..c4cd6340f67b 100644 --- a/lldb/source/Commands/CommandObjectStats.h +++ b/lldb/source/Commands/CommandObjectStats.h @@ -6,8 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectStats_h_ -#define liblldb_CommandObjectStats_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTSTATS_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTSTATS_H  #include "lldb/Interpreter/CommandObjectMultiword.h" @@ -20,4 +20,4 @@ public:  };  } // namespace lldb_private -#endif // liblldb_CommandObjectLanguage_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTSTATS_H diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index 8738e850c9f7..7bb71f4d518c 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectTarget.cpp ---------------------------------*- C++ -*-===// +//===-- CommandObjectTarget.cpp -------------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -16,7 +16,6 @@  #include "lldb/Core/ValueObjectVariable.h"  #include "lldb/DataFormatters/ValueObjectPrinter.h"  #include "lldb/Host/OptionParser.h" -#include "lldb/Host/StringConvert.h"  #include "lldb/Interpreter/CommandInterpreter.h"  #include "lldb/Interpreter/CommandReturnObject.h"  #include "lldb/Interpreter/OptionArgParser.h" @@ -200,7 +199,9 @@ public:    LoadDependentFiles m_load_dependent_files;  private: -  DISALLOW_COPY_AND_ASSIGN(OptionGroupDependents); +  OptionGroupDependents(const OptionGroupDependents &) = delete; +  const OptionGroupDependents & +  operator=(const OptionGroupDependents &) = delete;  };  #pragma mark CommandObjectTargetCreate @@ -271,15 +272,13 @@ protected:      FileSpec remote_file(m_remote_file.GetOptionValue().GetCurrentValue());      if (core_file) { -      if (!FileSystem::Instance().Exists(core_file)) { -        result.AppendErrorWithFormat("core file '%s' doesn't exist", -                                     core_file.GetPath().c_str()); -        result.SetStatus(eReturnStatusFailed); -        return false; -      } -      if (!FileSystem::Instance().Readable(core_file)) { -        result.AppendErrorWithFormat("core file '%s' is not readable", -                                     core_file.GetPath().c_str()); +      auto file = FileSystem::Instance().Open( +          core_file, lldb_private::File::eOpenOptionRead); + +      if (!file) { +        result.AppendErrorWithFormatv("Cannot open '{0}': {1}.", +                                      core_file.GetPath(), +                                      llvm::toString(file.takeError()));          result.SetStatus(eReturnStatusFailed);          return false;        } @@ -288,18 +287,13 @@ protected:      if (argc == 1 || core_file || remote_file) {        FileSpec symfile(m_symbol_file.GetOptionValue().GetCurrentValue());        if (symfile) { -        if (FileSystem::Instance().Exists(symfile)) { -          if (!FileSystem::Instance().Readable(symfile)) { -            result.AppendErrorWithFormat("symbol file '%s' is not readable", -                                         symfile.GetPath().c_str()); -            result.SetStatus(eReturnStatusFailed); -            return false; -          } -        } else { -          char symfile_path[PATH_MAX]; -          symfile.GetPath(symfile_path, sizeof(symfile_path)); -          result.AppendErrorWithFormat("invalid symbol file path '%s'", -                                       symfile_path); +        auto file = FileSystem::Instance().Open( +            symfile, lldb_private::File::eOpenOptionRead); + +        if (!file) { +          result.AppendErrorWithFormatv("Cannot open '{0}': {1}.", +                                        symfile.GetPath(), +                                        llvm::toString(file.takeError()));            result.SetStatus(eReturnStatusFailed);            return false;          } @@ -401,48 +395,34 @@ protected:            if (module_sp)              module_sp->SetPlatformFileSpec(remote_file);          } +          if (core_file) { -          char core_path[PATH_MAX]; -          core_file.GetPath(core_path, sizeof(core_path)); -          if (FileSystem::Instance().Exists(core_file)) { -            if (!FileSystem::Instance().Readable(core_file)) { -              result.AppendMessageWithFormat( -                  "Core file '%s' is not readable.\n", core_path); -              result.SetStatus(eReturnStatusFailed); -              return false; -            } -            FileSpec core_file_dir; -            core_file_dir.GetDirectory() = core_file.GetDirectory(); -            target_sp->AppendExecutableSearchPaths(core_file_dir); +          FileSpec core_file_dir; +          core_file_dir.GetDirectory() = core_file.GetDirectory(); +          target_sp->AppendExecutableSearchPaths(core_file_dir); -            ProcessSP process_sp(target_sp->CreateProcess( -                GetDebugger().GetListener(), llvm::StringRef(), &core_file)); +          ProcessSP process_sp(target_sp->CreateProcess( +              GetDebugger().GetListener(), llvm::StringRef(), &core_file)); -            if (process_sp) { -              // Seems weird that we Launch a core file, but that is what we -              // do! -              error = process_sp->LoadCore(); +          if (process_sp) { +            // Seems weird that we Launch a core file, but that is what we +            // do! +            error = process_sp->LoadCore(); -              if (error.Fail()) { -                result.AppendError( -                    error.AsCString("can't find plug-in for core file")); -                result.SetStatus(eReturnStatusFailed); -                return false; -              } else { -                result.AppendMessageWithFormat( -                    "Core file '%s' (%s) was loaded.\n", core_path, -                    target_sp->GetArchitecture().GetArchitectureName()); -                result.SetStatus(eReturnStatusSuccessFinishNoResult); -              } -            } else { -              result.AppendErrorWithFormat( -                  "Unable to find process plug-in for core file '%s'\n", -                  core_path); +            if (error.Fail()) { +              result.AppendError( +                  error.AsCString("can't find plug-in for core file"));                result.SetStatus(eReturnStatusFailed); +              return false; +            } else { +              result.AppendMessageWithFormatv("Core file '{0}' ({1}) was loaded.\n", core_file.GetPath(), +                  target_sp->GetArchitecture().GetArchitectureName()); +              result.SetStatus(eReturnStatusSuccessFinishNoResult);              }            } else { -            result.AppendErrorWithFormat("Core file '%s' does not exist\n", -                                         core_path); +            result.AppendErrorWithFormatv( +                "Unable to find process plug-in for core file '{0}'\n", +                core_file.GetPath());              result.SetStatus(eReturnStatusFailed);            }          } else { @@ -525,11 +505,9 @@ public:  protected:    bool DoExecute(Args &args, CommandReturnObject &result) override {      if (args.GetArgumentCount() == 1) { -      bool success = false;        const char *target_idx_arg = args.GetArgumentAtIndex(0); -      uint32_t target_idx = -          StringConvert::ToUInt32(target_idx_arg, UINT32_MAX, 0, &success); -      if (success) { +      uint32_t target_idx; +      if (llvm::to_integer(target_idx_arg, target_idx)) {          TargetList &target_list = GetDebugger().GetTargetList();          const uint32_t num_targets = target_list.GetNumTargets();          if (target_idx < num_targets) { @@ -571,7 +549,7 @@ protected:    }  }; -#pragma mark CommandObjectTargetSelect +#pragma mark CommandObjectTargetDelete  // "target delete" @@ -682,6 +660,41 @@ protected:    OptionGroupBoolean m_cleanup_option;  }; +class CommandObjectTargetShowLaunchEnvironment : public CommandObjectParsed { +public: +  CommandObjectTargetShowLaunchEnvironment(CommandInterpreter &interpreter) +      : CommandObjectParsed( +            interpreter, "target show-launch-environment", +            "Shows the environment being passed to the process when launched, " +            "taking info account 3 settings: target.env-vars, " +            "target.inherit-env and target.unset-env-vars.", +            nullptr, eCommandRequiresTarget) {} + +  ~CommandObjectTargetShowLaunchEnvironment() override = default; + +protected: +  bool DoExecute(Args &args, CommandReturnObject &result) override { +    Target *target = m_exe_ctx.GetTargetPtr(); +    Environment env = target->GetEnvironment(); + +    std::vector<Environment::value_type *> env_vector; +    env_vector.reserve(env.size()); +    for (auto &KV : env) +      env_vector.push_back(&KV); +    std::sort(env_vector.begin(), env_vector.end(), +              [](Environment::value_type *a, Environment::value_type *b) { +                return a->first() < b->first(); +              }); + +    auto &strm = result.GetOutputStream(); +    for (auto &KV : env_vector) +      strm.Format("{0}={1}\n", KV->first(), KV->second); + +    result.SetStatus(eReturnStatusSuccessFinishResult); +    return result.Succeeded(); +  } +}; +  #pragma mark CommandObjectTargetVariable  // "target variable" @@ -841,21 +854,18 @@ protected:      Stream &s = result.GetOutputStream();      if (argc > 0) { - -      // TODO: Convert to entry-based iteration.  Requires converting -      // DumpValueObject. -      for (size_t idx = 0; idx < argc; ++idx) { +      for (const Args::ArgEntry &arg : args) {          VariableList variable_list;          ValueObjectList valobj_list; -        const char *arg = args.GetArgumentAtIndex(idx);          size_t matches = 0;          bool use_var_name = false;          if (m_option_variable.use_regex) { -          RegularExpression regex(llvm::StringRef::withNullAsEmpty(arg)); +          RegularExpression regex( +              llvm::StringRef::withNullAsEmpty(arg.c_str()));            if (!regex.IsValid()) {              result.GetErrorStream().Printf( -                "error: invalid regular expression: '%s'\n", arg); +                "error: invalid regular expression: '%s'\n", arg.c_str());              result.SetStatus(eReturnStatusFailed);              return false;            } @@ -865,14 +875,14 @@ protected:            matches = variable_list.GetSize();          } else {            Status error(Variable::GetValuesForVariableExpressionPath( -              arg, m_exe_ctx.GetBestExecutionContextScope(), +              arg.c_str(), m_exe_ctx.GetBestExecutionContextScope(),                GetVariableCallback, target, variable_list, valobj_list));            matches = variable_list.GetSize();          }          if (matches == 0) {            result.GetErrorStream().Printf( -              "error: can't find global variable '%s'\n", arg); +              "error: can't find global variable '%s'\n", arg.c_str());            result.SetStatus(eReturnStatusFailed);            return false;          } else { @@ -888,7 +898,7 @@ protected:                if (valobj_sp)                  DumpValueObject(s, var_sp, valobj_sp,                                  use_var_name ? var_sp->GetName().GetCString() -                                             : arg); +                                             : arg.c_str());              }            }          } @@ -1163,12 +1173,9 @@ protected:      size_t argc = command.GetArgumentCount();      // check for at least 3 arguments and an odd number of parameters      if (argc >= 3 && argc & 1) { -      bool success = false; - -      uint32_t insert_idx = StringConvert::ToUInt32( -          command.GetArgumentAtIndex(0), UINT32_MAX, 0, &success); +      uint32_t insert_idx; -      if (!success) { +      if (!llvm::to_integer(command.GetArgumentAtIndex(0), insert_idx)) {          result.AppendErrorWithFormat(              "<index> parameter is not an integer: '%s'.\n",              command.GetArgumentAtIndex(0)); @@ -1292,7 +1299,7 @@ static void DumpModuleArchitecture(Stream &strm, Module *module,        module->GetArchitecture().DumpTriple(arch_strm.AsRawOstream());      else        arch_strm.PutCString(module->GetArchitecture().GetArchitectureName()); -    std::string arch_str = arch_strm.GetString(); +    std::string arch_str = std::string(arch_strm.GetString());      if (width)        strm.Printf("%-*s", width, arch_str.c_str()); @@ -1431,11 +1438,9 @@ static void DumpModuleSections(CommandInterpreter &interpreter, Stream &strm,        strm.Printf("Sections for '%s' (%s):\n",                    module->GetSpecificationDescription().c_str(),                    module->GetArchitecture().GetArchitectureName()); -      strm.IndentMore(); -      section_list->Dump(&strm, +      section_list->Dump(strm.AsRawOstream(), strm.GetIndentLevel() + 2,                           interpreter.GetExecutionContext().GetTargetPtr(), true,                           UINT32_MAX); -      strm.IndentLess();      }    }  } @@ -1599,8 +1604,9 @@ static size_t LookupFunctionInModule(CommandInterpreter &interpreter,                              include_inlines, sc_list);      } else {        ConstString function_name(name); -      module->FindFunctions(function_name, nullptr, eFunctionNameTypeAuto, -                            include_symbols, include_inlines, sc_list); +      module->FindFunctions(function_name, CompilerDeclContext(), +                            eFunctionNameTypeAuto, include_symbols, +                            include_inlines, sc_list);      }      num_matches = sc_list.GetSize();      if (num_matches) { @@ -2162,7 +2168,7 @@ protected:    }  }; -#pragma mark CommandObjectTargetModulesDumpSections +#pragma mark CommandObjectTargetModulesDumpClangAST  // Clang AST dumping command @@ -2736,10 +2742,8 @@ protected:                    const char *load_addr_cstr = args.GetArgumentAtIndex(i + 1);                    if (sect_name && load_addr_cstr) {                      ConstString const_sect_name(sect_name); -                    bool success = false; -                    addr_t load_addr = StringConvert::ToUInt64( -                        load_addr_cstr, LLDB_INVALID_ADDRESS, 0, &success); -                    if (success) { +                    addr_t load_addr; +                    if (llvm::to_integer(load_addr_cstr, load_addr)) {                        SectionSP section_sp(                            section_list->FindSectionByName(const_sect_name));                        if (section_sp) { @@ -3022,17 +3026,14 @@ protected:            module_list_ptr = &target->GetImages();          }        } else { -        // TODO: Convert to entry based iteration.  Requires converting -        // FindModulesByName. -        for (size_t i = 0; i < argc; ++i) { +        for (const Args::ArgEntry &arg : command) {            // Dump specified images (by basename or fullpath) -          const char *arg_cstr = command.GetArgumentAtIndex(i);            const size_t num_matches = FindModulesByName( -              target, arg_cstr, module_list, use_global_module_list); +              target, arg.c_str(), module_list, use_global_module_list);            if (num_matches == 0) {              if (argc == 1) {                result.AppendErrorWithFormat("no modules found that match '%s'", -                                           arg_cstr); +                                           arg.c_str());                result.SetStatus(eReturnStatusFailed);                return false;              } @@ -3268,7 +3269,7 @@ public:        switch (short_option) {        case 'a': { -        m_str = option_arg; +        m_str = std::string(option_arg);          m_type = eLookupTypeAddress;          m_addr = OptionArgParser::ToAddress(execution_context, option_arg,                                              LLDB_INVALID_ADDRESS, &error); @@ -3279,7 +3280,7 @@ public:        }        case 'n': -        m_str = option_arg; +        m_str = std::string(option_arg);          m_type = eLookupTypeFunctionOrSymbol;          break; @@ -3603,7 +3604,7 @@ public:          break;        case 's': -        m_str = option_arg; +        m_str = std::string(option_arg);          m_type = eLookupTypeSymbol;          break; @@ -3626,17 +3627,17 @@ public:          break;        case 'F': -        m_str = option_arg; +        m_str = std::string(option_arg);          m_type = eLookupTypeFunction;          break;        case 'n': -        m_str = option_arg; +        m_str = std::string(option_arg);          m_type = eLookupTypeFunctionOrSymbol;          break;        case 't': -        m_str = option_arg; +        m_str = std::string(option_arg);          m_type = eLookupTypeType;          break; @@ -3990,7 +3991,9 @@ public:  private:    // For CommandObjectTargetModules only -  DISALLOW_COPY_AND_ASSIGN(CommandObjectTargetModules); +  CommandObjectTargetModules(const CommandObjectTargetModules &) = delete; +  const CommandObjectTargetModules & +  operator=(const CommandObjectTargetModules &) = delete;  };  class CommandObjectTargetSymbolsAdd : public CommandObjectParsed { @@ -3999,19 +4002,20 @@ public:        : CommandObjectParsed(              interpreter, "target symbols add",              "Add a debug symbol file to one of the target's current modules by " -            "specifying a path to a debug symbols file, or using the options " -            "to specify a module to download symbols for.", +            "specifying a path to a debug symbols file or by using the options " +            "to specify a module.",              "target symbols add <cmd-options> [<symfile>]",              eCommandRequiresTarget),          m_option_group(),          m_file_option(              LLDB_OPT_SET_1, false, "shlib", 's',              CommandCompletions::eModuleCompletion, eArgTypeShlibName, -            "Fullpath or basename for module to find debug symbols for."), +            "Locate the debug symbols for the shared library specified by " +            "name."),          m_current_frame_option(              LLDB_OPT_SET_2, false, "frame", 'F', -            "Locate the debug symbols the currently selected frame.", false, -            true) +            "Locate the debug symbols for the currently selected frame.", +            false, true)    {      m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL, @@ -4053,12 +4057,10 @@ protected:          module_spec.GetFileSpec().GetFilename() = symbol_fspec.GetFilename();      } -    // We now have a module that represents a symbol file that can be used -    // for a module that might exist in the current target, so we need to -    // find that module in the target -    ModuleList matching_module_list; +    // Now module_spec represents a symbol file for a module that might exist +    // in the current target.  Let's find possible matches. +    ModuleList matching_modules; -    size_t num_matches = 0;      // First extract all module specs from the symbol file      lldb_private::ModuleSpecList symfile_module_specs;      if (ObjectFile::GetModuleSpecifications(module_spec.GetSymbolFileSpec(), @@ -4069,34 +4071,30 @@ protected:        target_arch_module_spec.GetArchitecture() = target->GetArchitecture();        if (symfile_module_specs.FindMatchingModuleSpec(target_arch_module_spec,                                                        symfile_module_spec)) { -        // See if it has a UUID?          if (symfile_module_spec.GetUUID().IsValid()) {            // It has a UUID, look for this UUID in the target modules            ModuleSpec symfile_uuid_module_spec;            symfile_uuid_module_spec.GetUUID() = symfile_module_spec.GetUUID();            target->GetImages().FindModules(symfile_uuid_module_spec, -                                          matching_module_list); -          num_matches = matching_module_list.GetSize(); +                                          matching_modules);          }        } -      if (num_matches == 0) { -        // No matches yet, iterate through the module specs to find a UUID -        // value that we can match up to an image in our target -        const size_t num_symfile_module_specs = -            symfile_module_specs.GetSize(); -        for (size_t i = 0; i < num_symfile_module_specs && num_matches == 0; -              ++i) { +      if (matching_modules.IsEmpty()) { +        // No matches yet.  Iterate through the module specs to find a UUID +        // value that we can match up to an image in our target. +        const size_t num_symfile_module_specs = symfile_module_specs.GetSize(); +        for (size_t i = 0; +             i < num_symfile_module_specs && matching_modules.IsEmpty(); ++i) {            if (symfile_module_specs.GetModuleSpecAtIndex(                    i, symfile_module_spec)) {              if (symfile_module_spec.GetUUID().IsValid()) { -              // It has a UUID, look for this UUID in the target modules +              // It has a UUID.  Look for this UUID in the target modules.                ModuleSpec symfile_uuid_module_spec;                symfile_uuid_module_spec.GetUUID() =                    symfile_module_spec.GetUUID();                target->GetImages().FindModules(symfile_uuid_module_spec, -                                              matching_module_list); -              num_matches = matching_module_list.GetSize(); +                                              matching_modules);              }            }          } @@ -4104,13 +4102,11 @@ protected:      }      // Just try to match up the file by basename if we have no matches at -    // this point -    if (num_matches == 0) { -      target->GetImages().FindModules(module_spec, matching_module_list); -      num_matches = matching_module_list.GetSize(); -    } +    // this point.  For example, module foo might have symbols in foo.debug. +    if (matching_modules.IsEmpty()) +      target->GetImages().FindModules(module_spec, matching_modules); -    while (num_matches == 0) { +    while (matching_modules.IsEmpty()) {        ConstString filename_no_extension(            module_spec.GetFileSpec().GetFileNameStrippingExtension());        // Empty string returned, let's bail @@ -4123,17 +4119,20 @@ protected:        // Replace basename with one fewer extension        module_spec.GetFileSpec().GetFilename() = filename_no_extension; -      target->GetImages().FindModules(module_spec, matching_module_list); -      num_matches = matching_module_list.GetSize(); +      target->GetImages().FindModules(module_spec, matching_modules);      } -    if (num_matches > 1) { +    if (matching_modules.GetSize() > 1) {        result.AppendErrorWithFormat("multiple modules match symbol file '%s', "                                     "use the --uuid option to resolve the "                                     "ambiguity.\n",                                     symfile_path); -    } else if (num_matches == 1) { -      ModuleSP module_sp(matching_module_list.GetModuleAtIndex(0)); +      result.SetStatus(eReturnStatusFailed); +      return false; +    } + +    if (matching_modules.GetSize() == 1) { +      ModuleSP module_sp(matching_modules.GetModuleAtIndex(0));        // The module has not yet created its symbol vendor, we can just give        // the existing target module the symfile path to use for when it @@ -4144,7 +4143,6 @@ protected:            module_sp->GetSymbolFile(true, &result.GetErrorStream());        if (symbol_file) {          ObjectFile *object_file = symbol_file->GetObjectFile(); -          if (object_file && object_file->GetFileSpec() == symbol_fspec) {            // Provide feedback that the symfile has been successfully added.            const FileSpec &module_fs = module_sp->GetFileSpec(); @@ -4163,7 +4161,7 @@ protected:            Status error;            StreamString feedback_stream;            module_sp->LoadScriptingResourceInTarget(target, error, -                                                    &feedback_stream); +                                                   &feedback_stream);            if (error.Fail() && error.AsCString())              result.AppendWarningWithFormat(                  "unable to load scripting data for module %s - error " @@ -4173,7 +4171,7 @@ protected:                      .GetCString(),                  error.AsCString());            else if (feedback_stream.GetSize()) -            result.AppendWarningWithFormat("%s", feedback_stream.GetData()); +            result.AppendWarning(feedback_stream.GetData());            flush = true;            result.SetStatus(eReturnStatusSuccessFinishResult); @@ -4184,7 +4182,6 @@ protected:        module_sp->SetSymbolFileFileSpec(FileSpec());      } -    namespace fs = llvm::sys::fs;      StreamString ss_symfile_uuid;      if (module_spec.GetUUID().IsValid()) {        ss_symfile_uuid << " ("; @@ -4194,7 +4191,7 @@ protected:      result.AppendErrorWithFormat(          "symbol file '%s'%s does not match any existing module%s\n",          symfile_path, ss_symfile_uuid.GetData(), -        !fs::is_regular_file(symbol_fspec.GetPath()) +        !llvm::sys::fs::is_regular_file(symbol_fspec.GetPath())              ? "\n       please specify the full path to the symbol file"              : "");      result.SetStatus(eReturnStatusFailed); @@ -4394,7 +4391,9 @@ public:  private:    // For CommandObjectTargetModules only -  DISALLOW_COPY_AND_ASSIGN(CommandObjectTargetSymbols); +  CommandObjectTargetSymbols(const CommandObjectTargetSymbols &) = delete; +  const CommandObjectTargetSymbols & +  operator=(const CommandObjectTargetSymbols &) = delete;  };  #pragma mark CommandObjectTargetStopHookAdd @@ -4427,7 +4426,7 @@ public:        switch (short_option) {        case 'c': -        m_class_name = option_arg; +        m_class_name = std::string(option_arg);          m_sym_ctx_specified = true;          break; @@ -4464,18 +4463,18 @@ public:          break;        case 'n': -        m_function_name = option_arg; +        m_function_name = std::string(option_arg);          m_func_name_type_mask |= eFunctionNameTypeAuto;          m_sym_ctx_specified = true;          break;        case 'f': -        m_file_name = option_arg; +        m_file_name = std::string(option_arg);          m_sym_ctx_specified = true;          break;        case 's': -        m_module_name = option_arg; +        m_module_name = std::string(option_arg);          m_sym_ctx_specified = true;          break; @@ -4487,12 +4486,12 @@ public:          break;        case 'T': -        m_thread_name = option_arg; +        m_thread_name = std::string(option_arg);          m_thread_specified = true;          break;        case 'q': -        m_queue_name = option_arg; +        m_queue_name = std::string(option_arg);          m_thread_specified = true;          break; @@ -4505,7 +4504,7 @@ public:        case 'o':          m_use_one_liner = true; -        m_one_liner.push_back(option_arg); +        m_one_liner.push_back(std::string(option_arg));          break;        default: @@ -4615,8 +4614,8 @@ protected:      //  First step, make the specifier.      std::unique_ptr<SymbolContextSpecifier> specifier_up;      if (m_options.m_sym_ctx_specified) { -      specifier_up.reset( -          new SymbolContextSpecifier(GetDebugger().GetSelectedTarget())); +      specifier_up = std::make_unique<SymbolContextSpecifier>( +          GetDebugger().GetSelectedTarget());        if (!m_options.m_module_name.empty()) {          specifier_up->AddSpecification( @@ -4725,18 +4724,15 @@ protected:          target.RemoveAllStopHooks();        }      } else { -      bool success;        for (size_t i = 0; i < num_args; i++) { -        lldb::user_id_t user_id = StringConvert::ToUInt32( -            command.GetArgumentAtIndex(i), 0, 0, &success); -        if (!success) { +        lldb::user_id_t user_id; +        if (!llvm::to_integer(command.GetArgumentAtIndex(i), user_id)) {            result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",                                         command.GetArgumentAtIndex(i));            result.SetStatus(eReturnStatusFailed);            return false;          } -        success = target.RemoveStopHookByID(user_id); -        if (!success) { +        if (!target.RemoveStopHookByID(user_id)) {            result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",                                         command.GetArgumentAtIndex(i));            result.SetStatus(eReturnStatusFailed); @@ -4774,9 +4770,8 @@ protected:        target.SetAllStopHooksActiveState(m_enable);      } else {        for (size_t i = 0; i < num_args; i++) { -        lldb::user_id_t user_id = StringConvert::ToUInt32( -            command.GetArgumentAtIndex(i), 0, 0, &success); -        if (!success) { +        lldb::user_id_t user_id; +        if (!llvm::to_integer(command.GetArgumentAtIndex(i), user_id)) {            result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",                                         command.GetArgumentAtIndex(i));            result.SetStatus(eReturnStatusFailed); @@ -4881,6 +4876,9 @@ CommandObjectMultiwordTarget::CommandObjectMultiwordTarget(                   CommandObjectSP(new CommandObjectTargetList(interpreter)));    LoadSubCommand("select",                   CommandObjectSP(new CommandObjectTargetSelect(interpreter))); +  LoadSubCommand("show-launch-environment", +                 CommandObjectSP(new CommandObjectTargetShowLaunchEnvironment( +                     interpreter)));    LoadSubCommand(        "stop-hook",        CommandObjectSP(new CommandObjectMultiwordTargetStopHooks(interpreter))); diff --git a/lldb/source/Commands/CommandObjectTarget.h b/lldb/source/Commands/CommandObjectTarget.h index bf1dae6bfdc1..94afc00064c8 100644 --- a/lldb/source/Commands/CommandObjectTarget.h +++ b/lldb/source/Commands/CommandObjectTarget.h @@ -6,8 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectTarget_h_ -#define liblldb_CommandObjectTarget_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTTARGET_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTTARGET_H  #include "lldb/Interpreter/CommandObjectMultiword.h" @@ -24,4 +24,4 @@ public:  } // namespace lldb_private -#endif // liblldb_CommandObjectTarget_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTTARGET_H diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index 83c7cb50d142..f0ad1798fec6 100644 --- a/lldb/source/Commands/CommandObjectThread.cpp +++ b/lldb/source/Commands/CommandObjectThread.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectThread.cpp ---------------------------------*- C++ -*-===// +//===-- CommandObjectThread.cpp -------------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -10,7 +10,6 @@  #include "lldb/Core/ValueObject.h"  #include "lldb/Host/OptionParser.h" -#include "lldb/Host/StringConvert.h"  #include "lldb/Interpreter/CommandInterpreter.h"  #include "lldb/Interpreter/CommandReturnObject.h"  #include "lldb/Interpreter/OptionArgParser.h" @@ -109,11 +108,8 @@ public:            process->GetThreadList().GetMutex());        for (size_t i = 0; i < num_args; i++) { -        bool success; - -        uint32_t thread_idx = StringConvert::ToUInt32( -            command.GetArgumentAtIndex(i), 0, 0, &success); -        if (!success) { +        uint32_t thread_idx; +        if (!llvm::to_integer(command.GetArgumentAtIndex(i), thread_idx)) {            result.AppendErrorWithFormat("invalid thread specification: \"%s\"\n",                                         command.GetArgumentAtIndex(i));            result.SetStatus(eReturnStatusFailed); @@ -464,12 +460,12 @@ public:      case 'r':        m_avoid_regexp.clear(); -      m_avoid_regexp.assign(option_arg); +      m_avoid_regexp.assign(std::string(option_arg));        break;      case 't':        m_step_in_target.clear(); -      m_step_in_target.assign(option_arg); +      m_step_in_target.assign(std::string(option_arg));        break;      default: @@ -565,9 +561,9 @@ protected:        }      } else {        const char *thread_idx_cstr = command.GetArgumentAtIndex(0); -      uint32_t step_thread_idx = -          StringConvert::ToUInt32(thread_idx_cstr, LLDB_INVALID_INDEX32); -      if (step_thread_idx == LLDB_INVALID_INDEX32) { +      uint32_t step_thread_idx; + +      if (!llvm::to_integer(thread_idx_cstr, step_thread_idx)) {          result.AppendErrorWithFormat("invalid thread index '%s'.\n",                                       thread_idx_cstr);          result.SetStatus(eReturnStatusFailed); @@ -775,7 +771,6 @@ protected:      return result.Succeeded();    } -protected:    StepType m_step_type;    StepScope m_step_scope;    ThreadStepScopeOptionGroup m_options; @@ -1096,9 +1091,7 @@ protected:          size_t num_args = command.GetArgumentCount();          for (size_t i = 0; i < num_args; i++) {            uint32_t line_number; -          line_number = StringConvert::ToUInt32(command.GetArgumentAtIndex(i), -                                                UINT32_MAX); -          if (line_number == UINT32_MAX) { +          if (!llvm::to_integer(command.GetArgumentAtIndex(i), line_number)) {              result.AppendErrorWithFormat("invalid line number: '%s'.\n",                                           command.GetArgumentAtIndex(i));              result.SetStatus(eReturnStatusFailed); @@ -1322,8 +1315,13 @@ protected:        return false;      } -    uint32_t index_id = -        StringConvert::ToUInt32(command.GetArgumentAtIndex(0), 0, 0); +    uint32_t index_id; +    if (!llvm::to_integer(command.GetArgumentAtIndex(0), index_id)) { +      result.AppendErrorWithFormat("Invalid thread index '%s'", +                                   command.GetArgumentAtIndex(0)); +      result.SetStatus(eReturnStatusFailed); +      return false; +    }      Thread *new_thread =          process->GetThreadList().FindThreadByIndexID(index_id).get(); @@ -1833,25 +1831,36 @@ public:      Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,                            ExecutionContext *execution_context) override { -      Status error;        const int short_option = m_getopt_table[option_idx].val;        switch (short_option) {        case 'i':          m_internal = true;          break; +      case 't': +        lldb::tid_t tid; +        if (option_arg.getAsInteger(0, tid)) +          return Status("invalid tid: '%s'.", option_arg.str().c_str()); +        m_tids.push_back(tid); +        break; +      case 'u': +        m_unreported = false; +        break;        case 'v':          m_verbose = true;          break;        default:          llvm_unreachable("Unimplemented option");        } -      return error; +      return {};      }      void OptionParsingStarting(ExecutionContext *execution_context) override {        m_verbose = false;        m_internal = false; +      m_unreported = true; // The variable is "skip unreported" and we want to +                           // skip unreported by default. +      m_tids.clear();      }      llvm::ArrayRef<OptionDefinition> GetDefinitions() override { @@ -1861,6 +1870,8 @@ public:      // Instance variables to hold the values for command options.      bool m_verbose;      bool m_internal; +    bool m_unreported; +    std::vector<lldb::tid_t> m_tids;    };    CommandObjectThreadPlanList(CommandInterpreter &interpreter) @@ -1879,25 +1890,59 @@ public:    Options *GetOptions() override { return &m_options; } +  bool DoExecute(Args &command, CommandReturnObject &result) override { +    // If we are reporting all threads, dispatch to the Process to do that: +    if (command.GetArgumentCount() == 0 && m_options.m_tids.empty()) { +      Stream &strm = result.GetOutputStream(); +      DescriptionLevel desc_level = m_options.m_verbose +                                        ? eDescriptionLevelVerbose +                                        : eDescriptionLevelFull; +      m_exe_ctx.GetProcessPtr()->DumpThreadPlans( +          strm, desc_level, m_options.m_internal, true, m_options.m_unreported); +      result.SetStatus(eReturnStatusSuccessFinishResult); +      return true; +    } else { +      // Do any TID's that the user may have specified as TID, then do any +      // Thread Indexes... +      if (!m_options.m_tids.empty()) { +        Process *process = m_exe_ctx.GetProcessPtr(); +        StreamString tmp_strm; +        for (lldb::tid_t tid : m_options.m_tids) { +          bool success = process->DumpThreadPlansForTID( +              tmp_strm, tid, eDescriptionLevelFull, m_options.m_internal, +              true /* condense_trivial */, m_options.m_unreported); +          // If we didn't find a TID, stop here and return an error. +          if (!success) { +            result.SetError("Error dumping plans:"); +            result.AppendError(tmp_strm.GetString()); +            result.SetStatus(eReturnStatusFailed); +            return false; +          } +          // Otherwise, add our data to the output: +          result.GetOutputStream() << tmp_strm.GetString(); +        } +      } +      return CommandObjectIterateOverThreads::DoExecute(command, result); +    } +  } +  protected:    bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { -    ThreadSP thread_sp = -        m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); -    if (!thread_sp) { -      result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n", -                                   tid); -      result.SetStatus(eReturnStatusFailed); -      return false; -    } +    // If we have already handled this from a -t option, skip it here. +    if (std::find(m_options.m_tids.begin(), m_options.m_tids.end(), tid) != +        m_options.m_tids.end()) +      return true; -    Thread *thread = thread_sp.get(); +    Process *process = m_exe_ctx.GetProcessPtr();      Stream &strm = result.GetOutputStream();      DescriptionLevel desc_level = eDescriptionLevelFull;      if (m_options.m_verbose)        desc_level = eDescriptionLevelVerbose; -    thread->DumpThreadPlans(&strm, desc_level, m_options.m_internal, true); +    process->DumpThreadPlansForTID(strm, tid, desc_level, m_options.m_internal, +                                   true /* condense_trivial */, +                                   m_options.m_unreported);      return true;    } @@ -1943,10 +1988,8 @@ public:        return false;      } -    bool success; -    uint32_t thread_plan_idx = -        StringConvert::ToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success); -    if (!success) { +    uint32_t thread_plan_idx; +    if (!llvm::to_integer(args.GetArgumentAtIndex(0), thread_plan_idx)) {        result.AppendErrorWithFormat(            "Invalid thread index: \"%s\" - should be unsigned int.",            args.GetArgumentAtIndex(0)); @@ -1974,6 +2017,71 @@ public:    }  }; +class CommandObjectThreadPlanPrune : public CommandObjectParsed { +public: +  CommandObjectThreadPlanPrune(CommandInterpreter &interpreter) +      : CommandObjectParsed(interpreter, "thread plan prune", +                            "Removes any thread plans associated with " +                            "currently unreported threads.  " +                            "Specify one or more TID's to remove, or if no " +                            "TID's are provides, remove threads for all " +                            "unreported threads", +                            nullptr, +                            eCommandRequiresProcess | +                                eCommandTryTargetAPILock | +                                eCommandProcessMustBeLaunched | +                                eCommandProcessMustBePaused) { +    CommandArgumentEntry arg; +    CommandArgumentData tid_arg; + +    // Define the first (and only) variant of this arg. +    tid_arg.arg_type = eArgTypeThreadID; +    tid_arg.arg_repetition = eArgRepeatStar; + +    // There is only one variant this argument could be; put it into the +    // argument entry. +    arg.push_back(tid_arg); + +    // Push the data for the first argument into the m_arguments vector. +    m_arguments.push_back(arg); +  } + +  ~CommandObjectThreadPlanPrune() override = default; + +  bool DoExecute(Args &args, CommandReturnObject &result) override { +    Process *process = m_exe_ctx.GetProcessPtr(); +     +    if (args.GetArgumentCount() == 0) { +      process->PruneThreadPlans(); +      result.SetStatus(eReturnStatusSuccessFinishNoResult); +      return true;   +    } + +    const size_t num_args = args.GetArgumentCount(); + +    std::lock_guard<std::recursive_mutex> guard( +        process->GetThreadList().GetMutex()); + +    for (size_t i = 0; i < num_args; i++) { +      lldb::tid_t tid; +      if (!llvm::to_integer(args.GetArgumentAtIndex(i), tid)) { +        result.AppendErrorWithFormat("invalid thread specification: \"%s\"\n", +                                     args.GetArgumentAtIndex(i)); +        result.SetStatus(eReturnStatusFailed); +        return false; +      } +      if (!process->PruneThreadPlansForTID(tid)) { +        result.AppendErrorWithFormat("Could not find unreported tid: \"%s\"\n", +                                     args.GetArgumentAtIndex(i)); +        result.SetStatus(eReturnStatusFailed); +        return false; +      } +    } +    result.SetStatus(eReturnStatusSuccessFinishNoResult); +    return true; +  } +}; +  // CommandObjectMultiwordThreadPlan  class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword { @@ -1988,6 +2096,9 @@ public:      LoadSubCommand(          "discard",          CommandObjectSP(new CommandObjectThreadPlanDiscard(interpreter))); +    LoadSubCommand( +        "prune", +        CommandObjectSP(new CommandObjectThreadPlanPrune(interpreter)));    }    ~CommandObjectMultiwordThreadPlan() override = default; diff --git a/lldb/source/Commands/CommandObjectThread.h b/lldb/source/Commands/CommandObjectThread.h index 77729ceecd63..3ca6a2159501 100644 --- a/lldb/source/Commands/CommandObjectThread.h +++ b/lldb/source/Commands/CommandObjectThread.h @@ -6,8 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectThread_h_ -#define liblldb_CommandObjectThread_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTTHREAD_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTTHREAD_H  #include "lldb/Interpreter/CommandObjectMultiword.h" @@ -22,4 +22,4 @@ public:  } // namespace lldb_private -#endif // liblldb_CommandObjectThread_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTTHREAD_H diff --git a/lldb/source/Commands/CommandObjectType.cpp b/lldb/source/Commands/CommandObjectType.cpp index 87c107cfb943..b2020f26621f 100644 --- a/lldb/source/Commands/CommandObjectType.cpp +++ b/lldb/source/Commands/CommandObjectType.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectType.cpp -----------------------------------*- C++ -*-===// +//===-- CommandObjectType.cpp ---------------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -531,7 +531,7 @@ private:          m_skip_pointers = true;          break;        case 'w': -        m_category.assign(option_value); +        m_category.assign(std::string(option_value));          break;        case 'r':          m_skip_references = true; @@ -540,7 +540,7 @@ private:          m_regex = true;          break;        case 't': -        m_custom_type_name.assign(option_value); +        m_custom_type_name.assign(std::string(option_value));          break;        default:          llvm_unreachable("Unimplemented option"); @@ -1031,8 +1031,8 @@ protected:      std::unique_ptr<RegularExpression> formatter_regex;      if (m_options.m_category_regex.OptionWasSet()) { -      category_regex.reset(new RegularExpression( -          m_options.m_category_regex.GetCurrentValueAsRef())); +      category_regex = std::make_unique<RegularExpression>( +          m_options.m_category_regex.GetCurrentValueAsRef());        if (!category_regex->IsValid()) {          result.AppendErrorWithFormat(              "syntax error in category regular expression '%s'", @@ -1044,8 +1044,8 @@ protected:      if (argc == 1) {        const char *arg = command.GetArgumentAtIndex(0); -      formatter_regex.reset( -          new RegularExpression(llvm::StringRef::withNullAsEmpty(arg))); +      formatter_regex = std::make_unique<RegularExpression>( +          llvm::StringRef::withNullAsEmpty(arg));        if (!formatter_regex->IsValid()) {          result.AppendErrorWithFormat("syntax error in regular expression '%s'",                                       arg); @@ -1206,11 +1206,11 @@ Status CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue(      m_name.SetString(option_arg);      break;    case 'o': -    m_python_script = option_arg; +    m_python_script = std::string(option_arg);      m_is_add_script = true;      break;    case 'F': -    m_python_function = option_arg; +    m_python_function = std::string(option_arg);      m_is_add_script = true;      break;    case 'P': @@ -1326,7 +1326,7 @@ bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(          return false;        } -      options->m_target_types << entry.ref(); +      options->m_target_types << std::string(entry.ref());      }      m_interpreter.GetPythonCommandsFromIOHandler( @@ -2092,7 +2092,8 @@ protected:      if (argc == 1) {        const char *arg = command.GetArgumentAtIndex(0); -      regex.reset(new RegularExpression(llvm::StringRef::withNullAsEmpty(arg))); +      regex = std::make_unique<RegularExpression>( +          llvm::StringRef::withNullAsEmpty(arg));        if (!regex->IsValid()) {          result.AppendErrorWithFormat(              "syntax error in category regular expression '%s'", arg); @@ -2225,7 +2226,7 @@ bool CommandObjectTypeSynthAdd::Execute_HandwritePython(        return false;      } -    options->m_target_types << entry.ref(); +    options->m_target_types << std::string(entry.ref());    }    m_interpreter.GetPythonCommandsFromIOHandler( @@ -2390,7 +2391,7 @@ private:                                           option_arg.str().c_str());          break;        case 'c': -        m_expr_paths.push_back(option_arg); +        m_expr_paths.push_back(std::string(option_arg));          has_child_list = true;          break;        case 'p': @@ -2705,7 +2706,7 @@ public:        return true;      }); -    m_cmd_help_long = stream.GetString(); +    m_cmd_help_long = std::string(stream.GetString());      return m_cmd_help_long;    } diff --git a/lldb/source/Commands/CommandObjectType.h b/lldb/source/Commands/CommandObjectType.h index 938e481a6b87..1c081abe2be4 100644 --- a/lldb/source/Commands/CommandObjectType.h +++ b/lldb/source/Commands/CommandObjectType.h @@ -6,8 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectType_h_ -#define liblldb_CommandObjectType_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTTYPE_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTTYPE_H  #include "lldb/Interpreter/CommandObjectMultiword.h" @@ -22,4 +22,4 @@ public:  } // namespace lldb_private -#endif // liblldb_CommandObjectType_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTTYPE_H diff --git a/lldb/source/Commands/CommandObjectVersion.cpp b/lldb/source/Commands/CommandObjectVersion.cpp index 227d5d132d96..065cbe4660d3 100644 --- a/lldb/source/Commands/CommandObjectVersion.cpp +++ b/lldb/source/Commands/CommandObjectVersion.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectVersion.cpp --------------------------------*- C++ -*-===// +//===-- CommandObjectVersion.cpp ------------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Commands/CommandObjectVersion.h b/lldb/source/Commands/CommandObjectVersion.h index 30f44aeb1658..dce1a8d67b88 100644 --- a/lldb/source/Commands/CommandObjectVersion.h +++ b/lldb/source/Commands/CommandObjectVersion.h @@ -6,8 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectVersion_h_ -#define liblldb_CommandObjectVersion_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTVERSION_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTVERSION_H  #include "lldb/Interpreter/CommandObject.h" @@ -27,4 +27,4 @@ protected:  } // namespace lldb_private -#endif // liblldb_CommandObjectVersion_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTVERSION_H diff --git a/lldb/source/Commands/CommandObjectWatchpoint.cpp b/lldb/source/Commands/CommandObjectWatchpoint.cpp index c965d354f734..ce4662930a7c 100644 --- a/lldb/source/Commands/CommandObjectWatchpoint.cpp +++ b/lldb/source/Commands/CommandObjectWatchpoint.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectWatchpoint.cpp -----------------------------*- C++ -*-===// +//===-- CommandObjectWatchpoint.cpp ---------------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -41,7 +41,7 @@ static bool CheckTargetForWatchpointOperations(Target *target,    bool process_is_valid =        target->GetProcessSP() && target->GetProcessSP()->IsAlive();    if (!process_is_valid) { -    result.AppendError("Thre's no process or it is not alive."); +    result.AppendError("There's no process or it is not alive.");      result.SetStatus(eReturnStatusFailed);      return false;    } @@ -692,7 +692,7 @@ public:        switch (short_option) {        case 'c': -        m_condition = option_arg; +        m_condition = std::string(option_arg);          m_condition_passed = true;          break;        default: @@ -934,7 +934,7 @@ protected:          StreamString ss;          // True to show fullpath for declaration file.          var_sp->GetDeclaration().DumpStopContext(&ss, true); -        wp->SetDeclInfo(ss.GetString()); +        wp->SetDeclInfo(std::string(ss.GetString()));        }        output_stream.Printf("Watchpoint created: ");        wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); @@ -1038,7 +1038,7 @@ protected:      // set a watchpoint.      if (raw_command.trim().empty()) {        result.GetErrorStream().Printf("error: required argument missing; " -                                     "specify an expression to evaulate into " +                                     "specify an expression to evaluate into "                                       "the address to watch for\n");        result.SetStatus(eReturnStatusFailed);        return false; @@ -1070,6 +1070,8 @@ protected:        result.GetErrorStream().Printf(            "error: expression evaluation of address to watch failed\n");        result.GetErrorStream() << "expression evaluated: \n" << expr << "\n"; +      if (valobj_sp && !valobj_sp->GetError().Success()) +        result.GetErrorStream() << valobj_sp->GetError().AsCString() << "\n";        result.SetStatus(eReturnStatusFailed);        return false;      } diff --git a/lldb/source/Commands/CommandObjectWatchpoint.h b/lldb/source/Commands/CommandObjectWatchpoint.h index 4f4f80bbd620..87f9f4383bd2 100644 --- a/lldb/source/Commands/CommandObjectWatchpoint.h +++ b/lldb/source/Commands/CommandObjectWatchpoint.h @@ -6,8 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectWatchpoint_h_ -#define liblldb_CommandObjectWatchpoint_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTWATCHPOINT_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTWATCHPOINT_H  #include "lldb/Interpreter/CommandObjectMultiword.h"  #include "lldb/Interpreter/OptionGroupWatchpoint.h" @@ -28,4 +28,4 @@ public:  } // namespace lldb_private -#endif // liblldb_CommandObjectWatchpoint_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTWATCHPOINT_H diff --git a/lldb/source/Commands/CommandObjectWatchpointCommand.cpp b/lldb/source/Commands/CommandObjectWatchpointCommand.cpp index 1b83e885d27e..fe3052a775a2 100644 --- a/lldb/source/Commands/CommandObjectWatchpointCommand.cpp +++ b/lldb/source/Commands/CommandObjectWatchpointCommand.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectWatchpointCommand.cpp ----------------------*- C++ -*-===// +//===-- CommandObjectWatchpointCommand.cpp --------------------------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -39,7 +39,7 @@ static constexpr OptionEnumValueElement g_script_option_enumeration[] = {      {          eScriptLanguageLua,          "lua", -        "Commands are in the Python language.", +        "Commands are in the Lua language.",      },      {          eSortOrderByName, @@ -282,12 +282,12 @@ are no syntax errors may indicate that a function was declared but never called.        ExecutionContext exe_ctx(context->exe_ctx_ref);        Target *target = exe_ctx.GetTargetPtr();        if (target) { -        CommandReturnObject result;          Debugger &debugger = target->GetDebugger(); +        CommandReturnObject result(debugger.GetUseColor()); +          // Rig up the results secondary output stream to the debugger's, so the          // output will come out synchronously if the debugger is set up that          // way. -          StreamSP output_stream(debugger.GetAsyncOutputStream());          StreamSP error_stream(debugger.GetAsyncErrorStream());          result.SetImmediateOutputStream(output_stream); @@ -327,7 +327,7 @@ are no syntax errors may indicate that a function was declared but never called.        switch (short_option) {        case 'o':          m_use_one_liner = true; -        m_one_liner = option_arg; +        m_one_liner = std::string(option_arg);          break;        case 's': @@ -359,7 +359,7 @@ are no syntax errors may indicate that a function was declared but never called.        case 'F':          m_use_one_liner = false; -        m_function_name.assign(option_arg); +        m_function_name.assign(std::string(option_arg));          break;        default: diff --git a/lldb/source/Commands/CommandObjectWatchpointCommand.h b/lldb/source/Commands/CommandObjectWatchpointCommand.h index 6fbc9c741617..b3cb70d08985 100644 --- a/lldb/source/Commands/CommandObjectWatchpointCommand.h +++ b/lldb/source/Commands/CommandObjectWatchpointCommand.h @@ -6,8 +6,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_CommandObjectWatchpointCommand_h_ -#define liblldb_CommandObjectWatchpointCommand_h_ +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTWATCHPOINTCOMMAND_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTWATCHPOINTCOMMAND_H  #include "lldb/Interpreter/CommandObjectMultiword.h" @@ -24,4 +24,4 @@ public:  } // namespace lldb_private -#endif // liblldb_CommandObjectWatchpointCommand_h_ +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTWATCHPOINTCOMMAND_H diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td index 850df133a429..d6f1e0a3c96d 100644 --- a/lldb/source/Commands/Options.td +++ b/lldb/source/Commands/Options.td @@ -39,6 +39,11 @@ let Command = "settings read" in {      Desc<"The file from which to read the settings.">;  } +let Command = "settings clear" in { +  def setclear_all : Option<"all", "a">, +    Desc<"Clear all settings.">; +} +  let Command = "breakpoint list" in {    // FIXME: We need to add an "internal" command, and then add this sort of    // thing to it. But I need to see it for now, and don't want to wait. @@ -115,6 +120,8 @@ let Command = "breakpoint set" in {    def breakpoint_set_line : Option<"line", "l">, Group<1>, Arg<"LineNum">,      Required,      Desc<"Specifies the line number on which to set this breakpoint.">; +  def breakpoint_set_column : Option<"column", "u">, Group<1>, Arg<"ColumnNum">, +    Desc<"Specifies the column number on which to set this breakpoint.">;    def breakpoint_set_address : Option<"address", "a">, Group<2>,      Arg<"AddressOrExpression">, Required,      Desc<"Set the breakpoint at the specified address.  If the address maps " @@ -150,7 +157,7 @@ let Command = "breakpoint set" in {      "multiple times tomake one breakpoint for multiple methods.">;    def breakpoint_set_func_regex : Option<"func-regex", "r">, Group<7>,      Arg<"RegularExpression">, Required, Desc<"Set the breakpoint by function " -    "name, evaluating a regular-expression to findthe function name(s).">; +    "name, evaluating a regular-expression to find the function name(s).">;    def breakpoint_set_basename : Option<"basename", "b">, Group<8>,      Arg<"FunctionName">, Required, Completion<"Symbol">,      Desc<"Set the breakpoint by function basename (C++ namespaces and arguments" @@ -304,7 +311,7 @@ let Command = "disassemble" in {      Desc<"Address at which to start disassembling.">;    def disassemble_options_end_address : Option<"end-address", "e">, Group<1>,      Arg<"AddressOrExpression">, Desc<"Address at which to end disassembling.">; -  def disassemble_options_count : Option<"count", "c">, Groups<[2,3,4,5]>, +  def disassemble_options_count : Option<"count", "c">, Groups<[2,3,4,5,7]>,      Arg<"NumLines">, Desc<"Number of instructions to display.">;    def disassemble_options_name : Option<"name", "n">, Group<3>,      Arg<"FunctionName">, Completion<"Symbol">, @@ -319,6 +326,8 @@ let Command = "disassemble" in {    def disassemble_options_address : Option<"address", "a">, Group<7>,      Arg<"AddressOrExpression">,      Desc<"Disassemble function containing this address.">; +  def disassemble_options_force : Option<"force", "\\x01">, Groups<[2,3,4,5,7]>, +    Desc<"Force dissasembly of large functions.">;  }  let Command = "expression" in { @@ -382,7 +391,8 @@ let Command = "frame recognizer add" in {      "to.">;    def frame_recognizer_function : Option<"function", "n">, Arg<"Name">,      Completion<"Symbol">, -    Desc<"Name of the function that this recognizer applies to.">; +    Desc<"Name of the function that this recognizer applies to. " +         "Can be specified more than once except if -x|--regex is provided.">;    def frame_recognizer_python_class : Option<"python-class", "l">, Group<2>,      Arg<"PythonClass">,      Desc<"Give the name of a Python class to use for this frame recognizer.">; @@ -614,6 +624,8 @@ let Command = "platform process attach" in {  }  let Command = "platform shell" in { +  def platform_shell_host : Option<"host", "h">, +    Desc<"Run the commands on the host shell when enabled.">;    def platform_shell_timeout : Option<"timeout", "t">, Arg<"Value">,      Desc<"Seconds to wait for the remote host to finish running the command.">;  } @@ -668,6 +680,11 @@ let Command = "process handle" in {      Desc<"Whether or not the signal should be passed to the process.">;  } +let Command = "process status" in { +  def process_status_verbose : Option<"verbose", "v">, Group<1>, +    Desc<"Show verbose process status including extended crash information.">; +} +  let Command = "script import" in {    def script_import_allow_reload : Option<"allow-reload", "r">, Group<1>,      Desc<"Allow the script to be loaded even if it was already loaded before. " @@ -688,6 +705,7 @@ let Command = "script add" in {      Desc<"Set the synchronicity of this command's executions with regard to "      "LLDB event system.">;  } +  let Command = "source info" in {    def source_info_count : Option<"count", "c">, Arg<"Count">,      Desc<"The number of line entries to display.">; @@ -956,6 +974,11 @@ let Command = "thread plan list" in {      Desc<"Display more information about the thread plans">;    def thread_plan_list_internal : Option<"internal", "i">, Group<1>,      Desc<"Display internal as well as user thread plans">; +  def thread_plan_list_thread_id : Option<"thread-id", "t">, Group<1>, +    Arg<"ThreadID">, Desc<"List the thread plans for this TID, can be " +    "specified more than once.">; +  def thread_plan_list_unreported : Option<"unreported", "u">, Group<1>, +    Desc<"Display thread plans for unreported threads">;  }  let Command = "type summary add" in {  | 
