diff options
Diffstat (limited to 'lldb/source/Commands')
58 files changed, 24670 insertions, 28378 deletions
diff --git a/lldb/source/Commands/CommandCompletions.cpp b/lldb/source/Commands/CommandCompletions.cpp index dd0ecb4..9d70f40 100644 --- a/lldb/source/Commands/CommandCompletions.cpp +++ b/lldb/source/Commands/CommandCompletions.cpp @@ -37,447 +37,368 @@ 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. + 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. }; -bool -CommandCompletions::InvokeCommonCompletionCallbacks(CommandInterpreter &interpreter, - uint32_t completion_mask, - const char *completion_str, - int match_start_point, - int max_return_elements, - SearchFilter *searcher, - bool &word_complete, - StringList &matches) -{ - bool handled = false; - - if (completion_mask & eCustomCompletion) - return false; - - for (int i = 0; ; i++) - { - if (g_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) - { - handled = true; - g_common_completions[i].callback (interpreter, - completion_str, - match_start_point, - max_return_elements, - searcher, - word_complete, - matches); - } +bool CommandCompletions::InvokeCommonCompletionCallbacks( + CommandInterpreter &interpreter, uint32_t completion_mask, + const char *completion_str, int match_start_point, int max_return_elements, + SearchFilter *searcher, bool &word_complete, StringList &matches) { + bool handled = false; + + if (completion_mask & eCustomCompletion) + return false; + + for (int i = 0;; i++) { + if (g_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) { + handled = true; + g_common_completions[i].callback(interpreter, completion_str, + match_start_point, max_return_elements, + searcher, word_complete, matches); } - return handled; + } + return handled; } -int -CommandCompletions::SourceFiles(CommandInterpreter &interpreter, - const char *partial_file_name, - int match_start_point, - int max_return_elements, - SearchFilter *searcher, - bool &word_complete, - StringList &matches) -{ - word_complete = true; - // Find some way to switch "include support files..." - SourceFileCompleter completer (interpreter, - false, - partial_file_name, - match_start_point, - max_return_elements, - matches); - - if (searcher == nullptr) - { - lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); - SearchFilterForUnconstrainedSearches null_searcher (target_sp); - completer.DoCompletion (&null_searcher); - } - else - { - completer.DoCompletion (searcher); - } - return matches.GetSize(); +int CommandCompletions::SourceFiles(CommandInterpreter &interpreter, + const char *partial_file_name, + int match_start_point, + int max_return_elements, + SearchFilter *searcher, bool &word_complete, + StringList &matches) { + word_complete = true; + // Find some way to switch "include support files..." + SourceFileCompleter completer(interpreter, false, partial_file_name, + match_start_point, max_return_elements, + matches); + + if (searcher == nullptr) { + lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); + SearchFilterForUnconstrainedSearches null_searcher(target_sp); + completer.DoCompletion(&null_searcher); + } else { + completer.DoCompletion(searcher); + } + return matches.GetSize(); } -typedef struct DiskFilesOrDirectoriesBaton -{ - const char *remainder; - char *partial_name_copy; - bool only_directories; - bool *saw_directory; - StringList *matches; - char *end_ptr; - size_t baselen; +typedef struct DiskFilesOrDirectoriesBaton { + const char *remainder; + char *partial_name_copy; + bool only_directories; + bool *saw_directory; + StringList *matches; + char *end_ptr; + size_t baselen; } DiskFilesOrDirectoriesBaton; -FileSpec::EnumerateDirectoryResult DiskFilesOrDirectoriesCallback(void *baton, FileSpec::FileType file_type, const FileSpec &spec) -{ - const char *name = spec.GetFilename().AsCString(); - - const DiskFilesOrDirectoriesBaton *parameters = (DiskFilesOrDirectoriesBaton*)baton; - char *end_ptr = parameters->end_ptr; - char *partial_name_copy = parameters->partial_name_copy; - const char *remainder = parameters->remainder; - - // Omit ".", ".." and any . files if the match string doesn't start with . - if (name[0] == '.') - { - if (name[1] == '\0') - return FileSpec::eEnumerateDirectoryResultNext; - else if (name[1] == '.' && name[2] == '\0') - return FileSpec::eEnumerateDirectoryResultNext; - else if (remainder[0] != '.') - return FileSpec::eEnumerateDirectoryResultNext; +FileSpec::EnumerateDirectoryResult +DiskFilesOrDirectoriesCallback(void *baton, FileSpec::FileType file_type, + const FileSpec &spec) { + const char *name = spec.GetFilename().AsCString(); + + const DiskFilesOrDirectoriesBaton *parameters = + (DiskFilesOrDirectoriesBaton *)baton; + char *end_ptr = parameters->end_ptr; + char *partial_name_copy = parameters->partial_name_copy; + const char *remainder = parameters->remainder; + + // Omit ".", ".." and any . files if the match string doesn't start with . + if (name[0] == '.') { + if (name[1] == '\0') + return FileSpec::eEnumerateDirectoryResultNext; + else if (name[1] == '.' && name[2] == '\0') + return FileSpec::eEnumerateDirectoryResultNext; + else if (remainder[0] != '.') + return FileSpec::eEnumerateDirectoryResultNext; + } + + // If we found a directory, we put a "/" at the end of the name. + + if (remainder[0] == '\0' || strstr(name, remainder) == name) { + if (strlen(name) + parameters->baselen >= PATH_MAX) + return FileSpec::eEnumerateDirectoryResultNext; + + strcpy(end_ptr, name); + + bool isa_directory = false; + if (file_type == FileSpec::eFileTypeDirectory) + isa_directory = true; + else if (file_type == FileSpec::eFileTypeSymbolicLink) { + if (FileSpec(partial_name_copy, false).IsDirectory()) + isa_directory = true; } - // If we found a directory, we put a "/" at the end of the name. - - if (remainder[0] == '\0' || strstr(name, remainder) == name) - { - if (strlen(name) + parameters->baselen >= PATH_MAX) - return FileSpec::eEnumerateDirectoryResultNext; + if (isa_directory) { + *parameters->saw_directory = true; + size_t len = strlen(parameters->partial_name_copy); + partial_name_copy[len] = '/'; + partial_name_copy[len + 1] = '\0'; + } + if (parameters->only_directories && !isa_directory) + return FileSpec::eEnumerateDirectoryResultNext; + parameters->matches->AppendString(partial_name_copy); + } - strcpy(end_ptr, name); + return FileSpec::eEnumerateDirectoryResultNext; +} - bool isa_directory = false; - if (file_type == FileSpec::eFileTypeDirectory) - isa_directory = true; - else if (file_type == FileSpec::eFileTypeSymbolicLink) - { - if (FileSpec(partial_name_copy, false).IsDirectory()) - isa_directory = true; - } +static int DiskFilesOrDirectories(const char *partial_file_name, + bool only_directories, bool &saw_directory, + StringList &matches) { + // I'm going to use the "glob" function with GLOB_TILDE for user directory + // expansion. + // If it is not defined on your host system, you'll need to implement it + // yourself... - if (isa_directory) - { - *parameters->saw_directory = true; - size_t len = strlen(parameters->partial_name_copy); - partial_name_copy[len] = '/'; - partial_name_copy[len + 1] = '\0'; - } - if (parameters->only_directories && !isa_directory) - return FileSpec::eEnumerateDirectoryResultNext; - parameters->matches->AppendString(partial_name_copy); - } + size_t partial_name_len = strlen(partial_file_name); - return FileSpec::eEnumerateDirectoryResultNext; -} + if (partial_name_len >= PATH_MAX) + return matches.GetSize(); -static int -DiskFilesOrDirectories(const char *partial_file_name, - bool only_directories, - bool &saw_directory, - StringList &matches) -{ - // I'm going to use the "glob" function with GLOB_TILDE for user directory expansion. - // If it is not defined on your host system, you'll need to implement it yourself... - - size_t partial_name_len = strlen(partial_file_name); - - if (partial_name_len >= PATH_MAX) + // This copy of the string will be cut up into the directory part, and the + // remainder. end_ptr + // below will point to the place of the remainder in this string. Then when + // we've resolved the + // containing directory, and opened it, we'll read the directory contents and + // overwrite the + // partial_name_copy starting from end_ptr with each of the matches. Thus we + // will preserve + // the form the user originally typed. + + char partial_name_copy[PATH_MAX]; + memcpy(partial_name_copy, partial_file_name, partial_name_len); + partial_name_copy[partial_name_len] = '\0'; + + // We'll need to save a copy of the remainder for comparison, which we do + // here. + char remainder[PATH_MAX]; + + // end_ptr will point past the last / in partial_name_copy, or if there is no + // slash to the beginning of the string. + char *end_ptr; + + end_ptr = strrchr(partial_name_copy, '/'); + + // This will store the resolved form of the containing directory + llvm::SmallString<64> containing_part; + + if (end_ptr == nullptr) { + // There's no directory. If the thing begins with a "~" then this is a bare + // user name. + if (*partial_name_copy == '~') { + // Nothing here but the user name. We could just put a slash on the end, + // but for completeness sake we'll resolve the user name and only put a + // slash + // on the end if it exists. + llvm::SmallString<64> resolved_username(partial_name_copy); + FileSpec::ResolveUsername(resolved_username); + + // Not sure how this would happen, a username longer than PATH_MAX? + // Still... + if (resolved_username.size() == 0) { + // The user name didn't resolve, let's look in the password database for + // matches. + // The user name database contains duplicates, and is not in + // alphabetical order, so + // we'll use a set to manage that for us. + FileSpec::ResolvePartialUsername(partial_name_copy, matches); + if (matches.GetSize() > 0) + saw_directory = true; return matches.GetSize(); - - // This copy of the string will be cut up into the directory part, and the remainder. end_ptr - // below will point to the place of the remainder in this string. Then when we've resolved the - // containing directory, and opened it, we'll read the directory contents and overwrite the - // partial_name_copy starting from end_ptr with each of the matches. Thus we will preserve - // the form the user originally typed. - - char partial_name_copy[PATH_MAX]; - memcpy(partial_name_copy, partial_file_name, partial_name_len); - partial_name_copy[partial_name_len] = '\0'; - - // We'll need to save a copy of the remainder for comparison, which we do here. - char remainder[PATH_MAX]; - - // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string. - char *end_ptr; - - end_ptr = strrchr(partial_name_copy, '/'); - - // This will store the resolved form of the containing directory - llvm::SmallString<64> containing_part; - - if (end_ptr == nullptr) - { - // There's no directory. If the thing begins with a "~" then this is a bare - // user name. - if (*partial_name_copy == '~') - { - // Nothing here but the user name. We could just put a slash on the end, - // but for completeness sake we'll resolve the user name and only put a slash - // on the end if it exists. - llvm::SmallString<64> resolved_username(partial_name_copy); - FileSpec::ResolveUsername (resolved_username); - - // Not sure how this would happen, a username longer than PATH_MAX? Still... - if (resolved_username.size() == 0) - { - // The user name didn't resolve, let's look in the password database for matches. - // The user name database contains duplicates, and is not in alphabetical order, so - // we'll use a set to manage that for us. - FileSpec::ResolvePartialUsername (partial_name_copy, matches); - if (matches.GetSize() > 0) - saw_directory = true; - return matches.GetSize(); - } - else - { - //The thing exists, put a '/' on the end, and return it... - // FIXME: complete user names here: - partial_name_copy[partial_name_len] = '/'; - partial_name_copy[partial_name_len+1] = '\0'; - matches.AppendString(partial_name_copy); - saw_directory = true; - return matches.GetSize(); - } - } - else - { - // The containing part is the CWD, and the whole string is the remainder. - containing_part = "."; - strcpy(remainder, partial_name_copy); - end_ptr = partial_name_copy; - } - } - else - { - if (end_ptr == partial_name_copy) - { - // We're completing a file or directory in the root volume. - containing_part = "/"; - } - else - { - containing_part.append(partial_name_copy, end_ptr); - } - // Push end_ptr past the final "/" and set remainder. - end_ptr++; - strcpy(remainder, end_ptr); + } else { + // The thing exists, put a '/' on the end, and return it... + // FIXME: complete user names here: + partial_name_copy[partial_name_len] = '/'; + partial_name_copy[partial_name_len + 1] = '\0'; + matches.AppendString(partial_name_copy); + saw_directory = true; + return matches.GetSize(); + } + } else { + // The containing part is the CWD, and the whole string is the remainder. + containing_part = "."; + strcpy(remainder, partial_name_copy); + end_ptr = partial_name_copy; } - - // Look for a user name in the containing part, and if it's there, resolve it and stick the - // result back into the containing_part: - - if (*partial_name_copy == '~') - { - FileSpec::ResolveUsername(containing_part); - // User name doesn't exist, we're not getting any further... - if (containing_part.empty()) - return matches.GetSize(); + } else { + if (end_ptr == partial_name_copy) { + // We're completing a file or directory in the root volume. + containing_part = "/"; + } else { + containing_part.append(partial_name_copy, end_ptr); } - - // Okay, containing_part is now the directory we want to open and look for files: - - size_t baselen = end_ptr - partial_name_copy; - - DiskFilesOrDirectoriesBaton parameters; - parameters.remainder = remainder; - parameters.partial_name_copy = partial_name_copy; - parameters.only_directories = only_directories; - parameters.saw_directory = &saw_directory; - parameters.matches = &matches; - parameters.end_ptr = end_ptr; - parameters.baselen = baselen; - - FileSpec::EnumerateDirectory(containing_part.c_str(), true, true, true, DiskFilesOrDirectoriesCallback, ¶meters); - - return matches.GetSize(); + // Push end_ptr past the final "/" and set remainder. + end_ptr++; + strcpy(remainder, end_ptr); + } + + // Look for a user name in the containing part, and if it's there, resolve it + // and stick the + // result back into the containing_part: + + if (*partial_name_copy == '~') { + FileSpec::ResolveUsername(containing_part); + // User name doesn't exist, we're not getting any further... + if (containing_part.empty()) + return matches.GetSize(); + } + + // Okay, containing_part is now the directory we want to open and look for + // files: + + size_t baselen = end_ptr - partial_name_copy; + + DiskFilesOrDirectoriesBaton parameters; + parameters.remainder = remainder; + parameters.partial_name_copy = partial_name_copy; + parameters.only_directories = only_directories; + parameters.saw_directory = &saw_directory; + parameters.matches = &matches; + parameters.end_ptr = end_ptr; + parameters.baselen = baselen; + + FileSpec::EnumerateDirectory(containing_part.c_str(), true, true, true, + DiskFilesOrDirectoriesCallback, ¶meters); + + return matches.GetSize(); } -int -CommandCompletions::DiskFiles(CommandInterpreter &interpreter, - const char *partial_file_name, - int match_start_point, - int max_return_elements, - SearchFilter *searcher, - bool &word_complete, - StringList &matches) -{ - int ret_val = DiskFilesOrDirectories (partial_file_name, - false, - word_complete, - matches); - word_complete = !word_complete; - return ret_val; +int CommandCompletions::DiskFiles(CommandInterpreter &interpreter, + const char *partial_file_name, + int match_start_point, + int max_return_elements, + SearchFilter *searcher, bool &word_complete, + StringList &matches) { + int ret_val = + DiskFilesOrDirectories(partial_file_name, false, word_complete, matches); + word_complete = !word_complete; + return ret_val; } -int -CommandCompletions::DiskDirectories(CommandInterpreter &interpreter, - const char *partial_file_name, - int match_start_point, - int max_return_elements, - SearchFilter *searcher, - bool &word_complete, - StringList &matches) -{ - int ret_val = DiskFilesOrDirectories (partial_file_name, - true, - word_complete, - matches); - word_complete = false; - return ret_val; +int CommandCompletions::DiskDirectories( + CommandInterpreter &interpreter, const char *partial_file_name, + int match_start_point, int max_return_elements, SearchFilter *searcher, + bool &word_complete, StringList &matches) { + int ret_val = + DiskFilesOrDirectories(partial_file_name, true, word_complete, matches); + word_complete = false; + return ret_val; } -int -CommandCompletions::Modules(CommandInterpreter &interpreter, - const char *partial_file_name, - int match_start_point, - int max_return_elements, - SearchFilter *searcher, - bool &word_complete, - StringList &matches) -{ - word_complete = true; - ModuleCompleter completer (interpreter, - partial_file_name, - match_start_point, - max_return_elements, - matches); - - if (searcher == nullptr) - { - lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); - SearchFilterForUnconstrainedSearches null_searcher (target_sp); - completer.DoCompletion (&null_searcher); - } - else - { - completer.DoCompletion (searcher); - } - return matches.GetSize(); +int CommandCompletions::Modules(CommandInterpreter &interpreter, + const char *partial_file_name, + int match_start_point, int max_return_elements, + SearchFilter *searcher, bool &word_complete, + StringList &matches) { + word_complete = true; + ModuleCompleter completer(interpreter, partial_file_name, match_start_point, + max_return_elements, matches); + + if (searcher == nullptr) { + lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); + SearchFilterForUnconstrainedSearches null_searcher(target_sp); + completer.DoCompletion(&null_searcher); + } else { + completer.DoCompletion(searcher); + } + return matches.GetSize(); } -int -CommandCompletions::Symbols(CommandInterpreter &interpreter, - const char *partial_file_name, - int match_start_point, - int max_return_elements, - SearchFilter *searcher, - bool &word_complete, - StringList &matches) -{ - word_complete = true; - SymbolCompleter completer (interpreter, - partial_file_name, - match_start_point, - max_return_elements, - matches); - - if (searcher == nullptr) - { - lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); - SearchFilterForUnconstrainedSearches null_searcher (target_sp); - completer.DoCompletion (&null_searcher); - } - else - { - completer.DoCompletion (searcher); - } - return matches.GetSize(); +int CommandCompletions::Symbols(CommandInterpreter &interpreter, + const char *partial_file_name, + int match_start_point, int max_return_elements, + SearchFilter *searcher, bool &word_complete, + StringList &matches) { + word_complete = true; + SymbolCompleter completer(interpreter, partial_file_name, match_start_point, + max_return_elements, matches); + + if (searcher == nullptr) { + lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); + SearchFilterForUnconstrainedSearches null_searcher(target_sp); + completer.DoCompletion(&null_searcher); + } else { + completer.DoCompletion(searcher); + } + return matches.GetSize(); } -int -CommandCompletions::SettingsNames (CommandInterpreter &interpreter, - const char *partial_setting_name, - int match_start_point, - int max_return_elements, - SearchFilter *searcher, - bool &word_complete, - StringList &matches) -{ - // Cache the full setting name list - static StringList g_property_names; - if (g_property_names.GetSize() == 0) - { - // Generate the full setting name list on demand - lldb::OptionValuePropertiesSP properties_sp (interpreter.GetDebugger().GetValueProperties()); - if (properties_sp) - { - StreamString strm; - properties_sp->DumpValue(nullptr, strm, OptionValue::eDumpOptionName); - const std::string &str = strm.GetString(); - g_property_names.SplitIntoLines(str.c_str(), str.size()); - } +int CommandCompletions::SettingsNames( + CommandInterpreter &interpreter, const char *partial_setting_name, + int match_start_point, int max_return_elements, SearchFilter *searcher, + bool &word_complete, StringList &matches) { + // Cache the full setting name list + static StringList g_property_names; + if (g_property_names.GetSize() == 0) { + // Generate the full setting name list on demand + lldb::OptionValuePropertiesSP properties_sp( + interpreter.GetDebugger().GetValueProperties()); + if (properties_sp) { + StreamString strm; + properties_sp->DumpValue(nullptr, strm, OptionValue::eDumpOptionName); + const std::string &str = strm.GetString(); + g_property_names.SplitIntoLines(str.c_str(), str.size()); } - - size_t exact_matches_idx = SIZE_MAX; - const size_t num_matches = g_property_names.AutoComplete (partial_setting_name, matches, exact_matches_idx); - word_complete = exact_matches_idx != SIZE_MAX; - return num_matches; + } + + size_t exact_matches_idx = SIZE_MAX; + const size_t num_matches = g_property_names.AutoComplete( + partial_setting_name, matches, exact_matches_idx); + word_complete = exact_matches_idx != SIZE_MAX; + return num_matches; } -int -CommandCompletions::PlatformPluginNames (CommandInterpreter &interpreter, - const char *partial_name, - int match_start_point, - int max_return_elements, - SearchFilter *searcher, - bool &word_complete, - lldb_private::StringList &matches) -{ - const uint32_t num_matches = PluginManager::AutoCompletePlatformName(partial_name, matches); - word_complete = num_matches == 1; - return num_matches; +int CommandCompletions::PlatformPluginNames( + CommandInterpreter &interpreter, const char *partial_name, + int match_start_point, int max_return_elements, SearchFilter *searcher, + bool &word_complete, lldb_private::StringList &matches) { + const uint32_t num_matches = + PluginManager::AutoCompletePlatformName(partial_name, matches); + word_complete = num_matches == 1; + return num_matches; } -int -CommandCompletions::ArchitectureNames (CommandInterpreter &interpreter, - const char *partial_name, - int match_start_point, - int max_return_elements, - SearchFilter *searcher, - bool &word_complete, - lldb_private::StringList &matches) -{ - const uint32_t num_matches = ArchSpec::AutoComplete (partial_name, matches); - word_complete = num_matches == 1; - return num_matches; +int CommandCompletions::ArchitectureNames( + CommandInterpreter &interpreter, const char *partial_name, + int match_start_point, int max_return_elements, SearchFilter *searcher, + bool &word_complete, lldb_private::StringList &matches) { + const uint32_t num_matches = ArchSpec::AutoComplete(partial_name, matches); + word_complete = num_matches == 1; + return num_matches; } -int -CommandCompletions::VariablePath (CommandInterpreter &interpreter, - const char *partial_name, - int match_start_point, - int max_return_elements, - SearchFilter *searcher, - bool &word_complete, - lldb_private::StringList &matches) -{ - return Variable::AutoComplete (interpreter.GetExecutionContext(), partial_name, matches, word_complete); +int CommandCompletions::VariablePath( + CommandInterpreter &interpreter, const char *partial_name, + int match_start_point, int max_return_elements, SearchFilter *searcher, + bool &word_complete, lldb_private::StringList &matches) { + return Variable::AutoComplete(interpreter.GetExecutionContext(), partial_name, + matches, word_complete); } CommandCompletions::Completer::Completer(CommandInterpreter &interpreter, const char *completion_str, int match_start_point, int max_return_elements, - StringList &matches) : - m_interpreter (interpreter), - m_completion_str (completion_str), - m_match_start_point (match_start_point), - m_max_return_elements (max_return_elements), - m_matches (matches) -{ -} + StringList &matches) + : m_interpreter(interpreter), m_completion_str(completion_str), + m_match_start_point(match_start_point), + m_max_return_elements(max_return_elements), m_matches(matches) {} CommandCompletions::Completer::~Completer() = default; @@ -485,237 +406,195 @@ CommandCompletions::Completer::~Completer() = default; // SourceFileCompleter //---------------------------------------------------------------------- -CommandCompletions::SourceFileCompleter::SourceFileCompleter(CommandInterpreter &interpreter, - bool include_support_files, - const char *completion_str, - int match_start_point, - int max_return_elements, - StringList &matches) : - CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches), - m_include_support_files (include_support_files), - m_matching_files() -{ - FileSpec partial_spec (m_completion_str.c_str(), false); - m_file_name = partial_spec.GetFilename().GetCString(); - m_dir_name = partial_spec.GetDirectory().GetCString(); +CommandCompletions::SourceFileCompleter::SourceFileCompleter( + CommandInterpreter &interpreter, bool include_support_files, + const char *completion_str, int match_start_point, int max_return_elements, + StringList &matches) + : CommandCompletions::Completer(interpreter, completion_str, + match_start_point, max_return_elements, + matches), + m_include_support_files(include_support_files), m_matching_files() { + FileSpec partial_spec(m_completion_str.c_str(), false); + m_file_name = partial_spec.GetFilename().GetCString(); + m_dir_name = partial_spec.GetDirectory().GetCString(); } -Searcher::Depth -CommandCompletions::SourceFileCompleter::GetDepth() -{ - return eDepthCompUnit; +Searcher::Depth CommandCompletions::SourceFileCompleter::GetDepth() { + return eDepthCompUnit; } Searcher::CallbackReturn CommandCompletions::SourceFileCompleter::SearchCallback(SearchFilter &filter, SymbolContext &context, Address *addr, - bool complete) -{ - 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->GetFilename().GetCString(); - const char *cur_dir_name = context.comp_unit->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); - } + bool complete) { + 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->GetFilename().GetCString(); + const char *cur_dir_name = context.comp_unit->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); + } } - return Searcher::eCallbackReturnContinue; + } + return Searcher::eCallbackReturnContinue; } size_t -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_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString()); - } - return m_matches.GetSize(); +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_matches.AppendString( + m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString()); + } + return m_matches.GetSize(); } //---------------------------------------------------------------------- // SymbolCompleter //---------------------------------------------------------------------- -static bool -regex_chars (const char comp) -{ - return (comp == '[' || comp == ']' || - comp == '(' || comp == ')' || - comp == '{' || comp == '}' || - comp == '+' || - comp == '.' || - comp == '*' || - comp == '|' || - comp == '^' || - comp == '$' || - comp == '\\' || - comp == '?'); +static bool regex_chars(const char comp) { + return (comp == '[' || comp == ']' || comp == '(' || comp == ')' || + comp == '{' || comp == '}' || comp == '+' || comp == '.' || + comp == '*' || comp == '|' || comp == '^' || comp == '$' || + comp == '\\' || comp == '?'); } -CommandCompletions::SymbolCompleter::SymbolCompleter(CommandInterpreter &interpreter, - const char *completion_str, - int match_start_point, - int max_return_elements, - StringList &matches) : - CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches) -{ - std::string regex_str; - if (completion_str && completion_str[0]) - { - regex_str.append("^"); - regex_str.append(completion_str); - } - 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.Compile(regex_str.c_str()); +CommandCompletions::SymbolCompleter::SymbolCompleter( + CommandInterpreter &interpreter, const char *completion_str, + int match_start_point, int max_return_elements, StringList &matches) + : CommandCompletions::Completer(interpreter, completion_str, + match_start_point, max_return_elements, + matches) { + std::string regex_str; + if (completion_str && completion_str[0]) { + regex_str.append("^"); + regex_str.append(completion_str); + } 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.Compile(regex_str.c_str()); } -Searcher::Depth -CommandCompletions::SymbolCompleter::GetDepth() -{ - return eDepthModule; +Searcher::Depth CommandCompletions::SymbolCompleter::GetDepth() { + return eDepthModule; } -Searcher::CallbackReturn -CommandCompletions::SymbolCompleter::SearchCallback(SearchFilter &filter, - SymbolContext &context, - Address *addr, - bool complete) -{ - if (context.module_sp) - { - SymbolContextList sc_list; - const bool include_symbols = true; - const bool include_inlines = true; - const bool append = true; - context.module_sp->FindFunctions (m_regex, include_symbols, include_inlines, append, 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); - if (!func_name.IsEmpty()) - m_match_set.insert (func_name); - } - } +Searcher::CallbackReturn CommandCompletions::SymbolCompleter::SearchCallback( + SearchFilter &filter, SymbolContext &context, Address *addr, + bool complete) { + if (context.module_sp) { + SymbolContextList sc_list; + const bool include_symbols = true; + const bool include_inlines = true; + const bool append = true; + context.module_sp->FindFunctions(m_regex, include_symbols, include_inlines, + append, 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); + if (!func_name.IsEmpty()) + m_match_set.insert(func_name); + } } - return Searcher::eCallbackReturnContinue; + } + return Searcher::eCallbackReturnContinue; } -size_t -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_matches.AppendString((*pos).GetCString()); - - return m_matches.GetSize(); +size_t 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_matches.AppendString((*pos).GetCString()); + + return m_matches.GetSize(); } //---------------------------------------------------------------------- // ModuleCompleter //---------------------------------------------------------------------- -CommandCompletions::ModuleCompleter::ModuleCompleter(CommandInterpreter &interpreter, - const char *completion_str, - int match_start_point, - int max_return_elements, - StringList &matches) : - CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches) -{ - FileSpec partial_spec (m_completion_str.c_str(), false); - m_file_name = partial_spec.GetFilename().GetCString(); - m_dir_name = partial_spec.GetDirectory().GetCString(); +CommandCompletions::ModuleCompleter::ModuleCompleter( + CommandInterpreter &interpreter, const char *completion_str, + int match_start_point, int max_return_elements, StringList &matches) + : CommandCompletions::Completer(interpreter, completion_str, + match_start_point, max_return_elements, + matches) { + FileSpec partial_spec(m_completion_str.c_str(), false); + m_file_name = partial_spec.GetFilename().GetCString(); + m_dir_name = partial_spec.GetDirectory().GetCString(); } -Searcher::Depth -CommandCompletions::ModuleCompleter::GetDepth() -{ - return eDepthModule; +Searcher::Depth CommandCompletions::ModuleCompleter::GetDepth() { + return eDepthModule; } -Searcher::CallbackReturn -CommandCompletions::ModuleCompleter::SearchCallback(SearchFilter &filter, - SymbolContext &context, - Address *addr, - bool complete) -{ - 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_matches.AppendString (cur_file_name); - } +Searcher::CallbackReturn CommandCompletions::ModuleCompleter::SearchCallback( + SearchFilter &filter, SymbolContext &context, Address *addr, + bool complete) { + 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_matches.AppendString(cur_file_name); } - return Searcher::eCallbackReturnContinue; + } + return Searcher::eCallbackReturnContinue; } -size_t -CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter) -{ - filter->Search (*this); - return m_matches.GetSize(); +size_t CommandCompletions::ModuleCompleter::DoCompletion(SearchFilter *filter) { + filter->Search(*this); + return m_matches.GetSize(); } diff --git a/lldb/source/Commands/CommandObjectApropos.cpp b/lldb/source/Commands/CommandObjectApropos.cpp index 29e1f14..c70d021 100644 --- a/lldb/source/Commands/CommandObjectApropos.cpp +++ b/lldb/source/Commands/CommandObjectApropos.cpp @@ -1,4 +1,5 @@ -//===-- CommandObjectApropos.cpp ---------------------------------*- C++ -*-===// +//===-- CommandObjectApropos.cpp ---------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -13,10 +14,10 @@ // Project includes #include "CommandObjectApropos.h" #include "lldb/Interpreter/Args.h" -#include "lldb/Interpreter/Options.h" -#include "lldb/Interpreter/Property.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Interpreter/Options.h" +#include "lldb/Interpreter/Property.h" using namespace lldb; using namespace lldb_private; @@ -26,93 +27,87 @@ using namespace lldb_private; //------------------------------------------------------------------------- CommandObjectApropos::CommandObjectApropos(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "apropos", "List debugger commands related to a word or subject.", nullptr) -{ - CommandArgumentEntry arg; - CommandArgumentData search_word_arg; + : CommandObjectParsed( + interpreter, "apropos", + "List debugger commands related to a word or subject.", nullptr) { + CommandArgumentEntry arg; + CommandArgumentData search_word_arg; - // Define the first (and only) variant of this arg. - search_word_arg.arg_type = eArgTypeSearchWord; - search_word_arg.arg_repetition = eArgRepeatPlain; + // Define the first (and only) variant of this arg. + search_word_arg.arg_type = eArgTypeSearchWord; + search_word_arg.arg_repetition = eArgRepeatPlain; - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (search_word_arg); + // There is only one variant this argument could be; put it into the argument + // entry. + arg.push_back(search_word_arg); - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); } CommandObjectApropos::~CommandObjectApropos() = default; -bool -CommandObjectApropos::DoExecute (Args& args, CommandReturnObject &result) -{ - const size_t argc = args.GetArgumentCount (); - - if (argc == 1) - { - const char *search_word = args.GetArgumentAtIndex(0); - if ((search_word != nullptr) - && (strlen (search_word) > 0)) - { - // The bulk of the work must be done inside the Command Interpreter, since the command dictionary - // is private. - StringList commands_found; - StringList commands_help; - - m_interpreter.FindCommandsForApropos (search_word, commands_found, commands_help, true, true, true); - - if (commands_found.GetSize() == 0) - { - result.AppendMessageWithFormat ("No commands found pertaining to '%s'. Try 'help' to see a complete list of debugger commands.\n", search_word); - } - else - { - if (commands_found.GetSize() > 0) - { - result.AppendMessageWithFormat ("The following commands may relate to '%s':\n", search_word); - size_t max_len = 0; - - for (size_t i = 0; i < commands_found.GetSize(); ++i) - { - size_t len = strlen (commands_found.GetStringAtIndex (i)); - if (len > max_len) - max_len = len; - } - - for (size_t i = 0; i < commands_found.GetSize(); ++i) - m_interpreter.OutputFormattedHelpText (result.GetOutputStream(), - commands_found.GetStringAtIndex(i), - "--", - commands_help.GetStringAtIndex(i), - max_len); - } - } - - std::vector<const Property *> properties; - const size_t num_properties = m_interpreter.GetDebugger().Apropos(search_word, properties); - if (num_properties) - { - const bool dump_qualified_name = true; - result.AppendMessageWithFormat ("\nThe following settings variables may relate to '%s': \n\n", search_word); - for (size_t i=0; i<num_properties; ++i) - properties[i]->DumpDescription (m_interpreter, result.GetOutputStream(), 0, dump_qualified_name); - - } - - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendError ("'' is not a valid search word.\n"); - result.SetStatus (eReturnStatusFailed); +bool CommandObjectApropos::DoExecute(Args &args, CommandReturnObject &result) { + const size_t argc = args.GetArgumentCount(); + + if (argc == 1) { + const char *search_word = args.GetArgumentAtIndex(0); + if ((search_word != nullptr) && (strlen(search_word) > 0)) { + // The bulk of the work must be done inside the Command Interpreter, since + // the command dictionary + // is private. + StringList commands_found; + StringList commands_help; + + m_interpreter.FindCommandsForApropos(search_word, commands_found, + commands_help, true, true, true); + + if (commands_found.GetSize() == 0) { + result.AppendMessageWithFormat("No commands found pertaining to '%s'. " + "Try 'help' to see a complete list of " + "debugger commands.\n", + search_word); + } else { + if (commands_found.GetSize() > 0) { + result.AppendMessageWithFormat( + "The following commands may relate to '%s':\n", search_word); + size_t max_len = 0; + + for (size_t i = 0; i < commands_found.GetSize(); ++i) { + size_t len = strlen(commands_found.GetStringAtIndex(i)); + if (len > max_len) + max_len = len; + } + + for (size_t i = 0; i < commands_found.GetSize(); ++i) + m_interpreter.OutputFormattedHelpText( + result.GetOutputStream(), commands_found.GetStringAtIndex(i), + "--", commands_help.GetStringAtIndex(i), max_len); } + } + + std::vector<const Property *> properties; + const size_t num_properties = + m_interpreter.GetDebugger().Apropos(search_word, properties); + if (num_properties) { + const bool dump_qualified_name = true; + result.AppendMessageWithFormat( + "\nThe following settings variables may relate to '%s': \n\n", + search_word); + for (size_t i = 0; i < num_properties; ++i) + properties[i]->DumpDescription( + m_interpreter, result.GetOutputStream(), 0, dump_qualified_name); + } + + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.AppendError("'' is not a valid search word.\n"); + result.SetStatus(eReturnStatusFailed); } - else - { - result.AppendError ("'apropos' must be called with exactly one argument.\n"); - result.SetStatus (eReturnStatusFailed); - } + } else { + result.AppendError("'apropos' must be called with exactly one argument.\n"); + result.SetStatus(eReturnStatusFailed); + } - return result.Succeeded(); + return result.Succeeded(); } diff --git a/lldb/source/Commands/CommandObjectApropos.h b/lldb/source/Commands/CommandObjectApropos.h index d04620b..5cad40d 100644 --- a/lldb/source/Commands/CommandObjectApropos.h +++ b/lldb/source/Commands/CommandObjectApropos.h @@ -1,4 +1,5 @@ -//===-- CommandObjectApropos.h -----------------------------------*- C++ -*-===// +//===-- CommandObjectApropos.h -----------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -22,18 +23,14 @@ namespace lldb_private { // CommandObjectApropos //------------------------------------------------------------------------- -class CommandObjectApropos : public CommandObjectParsed -{ +class CommandObjectApropos : public CommandObjectParsed { public: + CommandObjectApropos(CommandInterpreter &interpreter); - CommandObjectApropos (CommandInterpreter &interpreter); - - ~CommandObjectApropos() override; + ~CommandObjectApropos() override; protected: - bool - DoExecute(Args& command, - CommandReturnObject &result) override; + bool DoExecute(Args &command, CommandReturnObject &result) override; }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectArgs.cpp b/lldb/source/Commands/CommandObjectArgs.cpp index ac1b581..eec83b7 100644 --- a/lldb/source/Commands/CommandObjectArgs.cpp +++ b/lldb/source/Commands/CommandObjectArgs.cpp @@ -12,12 +12,12 @@ // Other libraries and framework includes // Project includes #include "CommandObjectArgs.h" -#include "lldb/Interpreter/Args.h" +#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/Value.h" -#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h" #include "lldb/Host/Host.h" +#include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Symbol/ClangASTContext.h" @@ -25,242 +25,213 @@ #include "lldb/Symbol/Variable.h" #include "lldb/Target/ABI.h" #include "lldb/Target/Process.h" +#include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" -#include "lldb/Target/StackFrame.h" using namespace lldb; using namespace lldb_private; -// This command is a toy. I'm just using it to have a way to construct the arguments to +// This command is a toy. I'm just using it to have a way to construct the +// arguments to // calling functions. // -CommandObjectArgs::CommandOptions::CommandOptions (CommandInterpreter &interpreter) : - Options() -{ - // Keep only one place to reset the values to their defaults - OptionParsingStarting(nullptr); +CommandObjectArgs::CommandOptions::CommandOptions( + CommandInterpreter &interpreter) + : Options() { + // Keep only one place to reset the values to their defaults + OptionParsingStarting(nullptr); } CommandObjectArgs::CommandOptions::~CommandOptions() = default; -Error -CommandObjectArgs::CommandOptions::SetOptionValue(uint32_t option_idx, - const char *option_arg, - ExecutionContext *execution_context) -{ - Error error; - - const int short_option = m_getopt_table[option_idx].val; - error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); - - return error; -} - -void -CommandObjectArgs::CommandOptions::OptionParsingStarting( - ExecutionContext *execution_context) -{ -} +Error CommandObjectArgs::CommandOptions::SetOptionValue( + uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) { + Error error; -const OptionDefinition* -CommandObjectArgs::CommandOptions::GetDefinitions () -{ - return g_option_table; -} + const int short_option = m_getopt_table[option_idx].val; + error.SetErrorStringWithFormat("invalid short option character '%c'", + short_option); -CommandObjectArgs::CommandObjectArgs (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "args", - "When stopped at the start of a function, reads function arguments of type (u?)int(8|16|32|64)_t, (void|char)*", - "args"), - m_options (interpreter) -{ + return error; } -CommandObjectArgs::~CommandObjectArgs() = default; +void CommandObjectArgs::CommandOptions::OptionParsingStarting( + ExecutionContext *execution_context) {} -Options * -CommandObjectArgs::GetOptions () -{ - return &m_options; +const OptionDefinition *CommandObjectArgs::CommandOptions::GetDefinitions() { + return g_option_table; } -bool -CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result) -{ - ConstString target_triple; +CommandObjectArgs::CommandObjectArgs(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "args", + "When stopped at the start of a function, reads " + "function arguments of type (u?)int(8|16|32|64)_t, " + "(void|char)*", + "args"), + m_options(interpreter) {} - Process *process = m_exe_ctx.GetProcessPtr(); - if (!process) - { - result.AppendError ("Args found no process."); - result.SetStatus (eReturnStatusFailed); - return false; - } - - const ABI *abi = process->GetABI().get(); - if (!abi) - { - result.AppendError ("The current process has no ABI."); - result.SetStatus (eReturnStatusFailed); - return false; - } - - const size_t num_args = args.GetArgumentCount (); - size_t arg_index; - - if (!num_args) - { - result.AppendError ("args requires at least one argument"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - Thread *thread = m_exe_ctx.GetThreadPtr(); - - if (!thread) - { - result.AppendError ("args found no thread."); - result.SetStatus (eReturnStatusFailed); +CommandObjectArgs::~CommandObjectArgs() = default; + +Options *CommandObjectArgs::GetOptions() { return &m_options; } + +bool CommandObjectArgs::DoExecute(Args &args, CommandReturnObject &result) { + ConstString target_triple; + + Process *process = m_exe_ctx.GetProcessPtr(); + if (!process) { + result.AppendError("Args found no process."); + result.SetStatus(eReturnStatusFailed); + return false; + } + + const ABI *abi = process->GetABI().get(); + if (!abi) { + result.AppendError("The current process has no ABI."); + result.SetStatus(eReturnStatusFailed); + return false; + } + + const size_t num_args = args.GetArgumentCount(); + size_t arg_index; + + if (!num_args) { + result.AppendError("args requires at least one argument"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + Thread *thread = m_exe_ctx.GetThreadPtr(); + + if (!thread) { + result.AppendError("args found no thread."); + result.SetStatus(eReturnStatusFailed); + return false; + } + + lldb::StackFrameSP thread_cur_frame = thread->GetSelectedFrame(); + if (!thread_cur_frame) { + result.AppendError("The current thread has no current frame."); + result.SetStatus(eReturnStatusFailed); + return false; + } + + ModuleSP thread_module_sp( + thread_cur_frame->GetFrameCodeAddress().GetModule()); + if (!thread_module_sp) { + result.AppendError("The PC has no associated module."); + result.SetStatus(eReturnStatusFailed); + return false; + } + + TypeSystem *type_system = + thread_module_sp->GetTypeSystemForLanguage(eLanguageTypeC); + if (type_system == nullptr) { + result.AppendError("Unable to create C type system."); + result.SetStatus(eReturnStatusFailed); + return false; + } + + ValueList value_list; + + for (arg_index = 0; arg_index < num_args; ++arg_index) { + const char *arg_type_cstr = args.GetArgumentAtIndex(arg_index); + Value value; + value.SetValueType(Value::eValueTypeScalar); + CompilerType compiler_type; + + char *int_pos; + if ((int_pos = strstr(const_cast<char *>(arg_type_cstr), "int"))) { + Encoding encoding = eEncodingSint; + + int width = 0; + + if (int_pos > arg_type_cstr + 1) { + result.AppendErrorWithFormat("Invalid format: %s.\n", arg_type_cstr); + result.SetStatus(eReturnStatusFailed); return false; - } - - lldb::StackFrameSP thread_cur_frame = thread->GetSelectedFrame (); - if (!thread_cur_frame) - { - result.AppendError ("The current thread has no current frame."); - result.SetStatus (eReturnStatusFailed); + } + if (int_pos == arg_type_cstr + 1 && arg_type_cstr[0] != 'u') { + result.AppendErrorWithFormat("Invalid format: %s.\n", arg_type_cstr); + result.SetStatus(eReturnStatusFailed); return false; - } - - ModuleSP thread_module_sp (thread_cur_frame->GetFrameCodeAddress ().GetModule()); - if (!thread_module_sp) - { - result.AppendError ("The PC has no associated module."); - result.SetStatus (eReturnStatusFailed); + } + if (arg_type_cstr[0] == 'u') { + encoding = eEncodingUint; + } + + char *width_pos = int_pos + 3; + + if (!strcmp(width_pos, "8_t")) + width = 8; + else if (!strcmp(width_pos, "16_t")) + width = 16; + else if (!strcmp(width_pos, "32_t")) + width = 32; + else if (!strcmp(width_pos, "64_t")) + width = 64; + else { + result.AppendErrorWithFormat("Invalid format: %s.\n", arg_type_cstr); + result.SetStatus(eReturnStatusFailed); return false; - } + } + compiler_type = + type_system->GetBuiltinTypeForEncodingAndBitSize(encoding, width); - TypeSystem *type_system = thread_module_sp->GetTypeSystemForLanguage(eLanguageTypeC); - if (type_system == nullptr) - { - result.AppendError ("Unable to create C type system."); - result.SetStatus (eReturnStatusFailed); + if (!compiler_type.IsValid()) { + result.AppendErrorWithFormat( + "Couldn't get Clang type for format %s (%s integer, width %d).\n", + arg_type_cstr, (encoding == eEncodingSint ? "signed" : "unsigned"), + width); + + result.SetStatus(eReturnStatusFailed); return false; - } - - ValueList value_list; - - for (arg_index = 0; arg_index < num_args; ++arg_index) - { - const char *arg_type_cstr = args.GetArgumentAtIndex(arg_index); - Value value; - value.SetValueType(Value::eValueTypeScalar); - CompilerType compiler_type; - - char *int_pos; - if ((int_pos = strstr (const_cast<char*>(arg_type_cstr), "int"))) - { - Encoding encoding = eEncodingSint; - - int width = 0; - - if (int_pos > arg_type_cstr + 1) - { - result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr); - result.SetStatus (eReturnStatusFailed); - return false; - } - if (int_pos == arg_type_cstr + 1 && arg_type_cstr[0] != 'u') - { - result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr); - result.SetStatus (eReturnStatusFailed); - return false; - } - if (arg_type_cstr[0] == 'u') - { - encoding = eEncodingUint; - } - - char *width_pos = int_pos + 3; - - if (!strcmp (width_pos, "8_t")) - width = 8; - else if (!strcmp (width_pos, "16_t")) - width = 16; - else if (!strcmp (width_pos, "32_t")) - width = 32; - else if (!strcmp (width_pos, "64_t")) - width = 64; - else - { - result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr); - result.SetStatus (eReturnStatusFailed); - return false; - } - compiler_type = type_system->GetBuiltinTypeForEncodingAndBitSize(encoding, width); - - if (!compiler_type.IsValid()) - { - result.AppendErrorWithFormat ("Couldn't get Clang type for format %s (%s integer, width %d).\n", - arg_type_cstr, - (encoding == eEncodingSint ? "signed" : "unsigned"), - width); - - result.SetStatus (eReturnStatusFailed); - return false; - } - } - else if (strchr (arg_type_cstr, '*')) - { - if (!strcmp (arg_type_cstr, "void*")) - compiler_type = type_system->GetBasicTypeFromAST(eBasicTypeVoid).GetPointerType(); - else if (!strcmp (arg_type_cstr, "char*")) - compiler_type = type_system->GetBasicTypeFromAST(eBasicTypeChar).GetPointerType(); - else - { - result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - else - { - result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr); - result.SetStatus (eReturnStatusFailed); - return false; - } - - value.SetCompilerType (compiler_type); - value_list.PushValue(value); - } - - if (!abi->GetArgumentValues (*thread, value_list)) - { - result.AppendError ("Couldn't get argument values"); - result.SetStatus (eReturnStatusFailed); + } + } else if (strchr(arg_type_cstr, '*')) { + if (!strcmp(arg_type_cstr, "void*")) + compiler_type = + type_system->GetBasicTypeFromAST(eBasicTypeVoid).GetPointerType(); + else if (!strcmp(arg_type_cstr, "char*")) + compiler_type = + type_system->GetBasicTypeFromAST(eBasicTypeChar).GetPointerType(); + else { + result.AppendErrorWithFormat("Invalid format: %s.\n", arg_type_cstr); + result.SetStatus(eReturnStatusFailed); return false; + } + } else { + result.AppendErrorWithFormat("Invalid format: %s.\n", arg_type_cstr); + result.SetStatus(eReturnStatusFailed); + return false; } - - result.GetOutputStream ().Printf("Arguments : \n"); - - for (arg_index = 0; arg_index < num_args; ++arg_index) - { - result.GetOutputStream ().Printf ("%" PRIu64 " (%s): ", (uint64_t)arg_index, args.GetArgumentAtIndex (arg_index)); - value_list.GetValueAtIndex (arg_index)->Dump (&result.GetOutputStream ()); - result.GetOutputStream ().Printf("\n"); - } - - return result.Succeeded(); + + value.SetCompilerType(compiler_type); + value_list.PushValue(value); + } + + if (!abi->GetArgumentValues(*thread, value_list)) { + result.AppendError("Couldn't get argument values"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + result.GetOutputStream().Printf("Arguments : \n"); + + for (arg_index = 0; arg_index < num_args; ++arg_index) { + result.GetOutputStream().Printf("%" PRIu64 " (%s): ", (uint64_t)arg_index, + args.GetArgumentAtIndex(arg_index)); + value_list.GetValueAtIndex(arg_index)->Dump(&result.GetOutputStream()); + result.GetOutputStream().Printf("\n"); + } + + return result.Succeeded(); } -OptionDefinition -CommandObjectArgs::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectArgs::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "debug", 'g', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable verbose debug logging of the expression parsing and evaluation."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; diff --git a/lldb/source/Commands/CommandObjectArgs.h b/lldb/source/Commands/CommandObjectArgs.h index 90b2f50..2a154a3 100644 --- a/lldb/source/Commands/CommandObjectArgs.h +++ b/lldb/source/Commands/CommandObjectArgs.h @@ -18,50 +18,39 @@ #include "lldb/Interpreter/Options.h" namespace lldb_private { - - class CommandObjectArgs : public CommandObjectParsed - { - public: - - class CommandOptions : public Options - { - public: - - CommandOptions (CommandInterpreter &interpreter); - - ~CommandOptions() override; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override; - - void - OptionParsingStarting(ExecutionContext *execution_context) override; - - const OptionDefinition* - GetDefinitions() override; - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - }; - - CommandObjectArgs (CommandInterpreter &interpreter); - - ~CommandObjectArgs() override; - - Options * - GetOptions() override; - - protected: - - CommandOptions m_options; - - bool - DoExecute(Args& command, - CommandReturnObject &result) override; - }; - + +class CommandObjectArgs : public CommandObjectParsed { +public: + class CommandOptions : public Options { + public: + CommandOptions(CommandInterpreter &interpreter); + + ~CommandOptions() override; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override; + + void OptionParsingStarting(ExecutionContext *execution_context) override; + + const OptionDefinition *GetDefinitions() override; + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + }; + + CommandObjectArgs(CommandInterpreter &interpreter); + + ~CommandObjectArgs() override; + + Options *GetOptions() override; + +protected: + CommandOptions m_options; + + bool DoExecute(Args &command, CommandReturnObject &result) override; +}; + } // namespace lldb_private #endif // liblldb_CommandObjectArgs_h_ diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp index 6f92506..a5bfe1d 100644 --- a/lldb/source/Commands/CommandObjectBreakpoint.cpp +++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp @@ -18,749 +18,692 @@ #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointIDList.h" #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Host/StringConvert.h" -#include "lldb/Interpreter/Options.h" -#include "lldb/Interpreter/OptionValueBoolean.h" -#include "lldb/Interpreter/OptionValueString.h" -#include "lldb/Interpreter/OptionValueUInt64.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/StreamString.h" +#include "lldb/Host/StringConvert.h" +#include "lldb/Interpreter/CommandCompletions.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Interpreter/OptionValueBoolean.h" +#include "lldb/Interpreter/OptionValueString.h" +#include "lldb/Interpreter/OptionValueUInt64.h" +#include "lldb/Interpreter/Options.h" #include "lldb/Target/Language.h" -#include "lldb/Target/Target.h" -#include "lldb/Interpreter/CommandCompletions.h" #include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadSpec.h" using namespace lldb; using namespace lldb_private; -static void -AddBreakpointDescription (Stream *s, Breakpoint *bp, lldb::DescriptionLevel level) -{ - s->IndentMore(); - bp->GetDescription (s, level, true); - s->IndentLess(); - s->EOL(); +static void AddBreakpointDescription(Stream *s, Breakpoint *bp, + lldb::DescriptionLevel level) { + s->IndentMore(); + bp->GetDescription(s, level, true); + s->IndentLess(); + s->EOL(); } //------------------------------------------------------------------------- // CommandObjectBreakpointSet //------------------------------------------------------------------------- -class CommandObjectBreakpointSet : public CommandObjectParsed -{ +class CommandObjectBreakpointSet : public CommandObjectParsed { public: - typedef enum BreakpointSetType - { - eSetTypeInvalid, - eSetTypeFileAndLine, - eSetTypeAddress, - eSetTypeFunctionName, - eSetTypeFunctionRegexp, - eSetTypeSourceRegexp, - eSetTypeException - } BreakpointSetType; - - CommandObjectBreakpointSet (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "breakpoint set", - "Sets a breakpoint or set of breakpoints in the executable.", - "breakpoint set <cmd-options>"), - m_options () - { + typedef enum BreakpointSetType { + eSetTypeInvalid, + eSetTypeFileAndLine, + eSetTypeAddress, + eSetTypeFunctionName, + eSetTypeFunctionRegexp, + eSetTypeSourceRegexp, + eSetTypeException + } BreakpointSetType; + + CommandObjectBreakpointSet(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "breakpoint set", + "Sets a breakpoint or set of breakpoints in the executable.", + "breakpoint set <cmd-options>"), + m_options() {} + + ~CommandObjectBreakpointSet() override = default; + + Options *GetOptions() override { return &m_options; } + + class CommandOptions : public Options { + public: + CommandOptions() + : Options(), m_condition(), m_filenames(), m_line_num(0), m_column(0), + m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone), + m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(), + m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID), + m_thread_index(UINT32_MAX), m_thread_name(), m_queue_name(), + m_catch_bp(false), m_throw_bp(true), m_hardware(false), + m_exception_language(eLanguageTypeUnknown), + m_language(lldb::eLanguageTypeUnknown), + m_skip_prologue(eLazyBoolCalculate), m_one_shot(false), + m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'a': { + m_load_addr = Args::StringToAddress(execution_context, option_arg, + LLDB_INVALID_ADDRESS, &error); + } break; + + case 'A': + m_all_files = true; + break; + + case 'b': + m_func_names.push_back(option_arg); + m_func_name_type_mask |= eFunctionNameTypeBase; + break; + + case 'C': { + bool success; + m_column = StringConvert::ToUInt32(option_arg, 0, 0, &success); + if (!success) + error.SetErrorStringWithFormat("invalid column number: %s", + option_arg); + break; + } + + case 'c': + m_condition.assign(option_arg); + break; + + case 'D': + m_use_dummy = true; + break; + + case 'E': { + LanguageType language = Language::GetLanguageTypeFromString(option_arg); + + switch (language) { + case eLanguageTypeC89: + case eLanguageTypeC: + case eLanguageTypeC99: + case eLanguageTypeC11: + m_exception_language = eLanguageTypeC; + break; + case eLanguageTypeC_plus_plus: + case eLanguageTypeC_plus_plus_03: + case eLanguageTypeC_plus_plus_11: + case eLanguageTypeC_plus_plus_14: + m_exception_language = eLanguageTypeC_plus_plus; + break; + case eLanguageTypeObjC: + m_exception_language = eLanguageTypeObjC; + break; + case eLanguageTypeObjC_plus_plus: + error.SetErrorStringWithFormat( + "Set exception breakpoints separately for c++ and objective-c"); + break; + case eLanguageTypeUnknown: + error.SetErrorStringWithFormat( + "Unknown language type: '%s' for exception breakpoint", + option_arg); + break; + default: + error.SetErrorStringWithFormat( + "Unsupported language type: '%s' for exception breakpoint", + option_arg); + } + } break; + + case 'f': + m_filenames.AppendIfUnique(FileSpec(option_arg, false)); + break; + + case 'F': + m_func_names.push_back(option_arg); + m_func_name_type_mask |= eFunctionNameTypeFull; + break; + + case 'h': { + bool success; + m_catch_bp = Args::StringToBoolean(option_arg, true, &success); + if (!success) + error.SetErrorStringWithFormat( + "Invalid boolean value for on-catch option: '%s'", option_arg); + } break; + + case 'H': + m_hardware = true; + break; + + case 'i': + m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); + if (m_ignore_count == UINT32_MAX) + error.SetErrorStringWithFormat("invalid ignore count '%s'", + option_arg); + break; + + case 'K': { + bool success; + bool value; + value = Args::StringToBoolean(option_arg, true, &success); + if (value) + m_skip_prologue = eLazyBoolYes; + else + m_skip_prologue = eLazyBoolNo; + + if (!success) + error.SetErrorStringWithFormat( + "Invalid boolean value for skip prologue option: '%s'", + option_arg); + } break; + + case 'l': { + bool success; + m_line_num = StringConvert::ToUInt32(option_arg, 0, 0, &success); + if (!success) + error.SetErrorStringWithFormat("invalid line number: %s.", + option_arg); + break; + } + + case 'L': + m_language = Language::GetLanguageTypeFromString(option_arg); + if (m_language == eLanguageTypeUnknown) + error.SetErrorStringWithFormat( + "Unknown language type: '%s' for breakpoint", option_arg); + break; + + case 'm': { + bool success; + bool value; + value = Args::StringToBoolean(option_arg, true, &success); + if (value) + m_move_to_nearest_code = eLazyBoolYes; + else + m_move_to_nearest_code = eLazyBoolNo; + + if (!success) + error.SetErrorStringWithFormat( + "Invalid boolean value for move-to-nearest-code option: '%s'", + option_arg); + break; + } + + case 'M': + m_func_names.push_back(option_arg); + m_func_name_type_mask |= eFunctionNameTypeMethod; + break; + + case 'n': + m_func_names.push_back(option_arg); + m_func_name_type_mask |= eFunctionNameTypeAuto; + break; + + case 'N': + if (BreakpointID::StringIsBreakpointName(option_arg, error)) + m_breakpoint_names.push_back(option_arg); + break; + + case 'R': { + lldb::addr_t tmp_offset_addr; + tmp_offset_addr = + Args::StringToAddress(execution_context, option_arg, 0, &error); + if (error.Success()) + m_offset_addr = tmp_offset_addr; + } break; + + case 'o': + m_one_shot = true; + break; + + case 'O': + m_exception_extra_args.AppendArgument("-O"); + m_exception_extra_args.AppendArgument(option_arg); + break; + + case 'p': + m_source_text_regexp.assign(option_arg); + break; + + case 'q': + m_queue_name.assign(option_arg); + break; + + case 'r': + m_func_regexp.assign(option_arg); + break; + + case 's': + m_modules.AppendIfUnique(FileSpec(option_arg, false)); + break; + + case 'S': + m_func_names.push_back(option_arg); + m_func_name_type_mask |= eFunctionNameTypeSelector; + break; + + case 't': + m_thread_id = + StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); + if (m_thread_id == LLDB_INVALID_THREAD_ID) + error.SetErrorStringWithFormat("invalid thread id string '%s'", + option_arg); + break; + + case 'T': + m_thread_name.assign(option_arg); + break; + + case 'w': { + bool success; + m_throw_bp = Args::StringToBoolean(option_arg, true, &success); + if (!success) + error.SetErrorStringWithFormat( + "Invalid boolean value for on-throw option: '%s'", option_arg); + } break; + + case 'x': + m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); + if (m_thread_id == UINT32_MAX) + error.SetErrorStringWithFormat("invalid thread index string '%s'", + option_arg); + break; + + case 'X': + m_source_regex_func_names.insert(option_arg); + break; + + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; } - ~CommandObjectBreakpointSet() override = default; + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_condition.clear(); + m_filenames.Clear(); + m_line_num = 0; + m_column = 0; + m_func_names.clear(); + m_func_name_type_mask = eFunctionNameTypeNone; + m_func_regexp.clear(); + m_source_text_regexp.clear(); + m_modules.Clear(); + m_load_addr = LLDB_INVALID_ADDRESS; + m_offset_addr = 0; + m_ignore_count = 0; + m_thread_id = LLDB_INVALID_THREAD_ID; + m_thread_index = UINT32_MAX; + m_thread_name.clear(); + m_queue_name.clear(); + m_catch_bp = false; + m_throw_bp = true; + m_hardware = false; + m_exception_language = eLanguageTypeUnknown; + m_language = lldb::eLanguageTypeUnknown; + m_skip_prologue = eLazyBoolCalculate; + m_one_shot = false; + m_use_dummy = false; + m_breakpoint_names.clear(); + m_all_files = false; + m_exception_extra_args.Clear(); + m_move_to_nearest_code = eLazyBoolCalculate; + m_source_regex_func_names.clear(); + } - Options * - GetOptions () override - { - return &m_options; + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + std::string m_condition; + FileSpecList m_filenames; + uint32_t m_line_num; + uint32_t m_column; + std::vector<std::string> m_func_names; + std::vector<std::string> m_breakpoint_names; + uint32_t m_func_name_type_mask; + std::string m_func_regexp; + std::string m_source_text_regexp; + FileSpecList m_modules; + lldb::addr_t m_load_addr; + lldb::addr_t m_offset_addr; + uint32_t m_ignore_count; + lldb::tid_t m_thread_id; + uint32_t m_thread_index; + std::string m_thread_name; + std::string m_queue_name; + bool m_catch_bp; + bool m_throw_bp; + bool m_hardware; // Request to use hardware breakpoints + lldb::LanguageType m_exception_language; + lldb::LanguageType m_language; + LazyBool m_skip_prologue; + bool m_one_shot; + bool m_use_dummy; + bool m_all_files; + Args m_exception_extra_args; + LazyBool m_move_to_nearest_code; + std::unordered_set<std::string> m_source_regex_func_names; + }; + +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); + + if (target == nullptr) { + result.AppendError("Invalid target. Must set target before setting " + "breakpoints (see 'target create' command)."); + result.SetStatus(eReturnStatusFailed); + return false; } - class CommandOptions : public Options + // The following are the various types of breakpoints that could be set: + // 1). -f -l -p [-s -g] (setting breakpoint by source location) + // 2). -a [-s -g] (setting breakpoint by address) + // 3). -n [-s -g] (setting breakpoint by function name) + // 4). -r [-s -g] (setting breakpoint by function name regular + // expression) + // 5). -p -f (setting a breakpoint by comparing a reg-exp + // to source text) + // 6). -E [-w -h] (setting a breakpoint for exceptions for a + // given language.) + + BreakpointSetType break_type = eSetTypeInvalid; + + if (m_options.m_line_num != 0) + break_type = eSetTypeFileAndLine; + else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) + break_type = eSetTypeAddress; + else if (!m_options.m_func_names.empty()) + break_type = eSetTypeFunctionName; + else if (!m_options.m_func_regexp.empty()) + break_type = eSetTypeFunctionRegexp; + else if (!m_options.m_source_text_regexp.empty()) + break_type = eSetTypeSourceRegexp; + else if (m_options.m_exception_language != eLanguageTypeUnknown) + break_type = eSetTypeException; + + Breakpoint *bp = nullptr; + FileSpec module_spec; + const bool internal = false; + + // If the user didn't specify skip-prologue, having an offset should turn + // that off. + if (m_options.m_offset_addr != 0 && + m_options.m_skip_prologue == eLazyBoolCalculate) + m_options.m_skip_prologue = eLazyBoolNo; + + switch (break_type) { + case eSetTypeFileAndLine: // Breakpoint by source position { - public: - CommandOptions () : - Options (), - m_condition (), - m_filenames (), - m_line_num (0), - m_column (0), - m_func_names (), - m_func_name_type_mask (eFunctionNameTypeNone), - m_func_regexp (), - m_source_text_regexp(), - m_modules (), - m_load_addr(), - m_ignore_count (0), - m_thread_id(LLDB_INVALID_THREAD_ID), - m_thread_index (UINT32_MAX), - m_thread_name(), - m_queue_name(), - m_catch_bp (false), - m_throw_bp (true), - m_hardware (false), - m_exception_language (eLanguageTypeUnknown), - m_language (lldb::eLanguageTypeUnknown), - m_skip_prologue (eLazyBoolCalculate), - m_one_shot (false), - m_all_files (false), - m_move_to_nearest_code (eLazyBoolCalculate) - { - } + FileSpec file; + const size_t num_files = m_options.m_filenames.GetSize(); + if (num_files == 0) { + if (!GetDefaultFile(target, file, result)) { + result.AppendError("No file supplied and no default file available."); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else if (num_files > 1) { + result.AppendError("Only one file at a time is allowed for file and " + "line breakpoints."); + result.SetStatus(eReturnStatusFailed); + return false; + } else + file = m_options.m_filenames.GetFileSpecAtIndex(0); + + // Only check for inline functions if + LazyBool check_inlines = eLazyBoolCalculate; + + bp = target + ->CreateBreakpoint(&(m_options.m_modules), file, + m_options.m_line_num, m_options.m_offset_addr, + check_inlines, m_options.m_skip_prologue, + internal, m_options.m_hardware, + m_options.m_move_to_nearest_code) + .get(); + } break; + + case eSetTypeAddress: // Breakpoint by address + { + // If a shared library has been specified, make an lldb_private::Address + // with the library, and + // use that. That way the address breakpoint will track the load location + // of the library. + size_t num_modules_specified = m_options.m_modules.GetSize(); + if (num_modules_specified == 1) { + const FileSpec *file_spec = + m_options.m_modules.GetFileSpecPointerAtIndex(0); + bp = target + ->CreateAddressInModuleBreakpoint(m_options.m_load_addr, + internal, file_spec, + m_options.m_hardware) + .get(); + } else if (num_modules_specified == 0) { + bp = target + ->CreateBreakpoint(m_options.m_load_addr, internal, + m_options.m_hardware) + .get(); + } else { + result.AppendError("Only one shared library can be specified for " + "address breakpoints."); + result.SetStatus(eReturnStatusFailed); + return false; + } + break; + } + case eSetTypeFunctionName: // Breakpoint by function name + { + uint32_t name_type_mask = m_options.m_func_name_type_mask; + + if (name_type_mask == 0) + name_type_mask = eFunctionNameTypeAuto; + + bp = target + ->CreateBreakpoint( + &(m_options.m_modules), &(m_options.m_filenames), + m_options.m_func_names, name_type_mask, m_options.m_language, + m_options.m_offset_addr, m_options.m_skip_prologue, internal, + m_options.m_hardware) + .get(); + } break; + + case eSetTypeFunctionRegexp: // Breakpoint by regular expression function + // name + { + RegularExpression regexp(m_options.m_func_regexp.c_str()); + if (!regexp.IsValid()) { + char err_str[1024]; + regexp.GetErrorAsCString(err_str, sizeof(err_str)); + result.AppendErrorWithFormat( + "Function name regular expression could not be compiled: \"%s\"", + err_str); + result.SetStatus(eReturnStatusFailed); + return false; + } + + bp = target + ->CreateFuncRegexBreakpoint( + &(m_options.m_modules), &(m_options.m_filenames), regexp, + m_options.m_language, m_options.m_skip_prologue, internal, + m_options.m_hardware) + .get(); + } break; + case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. + { + const size_t num_files = m_options.m_filenames.GetSize(); + + if (num_files == 0 && !m_options.m_all_files) { + FileSpec file; + if (!GetDefaultFile(target, file, result)) { + result.AppendError( + "No files provided and could not find default file."); + result.SetStatus(eReturnStatusFailed); + return false; + } else { + m_options.m_filenames.Append(file); + } + } + + RegularExpression regexp(m_options.m_source_text_regexp.c_str()); + if (!regexp.IsValid()) { + char err_str[1024]; + regexp.GetErrorAsCString(err_str, sizeof(err_str)); + result.AppendErrorWithFormat( + "Source text regular expression could not be compiled: \"%s\"", + err_str); + result.SetStatus(eReturnStatusFailed); + return false; + } + bp = target + ->CreateSourceRegexBreakpoint( + &(m_options.m_modules), &(m_options.m_filenames), + m_options.m_source_regex_func_names, regexp, internal, + m_options.m_hardware, m_options.m_move_to_nearest_code) + .get(); + } break; + case eSetTypeException: { + Error precond_error; + bp = target + ->CreateExceptionBreakpoint( + m_options.m_exception_language, m_options.m_catch_bp, + m_options.m_throw_bp, internal, + &m_options.m_exception_extra_args, &precond_error) + .get(); + if (precond_error.Fail()) { + result.AppendErrorWithFormat( + "Error setting extra exception arguments: %s", + precond_error.AsCString()); + target->RemoveBreakpointByID(bp->GetID()); + result.SetStatus(eReturnStatusFailed); + return false; + } + } break; + default: + break; + } - ~CommandOptions() override = default; - - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'a': - { - m_load_addr = - Args::StringToAddress(execution_context, option_arg, - LLDB_INVALID_ADDRESS, &error); - } - break; - - case 'A': - m_all_files = true; - break; - - case 'b': - m_func_names.push_back (option_arg); - m_func_name_type_mask |= eFunctionNameTypeBase; - break; - - case 'C': - { - bool success; - m_column = StringConvert::ToUInt32 (option_arg, 0, 0, &success); - if (!success) - error.SetErrorStringWithFormat("invalid column number: %s", option_arg); - break; - } - - case 'c': - m_condition.assign(option_arg); - break; - - case 'D': - m_use_dummy = true; - break; - - case 'E': - { - LanguageType language = Language::GetLanguageTypeFromString (option_arg); - - switch (language) - { - case eLanguageTypeC89: - case eLanguageTypeC: - case eLanguageTypeC99: - case eLanguageTypeC11: - m_exception_language = eLanguageTypeC; - break; - case eLanguageTypeC_plus_plus: - case eLanguageTypeC_plus_plus_03: - case eLanguageTypeC_plus_plus_11: - case eLanguageTypeC_plus_plus_14: - m_exception_language = eLanguageTypeC_plus_plus; - break; - case eLanguageTypeObjC: - m_exception_language = eLanguageTypeObjC; - break; - case eLanguageTypeObjC_plus_plus: - error.SetErrorStringWithFormat ("Set exception breakpoints separately for c++ and objective-c"); - break; - case eLanguageTypeUnknown: - error.SetErrorStringWithFormat ("Unknown language type: '%s' for exception breakpoint", option_arg); - break; - default: - error.SetErrorStringWithFormat ("Unsupported language type: '%s' for exception breakpoint", option_arg); - } - } - break; - - case 'f': - m_filenames.AppendIfUnique (FileSpec(option_arg, false)); - break; - - case 'F': - m_func_names.push_back (option_arg); - m_func_name_type_mask |= eFunctionNameTypeFull; - break; - - case 'h': - { - bool success; - m_catch_bp = Args::StringToBoolean (option_arg, true, &success); - if (!success) - error.SetErrorStringWithFormat ("Invalid boolean value for on-catch option: '%s'", option_arg); - } - break; - - case 'H': - m_hardware = true; - break; - - case 'i': - m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); - if (m_ignore_count == UINT32_MAX) - error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg); - break; - - case 'K': - { - bool success; - bool value; - value = Args::StringToBoolean (option_arg, true, &success); - if (value) - m_skip_prologue = eLazyBoolYes; - else - m_skip_prologue = eLazyBoolNo; - - if (!success) - error.SetErrorStringWithFormat ("Invalid boolean value for skip prologue option: '%s'", option_arg); - } - break; - - case 'l': - { - bool success; - m_line_num = StringConvert::ToUInt32 (option_arg, 0, 0, &success); - if (!success) - error.SetErrorStringWithFormat ("invalid line number: %s.", option_arg); - break; - } - - case 'L': - m_language = Language::GetLanguageTypeFromString (option_arg); - if (m_language == eLanguageTypeUnknown) - error.SetErrorStringWithFormat ("Unknown language type: '%s' for breakpoint", option_arg); - break; - - case 'm': - { - bool success; - bool value; - value = Args::StringToBoolean (option_arg, true, &success); - if (value) - m_move_to_nearest_code = eLazyBoolYes; - else - m_move_to_nearest_code = eLazyBoolNo; - - if (!success) - error.SetErrorStringWithFormat ("Invalid boolean value for move-to-nearest-code option: '%s'", option_arg); - break; - } - - case 'M': - m_func_names.push_back (option_arg); - m_func_name_type_mask |= eFunctionNameTypeMethod; - break; - - case 'n': - m_func_names.push_back (option_arg); - m_func_name_type_mask |= eFunctionNameTypeAuto; - break; - - case 'N': - if (BreakpointID::StringIsBreakpointName(option_arg, error)) - m_breakpoint_names.push_back (option_arg); - break; - - case 'R': - { - lldb::addr_t tmp_offset_addr; - tmp_offset_addr = - Args::StringToAddress(execution_context, option_arg, - 0, &error); - if (error.Success()) - m_offset_addr = tmp_offset_addr; - } - break; - - case 'o': - m_one_shot = true; - break; - - case 'O': - m_exception_extra_args.AppendArgument ("-O"); - m_exception_extra_args.AppendArgument (option_arg); - break; - - case 'p': - m_source_text_regexp.assign (option_arg); - break; - - case 'q': - m_queue_name.assign (option_arg); - break; - - case 'r': - m_func_regexp.assign (option_arg); - break; - - case 's': - m_modules.AppendIfUnique (FileSpec (option_arg, false)); - break; - - case 'S': - m_func_names.push_back (option_arg); - m_func_name_type_mask |= eFunctionNameTypeSelector; - break; - - case 't' : - m_thread_id = StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); - if (m_thread_id == LLDB_INVALID_THREAD_ID) - error.SetErrorStringWithFormat ("invalid thread id string '%s'", option_arg); - break; - - case 'T': - m_thread_name.assign (option_arg); - break; - - case 'w': - { - bool success; - m_throw_bp = Args::StringToBoolean (option_arg, true, &success); - if (!success) - error.SetErrorStringWithFormat ("Invalid boolean value for on-throw option: '%s'", option_arg); - } - break; - - case 'x': - m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); - if (m_thread_id == UINT32_MAX) - error.SetErrorStringWithFormat ("invalid thread index string '%s'", option_arg); - break; - - case 'X': - m_source_regex_func_names.insert(option_arg); - break; - - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } + // Now set the various options that were passed in: + if (bp) { + if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) + bp->SetThreadID(m_options.m_thread_id); - return error; - } + if (m_options.m_thread_index != UINT32_MAX) + bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index); - void - OptionParsingStarting (ExecutionContext *execution_context) override - { - m_condition.clear(); - m_filenames.Clear(); - m_line_num = 0; - m_column = 0; - m_func_names.clear(); - m_func_name_type_mask = eFunctionNameTypeNone; - m_func_regexp.clear(); - m_source_text_regexp.clear(); - m_modules.Clear(); - m_load_addr = LLDB_INVALID_ADDRESS; - m_offset_addr = 0; - m_ignore_count = 0; - m_thread_id = LLDB_INVALID_THREAD_ID; - m_thread_index = UINT32_MAX; - m_thread_name.clear(); - m_queue_name.clear(); - m_catch_bp = false; - m_throw_bp = true; - m_hardware = false; - m_exception_language = eLanguageTypeUnknown; - m_language = lldb::eLanguageTypeUnknown; - m_skip_prologue = eLazyBoolCalculate; - m_one_shot = false; - m_use_dummy = false; - m_breakpoint_names.clear(); - m_all_files = false; - m_exception_extra_args.Clear(); - m_move_to_nearest_code = eLazyBoolCalculate; - m_source_regex_func_names.clear(); - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } + if (!m_options.m_thread_name.empty()) + bp->GetOptions()->GetThreadSpec()->SetName( + m_options.m_thread_name.c_str()); - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - std::string m_condition; - FileSpecList m_filenames; - uint32_t m_line_num; - uint32_t m_column; - std::vector<std::string> m_func_names; - std::vector<std::string> m_breakpoint_names; - uint32_t m_func_name_type_mask; - std::string m_func_regexp; - std::string m_source_text_regexp; - FileSpecList m_modules; - lldb::addr_t m_load_addr; - lldb::addr_t m_offset_addr; - uint32_t m_ignore_count; - lldb::tid_t m_thread_id; - uint32_t m_thread_index; - std::string m_thread_name; - std::string m_queue_name; - bool m_catch_bp; - bool m_throw_bp; - bool m_hardware; // Request to use hardware breakpoints - lldb::LanguageType m_exception_language; - lldb::LanguageType m_language; - LazyBool m_skip_prologue; - bool m_one_shot; - bool m_use_dummy; - bool m_all_files; - Args m_exception_extra_args; - LazyBool m_move_to_nearest_code; - std::unordered_set<std::string> m_source_regex_func_names; - }; + if (!m_options.m_queue_name.empty()) + bp->GetOptions()->GetThreadSpec()->SetQueueName( + m_options.m_queue_name.c_str()); -protected: - bool - DoExecute (Args& command, - CommandReturnObject &result) override - { - Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); + if (m_options.m_ignore_count != 0) + bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count); - if (target == nullptr) - { - result.AppendError ("Invalid target. Must set target before setting breakpoints (see 'target create' command)."); - result.SetStatus (eReturnStatusFailed); - return false; - } - - // The following are the various types of breakpoints that could be set: - // 1). -f -l -p [-s -g] (setting breakpoint by source location) - // 2). -a [-s -g] (setting breakpoint by address) - // 3). -n [-s -g] (setting breakpoint by function name) - // 4). -r [-s -g] (setting breakpoint by function name regular expression) - // 5). -p -f (setting a breakpoint by comparing a reg-exp to source text) - // 6). -E [-w -h] (setting a breakpoint for exceptions for a given language.) - - BreakpointSetType break_type = eSetTypeInvalid; - - if (m_options.m_line_num != 0) - break_type = eSetTypeFileAndLine; - else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) - break_type = eSetTypeAddress; - else if (!m_options.m_func_names.empty()) - break_type = eSetTypeFunctionName; - else if (!m_options.m_func_regexp.empty()) - break_type = eSetTypeFunctionRegexp; - else if (!m_options.m_source_text_regexp.empty()) - break_type = eSetTypeSourceRegexp; - else if (m_options.m_exception_language != eLanguageTypeUnknown) - break_type = eSetTypeException; - - Breakpoint *bp = nullptr; - FileSpec module_spec; - const bool internal = false; - - // If the user didn't specify skip-prologue, having an offset should turn that off. - if (m_options.m_offset_addr != 0 && m_options.m_skip_prologue == eLazyBoolCalculate) - m_options.m_skip_prologue = eLazyBoolNo; - - switch (break_type) - { - case eSetTypeFileAndLine: // Breakpoint by source position - { - FileSpec file; - const size_t num_files = m_options.m_filenames.GetSize(); - if (num_files == 0) - { - if (!GetDefaultFile (target, file, result)) - { - result.AppendError("No file supplied and no default file available."); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - else if (num_files > 1) - { - result.AppendError("Only one file at a time is allowed for file and line breakpoints."); - result.SetStatus (eReturnStatusFailed); - return false; - } - else - file = m_options.m_filenames.GetFileSpecAtIndex(0); - - // Only check for inline functions if - LazyBool check_inlines = eLazyBoolCalculate; - - bp = target->CreateBreakpoint (&(m_options.m_modules), - file, - m_options.m_line_num, - m_options.m_offset_addr, - check_inlines, - m_options.m_skip_prologue, - internal, - m_options.m_hardware, - m_options.m_move_to_nearest_code).get(); - } - break; - - case eSetTypeAddress: // Breakpoint by address - { - // If a shared library has been specified, make an lldb_private::Address with the library, and - // use that. That way the address breakpoint will track the load location of the library. - size_t num_modules_specified = m_options.m_modules.GetSize(); - if (num_modules_specified == 1) - { - const FileSpec *file_spec = m_options.m_modules.GetFileSpecPointerAtIndex(0); - bp = target->CreateAddressInModuleBreakpoint (m_options.m_load_addr, - internal, - file_spec, - m_options.m_hardware).get(); - } - else if (num_modules_specified == 0) - { - bp = target->CreateBreakpoint (m_options.m_load_addr, - internal, - m_options.m_hardware).get(); - } - else - { - result.AppendError("Only one shared library can be specified for address breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } - break; - } - case eSetTypeFunctionName: // Breakpoint by function name - { - uint32_t name_type_mask = m_options.m_func_name_type_mask; - - if (name_type_mask == 0) - name_type_mask = eFunctionNameTypeAuto; - - bp = target->CreateBreakpoint (&(m_options.m_modules), - &(m_options.m_filenames), - m_options.m_func_names, - name_type_mask, - m_options.m_language, - m_options.m_offset_addr, - m_options.m_skip_prologue, - internal, - m_options.m_hardware).get(); - } - break; - - case eSetTypeFunctionRegexp: // Breakpoint by regular expression function name - { - RegularExpression regexp(m_options.m_func_regexp.c_str()); - if (!regexp.IsValid()) - { - char err_str[1024]; - regexp.GetErrorAsCString(err_str, sizeof(err_str)); - result.AppendErrorWithFormat("Function name regular expression could not be compiled: \"%s\"", - err_str); - result.SetStatus (eReturnStatusFailed); - return false; - } - - bp = target->CreateFuncRegexBreakpoint (&(m_options.m_modules), - &(m_options.m_filenames), - regexp, - m_options.m_language, - m_options.m_skip_prologue, - internal, - m_options.m_hardware).get(); - } - break; - case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. - { - const size_t num_files = m_options.m_filenames.GetSize(); - - if (num_files == 0 && !m_options.m_all_files) - { - FileSpec file; - if (!GetDefaultFile (target, file, result)) - { - result.AppendError ("No files provided and could not find default file."); - result.SetStatus (eReturnStatusFailed); - return false; - } - else - { - m_options.m_filenames.Append (file); - } - } - - RegularExpression regexp(m_options.m_source_text_regexp.c_str()); - if (!regexp.IsValid()) - { - char err_str[1024]; - regexp.GetErrorAsCString(err_str, sizeof(err_str)); - result.AppendErrorWithFormat("Source text regular expression could not be compiled: \"%s\"", - err_str); - result.SetStatus (eReturnStatusFailed); - return false; - } - bp = target->CreateSourceRegexBreakpoint (&(m_options.m_modules), - &(m_options.m_filenames), - m_options.m_source_regex_func_names, - regexp, - internal, - m_options.m_hardware, - m_options.m_move_to_nearest_code).get(); - } - break; - case eSetTypeException: - { - Error precond_error; - bp = target->CreateExceptionBreakpoint (m_options.m_exception_language, - m_options.m_catch_bp, - m_options.m_throw_bp, - internal, - &m_options.m_exception_extra_args, - &precond_error).get(); - if (precond_error.Fail()) - { - result.AppendErrorWithFormat("Error setting extra exception arguments: %s", - precond_error.AsCString()); - target->RemoveBreakpointByID(bp->GetID()); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - break; - default: - break; - } - - // Now set the various options that were passed in: - if (bp) - { - if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) - bp->SetThreadID (m_options.m_thread_id); - - if (m_options.m_thread_index != UINT32_MAX) - bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index); - - if (!m_options.m_thread_name.empty()) - bp->GetOptions()->GetThreadSpec()->SetName(m_options.m_thread_name.c_str()); - - if (!m_options.m_queue_name.empty()) - bp->GetOptions()->GetThreadSpec()->SetQueueName(m_options.m_queue_name.c_str()); - - if (m_options.m_ignore_count != 0) - bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count); + if (!m_options.m_condition.empty()) + bp->GetOptions()->SetCondition(m_options.m_condition.c_str()); - if (!m_options.m_condition.empty()) - bp->GetOptions()->SetCondition(m_options.m_condition.c_str()); + if (!m_options.m_breakpoint_names.empty()) { + Error error; // We don't need to check the error here, since the option + // parser checked it... + for (auto name : m_options.m_breakpoint_names) + bp->AddName(name.c_str(), error); + } - if (!m_options.m_breakpoint_names.empty()) - { - Error error; // We don't need to check the error here, since the option parser checked it... - for (auto name : m_options.m_breakpoint_names) - bp->AddName(name.c_str(), error); - } - - bp->SetOneShot (m_options.m_one_shot); - } - - if (bp) - { - Stream &output_stream = result.GetOutputStream(); - const bool show_locations = false; - bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, show_locations); - if (target == m_interpreter.GetDebugger().GetDummyTarget()) - output_stream.Printf ("Breakpoint set in dummy target, will get copied into future targets.\n"); - else - { - // Don't print out this warning for exception breakpoints. They can get set before the target - // is set, but we won't know how to actually set the breakpoint till we run. - if (bp->GetNumLocations() == 0 && break_type != eSetTypeException) - { - output_stream.Printf ("WARNING: Unable to resolve breakpoint to any actual locations.\n"); - } - } - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else if (!bp) - { - result.AppendError ("Breakpoint creation failed: No breakpoint created."); - result.SetStatus (eReturnStatusFailed); - } + bp->SetOneShot(m_options.m_one_shot); + } - return result.Succeeded(); + if (bp) { + Stream &output_stream = result.GetOutputStream(); + const bool show_locations = false; + bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, + show_locations); + if (target == m_interpreter.GetDebugger().GetDummyTarget()) + output_stream.Printf("Breakpoint set in dummy target, will get copied " + "into future targets.\n"); + else { + // Don't print out this warning for exception breakpoints. They can get + // set before the target + // is set, but we won't know how to actually set the breakpoint till we + // run. + if (bp->GetNumLocations() == 0 && break_type != eSetTypeException) { + output_stream.Printf("WARNING: Unable to resolve breakpoint to any " + "actual locations.\n"); + } + } + result.SetStatus(eReturnStatusSuccessFinishResult); + } else if (!bp) { + result.AppendError("Breakpoint creation failed: No breakpoint created."); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } + private: - bool - GetDefaultFile (Target *target, FileSpec &file, CommandReturnObject &result) - { - uint32_t default_line; - // First use the Source Manager's default file. - // Then use the current stack frame's file. - if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) - { - StackFrame *cur_frame = m_exe_ctx.GetFramePtr(); - if (cur_frame == nullptr) - { - result.AppendError ("No selected frame to use to find the default file."); - result.SetStatus (eReturnStatusFailed); - return false; - } - else if (!cur_frame->HasDebugInformation()) - { - result.AppendError ("Cannot use the selected frame to find the default file, it has no debug info."); - result.SetStatus (eReturnStatusFailed); - return false; - } - else - { - const SymbolContext &sc = cur_frame->GetSymbolContext (eSymbolContextLineEntry); - if (sc.line_entry.file) - { - file = sc.line_entry.file; - } - else - { - result.AppendError ("Can't find the file for the selected frame to use as the default file."); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - } - return true; + bool GetDefaultFile(Target *target, FileSpec &file, + CommandReturnObject &result) { + uint32_t default_line; + // First use the Source Manager's default file. + // Then use the current stack frame's file. + if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) { + StackFrame *cur_frame = m_exe_ctx.GetFramePtr(); + if (cur_frame == nullptr) { + result.AppendError( + "No selected frame to use to find the default file."); + result.SetStatus(eReturnStatusFailed); + return false; + } else if (!cur_frame->HasDebugInformation()) { + result.AppendError("Cannot use the selected frame to find the default " + "file, it has no debug info."); + result.SetStatus(eReturnStatusFailed); + return false; + } else { + const SymbolContext &sc = + cur_frame->GetSymbolContext(eSymbolContextLineEntry); + if (sc.line_entry.file) { + file = sc.line_entry.file; + } else { + result.AppendError("Can't find the file for the selected frame to " + "use as the default file."); + result.SetStatus(eReturnStatusFailed); + return false; + } + } } - - CommandOptions m_options; + return true; + } + + CommandOptions m_options; }; // If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to // update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately. -#define LLDB_OPT_FILE ( LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2 ) -#define LLDB_OPT_NOT_10 ( LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10 ) -#define LLDB_OPT_SKIP_PROLOGUE ( LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3,8) ) -#define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3,8) ) -#define LLDB_OPT_MOVE_TO_NEAREST_CODE ( LLDB_OPT_SET_1 | LLDB_OPT_SET_9 ) -#define LLDB_OPT_EXPR_LANGUAGE ( LLDB_OPT_SET_FROM_TO(3, 8) ) - -OptionDefinition -CommandObjectBreakpointSet::CommandOptions::g_option_table[] = -{ - // clang-format off +#define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2) +#define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10) +#define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8)) +#define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8)) +#define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9) +#define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8)) + +OptionDefinition CommandObjectBreakpointSet::CommandOptions::g_option_table[] = + { + // clang-format off {LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the breakpoint only in this shared library. Can repeat this option " "multiple times to specify multiple shared libraries."}, {LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." }, @@ -838,7 +781,7 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] = {LLDB_OPT_MOVE_TO_NEAREST_CODE, false, "move-to-nearest-code", 'm', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Move breakpoints to nearest code. If not set the target.move-to-nearest-code " "setting is used."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- @@ -846,300 +789,264 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] = //------------------------------------------------------------------------- #pragma mark Modify -class CommandObjectBreakpointModify : public CommandObjectParsed -{ +class CommandObjectBreakpointModify : public CommandObjectParsed { public: - CommandObjectBreakpointModify (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "breakpoint modify", - "Modify the options on a breakpoint or set of breakpoints in the executable. " - "If no breakpoint is specified, acts on the last created breakpoint. " - "With the exception of -e, -d and -i, passing an empty argument clears the modification.", + CommandObjectBreakpointModify(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "breakpoint modify", + "Modify the options on a breakpoint or set of " + "breakpoints in the executable. " + "If no breakpoint is specified, acts on the last " + "created breakpoint. " + "With the exception of -e, -d and -i, passing an " + "empty argument clears the modification.", 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() { + 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); + } + + ~CommandObjectBreakpointModify() override = default; + + Options *GetOptions() override { return &m_options; } + + class CommandOptions : public Options { + public: + CommandOptions() + : Options(), m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID), + m_thread_id_passed(false), m_thread_index(UINT32_MAX), + m_thread_index_passed(false), m_thread_name(), m_queue_name(), + m_condition(), m_one_shot(false), m_enable_passed(false), + m_enable_value(false), m_name_passed(false), m_queue_passed(false), + m_condition_passed(false), m_one_shot_passed(false), + m_use_dummy(false) {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'c': + if (option_arg != nullptr) + m_condition.assign(option_arg); + else + m_condition.clear(); + m_condition_passed = true; + break; + case 'd': + m_enable_passed = true; + m_enable_value = false; + break; + case 'D': + m_use_dummy = true; + break; + case 'e': + m_enable_passed = true; + m_enable_value = true; + break; + case 'i': + m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); + if (m_ignore_count == UINT32_MAX) + error.SetErrorStringWithFormat("invalid ignore count '%s'", + option_arg); + break; + case 'o': { + bool value, success; + value = Args::StringToBoolean(option_arg, false, &success); + if (success) { + m_one_shot_passed = true; + m_one_shot = value; + } else + error.SetErrorStringWithFormat( + "invalid boolean value '%s' passed for -o option", option_arg); + } break; + case 't': + if (option_arg[0] == '\0') { + m_thread_id = LLDB_INVALID_THREAD_ID; + m_thread_id_passed = true; + } else { + m_thread_id = + StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); + if (m_thread_id == LLDB_INVALID_THREAD_ID) + error.SetErrorStringWithFormat("invalid thread id string '%s'", + option_arg); + else + m_thread_id_passed = true; + } + break; + case 'T': + if (option_arg != nullptr) + m_thread_name.assign(option_arg); + else + m_thread_name.clear(); + m_name_passed = true; + break; + case 'q': + if (option_arg != nullptr) + m_queue_name.assign(option_arg); + else + m_queue_name.clear(); + m_queue_passed = true; + break; + case 'x': + if (option_arg[0] == '\n') { + m_thread_index = UINT32_MAX; + m_thread_index_passed = true; + } else { + m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); + if (m_thread_id == UINT32_MAX) + error.SetErrorStringWithFormat("invalid thread index string '%s'", + option_arg); + else + m_thread_index_passed = true; + } + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; } - ~CommandObjectBreakpointModify() override = default; - - Options * - GetOptions () override - { - return &m_options; + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_ignore_count = 0; + m_thread_id = LLDB_INVALID_THREAD_ID; + m_thread_id_passed = false; + m_thread_index = UINT32_MAX; + m_thread_index_passed = false; + m_thread_name.clear(); + m_queue_name.clear(); + m_condition.clear(); + m_one_shot = false; + m_enable_passed = false; + m_queue_passed = false; + m_name_passed = false; + m_condition_passed = false; + m_one_shot_passed = false; + m_use_dummy = false; } - class CommandOptions : public Options - { - public: - CommandOptions () : - Options (), - m_ignore_count (0), - m_thread_id(LLDB_INVALID_THREAD_ID), - m_thread_id_passed(false), - m_thread_index (UINT32_MAX), - m_thread_index_passed(false), - m_thread_name(), - m_queue_name(), - m_condition (), - m_one_shot (false), - m_enable_passed (false), - m_enable_value (false), - m_name_passed (false), - m_queue_passed (false), - m_condition_passed (false), - m_one_shot_passed (false), - m_use_dummy (false) - { - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } - ~CommandOptions() override = default; - - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'c': - if (option_arg != nullptr) - m_condition.assign (option_arg); - else - m_condition.clear(); - m_condition_passed = true; - break; - case 'd': - m_enable_passed = true; - m_enable_value = false; - break; - case 'D': - m_use_dummy = true; - break; - case 'e': - m_enable_passed = true; - m_enable_value = true; - break; - case 'i': - m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); - if (m_ignore_count == UINT32_MAX) - error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg); - break; - case 'o': - { - bool value, success; - value = Args::StringToBoolean(option_arg, false, &success); - if (success) - { - m_one_shot_passed = true; - m_one_shot = value; - } - else - error.SetErrorStringWithFormat("invalid boolean value '%s' passed for -o option", option_arg); - } - break; - case 't' : - if (option_arg[0] == '\0') - { - m_thread_id = LLDB_INVALID_THREAD_ID; - m_thread_id_passed = true; - } - else - { - m_thread_id = StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); - if (m_thread_id == LLDB_INVALID_THREAD_ID) - error.SetErrorStringWithFormat ("invalid thread id string '%s'", option_arg); - else - m_thread_id_passed = true; - } - break; - case 'T': - if (option_arg != nullptr) - m_thread_name.assign (option_arg); - else - m_thread_name.clear(); - m_name_passed = true; - break; - case 'q': - if (option_arg != nullptr) - m_queue_name.assign (option_arg); - else - m_queue_name.clear(); - m_queue_passed = true; - break; - case 'x': - if (option_arg[0] == '\n') - { - m_thread_index = UINT32_MAX; - m_thread_index_passed = true; - } - else - { - m_thread_index = StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0); - if (m_thread_id == UINT32_MAX) - error.SetErrorStringWithFormat ("invalid thread index string '%s'", option_arg); - else - m_thread_index_passed = true; - } - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } + // Options table: Required for subclasses of Options. - return error; - } + static OptionDefinition g_option_table[]; - void - OptionParsingStarting (ExecutionContext *execution_context) override - { - m_ignore_count = 0; - m_thread_id = LLDB_INVALID_THREAD_ID; - m_thread_id_passed = false; - m_thread_index = UINT32_MAX; - m_thread_index_passed = false; - m_thread_name.clear(); - m_queue_name.clear(); - m_condition.clear(); - m_one_shot = false; - m_enable_passed = false; - m_queue_passed = false; - m_name_passed = false; - m_condition_passed = false; - m_one_shot_passed = false; - m_use_dummy = false; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - uint32_t m_ignore_count; - lldb::tid_t m_thread_id; - bool m_thread_id_passed; - uint32_t m_thread_index; - bool m_thread_index_passed; - std::string m_thread_name; - std::string m_queue_name; - std::string m_condition; - bool m_one_shot; - bool m_enable_passed; - bool m_enable_value; - bool m_name_passed; - bool m_queue_passed; - bool m_condition_passed; - bool m_one_shot_passed; - bool m_use_dummy; - }; + // Instance variables to hold the values for command options. + + uint32_t m_ignore_count; + lldb::tid_t m_thread_id; + bool m_thread_id_passed; + uint32_t m_thread_index; + bool m_thread_index_passed; + std::string m_thread_name; + std::string m_queue_name; + std::string m_condition; + bool m_one_shot; + bool m_enable_passed; + bool m_enable_value; + bool m_name_passed; + bool m_queue_passed; + bool m_condition_passed; + bool m_one_shot_passed; + bool m_use_dummy; + }; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); - if (target == nullptr) - { - result.AppendError ("Invalid target. No existing target or breakpoints."); - result.SetStatus (eReturnStatusFailed); - return false; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); + if (target == nullptr) { + result.AppendError("Invalid target. No existing target or breakpoints."); + result.SetStatus(eReturnStatusFailed); + return false; + } + + std::unique_lock<std::recursive_mutex> lock; + target->GetBreakpointList().GetListMutex(lock); + + BreakpointIDList valid_bp_ids; + + CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( + command, target, result, &valid_bp_ids); + + if (result.Succeeded()) { + const size_t count = valid_bp_ids.GetSize(); + for (size_t i = 0; i < count; ++i) { + BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); + + if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { + Breakpoint *bp = + target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { + BreakpointLocation *location = + bp->FindLocationByID(cur_bp_id.GetLocationID()).get(); + if (location) { + if (m_options.m_thread_id_passed) + location->SetThreadID(m_options.m_thread_id); + + if (m_options.m_thread_index_passed) + location->SetThreadIndex(m_options.m_thread_index); + + if (m_options.m_name_passed) + location->SetThreadName(m_options.m_thread_name.c_str()); - std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); - - BreakpointIDList valid_bp_ids; - - CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); - - if (result.Succeeded()) - { - const size_t count = valid_bp_ids.GetSize(); - for (size_t i = 0; i < count; ++i) - { - BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); - - if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) - { - Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); - if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) - { - BreakpointLocation *location = bp->FindLocationByID (cur_bp_id.GetLocationID()).get(); - if (location) - { - if (m_options.m_thread_id_passed) - location->SetThreadID (m_options.m_thread_id); - - if (m_options.m_thread_index_passed) - location->SetThreadIndex(m_options.m_thread_index); - - if (m_options.m_name_passed) - location->SetThreadName(m_options.m_thread_name.c_str()); - - if (m_options.m_queue_passed) - location->SetQueueName(m_options.m_queue_name.c_str()); - - if (m_options.m_ignore_count != 0) - location->SetIgnoreCount(m_options.m_ignore_count); - - if (m_options.m_enable_passed) - location->SetEnabled (m_options.m_enable_value); - - if (m_options.m_condition_passed) - location->SetCondition (m_options.m_condition.c_str()); - } - } - else - { - if (m_options.m_thread_id_passed) - bp->SetThreadID (m_options.m_thread_id); - - if (m_options.m_thread_index_passed) - bp->SetThreadIndex(m_options.m_thread_index); - - if (m_options.m_name_passed) - bp->SetThreadName(m_options.m_thread_name.c_str()); - - if (m_options.m_queue_passed) - bp->SetQueueName(m_options.m_queue_name.c_str()); - - if (m_options.m_ignore_count != 0) - bp->SetIgnoreCount(m_options.m_ignore_count); - - if (m_options.m_enable_passed) - bp->SetEnabled (m_options.m_enable_value); - - if (m_options.m_condition_passed) - bp->SetCondition (m_options.m_condition.c_str()); - } - } + if (m_options.m_queue_passed) + location->SetQueueName(m_options.m_queue_name.c_str()); + + if (m_options.m_ignore_count != 0) + location->SetIgnoreCount(m_options.m_ignore_count); + + if (m_options.m_enable_passed) + location->SetEnabled(m_options.m_enable_value); + + if (m_options.m_condition_passed) + location->SetCondition(m_options.m_condition.c_str()); } + } else { + if (m_options.m_thread_id_passed) + bp->SetThreadID(m_options.m_thread_id); + + if (m_options.m_thread_index_passed) + bp->SetThreadIndex(m_options.m_thread_index); + + if (m_options.m_name_passed) + bp->SetThreadName(m_options.m_thread_name.c_str()); + + if (m_options.m_queue_passed) + bp->SetQueueName(m_options.m_queue_name.c_str()); + + if (m_options.m_ignore_count != 0) + bp->SetIgnoreCount(m_options.m_ignore_count); + + if (m_options.m_enable_passed) + bp->SetEnabled(m_options.m_enable_value); + + if (m_options.m_condition_passed) + bp->SetCondition(m_options.m_condition.c_str()); + } } - - return result.Succeeded(); + } } + return result.Succeeded(); + } + private: - CommandOptions m_options; + CommandOptions m_options; }; #pragma mark Modify::CommandOptions OptionDefinition -CommandObjectBreakpointModify::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectBreakpointModify::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping."}, {LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop."}, {LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument."}, @@ -1151,7 +1058,7 @@ CommandObjectBreakpointModify::CommandOptions::g_option_table[] = {LLDB_OPT_SET_2, false, "disable", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disable the breakpoint."}, {LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- @@ -1159,97 +1066,89 @@ CommandObjectBreakpointModify::CommandOptions::g_option_table[] = //------------------------------------------------------------------------- #pragma mark Enable -class CommandObjectBreakpointEnable : public CommandObjectParsed -{ +class CommandObjectBreakpointEnable : public CommandObjectParsed { public: - CommandObjectBreakpointEnable (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "enable", - "Enable the specified disabled breakpoint(s). If no breakpoints are specified, enable all of them.", - nullptr) - { - 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); - } - - ~CommandObjectBreakpointEnable() override = default; + CommandObjectBreakpointEnable(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "enable", + "Enable the specified disabled breakpoint(s). If " + "no breakpoints are specified, enable all of them.", + nullptr) { + 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); + } + + ~CommandObjectBreakpointEnable() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = GetSelectedOrDummyTarget(); - if (target == nullptr) - { - result.AppendError ("Invalid target. No existing target or breakpoints."); - result.SetStatus (eReturnStatusFailed); - return false; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = GetSelectedOrDummyTarget(); + if (target == nullptr) { + result.AppendError("Invalid target. No existing target or breakpoints."); + result.SetStatus(eReturnStatusFailed); + return false; + } - std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + std::unique_lock<std::recursive_mutex> lock; + target->GetBreakpointList().GetListMutex(lock); - const BreakpointList &breakpoints = target->GetBreakpointList(); + const BreakpointList &breakpoints = target->GetBreakpointList(); - size_t num_breakpoints = breakpoints.GetSize(); + size_t num_breakpoints = breakpoints.GetSize(); - if (num_breakpoints == 0) - { - result.AppendError ("No breakpoints exist to be enabled."); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (num_breakpoints == 0) { + result.AppendError("No breakpoints exist to be enabled."); + result.SetStatus(eReturnStatusFailed); + return false; + } - if (command.GetArgumentCount() == 0) - { - // No breakpoint selected; enable all currently set breakpoints. - target->EnableAllBreakpoints (); - result.AppendMessageWithFormat ("All breakpoints enabled. (%" PRIu64 " breakpoints)\n", (uint64_t)num_breakpoints); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - // Particular breakpoint selected; enable that breakpoint. - BreakpointIDList valid_bp_ids; - CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); - - if (result.Succeeded()) - { - int enable_count = 0; - int loc_count = 0; - const size_t count = valid_bp_ids.GetSize(); - for (size_t i = 0; i < count; ++i) - { - BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); - - if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) - { - Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); - if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) - { - BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get(); - if (location) - { - location->SetEnabled (true); - ++loc_count; - } - } - else - { - breakpoint->SetEnabled (true); - ++enable_count; - } - } - } - result.AppendMessageWithFormat ("%d breakpoints enabled.\n", enable_count + loc_count); - result.SetStatus (eReturnStatusSuccessFinishNoResult); + if (command.GetArgumentCount() == 0) { + // No breakpoint selected; enable all currently set breakpoints. + target->EnableAllBreakpoints(); + result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64 + " breakpoints)\n", + (uint64_t)num_breakpoints); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + // Particular breakpoint selected; enable that breakpoint. + BreakpointIDList valid_bp_ids; + CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( + command, target, result, &valid_bp_ids); + + if (result.Succeeded()) { + int enable_count = 0; + int loc_count = 0; + const size_t count = valid_bp_ids.GetSize(); + for (size_t i = 0; i < count; ++i) { + BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); + + if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { + Breakpoint *breakpoint = + target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { + BreakpointLocation *location = + breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); + if (location) { + location->SetEnabled(true); + ++loc_count; + } + } else { + breakpoint->SetEnabled(true); + ++enable_count; } + } } - - return result.Succeeded(); + result.AppendMessageWithFormat("%d breakpoints enabled.\n", + enable_count + loc_count); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } } + + return result.Succeeded(); + } }; //------------------------------------------------------------------------- @@ -1257,23 +1156,24 @@ protected: //------------------------------------------------------------------------- #pragma mark Disable -class CommandObjectBreakpointDisable : public CommandObjectParsed -{ +class CommandObjectBreakpointDisable : public CommandObjectParsed { public: - CommandObjectBreakpointDisable(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "breakpoint disable", "Disable the specified breakpoint(s) without deleting " - "them. If none are specified, disable all " - "breakpoints.", - nullptr) - { - SetHelpLong("Disable the specified breakpoint(s) without deleting them. \ + CommandObjectBreakpointDisable(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "breakpoint disable", + "Disable the specified breakpoint(s) without deleting " + "them. If none are specified, disable all " + "breakpoints.", + nullptr) { + SetHelpLong( + "Disable the specified breakpoint(s) without deleting them. \ If none are specified, disable all breakpoints." - R"( + R"( )" - "Note: disabling a breakpoint will cause none of its locations to be hit \ + "Note: disabling a breakpoint will cause none of its locations to be hit \ regardless of whether individual locations are enabled or disabled. After the sequence:" - R"( + R"( (lldb) break disable 1 (lldb) break enable 1.1 @@ -1284,91 +1184,85 @@ execution will NOT stop at location 1.1. To achieve that, type: (lldb) break enable 1.1 )" - "The first command disables all locations for breakpoint 1, \ + "The first command disables all locations for breakpoint 1, \ the second re-enables the first location."); - 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); - } + 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); + } - ~CommandObjectBreakpointDisable() override = default; + ~CommandObjectBreakpointDisable() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = GetSelectedOrDummyTarget(); - if (target == nullptr) - { - result.AppendError ("Invalid target. No existing target or breakpoints."); - result.SetStatus (eReturnStatusFailed); - return false; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = GetSelectedOrDummyTarget(); + if (target == nullptr) { + result.AppendError("Invalid target. No existing target or breakpoints."); + result.SetStatus(eReturnStatusFailed); + return false; + } - std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + std::unique_lock<std::recursive_mutex> lock; + target->GetBreakpointList().GetListMutex(lock); - const BreakpointList &breakpoints = target->GetBreakpointList(); - size_t num_breakpoints = breakpoints.GetSize(); + const BreakpointList &breakpoints = target->GetBreakpointList(); + size_t num_breakpoints = breakpoints.GetSize(); - if (num_breakpoints == 0) - { - result.AppendError ("No breakpoints exist to be disabled."); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (num_breakpoints == 0) { + result.AppendError("No breakpoints exist to be disabled."); + result.SetStatus(eReturnStatusFailed); + return false; + } - if (command.GetArgumentCount() == 0) - { - // No breakpoint selected; disable all currently set breakpoints. - target->DisableAllBreakpoints (); - result.AppendMessageWithFormat ("All breakpoints disabled. (%" PRIu64 " breakpoints)\n", (uint64_t)num_breakpoints); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - // Particular breakpoint selected; disable that breakpoint. - BreakpointIDList valid_bp_ids; - - CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); - - if (result.Succeeded()) - { - int disable_count = 0; - int loc_count = 0; - const size_t count = valid_bp_ids.GetSize(); - for (size_t i = 0; i < count; ++i) - { - BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); - - if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) - { - Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); - if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) - { - BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get(); - if (location) - { - location->SetEnabled (false); - ++loc_count; - } - } - else - { - breakpoint->SetEnabled (false); - ++disable_count; - } - } - } - result.AppendMessageWithFormat ("%d breakpoints disabled.\n", disable_count + loc_count); - result.SetStatus (eReturnStatusSuccessFinishNoResult); + if (command.GetArgumentCount() == 0) { + // No breakpoint selected; disable all currently set breakpoints. + target->DisableAllBreakpoints(); + result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64 + " breakpoints)\n", + (uint64_t)num_breakpoints); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + // Particular breakpoint selected; disable that breakpoint. + BreakpointIDList valid_bp_ids; + + CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( + command, target, result, &valid_bp_ids); + + if (result.Succeeded()) { + int disable_count = 0; + int loc_count = 0; + const size_t count = valid_bp_ids.GetSize(); + for (size_t i = 0; i < count; ++i) { + BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); + + if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { + Breakpoint *breakpoint = + target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { + BreakpointLocation *location = + breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); + if (location) { + location->SetEnabled(false); + ++loc_count; + } + } else { + breakpoint->SetEnabled(false); + ++disable_count; } + } } - - return result.Succeeded(); + result.AppendMessageWithFormat("%d breakpoints disabled.\n", + disable_count + loc_count); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } } + + return result.Succeeded(); + } }; //------------------------------------------------------------------------- @@ -1376,182 +1270,156 @@ protected: //------------------------------------------------------------------------- #pragma mark List -class CommandObjectBreakpointList : public CommandObjectParsed -{ +class CommandObjectBreakpointList : public CommandObjectParsed { public: - CommandObjectBreakpointList (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "breakpoint list", - "List some or all breakpoints at configurable levels of detail.", - nullptr), - m_options () - { - CommandArgumentEntry arg; - CommandArgumentData bp_id_arg; - - // Define the first (and only) variant of this arg. - bp_id_arg.arg_type = eArgTypeBreakpointID; - bp_id_arg.arg_repetition = eArgRepeatOptional; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (bp_id_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); + CommandObjectBreakpointList(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "breakpoint list", + "List some or all breakpoints at configurable levels of detail.", + nullptr), + m_options() { + CommandArgumentEntry arg; + CommandArgumentData bp_id_arg; + + // Define the first (and only) variant of this arg. + bp_id_arg.arg_type = eArgTypeBreakpointID; + bp_id_arg.arg_repetition = eArgRepeatOptional; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(bp_id_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectBreakpointList() override = default; + + Options *GetOptions() override { return &m_options; } + + class CommandOptions : public Options { + public: + CommandOptions() + : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) { } - ~CommandObjectBreakpointList() override = default; - - Options * - GetOptions () override - { - return &m_options; + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'b': + m_level = lldb::eDescriptionLevelBrief; + break; + case 'D': + m_use_dummy = true; + break; + case 'f': + m_level = lldb::eDescriptionLevelFull; + break; + case 'v': + m_level = lldb::eDescriptionLevelVerbose; + break; + case 'i': + m_internal = true; + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; } - - class CommandOptions : public Options - { - public: - CommandOptions () : - Options (), - m_level (lldb::eDescriptionLevelBrief), - m_use_dummy(false) - { - } - - ~CommandOptions() override = default; - - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'b': - m_level = lldb::eDescriptionLevelBrief; - break; - case 'D': - m_use_dummy = true; - break; - case 'f': - m_level = lldb::eDescriptionLevelFull; - break; - case 'v': - m_level = lldb::eDescriptionLevelVerbose; - break; - case 'i': - m_internal = true; - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - return error; - } - - void - OptionParsingStarting (ExecutionContext *execution_context) override - { - m_level = lldb::eDescriptionLevelFull; - m_internal = false; - m_use_dummy = false; - } + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_level = lldb::eDescriptionLevelFull; + m_internal = false; + m_use_dummy = false; + } - const OptionDefinition * - GetDefinitions () override - { - return g_option_table; - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } - // Options table: Required for subclasses of Options. + // Options table: Required for subclasses of Options. - static OptionDefinition g_option_table[]; + static OptionDefinition g_option_table[]; - // Instance variables to hold the values for command options. + // Instance variables to hold the values for command options. - lldb::DescriptionLevel m_level; + lldb::DescriptionLevel m_level; - bool m_internal; - bool m_use_dummy; - }; + bool m_internal; + bool m_use_dummy; + }; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); - - if (target == nullptr) - { - result.AppendError ("Invalid target. No current target or breakpoints."); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - return true; - } - - const BreakpointList &breakpoints = target->GetBreakpointList(m_options.m_internal); - std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList(m_options.m_internal).GetListMutex(lock); + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); - size_t num_breakpoints = breakpoints.GetSize(); + if (target == nullptr) { + result.AppendError("Invalid target. No current target or breakpoints."); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return true; + } - if (num_breakpoints == 0) - { - result.AppendMessage ("No breakpoints currently set."); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - return true; - } + const BreakpointList &breakpoints = + target->GetBreakpointList(m_options.m_internal); + std::unique_lock<std::recursive_mutex> lock; + target->GetBreakpointList(m_options.m_internal).GetListMutex(lock); - Stream &output_stream = result.GetOutputStream(); + size_t num_breakpoints = breakpoints.GetSize(); - if (command.GetArgumentCount() == 0) - { - // No breakpoint selected; show info about all currently set breakpoints. - result.AppendMessage ("Current breakpoints:"); - for (size_t i = 0; i < num_breakpoints; ++i) - { - Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex (i).get(); - AddBreakpointDescription (&output_stream, breakpoint, m_options.m_level); - } - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - // Particular breakpoints selected; show info about that breakpoint. - BreakpointIDList valid_bp_ids; - CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); - - if (result.Succeeded()) - { - for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) - { - BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); - Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); - AddBreakpointDescription (&output_stream, breakpoint, m_options.m_level); - } - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendError("Invalid breakpoint ID."); - result.SetStatus (eReturnStatusFailed); - } - } + if (num_breakpoints == 0) { + result.AppendMessage("No breakpoints currently set."); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return true; + } - return result.Succeeded(); + Stream &output_stream = result.GetOutputStream(); + + if (command.GetArgumentCount() == 0) { + // No breakpoint selected; show info about all currently set breakpoints. + result.AppendMessage("Current breakpoints:"); + for (size_t i = 0; i < num_breakpoints; ++i) { + Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get(); + AddBreakpointDescription(&output_stream, breakpoint, m_options.m_level); + } + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + // Particular breakpoints selected; show info about that breakpoint. + BreakpointIDList valid_bp_ids; + CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( + command, target, result, &valid_bp_ids); + + if (result.Succeeded()) { + for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) { + BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); + Breakpoint *breakpoint = + target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + AddBreakpointDescription(&output_stream, breakpoint, + m_options.m_level); + } + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.AppendError("Invalid breakpoint ID."); + result.SetStatus(eReturnStatusFailed); + } } + return result.Succeeded(); + } + private: - CommandOptions m_options; + CommandOptions m_options; }; #pragma mark List::CommandOptions -OptionDefinition -CommandObjectBreakpointList::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectBreakpointList::CommandOptions::g_option_table[] = + { + // clang-format off {LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show debugger internal breakpoints" }, {LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)."}, // FIXME: We need to add an "internal" command, and then add this sort of thing to it. @@ -1560,7 +1428,7 @@ CommandObjectBreakpointList::CommandOptions::g_option_table[] = {LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)."}, {LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "List Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- @@ -1568,196 +1436,162 @@ CommandObjectBreakpointList::CommandOptions::g_option_table[] = //------------------------------------------------------------------------- #pragma mark Clear -class CommandObjectBreakpointClear : public CommandObjectParsed -{ +class CommandObjectBreakpointClear : public CommandObjectParsed { public: - typedef enum BreakpointClearType - { - eClearTypeInvalid, - eClearTypeFileAndLine - } BreakpointClearType; - - CommandObjectBreakpointClear(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "breakpoint clear", - "Delete or disable breakpoints matching the specified source file and line.", - "breakpoint clear <cmd-options>"), - m_options() - { - } + typedef enum BreakpointClearType { + eClearTypeInvalid, + eClearTypeFileAndLine + } BreakpointClearType; - ~CommandObjectBreakpointClear() override = default; + CommandObjectBreakpointClear(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "breakpoint clear", + "Delete or disable breakpoints matching the " + "specified source file and line.", + "breakpoint clear <cmd-options>"), + m_options() {} - Options * - GetOptions () override - { - return &m_options; - } + ~CommandObjectBreakpointClear() override = default; - class CommandOptions : public Options - { - public: - CommandOptions () : - Options (), - m_filename (), - m_line_num (0) - { - } + Options *GetOptions() override { return &m_options; } - ~CommandOptions() override = default; + class CommandOptions : public Options { + public: + CommandOptions() : Options(), m_filename(), m_line_num(0) {} - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; + ~CommandOptions() override = default; - switch (short_option) - { - case 'f': - m_filename.assign (option_arg); - break; + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; - case 'l': - m_line_num = StringConvert::ToUInt32 (option_arg, 0); - break; + switch (short_option) { + case 'f': + m_filename.assign(option_arg); + break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } + case 'l': + m_line_num = StringConvert::ToUInt32(option_arg, 0); + break; - return error; - } + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } - void - OptionParsingStarting (ExecutionContext *execution_context) override - { - m_filename.clear(); - m_line_num = 0; - } + return error; + } - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_filename.clear(); + m_line_num = 0; + } - // Options table: Required for subclasses of Options. + const OptionDefinition *GetDefinitions() override { return g_option_table; } - static OptionDefinition g_option_table[]; + // Options table: Required for subclasses of Options. - // Instance variables to hold the values for command options. + static OptionDefinition g_option_table[]; - std::string m_filename; - uint32_t m_line_num; + // Instance variables to hold the values for command options. - }; + std::string m_filename; + uint32_t m_line_num; + }; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = GetSelectedOrDummyTarget(); - if (target == nullptr) - { - result.AppendError ("Invalid target. No existing target or breakpoints."); - result.SetStatus (eReturnStatusFailed); - return false; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = GetSelectedOrDummyTarget(); + if (target == nullptr) { + result.AppendError("Invalid target. No existing target or breakpoints."); + result.SetStatus(eReturnStatusFailed); + return false; + } - // The following are the various types of breakpoints that could be cleared: - // 1). -f -l (clearing breakpoint by source location) + // The following are the various types of breakpoints that could be cleared: + // 1). -f -l (clearing breakpoint by source location) - BreakpointClearType break_type = eClearTypeInvalid; + BreakpointClearType break_type = eClearTypeInvalid; - if (m_options.m_line_num != 0) - break_type = eClearTypeFileAndLine; + if (m_options.m_line_num != 0) + break_type = eClearTypeFileAndLine; - std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + std::unique_lock<std::recursive_mutex> lock; + target->GetBreakpointList().GetListMutex(lock); - BreakpointList &breakpoints = target->GetBreakpointList(); - size_t num_breakpoints = breakpoints.GetSize(); + BreakpointList &breakpoints = target->GetBreakpointList(); + size_t num_breakpoints = breakpoints.GetSize(); - // Early return if there's no breakpoint at all. - if (num_breakpoints == 0) - { - result.AppendError ("Breakpoint clear: No breakpoint cleared."); - result.SetStatus (eReturnStatusFailed); - return result.Succeeded(); - } + // Early return if there's no breakpoint at all. + if (num_breakpoints == 0) { + result.AppendError("Breakpoint clear: No breakpoint cleared."); + result.SetStatus(eReturnStatusFailed); + return result.Succeeded(); + } - // Find matching breakpoints and delete them. - - // First create a copy of all the IDs. - std::vector<break_id_t> BreakIDs; - for (size_t i = 0; i < num_breakpoints; ++i) - BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID()); - - int num_cleared = 0; - StreamString ss; - switch (break_type) - { - case eClearTypeFileAndLine: // Breakpoint by source position - { - const ConstString filename(m_options.m_filename.c_str()); - BreakpointLocationCollection loc_coll; - - for (size_t i = 0; i < num_breakpoints; ++i) - { - Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get(); - - if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) - { - // If the collection size is 0, it's a full match and we can just remove the breakpoint. - if (loc_coll.GetSize() == 0) - { - bp->GetDescription(&ss, lldb::eDescriptionLevelBrief); - ss.EOL(); - target->RemoveBreakpointByID (bp->GetID()); - ++num_cleared; - } - } - } - } - break; - - default: - break; - } + // Find matching breakpoints and delete them. - if (num_cleared > 0) - { - Stream &output_stream = result.GetOutputStream(); - output_stream.Printf ("%d breakpoints cleared:\n", num_cleared); - output_stream << ss.GetData(); - output_stream.EOL(); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendError ("Breakpoint clear: No breakpoint cleared."); - result.SetStatus (eReturnStatusFailed); - } + // First create a copy of all the IDs. + std::vector<break_id_t> BreakIDs; + for (size_t i = 0; i < num_breakpoints; ++i) + BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID()); + + int num_cleared = 0; + StreamString ss; + switch (break_type) { + case eClearTypeFileAndLine: // Breakpoint by source position + { + const ConstString filename(m_options.m_filename.c_str()); + BreakpointLocationCollection loc_coll; + + for (size_t i = 0; i < num_breakpoints; ++i) { + Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get(); + + if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) { + // If the collection size is 0, it's a full match and we can just + // remove the breakpoint. + if (loc_coll.GetSize() == 0) { + bp->GetDescription(&ss, lldb::eDescriptionLevelBrief); + ss.EOL(); + target->RemoveBreakpointByID(bp->GetID()); + ++num_cleared; + } + } + } + } break; + + default: + break; + } - return result.Succeeded(); + if (num_cleared > 0) { + Stream &output_stream = result.GetOutputStream(); + output_stream.Printf("%d breakpoints cleared:\n", num_cleared); + output_stream << ss.GetData(); + output_stream.EOL(); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.AppendError("Breakpoint clear: No breakpoint cleared."); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } + private: - CommandOptions m_options; + CommandOptions m_options; }; #pragma mark Clear::CommandOptions OptionDefinition -CommandObjectBreakpointClear::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectBreakpointClear::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file."}, {LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- @@ -1765,184 +1599,158 @@ CommandObjectBreakpointClear::CommandOptions::g_option_table[] = //------------------------------------------------------------------------- #pragma mark Delete -class CommandObjectBreakpointDelete : public CommandObjectParsed -{ +class CommandObjectBreakpointDelete : public CommandObjectParsed { public: - CommandObjectBreakpointDelete (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "breakpoint delete", - "Delete the specified breakpoint(s). If no breakpoints are specified, delete them all.", + CommandObjectBreakpointDelete(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "breakpoint delete", + "Delete the specified breakpoint(s). If no " + "breakpoints are specified, delete them all.", 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() { + 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); + } + + ~CommandObjectBreakpointDelete() override = default; + + Options *GetOptions() override { return &m_options; } + + class CommandOptions : public Options { + public: + CommandOptions() : Options(), m_use_dummy(false), m_force(false) {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'f': + m_force = true; + break; + + case 'D': + m_use_dummy = true; + break; + + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; } - ~CommandObjectBreakpointDelete() override = default; - - Options * - GetOptions () override - { - return &m_options; + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_use_dummy = false; + m_force = false; } - class CommandOptions : public Options - { - public: - CommandOptions () : - Options (), - m_use_dummy (false), - m_force (false) - { - } - - ~CommandOptions() override = default; + const OptionDefinition *GetDefinitions() override { return g_option_table; } - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; + // Options table: Required for subclasses of Options. - switch (short_option) - { - case 'f': - m_force = true; - break; + static OptionDefinition g_option_table[]; - case 'D': - m_use_dummy = true; - break; - - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting (ExecutionContext *execution_context) override - { - m_use_dummy = false; - m_force = false; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - bool m_use_dummy; - bool m_force; - }; + // Instance variables to hold the values for command options. + bool m_use_dummy; + bool m_force; + }; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); - if (target == nullptr) - { - result.AppendError ("Invalid target. No existing target or breakpoints."); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (target == nullptr) { + result.AppendError("Invalid target. No existing target or breakpoints."); + result.SetStatus(eReturnStatusFailed); + return false; + } - std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + std::unique_lock<std::recursive_mutex> lock; + target->GetBreakpointList().GetListMutex(lock); - const BreakpointList &breakpoints = target->GetBreakpointList(); + const BreakpointList &breakpoints = target->GetBreakpointList(); - size_t num_breakpoints = breakpoints.GetSize(); + size_t num_breakpoints = breakpoints.GetSize(); - if (num_breakpoints == 0) - { - result.AppendError ("No breakpoints exist to be deleted."); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (num_breakpoints == 0) { + result.AppendError("No breakpoints exist to be deleted."); + result.SetStatus(eReturnStatusFailed); + return false; + } - if (command.GetArgumentCount() == 0) - { - if (!m_options.m_force && !m_interpreter.Confirm ("About to delete all breakpoints, do you want to do that?", true)) - { - result.AppendMessage("Operation cancelled..."); + if (command.GetArgumentCount() == 0) { + if (!m_options.m_force && + !m_interpreter.Confirm( + "About to delete all breakpoints, do you want to do that?", + true)) { + result.AppendMessage("Operation cancelled..."); + } else { + target->RemoveAllBreakpoints(); + result.AppendMessageWithFormat( + "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", + (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); + } + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + // Particular breakpoint selected; disable that breakpoint. + BreakpointIDList valid_bp_ids; + CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( + command, target, result, &valid_bp_ids); + + if (result.Succeeded()) { + int delete_count = 0; + int disable_count = 0; + const size_t count = valid_bp_ids.GetSize(); + for (size_t i = 0; i < count; ++i) { + BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); + + if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { + if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { + Breakpoint *breakpoint = + target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + BreakpointLocation *location = + breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); + // It makes no sense to try to delete individual locations, so we + // disable them instead. + if (location) { + location->SetEnabled(false); + ++disable_count; + } + } else { + target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID()); + ++delete_count; } - else - { - target->RemoveAllBreakpoints (); - result.AppendMessageWithFormat ("All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); - } - result.SetStatus (eReturnStatusSuccessFinishNoResult); + } } - else - { - // Particular breakpoint selected; disable that breakpoint. - BreakpointIDList valid_bp_ids; - CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); - - if (result.Succeeded()) - { - int delete_count = 0; - int disable_count = 0; - const size_t count = valid_bp_ids.GetSize(); - for (size_t i = 0; i < count; ++i) - { - BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); - - if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) - { - if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) - { - Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); - BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get(); - // It makes no sense to try to delete individual locations, so we disable them instead. - if (location) - { - location->SetEnabled (false); - ++disable_count; - } - } - else - { - target->RemoveBreakpointByID (cur_bp_id.GetBreakpointID()); - ++delete_count; - } - } - } - result.AppendMessageWithFormat ("%d breakpoints deleted; %d breakpoint locations disabled.\n", - delete_count, disable_count); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - } - return result.Succeeded(); + result.AppendMessageWithFormat( + "%d breakpoints deleted; %d breakpoint locations disabled.\n", + delete_count, disable_count); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } } + return result.Succeeded(); + } private: - CommandOptions m_options; + CommandOptions m_options; }; OptionDefinition -CommandObjectBreakpointDelete::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectBreakpointDelete::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation."}, {LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- @@ -1950,374 +1758,327 @@ CommandObjectBreakpointDelete::CommandOptions::g_option_table[] = //------------------------------------------------------------------------- static OptionDefinition g_breakpoint_name_options[] = { - // clang-format off + // clang-format off {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."}, {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."}, {LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, - // clang-format on + // clang-format on }; -class BreakpointNameOptionGroup : public OptionGroup -{ +class BreakpointNameOptionGroup : public OptionGroup { public: - BreakpointNameOptionGroup() : - OptionGroup(), - m_breakpoint(LLDB_INVALID_BREAK_ID), - m_use_dummy (false) - { + BreakpointNameOptionGroup() + : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) { + } + + ~BreakpointNameOptionGroup() override = default; + + uint32_t GetNumDefinitions() override { + return sizeof(g_breakpoint_name_options) / sizeof(OptionDefinition); + } + + const OptionDefinition *GetDefinitions() override { + return g_breakpoint_name_options; + } + + Error SetOptionValue(uint32_t option_idx, const char *option_value, + ExecutionContext *execution_context) override { + Error error; + const int short_option = g_breakpoint_name_options[option_idx].short_option; + + switch (short_option) { + case 'N': + if (BreakpointID::StringIsBreakpointName(option_value, error) && + error.Success()) + m_name.SetValueFromString(option_value); + break; + + case 'B': + if (m_breakpoint.SetValueFromString(option_value).Fail()) + error.SetErrorStringWithFormat( + "unrecognized value \"%s\" for breakpoint", option_value); + break; + case 'D': + if (m_use_dummy.SetValueFromString(option_value).Fail()) + error.SetErrorStringWithFormat( + "unrecognized value \"%s\" for use-dummy", option_value); + break; + + default: + error.SetErrorStringWithFormat("unrecognized short option '%c'", + short_option); + break; } - - ~BreakpointNameOptionGroup() override = default; - - uint32_t - GetNumDefinitions () override - { - return sizeof (g_breakpoint_name_options) / sizeof (OptionDefinition); - } - - const OptionDefinition* - GetDefinitions () override - { - return g_breakpoint_name_options; - } - - Error - SetOptionValue (uint32_t option_idx, - const char *option_value, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = g_breakpoint_name_options[option_idx].short_option; - - switch (short_option) - { - case 'N': - if (BreakpointID::StringIsBreakpointName(option_value, error) && error.Success()) - m_name.SetValueFromString(option_value); - break; - - case 'B': - if (m_breakpoint.SetValueFromString(option_value).Fail()) - error.SetErrorStringWithFormat ("unrecognized value \"%s\" for breakpoint", option_value); - break; - case 'D': - if (m_use_dummy.SetValueFromString(option_value).Fail()) - error.SetErrorStringWithFormat ("unrecognized value \"%s\" for use-dummy", option_value); - break; - - default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); - break; - } - return error; - } - - void - OptionParsingStarting (ExecutionContext *execution_context) override - { - m_name.Clear(); - m_breakpoint.Clear(); - m_use_dummy.Clear(); - m_use_dummy.SetDefaultValue(false); - } - - OptionValueString m_name; - OptionValueUInt64 m_breakpoint; - OptionValueBoolean m_use_dummy; + return error; + } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_name.Clear(); + m_breakpoint.Clear(); + m_use_dummy.Clear(); + m_use_dummy.SetDefaultValue(false); + } + + OptionValueString m_name; + OptionValueUInt64 m_breakpoint; + OptionValueBoolean m_use_dummy; }; -class CommandObjectBreakpointNameAdd : public CommandObjectParsed -{ +class CommandObjectBreakpointNameAdd : public CommandObjectParsed { public: - CommandObjectBreakpointNameAdd (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "add", - "Add a name to the breakpoints provided.", - "breakpoint name add <command-options> <breakpoint-id-list>"), - m_name_options(), - m_option_group() - { - // Create the first variant for the first (and only) argument for this command. - CommandArgumentEntry arg1; - CommandArgumentData id_arg; - id_arg.arg_type = eArgTypeBreakpointID; - id_arg.arg_repetition = eArgRepeatOptional; - arg1.push_back(id_arg); - m_arguments.push_back (arg1); - - m_option_group.Append (&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); - m_option_group.Finalize(); - } - - ~CommandObjectBreakpointNameAdd() override = default; - - Options * - GetOptions() override - { - return &m_option_group; - } + CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "add", "Add a name to the breakpoints provided.", + "breakpoint name add <command-options> <breakpoint-id-list>"), + m_name_options(), m_option_group() { + // Create the first variant for the first (and only) argument for this + // command. + CommandArgumentEntry arg1; + CommandArgumentData id_arg; + id_arg.arg_type = eArgTypeBreakpointID; + id_arg.arg_repetition = eArgRepeatOptional; + arg1.push_back(id_arg); + m_arguments.push_back(arg1); + + m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); + m_option_group.Finalize(); + } + + ~CommandObjectBreakpointNameAdd() override = default; + + Options *GetOptions() override { return &m_option_group; } protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - if (!m_name_options.m_name.OptionWasSet()) - { - result.SetError("No name option provided."); - return false; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + if (!m_name_options.m_name.OptionWasSet()) { + result.SetError("No name option provided."); + return false; + } - Target *target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); + Target *target = + GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); - if (target == nullptr) - { - result.AppendError ("Invalid target. No existing target or breakpoints."); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (target == nullptr) { + result.AppendError("Invalid target. No existing target or breakpoints."); + result.SetStatus(eReturnStatusFailed); + return false; + } - std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + std::unique_lock<std::recursive_mutex> lock; + target->GetBreakpointList().GetListMutex(lock); - const BreakpointList &breakpoints = target->GetBreakpointList(); + const BreakpointList &breakpoints = target->GetBreakpointList(); - size_t num_breakpoints = breakpoints.GetSize(); - if (num_breakpoints == 0) - { - result.SetError("No breakpoints, cannot add names."); - result.SetStatus (eReturnStatusFailed); - return false; - } - - // Particular breakpoint selected; disable that breakpoint. - BreakpointIDList valid_bp_ids; - CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); - - if (result.Succeeded()) - { - if (valid_bp_ids.GetSize() == 0) - { - result.SetError("No breakpoints specified, cannot add names."); - result.SetStatus (eReturnStatusFailed); - return false; - } - size_t num_valid_ids = valid_bp_ids.GetSize(); - for (size_t index = 0; index < num_valid_ids; index++) - { - lldb::break_id_t bp_id = valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); - BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); - Error error; // We don't need to check the error here, since the option parser checked it... - bp_sp->AddName(m_name_options.m_name.GetCurrentValue(), error); - } - } + size_t num_breakpoints = breakpoints.GetSize(); + if (num_breakpoints == 0) { + result.SetError("No breakpoints, cannot add names."); + result.SetStatus(eReturnStatusFailed); + return false; + } - return true; + // Particular breakpoint selected; disable that breakpoint. + BreakpointIDList valid_bp_ids; + CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( + command, target, result, &valid_bp_ids); + + if (result.Succeeded()) { + if (valid_bp_ids.GetSize() == 0) { + result.SetError("No breakpoints specified, cannot add names."); + result.SetStatus(eReturnStatusFailed); + return false; + } + size_t num_valid_ids = valid_bp_ids.GetSize(); + for (size_t index = 0; index < num_valid_ids; index++) { + lldb::break_id_t bp_id = + valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); + BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); + Error error; // We don't need to check the error here, since the option + // parser checked it... + bp_sp->AddName(m_name_options.m_name.GetCurrentValue(), error); + } } + return true; + } + private: - BreakpointNameOptionGroup m_name_options; - OptionGroupOptions m_option_group; + BreakpointNameOptionGroup m_name_options; + OptionGroupOptions m_option_group; }; -class CommandObjectBreakpointNameDelete : public CommandObjectParsed -{ +class CommandObjectBreakpointNameDelete : public CommandObjectParsed { public: - CommandObjectBreakpointNameDelete (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "delete", - "Delete a name from the breakpoints provided.", - "breakpoint name delete <command-options> <breakpoint-id-list>"), - m_name_options(), - m_option_group() - { - // Create the first variant for the first (and only) argument for this command. - CommandArgumentEntry arg1; - CommandArgumentData id_arg; - id_arg.arg_type = eArgTypeBreakpointID; - id_arg.arg_repetition = eArgRepeatOptional; - arg1.push_back(id_arg); - m_arguments.push_back (arg1); - - m_option_group.Append (&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); - m_option_group.Finalize(); - } - - ~CommandObjectBreakpointNameDelete() override = default; - - Options * - GetOptions() override - { - return &m_option_group; - } + CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "delete", + "Delete a name from the breakpoints provided.", + "breakpoint name delete <command-options> <breakpoint-id-list>"), + m_name_options(), m_option_group() { + // Create the first variant for the first (and only) argument for this + // command. + CommandArgumentEntry arg1; + CommandArgumentData id_arg; + id_arg.arg_type = eArgTypeBreakpointID; + id_arg.arg_repetition = eArgRepeatOptional; + arg1.push_back(id_arg); + m_arguments.push_back(arg1); + + m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); + m_option_group.Finalize(); + } + + ~CommandObjectBreakpointNameDelete() override = default; + + Options *GetOptions() override { return &m_option_group; } protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - if (!m_name_options.m_name.OptionWasSet()) - { - result.SetError("No name option provided."); - return false; - } - - Target *target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); + bool DoExecute(Args &command, CommandReturnObject &result) override { + if (!m_name_options.m_name.OptionWasSet()) { + result.SetError("No name option provided."); + return false; + } - if (target == nullptr) - { - result.AppendError ("Invalid target. No existing target or breakpoints."); - result.SetStatus (eReturnStatusFailed); - return false; - } + Target *target = + GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); - std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + if (target == nullptr) { + result.AppendError("Invalid target. No existing target or breakpoints."); + result.SetStatus(eReturnStatusFailed); + return false; + } - const BreakpointList &breakpoints = target->GetBreakpointList(); + std::unique_lock<std::recursive_mutex> lock; + target->GetBreakpointList().GetListMutex(lock); - size_t num_breakpoints = breakpoints.GetSize(); - if (num_breakpoints == 0) - { - result.SetError("No breakpoints, cannot delete names."); - result.SetStatus (eReturnStatusFailed); - return false; - } + const BreakpointList &breakpoints = target->GetBreakpointList(); - // Particular breakpoint selected; disable that breakpoint. - BreakpointIDList valid_bp_ids; - CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); - - if (result.Succeeded()) - { - if (valid_bp_ids.GetSize() == 0) - { - result.SetError("No breakpoints specified, cannot delete names."); - result.SetStatus (eReturnStatusFailed); - return false; - } - size_t num_valid_ids = valid_bp_ids.GetSize(); - for (size_t index = 0; index < num_valid_ids; index++) - { - lldb::break_id_t bp_id = valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); - BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); - bp_sp->RemoveName(m_name_options.m_name.GetCurrentValue()); - } - } + size_t num_breakpoints = breakpoints.GetSize(); + if (num_breakpoints == 0) { + result.SetError("No breakpoints, cannot delete names."); + result.SetStatus(eReturnStatusFailed); + return false; + } - return true; + // Particular breakpoint selected; disable that breakpoint. + BreakpointIDList valid_bp_ids; + CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( + command, target, result, &valid_bp_ids); + + if (result.Succeeded()) { + if (valid_bp_ids.GetSize() == 0) { + result.SetError("No breakpoints specified, cannot delete names."); + result.SetStatus(eReturnStatusFailed); + return false; + } + size_t num_valid_ids = valid_bp_ids.GetSize(); + for (size_t index = 0; index < num_valid_ids; index++) { + lldb::break_id_t bp_id = + valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); + BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); + bp_sp->RemoveName(m_name_options.m_name.GetCurrentValue()); + } } + return true; + } + private: - BreakpointNameOptionGroup m_name_options; - OptionGroupOptions m_option_group; + BreakpointNameOptionGroup m_name_options; + OptionGroupOptions m_option_group; }; -class CommandObjectBreakpointNameList : public CommandObjectParsed -{ +class CommandObjectBreakpointNameList : public CommandObjectParsed { public: - CommandObjectBreakpointNameList (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "list", - "List either the names for a breakpoint or the breakpoints for a given name.", - "breakpoint name list <command-options>"), - m_name_options(), - m_option_group() - { - m_option_group.Append (&m_name_options); - m_option_group.Finalize(); - } + CommandObjectBreakpointNameList(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "list", + "List either the names for a breakpoint or the " + "breakpoints for a given name.", + "breakpoint name list <command-options>"), + m_name_options(), m_option_group() { + m_option_group.Append(&m_name_options); + m_option_group.Finalize(); + } - ~CommandObjectBreakpointNameList() override = default; + ~CommandObjectBreakpointNameList() override = default; - Options * - GetOptions() override - { - return &m_option_group; - } + Options *GetOptions() override { return &m_option_group; } protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); - - if (target == nullptr) - { - result.AppendError ("Invalid target. No existing target or breakpoints."); - result.SetStatus (eReturnStatusFailed); - return false; - } - - if (m_name_options.m_name.OptionWasSet()) - { - const char *name = m_name_options.m_name.GetCurrentValue(); - std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); - - BreakpointList &breakpoints = target->GetBreakpointList(); - for (BreakpointSP bp_sp : breakpoints.Breakpoints()) - { - if (bp_sp->MatchesName(name)) - { - StreamString s; - bp_sp->GetDescription(&s, eDescriptionLevelBrief); - s.EOL(); - result.AppendMessage(s.GetData()); - } - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = + GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); + + if (target == nullptr) { + result.AppendError("Invalid target. No existing target or breakpoints."); + result.SetStatus(eReturnStatusFailed); + return false; + } - } - else if (m_name_options.m_breakpoint.OptionWasSet()) - { - BreakpointSP bp_sp = target->GetBreakpointList().FindBreakpointByID(m_name_options.m_breakpoint.GetCurrentValue()); - if (bp_sp) - { - std::vector<std::string> names; - bp_sp->GetNames (names); - result.AppendMessage ("Names:"); - for (auto name : names) - result.AppendMessageWithFormat (" %s\n", name.c_str()); - } - else - { - result.AppendErrorWithFormat ("Could not find breakpoint %" PRId64 ".\n", - m_name_options.m_breakpoint.GetCurrentValue()); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - else - { - result.SetError ("Must specify -N or -B option to list."); - result.SetStatus (eReturnStatusFailed); - return false; - } - return true; + if (m_name_options.m_name.OptionWasSet()) { + const char *name = m_name_options.m_name.GetCurrentValue(); + std::unique_lock<std::recursive_mutex> lock; + target->GetBreakpointList().GetListMutex(lock); + + BreakpointList &breakpoints = target->GetBreakpointList(); + for (BreakpointSP bp_sp : breakpoints.Breakpoints()) { + if (bp_sp->MatchesName(name)) { + StreamString s; + bp_sp->GetDescription(&s, eDescriptionLevelBrief); + s.EOL(); + result.AppendMessage(s.GetData()); + } + } + + } else if (m_name_options.m_breakpoint.OptionWasSet()) { + BreakpointSP bp_sp = target->GetBreakpointList().FindBreakpointByID( + m_name_options.m_breakpoint.GetCurrentValue()); + if (bp_sp) { + std::vector<std::string> names; + bp_sp->GetNames(names); + result.AppendMessage("Names:"); + for (auto name : names) + result.AppendMessageWithFormat(" %s\n", name.c_str()); + } else { + result.AppendErrorWithFormat( + "Could not find breakpoint %" PRId64 ".\n", + m_name_options.m_breakpoint.GetCurrentValue()); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + result.SetError("Must specify -N or -B option to list."); + result.SetStatus(eReturnStatusFailed); + return false; } + return true; + } private: - BreakpointNameOptionGroup m_name_options; - OptionGroupOptions m_option_group; + BreakpointNameOptionGroup m_name_options; + OptionGroupOptions m_option_group; }; //------------------------------------------------------------------------- // CommandObjectMultiwordBreakpoint //------------------------------------------------------------------------- -class CommandObjectBreakpointName : public CommandObjectMultiword -{ +class CommandObjectBreakpointName : public CommandObjectMultiword { public: - CommandObjectBreakpointName(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "name", "Commands to manage name tags for breakpoints", - "breakpoint name <subcommand> [<command-options>]") - { - CommandObjectSP add_command_object (new CommandObjectBreakpointNameAdd (interpreter)); - CommandObjectSP delete_command_object (new CommandObjectBreakpointNameDelete (interpreter)); - CommandObjectSP list_command_object (new CommandObjectBreakpointNameList (interpreter)); - - LoadSubCommand ("add", add_command_object); - LoadSubCommand ("delete", delete_command_object); - LoadSubCommand ("list", list_command_object); - } - - ~CommandObjectBreakpointName() override = default; + CommandObjectBreakpointName(CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "name", "Commands to manage name tags for breakpoints", + "breakpoint name <subcommand> [<command-options>]") { + CommandObjectSP add_command_object( + new CommandObjectBreakpointNameAdd(interpreter)); + CommandObjectSP delete_command_object( + new CommandObjectBreakpointNameDelete(interpreter)); + CommandObjectSP list_command_object( + new CommandObjectBreakpointNameList(interpreter)); + + LoadSubCommand("add", add_command_object); + LoadSubCommand("delete", delete_command_object); + LoadSubCommand("list", list_command_object); + } + + ~CommandObjectBreakpointName() override = default; }; //------------------------------------------------------------------------- @@ -2325,120 +2086,134 @@ public: //------------------------------------------------------------------------- #pragma mark MultiwordBreakpoint -CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "breakpoint", - "Commands for operating on breakpoints (see 'help b' for shorthand.)", - "breakpoint <subcommand> [<command-options>]") -{ - CommandObjectSP list_command_object (new CommandObjectBreakpointList (interpreter)); - CommandObjectSP enable_command_object (new CommandObjectBreakpointEnable (interpreter)); - CommandObjectSP disable_command_object (new CommandObjectBreakpointDisable (interpreter)); - CommandObjectSP clear_command_object (new CommandObjectBreakpointClear (interpreter)); - CommandObjectSP delete_command_object (new CommandObjectBreakpointDelete (interpreter)); - CommandObjectSP set_command_object (new CommandObjectBreakpointSet (interpreter)); - CommandObjectSP command_command_object (new CommandObjectBreakpointCommand (interpreter)); - CommandObjectSP modify_command_object (new CommandObjectBreakpointModify(interpreter)); - CommandObjectSP name_command_object (new CommandObjectBreakpointName(interpreter)); - - list_command_object->SetCommandName ("breakpoint list"); - enable_command_object->SetCommandName("breakpoint enable"); - disable_command_object->SetCommandName("breakpoint disable"); - clear_command_object->SetCommandName("breakpoint clear"); - delete_command_object->SetCommandName("breakpoint delete"); - set_command_object->SetCommandName("breakpoint set"); - command_command_object->SetCommandName ("breakpoint command"); - modify_command_object->SetCommandName ("breakpoint modify"); - name_command_object->SetCommandName ("breakpoint name"); - - LoadSubCommand ("list", list_command_object); - LoadSubCommand ("enable", enable_command_object); - LoadSubCommand ("disable", disable_command_object); - LoadSubCommand ("clear", clear_command_object); - LoadSubCommand ("delete", delete_command_object); - LoadSubCommand ("set", set_command_object); - LoadSubCommand ("command", command_command_object); - LoadSubCommand ("modify", modify_command_object); - LoadSubCommand ("name", name_command_object); +CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint( + CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "breakpoint", + "Commands for operating on breakpoints (see 'help b' for shorthand.)", + "breakpoint <subcommand> [<command-options>]") { + CommandObjectSP list_command_object( + new CommandObjectBreakpointList(interpreter)); + CommandObjectSP enable_command_object( + new CommandObjectBreakpointEnable(interpreter)); + CommandObjectSP disable_command_object( + new CommandObjectBreakpointDisable(interpreter)); + CommandObjectSP clear_command_object( + new CommandObjectBreakpointClear(interpreter)); + CommandObjectSP delete_command_object( + new CommandObjectBreakpointDelete(interpreter)); + CommandObjectSP set_command_object( + new CommandObjectBreakpointSet(interpreter)); + CommandObjectSP command_command_object( + new CommandObjectBreakpointCommand(interpreter)); + CommandObjectSP modify_command_object( + new CommandObjectBreakpointModify(interpreter)); + CommandObjectSP name_command_object( + new CommandObjectBreakpointName(interpreter)); + + list_command_object->SetCommandName("breakpoint list"); + enable_command_object->SetCommandName("breakpoint enable"); + disable_command_object->SetCommandName("breakpoint disable"); + clear_command_object->SetCommandName("breakpoint clear"); + delete_command_object->SetCommandName("breakpoint delete"); + set_command_object->SetCommandName("breakpoint set"); + command_command_object->SetCommandName("breakpoint command"); + modify_command_object->SetCommandName("breakpoint modify"); + name_command_object->SetCommandName("breakpoint name"); + + LoadSubCommand("list", list_command_object); + LoadSubCommand("enable", enable_command_object); + LoadSubCommand("disable", disable_command_object); + LoadSubCommand("clear", clear_command_object); + LoadSubCommand("delete", delete_command_object); + LoadSubCommand("set", set_command_object); + LoadSubCommand("command", command_command_object); + LoadSubCommand("modify", modify_command_object); + LoadSubCommand("name", name_command_object); } CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default; -void -CommandObjectMultiwordBreakpoint::VerifyIDs (Args &args, - Target *target, - bool allow_locations, - CommandReturnObject &result, - BreakpointIDList *valid_ids) -{ - // args can be strings representing 1). integers (for breakpoint ids) - // 2). the full breakpoint & location canonical representation - // 3). the word "to" or a hyphen, representing a range (in which case there - // had *better* be an entry both before & after of one of the first two types. - // 4). A breakpoint name - // If args is empty, we will use the last created breakpoint (if there is one.) - - Args temp_args; - - if (args.GetArgumentCount() == 0) - { - if (target->GetLastCreatedBreakpoint()) - { - valid_ids->AddBreakpointID (BreakpointID(target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID)); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendError("No breakpoint specified and no last created breakpoint."); - result.SetStatus (eReturnStatusFailed); - } - return; +void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target, + bool allow_locations, + CommandReturnObject &result, + BreakpointIDList *valid_ids) { + // args can be strings representing 1). integers (for breakpoint ids) + // 2). the full breakpoint & location + // canonical representation + // 3). the word "to" or a hyphen, + // representing a range (in which case there + // had *better* be an entry both before & + // after of one of the first two types. + // 4). A breakpoint name + // If args is empty, we will use the last created breakpoint (if there is + // one.) + + Args temp_args; + + if (args.GetArgumentCount() == 0) { + if (target->GetLastCreatedBreakpoint()) { + valid_ids->AddBreakpointID(BreakpointID( + target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID)); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.AppendError( + "No breakpoint specified and no last created breakpoint."); + result.SetStatus(eReturnStatusFailed); } - - // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff directly from the old ARGS to - // the new TEMP_ARGS. Do not copy breakpoint id range strings over; instead generate a list of strings for - // all the breakpoint ids in the range, and shove all of those breakpoint id strings into TEMP_ARGS. - - BreakpointIDList::FindAndReplaceIDRanges (args, target, allow_locations, result, temp_args); - - // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual BreakpointIDList: - - valid_ids->InsertStringArray (temp_args.GetConstArgumentVector(), temp_args.GetArgumentCount(), result); - - // At this point, all of the breakpoint ids that the user passed in have been converted to breakpoint IDs - // and put into valid_ids. - - if (result.Succeeded()) - { - // Now that we've converted everything from args into a list of breakpoint ids, go through our tentative list - // of breakpoint id's and verify that they correspond to valid/currently set breakpoints. - - const size_t count = valid_ids->GetSize(); - for (size_t i = 0; i < count; ++i) - { - BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex (i); - Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); - if (breakpoint != nullptr) - { - const size_t num_locations = breakpoint->GetNumLocations(); - if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) - { - StreamString id_str; - BreakpointID::GetCanonicalReference (&id_str, - cur_bp_id.GetBreakpointID(), - cur_bp_id.GetLocationID()); - i = valid_ids->GetSize() + 1; - result.AppendErrorWithFormat ("'%s' is not a currently valid breakpoint/location id.\n", - id_str.GetData()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - i = valid_ids->GetSize() + 1; - result.AppendErrorWithFormat("'%d' is not a currently valid breakpoint ID.\n", - cur_bp_id.GetBreakpointID()); - result.SetStatus (eReturnStatusFailed); - } - } + return; + } + + // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff + // directly from the old ARGS to + // the new TEMP_ARGS. Do not copy breakpoint id range strings over; instead + // generate a list of strings for + // all the breakpoint ids in the range, and shove all of those breakpoint id + // strings into TEMP_ARGS. + + BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations, + result, temp_args); + + // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual + // BreakpointIDList: + + valid_ids->InsertStringArray(temp_args.GetConstArgumentVector(), + temp_args.GetArgumentCount(), result); + + // At this point, all of the breakpoint ids that the user passed in have been + // converted to breakpoint IDs + // and put into valid_ids. + + if (result.Succeeded()) { + // Now that we've converted everything from args into a list of breakpoint + // ids, go through our tentative list + // of breakpoint id's and verify that they correspond to valid/currently set + // breakpoints. + + const size_t count = valid_ids->GetSize(); + for (size_t i = 0; i < count; ++i) { + BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i); + Breakpoint *breakpoint = + target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + if (breakpoint != nullptr) { + const size_t num_locations = breakpoint->GetNumLocations(); + if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) { + StreamString id_str; + BreakpointID::GetCanonicalReference( + &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); + i = valid_ids->GetSize() + 1; + result.AppendErrorWithFormat( + "'%s' is not a currently valid breakpoint/location id.\n", + id_str.GetData()); + result.SetStatus(eReturnStatusFailed); + } + } else { + i = valid_ids->GetSize() + 1; + result.AppendErrorWithFormat( + "'%d' is not a currently valid breakpoint ID.\n", + cur_bp_id.GetBreakpointID()); + result.SetStatus(eReturnStatusFailed); + } } + } } diff --git a/lldb/source/Commands/CommandObjectBreakpoint.h b/lldb/source/Commands/CommandObjectBreakpoint.h index 123e823..6e14b8f 100644 --- a/lldb/source/Commands/CommandObjectBreakpoint.h +++ b/lldb/source/Commands/CommandObjectBreakpoint.h @@ -19,9 +19,9 @@ // Other libraries and framework includes // Project includes #include "lldb/Core/Address.h" +#include "lldb/Core/STLUtils.h" #include "lldb/Interpreter/CommandObjectMultiword.h" #include "lldb/Interpreter/Options.h" -#include "lldb/Core/STLUtils.h" namespace lldb_private { @@ -29,28 +29,28 @@ namespace lldb_private { // CommandObjectMultiwordBreakpoint //------------------------------------------------------------------------- -class CommandObjectMultiwordBreakpoint : public CommandObjectMultiword -{ +class CommandObjectMultiwordBreakpoint : public CommandObjectMultiword { public: - CommandObjectMultiwordBreakpoint (CommandInterpreter &interpreter); + CommandObjectMultiwordBreakpoint(CommandInterpreter &interpreter); - ~CommandObjectMultiwordBreakpoint() override; + ~CommandObjectMultiwordBreakpoint() override; - static void - VerifyBreakpointOrLocationIDs (Args &args, Target *target, CommandReturnObject &result, BreakpointIDList *valid_ids) - { - VerifyIDs (args, target, true, result, valid_ids); - } + static void VerifyBreakpointOrLocationIDs(Args &args, Target *target, + CommandReturnObject &result, + BreakpointIDList *valid_ids) { + VerifyIDs(args, target, true, result, valid_ids); + } - static void - VerifyBreakpointIDs (Args &args, Target *target, CommandReturnObject &result, BreakpointIDList *valid_ids) - { - VerifyIDs (args, target, false, result, valid_ids); - } + static void VerifyBreakpointIDs(Args &args, Target *target, + CommandReturnObject &result, + BreakpointIDList *valid_ids) { + VerifyIDs(args, target, false, result, valid_ids); + } private: - static void - VerifyIDs (Args &args, Target *target, bool allow_locations, CommandReturnObject &result, BreakpointIDList *valid_ids); + static void VerifyIDs(Args &args, Target *target, bool allow_locations, + CommandReturnObject &result, + BreakpointIDList *valid_ids); }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp index ce6d0ef..557cb5f 100644 --- a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp +++ b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp @@ -13,16 +13,16 @@ // Project includes #include "CommandObjectBreakpointCommand.h" #include "CommandObjectBreakpoint.h" +#include "lldb/Breakpoint/Breakpoint.h" +#include "lldb/Breakpoint/BreakpointIDList.h" +#include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/IOHandler.h" +#include "lldb/Core/State.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" -#include "lldb/Breakpoint/BreakpointIDList.h" -#include "lldb/Breakpoint/Breakpoint.h" -#include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Breakpoint/StoppointCallbackContext.h" -#include "lldb/Core/State.h" using namespace lldb; using namespace lldb_private; @@ -31,44 +31,52 @@ using namespace lldb_private; // CommandObjectBreakpointCommandAdd //------------------------------------------------------------------------- -class CommandObjectBreakpointCommandAdd : - public CommandObjectParsed, - public IOHandlerDelegateMultiline -{ +class CommandObjectBreakpointCommandAdd : public CommandObjectParsed, + public IOHandlerDelegateMultiline { public: - CommandObjectBreakpointCommandAdd(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "add", - "Add LLDB commands to a breakpoint, to be executed whenever the breakpoint is hit." - " If no breakpoint is specified, adds the commands to the last created breakpoint.", - nullptr), - IOHandlerDelegateMultiline("DONE", IOHandlerDelegate::Completion::LLDBCommand), - m_options() - { - SetHelpLong ( -R"( + CommandObjectBreakpointCommandAdd(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "add", + "Add LLDB commands to a breakpoint, to be executed " + "whenever the breakpoint is hit." + " If no breakpoint is specified, adds the " + "commands to the last created breakpoint.", + nullptr), + IOHandlerDelegateMultiline("DONE", + IOHandlerDelegate::Completion::LLDBCommand), + m_options() { + SetHelpLong( + R"( General information about entering breakpoint commands ------------------------------------------------------ -)" "This command will prompt for commands to be executed when the specified \ +)" + "This command will prompt for commands to be executed when the specified \ breakpoint is hit. Each command is typed on its own line following the '> ' \ -prompt until 'DONE' is entered." R"( +prompt until 'DONE' is entered." + R"( -)" "Syntactic errors may not be detected when initially entered, and many \ +)" + "Syntactic errors may not be detected when initially entered, and many \ malformed commands can silently fail when executed. If your breakpoint commands \ -do not appear to be executing, double-check the command syntax." R"( +do not appear to be executing, double-check the command syntax." + R"( -)" "Note: You may enter any debugger command exactly as you would at the debugger \ +)" + "Note: You may enter any debugger command exactly as you would at the debugger \ prompt. There is no limit to the number of commands supplied, but do NOT enter \ -more than one command per line." R"( +more than one command per line." + R"( Special information about PYTHON breakpoint commands ---------------------------------------------------- -)" "You may enter either one or more lines of Python, including function \ +)" + "You may enter either one or more lines of Python, including function \ definitions or calls to functions that will have been imported by the time \ the code executes. Single line breakpoint commands will be interpreted 'as is' \ when the breakpoint is hit. Multiple lines of Python will be wrapped in a \ -generated function, and a call to the function will be attached to the breakpoint." R"( +generated function, and a call to the function will be attached to the breakpoint." + R"( This auto-generated function is passed in three arguments: @@ -78,8 +86,10 @@ This auto-generated function is passed in three arguments: dict: the python session dictionary hit. -)" "When specifying a python function with the --python-function option, you need \ -to supply the function name prepended by the module name:" R"( +)" + "When specifying a python function with the --python-function option, you need \ +to supply the function name prepended by the module name:" + R"( --python-function myutils.breakpoint_callback @@ -88,16 +98,20 @@ The function itself must have the following prototype: def breakpoint_callback(frame, bp_loc, dict): # Your code goes here -)" "The arguments are the same as the arguments passed to generated functions as \ +)" + "The arguments are the same as the arguments passed to generated functions as \ described above. Note that the global variable 'lldb.frame' will NOT be updated when \ this function is called, so be sure to use the 'frame' argument. The 'frame' argument \ can get you to the thread via frame.GetThread(), the thread can get you to the \ process via thread.GetProcess(), and the process can get you back to the target \ -via process.GetTarget()." R"( +via process.GetTarget()." + R"( -)" "Important Note: As Python code gets collected into functions, access to global \ +)" + "Important Note: As Python code gets collected into functions, access to global \ variables requires explicit scoping using the 'global' keyword. Be sure to use correct \ -Python syntax, including indentation, when entering Python breakpoint commands." R"( +Python syntax, including indentation, when entering Python breakpoint commands." + R"( Example Python one-line breakpoint command: @@ -142,729 +156,658 @@ Enter your Python command(s). Type 'DONE' to end. > breakpoint_output (1) > DONE -)" "In this case, since there is a reference to a global variable, \ +)" + "In this case, since there is a reference to a global variable, \ 'bp_count', you will also need to make sure 'bp_count' exists and is \ -initialized:" R"( +initialized:" + R"( (lldb) script >>> bp_count = 0 >>> quit() -)" "Your Python code, however organized, can optionally return a value. \ +)" + "Your Python code, however organized, can optionally return a value. \ If the returned value is False, that tells LLDB not to stop at the breakpoint \ to which the code is associated. Returning anything other than False, or even \ returning None, or even omitting a return statement entirely, will cause \ -LLDB to stop." R"( +LLDB to stop." + R"( -)" "Final Note: A warning that no breakpoint command was generated when there \ -are no syntax errors may indicate that a function was declared but never called." - ); +)" + "Final Note: A warning that no breakpoint command was generated when there \ +are no syntax errors may indicate that a function was declared but never called."); - CommandArgumentEntry arg; - CommandArgumentData bp_id_arg; + CommandArgumentEntry arg; + CommandArgumentData bp_id_arg; - // Define the first (and only) variant of this arg. - bp_id_arg.arg_type = eArgTypeBreakpointID; - bp_id_arg.arg_repetition = eArgRepeatOptional; + // Define the first (and only) variant of this arg. + bp_id_arg.arg_type = eArgTypeBreakpointID; + bp_id_arg.arg_repetition = eArgRepeatOptional; - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (bp_id_arg); + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(bp_id_arg); - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - } + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } - ~CommandObjectBreakpointCommandAdd() override = default; + ~CommandObjectBreakpointCommandAdd() override = default; - Options * - GetOptions () override - { - return &m_options; - } + Options *GetOptions() override { return &m_options; } - void - IOHandlerActivated (IOHandler &io_handler) override - { - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); - if (output_sp) - { - output_sp->PutCString(g_reader_instructions); - output_sp->Flush(); - } + void IOHandlerActivated(IOHandler &io_handler) override { + StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + if (output_sp) { + output_sp->PutCString(g_reader_instructions); + output_sp->Flush(); } - - void - IOHandlerInputComplete (IOHandler &io_handler, std::string &line) override - { - io_handler.SetIsDone(true); - - std::vector<BreakpointOptions *> *bp_options_vec = (std::vector<BreakpointOptions *> *)io_handler.GetUserData(); - for (BreakpointOptions *bp_options : *bp_options_vec) - { - if (!bp_options) - continue; - - std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData()); - if (data_ap) - { - data_ap->user_source.SplitIntoLines (line.c_str(), line.size()); - BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); - bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp); - } - } + } + + void IOHandlerInputComplete(IOHandler &io_handler, + std::string &line) override { + io_handler.SetIsDone(true); + + std::vector<BreakpointOptions *> *bp_options_vec = + (std::vector<BreakpointOptions *> *)io_handler.GetUserData(); + for (BreakpointOptions *bp_options : *bp_options_vec) { + if (!bp_options) + continue; + + std::unique_ptr<BreakpointOptions::CommandData> data_ap( + new BreakpointOptions::CommandData()); + if (data_ap) { + data_ap->user_source.SplitIntoLines(line.c_str(), line.size()); + BatonSP baton_sp( + new BreakpointOptions::CommandBaton(data_ap.release())); + bp_options->SetCallback(BreakpointOptionsCallbackFunction, baton_sp); + } } - - void - CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec, - CommandReturnObject &result) - { - m_interpreter.GetLLDBCommandsFromIOHandler ("> ", // Prompt - *this, // IOHandlerDelegate - true, // Run IOHandler in async mode - &bp_options_vec); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions + } + + void CollectDataForBreakpointCommandCallback( + std::vector<BreakpointOptions *> &bp_options_vec, + CommandReturnObject &result) { + m_interpreter.GetLLDBCommandsFromIOHandler( + "> ", // Prompt + *this, // IOHandlerDelegate + true, // Run IOHandler in async mode + &bp_options_vec); // Baton for the "io_handler" that will be passed back + // into our IOHandlerDelegate functions + } + + /// Set a one-liner as the callback for the breakpoint. + void + SetBreakpointCommandCallback(std::vector<BreakpointOptions *> &bp_options_vec, + const char *oneliner) { + for (auto bp_options : bp_options_vec) { + std::unique_ptr<BreakpointOptions::CommandData> data_ap( + new BreakpointOptions::CommandData()); + + // It's necessary to set both user_source and script_source to the + // oneliner. + // The former is used to generate callback description (as in breakpoint + // command list) + // while the latter is used for Python to interpret during the actual + // callback. + data_ap->user_source.AppendString(oneliner); + data_ap->script_source.assign(oneliner); + data_ap->stop_on_error = m_options.m_stop_on_error; + + BatonSP baton_sp(new BreakpointOptions::CommandBaton(data_ap.release())); + bp_options->SetCallback(BreakpointOptionsCallbackFunction, baton_sp); } - - /// Set a one-liner as the callback for the breakpoint. - void - SetBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec, - const char *oneliner) - { - for (auto bp_options : bp_options_vec) - { - std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData()); - - // It's necessary to set both user_source and script_source to the oneliner. - // The former is used to generate callback description (as in breakpoint command list) - // while the latter is used for Python to interpret during the actual callback. - data_ap->user_source.AppendString (oneliner); - data_ap->script_source.assign (oneliner); - data_ap->stop_on_error = m_options.m_stop_on_error; - - BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); - bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp); - } + } + + static bool BreakpointOptionsCallbackFunction( + void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, + lldb::user_id_t break_loc_id) { + bool ret_value = true; + if (baton == nullptr) + return true; + + BreakpointOptions::CommandData *data = + (BreakpointOptions::CommandData *)baton; + StringList &commands = data->user_source; + + if (commands.GetSize() > 0) { + ExecutionContext exe_ctx(context->exe_ctx_ref); + Target *target = exe_ctx.GetTargetPtr(); + if (target) { + CommandReturnObject result; + Debugger &debugger = target->GetDebugger(); + // 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); + result.SetImmediateErrorStream(error_stream); + + CommandInterpreterRunOptions options; + options.SetStopOnContinue(true); + options.SetStopOnError(data->stop_on_error); + options.SetEchoCommands(true); + options.SetPrintResults(true); + options.SetAddToHistory(false); + + debugger.GetCommandInterpreter().HandleCommands(commands, &exe_ctx, + options, result); + result.GetImmediateOutputStream()->Flush(); + result.GetImmediateErrorStream()->Flush(); + } } - - static bool - BreakpointOptionsCallbackFunction (void *baton, - StoppointCallbackContext *context, - lldb::user_id_t break_id, - lldb::user_id_t break_loc_id) - { - bool ret_value = true; - if (baton == nullptr) - return true; - - BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton; - StringList &commands = data->user_source; - - if (commands.GetSize() > 0) - { - ExecutionContext exe_ctx (context->exe_ctx_ref); - Target *target = exe_ctx.GetTargetPtr(); - if (target) - { - CommandReturnObject result; - Debugger &debugger = target->GetDebugger(); - // 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); - result.SetImmediateErrorStream (error_stream); - - CommandInterpreterRunOptions options; - options.SetStopOnContinue(true); - options.SetStopOnError (data->stop_on_error); - options.SetEchoCommands (true); - options.SetPrintResults (true); - options.SetAddToHistory (false); - - debugger.GetCommandInterpreter().HandleCommands (commands, - &exe_ctx, - options, - result); - result.GetImmediateOutputStream()->Flush(); - result.GetImmediateErrorStream()->Flush(); - } - } - return ret_value; - } - - class CommandOptions : public Options - { - public: - CommandOptions () : - Options (), - m_use_commands (false), - m_use_script_language (false), - m_script_language (eScriptLanguageNone), - m_use_one_liner (false), - m_one_liner(), - m_function_name() - { + return ret_value; + } + + class CommandOptions : public Options { + public: + CommandOptions() + : Options(), m_use_commands(false), m_use_script_language(false), + m_script_language(eScriptLanguageNone), m_use_one_liner(false), + m_one_liner(), m_function_name() {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'o': + m_use_one_liner = true; + m_one_liner = option_arg; + break; + + case 's': + m_script_language = (lldb::ScriptLanguage)Args::StringToOptionEnum( + option_arg, g_option_table[option_idx].enum_values, + eScriptLanguageNone, error); + + if (m_script_language == eScriptLanguagePython || + m_script_language == eScriptLanguageDefault) { + m_use_script_language = true; + } else { + m_use_script_language = false; } + break; + + case 'e': { + bool success = false; + m_stop_on_error = Args::StringToBoolean(option_arg, false, &success); + if (!success) + error.SetErrorStringWithFormat( + "invalid value for stop-on-error: \"%s\"", option_arg); + } break; + + case 'F': + m_use_one_liner = false; + m_use_script_language = true; + m_function_name.assign(option_arg); + break; + + case 'D': + m_use_dummy = true; + break; + + default: + break; + } + return error; + } - ~CommandOptions() override = default; - - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'o': - m_use_one_liner = true; - m_one_liner = option_arg; - break; - - case 's': - m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg, - g_option_table[option_idx].enum_values, - eScriptLanguageNone, - error); - - if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault) - { - m_use_script_language = true; - } - else - { - m_use_script_language = false; - } - break; - - case 'e': - { - bool success = false; - m_stop_on_error = Args::StringToBoolean(option_arg, false, &success); - if (!success) - error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg); - } - break; - - case 'F': - m_use_one_liner = false; - m_use_script_language = true; - m_function_name.assign(option_arg); - break; - - case 'D': - m_use_dummy = true; - break; - - default: - break; - } - return error; - } + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_use_commands = true; + m_use_script_language = false; + m_script_language = eScriptLanguageNone; - void - OptionParsingStarting (ExecutionContext *execution_context) override - { - m_use_commands = true; - m_use_script_language = false; - m_script_language = eScriptLanguageNone; - - m_use_one_liner = false; - m_stop_on_error = true; - m_one_liner.clear(); - m_function_name.clear(); - m_use_dummy = false; - } + m_use_one_liner = false; + m_stop_on_error = true; + m_one_liner.clear(); + m_function_name.clear(); + m_use_dummy = false; + } - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } - // Options table: Required for subclasses of Options. + // Options table: Required for subclasses of Options. - static OptionDefinition g_option_table[]; + static OptionDefinition g_option_table[]; - // Instance variables to hold the values for command options. + // Instance variables to hold the values for command options. - bool m_use_commands; - bool m_use_script_language; - lldb::ScriptLanguage m_script_language; + bool m_use_commands; + bool m_use_script_language; + lldb::ScriptLanguage m_script_language; - // Instance variables to hold the values for one_liner options. - bool m_use_one_liner; - std::string m_one_liner; - bool m_stop_on_error; - std::string m_function_name; - bool m_use_dummy; - }; + // Instance variables to hold the values for one_liner options. + bool m_use_one_liner; + std::string m_one_liner; + bool m_stop_on_error; + std::string m_function_name; + bool m_use_dummy; + }; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); - - if (target == nullptr) - { - result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands"); - result.SetStatus (eReturnStatusFailed); - return false; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); + + if (target == nullptr) { + result.AppendError("There is not a current executable; there are no " + "breakpoints to which to add commands"); + result.SetStatus(eReturnStatusFailed); + return false; + } - const BreakpointList &breakpoints = target->GetBreakpointList(); - size_t num_breakpoints = breakpoints.GetSize(); + const BreakpointList &breakpoints = target->GetBreakpointList(); + size_t num_breakpoints = breakpoints.GetSize(); - if (num_breakpoints == 0) - { - result.AppendError ("No breakpoints exist to have commands added"); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (num_breakpoints == 0) { + result.AppendError("No breakpoints exist to have commands added"); + result.SetStatus(eReturnStatusFailed); + return false; + } - if (!m_options.m_use_script_language && !m_options.m_function_name.empty()) - { - result.AppendError ("need to enable scripting to have a function run as a breakpoint command"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - BreakpointIDList valid_bp_ids; - CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); - - m_bp_options_vec.clear(); - - if (result.Succeeded()) - { - const size_t count = valid_bp_ids.GetSize(); - - for (size_t i = 0; i < count; ++i) - { - BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); - if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) - { - Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); - BreakpointOptions *bp_options = nullptr; - if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID) - { - // This breakpoint does not have an associated location. - bp_options = bp->GetOptions(); - } - else - { - BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID())); - // This breakpoint does have an associated location. - // Get its breakpoint options. - if (bp_loc_sp) - bp_options = bp_loc_sp->GetLocationOptions(); - } - if (bp_options) - m_bp_options_vec.push_back (bp_options); - } - } + if (!m_options.m_use_script_language && + !m_options.m_function_name.empty()) { + result.AppendError("need to enable scripting to have a function run as a " + "breakpoint command"); + result.SetStatus(eReturnStatusFailed); + return false; + } - // If we are using script language, get the script interpreter - // in order to set or collect command callback. Otherwise, call - // the methods associated with this object. - if (m_options.m_use_script_language) - { - ScriptInterpreter *script_interp = m_interpreter.GetScriptInterpreter(); - // Special handling for one-liner specified inline. - if (m_options.m_use_one_liner) - { - script_interp->SetBreakpointCommandCallback (m_bp_options_vec, - m_options.m_one_liner.c_str()); - } - else if (!m_options.m_function_name.empty()) - { - script_interp->SetBreakpointCommandCallbackFunction (m_bp_options_vec, - m_options.m_function_name.c_str()); - } - else - { - script_interp->CollectDataForBreakpointCommandCallback (m_bp_options_vec, - result); - } - } - else - { - // Special handling for one-liner specified inline. - if (m_options.m_use_one_liner) - SetBreakpointCommandCallback (m_bp_options_vec, - m_options.m_one_liner.c_str()); - else - CollectDataForBreakpointCommandCallback (m_bp_options_vec, - result); - } + BreakpointIDList valid_bp_ids; + CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( + command, target, result, &valid_bp_ids); + + m_bp_options_vec.clear(); + + if (result.Succeeded()) { + const size_t count = valid_bp_ids.GetSize(); + + for (size_t i = 0; i < count; ++i) { + BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); + if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { + Breakpoint *bp = + target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + BreakpointOptions *bp_options = nullptr; + if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID) { + // This breakpoint does not have an associated location. + bp_options = bp->GetOptions(); + } else { + BreakpointLocationSP bp_loc_sp( + bp->FindLocationByID(cur_bp_id.GetLocationID())); + // This breakpoint does have an associated location. + // Get its breakpoint options. + if (bp_loc_sp) + bp_options = bp_loc_sp->GetLocationOptions(); + } + if (bp_options) + m_bp_options_vec.push_back(bp_options); } - - return result.Succeeded(); + } + + // If we are using script language, get the script interpreter + // in order to set or collect command callback. Otherwise, call + // the methods associated with this object. + if (m_options.m_use_script_language) { + ScriptInterpreter *script_interp = m_interpreter.GetScriptInterpreter(); + // Special handling for one-liner specified inline. + if (m_options.m_use_one_liner) { + script_interp->SetBreakpointCommandCallback( + m_bp_options_vec, m_options.m_one_liner.c_str()); + } else if (!m_options.m_function_name.empty()) { + script_interp->SetBreakpointCommandCallbackFunction( + m_bp_options_vec, m_options.m_function_name.c_str()); + } else { + script_interp->CollectDataForBreakpointCommandCallback( + m_bp_options_vec, result); + } + } else { + // Special handling for one-liner specified inline. + if (m_options.m_use_one_liner) + SetBreakpointCommandCallback(m_bp_options_vec, + m_options.m_one_liner.c_str()); + else + CollectDataForBreakpointCommandCallback(m_bp_options_vec, result); + } } + return result.Succeeded(); + } + private: - CommandOptions m_options; - std::vector<BreakpointOptions *> m_bp_options_vec; // This stores the breakpoint options that we are currently - // collecting commands for. In the CollectData... calls we need - // to hand this off to the IOHandler, which may run asynchronously. - // So we have to have some way to keep it alive, and not leak it. - // Making it an ivar of the command object, which never goes away - // achieves this. Note that if we were able to run - // the same command concurrently in one interpreter we'd have to - // make this "per invocation". But there are many more reasons - // why it is not in general safe to do that in lldb at present, - // so it isn't worthwhile to come up with a more complex mechanism - // to address this particular weakness right now. - static const char *g_reader_instructions; + CommandOptions m_options; + std::vector<BreakpointOptions *> m_bp_options_vec; // This stores the + // breakpoint options that + // we are currently + // collecting commands for. In the CollectData... calls we need + // to hand this off to the IOHandler, which may run asynchronously. + // So we have to have some way to keep it alive, and not leak it. + // Making it an ivar of the command object, which never goes away + // achieves this. Note that if we were able to run + // the same command concurrently in one interpreter we'd have to + // make this "per invocation". But there are many more reasons + // why it is not in general safe to do that in lldb at present, + // so it isn't worthwhile to come up with a more complex mechanism + // to address this particular weakness right now. + static const char *g_reader_instructions; }; -const char * -CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.\n"; +const char *CommandObjectBreakpointCommandAdd::g_reader_instructions = + "Enter your debugger command(s). Type 'DONE' to end.\n"; -// FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting -// language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper. +// FIXME: "script-type" needs to have its contents determined dynamically, so +// somebody can add a new scripting +// language to lldb and have it pickable here without having to change this +// enumeration by hand and rebuild lldb proper. -static OptionEnumValueElement -g_script_option_enumeration[4] = -{ - { eScriptLanguageNone, "command", "Commands are in the lldb command interpreter language"}, - { eScriptLanguagePython, "python", "Commands are in the Python language."}, - { eSortOrderByName, "default-script", "Commands are in the default scripting language."}, - { 0, nullptr, nullptr } -}; +static OptionEnumValueElement g_script_option_enumeration[4] = { + {eScriptLanguageNone, "command", + "Commands are in the lldb command interpreter language"}, + {eScriptLanguagePython, "python", "Commands are in the Python language."}, + {eSortOrderByName, "default-script", + "Commands are in the default scripting language."}, + {0, nullptr, nullptr}}; OptionDefinition -CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOneLiner, "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." }, {LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Specify whether breakpoint command execution should terminate on error." }, {LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, nullptr, g_script_option_enumeration, 0, eArgTypeNone, "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."}, {LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."}, {LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- // CommandObjectBreakpointCommandDelete //------------------------------------------------------------------------- -class CommandObjectBreakpointCommandDelete : public CommandObjectParsed -{ +class CommandObjectBreakpointCommandDelete : public CommandObjectParsed { public: - CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "delete", + CommandObjectBreakpointCommandDelete(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "delete", "Delete the set of commands from a breakpoint.", nullptr), - m_options() - { - CommandArgumentEntry arg; - CommandArgumentData bp_id_arg; + m_options() { + CommandArgumentEntry arg; + CommandArgumentData bp_id_arg; - // Define the first (and only) variant of this arg. - bp_id_arg.arg_type = eArgTypeBreakpointID; - bp_id_arg.arg_repetition = eArgRepeatPlain; + // Define the first (and only) variant of this arg. + bp_id_arg.arg_type = eArgTypeBreakpointID; + bp_id_arg.arg_repetition = eArgRepeatPlain; - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (bp_id_arg); + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(bp_id_arg); - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - } + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } - ~CommandObjectBreakpointCommandDelete() override = default; + ~CommandObjectBreakpointCommandDelete() override = default; - Options * - GetOptions () override - { - return &m_options; - } + Options *GetOptions() override { return &m_options; } - class CommandOptions : public Options - { - public: - CommandOptions() : - Options(), - m_use_dummy(false) - { - } + class CommandOptions : public Options { + public: + CommandOptions() : Options(), m_use_dummy(false) {} - ~CommandOptions() override = default; + ~CommandOptions() override = default; - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; - switch (short_option) - { - case 'D': - m_use_dummy = true; - break; + switch (short_option) { + case 'D': + m_use_dummy = true; + break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } - return error; - } + return error; + } - void - OptionParsingStarting (ExecutionContext *execution_context) override - { - m_use_dummy = false; - } + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_use_dummy = false; + } - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } - // Options table: Required for subclasses of Options. + // Options table: Required for subclasses of Options. - static OptionDefinition g_option_table[]; + static OptionDefinition g_option_table[]; - // Instance variables to hold the values for command options. - bool m_use_dummy; - }; + // Instance variables to hold the values for command options. + bool m_use_dummy; + }; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); - - if (target == nullptr) - { - result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands"); - result.SetStatus (eReturnStatusFailed); - return false; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); + + if (target == nullptr) { + result.AppendError("There is not a current executable; there are no " + "breakpoints from which to delete commands"); + result.SetStatus(eReturnStatusFailed); + return false; + } - const BreakpointList &breakpoints = target->GetBreakpointList(); - size_t num_breakpoints = breakpoints.GetSize(); + const BreakpointList &breakpoints = target->GetBreakpointList(); + size_t num_breakpoints = breakpoints.GetSize(); - if (num_breakpoints == 0) - { - result.AppendError ("No breakpoints exist to have commands deleted"); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (num_breakpoints == 0) { + result.AppendError("No breakpoints exist to have commands deleted"); + result.SetStatus(eReturnStatusFailed); + return false; + } - if (command.GetArgumentCount() == 0) - { - result.AppendError ("No breakpoint specified from which to delete the commands"); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (command.GetArgumentCount() == 0) { + result.AppendError( + "No breakpoint specified from which to delete the commands"); + result.SetStatus(eReturnStatusFailed); + return false; + } - BreakpointIDList valid_bp_ids; - CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); - - if (result.Succeeded()) - { - const size_t count = valid_bp_ids.GetSize(); - for (size_t i = 0; i < count; ++i) - { - BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); - if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) - { - Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); - if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) - { - BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID())); - if (bp_loc_sp) - bp_loc_sp->ClearCallback(); - else - { - result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n", - cur_bp_id.GetBreakpointID(), - cur_bp_id.GetLocationID()); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - else - { - bp->ClearCallback(); - } - } + BreakpointIDList valid_bp_ids; + CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( + command, target, result, &valid_bp_ids); + + if (result.Succeeded()) { + const size_t count = valid_bp_ids.GetSize(); + for (size_t i = 0; i < count; ++i) { + BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); + if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { + Breakpoint *bp = + target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { + BreakpointLocationSP bp_loc_sp( + bp->FindLocationByID(cur_bp_id.GetLocationID())); + if (bp_loc_sp) + bp_loc_sp->ClearCallback(); + else { + result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n", + cur_bp_id.GetBreakpointID(), + cur_bp_id.GetLocationID()); + result.SetStatus(eReturnStatusFailed); + return false; } + } else { + bp->ClearCallback(); + } } - return result.Succeeded(); + } } + return result.Succeeded(); + } private: - CommandOptions m_options; + CommandOptions m_options; }; OptionDefinition -CommandObjectBreakpointCommandDelete::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectBreakpointCommandDelete::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- // CommandObjectBreakpointCommandList //------------------------------------------------------------------------- -class CommandObjectBreakpointCommandList : public CommandObjectParsed -{ +class CommandObjectBreakpointCommandList : public CommandObjectParsed { public: - CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "list", - "List the script or set of commands to be executed when the breakpoint is hit.", - nullptr) - { - CommandArgumentEntry arg; - CommandArgumentData bp_id_arg; - - // Define the first (and only) variant of this arg. - bp_id_arg.arg_type = eArgTypeBreakpointID; - bp_id_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (bp_id_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - } + CommandObjectBreakpointCommandList(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "list", "List the script or set of " + "commands to be executed when " + "the breakpoint is hit.", + nullptr) { + CommandArgumentEntry arg; + CommandArgumentData bp_id_arg; + + // Define the first (and only) variant of this arg. + bp_id_arg.arg_type = eArgTypeBreakpointID; + bp_id_arg.arg_repetition = eArgRepeatPlain; - ~CommandObjectBreakpointCommandList() override = default; + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(bp_id_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectBreakpointCommandList() override = default; protected: - bool - DoExecute (Args& command, - CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - - if (target == nullptr) - { - result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands"); - result.SetStatus (eReturnStatusFailed); - return false; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + + if (target == nullptr) { + result.AppendError("There is not a current executable; there are no " + "breakpoints for which to list commands"); + result.SetStatus(eReturnStatusFailed); + return false; + } - const BreakpointList &breakpoints = target->GetBreakpointList(); - size_t num_breakpoints = breakpoints.GetSize(); + const BreakpointList &breakpoints = target->GetBreakpointList(); + size_t num_breakpoints = breakpoints.GetSize(); - if (num_breakpoints == 0) - { - result.AppendError ("No breakpoints exist for which to list commands"); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (num_breakpoints == 0) { + result.AppendError("No breakpoints exist for which to list commands"); + result.SetStatus(eReturnStatusFailed); + return false; + } - if (command.GetArgumentCount() == 0) - { - result.AppendError ("No breakpoint specified for which to list the commands"); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (command.GetArgumentCount() == 0) { + result.AppendError( + "No breakpoint specified for which to list the commands"); + result.SetStatus(eReturnStatusFailed); + return false; + } - BreakpointIDList valid_bp_ids; - CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); - - if (result.Succeeded()) - { - const size_t count = valid_bp_ids.GetSize(); - for (size_t i = 0; i < count; ++i) - { - BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); - if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) - { - Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); - - if (bp) - { - const BreakpointOptions *bp_options = nullptr; - if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) - { - BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID())); - if (bp_loc_sp) - bp_options = bp_loc_sp->GetOptionsNoCreate(); - else - { - result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n", - cur_bp_id.GetBreakpointID(), - cur_bp_id.GetLocationID()); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - else - { - bp_options = bp->GetOptions(); - } - - if (bp_options) - { - StreamString id_str; - BreakpointID::GetCanonicalReference (&id_str, - cur_bp_id.GetBreakpointID(), - cur_bp_id.GetLocationID()); - const Baton *baton = bp_options->GetBaton(); - if (baton) - { - result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData()); - result.GetOutputStream().IndentMore (); - baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull); - result.GetOutputStream().IndentLess (); - } - else - { - result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n", - id_str.GetData()); - } - } - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID()); - result.SetStatus (eReturnStatusFailed); - } - } + BreakpointIDList valid_bp_ids; + CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( + command, target, result, &valid_bp_ids); + + if (result.Succeeded()) { + const size_t count = valid_bp_ids.GetSize(); + for (size_t i = 0; i < count; ++i) { + BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); + if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { + Breakpoint *bp = + target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + + if (bp) { + const BreakpointOptions *bp_options = nullptr; + if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { + BreakpointLocationSP bp_loc_sp( + bp->FindLocationByID(cur_bp_id.GetLocationID())); + if (bp_loc_sp) + bp_options = bp_loc_sp->GetOptionsNoCreate(); + else { + result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n", + cur_bp_id.GetBreakpointID(), + cur_bp_id.GetLocationID()); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + bp_options = bp->GetOptions(); } - } - return result.Succeeded(); + if (bp_options) { + StreamString id_str; + BreakpointID::GetCanonicalReference(&id_str, + cur_bp_id.GetBreakpointID(), + cur_bp_id.GetLocationID()); + const Baton *baton = bp_options->GetBaton(); + if (baton) { + result.GetOutputStream().Printf("Breakpoint %s:\n", + id_str.GetData()); + result.GetOutputStream().IndentMore(); + baton->GetDescription(&result.GetOutputStream(), + eDescriptionLevelFull); + result.GetOutputStream().IndentLess(); + } else { + result.AppendMessageWithFormat( + "Breakpoint %s does not have an associated command.\n", + id_str.GetData()); + } + } + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", + cur_bp_id.GetBreakpointID()); + result.SetStatus(eReturnStatusFailed); + } + } + } } + + return result.Succeeded(); + } }; //------------------------------------------------------------------------- // CommandObjectBreakpointCommand //------------------------------------------------------------------------- -CommandObjectBreakpointCommand::CommandObjectBreakpointCommand(CommandInterpreter &interpreter) +CommandObjectBreakpointCommand::CommandObjectBreakpointCommand( + CommandInterpreter &interpreter) : CommandObjectMultiword( - interpreter, "command", - "Commands for adding, removing and listing LLDB commands executed when a breakpoint is hit.", - "command <sub-command> [<sub-command-options>] <breakpoint-id>") -{ - CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter)); - CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter)); - CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter)); - - add_command_object->SetCommandName ("breakpoint command add"); - delete_command_object->SetCommandName ("breakpoint command delete"); - list_command_object->SetCommandName ("breakpoint command list"); - - LoadSubCommand ("add", add_command_object); - LoadSubCommand ("delete", delete_command_object); - LoadSubCommand ("list", list_command_object); + interpreter, "command", "Commands for adding, removing and listing " + "LLDB commands executed when a breakpoint is " + "hit.", + "command <sub-command> [<sub-command-options>] <breakpoint-id>") { + CommandObjectSP add_command_object( + new CommandObjectBreakpointCommandAdd(interpreter)); + CommandObjectSP delete_command_object( + new CommandObjectBreakpointCommandDelete(interpreter)); + CommandObjectSP list_command_object( + new CommandObjectBreakpointCommandList(interpreter)); + + add_command_object->SetCommandName("breakpoint command add"); + delete_command_object->SetCommandName("breakpoint command delete"); + list_command_object->SetCommandName("breakpoint command list"); + + LoadSubCommand("add", add_command_object); + LoadSubCommand("delete", delete_command_object); + LoadSubCommand("list", list_command_object); } CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand() = default; diff --git a/lldb/source/Commands/CommandObjectBreakpointCommand.h b/lldb/source/Commands/CommandObjectBreakpointCommand.h index 94afc78..048cc5e 100644 --- a/lldb/source/Commands/CommandObjectBreakpointCommand.h +++ b/lldb/source/Commands/CommandObjectBreakpointCommand.h @@ -16,11 +16,11 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-types.h" -#include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/CommandObject.h" -#include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/CommandObjectMultiword.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Interpreter/Options.h" +#include "lldb/lldb-types.h" namespace lldb_private { @@ -28,12 +28,11 @@ namespace lldb_private { // CommandObjectMultiwordBreakpoint //------------------------------------------------------------------------- -class CommandObjectBreakpointCommand : public CommandObjectMultiword -{ +class CommandObjectBreakpointCommand : public CommandObjectMultiword { public: - CommandObjectBreakpointCommand (CommandInterpreter &interpreter); + CommandObjectBreakpointCommand(CommandInterpreter &interpreter); - ~CommandObjectBreakpointCommand() override; + ~CommandObjectBreakpointCommand() override; }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectBugreport.cpp b/lldb/source/Commands/CommandObjectBugreport.cpp index 7dd1979..04050e3 100644 --- a/lldb/source/Commands/CommandObjectBugreport.cpp +++ b/lldb/source/Commands/CommandObjectBugreport.cpp @@ -28,100 +28,87 @@ using namespace lldb_private; // "bugreport unwind" //------------------------------------------------------------------------- -class CommandObjectBugreportUnwind : public CommandObjectParsed -{ +class CommandObjectBugreportUnwind : public CommandObjectParsed { public: - CommandObjectBugreportUnwind(CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "bugreport unwind", - "Create a bugreport for a bug in the stack unwinding code.", - nullptr), - m_option_group(), - m_outfile_options() - { - m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); - m_option_group.Finalize(); - } + CommandObjectBugreportUnwind(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "bugreport unwind", + "Create a bugreport for a bug in the stack unwinding code.", + nullptr), + m_option_group(), m_outfile_options() { + m_option_group.Append(&m_outfile_options, LLDB_OPT_SET_ALL, + LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); + m_option_group.Finalize(); + } - ~CommandObjectBugreportUnwind() override - { - } + ~CommandObjectBugreportUnwind() override {} - Options * - GetOptions() override - { - return &m_option_group; - } + Options *GetOptions() override { return &m_option_group; } protected: - bool - DoExecute(Args& command, CommandReturnObject &result) override - { - StringList commands; - commands.AppendString("thread backtrace"); - - Thread *thread = m_exe_ctx.GetThreadPtr(); - if (thread) - { - char command_buffer[256]; - - uint32_t frame_count = thread->GetStackFrameCount(); - for (uint32_t i = 0; i < frame_count; ++i) - { - StackFrameSP frame = thread->GetStackFrameAtIndex(i); - lldb::addr_t pc = frame->GetStackID().GetPC(); - - snprintf(command_buffer, sizeof(command_buffer), "disassemble --bytes --address 0x%" PRIx64, pc); - commands.AppendString(command_buffer); - - snprintf(command_buffer, sizeof(command_buffer), "image show-unwind --address 0x%" PRIx64, pc); - commands.AppendString(command_buffer); - } - } - - const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue(); - if (outfile_spec) - { - char path[PATH_MAX]; - outfile_spec.GetPath (path, sizeof(path)); - - uint32_t open_options = File::eOpenOptionWrite | - File::eOpenOptionCanCreate | - File::eOpenOptionAppend | - File::eOpenOptionCloseOnExec; - - const bool append = m_outfile_options.GetAppend().GetCurrentValue(); - if (!append) - open_options |= File::eOpenOptionTruncate; - - StreamFileSP outfile_stream = std::make_shared<StreamFile>(); - Error error = outfile_stream->GetFile().Open(path, open_options); - if (error.Fail()) - { - result.AppendErrorWithFormat("Failed to open file '%s' for %s: %s\n", - path, - append ? "append" : "write", - error.AsCString()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - result.SetImmediateOutputStream(outfile_stream); - } - - CommandInterpreterRunOptions options; - options.SetStopOnError(false); - options.SetEchoCommands(true); - options.SetPrintResults(true); - options.SetAddToHistory(false); - m_interpreter.HandleCommands(commands, &m_exe_ctx, options, result); - - return result.Succeeded(); + bool DoExecute(Args &command, CommandReturnObject &result) override { + StringList commands; + commands.AppendString("thread backtrace"); + + Thread *thread = m_exe_ctx.GetThreadPtr(); + if (thread) { + char command_buffer[256]; + + uint32_t frame_count = thread->GetStackFrameCount(); + for (uint32_t i = 0; i < frame_count; ++i) { + StackFrameSP frame = thread->GetStackFrameAtIndex(i); + lldb::addr_t pc = frame->GetStackID().GetPC(); + + snprintf(command_buffer, sizeof(command_buffer), + "disassemble --bytes --address 0x%" PRIx64, pc); + commands.AppendString(command_buffer); + + snprintf(command_buffer, sizeof(command_buffer), + "image show-unwind --address 0x%" PRIx64, pc); + commands.AppendString(command_buffer); + } + } + + const FileSpec &outfile_spec = + m_outfile_options.GetFile().GetCurrentValue(); + if (outfile_spec) { + char path[PATH_MAX]; + outfile_spec.GetPath(path, sizeof(path)); + + uint32_t open_options = + File::eOpenOptionWrite | File::eOpenOptionCanCreate | + File::eOpenOptionAppend | File::eOpenOptionCloseOnExec; + + const bool append = m_outfile_options.GetAppend().GetCurrentValue(); + if (!append) + open_options |= File::eOpenOptionTruncate; + + StreamFileSP outfile_stream = std::make_shared<StreamFile>(); + Error error = outfile_stream->GetFile().Open(path, open_options); + if (error.Fail()) { + result.AppendErrorWithFormat("Failed to open file '%s' for %s: %s\n", + path, append ? "append" : "write", + error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + result.SetImmediateOutputStream(outfile_stream); } + CommandInterpreterRunOptions options; + options.SetStopOnError(false); + options.SetEchoCommands(true); + options.SetPrintResults(true); + options.SetAddToHistory(false); + m_interpreter.HandleCommands(commands, &m_exe_ctx, options, result); + + return result.Succeeded(); + } + private: - OptionGroupOptions m_option_group; - OptionGroupOutputFile m_outfile_options; + OptionGroupOptions m_option_group; + OptionGroupOutputFile m_outfile_options; }; #pragma mark CommandObjectMultiwordBugreport @@ -130,14 +117,15 @@ private: // CommandObjectMultiwordBugreport //------------------------------------------------------------------------- -CommandObjectMultiwordBugreport::CommandObjectMultiwordBugreport(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "bugreport", "Commands for creating domain-specific bug reports.", - "bugreport <subcommand> [<subcommand-options>]") -{ +CommandObjectMultiwordBugreport::CommandObjectMultiwordBugreport( + CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "bugreport", + "Commands for creating domain-specific bug reports.", + "bugreport <subcommand> [<subcommand-options>]") { - LoadSubCommand("unwind", CommandObjectSP(new CommandObjectBugreportUnwind(interpreter))); + LoadSubCommand( + "unwind", CommandObjectSP(new CommandObjectBugreportUnwind(interpreter))); } -CommandObjectMultiwordBugreport::~CommandObjectMultiwordBugreport () -{ -} +CommandObjectMultiwordBugreport::~CommandObjectMultiwordBugreport() {} diff --git a/lldb/source/Commands/CommandObjectBugreport.h b/lldb/source/Commands/CommandObjectBugreport.h index 3adde51e..281ea2d 100644 --- a/lldb/source/Commands/CommandObjectBugreport.h +++ b/lldb/source/Commands/CommandObjectBugreport.h @@ -22,12 +22,11 @@ namespace lldb_private { // CommandObjectMultiwordBugreport //------------------------------------------------------------------------- -class CommandObjectMultiwordBugreport : public CommandObjectMultiword -{ +class CommandObjectMultiwordBugreport : public CommandObjectMultiword { public: - CommandObjectMultiwordBugreport(CommandInterpreter &interpreter); + CommandObjectMultiwordBugreport(CommandInterpreter &interpreter); - ~CommandObjectMultiwordBugreport() override; + ~CommandObjectMultiwordBugreport() override; }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp index 2ffee58..f4f3afb 100644 --- a/lldb/source/Commands/CommandObjectCommands.cpp +++ b/lldb/source/Commands/CommandObjectCommands.cpp @@ -36,392 +36,318 @@ using namespace lldb_private; // CommandObjectCommandsSource //------------------------------------------------------------------------- -class CommandObjectCommandsHistory : public CommandObjectParsed -{ +class CommandObjectCommandsHistory : public CommandObjectParsed { public: - CommandObjectCommandsHistory(CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "command history", + CommandObjectCommandsHistory(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "command history", "Dump the history of commands in this session.", nullptr), - m_options() - { - } + m_options() {} - ~CommandObjectCommandsHistory() override = default; + ~CommandObjectCommandsHistory() override = default; - Options * - GetOptions () override - { - return &m_options; - } + Options *GetOptions() override { return &m_options; } protected: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options(), - m_start_idx(0), - m_stop_idx(0), - m_count(0), - m_clear(false) - { - } - - ~CommandOptions() override = default; - - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'c': - error = m_count.SetValueFromString(option_arg,eVarSetOperationAssign); - break; - case 's': - if (option_arg && strcmp("end", option_arg) == 0) - { - m_start_idx.SetCurrentValue(UINT64_MAX); - m_start_idx.SetOptionWasSet(); - } - else - error = m_start_idx.SetValueFromString(option_arg,eVarSetOperationAssign); - break; - case 'e': - error = m_stop_idx.SetValueFromString(option_arg,eVarSetOperationAssign); - break; - case 'C': - m_clear.SetCurrentValue(true); - m_clear.SetOptionWasSet(); - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting (ExecutionContext *execution_context) override - { - m_start_idx.Clear(); - m_stop_idx.Clear(); - m_count.Clear(); - m_clear.Clear(); - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. + class CommandOptions : public Options { + public: + CommandOptions() + : Options(), m_start_idx(0), m_stop_idx(0), m_count(0), m_clear(false) { + } - static OptionDefinition g_option_table[]; + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'c': + error = m_count.SetValueFromString(option_arg, eVarSetOperationAssign); + break; + case 's': + if (option_arg && strcmp("end", option_arg) == 0) { + m_start_idx.SetCurrentValue(UINT64_MAX); + m_start_idx.SetOptionWasSet(); + } else + error = m_start_idx.SetValueFromString(option_arg, + eVarSetOperationAssign); + break; + case 'e': + error = + m_stop_idx.SetValueFromString(option_arg, eVarSetOperationAssign); + break; + case 'C': + m_clear.SetCurrentValue(true); + m_clear.SetOptionWasSet(); + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; + } - // Instance variables to hold the values for command options. + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_start_idx.Clear(); + m_stop_idx.Clear(); + m_count.Clear(); + m_clear.Clear(); + } - OptionValueUInt64 m_start_idx; - OptionValueUInt64 m_stop_idx; - OptionValueUInt64 m_count; - OptionValueBoolean m_clear; - }; - - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - if (m_options.m_clear.GetCurrentValue() && m_options.m_clear.OptionWasSet()) - { - m_interpreter.GetCommandHistory().Clear(); - result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); - } - else - { - if (m_options.m_start_idx.OptionWasSet() && m_options.m_stop_idx.OptionWasSet() && m_options.m_count.OptionWasSet()) - { - result.AppendError("--count, --start-index and --end-index cannot be all specified in the same invocation"); - result.SetStatus(lldb::eReturnStatusFailed); + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + OptionValueUInt64 m_start_idx; + OptionValueUInt64 m_stop_idx; + OptionValueUInt64 m_count; + OptionValueBoolean m_clear; + }; + + bool DoExecute(Args &command, CommandReturnObject &result) override { + if (m_options.m_clear.GetCurrentValue() && + m_options.m_clear.OptionWasSet()) { + m_interpreter.GetCommandHistory().Clear(); + result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); + } else { + if (m_options.m_start_idx.OptionWasSet() && + m_options.m_stop_idx.OptionWasSet() && + m_options.m_count.OptionWasSet()) { + result.AppendError("--count, --start-index and --end-index cannot be " + "all specified in the same invocation"); + result.SetStatus(lldb::eReturnStatusFailed); + } else { + std::pair<bool, uint64_t> start_idx( + m_options.m_start_idx.OptionWasSet(), + m_options.m_start_idx.GetCurrentValue()); + std::pair<bool, uint64_t> stop_idx( + m_options.m_stop_idx.OptionWasSet(), + m_options.m_stop_idx.GetCurrentValue()); + std::pair<bool, uint64_t> count(m_options.m_count.OptionWasSet(), + m_options.m_count.GetCurrentValue()); + + const CommandHistory &history(m_interpreter.GetCommandHistory()); + + if (start_idx.first && start_idx.second == UINT64_MAX) { + if (count.first) { + start_idx.second = history.GetSize() - count.second; + stop_idx.second = history.GetSize() - 1; + } else if (stop_idx.first) { + start_idx.second = stop_idx.second; + stop_idx.second = history.GetSize() - 1; + } else { + start_idx.second = 0; + stop_idx.second = history.GetSize() - 1; + } + } else { + if (!start_idx.first && !stop_idx.first && !count.first) { + start_idx.second = 0; + stop_idx.second = history.GetSize() - 1; + } else if (start_idx.first) { + if (count.first) { + stop_idx.second = start_idx.second + count.second - 1; + } else if (!stop_idx.first) { + stop_idx.second = history.GetSize() - 1; } - else - { - std::pair<bool,uint64_t> start_idx(m_options.m_start_idx.OptionWasSet(),m_options.m_start_idx.GetCurrentValue()); - std::pair<bool,uint64_t> stop_idx(m_options.m_stop_idx.OptionWasSet(),m_options.m_stop_idx.GetCurrentValue()); - std::pair<bool,uint64_t> count(m_options.m_count.OptionWasSet(),m_options.m_count.GetCurrentValue()); - - const CommandHistory& history(m_interpreter.GetCommandHistory()); - - if (start_idx.first && start_idx.second == UINT64_MAX) - { - if (count.first) - { - start_idx.second = history.GetSize() - count.second; - stop_idx.second = history.GetSize() - 1; - } - else if (stop_idx.first) - { - start_idx.second = stop_idx.second; - stop_idx.second = history.GetSize() - 1; - } - else - { - start_idx.second = 0; - stop_idx.second = history.GetSize() - 1; - } - } - else - { - if (!start_idx.first && !stop_idx.first && !count.first) - { - start_idx.second = 0; - stop_idx.second = history.GetSize() - 1; - } - else if (start_idx.first) - { - if (count.first) - { - stop_idx.second = start_idx.second + count.second - 1; - } - else if (!stop_idx.first) - { - stop_idx.second = history.GetSize() - 1; - } - } - else if (stop_idx.first) - { - if (count.first) - { - if (stop_idx.second >= count.second) - start_idx.second = stop_idx.second - count.second + 1; - else - start_idx.second = 0; - } - } - else /* if (count.first) */ - { - start_idx.second = 0; - stop_idx.second = count.second - 1; - } - } - history.Dump(result.GetOutputStream(), start_idx.second, stop_idx.second); + } else if (stop_idx.first) { + if (count.first) { + if (stop_idx.second >= count.second) + start_idx.second = stop_idx.second - count.second + 1; + else + start_idx.second = 0; } - } - return result.Succeeded(); - + } else /* if (count.first) */ + { + start_idx.second = 0; + stop_idx.second = count.second - 1; + } + } + history.Dump(result.GetOutputStream(), start_idx.second, + stop_idx.second); + } } + return result.Succeeded(); + } - CommandOptions m_options; + CommandOptions m_options; }; OptionDefinition -CommandObjectCommandsHistory::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectCommandsHistory::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "How many history commands to print."}, {LLDB_OPT_SET_1, false, "start-index", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands (or end to mean tail mode)."}, {LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands."}, {LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Clears the current command history."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- // CommandObjectCommandsSource //------------------------------------------------------------------------- -class CommandObjectCommandsSource : public CommandObjectParsed -{ +class CommandObjectCommandsSource : public CommandObjectParsed { public: - CommandObjectCommandsSource(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "command source", "Read and execute LLDB commands from the file <filename>.", - nullptr), - m_options() - { - CommandArgumentEntry arg; - CommandArgumentData file_arg; - - // Define the first (and only) variant of this arg. - file_arg.arg_type = eArgTypeFilename; - file_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (file_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - } - - ~CommandObjectCommandsSource() override = default; + CommandObjectCommandsSource(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "command source", + "Read and execute LLDB commands from the file <filename>.", + nullptr), + m_options() { + CommandArgumentEntry arg; + CommandArgumentData file_arg; + + // Define the first (and only) variant of this arg. + file_arg.arg_type = eArgTypeFilename; + file_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(file_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectCommandsSource() override = default; + + const char *GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override { + return ""; + } + + int HandleArgumentCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, int max_return_elements, + bool &word_complete, + StringList &matches) override { + std::string completion_str(input.GetArgumentAtIndex(cursor_index)); + completion_str.erase(cursor_char_position); + + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, + completion_str.c_str(), match_start_point, max_return_elements, nullptr, + word_complete, matches); + return matches.GetSize(); + } + + Options *GetOptions() override { return &m_options; } - const char* - GetRepeatCommand (Args ¤t_command_args, uint32_t index) override - { - return ""; - } - - int - HandleArgumentCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - OptionElementVector &opt_element_vector, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) override - { - std::string completion_str (input.GetArgumentAtIndex(cursor_index)); - completion_str.erase (cursor_char_position); - - CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(), - CommandCompletions::eDiskFileCompletion, - completion_str.c_str(), - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - return matches.GetSize(); +protected: + class CommandOptions : public Options { + public: + CommandOptions() + : Options(), m_stop_on_error(true), m_silent_run(false), + m_stop_on_continue(true) {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'e': + error = m_stop_on_error.SetValueFromString(option_arg); + break; + + case 'c': + error = m_stop_on_continue.SetValueFromString(option_arg); + break; + + case 's': + error = m_silent_run.SetValueFromString(option_arg); + break; + + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; } - Options * - GetOptions () override - { - return &m_options; + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_stop_on_error.Clear(); + m_silent_run.Clear(); + m_stop_on_continue.Clear(); } -protected: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options(), - m_stop_on_error (true), - m_silent_run (false), - m_stop_on_continue (true) - { - } - - ~CommandOptions() override = default; - - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'e': - error = m_stop_on_error.SetValueFromString(option_arg); - break; - - case 'c': - error = m_stop_on_continue.SetValueFromString(option_arg); - break; - - case 's': - error = m_silent_run.SetValueFromString(option_arg); - break; - - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting (ExecutionContext *execution_context) override - { - m_stop_on_error.Clear(); - m_silent_run.Clear(); - m_stop_on_continue.Clear(); - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - OptionValueBoolean m_stop_on_error; - OptionValueBoolean m_silent_run; - OptionValueBoolean m_stop_on_continue; - }; - - bool - DoExecute(Args& command, CommandReturnObject &result) override - { - const size_t argc = command.GetArgumentCount(); - if (argc == 1) - { - const char *filename = command.GetArgumentAtIndex(0); - - FileSpec cmd_file (filename, true); - ExecutionContext *exe_ctx = nullptr; // Just use the default context. - - // If any options were set, then use them - if (m_options.m_stop_on_error.OptionWasSet() || - m_options.m_silent_run.OptionWasSet() || - m_options.m_stop_on_continue.OptionWasSet()) - { - // Use user set settings - CommandInterpreterRunOptions options; - options.SetStopOnContinue(m_options.m_stop_on_continue.GetCurrentValue()); - options.SetStopOnError (m_options.m_stop_on_error.GetCurrentValue()); - options.SetEchoCommands (!m_options.m_silent_run.GetCurrentValue()); - options.SetPrintResults (!m_options.m_silent_run.GetCurrentValue()); - - m_interpreter.HandleCommandsFromFile (cmd_file, - exe_ctx, - options, - result); - } - else - { - // No options were set, inherit any settings from nested "command source" commands, - // or set to sane default settings... - CommandInterpreterRunOptions options; - m_interpreter.HandleCommandsFromFile (cmd_file, - exe_ctx, - options, - result); - } - } - else - { - result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName()); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + OptionValueBoolean m_stop_on_error; + OptionValueBoolean m_silent_run; + OptionValueBoolean m_stop_on_continue; + }; + + bool DoExecute(Args &command, CommandReturnObject &result) override { + const size_t argc = command.GetArgumentCount(); + if (argc == 1) { + const char *filename = command.GetArgumentAtIndex(0); + + FileSpec cmd_file(filename, true); + ExecutionContext *exe_ctx = nullptr; // Just use the default context. + + // If any options were set, then use them + if (m_options.m_stop_on_error.OptionWasSet() || + m_options.m_silent_run.OptionWasSet() || + m_options.m_stop_on_continue.OptionWasSet()) { + // Use user set settings + CommandInterpreterRunOptions options; + options.SetStopOnContinue( + m_options.m_stop_on_continue.GetCurrentValue()); + options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue()); + options.SetEchoCommands(!m_options.m_silent_run.GetCurrentValue()); + options.SetPrintResults(!m_options.m_silent_run.GetCurrentValue()); + + m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, + result); + } else { + // No options were set, inherit any settings from nested "command + // source" commands, + // or set to sane default settings... + CommandInterpreterRunOptions options; + m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, + result); + } + } else { + result.AppendErrorWithFormat( + "'%s' takes exactly one executable filename argument.\n", + GetCommandName()); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } - CommandOptions m_options; + CommandOptions m_options; }; -OptionDefinition -CommandObjectCommandsSource::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectCommandsSource::CommandOptions::g_option_table[] = + { + // clang-format off {LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on error."}, {LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on continue."}, {LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true don't echo commands while executing."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; #pragma mark CommandObjectCommandsAlias @@ -429,102 +355,81 @@ CommandObjectCommandsSource::CommandOptions::g_option_table[] = // CommandObjectCommandsAlias //------------------------------------------------------------------------- -static const char *g_python_command_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" - "You must define a Python function with this signature:\n" - "def my_command_impl(debugger, args, result, internal_dict):\n"; +static const char *g_python_command_instructions = + "Enter your Python command(s). Type 'DONE' to end.\n" + "You must define a Python function with this signature:\n" + "def my_command_impl(debugger, args, result, internal_dict):\n"; -class CommandObjectCommandsAlias : public CommandObjectRaw -{ +class CommandObjectCommandsAlias : public CommandObjectRaw { protected: - class CommandOptions : public OptionGroup - { - public: - CommandOptions () : - OptionGroup(), - m_help(), - m_long_help() - {} - - ~CommandOptions() override = default; - - uint32_t - GetNumDefinitions () override - { - return 3; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - Error - SetOptionValue (uint32_t option_idx, - const char *option_value, - ExecutionContext *execution_context) override - { - Error error; - - const int short_option = g_option_table[option_idx].short_option; - - switch (short_option) - { - case 'h': - m_help.SetCurrentValue(option_value); - m_help.SetOptionWasSet(); - break; - - case 'H': - m_long_help.SetCurrentValue(option_value); - m_long_help.SetOptionWasSet(); - break; - - default: - error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting (ExecutionContext *execution_context) override - { - m_help.Clear(); - m_long_help.Clear(); - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - OptionValueString m_help; - OptionValueString m_long_help; - }; - - OptionGroupOptions m_option_group; - CommandOptions m_command_options; - -public: - Options * - GetOptions () override - { - return &m_option_group; + class CommandOptions : public OptionGroup { + public: + CommandOptions() : OptionGroup(), m_help(), m_long_help() {} + + ~CommandOptions() override = default; + + uint32_t GetNumDefinitions() override { return 3; } + + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + Error SetOptionValue(uint32_t option_idx, const char *option_value, + ExecutionContext *execution_context) override { + Error error; + + const int short_option = g_option_table[option_idx].short_option; + + switch (short_option) { + case 'h': + m_help.SetCurrentValue(option_value); + m_help.SetOptionWasSet(); + break; + + case 'H': + m_long_help.SetCurrentValue(option_value); + m_long_help.SetOptionWasSet(); + break; + + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", + short_option); + break; + } + + return error; } - CommandObjectCommandsAlias(CommandInterpreter &interpreter) - : CommandObjectRaw(interpreter, "command alias", "Define a custom command in terms of an existing command.", - nullptr), - m_option_group(), - m_command_options() - { - m_option_group.Append(&m_command_options); - m_option_group.Finalize(); + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_help.Clear(); + m_long_help.Clear(); + } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + OptionValueString m_help; + OptionValueString m_long_help; + }; - SetHelpLong( -"'alias' allows the user to create a short-cut or abbreviation for long \ + OptionGroupOptions m_option_group; + CommandOptions m_command_options; + +public: + Options *GetOptions() override { return &m_option_group; } + + CommandObjectCommandsAlias(CommandInterpreter &interpreter) + : CommandObjectRaw( + interpreter, "command alias", + "Define a custom command in terms of an existing command.", + nullptr), + m_option_group(), m_command_options() { + m_option_group.Append(&m_command_options); + m_option_group.Finalize(); + + SetHelpLong( + "'alias' allows the user to create a short-cut or abbreviation for long \ commands, multi-word commands, and commands that take particular options. \ -Below are some simple examples of how one might use the 'alias' command:" R"( +Below are some simple examples of how one might use the 'alias' command:" + R"( (lldb) command alias sc script @@ -532,22 +437,27 @@ Below are some simple examples of how one might use the 'alias' command:" R"( (lldb) command alias bp breakpoint -)" " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \ +)" + " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \ breakpoint commands are two-word commands, the user would still need to \ -enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'." R"( +enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'." + R"( (lldb) command alias bpl breakpoint list Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'. -)" "An alias can include some options for the command, with the values either \ +)" + "An alias can include some options for the command, with the values either \ filled in at the time the alias is created, or specified as positional \ arguments, to be filled in when the alias is invoked. The following example \ -shows how to create aliases with options:" R"( +shows how to create aliases with options:" + R"( (lldb) command alias bfl breakpoint set -f %1 -l %2 -)" " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \ +)" + " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \ options already part of the alias. So if the user wants to set a breakpoint \ by file and line without explicitly having to use the -f and -l options, the \ user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \ @@ -557,18 +467,23 @@ occupies when the alias is used. All the occurrences of '%1' in the alias \ will be replaced with the first argument, all the occurrences of '%2' in the \ alias will be replaced with the second argument, and so on. This also allows \ actual arguments to be used multiple times within an alias (see 'process \ -launch' example below)." R"( +launch' example below)." + R"( -)" "Note: the positional arguments must substitute as whole words in the resultant \ +)" + "Note: the positional arguments must substitute as whole words in the resultant \ command, so you can't at present do something like this to append the file extension \ -\".cpp\":" R"( +\".cpp\":" + R"( (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2 -)" "For more complex aliasing, use the \"command regex\" command instead. In the \ +)" + "For more complex aliasing, use the \"command regex\" command instead. In the \ 'bfl' case above, the actual file value will be filled in with the first argument \ following 'bfl' and the actual line number value will be filled in with the second \ -argument. The user would use this alias as follows:" R"( +argument. The user would use this alias as follows:" + R"( (lldb) command alias bfl breakpoint set -f %1 -l %2 (lldb) bfl my-file.c 137 @@ -582,343 +497,326 @@ Another example: Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0' -)" "If the user always wanted to pass the same value to a particular option, the \ +)" + "If the user always wanted to pass the same value to a particular option, the \ alias could be defined with that value directly in the alias as a constant, \ -rather than using a positional placeholder:" R"( +rather than using a positional placeholder:" + R"( (lldb) command alias bl3 breakpoint set -f %1 -l 3 - Always sets a breakpoint on line 3 of whatever file is indicated.)" - ); - - CommandArgumentEntry arg1; - CommandArgumentEntry arg2; - CommandArgumentEntry arg3; - CommandArgumentData alias_arg; - CommandArgumentData cmd_arg; - CommandArgumentData options_arg; - - // Define the first (and only) variant of this arg. - alias_arg.arg_type = eArgTypeAliasName; - alias_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg1.push_back (alias_arg); - - // Define the first (and only) variant of this arg. - cmd_arg.arg_type = eArgTypeCommandName; - cmd_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg2.push_back (cmd_arg); - - // Define the first (and only) variant of this arg. - options_arg.arg_type = eArgTypeAliasOptions; - options_arg.arg_repetition = eArgRepeatOptional; - - // There is only one variant this argument could be; put it into the argument entry. - arg3.push_back (options_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg1); - m_arguments.push_back (arg2); - m_arguments.push_back (arg3); - } + Always sets a breakpoint on line 3 of whatever file is indicated.)"); + + CommandArgumentEntry arg1; + CommandArgumentEntry arg2; + CommandArgumentEntry arg3; + CommandArgumentData alias_arg; + CommandArgumentData cmd_arg; + CommandArgumentData options_arg; + + // Define the first (and only) variant of this arg. + alias_arg.arg_type = eArgTypeAliasName; + alias_arg.arg_repetition = eArgRepeatPlain; - ~CommandObjectCommandsAlias() override = default; + // There is only one variant this argument could be; put it into the + // argument entry. + arg1.push_back(alias_arg); + + // Define the first (and only) variant of this arg. + cmd_arg.arg_type = eArgTypeCommandName; + cmd_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg2.push_back(cmd_arg); + + // Define the first (and only) variant of this arg. + options_arg.arg_type = eArgTypeAliasOptions; + options_arg.arg_repetition = eArgRepeatOptional; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg3.push_back(options_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg1); + m_arguments.push_back(arg2); + m_arguments.push_back(arg3); + } + + ~CommandObjectCommandsAlias() override = default; protected: - bool - DoExecute (const char *raw_command_line, CommandReturnObject &result) override - { - if (!raw_command_line || !raw_command_line[0]) - { - result.AppendError ("'command alias' requires at least two arguments"); - return false; - } + bool DoExecute(const char *raw_command_line, + CommandReturnObject &result) override { + if (!raw_command_line || !raw_command_line[0]) { + result.AppendError("'command alias' requires at least two arguments"); + return false; + } - ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext(); - m_option_group.NotifyOptionParsingStarting(&exe_ctx); - - const char * remainder = nullptr; - - if (raw_command_line[0] == '-') - { - // We have some options and these options MUST end with --. - const char *end_options = nullptr; - const char *s = raw_command_line; - while (s && s[0]) - { - end_options = ::strstr (s, "--"); - if (end_options) - { - end_options += 2; // Get past the "--" - if (::isspace (end_options[0])) - { - remainder = end_options; - while (::isspace (*remainder)) - ++remainder; - break; - } - } - s = end_options; - } - - if (end_options) - { - Args args (llvm::StringRef(raw_command_line, end_options - raw_command_line)); - if (!ParseOptions (args, result)) - return false; - - Error error (m_option_group.NotifyOptionParsingFinished(&exe_ctx)); - if (error.Fail()) - { - result.AppendError (error.AsCString()); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - } - if (nullptr == remainder) - remainder = raw_command_line; - - std::string raw_command_string (remainder); - Args args (raw_command_string.c_str()); - - size_t argc = args.GetArgumentCount(); - - if (argc < 2) - { - result.AppendError ("'command alias' requires at least two arguments"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - // Get the alias command. - - const std::string alias_command = args.GetArgumentAtIndex (0); - if (alias_command.size() > 1 && - alias_command[0] == '-') - { - result.AppendError("aliases starting with a dash are not supported"); - if (alias_command == "--help" || alias_command == "--long-help") - { - result.AppendWarning("if trying to pass options to 'command alias' add a -- at the end of the options"); - } - result.SetStatus (eReturnStatusFailed); - return false; - } - - // Strip the new alias name off 'raw_command_string' (leave it on args, which gets passed to 'Execute', which - // does the stripping itself. - size_t pos = raw_command_string.find (alias_command); - if (pos == 0) - { - raw_command_string = raw_command_string.substr (alias_command.size()); - pos = raw_command_string.find_first_not_of (' '); - if ((pos != std::string::npos) && (pos > 0)) - raw_command_string = raw_command_string.substr (pos); - } - else - { - result.AppendError ("Error parsing command string. No alias created."); - result.SetStatus (eReturnStatusFailed); - return false; - } - - - // Verify that the command is alias-able. - if (m_interpreter.CommandExists (alias_command.c_str())) - { - result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n", - alias_command.c_str()); - result.SetStatus (eReturnStatusFailed); - return false; - } - - // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string. - // raw_command_string is returned with the name of the command object stripped off the front. - std::string original_raw_command_string(raw_command_string); - CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string); - - if (!cmd_obj) - { - result.AppendErrorWithFormat ("invalid command given to 'command alias'. '%s' does not begin with a valid command." - " No alias created.", original_raw_command_string.c_str()); - result.SetStatus (eReturnStatusFailed); - return false; - } - else if (!cmd_obj->WantsRawCommandString ()) - { - // Note that args was initialized with the original command, and has not been updated to this point. - // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias. - return HandleAliasingNormalCommand (args, result); - } - else - { - return HandleAliasingRawCommand (alias_command, raw_command_string, *cmd_obj, result); - } - return result.Succeeded(); + ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext(); + m_option_group.NotifyOptionParsingStarting(&exe_ctx); + + const char *remainder = nullptr; + + if (raw_command_line[0] == '-') { + // We have some options and these options MUST end with --. + const char *end_options = nullptr; + const char *s = raw_command_line; + while (s && s[0]) { + end_options = ::strstr(s, "--"); + if (end_options) { + end_options += 2; // Get past the "--" + if (::isspace(end_options[0])) { + remainder = end_options; + while (::isspace(*remainder)) + ++remainder; + break; + } + } + s = end_options; + } + + if (end_options) { + Args args( + llvm::StringRef(raw_command_line, end_options - raw_command_line)); + if (!ParseOptions(args, result)) + return false; + + Error error(m_option_group.NotifyOptionParsingFinished(&exe_ctx)); + if (error.Fail()) { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + } } + if (nullptr == remainder) + remainder = raw_command_line; - bool - HandleAliasingRawCommand (const std::string &alias_command, std::string &raw_command_string, CommandObject &cmd_obj, CommandReturnObject &result) - { - // Verify & handle any options/arguments passed to the alias command - - OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector); - - if (CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj.GetCommandName(), false)) - { - if (m_interpreter.AliasExists (alias_command.c_str()) - || m_interpreter.UserCommandExists (alias_command.c_str())) - { - result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n", - alias_command.c_str()); - } - if (CommandAlias *alias = m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp, raw_command_string.c_str())) - { - if (m_command_options.m_help.OptionWasSet()) - alias->SetHelp(m_command_options.m_help.GetCurrentValue()); - if (m_command_options.m_long_help.OptionWasSet()) - alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendError ("Unable to create requested alias.\n"); - result.SetStatus (eReturnStatusFailed); - } + std::string raw_command_string(remainder); + Args args(raw_command_string.c_str()); - } - else - { - result.AppendError ("Unable to create requested alias.\n"); - result.SetStatus (eReturnStatusFailed); - } + size_t argc = args.GetArgumentCount(); - return result.Succeeded (); + if (argc < 2) { + result.AppendError("'command alias' requires at least two arguments"); + result.SetStatus(eReturnStatusFailed); + return false; } - - bool - HandleAliasingNormalCommand (Args& args, CommandReturnObject &result) - { - size_t argc = args.GetArgumentCount(); - if (argc < 2) - { - result.AppendError ("'command alias' requires at least two arguments"); - result.SetStatus (eReturnStatusFailed); - return false; - } + // Get the alias command. + + const std::string alias_command = args.GetArgumentAtIndex(0); + if (alias_command.size() > 1 && alias_command[0] == '-') { + result.AppendError("aliases starting with a dash are not supported"); + if (alias_command == "--help" || alias_command == "--long-help") { + result.AppendWarning("if trying to pass options to 'command alias' add " + "a -- at the end of the options"); + } + result.SetStatus(eReturnStatusFailed); + return false; + } + + // Strip the new alias name off 'raw_command_string' (leave it on args, + // which gets passed to 'Execute', which + // does the stripping itself. + size_t pos = raw_command_string.find(alias_command); + if (pos == 0) { + raw_command_string = raw_command_string.substr(alias_command.size()); + pos = raw_command_string.find_first_not_of(' '); + if ((pos != std::string::npos) && (pos > 0)) + raw_command_string = raw_command_string.substr(pos); + } else { + result.AppendError("Error parsing command string. No alias created."); + result.SetStatus(eReturnStatusFailed); + return false; + } + + // Verify that the command is alias-able. + if (m_interpreter.CommandExists(alias_command.c_str())) { + result.AppendErrorWithFormat( + "'%s' is a permanent debugger command and cannot be redefined.\n", + alias_command.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } - const std::string alias_command = args.GetArgumentAtIndex(0); - const std::string actual_command = args.GetArgumentAtIndex(1); + // Get CommandObject that is being aliased. The command name is read from + // the front of raw_command_string. + // raw_command_string is returned with the name of the command object + // stripped off the front. + std::string original_raw_command_string(raw_command_string); + CommandObject *cmd_obj = + m_interpreter.GetCommandObjectForCommand(raw_command_string); + + if (!cmd_obj) { + result.AppendErrorWithFormat("invalid command given to 'command alias'. " + "'%s' does not begin with a valid command." + " No alias created.", + original_raw_command_string.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } else if (!cmd_obj->WantsRawCommandString()) { + // Note that args was initialized with the original command, and has not + // been updated to this point. + // Therefore can we pass it to the version of Execute that does not + // need/expect raw input in the alias. + return HandleAliasingNormalCommand(args, result); + } else { + return HandleAliasingRawCommand(alias_command, raw_command_string, + *cmd_obj, result); + } + return result.Succeeded(); + } + + bool HandleAliasingRawCommand(const std::string &alias_command, + std::string &raw_command_string, + CommandObject &cmd_obj, + CommandReturnObject &result) { + // Verify & handle any options/arguments passed to the alias command + + OptionArgVectorSP option_arg_vector_sp = + OptionArgVectorSP(new OptionArgVector); + + if (CommandObjectSP cmd_obj_sp = + m_interpreter.GetCommandSPExact(cmd_obj.GetCommandName(), false)) { + if (m_interpreter.AliasExists(alias_command.c_str()) || + m_interpreter.UserCommandExists(alias_command.c_str())) { + result.AppendWarningWithFormat( + "Overwriting existing definition for '%s'.\n", + alias_command.c_str()); + } + if (CommandAlias *alias = m_interpreter.AddAlias( + alias_command.c_str(), cmd_obj_sp, raw_command_string.c_str())) { + if (m_command_options.m_help.OptionWasSet()) + alias->SetHelp(m_command_options.m_help.GetCurrentValue()); + if (m_command_options.m_long_help.OptionWasSet()) + alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.AppendError("Unable to create requested alias.\n"); + result.SetStatus(eReturnStatusFailed); + } + + } else { + result.AppendError("Unable to create requested alias.\n"); + result.SetStatus(eReturnStatusFailed); + } - args.Shift(); // Shift the alias command word off the argument vector. - args.Shift(); // Shift the old command word off the argument vector. + return result.Succeeded(); + } - // Verify that the command is alias'able, and get the appropriate command object. + bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) { + size_t argc = args.GetArgumentCount(); - if (m_interpreter.CommandExists (alias_command.c_str())) - { - result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n", - alias_command.c_str()); - result.SetStatus (eReturnStatusFailed); - } - else - { - CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true)); - CommandObjectSP subcommand_obj_sp; - bool use_subcommand = false; - if (command_obj_sp) - { - CommandObject *cmd_obj = command_obj_sp.get(); - CommandObject *sub_cmd_obj = nullptr; - OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector); - - while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0) - { - if (argc >= 3) - { - const std::string sub_command = args.GetArgumentAtIndex(0); - assert (sub_command.length() != 0); - subcommand_obj_sp = cmd_obj->GetSubcommandSP (sub_command.c_str()); - if (subcommand_obj_sp) - { - sub_cmd_obj = subcommand_obj_sp.get(); - use_subcommand = true; - args.Shift(); // Shift the sub_command word off the argument vector. - cmd_obj = sub_cmd_obj; - } - else - { - result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'. " - "Unable to create alias.\n", - sub_command.c_str(), actual_command.c_str()); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - } - - // Verify & handle any options/arguments passed to the alias command - - std::string args_string; - - if (args.GetArgumentCount () > 0) - { - CommandObjectSP tmp_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false); - if (use_subcommand) - tmp_sp = m_interpreter.GetCommandSPExact (sub_cmd_obj->GetCommandName(), false); - - args.GetCommandString (args_string); - } - - if (m_interpreter.AliasExists (alias_command.c_str()) - || m_interpreter.UserCommandExists (alias_command.c_str())) - { - result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n", - alias_command.c_str()); - } - - if (CommandAlias *alias = m_interpreter.AddAlias(alias_command.c_str(), - use_subcommand ? subcommand_obj_sp : command_obj_sp, - args_string.c_str())) - { - if (m_command_options.m_help.OptionWasSet()) - alias->SetHelp(m_command_options.m_help.GetCurrentValue()); - if (m_command_options.m_long_help.OptionWasSet()) - alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendError ("Unable to create requested alias.\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - else - { - result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str()); - result.SetStatus (eReturnStatusFailed); - return false; - } - } + if (argc < 2) { + result.AppendError("'command alias' requires at least two arguments"); + result.SetStatus(eReturnStatusFailed); + return false; + } - return result.Succeeded(); + const std::string alias_command = args.GetArgumentAtIndex(0); + const std::string actual_command = args.GetArgumentAtIndex(1); + + args.Shift(); // Shift the alias command word off the argument vector. + args.Shift(); // Shift the old command word off the argument vector. + + // Verify that the command is alias'able, and get the appropriate command + // object. + + if (m_interpreter.CommandExists(alias_command.c_str())) { + result.AppendErrorWithFormat( + "'%s' is a permanent debugger command and cannot be redefined.\n", + alias_command.c_str()); + result.SetStatus(eReturnStatusFailed); + } else { + CommandObjectSP command_obj_sp( + m_interpreter.GetCommandSPExact(actual_command.c_str(), true)); + CommandObjectSP subcommand_obj_sp; + bool use_subcommand = false; + if (command_obj_sp) { + CommandObject *cmd_obj = command_obj_sp.get(); + CommandObject *sub_cmd_obj = nullptr; + OptionArgVectorSP option_arg_vector_sp = + OptionArgVectorSP(new OptionArgVector); + + while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0) { + if (argc >= 3) { + const std::string sub_command = args.GetArgumentAtIndex(0); + assert(sub_command.length() != 0); + subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command.c_str()); + if (subcommand_obj_sp) { + sub_cmd_obj = subcommand_obj_sp.get(); + use_subcommand = true; + args.Shift(); // Shift the sub_command word off the argument + // vector. + cmd_obj = sub_cmd_obj; + } else { + result.AppendErrorWithFormat( + "'%s' is not a valid sub-command of '%s'. " + "Unable to create alias.\n", + sub_command.c_str(), actual_command.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + } + + // Verify & handle any options/arguments passed to the alias command + + std::string args_string; + + if (args.GetArgumentCount() > 0) { + CommandObjectSP tmp_sp = + m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName(), false); + if (use_subcommand) + tmp_sp = m_interpreter.GetCommandSPExact( + sub_cmd_obj->GetCommandName(), false); + + args.GetCommandString(args_string); + } + + if (m_interpreter.AliasExists(alias_command.c_str()) || + m_interpreter.UserCommandExists(alias_command.c_str())) { + result.AppendWarningWithFormat( + "Overwriting existing definition for '%s'.\n", + alias_command.c_str()); + } + + if (CommandAlias *alias = m_interpreter.AddAlias( + alias_command.c_str(), + use_subcommand ? subcommand_obj_sp : command_obj_sp, + args_string.c_str())) { + if (m_command_options.m_help.OptionWasSet()) + alias->SetHelp(m_command_options.m_help.GetCurrentValue()); + if (m_command_options.m_long_help.OptionWasSet()) + alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.AppendError("Unable to create requested alias.\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + result.AppendErrorWithFormat("'%s' is not an existing command.\n", + actual_command.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } } + + return result.Succeeded(); + } }; -OptionDefinition -CommandObjectCommandsAlias::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectCommandsAlias::CommandOptions::g_option_table[] = + { + // clang-format off {LLDB_OPT_SET_ALL, false, "help", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Help text for this command"}, {LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Long help text for this command"}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; #pragma mark CommandObjectCommandsUnalias @@ -926,87 +824,78 @@ CommandObjectCommandsAlias::CommandOptions::g_option_table[] = // CommandObjectCommandsUnalias //------------------------------------------------------------------------- -class CommandObjectCommandsUnalias : public CommandObjectParsed -{ +class CommandObjectCommandsUnalias : public CommandObjectParsed { public: - CommandObjectCommandsUnalias(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "command unalias", - "Delete one or more custom commands defined by 'command alias'.", nullptr) - { - CommandArgumentEntry arg; - CommandArgumentData alias_arg; - - // Define the first (and only) variant of this arg. - alias_arg.arg_type = eArgTypeAliasName; - alias_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (alias_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - } + CommandObjectCommandsUnalias(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "command unalias", + "Delete one or more custom commands defined by 'command alias'.", + nullptr) { + CommandArgumentEntry arg; + CommandArgumentData alias_arg; - ~CommandObjectCommandsUnalias() override = default; + // Define the first (and only) variant of this arg. + alias_arg.arg_type = eArgTypeAliasName; + alias_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(alias_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectCommandsUnalias() override = default; protected: - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - CommandObject::CommandMap::iterator pos; - CommandObject *cmd_obj; - - if (args.GetArgumentCount() != 0) - { - const char *command_name = args.GetArgumentAtIndex(0); - cmd_obj = m_interpreter.GetCommandObject(command_name); - if (cmd_obj) - { - if (m_interpreter.CommandExists (command_name)) - { - if (cmd_obj->IsRemovable()) - { - result.AppendErrorWithFormat ("'%s' is not an alias, it is a debugger command which can be removed using the 'command delete' command.\n", - command_name); - } - else - { - result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n", - command_name); - } - result.SetStatus (eReturnStatusFailed); - } - else - { - if (!m_interpreter.RemoveAlias(command_name)) - { - if (m_interpreter.AliasExists (command_name)) - result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n", - command_name); - else - result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name); - result.SetStatus (eReturnStatusFailed); - } - else - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - } + bool DoExecute(Args &args, CommandReturnObject &result) override { + CommandObject::CommandMap::iterator pos; + CommandObject *cmd_obj; + + if (args.GetArgumentCount() != 0) { + const char *command_name = args.GetArgumentAtIndex(0); + cmd_obj = m_interpreter.GetCommandObject(command_name); + if (cmd_obj) { + if (m_interpreter.CommandExists(command_name)) { + if (cmd_obj->IsRemovable()) { + result.AppendErrorWithFormat( + "'%s' is not an alias, it is a debugger command which can be " + "removed using the 'command delete' command.\n", + command_name); + } else { + result.AppendErrorWithFormat( + "'%s' is a permanent debugger command and cannot be removed.\n", + command_name); + } + result.SetStatus(eReturnStatusFailed); + } else { + if (!m_interpreter.RemoveAlias(command_name)) { + if (m_interpreter.AliasExists(command_name)) + result.AppendErrorWithFormat( + "Error occurred while attempting to unalias '%s'.\n", + command_name); else - { - result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a " - "current list of commands.\n", - command_name); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendError ("must call 'unalias' with a valid alias"); - result.SetStatus (eReturnStatusFailed); - } - - return result.Succeeded(); + result.AppendErrorWithFormat("'%s' is not an existing alias.\n", + command_name); + result.SetStatus(eReturnStatusFailed); + } else + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } + } else { + result.AppendErrorWithFormat( + "'%s' is not a known command.\nTry 'help' to see a " + "current list of commands.\n", + command_name); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendError("must call 'unalias' with a valid alias"); + result.SetStatus(eReturnStatusFailed); } + + return result.Succeeded(); + } }; #pragma mark CommandObjectCommandsDelete @@ -1014,76 +903,64 @@ protected: // CommandObjectCommandsDelete //------------------------------------------------------------------------- -class CommandObjectCommandsDelete : public CommandObjectParsed -{ +class CommandObjectCommandsDelete : public CommandObjectParsed { public: - CommandObjectCommandsDelete(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "command delete", - "Delete one or more custom commands defined by 'command regex'.", nullptr) - { - CommandArgumentEntry arg; - CommandArgumentData alias_arg; + CommandObjectCommandsDelete(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "command delete", + "Delete one or more custom commands defined by 'command regex'.", + nullptr) { + CommandArgumentEntry arg; + CommandArgumentData alias_arg; - // Define the first (and only) variant of this arg. - alias_arg.arg_type = eArgTypeCommandName; - alias_arg.arg_repetition = eArgRepeatPlain; + // Define the first (and only) variant of this arg. + alias_arg.arg_type = eArgTypeCommandName; + alias_arg.arg_repetition = eArgRepeatPlain; - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (alias_arg); + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(alias_arg); - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - } + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } - ~CommandObjectCommandsDelete() override = default; + ~CommandObjectCommandsDelete() override = default; protected: - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - CommandObject::CommandMap::iterator pos; - - if (args.GetArgumentCount() != 0) - { - const char *command_name = args.GetArgumentAtIndex(0); - if (m_interpreter.CommandExists (command_name)) - { - if (m_interpreter.RemoveCommand (command_name)) - { - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n", - command_name); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - StreamString error_msg_stream; - const bool generate_apropos = true; - const bool generate_type_lookup = false; - CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(&error_msg_stream, - command_name, - nullptr, - nullptr, - generate_apropos, - generate_type_lookup); - result.AppendErrorWithFormat ("%s", error_msg_stream.GetData()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendErrorWithFormat( - "must call '%s' with one or more valid user defined regular expression command names", - GetCommandName()); - result.SetStatus (eReturnStatusFailed); - } - - return result.Succeeded(); + bool DoExecute(Args &args, CommandReturnObject &result) override { + CommandObject::CommandMap::iterator pos; + + if (args.GetArgumentCount() != 0) { + const char *command_name = args.GetArgumentAtIndex(0); + if (m_interpreter.CommandExists(command_name)) { + if (m_interpreter.RemoveCommand(command_name)) { + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.AppendErrorWithFormat( + "'%s' is a permanent debugger command and cannot be removed.\n", + command_name); + result.SetStatus(eReturnStatusFailed); + } + } else { + StreamString error_msg_stream; + const bool generate_apropos = true; + const bool generate_type_lookup = false; + CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage( + &error_msg_stream, command_name, nullptr, nullptr, generate_apropos, + generate_type_lookup); + result.AppendErrorWithFormat("%s", error_msg_stream.GetData()); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendErrorWithFormat("must call '%s' with one or more valid user " + "defined regular expression command names", + GetCommandName()); + result.SetStatus(eReturnStatusFailed); } + + return result.Succeeded(); + } }; //------------------------------------------------------------------------- @@ -1091,1181 +968,967 @@ protected: //------------------------------------------------------------------------- #pragma mark CommandObjectCommandsAddRegex -class CommandObjectCommandsAddRegex : - public CommandObjectParsed, - public IOHandlerDelegateMultiline -{ +class CommandObjectCommandsAddRegex : public CommandObjectParsed, + public IOHandlerDelegateMultiline { public: - CommandObjectCommandsAddRegex(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "command regex", - "Define a custom command in terms of existing commands by matching regular expressions.", - "command regex <cmd-name> [s/<regex>/<subst>/ ...]"), - IOHandlerDelegateMultiline("", IOHandlerDelegate::Completion::LLDBCommand), - m_options() - { - SetHelpLong(R"( -)" "This command allows the user to create powerful regular expression commands \ + CommandObjectCommandsAddRegex(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "command regex", "Define a custom command in terms of " + "existing commands by matching " + "regular expressions.", + "command regex <cmd-name> [s/<regex>/<subst>/ ...]"), + IOHandlerDelegateMultiline("", + IOHandlerDelegate::Completion::LLDBCommand), + m_options() { + SetHelpLong( + R"( +)" + "This command allows the user to create powerful regular expression commands \ with substitutions. The regular expressions and substitutions are specified \ -using the regular expression substitution format of:" R"( +using the regular expression substitution format of:" + R"( s/<regex>/<subst>/ -)" "<regex> is a regular expression that can use parenthesis to capture regular \ +)" + "<regex> is a regular expression that can use parenthesis to capture regular \ expression input and substitute the captured matches in the output using %1 \ -for the first match, %2 for the second, and so on." R"( +for the first match, %2 for the second, and so on." + R"( -)" "The regular expressions can all be specified on the command line if more than \ +)" + "The regular expressions can all be specified on the command line if more than \ one argument is provided. If just the command name is provided on the command \ line, then the regular expressions and substitutions can be entered on separate \ -lines, followed by an empty line to terminate the command definition." R"( +lines, followed by an empty line to terminate the command definition." + R"( EXAMPLES -)" "The following example will define a regular expression command named 'f' that \ +)" + "The following example will define a regular expression command named 'f' that \ will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \ -a number follows 'f':" R"( +a number follows 'f':" + R"( - (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')" - ); - } + (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')"); + } - ~CommandObjectCommandsAddRegex() override = default; + ~CommandObjectCommandsAddRegex() override = default; protected: - void - IOHandlerActivated (IOHandler &io_handler) override - { - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); - if (output_sp) - { - output_sp->PutCString("Enter one of more sed substitution commands in the form: 's/<regex>/<subst>/'.\nTerminate the substitution list with an empty line.\n"); - output_sp->Flush(); - } + void IOHandlerActivated(IOHandler &io_handler) override { + StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + if (output_sp) { + output_sp->PutCString("Enter one of more sed substitution commands in " + "the form: 's/<regex>/<subst>/'.\nTerminate the " + "substitution list with an empty line.\n"); + output_sp->Flush(); } - - void - IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override - { - io_handler.SetIsDone(true); - if (m_regex_cmd_ap) - { - StringList lines; - if (lines.SplitIntoLines (data)) - { - const size_t num_lines = lines.GetSize(); - bool check_only = false; - for (size_t i=0; i<num_lines; ++i) - { - llvm::StringRef bytes_strref (lines[i]); - Error error = AppendRegexSubstitution (bytes_strref, check_only); - if (error.Fail()) - { - if (!m_interpreter.GetDebugger().GetCommandInterpreter().GetBatchCommandMode()) - { - StreamSP out_stream = m_interpreter.GetDebugger().GetAsyncOutputStream(); - out_stream->Printf("error: %s\n", error.AsCString()); - } - } - } - } - if (m_regex_cmd_ap->HasRegexEntries()) - { - CommandObjectSP cmd_sp (m_regex_cmd_ap.release()); - m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); + } + + void IOHandlerInputComplete(IOHandler &io_handler, + std::string &data) override { + io_handler.SetIsDone(true); + if (m_regex_cmd_ap) { + StringList lines; + if (lines.SplitIntoLines(data)) { + const size_t num_lines = lines.GetSize(); + bool check_only = false; + for (size_t i = 0; i < num_lines; ++i) { + llvm::StringRef bytes_strref(lines[i]); + Error error = AppendRegexSubstitution(bytes_strref, check_only); + if (error.Fail()) { + if (!m_interpreter.GetDebugger() + .GetCommandInterpreter() + .GetBatchCommandMode()) { + StreamSP out_stream = + m_interpreter.GetDebugger().GetAsyncOutputStream(); + out_stream->Printf("error: %s\n", error.AsCString()); } + } } + } + if (m_regex_cmd_ap->HasRegexEntries()) { + CommandObjectSP cmd_sp(m_regex_cmd_ap.release()); + m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); + } + } + } + + bool DoExecute(Args &command, CommandReturnObject &result) override { + const size_t argc = command.GetArgumentCount(); + if (argc == 0) { + result.AppendError("usage: 'command regex <command-name> " + "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n"); + result.SetStatus(eReturnStatusFailed); + } else { + Error error; + const char *name = command.GetArgumentAtIndex(0); + m_regex_cmd_ap.reset(new CommandObjectRegexCommand( + m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, + 0, true)); + + if (argc == 1) { + Debugger &debugger = m_interpreter.GetDebugger(); + bool color_prompt = debugger.GetUseColor(); + const bool multiple_lines = true; // Get multiple lines + IOHandlerSP io_handler_sp(new IOHandlerEditline( + debugger, IOHandler::Type::Other, + "lldb-regex", // Name of input reader for history + "> ", // Prompt + nullptr, // Continuation prompt + multiple_lines, color_prompt, + 0, // Don't show line numbers + *this)); + + if (io_handler_sp) { + debugger.PushIOHandler(io_handler_sp); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } + } else { + for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx) { + llvm::StringRef arg_strref(command.GetArgumentAtIndex(arg_idx)); + bool check_only = false; + error = AppendRegexSubstitution(arg_strref, check_only); + if (error.Fail()) + break; + } + + if (error.Success()) { + AddRegexCommandToInterpreter(); + } + } + if (error.Fail()) { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } } - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - const size_t argc = command.GetArgumentCount(); - if (argc == 0) - { - result.AppendError ("usage: 'command regex <command-name> [s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n"); - result.SetStatus (eReturnStatusFailed); - } - else - { - Error error; - const char *name = command.GetArgumentAtIndex(0); - m_regex_cmd_ap.reset (new CommandObjectRegexCommand (m_interpreter, - name, - m_options.GetHelp (), - m_options.GetSyntax (), - 10, - 0, - true)); - - if (argc == 1) - { - Debugger &debugger = m_interpreter.GetDebugger(); - bool color_prompt = debugger.GetUseColor(); - const bool multiple_lines = true; // Get multiple lines - IOHandlerSP io_handler_sp(new IOHandlerEditline(debugger, - IOHandler::Type::Other, - "lldb-regex", // Name of input reader for history - "> ", // Prompt - nullptr, // Continuation prompt - multiple_lines, - color_prompt, - 0, // Don't show line numbers - *this)); - - if (io_handler_sp) - { - debugger.PushIOHandler(io_handler_sp); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - } - else - { - for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx) - { - llvm::StringRef arg_strref (command.GetArgumentAtIndex(arg_idx)); - bool check_only = false; - error = AppendRegexSubstitution (arg_strref, check_only); - if (error.Fail()) - break; - } - - if (error.Success()) - { - AddRegexCommandToInterpreter(); - } - } - if (error.Fail()) - { - result.AppendError (error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } + return result.Succeeded(); + } + + Error AppendRegexSubstitution(const llvm::StringRef ®ex_sed, + bool check_only) { + Error error; - return result.Succeeded(); + if (!m_regex_cmd_ap) { + error.SetErrorStringWithFormat( + "invalid regular expression command object for: '%.*s'", + (int)regex_sed.size(), regex_sed.data()); + return error; } - - Error - AppendRegexSubstitution (const llvm::StringRef ®ex_sed, bool check_only) - { - Error error; - - if (!m_regex_cmd_ap) - { - error.SetErrorStringWithFormat("invalid regular expression command object for: '%.*s'", - (int)regex_sed.size(), - regex_sed.data()); - return error; - } - - size_t regex_sed_size = regex_sed.size(); - - if (regex_sed_size <= 1) - { - error.SetErrorStringWithFormat("regular expression substitution string is too short: '%.*s'", - (int)regex_sed.size(), - regex_sed.data()); - return error; - } - if (regex_sed[0] != 's') - { - error.SetErrorStringWithFormat("regular expression substitution string doesn't start with 's': '%.*s'", - (int)regex_sed.size(), - regex_sed.data()); - return error; - } - const size_t first_separator_char_pos = 1; - // use the char that follows 's' as the regex separator character - // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|" - const char separator_char = regex_sed[first_separator_char_pos]; - const size_t second_separator_char_pos = regex_sed.find (separator_char, first_separator_char_pos + 1); - - if (second_separator_char_pos == std::string::npos) - { - error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s' in '%.*s'", - separator_char, - (int)(regex_sed.size() - first_separator_char_pos - 1), - regex_sed.data() + (first_separator_char_pos + 1), - (int)regex_sed.size(), - regex_sed.data()); - return error; - } + size_t regex_sed_size = regex_sed.size(); - const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1); - - if (third_separator_char_pos == std::string::npos) - { - error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s' in '%.*s'", - separator_char, - (int)(regex_sed.size() - second_separator_char_pos - 1), - regex_sed.data() + (second_separator_char_pos + 1), - (int)regex_sed.size(), - regex_sed.data()); - return error; - } + if (regex_sed_size <= 1) { + error.SetErrorStringWithFormat( + "regular expression substitution string is too short: '%.*s'", + (int)regex_sed.size(), regex_sed.data()); + return error; + } - if (third_separator_char_pos != regex_sed_size - 1) - { - // Make sure that everything that follows the last regex - // separator char - if (regex_sed.find_first_not_of("\t\n\v\f\r ", third_separator_char_pos + 1) != std::string::npos) - { - error.SetErrorStringWithFormat("extra data found after the '%.*s' regular expression substitution string: '%.*s'", - (int)third_separator_char_pos + 1, - regex_sed.data(), - (int)(regex_sed.size() - third_separator_char_pos - 1), - regex_sed.data() + (third_separator_char_pos + 1)); - return error; - } - } - else if (first_separator_char_pos + 1 == second_separator_char_pos) - { - error.SetErrorStringWithFormat("<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", - separator_char, - separator_char, - separator_char, - (int)regex_sed.size(), - regex_sed.data()); - return error; - } - else if (second_separator_char_pos + 1 == third_separator_char_pos) - { - error.SetErrorStringWithFormat("<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", - separator_char, - separator_char, - separator_char, - (int)regex_sed.size(), - regex_sed.data()); - return error; - } + if (regex_sed[0] != 's') { + error.SetErrorStringWithFormat("regular expression substitution string " + "doesn't start with 's': '%.*s'", + (int)regex_sed.size(), regex_sed.data()); + return error; + } + const size_t first_separator_char_pos = 1; + // use the char that follows 's' as the regex separator character + // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|" + const char separator_char = regex_sed[first_separator_char_pos]; + const size_t second_separator_char_pos = + regex_sed.find(separator_char, first_separator_char_pos + 1); + + if (second_separator_char_pos == std::string::npos) { + error.SetErrorStringWithFormat( + "missing second '%c' separator char after '%.*s' in '%.*s'", + separator_char, + (int)(regex_sed.size() - first_separator_char_pos - 1), + regex_sed.data() + (first_separator_char_pos + 1), + (int)regex_sed.size(), regex_sed.data()); + return error; + } - 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)); - m_regex_cmd_ap->AddRegexCommand (regex.c_str(), - subst.c_str()); - } + const size_t third_separator_char_pos = + regex_sed.find(separator_char, second_separator_char_pos + 1); + + if (third_separator_char_pos == std::string::npos) { + error.SetErrorStringWithFormat( + "missing third '%c' separator char after '%.*s' in '%.*s'", + separator_char, + (int)(regex_sed.size() - second_separator_char_pos - 1), + regex_sed.data() + (second_separator_char_pos + 1), + (int)regex_sed.size(), regex_sed.data()); + return error; + } + + if (third_separator_char_pos != regex_sed_size - 1) { + // Make sure that everything that follows the last regex + // separator char + if (regex_sed.find_first_not_of("\t\n\v\f\r ", + third_separator_char_pos + 1) != + std::string::npos) { + error.SetErrorStringWithFormat( + "extra data found after the '%.*s' regular expression substitution " + "string: '%.*s'", + (int)third_separator_char_pos + 1, regex_sed.data(), + (int)(regex_sed.size() - third_separator_char_pos - 1), + regex_sed.data() + (third_separator_char_pos + 1)); return error; + } + } else if (first_separator_char_pos + 1 == second_separator_char_pos) { + error.SetErrorStringWithFormat( + "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", + separator_char, separator_char, separator_char, (int)regex_sed.size(), + regex_sed.data()); + return error; + } else if (second_separator_char_pos + 1 == third_separator_char_pos) { + error.SetErrorStringWithFormat( + "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", + separator_char, separator_char, separator_char, (int)regex_sed.size(), + regex_sed.data()); + return error; } - - void - AddRegexCommandToInterpreter() - { - if (m_regex_cmd_ap) - { - if (m_regex_cmd_ap->HasRegexEntries()) - { - CommandObjectSP cmd_sp (m_regex_cmd_ap.release()); - m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); - } - } + + 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)); + m_regex_cmd_ap->AddRegexCommand(regex.c_str(), subst.c_str()); + } + return error; + } + + void AddRegexCommandToInterpreter() { + if (m_regex_cmd_ap) { + if (m_regex_cmd_ap->HasRegexEntries()) { + CommandObjectSP cmd_sp(m_regex_cmd_ap.release()); + m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); + } } + } private: - std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap; - - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - } - - ~CommandOptions() override = default; - - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'h': - m_help.assign (option_arg); - break; - case 's': - m_syntax.assign (option_arg); - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting (ExecutionContext *execution_context) override - { - m_help.clear(); - m_syntax.clear(); - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - const char * - GetHelp() - { - return (m_help.empty() ? nullptr : m_help.c_str()); - } - - const char * - GetSyntax () - { - return (m_syntax.empty() ? nullptr : m_syntax.c_str()); - } - - protected: - // Instance variables to hold the values for command options. - - std::string m_help; - std::string m_syntax; - }; - - Options * - GetOptions () override - { - return &m_options; - } - - CommandOptions m_options; + std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap; + + class CommandOptions : public Options { + public: + CommandOptions() : Options() {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'h': + m_help.assign(option_arg); + break; + case 's': + m_syntax.assign(option_arg); + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; + } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_help.clear(); + m_syntax.clear(); + } + + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + const char *GetHelp() { + return (m_help.empty() ? nullptr : m_help.c_str()); + } + + const char *GetSyntax() { + return (m_syntax.empty() ? nullptr : m_syntax.c_str()); + } + + protected: + // Instance variables to hold the values for command options. + + std::string m_help; + std::string m_syntax; + }; + + Options *GetOptions() override { return &m_options; } + + CommandOptions m_options; }; OptionDefinition -CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The help text to display for this command."}, {LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; -class CommandObjectPythonFunction : public CommandObjectRaw -{ +class CommandObjectPythonFunction : public CommandObjectRaw { public: - CommandObjectPythonFunction (CommandInterpreter &interpreter, - std::string name, - std::string funct, - std::string help, - ScriptedCommandSynchronicity synch) : - CommandObjectRaw(interpreter, - name.c_str(), - nullptr, - nullptr), - m_function_name(funct), - m_synchro(synch), - m_fetched_help_long(false) - { - if (!help.empty()) - SetHelp(help.c_str()); - else - { - StreamString stream; - stream.Printf("For more information run 'help %s'",name.c_str()); - SetHelp(stream.GetData()); - } + CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name, + std::string funct, std::string help, + ScriptedCommandSynchronicity synch) + : CommandObjectRaw(interpreter, name.c_str(), nullptr, nullptr), + m_function_name(funct), m_synchro(synch), m_fetched_help_long(false) { + if (!help.empty()) + SetHelp(help.c_str()); + else { + StreamString stream; + stream.Printf("For more information run 'help %s'", name.c_str()); + SetHelp(stream.GetData()); } + } - ~CommandObjectPythonFunction() override = default; + ~CommandObjectPythonFunction() override = default; - bool - IsRemovable () const override - { - return true; - } + bool IsRemovable() const override { return true; } - const std::string& - GetFunctionName () - { - return m_function_name; - } + const std::string &GetFunctionName() { return m_function_name; } - ScriptedCommandSynchronicity - GetSynchronicity () - { - return m_synchro; - } - - const char * - GetHelpLong () override - { - if (!m_fetched_help_long) - { - ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); - if (scripter) - { - std::string docstring; - m_fetched_help_long = scripter->GetDocumentationForItem(m_function_name.c_str(),docstring); - if (!docstring.empty()) - SetHelpLong(docstring.c_str()); - } - } - return CommandObjectRaw::GetHelpLong(); + ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } + + const char *GetHelpLong() override { + if (!m_fetched_help_long) { + ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter(); + if (scripter) { + std::string docstring; + m_fetched_help_long = scripter->GetDocumentationForItem( + m_function_name.c_str(), docstring); + if (!docstring.empty()) + SetHelpLong(docstring.c_str()); + } } - + return CommandObjectRaw::GetHelpLong(); + } + protected: - bool - DoExecute (const char *raw_command_line, CommandReturnObject &result) override - { - ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); - - Error error; - - result.SetStatus(eReturnStatusInvalid); - - if (!scripter || !scripter->RunScriptBasedCommand(m_function_name.c_str(), - raw_command_line, - m_synchro, - result, - error, - m_exe_ctx)) - { - result.AppendError(error.AsCString()); - result.SetStatus(eReturnStatusFailed); - } + bool DoExecute(const char *raw_command_line, + CommandReturnObject &result) override { + ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter(); + + Error error; + + result.SetStatus(eReturnStatusInvalid); + + if (!scripter || + !scripter->RunScriptBasedCommand(m_function_name.c_str(), + raw_command_line, m_synchro, result, + error, m_exe_ctx)) { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } else { + // Don't change the status if the command already set it... + if (result.GetStatus() == eReturnStatusInvalid) { + if (result.GetOutputData() == nullptr || + result.GetOutputData()[0] == '\0') + result.SetStatus(eReturnStatusSuccessFinishNoResult); else - { - // Don't change the status if the command already set it... - if (result.GetStatus() == eReturnStatusInvalid) - { - if (result.GetOutputData() == nullptr || result.GetOutputData()[0] == '\0') - result.SetStatus(eReturnStatusSuccessFinishNoResult); - else - result.SetStatus(eReturnStatusSuccessFinishResult); - } - } - - return result.Succeeded(); + result.SetStatus(eReturnStatusSuccessFinishResult); + } } + return result.Succeeded(); + } + private: - std::string m_function_name; - ScriptedCommandSynchronicity m_synchro; - bool m_fetched_help_long; + std::string m_function_name; + ScriptedCommandSynchronicity m_synchro; + bool m_fetched_help_long; }; -class CommandObjectScriptingObject : public CommandObjectRaw -{ +class CommandObjectScriptingObject : public CommandObjectRaw { public: - CommandObjectScriptingObject (CommandInterpreter &interpreter, - std::string name, - StructuredData::GenericSP cmd_obj_sp, - ScriptedCommandSynchronicity synch) : - CommandObjectRaw(interpreter, - name.c_str(), - nullptr, - nullptr), - m_cmd_obj_sp(cmd_obj_sp), - m_synchro(synch), - m_fetched_help_short(false), - m_fetched_help_long(false) - { - StreamString stream; - stream.Printf("For more information run 'help %s'",name.c_str()); - SetHelp(stream.GetData()); - if (ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter()) - GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp)); + CommandObjectScriptingObject(CommandInterpreter &interpreter, + std::string name, + StructuredData::GenericSP cmd_obj_sp, + ScriptedCommandSynchronicity synch) + : CommandObjectRaw(interpreter, name.c_str(), nullptr, nullptr), + m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch), m_fetched_help_short(false), + m_fetched_help_long(false) { + StreamString stream; + stream.Printf("For more information run 'help %s'", name.c_str()); + SetHelp(stream.GetData()); + if (ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter()) + GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp)); + } + + ~CommandObjectScriptingObject() override = default; + + bool IsRemovable() const override { return true; } + + StructuredData::GenericSP GetImplementingObject() { return m_cmd_obj_sp; } + + ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } + + const char *GetHelp() override { + if (!m_fetched_help_short) { + ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter(); + if (scripter) { + std::string docstring; + m_fetched_help_short = + scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring); + if (!docstring.empty()) + SetHelp(docstring.c_str()); + } } - - ~CommandObjectScriptingObject() override = default; - - bool - IsRemovable () const override - { - return true; - } - - StructuredData::GenericSP - GetImplementingObject () - { - return m_cmd_obj_sp; - } - - ScriptedCommandSynchronicity - GetSynchronicity () - { - return m_synchro; + return CommandObjectRaw::GetHelp(); + } + + const char *GetHelpLong() override { + if (!m_fetched_help_long) { + ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter(); + if (scripter) { + std::string docstring; + m_fetched_help_long = + scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring); + if (!docstring.empty()) + SetHelpLong(docstring.c_str()); + } } + return CommandObjectRaw::GetHelpLong(); + } - const char * - GetHelp () override - { - if (!m_fetched_help_short) - { - ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); - if (scripter) - { - std::string docstring; - m_fetched_help_short = scripter->GetShortHelpForCommandObject(m_cmd_obj_sp,docstring); - if (!docstring.empty()) - SetHelp(docstring.c_str()); - } - } - return CommandObjectRaw::GetHelp(); - } - - const char * - GetHelpLong () override - { - if (!m_fetched_help_long) - { - ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); - if (scripter) - { - std::string docstring; - m_fetched_help_long = scripter->GetLongHelpForCommandObject(m_cmd_obj_sp,docstring); - if (!docstring.empty()) - SetHelpLong(docstring.c_str()); - } - } - return CommandObjectRaw::GetHelpLong(); - } - protected: - bool - DoExecute (const char *raw_command_line, CommandReturnObject &result) override - { - ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); - - Error error; - - result.SetStatus(eReturnStatusInvalid); - - if (!scripter || !scripter->RunScriptBasedCommand(m_cmd_obj_sp, - raw_command_line, - m_synchro, - result, - error, - m_exe_ctx)) - { - result.AppendError(error.AsCString()); - result.SetStatus(eReturnStatusFailed); - } + bool DoExecute(const char *raw_command_line, + CommandReturnObject &result) override { + ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter(); + + Error error; + + result.SetStatus(eReturnStatusInvalid); + + if (!scripter || + !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line, + m_synchro, result, error, m_exe_ctx)) { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } else { + // Don't change the status if the command already set it... + if (result.GetStatus() == eReturnStatusInvalid) { + if (result.GetOutputData() == nullptr || + result.GetOutputData()[0] == '\0') + result.SetStatus(eReturnStatusSuccessFinishNoResult); else - { - // Don't change the status if the command already set it... - if (result.GetStatus() == eReturnStatusInvalid) - { - if (result.GetOutputData() == nullptr || result.GetOutputData()[0] == '\0') - result.SetStatus(eReturnStatusSuccessFinishNoResult); - else - result.SetStatus(eReturnStatusSuccessFinishResult); - } - } - - return result.Succeeded(); + result.SetStatus(eReturnStatusSuccessFinishResult); + } } + return result.Succeeded(); + } + private: - StructuredData::GenericSP m_cmd_obj_sp; - ScriptedCommandSynchronicity m_synchro; - bool m_fetched_help_short: 1; - bool m_fetched_help_long: 1; + StructuredData::GenericSP m_cmd_obj_sp; + ScriptedCommandSynchronicity m_synchro; + bool m_fetched_help_short : 1; + bool m_fetched_help_long : 1; }; //------------------------------------------------------------------------- // CommandObjectCommandsScriptImport //------------------------------------------------------------------------- -class CommandObjectCommandsScriptImport : public CommandObjectParsed -{ +class CommandObjectCommandsScriptImport : public CommandObjectParsed { public: - CommandObjectCommandsScriptImport (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "command script import", - "Import a scripting module in LLDB.", - nullptr), - m_options() - { - CommandArgumentEntry arg1; - CommandArgumentData cmd_arg; - - // Define the first (and only) variant of this arg. - cmd_arg.arg_type = eArgTypeFilename; - cmd_arg.arg_repetition = eArgRepeatPlus; - - // There is only one variant this argument could be; put it into the argument entry. - arg1.push_back (cmd_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg1); + CommandObjectCommandsScriptImport(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "command script import", + "Import a scripting module in LLDB.", nullptr), + m_options() { + CommandArgumentEntry arg1; + CommandArgumentData cmd_arg; + + // Define the first (and only) variant of this arg. + cmd_arg.arg_type = eArgTypeFilename; + cmd_arg.arg_repetition = eArgRepeatPlus; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg1.push_back(cmd_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg1); + } + + ~CommandObjectCommandsScriptImport() override = default; + + int HandleArgumentCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, int max_return_elements, + bool &word_complete, + StringList &matches) override { + std::string completion_str(input.GetArgumentAtIndex(cursor_index)); + completion_str.erase(cursor_char_position); + + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, + completion_str.c_str(), match_start_point, max_return_elements, nullptr, + word_complete, matches); + return matches.GetSize(); + } + + Options *GetOptions() override { return &m_options; } + +protected: + class CommandOptions : public Options { + public: + CommandOptions() : Options() {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'r': + m_allow_reload = true; + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; } - ~CommandObjectCommandsScriptImport() override = default; - - int - HandleArgumentCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - OptionElementVector &opt_element_vector, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) override - { - std::string completion_str (input.GetArgumentAtIndex(cursor_index)); - completion_str.erase (cursor_char_position); - - CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(), - CommandCompletions::eDiskFileCompletion, - completion_str.c_str(), - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - return matches.GetSize(); + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_allow_reload = true; } - - Options * - GetOptions () override - { - return &m_options; + + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + bool m_allow_reload; + }; + + bool DoExecute(Args &command, CommandReturnObject &result) override { + if (m_interpreter.GetDebugger().GetScriptLanguage() != + lldb::eScriptLanguagePython) { + result.AppendError("only scripting language supported for module " + "importing is currently Python"); + result.SetStatus(eReturnStatusFailed); + return false; } -protected: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - } + size_t argc = command.GetArgumentCount(); + if (0 == argc) { + result.AppendError("command script import needs one or more arguments"); + result.SetStatus(eReturnStatusFailed); + return false; + } - ~CommandOptions() override = default; - - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'r': - m_allow_reload = true; - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_allow_reload = true; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - bool m_allow_reload; - }; - - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) - { - result.AppendError ("only scripting language supported for module importing is currently Python"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - size_t argc = command.GetArgumentCount(); - if (0 == argc) - { - result.AppendError("command script import needs one or more arguments"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - for (size_t i = 0; - i < argc; - i++) - { - std::string path = command.GetArgumentAtIndex(i); - Error error; - - const bool init_session = true; - // FIXME: this is necessary because CommandObject::CheckRequirements() assumes that - // commands won't ever be recursively invoked, but it's actually possible to craft - // a Python script that does other "command script imports" in __lldb_init_module - // the real fix is to have recursive commands possible with a CommandInvocation object - // separate from the CommandObject itself, so that recursive command invocations - // won't stomp on each other (wrt to execution contents, options, and more) - m_exe_ctx.Clear(); - if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(path.c_str(), - m_options.m_allow_reload, - init_session, - error)) - { - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendErrorWithFormat("module importing failed: %s", error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - - return result.Succeeded(); + for (size_t i = 0; i < argc; i++) { + std::string path = command.GetArgumentAtIndex(i); + Error error; + + const bool init_session = true; + // FIXME: this is necessary because CommandObject::CheckRequirements() + // assumes that + // commands won't ever be recursively invoked, but it's actually possible + // to craft + // a Python script that does other "command script imports" in + // __lldb_init_module + // the real fix is to have recursive commands possible with a + // CommandInvocation object + // separate from the CommandObject itself, so that recursive command + // invocations + // won't stomp on each other (wrt to execution contents, options, and + // more) + m_exe_ctx.Clear(); + if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule( + path.c_str(), m_options.m_allow_reload, init_session, error)) { + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.AppendErrorWithFormat("module importing failed: %s", + error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } } - - CommandOptions m_options; + + return result.Succeeded(); + } + + CommandOptions m_options; }; OptionDefinition -CommandObjectCommandsScriptImport::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectCommandsScriptImport::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "allow-reload", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow the script to be loaded even if it was already loaded before. This argument exists for backwards compatibility, but reloading is always allowed, whether you specify it or not."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- // CommandObjectCommandsScriptAdd //------------------------------------------------------------------------- -class CommandObjectCommandsScriptAdd : - public CommandObjectParsed, - public IOHandlerDelegateMultiline -{ +class CommandObjectCommandsScriptAdd : public CommandObjectParsed, + public IOHandlerDelegateMultiline { public: - CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "command script add", + CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "command script add", "Add a scripted function as an LLDB command.", nullptr), - IOHandlerDelegateMultiline ("DONE"), - m_options() - { - CommandArgumentEntry arg1; - CommandArgumentData cmd_arg; - - // Define the first (and only) variant of this arg. - cmd_arg.arg_type = eArgTypeCommandName; - cmd_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg1.push_back (cmd_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg1); - } + IOHandlerDelegateMultiline("DONE"), m_options() { + CommandArgumentEntry arg1; + CommandArgumentData cmd_arg; - ~CommandObjectCommandsScriptAdd() override = default; + // Define the first (and only) variant of this arg. + cmd_arg.arg_type = eArgTypeCommandName; + cmd_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg1.push_back(cmd_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg1); + } + + ~CommandObjectCommandsScriptAdd() override = default; + + Options *GetOptions() override { return &m_options; } - Options * - GetOptions () override - { - return &m_options; - } - protected: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options(), - m_class_name(), - m_funct_name(), - m_short_help(), - m_synchronicity(eScriptedCommandSynchronicitySynchronous) - { - } + class CommandOptions : public Options { + public: + CommandOptions() + : Options(), m_class_name(), m_funct_name(), m_short_help(), + m_synchronicity(eScriptedCommandSynchronicitySynchronous) {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'f': + if (option_arg) + m_funct_name.assign(option_arg); + break; + case 'c': + if (option_arg) + m_class_name.assign(option_arg); + break; + case 'h': + if (option_arg) + m_short_help.assign(option_arg); + break; + case 's': + m_synchronicity = + (ScriptedCommandSynchronicity)Args::StringToOptionEnum( + option_arg, g_option_table[option_idx].enum_values, 0, error); + if (!error.Success()) + error.SetErrorStringWithFormat( + "unrecognized value for synchronicity '%s'", option_arg); + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; + } - ~CommandOptions() override = default; - - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'f': - if (option_arg) - m_funct_name.assign(option_arg); - break; - case 'c': - if (option_arg) - m_class_name.assign(option_arg); - break; - case 'h': - if (option_arg) - m_short_help.assign(option_arg); - break; - case 's': - m_synchronicity = (ScriptedCommandSynchronicity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error); - if (!error.Success()) - error.SetErrorStringWithFormat ("unrecognized value for synchronicity '%s'", option_arg); - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_class_name.clear(); - m_funct_name.clear(); - m_short_help.clear(); - m_synchronicity = eScriptedCommandSynchronicitySynchronous; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - std::string m_class_name; - std::string m_funct_name; - std::string m_short_help; - ScriptedCommandSynchronicity m_synchronicity; - }; - - void - IOHandlerActivated (IOHandler &io_handler) override - { - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); - if (output_sp) - { - output_sp->PutCString(g_python_command_instructions); - output_sp->Flush(); - } + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_class_name.clear(); + m_funct_name.clear(); + m_short_help.clear(); + m_synchronicity = eScriptedCommandSynchronicitySynchronous; } - - void - IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override - { - StreamFileSP error_sp = io_handler.GetErrorStreamFile(); - - ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); - if (interpreter) - { - - StringList lines; - lines.SplitIntoLines(data); - if (lines.GetSize() > 0) - { - std::string funct_name_str; - if (interpreter->GenerateScriptAliasFunction (lines, funct_name_str)) - { - if (funct_name_str.empty()) - { - error_sp->Printf ("error: unable to obtain a function name, didn't add python command.\n"); - error_sp->Flush(); - } - else - { - // everything should be fine now, let's add this alias - - CommandObjectSP command_obj_sp(new CommandObjectPythonFunction (m_interpreter, - m_cmd_name, - funct_name_str.c_str(), - m_short_help, - m_synchronicity)); - - if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, true)) - { - error_sp->Printf ("error: unable to add selected command, didn't add python command.\n"); - error_sp->Flush(); - } - } - } - else - { - error_sp->Printf ("error: unable to create function, didn't add python command.\n"); - error_sp->Flush(); - } - } - else - { - error_sp->Printf ("error: empty function, didn't add python command.\n"); - error_sp->Flush(); - } - } - else - { - error_sp->Printf ("error: script interpreter missing, didn't add python command.\n"); - error_sp->Flush(); - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; - io_handler.SetIsDone(true); + // Instance variables to hold the values for command options. + + std::string m_class_name; + std::string m_funct_name; + std::string m_short_help; + ScriptedCommandSynchronicity m_synchronicity; + }; + + void IOHandlerActivated(IOHandler &io_handler) override { + StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + if (output_sp) { + output_sp->PutCString(g_python_command_instructions); + output_sp->Flush(); } + } + + void IOHandlerInputComplete(IOHandler &io_handler, + std::string &data) override { + StreamFileSP error_sp = io_handler.GetErrorStreamFile(); + + ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); + if (interpreter) { + + StringList lines; + lines.SplitIntoLines(data); + if (lines.GetSize() > 0) { + std::string funct_name_str; + if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) { + if (funct_name_str.empty()) { + error_sp->Printf("error: unable to obtain a function name, didn't " + "add python command.\n"); + error_sp->Flush(); + } else { + // everything should be fine now, let's add this alias + + CommandObjectSP command_obj_sp(new CommandObjectPythonFunction( + m_interpreter, m_cmd_name, funct_name_str.c_str(), m_short_help, + m_synchronicity)); + + if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, + true)) { + error_sp->Printf("error: unable to add selected command, didn't " + "add python command.\n"); + error_sp->Flush(); + } + } + } else { + error_sp->Printf( + "error: unable to create function, didn't add python command.\n"); + error_sp->Flush(); + } + } else { + error_sp->Printf("error: empty function, didn't add python command.\n"); + error_sp->Flush(); + } + } else { + error_sp->Printf( + "error: script interpreter missing, didn't add python command.\n"); + error_sp->Flush(); + } + + io_handler.SetIsDone(true); + } protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) - { - result.AppendError ("only scripting language supported for scripted commands is currently Python"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - size_t argc = command.GetArgumentCount(); - - if (argc != 1) - { - result.AppendError ("'command script add' requires one argument"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - // Store the options in case we get multi-line input - m_cmd_name = command.GetArgumentAtIndex(0); - m_short_help.assign(m_options.m_short_help); - m_synchronicity = m_options.m_synchronicity; - - if (m_options.m_class_name.empty()) - { - if (m_options.m_funct_name.empty()) - { - m_interpreter.GetPythonCommandsFromIOHandler(" ", // Prompt - *this, // IOHandlerDelegate - true, // Run IOHandler in async mode - nullptr); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions - } - else - { - CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter, - m_cmd_name, - m_options.m_funct_name, - m_options.m_short_help, - m_synchronicity)); - if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) - { - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendError("cannot add command"); - result.SetStatus (eReturnStatusFailed); - } - } - } - else - { - ScriptInterpreter *interpreter = GetCommandInterpreter().GetScriptInterpreter(); - if (!interpreter) - { - result.AppendError("cannot find ScriptInterpreter"); - result.SetStatus(eReturnStatusFailed); - return false; - } - - auto cmd_obj_sp = interpreter->CreateScriptCommandObject(m_options.m_class_name.c_str()); - if (!cmd_obj_sp) - { - result.AppendError("cannot create helper object"); - result.SetStatus(eReturnStatusFailed); - return false; - } - - CommandObjectSP new_cmd(new CommandObjectScriptingObject(m_interpreter, - m_cmd_name, - cmd_obj_sp, - m_synchronicity)); - if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) - { - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendError("cannot add command"); - result.SetStatus (eReturnStatusFailed); - } - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + if (m_interpreter.GetDebugger().GetScriptLanguage() != + lldb::eScriptLanguagePython) { + result.AppendError("only scripting language supported for scripted " + "commands is currently Python"); + result.SetStatus(eReturnStatusFailed); + return false; + } - return result.Succeeded(); + size_t argc = command.GetArgumentCount(); + + if (argc != 1) { + result.AppendError("'command script add' requires one argument"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + // Store the options in case we get multi-line input + m_cmd_name = command.GetArgumentAtIndex(0); + m_short_help.assign(m_options.m_short_help); + m_synchronicity = m_options.m_synchronicity; + + if (m_options.m_class_name.empty()) { + if (m_options.m_funct_name.empty()) { + m_interpreter.GetPythonCommandsFromIOHandler( + " ", // Prompt + *this, // IOHandlerDelegate + true, // Run IOHandler in async mode + nullptr); // Baton for the "io_handler" that will be passed back + // into our IOHandlerDelegate functions + } else { + CommandObjectSP new_cmd(new CommandObjectPythonFunction( + m_interpreter, m_cmd_name, m_options.m_funct_name, + m_options.m_short_help, m_synchronicity)); + if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) { + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.AppendError("cannot add command"); + result.SetStatus(eReturnStatusFailed); + } + } + } else { + ScriptInterpreter *interpreter = + GetCommandInterpreter().GetScriptInterpreter(); + if (!interpreter) { + result.AppendError("cannot find ScriptInterpreter"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + auto cmd_obj_sp = interpreter->CreateScriptCommandObject( + m_options.m_class_name.c_str()); + if (!cmd_obj_sp) { + result.AppendError("cannot create helper object"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + CommandObjectSP new_cmd(new CommandObjectScriptingObject( + m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity)); + if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) { + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.AppendError("cannot add command"); + result.SetStatus(eReturnStatusFailed); + } } - - CommandOptions m_options; - std::string m_cmd_name; - std::string m_short_help; - ScriptedCommandSynchronicity m_synchronicity; -}; -static OptionEnumValueElement g_script_synchro_type[] = -{ - { eScriptedCommandSynchronicitySynchronous, "synchronous", "Run synchronous"}, - { eScriptedCommandSynchronicityAsynchronous, "asynchronous", "Run asynchronous"}, - { eScriptedCommandSynchronicityCurrentValue, "current", "Do not alter current setting"}, - { 0, nullptr, nullptr } + return result.Succeeded(); + } + + CommandOptions m_options; + std::string m_cmd_name; + std::string m_short_help; + ScriptedCommandSynchronicity m_synchronicity; }; +static OptionEnumValueElement g_script_synchro_type[] = { + {eScriptedCommandSynchronicitySynchronous, "synchronous", + "Run synchronous"}, + {eScriptedCommandSynchronicityAsynchronous, "asynchronous", + "Run asynchronous"}, + {eScriptedCommandSynchronicityCurrentValue, "current", + "Do not alter current setting"}, + {0, nullptr, nullptr}}; + OptionDefinition -CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name."}, {LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name."}, {LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "The help text to display for this command."}, {LLDB_OPT_SET_ALL, false, "synchronicity", 's', OptionParser::eRequiredArgument, nullptr, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- // CommandObjectCommandsScriptList //------------------------------------------------------------------------- -class CommandObjectCommandsScriptList : public CommandObjectParsed -{ +class CommandObjectCommandsScriptList : public CommandObjectParsed { public: - CommandObjectCommandsScriptList(CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "command script list", - "List defined scripted commands.", - nullptr) - { - } + CommandObjectCommandsScriptList(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "command script list", + "List defined scripted commands.", nullptr) {} - ~CommandObjectCommandsScriptList() override = default; + ~CommandObjectCommandsScriptList() override = default; - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - m_interpreter.GetHelp(result, - CommandInterpreter::eCommandTypesUserDef); - - result.SetStatus (eReturnStatusSuccessFinishResult); - - return true; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef); + + result.SetStatus(eReturnStatusSuccessFinishResult); + + return true; + } }; //------------------------------------------------------------------------- // CommandObjectCommandsScriptClear //------------------------------------------------------------------------- -class CommandObjectCommandsScriptClear : public CommandObjectParsed -{ +class CommandObjectCommandsScriptClear : public CommandObjectParsed { public: - CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "command script clear", - "Delete all scripted commands.", - nullptr) - { - } + CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "command script clear", + "Delete all scripted commands.", nullptr) {} - ~CommandObjectCommandsScriptClear() override = default; + ~CommandObjectCommandsScriptClear() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - m_interpreter.RemoveAllUser(); - - result.SetStatus (eReturnStatusSuccessFinishResult); - - return true; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + m_interpreter.RemoveAllUser(); + + result.SetStatus(eReturnStatusSuccessFinishResult); + + return true; + } }; //------------------------------------------------------------------------- // CommandObjectCommandsScriptDelete //------------------------------------------------------------------------- -class CommandObjectCommandsScriptDelete : public CommandObjectParsed -{ +class CommandObjectCommandsScriptDelete : public CommandObjectParsed { public: - CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "command script delete", - "Delete a scripted command.", - nullptr) - { - CommandArgumentEntry arg1; - CommandArgumentData cmd_arg; - - // Define the first (and only) variant of this arg. - cmd_arg.arg_type = eArgTypeCommandName; - cmd_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg1.push_back (cmd_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg1); - } + CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "command script delete", + "Delete a scripted command.", nullptr) { + CommandArgumentEntry arg1; + CommandArgumentData cmd_arg; + + // Define the first (and only) variant of this arg. + cmd_arg.arg_type = eArgTypeCommandName; + cmd_arg.arg_repetition = eArgRepeatPlain; - ~CommandObjectCommandsScriptDelete() override = default; + // There is only one variant this argument could be; put it into the + // argument entry. + arg1.push_back(cmd_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg1); + } + + ~CommandObjectCommandsScriptDelete() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - - size_t argc = command.GetArgumentCount(); - - if (argc != 1) - { - result.AppendError ("'command script delete' requires one argument"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - const char* cmd_name = command.GetArgumentAtIndex(0); - - if (cmd_name && *cmd_name && m_interpreter.HasUserCommands() && m_interpreter.UserCommandExists(cmd_name)) - { - m_interpreter.RemoveUser(cmd_name); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendErrorWithFormat ("command %s not found", cmd_name); - result.SetStatus (eReturnStatusFailed); - } - - return result.Succeeded(); + bool DoExecute(Args &command, CommandReturnObject &result) override { + + size_t argc = command.GetArgumentCount(); + + if (argc != 1) { + result.AppendError("'command script delete' requires one argument"); + result.SetStatus(eReturnStatusFailed); + return false; } + + const char *cmd_name = command.GetArgumentAtIndex(0); + + if (cmd_name && *cmd_name && m_interpreter.HasUserCommands() && + m_interpreter.UserCommandExists(cmd_name)) { + m_interpreter.RemoveUser(cmd_name); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat("command %s not found", cmd_name); + result.SetStatus(eReturnStatusFailed); + } + + return result.Succeeded(); + } }; #pragma mark CommandObjectMultiwordCommandsScript @@ -2274,22 +1937,30 @@ protected: // CommandObjectMultiwordCommandsScript //------------------------------------------------------------------------- -class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword -{ +class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword { public: - CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "command script", - "Commands for managing custom commands implemented by interpreter scripts.", - "command script <subcommand> [<subcommand-options>]") - { - LoadSubCommand ("add", CommandObjectSP (new CommandObjectCommandsScriptAdd (interpreter))); - LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter))); - LoadSubCommand ("clear", CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter))); - LoadSubCommand ("list", CommandObjectSP (new CommandObjectCommandsScriptList (interpreter))); - LoadSubCommand ("import", CommandObjectSP (new CommandObjectCommandsScriptImport (interpreter))); - } - - ~CommandObjectMultiwordCommandsScript() override = default; + CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "command script", "Commands for managing custom " + "commands implemented by " + "interpreter scripts.", + "command script <subcommand> [<subcommand-options>]") { + LoadSubCommand("add", CommandObjectSP( + new CommandObjectCommandsScriptAdd(interpreter))); + LoadSubCommand( + "delete", + CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter))); + LoadSubCommand( + "clear", + CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter))); + LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList( + interpreter))); + LoadSubCommand( + "import", + CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter))); + } + + ~CommandObjectMultiwordCommandsScript() override = default; }; #pragma mark CommandObjectMultiwordCommands @@ -2298,17 +1969,26 @@ public: // CommandObjectMultiwordCommands //------------------------------------------------------------------------- -CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "command", "Commands for managing custom LLDB commands.", - "command <subcommand> [<subcommand-options>]") -{ - LoadSubCommand ("source", CommandObjectSP (new CommandObjectCommandsSource (interpreter))); - LoadSubCommand ("alias", CommandObjectSP (new CommandObjectCommandsAlias (interpreter))); - LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter))); - LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsDelete (interpreter))); - LoadSubCommand ("regex", CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter))); - LoadSubCommand ("history", CommandObjectSP (new CommandObjectCommandsHistory (interpreter))); - LoadSubCommand ("script", CommandObjectSP (new CommandObjectMultiwordCommandsScript (interpreter))); +CommandObjectMultiwordCommands::CommandObjectMultiwordCommands( + CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "command", + "Commands for managing custom LLDB commands.", + "command <subcommand> [<subcommand-options>]") { + LoadSubCommand("source", + CommandObjectSP(new CommandObjectCommandsSource(interpreter))); + LoadSubCommand("alias", + CommandObjectSP(new CommandObjectCommandsAlias(interpreter))); + LoadSubCommand("unalias", CommandObjectSP( + new CommandObjectCommandsUnalias(interpreter))); + LoadSubCommand("delete", + CommandObjectSP(new CommandObjectCommandsDelete(interpreter))); + LoadSubCommand( + "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter))); + LoadSubCommand("history", CommandObjectSP( + new CommandObjectCommandsHistory(interpreter))); + LoadSubCommand( + "script", + CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter))); } CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default; diff --git a/lldb/source/Commands/CommandObjectCommands.h b/lldb/source/Commands/CommandObjectCommands.h index c12c710..a5ef777 100644 --- a/lldb/source/Commands/CommandObjectCommands.h +++ b/lldb/source/Commands/CommandObjectCommands.h @@ -1,4 +1,5 @@ -//===-- CommandObjectCommands.h -----------------------------------*- C++ -*-===// +//===-- CommandObjectCommands.h -----------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -14,9 +15,9 @@ // C++ Includes // Other libraries and framework includes // Project includes +#include "lldb/Core/STLUtils.h" #include "lldb/Interpreter/CommandObject.h" #include "lldb/Interpreter/CommandObjectMultiword.h" -#include "lldb/Core/STLUtils.h" namespace lldb_private { @@ -24,13 +25,11 @@ namespace lldb_private { // CommandObjectMultiwordCommands //------------------------------------------------------------------------- -class CommandObjectMultiwordCommands : public CommandObjectMultiword -{ +class CommandObjectMultiwordCommands : public CommandObjectMultiword { public: + CommandObjectMultiwordCommands(CommandInterpreter &interpreter); - CommandObjectMultiwordCommands (CommandInterpreter &interpreter); - - ~CommandObjectMultiwordCommands() override; + ~CommandObjectMultiwordCommands() override; }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectDisassemble.cpp b/lldb/source/Commands/CommandObjectDisassemble.cpp index 796db61..7a1291b 100644 --- a/lldb/source/Commands/CommandObjectDisassemble.cpp +++ b/lldb/source/Commands/CommandObjectDisassemble.cpp @@ -29,221 +29,191 @@ #include "lldb/Target/Target.h" #define DEFAULT_DISASM_BYTE_SIZE 32 -#define DEFAULT_DISASM_NUM_INS 4 +#define DEFAULT_DISASM_NUM_INS 4 using namespace lldb; using namespace lldb_private; -CommandObjectDisassemble::CommandOptions::CommandOptions() : - Options(), - num_lines_context(0), - num_instructions (0), - func_name(), - current_function (false), - start_addr(), - end_addr (), - at_pc (false), - frame_line (false), - plugin_name (), - flavor_string(), - arch(), - some_location_specified (false), - symbol_containing_addr () -{ - OptionParsingStarting(nullptr); +CommandObjectDisassemble::CommandOptions::CommandOptions() + : Options(), num_lines_context(0), num_instructions(0), func_name(), + current_function(false), start_addr(), end_addr(), at_pc(false), + frame_line(false), plugin_name(), flavor_string(), arch(), + some_location_specified(false), symbol_containing_addr() { + OptionParsingStarting(nullptr); } CommandObjectDisassemble::CommandOptions::~CommandOptions() = default; -Error -CommandObjectDisassemble::CommandOptions::SetOptionValue(uint32_t option_idx, - const char *option_arg, - ExecutionContext *execution_context) -{ - Error error; - - const int short_option = m_getopt_table[option_idx].val; - - bool success; - - switch (short_option) - { - case 'm': - show_mixed = true; - break; - - case 'C': - num_lines_context = StringConvert::ToUInt32(option_arg, 0, 0, &success); - if (!success) - error.SetErrorStringWithFormat ("invalid num context lines string: \"%s\"", option_arg); - break; - - case 'c': - num_instructions = StringConvert::ToUInt32(option_arg, 0, 0, &success); - if (!success) - error.SetErrorStringWithFormat ("invalid num of instructions string: \"%s\"", option_arg); - break; - - case 'b': - show_bytes = true; - break; - - case 's': - { - start_addr = Args::StringToAddress(execution_context, option_arg, - LLDB_INVALID_ADDRESS, &error); - if (start_addr != LLDB_INVALID_ADDRESS) - some_location_specified = true; - } - break; - case 'e': - { - end_addr = Args::StringToAddress(execution_context, option_arg, - LLDB_INVALID_ADDRESS, &error); - if (end_addr != LLDB_INVALID_ADDRESS) - some_location_specified = true; - } - break; - - case 'n': - func_name.assign (option_arg); - some_location_specified = true; - break; - - case 'p': - at_pc = true; - some_location_specified = true; - break; - - case 'l': - frame_line = true; - // Disassemble the current source line kind of implies showing mixed - // source code context. - show_mixed = true; - some_location_specified = true; - break; - - case 'P': - plugin_name.assign (option_arg); - break; - - case 'F': - { - TargetSP target_sp = execution_context ? - execution_context->GetTargetSP() : TargetSP(); - if (target_sp && - (target_sp->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86 - || target_sp->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86_64)) - { - flavor_string.assign (option_arg); - } - else - error.SetErrorStringWithFormat("Disassembler flavors are currently only supported for x86 and x86_64 targets."); - break; - } - - case 'r': - raw = true; - break; - - case 'f': - current_function = true; - some_location_specified = true; - break; - - case 'A': - if (execution_context) - { - auto target_sp = execution_context ? - execution_context->GetTargetSP() : TargetSP(); - auto platform_sp = - target_sp ? target_sp->GetPlatform() : PlatformSP(); - if (!arch.SetTriple (option_arg, platform_sp.get())) - arch.SetTriple (option_arg); - } - break; - - case 'a': - { - symbol_containing_addr = - Args::StringToAddress(execution_context,option_arg, - LLDB_INVALID_ADDRESS, &error); - if (symbol_containing_addr != LLDB_INVALID_ADDRESS) - { - some_location_specified = true; - } - } - break; +Error CommandObjectDisassemble::CommandOptions::SetOptionValue( + uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) { + Error error; + + const int short_option = m_getopt_table[option_idx].val; + + bool success; + + switch (short_option) { + case 'm': + show_mixed = true; + break; + + case 'C': + num_lines_context = StringConvert::ToUInt32(option_arg, 0, 0, &success); + if (!success) + error.SetErrorStringWithFormat("invalid num context lines string: \"%s\"", + option_arg); + break; + + case 'c': + num_instructions = StringConvert::ToUInt32(option_arg, 0, 0, &success); + if (!success) + error.SetErrorStringWithFormat( + "invalid num of instructions string: \"%s\"", option_arg); + break; + + case 'b': + show_bytes = true; + break; + + case 's': { + start_addr = Args::StringToAddress(execution_context, option_arg, + LLDB_INVALID_ADDRESS, &error); + if (start_addr != LLDB_INVALID_ADDRESS) + some_location_specified = true; + } break; + case 'e': { + end_addr = Args::StringToAddress(execution_context, option_arg, + LLDB_INVALID_ADDRESS, &error); + if (end_addr != LLDB_INVALID_ADDRESS) + some_location_specified = true; + } break; + + case 'n': + func_name.assign(option_arg); + some_location_specified = true; + break; + + case 'p': + at_pc = true; + some_location_specified = true; + break; + + case 'l': + frame_line = true; + // Disassemble the current source line kind of implies showing mixed + // source code context. + show_mixed = true; + some_location_specified = true; + break; + + case 'P': + plugin_name.assign(option_arg); + break; + + case 'F': { + TargetSP target_sp = + execution_context ? execution_context->GetTargetSP() : TargetSP(); + if (target_sp && (target_sp->GetArchitecture().GetTriple().getArch() == + llvm::Triple::x86 || + target_sp->GetArchitecture().GetTriple().getArch() == + llvm::Triple::x86_64)) { + flavor_string.assign(option_arg); + } else + error.SetErrorStringWithFormat("Disassembler flavors are currently only " + "supported for x86 and x86_64 targets."); + break; + } + + case 'r': + raw = true; + break; + + case 'f': + current_function = true; + some_location_specified = true; + break; + + case 'A': + if (execution_context) { + auto target_sp = + execution_context ? execution_context->GetTargetSP() : TargetSP(); + auto platform_sp = target_sp ? target_sp->GetPlatform() : PlatformSP(); + if (!arch.SetTriple(option_arg, platform_sp.get())) + arch.SetTriple(option_arg); + } + break; - default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); - break; + case 'a': { + symbol_containing_addr = Args::StringToAddress( + execution_context, option_arg, LLDB_INVALID_ADDRESS, &error); + if (symbol_containing_addr != LLDB_INVALID_ADDRESS) { + some_location_specified = true; } + } break; + + default: + error.SetErrorStringWithFormat("unrecognized short option '%c'", + short_option); + break; + } - return error; + return error; } -void -CommandObjectDisassemble::CommandOptions::OptionParsingStarting( - ExecutionContext *execution_context) -{ - show_mixed = false; - show_bytes = false; - num_lines_context = 0; - num_instructions = 0; - func_name.clear(); - current_function = false; - at_pc = false; - frame_line = false; - start_addr = LLDB_INVALID_ADDRESS; - end_addr = LLDB_INVALID_ADDRESS; - symbol_containing_addr = LLDB_INVALID_ADDRESS; - raw = false; - plugin_name.clear(); - - Target *target = - execution_context ? execution_context->GetTargetPtr() : nullptr; - - // This is a hack till we get the ability to specify features based on architecture. For now GetDisassemblyFlavor - // is really only valid for x86 (and for the llvm assembler plugin, but I'm papering over that since that is the - // only disassembler plugin we have... - if (target) - { - if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86 - || target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86_64) - { - flavor_string.assign(target->GetDisassemblyFlavor()); - } - else - flavor_string.assign ("default"); - - } - else - flavor_string.assign("default"); - - arch.Clear(); - some_location_specified = false; +void CommandObjectDisassemble::CommandOptions::OptionParsingStarting( + ExecutionContext *execution_context) { + show_mixed = false; + show_bytes = false; + num_lines_context = 0; + num_instructions = 0; + func_name.clear(); + current_function = false; + at_pc = false; + frame_line = false; + start_addr = LLDB_INVALID_ADDRESS; + end_addr = LLDB_INVALID_ADDRESS; + symbol_containing_addr = LLDB_INVALID_ADDRESS; + raw = false; + plugin_name.clear(); + + Target *target = + execution_context ? execution_context->GetTargetPtr() : nullptr; + + // This is a hack till we get the ability to specify features based on + // architecture. For now GetDisassemblyFlavor + // is really only valid for x86 (and for the llvm assembler plugin, but I'm + // papering over that since that is the + // only disassembler plugin we have... + if (target) { + if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86 || + target->GetArchitecture().GetTriple().getArch() == + llvm::Triple::x86_64) { + flavor_string.assign(target->GetDisassemblyFlavor()); + } else + flavor_string.assign("default"); + + } else + flavor_string.assign("default"); + + arch.Clear(); + some_location_specified = false; } -Error -CommandObjectDisassemble::CommandOptions::OptionParsingFinished( - ExecutionContext *execution_context) -{ - if (!some_location_specified) - current_function = true; - return Error(); +Error CommandObjectDisassemble::CommandOptions::OptionParsingFinished( + ExecutionContext *execution_context) { + if (!some_location_specified) + current_function = true; + return Error(); } -const OptionDefinition* -CommandObjectDisassemble::CommandOptions::GetDefinitions () -{ - return g_option_table; +const OptionDefinition * +CommandObjectDisassemble::CommandOptions::GetDefinitions() { + return g_option_table; } -OptionDefinition -CommandObjectDisassemble::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectDisassemble::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_ALL, false, "bytes", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show opcode bytes when disassembling."}, {LLDB_OPT_SET_ALL, false, "context", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNumLines, "Number of context lines of source to show."}, {LLDB_OPT_SET_ALL, false, "mixed", 'm', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable mixed source and assembly display."}, @@ -267,367 +237,330 @@ CommandObjectDisassemble::CommandOptions::g_option_table[] = "table information, else disassemble around the pc."}, {LLDB_OPT_SET_7, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Disassemble function containing this address."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- // CommandObjectDisassemble //------------------------------------------------------------------------- -CommandObjectDisassemble::CommandObjectDisassemble(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "disassemble", "Disassemble specified instructions in the current target. " - "Defaults to the current function for the current thread and " - "stack frame.", - "disassemble [<cmd-options>]"), - m_options() -{ -} +CommandObjectDisassemble::CommandObjectDisassemble( + CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "disassemble", + "Disassemble specified instructions in the current target. " + "Defaults to the current function for the current thread and " + "stack frame.", + "disassemble [<cmd-options>]"), + m_options() {} CommandObjectDisassemble::~CommandObjectDisassemble() = default; -bool -CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result) -{ - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) - { - result.AppendError ("invalid target, create a debug target using the 'target create' command"); - result.SetStatus (eReturnStatusFailed); - return false; +bool CommandObjectDisassemble::DoExecute(Args &command, + CommandReturnObject &result) { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (target == nullptr) { + result.AppendError("invalid target, create a debug target using the " + "'target create' command"); + result.SetStatus(eReturnStatusFailed); + return false; + } + if (!m_options.arch.IsValid()) + m_options.arch = target->GetArchitecture(); + + if (!m_options.arch.IsValid()) { + result.AppendError( + "use the --arch option or set the target architecture to disassemble"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + const char *plugin_name = m_options.GetPluginName(); + const char *flavor_string = m_options.GetFlavorString(); + + DisassemblerSP disassembler = + Disassembler::FindPlugin(m_options.arch, flavor_string, plugin_name); + + if (!disassembler) { + if (plugin_name) { + result.AppendErrorWithFormat( + "Unable to find Disassembler plug-in named '%s' that supports the " + "'%s' architecture.\n", + plugin_name, m_options.arch.GetArchitectureName()); + } else + result.AppendErrorWithFormat( + "Unable to find Disassembler plug-in for the '%s' architecture.\n", + m_options.arch.GetArchitectureName()); + result.SetStatus(eReturnStatusFailed); + return false; + } else if (flavor_string != nullptr && + !disassembler->FlavorValidForArchSpec(m_options.arch, + flavor_string)) + result.AppendWarningWithFormat( + "invalid disassembler flavor \"%s\", using default.\n", flavor_string); + + result.SetStatus(eReturnStatusSuccessFinishResult); + + if (command.GetArgumentCount() != 0) { + result.AppendErrorWithFormat( + "\"disassemble\" arguments are specified as options.\n"); + const int terminal_width = + GetCommandInterpreter().GetDebugger().GetTerminalWidth(); + GetOptions()->GenerateOptionUsage(result.GetErrorStream(), this, + terminal_width); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (m_options.show_mixed && m_options.num_lines_context == 0) + m_options.num_lines_context = 1; + + // Always show the PC in the disassembly + uint32_t options = Disassembler::eOptionMarkPCAddress; + + // Mark the source line for the current PC only if we are doing mixed source + // and assembly + if (m_options.show_mixed) + options |= Disassembler::eOptionMarkPCSourceLine; + + if (m_options.show_bytes) + options |= Disassembler::eOptionShowBytes; + + if (m_options.raw) + options |= Disassembler::eOptionRawOuput; + + if (!m_options.func_name.empty()) { + ConstString name(m_options.func_name.c_str()); + + if (Disassembler::Disassemble( + m_interpreter.GetDebugger(), m_options.arch, plugin_name, + flavor_string, m_exe_ctx, name, + nullptr, // Module * + m_options.num_instructions, + 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); } - if (!m_options.arch.IsValid()) - m_options.arch = target->GetArchitecture(); - - if (!m_options.arch.IsValid()) - { - result.AppendError ("use the --arch option or set the target architecture to disassemble"); - 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; - } - - const char *plugin_name = m_options.GetPluginName (); - const char *flavor_string = m_options.GetFlavorString(); - - DisassemblerSP disassembler = Disassembler::FindPlugin(m_options.arch, flavor_string, plugin_name); - - if (!disassembler) - { - if (plugin_name) - { - result.AppendErrorWithFormat ("Unable to find Disassembler plug-in named '%s' that supports the '%s' architecture.\n", - plugin_name, - m_options.arch.GetArchitectureName()); - } - else - result.AppendErrorWithFormat ("Unable to find Disassembler plug-in for the '%s' architecture.\n", - m_options.arch.GetArchitectureName()); - result.SetStatus (eReturnStatusFailed); + } + 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()); + } } - else if (flavor_string != nullptr && !disassembler->FlavorValidForArchSpec(m_options.arch, flavor_string)) - result.AppendWarningWithFormat("invalid disassembler flavor \"%s\", using default.\n", flavor_string); - - result.SetStatus (eReturnStatusSuccessFinishResult); - - if (command.GetArgumentCount() != 0) - { - result.AppendErrorWithFormat ("\"disassemble\" arguments are specified as options.\n"); - const int terminal_width = - GetCommandInterpreter().GetDebugger().GetTerminalWidth(); - GetOptions()->GenerateOptionUsage(result.GetErrorStream(), this, - terminal_width); - result.SetStatus (eReturnStatusFailed); - return false; - } - - if (m_options.show_mixed && m_options.num_lines_context == 0) - m_options.num_lines_context = 1; - - // Always show the PC in the disassembly - uint32_t options = Disassembler::eOptionMarkPCAddress; - - // Mark the source line for the current PC only if we are doing mixed source and assembly - if (m_options.show_mixed) - options |= Disassembler::eOptionMarkPCSourceLine; - - if (m_options.show_bytes) - options |= Disassembler::eOptionShowBytes; - - if (m_options.raw) - options |= Disassembler::eOptionRawOuput; - - if (!m_options.func_name.empty()) - { - ConstString name(m_options.func_name.c_str()); - - if (Disassembler::Disassemble(m_interpreter.GetDebugger(), - m_options.arch, - plugin_name, - flavor_string, - m_exe_ctx, - name, - nullptr, // Module * - m_options.num_instructions, - 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); + + // 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; } - } - 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; - } + 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; } - 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()); + ranges.push_back(range); + } 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; } - } - - // 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; + 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; } - ranges.push_back(range); - } - 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); - } + } 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 - { - 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 (m_interpreter.GetDebugger(), - m_options.arch, - plugin_name, - flavor_string, - m_exe_ctx, - cur_range.GetBaseAddress(), - m_options.num_instructions, - 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 + 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(); } - 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 (m_interpreter.GetDebugger(), - m_options.arch, - plugin_name, - flavor_string, - m_exe_ctx, - cur_range, - m_options.num_instructions, - 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", m_options.start_addr); - result.SetStatus (eReturnStatusFailed); - } - if (print_sc_header) - result.AppendMessage("\n"); - } + + 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( + m_interpreter.GetDebugger(), m_options.arch, plugin_name, + flavor_string, m_exe_ctx, cur_range.GetBaseAddress(), + m_options.num_instructions, + 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( + m_interpreter.GetDebugger(), m_options.arch, plugin_name, + flavor_string, m_exe_ctx, cur_range, m_options.num_instructions, + 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", + m_options.start_addr); + result.SetStatus(eReturnStatusFailed); } + if (print_sc_header) + result.AppendMessage("\n"); + } } + } - return result.Succeeded(); + return result.Succeeded(); } diff --git a/lldb/source/Commands/CommandObjectDisassemble.h b/lldb/source/Commands/CommandObjectDisassemble.h index fa95122..a4d132a 100644 --- a/lldb/source/Commands/CommandObjectDisassemble.h +++ b/lldb/source/Commands/CommandObjectDisassemble.h @@ -24,79 +24,64 @@ namespace lldb_private { // CommandObjectDisassemble //------------------------------------------------------------------------- -class CommandObjectDisassemble : public CommandObjectParsed -{ +class CommandObjectDisassemble : public CommandObjectParsed { public: - class CommandOptions : public Options - { - public: - CommandOptions(); - - ~CommandOptions() override; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override; - - void - OptionParsingStarting(ExecutionContext *execution_context) override; - - const OptionDefinition* - GetDefinitions() override; - - const char * - GetPluginName () - { - return (plugin_name.empty() ? nullptr : plugin_name.c_str()); - } - - const char * - GetFlavorString () - { - if (flavor_string.empty() || flavor_string == "default") - return nullptr; - return flavor_string.c_str(); - } - - Error - OptionParsingFinished(ExecutionContext *execution_context) override; - - bool show_mixed; // Show mixed source/assembly - bool show_bytes; - uint32_t num_lines_context; - uint32_t num_instructions; - bool raw; - std::string func_name; - bool current_function; - lldb::addr_t start_addr; - lldb::addr_t end_addr; - bool at_pc; - bool frame_line; - std::string plugin_name; - std::string flavor_string; - ArchSpec arch; - bool some_location_specified; // If no location was specified, we'll select "at_pc". This should be set - // in SetOptionValue if anything the selects a location is set. - lldb::addr_t symbol_containing_addr; - static OptionDefinition g_option_table[]; - }; - - CommandObjectDisassemble (CommandInterpreter &interpreter); - - ~CommandObjectDisassemble() override; - - Options * - GetOptions() override - { - return &m_options; + class CommandOptions : public Options { + public: + CommandOptions(); + + ~CommandOptions() override; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override; + + void OptionParsingStarting(ExecutionContext *execution_context) override; + + const OptionDefinition *GetDefinitions() override; + + const char *GetPluginName() { + return (plugin_name.empty() ? nullptr : plugin_name.c_str()); + } + + const char *GetFlavorString() { + if (flavor_string.empty() || flavor_string == "default") + return nullptr; + return flavor_string.c_str(); } + Error OptionParsingFinished(ExecutionContext *execution_context) override; + + bool show_mixed; // Show mixed source/assembly + bool show_bytes; + uint32_t num_lines_context; + uint32_t num_instructions; + bool raw; + std::string func_name; + bool current_function; + lldb::addr_t start_addr; + lldb::addr_t end_addr; + bool at_pc; + bool frame_line; + std::string plugin_name; + std::string flavor_string; + ArchSpec arch; + bool some_location_specified; // If no location was specified, we'll select + // "at_pc". This should be set + // in SetOptionValue if anything the selects a location is set. + lldb::addr_t symbol_containing_addr; + static OptionDefinition g_option_table[]; + }; + + CommandObjectDisassemble(CommandInterpreter &interpreter); + + ~CommandObjectDisassemble() override; + + Options *GetOptions() override { return &m_options; } + protected: - bool - DoExecute(Args& command, - CommandReturnObject &result) override; + bool DoExecute(Args &command, CommandReturnObject &result) override; - CommandOptions m_options; + CommandOptions m_options; }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index b82a4fd..be4f5461 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -15,21 +15,21 @@ // Project includes #include "CommandObjectExpression.h" +#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h" +#include "lldb/Core/Debugger.h" #include "lldb/Core/Value.h" #include "lldb/Core/ValueObjectVariable.h" #include "lldb/DataFormatters/ValueObjectPrinter.h" -#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h" -#include "lldb/Expression/UserExpression.h" #include "lldb/Expression/DWARFExpression.h" #include "lldb/Expression/REPL.h" +#include "lldb/Expression/UserExpression.h" #include "lldb/Host/Host.h" #include "lldb/Host/StringConvert.h" -#include "lldb/Core/Debugger.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Target/Language.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/Variable.h" +#include "lldb/Target/Language.h" #include "lldb/Target/Process.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" @@ -38,24 +38,19 @@ using namespace lldb; using namespace lldb_private; -CommandObjectExpression::CommandOptions::CommandOptions () : - OptionGroup() -{ -} +CommandObjectExpression::CommandOptions::CommandOptions() : OptionGroup() {} CommandObjectExpression::CommandOptions::~CommandOptions() = default; -static OptionEnumValueElement g_description_verbosity_type[] = -{ - { eLanguageRuntimeDescriptionDisplayVerbosityCompact, "compact", "Only show the description string"}, - { eLanguageRuntimeDescriptionDisplayVerbosityFull, "full", "Show the full output, including persistent variable's name and type"}, - { 0, nullptr, nullptr } -}; +static OptionEnumValueElement g_description_verbosity_type[] = { + {eLanguageRuntimeDescriptionDisplayVerbosityCompact, "compact", + "Only show the description string"}, + {eLanguageRuntimeDescriptionDisplayVerbosityFull, "full", + "Show the full output, including persistent variable's name and type"}, + {0, nullptr, nullptr}}; -OptionDefinition -CommandObjectExpression::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectExpression::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Should we run all threads if the execution doesn't complete on one thread."}, {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"}, {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Timeout value (in microseconds) for running the expression."}, @@ -71,604 +66,572 @@ CommandObjectExpression::CommandOptions::g_option_table[] = "executed."}, {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "allow-jit", 'j', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Controls whether the expression can fall back to being JITted if it's not supported by " "the interpreter (defaults to true)."} - // clang-format on + // clang-format on }; -uint32_t -CommandObjectExpression::CommandOptions::GetNumDefinitions () -{ - return llvm::array_lengthof(g_option_table); +uint32_t CommandObjectExpression::CommandOptions::GetNumDefinitions() { + return llvm::array_lengthof(g_option_table); } -Error -CommandObjectExpression::CommandOptions::SetOptionValue (uint32_t option_idx, - const char *option_arg, - ExecutionContext *execution_context) -{ - Error error; - - const int short_option = g_option_table[option_idx].short_option; - - switch (short_option) - { - case 'l': - language = Language::GetLanguageTypeFromString (option_arg); - if (language == eLanguageTypeUnknown) - error.SetErrorStringWithFormat ("unknown language type: '%s' for expression", option_arg); - break; - - case 'a': - { - bool success; - bool result; - result = Args::StringToBoolean(option_arg, true, &success); - if (!success) - error.SetErrorStringWithFormat("invalid all-threads value setting: \"%s\"", option_arg); - else - try_all_threads = result; - } - break; - - case 'i': - { - bool success; - bool tmp_value = Args::StringToBoolean(option_arg, true, &success); - if (success) - ignore_breakpoints = tmp_value; - else - error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg); - break; - } - - case 'j': - { - bool success; - bool tmp_value = Args::StringToBoolean(option_arg, true, &success); - if (success) - allow_jit = tmp_value; - else - error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg); - break; - } - - case 't': - { - bool success; - uint32_t result; - result = StringConvert::ToUInt32(option_arg, 0, 0, &success); - if (success) - timeout = result; - else - error.SetErrorStringWithFormat ("invalid timeout setting \"%s\"", option_arg); - } - break; - - case 'u': - { - bool success; - bool tmp_value = Args::StringToBoolean(option_arg, true, &success); - if (success) - unwind_on_error = tmp_value; - else - error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg); - break; - } - - case 'v': - if (!option_arg) - { - m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityFull; - break; - } - m_verbosity = (LanguageRuntimeDescriptionDisplayVerbosity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error); - if (!error.Success()) - error.SetErrorStringWithFormat ("unrecognized value for description-verbosity '%s'", option_arg); - break; - - case 'g': - debug = true; - unwind_on_error = false; - ignore_breakpoints = false; - break; - - case 'p': - top_level = true; - break; - - case 'X': - { - bool success; - bool tmp_value = Args::StringToBoolean(option_arg, true, &success); - if (success) - auto_apply_fixits = tmp_value ? eLazyBoolYes : eLazyBoolNo; - else - error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg); - break; - } - - default: - error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); - break; +Error CommandObjectExpression::CommandOptions::SetOptionValue( + uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) { + Error error; + + const int short_option = g_option_table[option_idx].short_option; + + switch (short_option) { + case 'l': + language = Language::GetLanguageTypeFromString(option_arg); + if (language == eLanguageTypeUnknown) + error.SetErrorStringWithFormat( + "unknown language type: '%s' for expression", option_arg); + break; + + case 'a': { + bool success; + bool result; + result = Args::StringToBoolean(option_arg, true, &success); + if (!success) + error.SetErrorStringWithFormat( + "invalid all-threads value setting: \"%s\"", option_arg); + else + try_all_threads = result; + } break; + + case 'i': { + bool success; + bool tmp_value = Args::StringToBoolean(option_arg, true, &success); + if (success) + ignore_breakpoints = tmp_value; + else + error.SetErrorStringWithFormat( + "could not convert \"%s\" to a boolean value.", option_arg); + break; + } + + case 'j': { + bool success; + bool tmp_value = Args::StringToBoolean(option_arg, true, &success); + if (success) + allow_jit = tmp_value; + else + error.SetErrorStringWithFormat( + "could not convert \"%s\" to a boolean value.", option_arg); + break; + } + + case 't': { + bool success; + uint32_t result; + result = StringConvert::ToUInt32(option_arg, 0, 0, &success); + if (success) + timeout = result; + else + error.SetErrorStringWithFormat("invalid timeout setting \"%s\"", + option_arg); + } break; + + case 'u': { + bool success; + bool tmp_value = Args::StringToBoolean(option_arg, true, &success); + if (success) + unwind_on_error = tmp_value; + else + error.SetErrorStringWithFormat( + "could not convert \"%s\" to a boolean value.", option_arg); + break; + } + + case 'v': + if (!option_arg) { + m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityFull; + break; } - - return error; + m_verbosity = + (LanguageRuntimeDescriptionDisplayVerbosity)Args::StringToOptionEnum( + option_arg, g_option_table[option_idx].enum_values, 0, error); + if (!error.Success()) + error.SetErrorStringWithFormat( + "unrecognized value for description-verbosity '%s'", option_arg); + break; + + case 'g': + debug = true; + unwind_on_error = false; + ignore_breakpoints = false; + break; + + case 'p': + top_level = true; + break; + + case 'X': { + bool success; + bool tmp_value = Args::StringToBoolean(option_arg, true, &success); + if (success) + auto_apply_fixits = tmp_value ? eLazyBoolYes : eLazyBoolNo; + else + error.SetErrorStringWithFormat( + "could not convert \"%s\" to a boolean value.", option_arg); + break; + } + + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", + short_option); + break; + } + + return error; } -void -CommandObjectExpression::CommandOptions::OptionParsingStarting( - ExecutionContext *execution_context) -{ - auto process_sp = - execution_context ? execution_context->GetProcessSP() : ProcessSP(); - if (process_sp) - { - ignore_breakpoints = process_sp->GetIgnoreBreakpointsInExpressions(); - unwind_on_error = process_sp->GetUnwindOnErrorInExpressions(); - } - else - { - ignore_breakpoints = true; - unwind_on_error = true; - } - - show_summary = true; - try_all_threads = true; - timeout = 0; - debug = false; - language = eLanguageTypeUnknown; - m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact; - auto_apply_fixits = eLazyBoolCalculate; - top_level = false; - allow_jit = true; +void CommandObjectExpression::CommandOptions::OptionParsingStarting( + ExecutionContext *execution_context) { + auto process_sp = + execution_context ? execution_context->GetProcessSP() : ProcessSP(); + if (process_sp) { + ignore_breakpoints = process_sp->GetIgnoreBreakpointsInExpressions(); + unwind_on_error = process_sp->GetUnwindOnErrorInExpressions(); + } else { + ignore_breakpoints = true; + unwind_on_error = true; + } + + show_summary = true; + try_all_threads = true; + timeout = 0; + debug = false; + language = eLanguageTypeUnknown; + m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact; + auto_apply_fixits = eLazyBoolCalculate; + top_level = false; + allow_jit = true; } -const OptionDefinition* -CommandObjectExpression::CommandOptions::GetDefinitions () -{ - return g_option_table; +const OptionDefinition * +CommandObjectExpression::CommandOptions::GetDefinitions() { + return g_option_table; } -CommandObjectExpression::CommandObjectExpression(CommandInterpreter &interpreter) +CommandObjectExpression::CommandObjectExpression( + CommandInterpreter &interpreter) : CommandObjectRaw( - interpreter, "expression", - "Evaluate an expression on the current thread. Displays any returned value with LLDB's default formatting.", + interpreter, "expression", "Evaluate an expression on the current " + "thread. Displays any returned value " + "with LLDB's default formatting.", nullptr, eCommandProcessMustBePaused | eCommandTryTargetAPILock), IOHandlerDelegate(IOHandlerDelegate::Completion::Expression), - m_option_group(), - m_format_options(eFormatDefault), - m_repl_option(LLDB_OPT_SET_1, false, "repl", 'r', "Drop into REPL", false, true), - m_command_options(), - m_expr_line_count(0), - m_expr_lines() -{ - SetHelpLong( -R"( + m_option_group(), m_format_options(eFormatDefault), + m_repl_option(LLDB_OPT_SET_1, false, "repl", 'r', "Drop into REPL", false, + true), + m_command_options(), m_expr_line_count(0), m_expr_lines() { + SetHelpLong( + R"( Timeouts: -)" " If the expression can be evaluated statically (without running code) then it will be. \ +)" + " If the expression can be evaluated statically (without running code) then it will be. \ Otherwise, by default the expression will run on the current thread with a short timeout: \ currently .25 seconds. If it doesn't return in that time, the evaluation will be interrupted \ and resumed with all threads running. You can use the -a option to disable retrying on all \ -threads. You can use the -t option to set a shorter timeout." R"( +threads. You can use the -t option to set a shorter timeout." + R"( User defined variables: -)" " You can define your own variables for convenience or to be used in subsequent expressions. \ +)" + " You can define your own variables for convenience or to be used in subsequent expressions. \ You define them the same way you would define variables in C. If the first character of \ your user defined variable is a $, then the variable's value will be available in future \ -expressions, otherwise it will just be available in the current expression." R"( +expressions, otherwise it will just be available in the current expression." + R"( Continuing evaluation after a breakpoint: -)" " If the \"-i false\" option is used, and execution is interrupted by a breakpoint hit, once \ +)" + " If the \"-i false\" option is used, and execution is interrupted by a breakpoint hit, once \ you are done with your investigation, you can either remove the expression execution frames \ from the stack with \"thread return -x\" or if you are still interested in the expression result \ you can issue the \"continue\" command and the expression evaluation will complete and the \ expression result will be available using the \"thread.completed-expression\" key in the thread \ -format." R"( +format." + R"( Examples: expr my_struct->a = my_array[3] expr -f bin -- (index * 8) + 5 expr unsigned int $foo = 5 - expr char c[] = \"foo\"; c[0])" - ); - - CommandArgumentEntry arg; - CommandArgumentData expression_arg; - - // Define the first (and only) variant of this arg. - expression_arg.arg_type = eArgTypeExpression; - expression_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (expression_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - - // Add the "--format" and "--gdb-format" - m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_1); - m_option_group.Append (&m_command_options); - m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2); - m_option_group.Append (&m_repl_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3); - m_option_group.Finalize(); + expr char c[] = \"foo\"; c[0])"); + + CommandArgumentEntry arg; + CommandArgumentData expression_arg; + + // Define the first (and only) variant of this arg. + expression_arg.arg_type = eArgTypeExpression; + expression_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the argument + // entry. + arg.push_back(expression_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + + // Add the "--format" and "--gdb-format" + m_option_group.Append(&m_format_options, + OptionGroupFormat::OPTION_GROUP_FORMAT | + OptionGroupFormat::OPTION_GROUP_GDB_FMT, + LLDB_OPT_SET_1); + m_option_group.Append(&m_command_options); + m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, + LLDB_OPT_SET_1 | LLDB_OPT_SET_2); + m_option_group.Append(&m_repl_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3); + m_option_group.Finalize(); } CommandObjectExpression::~CommandObjectExpression() = default; -Options * -CommandObjectExpression::GetOptions () -{ - return &m_option_group; -} +Options *CommandObjectExpression::GetOptions() { return &m_option_group; } static lldb_private::Error -CanBeUsedForElementCountPrinting (ValueObject& valobj) -{ - CompilerType type(valobj.GetCompilerType()); - CompilerType pointee; - if (!type.IsPointerType(&pointee)) - return Error("as it does not refer to a pointer"); - if (pointee.IsVoidType()) - return Error("as it refers to a pointer to void"); - return Error(); +CanBeUsedForElementCountPrinting(ValueObject &valobj) { + CompilerType type(valobj.GetCompilerType()); + CompilerType pointee; + if (!type.IsPointerType(&pointee)) + return Error("as it does not refer to a pointer"); + if (pointee.IsVoidType()) + return Error("as it refers to a pointer to void"); + return Error(); } -bool -CommandObjectExpression::EvaluateExpression(const char *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(); - - if (target) - { - lldb::ValueObjectSP result_valobj_sp; - bool keep_in_memory = true; - StackFrame *frame = exe_ctx.GetFramePtr(); - - 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.SetUseDynamic(m_varobj_options.use_dynamic); - options.SetTryAllThreads(m_command_options.try_all_threads); - options.SetDebug(m_command_options.debug); - options.SetLanguage(m_command_options.language); - options.SetExecutionPolicy(m_command_options.allow_jit ? - EvaluateExpressionOptions::default_execution_policy : - lldb_private::eExecutionPolicyNever); - - bool auto_apply_fixits; - if (m_command_options.auto_apply_fixits == eLazyBoolCalculate) - auto_apply_fixits = target->GetEnableAutoApplyFixIts(); - else - auto_apply_fixits = m_command_options.auto_apply_fixits == eLazyBoolYes ? true : false; - - options.SetAutoApplyFixIts(auto_apply_fixits); - - if (m_command_options.top_level) - options.SetExecutionPolicy(eExecutionPolicyTopLevel); - - // If there is any chance we are going to stop and want to see - // what went wrong with our expression, we should generate debug info - if (!m_command_options.ignore_breakpoints || - !m_command_options.unwind_on_error) - options.SetGenerateDebugInfo(true); - - if (m_command_options.timeout > 0) - options.SetTimeoutUsec(m_command_options.timeout); - else - options.SetTimeoutUsec(0); - - 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 (success == eExpressionCompleted) - error_stream->Printf (" Fix-it applied, fixed expression was: \n %s\n", m_fixed_expression.c_str()); - } +bool CommandObjectExpression::EvaluateExpression(const char *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(); + + if (target) { + lldb::ValueObjectSP result_valobj_sp; + bool keep_in_memory = true; + StackFrame *frame = exe_ctx.GetFramePtr(); + + 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.SetUseDynamic(m_varobj_options.use_dynamic); + options.SetTryAllThreads(m_command_options.try_all_threads); + options.SetDebug(m_command_options.debug); + options.SetLanguage(m_command_options.language); + options.SetExecutionPolicy( + m_command_options.allow_jit + ? EvaluateExpressionOptions::default_execution_policy + : lldb_private::eExecutionPolicyNever); + + bool auto_apply_fixits; + if (m_command_options.auto_apply_fixits == eLazyBoolCalculate) + auto_apply_fixits = target->GetEnableAutoApplyFixIts(); + else + auto_apply_fixits = + m_command_options.auto_apply_fixits == eLazyBoolYes ? true : false; - if (result_valobj_sp) - { - Format format = m_format_options.GetFormat(); - - if (result_valobj_sp->GetError().Success()) - { - if (format != eFormatVoid) - { - if (format != eFormatDefault) - result_valobj_sp->SetFormat (format); - - if (m_varobj_options.elem_count > 0) - { - Error error(CanBeUsedForElementCountPrinting(*result_valobj_sp)); - if (error.Fail()) - { - result->AppendErrorWithFormat("expression cannot be used with --element-count %s\n", error.AsCString("")); - result->SetStatus(eReturnStatusFailed); - return false; - } - } - - DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(m_command_options.m_verbosity,format)); - options.SetVariableFormatDisplayLanguage(result_valobj_sp->GetPreferredDisplayLanguage()); - - result_valobj_sp->Dump(*output_stream,options); - - if (result) - result->SetStatus (eReturnStatusSuccessFinishResult); - } - } - else - { - if (result_valobj_sp->GetError().GetError() == UserExpression::kNoResult) - { - if (format != eFormatVoid && m_interpreter.GetDebugger().GetNotifyVoid()) - { - error_stream->PutCString("(void)\n"); - } - - if (result) - 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); - if (!ends_with_newline) - error_stream->EOL(); - } - else - { - error_stream->PutCString ("error: unknown error\n"); - } - - if (result) - result->SetStatus (eReturnStatusFailed); - } - } - } - } + options.SetAutoApplyFixIts(auto_apply_fixits); + + if (m_command_options.top_level) + options.SetExecutionPolicy(eExecutionPolicyTopLevel); + + // If there is any chance we are going to stop and want to see + // what went wrong with our expression, we should generate debug info + if (!m_command_options.ignore_breakpoints || + !m_command_options.unwind_on_error) + options.SetGenerateDebugInfo(true); + + if (m_command_options.timeout > 0) + options.SetTimeoutUsec(m_command_options.timeout); else - { - error_stream->Printf ("error: invalid execution context for expression\n"); - return false; + options.SetTimeoutUsec(0); + + 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 (success == eExpressionCompleted) + error_stream->Printf( + " Fix-it applied, fixed expression was: \n %s\n", + m_fixed_expression.c_str()); } - - return true; -} -void -CommandObjectExpression::IOHandlerInputComplete (IOHandler &io_handler, std::string &line) -{ - io_handler.SetIsDone(true); -// StreamSP output_stream = io_handler.GetDebugger().GetAsyncOutputStream(); -// StreamSP error_stream = io_handler.GetDebugger().GetAsyncErrorStream(); - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); - StreamFileSP error_sp(io_handler.GetErrorStreamFile()); - - EvaluateExpression (line.c_str(), - output_sp.get(), - error_sp.get()); - if (output_sp) - output_sp->Flush(); - if (error_sp) - error_sp->Flush(); -} + if (result_valobj_sp) { + Format format = m_format_options.GetFormat(); + + if (result_valobj_sp->GetError().Success()) { + if (format != eFormatVoid) { + if (format != eFormatDefault) + result_valobj_sp->SetFormat(format); + + if (m_varobj_options.elem_count > 0) { + Error error(CanBeUsedForElementCountPrinting(*result_valobj_sp)); + if (error.Fail()) { + result->AppendErrorWithFormat( + "expression cannot be used with --element-count %s\n", + error.AsCString("")); + result->SetStatus(eReturnStatusFailed); + return false; + } + } + + DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions( + m_command_options.m_verbosity, format)); + options.SetVariableFormatDisplayLanguage( + result_valobj_sp->GetPreferredDisplayLanguage()); + + result_valobj_sp->Dump(*output_stream, options); -bool -CommandObjectExpression::IOHandlerIsInputComplete (IOHandler &io_handler, - StringList &lines) -{ - // An empty lines is used to indicate the end of input - const size_t num_lines = lines.GetSize(); - if (num_lines > 0 && lines[num_lines - 1].empty()) - { - // Remove the last empty line from "lines" so it doesn't appear - // in our resulting input and return true to indicate we are done - // getting lines - lines.PopBack(); - return true; + if (result) + result->SetStatus(eReturnStatusSuccessFinishResult); + } + } else { + if (result_valobj_sp->GetError().GetError() == + UserExpression::kNoResult) { + if (format != eFormatVoid && + m_interpreter.GetDebugger().GetNotifyVoid()) { + error_stream->PutCString("(void)\n"); + } + + if (result) + 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); + if (!ends_with_newline) + error_stream->EOL(); + } else { + error_stream->PutCString("error: unknown error\n"); + } + + if (result) + result->SetStatus(eReturnStatusFailed); + } + } } + } else { + error_stream->Printf("error: invalid execution context for expression\n"); return false; + } + + return true; } -void -CommandObjectExpression::GetMultilineExpression () -{ - m_expr_lines.clear(); - m_expr_line_count = 0; - - Debugger &debugger = GetCommandInterpreter().GetDebugger(); - bool color_prompt = debugger.GetUseColor(); - const bool multiple_lines = true; // Get multiple lines - IOHandlerSP io_handler_sp(new IOHandlerEditline(debugger, - IOHandler::Type::Expression, - "lldb-expr", // Name of input reader for history - nullptr, // No prompt - nullptr, // Continuation prompt - multiple_lines, - color_prompt, - 1, // Show line numbers starting at 1 - *this)); - - StreamFileSP output_sp(io_handler_sp->GetOutputStreamFile()); - if (output_sp) - { - output_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n"); - output_sp->Flush(); - } - debugger.PushIOHandler(io_handler_sp); +void CommandObjectExpression::IOHandlerInputComplete(IOHandler &io_handler, + std::string &line) { + io_handler.SetIsDone(true); + // StreamSP output_stream = + // io_handler.GetDebugger().GetAsyncOutputStream(); + // StreamSP error_stream = io_handler.GetDebugger().GetAsyncErrorStream(); + StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + StreamFileSP error_sp(io_handler.GetErrorStreamFile()); + + EvaluateExpression(line.c_str(), output_sp.get(), error_sp.get()); + if (output_sp) + output_sp->Flush(); + if (error_sp) + error_sp->Flush(); } -bool -CommandObjectExpression::DoExecute(const char *command, - CommandReturnObject &result) -{ - m_fixed_expression.clear(); - auto exe_ctx = GetCommandInterpreter().GetExecutionContext(); - m_option_group.NotifyOptionParsingStarting(&exe_ctx); +bool CommandObjectExpression::IOHandlerIsInputComplete(IOHandler &io_handler, + StringList &lines) { + // An empty lines is used to indicate the end of input + const size_t num_lines = lines.GetSize(); + if (num_lines > 0 && lines[num_lines - 1].empty()) { + // Remove the last empty line from "lines" so it doesn't appear + // in our resulting input and return true to indicate we are done + // getting lines + lines.PopBack(); + return true; + } + return false; +} - const char * expr = nullptr; +void CommandObjectExpression::GetMultilineExpression() { + m_expr_lines.clear(); + m_expr_line_count = 0; + + Debugger &debugger = GetCommandInterpreter().GetDebugger(); + bool color_prompt = debugger.GetUseColor(); + const bool multiple_lines = true; // Get multiple lines + IOHandlerSP io_handler_sp( + new IOHandlerEditline(debugger, IOHandler::Type::Expression, + "lldb-expr", // Name of input reader for history + nullptr, // No prompt + nullptr, // Continuation prompt + multiple_lines, color_prompt, + 1, // Show line numbers starting at 1 + *this)); + + StreamFileSP output_sp(io_handler_sp->GetOutputStreamFile()); + if (output_sp) { + output_sp->PutCString( + "Enter expressions, then terminate with an empty line to evaluate:\n"); + output_sp->Flush(); + } + debugger.PushIOHandler(io_handler_sp); +} - if (command[0] == '\0') - { - GetMultilineExpression (); - return result.Succeeded(); +bool CommandObjectExpression::DoExecute(const char *command, + CommandReturnObject &result) { + m_fixed_expression.clear(); + auto exe_ctx = GetCommandInterpreter().GetExecutionContext(); + m_option_group.NotifyOptionParsingStarting(&exe_ctx); + + const char *expr = nullptr; + + if (command[0] == '\0') { + GetMultilineExpression(); + return result.Succeeded(); + } + + if (command[0] == '-') { + // We have some options and these options MUST end with --. + const char *end_options = nullptr; + const char *s = command; + while (s && s[0]) { + end_options = ::strstr(s, "--"); + if (end_options) { + end_options += 2; // Get past the "--" + if (::isspace(end_options[0])) { + expr = end_options; + while (::isspace(*expr)) + ++expr; + break; + } + } + s = end_options; } - if (command[0] == '-') - { - // We have some options and these options MUST end with --. - const char *end_options = nullptr; - const char *s = command; - while (s && s[0]) - { - end_options = ::strstr (s, "--"); - if (end_options) - { - end_options += 2; // Get past the "--" - if (::isspace (end_options[0])) - { - expr = end_options; - while (::isspace (*expr)) - ++expr; - break; - } - } - s = end_options; - } + if (end_options) { + Args args(llvm::StringRef(command, end_options - command)); + if (!ParseOptions(args, result)) + return false; - if (end_options) - { - Args args (llvm::StringRef(command, end_options - command)); - if (!ParseOptions (args, result)) - return false; - - Error error (m_option_group.NotifyOptionParsingFinished(&exe_ctx)); - if (error.Fail()) - { - result.AppendError (error.AsCString()); - result.SetStatus (eReturnStatusFailed); - return false; - } - - if (m_repl_option.GetOptionValue().GetCurrentValue()) - { - Target *target = m_interpreter.GetExecutionContext().GetTargetPtr(); - if (target) - { - // Drop into REPL - m_expr_lines.clear(); - m_expr_line_count = 0; - - Debugger &debugger = target->GetDebugger(); - - // Check if the LLDB command interpreter is sitting on top of a REPL that - // launched it... - if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::CommandInterpreter, IOHandler::Type::REPL)) - { - // the LLDB command interpreter is sitting on top of a REPL that launched it, - // so just say the command interpreter is done and fall back to the existing REPL - m_interpreter.GetIOHandler(false)->SetIsDone(true); - } - else - { - // We are launching the REPL on top of the current LLDB command interpreter, - // so just push one - bool initialize = false; - Error repl_error; - REPLSP repl_sp (target->GetREPL(repl_error, m_command_options.language, nullptr, false)); - - if (!repl_sp) - { - initialize = true; - repl_sp = target->GetREPL(repl_error, m_command_options.language, nullptr, true); - if (!repl_error.Success()) - { - result.SetError(repl_error); - return result.Succeeded(); - } - } - - if (repl_sp) - { - if (initialize) - { - repl_sp->SetCommandOptions(m_command_options); - repl_sp->SetFormatOptions(m_format_options); - repl_sp->SetValueObjectDisplayOptions(m_varobj_options); - } - - IOHandlerSP io_handler_sp (repl_sp->GetIOHandler()); - - io_handler_sp->SetIsDone(false); - - debugger.PushIOHandler(io_handler_sp); - } - else - { - repl_error.SetErrorStringWithFormat("Couldn't create a REPL for %s", Language::GetNameForLanguageType(m_command_options.language)); - result.SetError(repl_error); - return result.Succeeded(); - } - } - } - } - // No expression following options - else if (expr == nullptr || expr[0] == '\0') - { - GetMultilineExpression (); + Error error(m_option_group.NotifyOptionParsingFinished(&exe_ctx)); + if (error.Fail()) { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (m_repl_option.GetOptionValue().GetCurrentValue()) { + Target *target = m_interpreter.GetExecutionContext().GetTargetPtr(); + if (target) { + // Drop into REPL + m_expr_lines.clear(); + m_expr_line_count = 0; + + Debugger &debugger = target->GetDebugger(); + + // Check if the LLDB command interpreter is sitting on top of a REPL + // that + // launched it... + if (debugger.CheckTopIOHandlerTypes( + IOHandler::Type::CommandInterpreter, IOHandler::Type::REPL)) { + // the LLDB command interpreter is sitting on top of a REPL that + // launched it, + // so just say the command interpreter is done and fall back to the + // existing REPL + m_interpreter.GetIOHandler(false)->SetIsDone(true); + } else { + // We are launching the REPL on top of the current LLDB command + // interpreter, + // so just push one + bool initialize = false; + Error repl_error; + REPLSP repl_sp(target->GetREPL( + repl_error, m_command_options.language, nullptr, false)); + + if (!repl_sp) { + initialize = true; + repl_sp = target->GetREPL(repl_error, m_command_options.language, + nullptr, true); + if (!repl_error.Success()) { + result.SetError(repl_error); return result.Succeeded(); + } } - } - } - if (expr == nullptr) - expr = command; - - if (EvaluateExpression (expr, &(result.GetOutputStream()), &(result.GetErrorStream()), &result)) - { - Target *target = m_interpreter.GetExecutionContext().GetTargetPtr(); - if (!m_fixed_expression.empty() && target->GetEnableNotifyAboutFixIts()) - { - CommandHistory &history = m_interpreter.GetCommandHistory(); - // FIXME: Can we figure out what the user actually typed (e.g. some alias for expr???) - // If we can it would be nice to show that. - std::string fixed_command("expression "); - if (expr == command) - fixed_command.append(m_fixed_expression); - else - { - // Add in any options that might have been in the original command: - fixed_command.append(command, expr - command); - fixed_command.append(m_fixed_expression); + if (repl_sp) { + if (initialize) { + repl_sp->SetCommandOptions(m_command_options); + repl_sp->SetFormatOptions(m_format_options); + repl_sp->SetValueObjectDisplayOptions(m_varobj_options); + } + + IOHandlerSP io_handler_sp(repl_sp->GetIOHandler()); + + io_handler_sp->SetIsDone(false); + + debugger.PushIOHandler(io_handler_sp); + } else { + repl_error.SetErrorStringWithFormat( + "Couldn't create a REPL for %s", + Language::GetNameForLanguageType(m_command_options.language)); + result.SetError(repl_error); + return result.Succeeded(); } - history.AppendString(fixed_command); + } } - return true; + } + // No expression following options + else if (expr == nullptr || expr[0] == '\0') { + GetMultilineExpression(); + return result.Succeeded(); + } + } + } + + if (expr == nullptr) + expr = command; + + if (EvaluateExpression(expr, &(result.GetOutputStream()), + &(result.GetErrorStream()), &result)) { + Target *target = m_interpreter.GetExecutionContext().GetTargetPtr(); + if (!m_fixed_expression.empty() && target->GetEnableNotifyAboutFixIts()) { + CommandHistory &history = m_interpreter.GetCommandHistory(); + // FIXME: Can we figure out what the user actually typed (e.g. some alias + // for expr???) + // If we can it would be nice to show that. + std::string fixed_command("expression "); + if (expr == command) + fixed_command.append(m_fixed_expression); + else { + // Add in any options that might have been in the original command: + fixed_command.append(command, expr - command); + fixed_command.append(m_fixed_expression); + } + history.AppendString(fixed_command); } + return true; + } - result.SetStatus (eReturnStatusFailed); - return false; + result.SetStatus(eReturnStatusFailed); + return false; } diff --git a/lldb/source/Commands/CommandObjectExpression.h b/lldb/source/Commands/CommandObjectExpression.h index 9e62783..5b8173f 100644 --- a/lldb/source/Commands/CommandObjectExpression.h +++ b/lldb/source/Commands/CommandObjectExpression.h @@ -14,101 +14,82 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/lldb-private-enumerations.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/ExecutionContext.h" +#include "lldb/lldb-private-enumerations.h" namespace lldb_private { -class CommandObjectExpression : - public CommandObjectRaw, - public IOHandlerDelegate -{ +class CommandObjectExpression : public CommandObjectRaw, + public IOHandlerDelegate { public: + class CommandOptions : public OptionGroup { + public: + CommandOptions(); + + ~CommandOptions() override; + + uint32_t GetNumDefinitions() override; + + const OptionDefinition *GetDefinitions() override; + + Error SetOptionValue(uint32_t option_idx, const char *option_value, + ExecutionContext *execution_context) override; + + void OptionParsingStarting(ExecutionContext *execution_context) override; + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + bool top_level; + bool unwind_on_error; + bool ignore_breakpoints; + bool allow_jit; + bool show_types; + bool show_summary; + bool debug; + uint32_t timeout; + bool try_all_threads; + lldb::LanguageType language; + LanguageRuntimeDescriptionDisplayVerbosity m_verbosity; + LazyBool auto_apply_fixits; + }; + + CommandObjectExpression(CommandInterpreter &interpreter); + + ~CommandObjectExpression() override; - class CommandOptions : public OptionGroup - { - public: - - CommandOptions (); - - ~CommandOptions() override; - - uint32_t - GetNumDefinitions() override; - - const OptionDefinition* - GetDefinitions() override; - - Error - SetOptionValue(uint32_t option_idx, - const char *option_value, - ExecutionContext *execution_context) override; - - void - OptionParsingStarting(ExecutionContext *execution_context) override; - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - bool top_level; - bool unwind_on_error; - bool ignore_breakpoints; - bool allow_jit; - bool show_types; - bool show_summary; - bool debug; - uint32_t timeout; - bool try_all_threads; - lldb::LanguageType language; - LanguageRuntimeDescriptionDisplayVerbosity m_verbosity; - LazyBool auto_apply_fixits; - }; - - CommandObjectExpression (CommandInterpreter &interpreter); - - ~CommandObjectExpression() override; - - Options * - GetOptions() override; + Options *GetOptions() override; protected: - - //------------------------------------------------------------------ - // IOHandler::Delegate functions - //------------------------------------------------------------------ - void - IOHandlerInputComplete(IOHandler &io_handler, - std::string &line) override; - - bool - IOHandlerIsInputComplete (IOHandler &io_handler, - StringList &lines) override; - - bool - DoExecute(const char *command, - CommandReturnObject &result) override; - - bool - EvaluateExpression (const char *expr, - Stream *output_stream, - Stream *error_stream, - CommandReturnObject *result = NULL); - - void - GetMultilineExpression (); - - OptionGroupOptions m_option_group; - OptionGroupFormat m_format_options; - OptionGroupValueObjectDisplay m_varobj_options; - OptionGroupBoolean m_repl_option; - CommandOptions m_command_options; - uint32_t m_expr_line_count; - std::string m_expr_lines; // Multi-line expression support - std::string m_fixed_expression; // Holds the current expression's fixed text. + //------------------------------------------------------------------ + // IOHandler::Delegate functions + //------------------------------------------------------------------ + void IOHandlerInputComplete(IOHandler &io_handler, + std::string &line) override; + + bool IOHandlerIsInputComplete(IOHandler &io_handler, + StringList &lines) override; + + bool DoExecute(const char *command, CommandReturnObject &result) override; + + bool EvaluateExpression(const char *expr, Stream *output_stream, + Stream *error_stream, + CommandReturnObject *result = NULL); + + void GetMultilineExpression(); + + OptionGroupOptions m_option_group; + OptionGroupFormat m_format_options; + OptionGroupValueObjectDisplay m_varobj_options; + OptionGroupBoolean m_repl_option; + CommandOptions m_command_options; + uint32_t m_expr_line_count; + std::string m_expr_lines; // Multi-line expression support + std::string m_fixed_expression; // Holds the current expression's fixed text. }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp index a8e73fb..05b16bc 100644 --- a/lldb/source/Commands/CommandObjectFrame.cpp +++ b/lldb/source/Commands/CommandObjectFrame.cpp @@ -29,12 +29,12 @@ #include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/OptionGroupFormat.h" #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" #include "lldb/Interpreter/OptionGroupVariable.h" -#include "lldb/Symbol/CompilerType.h" +#include "lldb/Interpreter/Options.h" #include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContext.h" @@ -44,8 +44,8 @@ #include "lldb/Target/Process.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/StopInfo.h" -#include "lldb/Target/Thread.h" #include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" #include "lldb/Utility/LLDBAssert.h" using namespace lldb; @@ -61,194 +61,168 @@ using namespace lldb_private; // CommandObjectFrameDiagnose //------------------------------------------------------------------------- -class CommandObjectFrameDiagnose : public CommandObjectParsed -{ +class CommandObjectFrameDiagnose : public CommandObjectParsed { public: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - OptionParsingStarting(nullptr); - } - - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - switch (short_option) - { - case 'r': - reg = ConstString(option_arg); - break; - - case 'a': - { - bool success = false; - - address = StringConvert::ToUInt64 (option_arg, 0, 0, &success); - if (!success) - { - address.reset(); - error.SetErrorStringWithFormat ("invalid address argument '%s'", option_arg); - } - } - break; - - case 'o': - { - bool success = false; - - offset = StringConvert::ToSInt64 (option_arg, 0, 0, &success); - if (!success) - { - offset.reset(); - error.SetErrorStringWithFormat ("invalid offset argument '%s'", option_arg); - } - } - break; - - default: - error.SetErrorStringWithFormat ("invalid short option character '%c'", short_option); - break; - } - - return error; + class CommandOptions : public Options { + public: + CommandOptions() : Options() { OptionParsingStarting(nullptr); } + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + switch (short_option) { + case 'r': + reg = ConstString(option_arg); + break; + + case 'a': { + bool success = false; + + address = StringConvert::ToUInt64(option_arg, 0, 0, &success); + if (!success) { + address.reset(); + error.SetErrorStringWithFormat("invalid address argument '%s'", + option_arg); } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - address.reset(); - reg.reset(); - offset.reset(); - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; + } break; + + case 'o': { + bool success = false; + + offset = StringConvert::ToSInt64(option_arg, 0, 0, &success); + if (!success) { + offset.reset(); + error.SetErrorStringWithFormat("invalid offset argument '%s'", + option_arg); } - - // Options table: Required for subclasses of Options. - static OptionDefinition g_option_table[]; - - // Options. - llvm::Optional<lldb::addr_t> address; - llvm::Optional<ConstString> reg; - llvm::Optional<int64_t> offset; - }; - - CommandObjectFrameDiagnose(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "frame diagnose", - "Try to determine what path path the current stop location used to get to a register or address", - nullptr, eCommandRequiresThread | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | - eCommandProcessMustBePaused), - m_options() - { - CommandArgumentEntry arg; - CommandArgumentData index_arg; - - // Define the first (and only) variant of this arg. - index_arg.arg_type = eArgTypeFrameIndex; - index_arg.arg_repetition = eArgRepeatOptional; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (index_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); + } break; + + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", + short_option); + break; + } + + return error; } - - ~CommandObjectFrameDiagnose() override = default; - - Options * - GetOptions () override - { - return &m_options; + + void OptionParsingStarting(ExecutionContext *execution_context) override { + address.reset(); + reg.reset(); + offset.reset(); } - -protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Thread *thread = m_exe_ctx.GetThreadPtr(); - StackFrameSP frame_sp = thread->GetSelectedFrame(); - - ValueObjectSP valobj_sp; - - if (m_options.address.hasValue()) - { - if (m_options.reg.hasValue() || m_options.offset.hasValue()) - { - result.AppendError("`frame diagnose --address` is incompatible with other arguments."); - result.SetStatus(eReturnStatusFailed); - return false; - } - valobj_sp = frame_sp->GuessValueForAddress(m_options.address.getValue()); - } - else if (m_options.reg.hasValue()) - { - valobj_sp = frame_sp->GuessValueForRegisterAndOffset(m_options.reg.getValue(), m_options.offset.getValueOr(0)); - } - else - { - StopInfoSP stop_info_sp = thread->GetStopInfo(); - if (!stop_info_sp) - { - result.AppendError("No arguments provided, and no stop info."); - result.SetStatus(eReturnStatusFailed); - return false; - } - valobj_sp = StopInfo::GetCrashingDereference(stop_info_sp); - } - - if (!valobj_sp) - { - result.AppendError("No diagnosis available."); - result.SetStatus(eReturnStatusFailed); - return false; - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + static OptionDefinition g_option_table[]; + + // Options. + llvm::Optional<lldb::addr_t> address; + llvm::Optional<ConstString> reg; + llvm::Optional<int64_t> offset; + }; + + CommandObjectFrameDiagnose(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "frame diagnose", + "Try to determine what path path the current stop " + "location used to get to a register or address", + nullptr, + eCommandRequiresThread | eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused), + m_options() { + CommandArgumentEntry arg; + CommandArgumentData index_arg; + + // Define the first (and only) variant of this arg. + index_arg.arg_type = eArgTypeFrameIndex; + index_arg.arg_repetition = eArgRepeatOptional; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(index_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectFrameDiagnose() override = default; + + Options *GetOptions() override { return &m_options; } + +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + Thread *thread = m_exe_ctx.GetThreadPtr(); + StackFrameSP frame_sp = thread->GetSelectedFrame(); + + ValueObjectSP valobj_sp; + + if (m_options.address.hasValue()) { + if (m_options.reg.hasValue() || m_options.offset.hasValue()) { + result.AppendError( + "`frame diagnose --address` is incompatible with other arguments."); + result.SetStatus(eReturnStatusFailed); + return false; + } + valobj_sp = frame_sp->GuessValueForAddress(m_options.address.getValue()); + } else if (m_options.reg.hasValue()) { + valobj_sp = frame_sp->GuessValueForRegisterAndOffset( + m_options.reg.getValue(), m_options.offset.getValueOr(0)); + } else { + StopInfoSP stop_info_sp = thread->GetStopInfo(); + if (!stop_info_sp) { + result.AppendError("No arguments provided, and no stop info."); + result.SetStatus(eReturnStatusFailed); + return false; + } + + valobj_sp = StopInfo::GetCrashingDereference(stop_info_sp); + } - const bool qualify_cxx_base_classes = false; - - DumpValueObjectOptions::DeclPrintingHelper helper = [&valobj_sp, qualify_cxx_base_classes](ConstString type, - ConstString var, - const DumpValueObjectOptions &opts, - Stream &stream) -> bool { - const ValueObject::GetExpressionPathFormat format = ValueObject::GetExpressionPathFormat::eGetExpressionPathFormatHonorPointers; - valobj_sp->GetExpressionPath(stream, qualify_cxx_base_classes, format); - stream.PutCString(" ="); - return true; - }; - - DumpValueObjectOptions options; - options.SetDeclPrintingHelper(helper); - ValueObjectPrinter printer(valobj_sp.get(), &result.GetOutputStream(), options); - printer.PrintValueObject(); - - return true; + if (!valobj_sp) { + result.AppendError("No diagnosis available."); + result.SetStatus(eReturnStatusFailed); + return false; } - + + const bool qualify_cxx_base_classes = false; + + DumpValueObjectOptions::DeclPrintingHelper helper = + [&valobj_sp, qualify_cxx_base_classes]( + ConstString type, ConstString var, + const DumpValueObjectOptions &opts, Stream &stream) -> bool { + const ValueObject::GetExpressionPathFormat format = ValueObject:: + GetExpressionPathFormat::eGetExpressionPathFormatHonorPointers; + valobj_sp->GetExpressionPath(stream, qualify_cxx_base_classes, format); + stream.PutCString(" ="); + return true; + }; + + DumpValueObjectOptions options; + options.SetDeclPrintingHelper(helper); + ValueObjectPrinter printer(valobj_sp.get(), &result.GetOutputStream(), + options); + printer.PrintValueObject(); + + return true; + } + protected: - CommandOptions m_options; + CommandOptions m_options; }; -OptionDefinition -CommandObjectFrameDiagnose::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectFrameDiagnose::CommandOptions::g_option_table[] = + { + // clang-format off {LLDB_OPT_SET_1, false, "register", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegisterName, "A register to diagnose."}, {LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddress, "An address to diagnose."}, {LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "An optional offset. Requires --register."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; #pragma mark CommandObjectFrameInfo @@ -257,27 +231,24 @@ CommandObjectFrameDiagnose::CommandOptions::g_option_table[] = // CommandObjectFrameInfo //------------------------------------------------------------------------- -class CommandObjectFrameInfo : public CommandObjectParsed -{ +class CommandObjectFrameInfo : public CommandObjectParsed { public: - CommandObjectFrameInfo(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "frame info", - "List information about the current stack frame in the current thread.", "frame info", - eCommandRequiresFrame | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | - eCommandProcessMustBePaused) - { - } + CommandObjectFrameInfo(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "frame info", "List information about the current " + "stack frame in the current thread.", + "frame info", + eCommandRequiresFrame | eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} - ~CommandObjectFrameInfo() override = default; + ~CommandObjectFrameInfo() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat (&result.GetOutputStream()); - result.SetStatus (eReturnStatusSuccessFinishResult); - return result.Succeeded(); - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat(&result.GetOutputStream()); + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); + } }; #pragma mark CommandObjectFrameSelect @@ -286,521 +257,484 @@ protected: // CommandObjectFrameSelect //------------------------------------------------------------------------- -class CommandObjectFrameSelect : public CommandObjectParsed -{ +class CommandObjectFrameSelect : public CommandObjectParsed { public: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - OptionParsingStarting(nullptr); - } - - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - bool success = false; - const int short_option = m_getopt_table[option_idx].val; - switch (short_option) - { - case 'r': - relative_frame_offset = StringConvert::ToSInt32 (option_arg, INT32_MIN, 0, &success); - if (!success) - error.SetErrorStringWithFormat ("invalid frame offset argument '%s'", option_arg); - break; - - default: - error.SetErrorStringWithFormat ("invalid short option character '%c'", short_option); - break; - } - - return error; - } + class CommandOptions : public Options { + public: + CommandOptions() : Options() { OptionParsingStarting(nullptr); } + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + bool success = false; + const int short_option = m_getopt_table[option_idx].val; + switch (short_option) { + case 'r': + relative_frame_offset = + StringConvert::ToSInt32(option_arg, INT32_MIN, 0, &success); + if (!success) + error.SetErrorStringWithFormat("invalid frame offset argument '%s'", + option_arg); + break; + + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", + short_option); + break; + } + + return error; + } - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - relative_frame_offset = INT32_MIN; - } + void OptionParsingStarting(ExecutionContext *execution_context) override { + relative_frame_offset = INT32_MIN; + } - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } - // Options table: Required for subclasses of Options. + // Options table: Required for subclasses of Options. - static OptionDefinition g_option_table[]; - int32_t relative_frame_offset; - }; + static OptionDefinition g_option_table[]; + int32_t relative_frame_offset; + }; - CommandObjectFrameSelect(CommandInterpreter &interpreter) - : CommandObjectParsed( - interpreter, "frame select", - "Select the current stack frame by index from within the current thread (see 'thread backtrace'.)", - nullptr, eCommandRequiresThread | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | - eCommandProcessMustBePaused), - m_options() - { - CommandArgumentEntry arg; - CommandArgumentData index_arg; + CommandObjectFrameSelect(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "frame select", "Select the current stack frame by " + "index from within the current thread " + "(see 'thread backtrace'.)", + nullptr, + eCommandRequiresThread | eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), + m_options() { + CommandArgumentEntry arg; + CommandArgumentData index_arg; - // Define the first (and only) variant of this arg. - index_arg.arg_type = eArgTypeFrameIndex; - index_arg.arg_repetition = eArgRepeatOptional; + // Define the first (and only) variant of this arg. + index_arg.arg_type = eArgTypeFrameIndex; + index_arg.arg_repetition = eArgRepeatOptional; - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (index_arg); + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(index_arg); - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - } + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } - ~CommandObjectFrameSelect() override = default; + ~CommandObjectFrameSelect() override = default; - Options * - GetOptions () override - { - return &m_options; - } + Options *GetOptions() override { return &m_options; } protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - // No need to check "thread" for validity as eCommandRequiresThread ensures it is valid - Thread *thread = m_exe_ctx.GetThreadPtr(); - - uint32_t frame_idx = UINT32_MAX; - if (m_options.relative_frame_offset != INT32_MIN) - { - // The one and only argument is a signed relative frame index - frame_idx = thread->GetSelectedFrameIndex (); - if (frame_idx == UINT32_MAX) - frame_idx = 0; - - if (m_options.relative_frame_offset < 0) - { - if (static_cast<int32_t>(frame_idx) >= -m_options.relative_frame_offset) - frame_idx += m_options.relative_frame_offset; - else - { - if (frame_idx == 0) - { - //If you are already at the bottom of the stack, then just warn and don't reset the frame. - result.AppendError("Already at the bottom of the stack."); - result.SetStatus(eReturnStatusFailed); - return false; - } - else - frame_idx = 0; - } - } - else if (m_options.relative_frame_offset > 0) - { - // I don't want "up 20" where "20" takes you past the top of the stack to produce - // an error, but rather to just go to the top. So I have to count the stack here... - const uint32_t num_frames = thread->GetStackFrameCount(); - if (static_cast<int32_t>(num_frames - frame_idx) > m_options.relative_frame_offset) - frame_idx += m_options.relative_frame_offset; - else - { - if (frame_idx == num_frames - 1) - { - //If we are already at the top of the stack, just warn and don't reset the frame. - result.AppendError("Already at the top of the stack."); - result.SetStatus(eReturnStatusFailed); - return false; - } - else - frame_idx = num_frames - 1; - } - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + // No need to check "thread" for validity as eCommandRequiresThread ensures + // it is valid + Thread *thread = m_exe_ctx.GetThreadPtr(); + + uint32_t frame_idx = UINT32_MAX; + if (m_options.relative_frame_offset != INT32_MIN) { + // The one and only argument is a signed relative frame index + frame_idx = thread->GetSelectedFrameIndex(); + if (frame_idx == UINT32_MAX) + frame_idx = 0; + + if (m_options.relative_frame_offset < 0) { + if (static_cast<int32_t>(frame_idx) >= -m_options.relative_frame_offset) + frame_idx += m_options.relative_frame_offset; + else { + if (frame_idx == 0) { + // If you are already at the bottom of the stack, then just warn and + // don't reset the frame. + result.AppendError("Already at the bottom of the stack."); + result.SetStatus(eReturnStatusFailed); + return false; + } else + frame_idx = 0; } - else - { - if (command.GetArgumentCount() == 1) - { - const char *frame_idx_cstr = command.GetArgumentAtIndex(0); - bool success = false; - frame_idx = StringConvert::ToUInt32 (frame_idx_cstr, UINT32_MAX, 0, &success); - if (!success) - { - result.AppendErrorWithFormat("invalid frame index argument '%s'.", frame_idx_cstr); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - else if (command.GetArgumentCount() == 0) - { - frame_idx = thread->GetSelectedFrameIndex (); - if (frame_idx == UINT32_MAX) - { - frame_idx = 0; - } - } - else - { - result.AppendErrorWithFormat ("too many arguments; expected frame-index, saw '%s'.\n", - command.GetArgumentAtIndex(0)); - m_options.GenerateOptionUsage(result.GetErrorStream(), this, - GetCommandInterpreter() - .GetDebugger() - .GetTerminalWidth()); - return false; - } + } else if (m_options.relative_frame_offset > 0) { + // I don't want "up 20" where "20" takes you past the top of the stack + // to produce + // an error, but rather to just go to the top. So I have to count the + // stack here... + const uint32_t num_frames = thread->GetStackFrameCount(); + if (static_cast<int32_t>(num_frames - frame_idx) > + m_options.relative_frame_offset) + frame_idx += m_options.relative_frame_offset; + else { + if (frame_idx == num_frames - 1) { + // If we are already at the top of the stack, just warn and don't + // reset the frame. + result.AppendError("Already at the top of the stack."); + result.SetStatus(eReturnStatusFailed); + return false; + } else + frame_idx = num_frames - 1; } - - bool success = thread->SetSelectedFrameByIndexNoisily (frame_idx, result.GetOutputStream()); - if (success) - { - m_exe_ctx.SetFrameSP(thread->GetSelectedFrame ()); - result.SetStatus (eReturnStatusSuccessFinishResult); + } + } else { + if (command.GetArgumentCount() == 1) { + const char *frame_idx_cstr = command.GetArgumentAtIndex(0); + bool success = false; + frame_idx = + StringConvert::ToUInt32(frame_idx_cstr, UINT32_MAX, 0, &success); + if (!success) { + result.AppendErrorWithFormat("invalid frame index argument '%s'.", + frame_idx_cstr); + result.SetStatus(eReturnStatusFailed); + return false; } - else - { - result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx); - result.SetStatus (eReturnStatusFailed); + } else if (command.GetArgumentCount() == 0) { + frame_idx = thread->GetSelectedFrameIndex(); + if (frame_idx == UINT32_MAX) { + frame_idx = 0; } - - return result.Succeeded(); + } else { + result.AppendErrorWithFormat( + "too many arguments; expected frame-index, saw '%s'.\n", + command.GetArgumentAtIndex(0)); + m_options.GenerateOptionUsage( + result.GetErrorStream(), this, + GetCommandInterpreter().GetDebugger().GetTerminalWidth()); + return false; + } + } + + bool success = thread->SetSelectedFrameByIndexNoisily( + frame_idx, result.GetOutputStream()); + if (success) { + m_exe_ctx.SetFrameSP(thread->GetSelectedFrame()); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat("Frame index (%u) out of range.\n", + frame_idx); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } + protected: - CommandOptions m_options; + CommandOptions m_options; }; -OptionDefinition -CommandObjectFrameSelect::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectFrameSelect::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "relative", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "A relative frame index offset from the current frame index."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; #pragma mark CommandObjectFrameVariable //---------------------------------------------------------------------- // List images with associated information //---------------------------------------------------------------------- -class CommandObjectFrameVariable : public CommandObjectParsed -{ +class CommandObjectFrameVariable : public CommandObjectParsed { public: - CommandObjectFrameVariable(CommandInterpreter &interpreter) - : CommandObjectParsed( - interpreter, "frame variable", "Show variables for the current stack frame. Defaults to all " - "arguments and local variables in scope. Names of argument, " - "local, file static and file global variables can be specified. " - "Children of aggregate variables can be specified such as " - "'var->child.x'.", - nullptr, eCommandRequiresFrame | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | - eCommandProcessMustBePaused | eCommandRequiresProcess), - m_option_group(), - m_option_variable(true), // Include the frame specific options by passing "true" - m_option_format(eFormatDefault), - m_varobj_options() - { - CommandArgumentEntry arg; - CommandArgumentData var_name_arg; - - // Define the first (and only) variant of this arg. - var_name_arg.arg_type = eArgTypeVarName; - var_name_arg.arg_repetition = eArgRepeatStar; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (var_name_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - - m_option_group.Append (&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Append (&m_option_format, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_1); - m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Finalize(); - } - - ~CommandObjectFrameVariable() override = default; - - Options * - GetOptions () override - { - return &m_option_group; - } - - int - HandleArgumentCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - OptionElementVector &opt_element_vector, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) override - { - // Arguments are the standard source file completer. - std::string completion_str (input.GetArgumentAtIndex(cursor_index)); - completion_str.erase (cursor_char_position); - - CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(), - CommandCompletions::eVariablePathCompletion, - completion_str.c_str(), - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - return matches.GetSize(); - } + CommandObjectFrameVariable(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "frame variable", + "Show variables for the current stack frame. Defaults to all " + "arguments and local variables in scope. Names of argument, " + "local, file static and file global variables can be specified. " + "Children of aggregate variables can be specified such as " + "'var->child.x'.", + nullptr, eCommandRequiresFrame | eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused | eCommandRequiresProcess), + m_option_group(), + m_option_variable( + true), // Include the frame specific options by passing "true" + m_option_format(eFormatDefault), + m_varobj_options() { + CommandArgumentEntry arg; + CommandArgumentData var_name_arg; + + // Define the first (and only) variant of this arg. + var_name_arg.arg_type = eArgTypeVarName; + var_name_arg.arg_repetition = eArgRepeatStar; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(var_name_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + + m_option_group.Append(&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append(&m_option_format, + OptionGroupFormat::OPTION_GROUP_FORMAT | + OptionGroupFormat::OPTION_GROUP_GDB_FMT, + LLDB_OPT_SET_1); + m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Finalize(); + } + + ~CommandObjectFrameVariable() override = default; + + Options *GetOptions() override { return &m_option_group; } + + int HandleArgumentCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, int max_return_elements, + bool &word_complete, + StringList &matches) override { + // Arguments are the standard source file completer. + std::string completion_str(input.GetArgumentAtIndex(cursor_index)); + completion_str.erase(cursor_char_position); + + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eVariablePathCompletion, + completion_str.c_str(), match_start_point, max_return_elements, nullptr, + word_complete, matches); + return matches.GetSize(); + } protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - // No need to check "frame" for validity as eCommandRequiresFrame ensures it is valid - StackFrame *frame = m_exe_ctx.GetFramePtr(); - - Stream &s = result.GetOutputStream(); - - // Be careful about the stack frame, if any summary formatter runs code, it might clear the StackFrameList - // for the thread. So hold onto a shared pointer to the frame so it stays alive. - - VariableList *variable_list = frame->GetVariableList (m_option_variable.show_globals); - - VariableSP var_sp; - ValueObjectSP valobj_sp; - - const char *name_cstr = nullptr; - size_t idx; - - TypeSummaryImplSP summary_format_sp; - if (!m_option_variable.summary.IsCurrentValueEmpty()) - DataVisualization::NamedSummaryFormats::GetSummaryFormat(ConstString(m_option_variable.summary.GetCurrentValue()), summary_format_sp); - else if (!m_option_variable.summary_string.IsCurrentValueEmpty()) - summary_format_sp.reset(new StringSummaryFormat(TypeSummaryImpl::Flags(),m_option_variable.summary_string.GetCurrentValue())); - - DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,eFormatDefault,summary_format_sp)); - - const SymbolContext& sym_ctx = frame->GetSymbolContext(eSymbolContextFunction); - if (sym_ctx.function && sym_ctx.function->IsTopLevelFunction()) - m_option_variable.show_globals = true; - - if (variable_list) - { - const Format format = m_option_format.GetFormat(); - options.SetFormat(format); - - if (command.GetArgumentCount() > 0) - { - VariableList regex_var_list; - - // If we have any args to the variable command, we will make - // variable objects from them... - for (idx = 0; (name_cstr = command.GetArgumentAtIndex(idx)) != nullptr; ++idx) - { - if (m_option_variable.use_regex) - { - const size_t regex_start_index = regex_var_list.GetSize(); - RegularExpression regex (name_cstr); - if (regex.Compile(name_cstr)) - { - size_t num_matches = 0; - const size_t num_new_regex_vars = variable_list->AppendVariablesIfUnique(regex, - regex_var_list, - num_matches); - if (num_new_regex_vars > 0) - { - for (size_t regex_idx = regex_start_index, end_index = regex_var_list.GetSize(); - regex_idx < end_index; - ++regex_idx) - { - var_sp = regex_var_list.GetVariableAtIndex (regex_idx); - if (var_sp) - { - valobj_sp = frame->GetValueObjectForFrameVariable (var_sp, m_varobj_options.use_dynamic); - if (valobj_sp) - { -// if (format != eFormatDefault) -// valobj_sp->SetFormat (format); - - if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile()) - { - bool show_fullpaths = false; - bool show_module = true; - if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module)) - s.PutCString (": "); - } - valobj_sp->Dump(result.GetOutputStream(),options); - } - } - } - } - else if (num_matches == 0) - { - result.GetErrorStream().Printf ("error: no variables matched the regular expression '%s'.\n", name_cstr); - } - } - else - { - char regex_error[1024]; - if (regex.GetErrorAsCString(regex_error, sizeof(regex_error))) - result.GetErrorStream().Printf ("error: %s\n", regex_error); - else - result.GetErrorStream().Printf ("error: unknown regex error when compiling '%s'\n", name_cstr); - } - } - else // No regex, either exact variable names or variable expressions. - { - Error error; - uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember | - StackFrame::eExpressionPathOptionsAllowDirectIVarAccess | - StackFrame::eExpressionPathOptionsInspectAnonymousUnions; - lldb::VariableSP var_sp; - valobj_sp = frame->GetValueForVariableExpressionPath (name_cstr, - m_varobj_options.use_dynamic, - expr_path_options, - var_sp, - error); - if (valobj_sp) - { -// if (format != eFormatDefault) -// valobj_sp->SetFormat (format); - if (m_option_variable.show_decl && var_sp && var_sp->GetDeclaration ().GetFile()) - { - var_sp->GetDeclaration ().DumpStopContext (&s, false); - s.PutCString (": "); - } - - options.SetFormat(format); - options.SetVariableFormatDisplayLanguage(valobj_sp->GetPreferredDisplayLanguage()); - - Stream &output_stream = result.GetOutputStream(); - options.SetRootValueObjectName(valobj_sp->GetParent() ? name_cstr : nullptr); - valobj_sp->Dump(output_stream,options); - } - else - { - const char *error_cstr = error.AsCString(nullptr); - if (error_cstr) - result.GetErrorStream().Printf("error: %s\n", error_cstr); - else - result.GetErrorStream().Printf( - "error: unable to find any variable expression path that matches '%s'.\n", - name_cstr); - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + // No need to check "frame" for validity as eCommandRequiresFrame ensures it + // is valid + StackFrame *frame = m_exe_ctx.GetFramePtr(); + + Stream &s = result.GetOutputStream(); + + // Be careful about the stack frame, if any summary formatter runs code, it + // might clear the StackFrameList + // for the thread. So hold onto a shared pointer to the frame so it stays + // alive. + + VariableList *variable_list = + frame->GetVariableList(m_option_variable.show_globals); + + VariableSP var_sp; + ValueObjectSP valobj_sp; + + const char *name_cstr = nullptr; + size_t idx; + + TypeSummaryImplSP summary_format_sp; + if (!m_option_variable.summary.IsCurrentValueEmpty()) + DataVisualization::NamedSummaryFormats::GetSummaryFormat( + ConstString(m_option_variable.summary.GetCurrentValue()), + summary_format_sp); + else if (!m_option_variable.summary_string.IsCurrentValueEmpty()) + summary_format_sp.reset(new StringSummaryFormat( + TypeSummaryImpl::Flags(), + m_option_variable.summary_string.GetCurrentValue())); + + DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions( + eLanguageRuntimeDescriptionDisplayVerbosityFull, eFormatDefault, + summary_format_sp)); + + const SymbolContext &sym_ctx = + frame->GetSymbolContext(eSymbolContextFunction); + if (sym_ctx.function && sym_ctx.function->IsTopLevelFunction()) + m_option_variable.show_globals = true; + + if (variable_list) { + const Format format = m_option_format.GetFormat(); + options.SetFormat(format); + + if (command.GetArgumentCount() > 0) { + VariableList regex_var_list; + + // If we have any args to the variable command, we will make + // variable objects from them... + for (idx = 0; (name_cstr = command.GetArgumentAtIndex(idx)) != nullptr; + ++idx) { + if (m_option_variable.use_regex) { + const size_t regex_start_index = regex_var_list.GetSize(); + RegularExpression regex(name_cstr); + if (regex.Compile(name_cstr)) { + size_t num_matches = 0; + const size_t num_new_regex_vars = + variable_list->AppendVariablesIfUnique(regex, regex_var_list, + num_matches); + if (num_new_regex_vars > 0) { + for (size_t regex_idx = regex_start_index, + end_index = regex_var_list.GetSize(); + regex_idx < end_index; ++regex_idx) { + var_sp = regex_var_list.GetVariableAtIndex(regex_idx); + if (var_sp) { + valobj_sp = frame->GetValueObjectForFrameVariable( + var_sp, m_varobj_options.use_dynamic); + if (valobj_sp) { + // if (format + // != + // eFormatDefault) + // valobj_sp->SetFormat + // (format); + + if (m_option_variable.show_decl && + var_sp->GetDeclaration().GetFile()) { + bool show_fullpaths = false; + bool show_module = true; + if (var_sp->DumpDeclaration(&s, show_fullpaths, + show_module)) + s.PutCString(": "); + } + valobj_sp->Dump(result.GetOutputStream(), options); } + } } + } else if (num_matches == 0) { + result.GetErrorStream().Printf("error: no variables matched " + "the regular expression '%s'.\n", + name_cstr); + } + } else { + char regex_error[1024]; + if (regex.GetErrorAsCString(regex_error, sizeof(regex_error))) + result.GetErrorStream().Printf("error: %s\n", regex_error); + else + result.GetErrorStream().Printf( + "error: unknown regex error when compiling '%s'\n", + name_cstr); } - else // No command arg specified. Use variable_list, instead. - { - const size_t num_variables = variable_list->GetSize(); - if (num_variables > 0) - { - for (size_t i=0; i<num_variables; i++) - { - var_sp = variable_list->GetVariableAtIndex(i); - bool dump_variable = true; - std::string scope_string; - switch (var_sp->GetScope()) - { - case eValueTypeVariableGlobal: - // Always dump globals since we only fetched them if - // m_option_variable.show_scope was true - if (dump_variable && m_option_variable.show_scope) - scope_string = "GLOBAL: "; - break; - - case eValueTypeVariableStatic: - // Always dump globals since we only fetched them if - // m_option_variable.show_scope was true, or this is - // a static variable from a block in the current scope - if (dump_variable && m_option_variable.show_scope) - scope_string = "STATIC: "; - break; - - case eValueTypeVariableArgument: - dump_variable = m_option_variable.show_args; - if (dump_variable && m_option_variable.show_scope) - scope_string = " ARG: "; - break; - - case eValueTypeVariableLocal: - dump_variable = m_option_variable.show_locals; - if (dump_variable && m_option_variable.show_scope) - scope_string = " LOCAL: "; - break; - - case eValueTypeVariableThreadLocal: - if (dump_variable && m_option_variable.show_scope) - scope_string = "THREAD: "; - break; - default: - break; - } - - if (dump_variable) - { - // Use the variable object code to make sure we are - // using the same APIs as the public API will be - // using... - valobj_sp = frame->GetValueObjectForFrameVariable (var_sp, - m_varobj_options.use_dynamic); - if (valobj_sp) - { -// if (format != eFormatDefault) -// valobj_sp->SetFormat (format); - - // When dumping all variables, don't print any variables - // that are not in scope to avoid extra unneeded output - if (valobj_sp->IsInScope ()) - { - if (!valobj_sp->GetTargetSP()->GetDisplayRuntimeSupportValues() && - valobj_sp->IsRuntimeSupportValue()) - continue; - - if (!scope_string.empty()) - s.PutCString(scope_string.c_str()); - - if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile()) - { - var_sp->GetDeclaration ().DumpStopContext (&s, false); - s.PutCString (": "); - } - - options.SetFormat(format); - options.SetVariableFormatDisplayLanguage(valobj_sp->GetPreferredDisplayLanguage()); - options.SetRootValueObjectName(name_cstr); - valobj_sp->Dump(result.GetOutputStream(),options); - } - } - } - } - } + } else // No regex, either exact variable names or variable + // expressions. + { + Error error; + uint32_t expr_path_options = + StackFrame::eExpressionPathOptionCheckPtrVsMember | + StackFrame::eExpressionPathOptionsAllowDirectIVarAccess | + StackFrame::eExpressionPathOptionsInspectAnonymousUnions; + lldb::VariableSP var_sp; + valobj_sp = frame->GetValueForVariableExpressionPath( + name_cstr, m_varobj_options.use_dynamic, expr_path_options, + var_sp, error); + if (valobj_sp) { + // if (format != eFormatDefault) + // valobj_sp->SetFormat (format); + if (m_option_variable.show_decl && var_sp && + var_sp->GetDeclaration().GetFile()) { + var_sp->GetDeclaration().DumpStopContext(&s, false); + s.PutCString(": "); + } + + options.SetFormat(format); + options.SetVariableFormatDisplayLanguage( + valobj_sp->GetPreferredDisplayLanguage()); + + Stream &output_stream = result.GetOutputStream(); + options.SetRootValueObjectName(valobj_sp->GetParent() ? name_cstr + : nullptr); + valobj_sp->Dump(output_stream, options); + } else { + const char *error_cstr = error.AsCString(nullptr); + if (error_cstr) + result.GetErrorStream().Printf("error: %s\n", error_cstr); + else + result.GetErrorStream().Printf("error: unable to find any " + "variable expression path that " + "matches '%s'.\n", + name_cstr); } - result.SetStatus (eReturnStatusSuccessFinishResult); + } } - - if (m_interpreter.TruncationWarningNecessary()) - { - result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(), - m_cmd_name.c_str()); - m_interpreter.TruncationWarningGiven(); + } else // No command arg specified. Use variable_list, instead. + { + const size_t num_variables = variable_list->GetSize(); + if (num_variables > 0) { + for (size_t i = 0; i < num_variables; i++) { + var_sp = variable_list->GetVariableAtIndex(i); + bool dump_variable = true; + std::string scope_string; + switch (var_sp->GetScope()) { + case eValueTypeVariableGlobal: + // Always dump globals since we only fetched them if + // m_option_variable.show_scope was true + if (dump_variable && m_option_variable.show_scope) + scope_string = "GLOBAL: "; + break; + + case eValueTypeVariableStatic: + // Always dump globals since we only fetched them if + // m_option_variable.show_scope was true, or this is + // a static variable from a block in the current scope + if (dump_variable && m_option_variable.show_scope) + scope_string = "STATIC: "; + break; + + case eValueTypeVariableArgument: + dump_variable = m_option_variable.show_args; + if (dump_variable && m_option_variable.show_scope) + scope_string = " ARG: "; + break; + + case eValueTypeVariableLocal: + dump_variable = m_option_variable.show_locals; + if (dump_variable && m_option_variable.show_scope) + scope_string = " LOCAL: "; + break; + + case eValueTypeVariableThreadLocal: + if (dump_variable && m_option_variable.show_scope) + scope_string = "THREAD: "; + break; + default: + break; + } + + if (dump_variable) { + // Use the variable object code to make sure we are + // using the same APIs as the public API will be + // using... + valobj_sp = frame->GetValueObjectForFrameVariable( + var_sp, m_varobj_options.use_dynamic); + if (valobj_sp) { + // if (format != eFormatDefault) + // valobj_sp->SetFormat + // (format); + + // When dumping all variables, don't print any variables + // that are not in scope to avoid extra unneeded output + if (valobj_sp->IsInScope()) { + if (!valobj_sp->GetTargetSP() + ->GetDisplayRuntimeSupportValues() && + valobj_sp->IsRuntimeSupportValue()) + continue; + + if (!scope_string.empty()) + s.PutCString(scope_string.c_str()); + + if (m_option_variable.show_decl && + var_sp->GetDeclaration().GetFile()) { + var_sp->GetDeclaration().DumpStopContext(&s, false); + s.PutCString(": "); + } + + options.SetFormat(format); + options.SetVariableFormatDisplayLanguage( + valobj_sp->GetPreferredDisplayLanguage()); + options.SetRootValueObjectName(name_cstr); + valobj_sp->Dump(result.GetOutputStream(), options); + } + } + } + } } - - return result.Succeeded(); + } + result.SetStatus(eReturnStatusSuccessFinishResult); } + if (m_interpreter.TruncationWarningNecessary()) { + result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(), + m_cmd_name.c_str()); + m_interpreter.TruncationWarningGiven(); + } + + return result.Succeeded(); + } + protected: - OptionGroupOptions m_option_group; - OptionGroupVariable m_option_variable; - OptionGroupFormat m_option_format; - OptionGroupValueObjectDisplay m_varobj_options; + OptionGroupOptions m_option_group; + OptionGroupVariable m_option_variable; + OptionGroupFormat m_option_format; + OptionGroupValueObjectDisplay m_varobj_options; }; #pragma mark CommandObjectMultiwordFrame @@ -809,15 +743,20 @@ protected: // CommandObjectMultiwordFrame //------------------------------------------------------------------------- -CommandObjectMultiwordFrame::CommandObjectMultiwordFrame(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "frame", - "Commands for selecting and examing the current thread's stack frames.", - "frame <subcommand> [<subcommand-options>]") -{ - LoadSubCommand ("diagnose", CommandObjectSP (new CommandObjectFrameDiagnose (interpreter))); - LoadSubCommand ("info", CommandObjectSP (new CommandObjectFrameInfo (interpreter))); - LoadSubCommand ("select", CommandObjectSP (new CommandObjectFrameSelect (interpreter))); - LoadSubCommand ("variable", CommandObjectSP (new CommandObjectFrameVariable (interpreter))); +CommandObjectMultiwordFrame::CommandObjectMultiwordFrame( + CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "frame", "Commands for selecting and " + "examing the current " + "thread's stack frames.", + "frame <subcommand> [<subcommand-options>]") { + LoadSubCommand("diagnose", + CommandObjectSP(new CommandObjectFrameDiagnose(interpreter))); + LoadSubCommand("info", + CommandObjectSP(new CommandObjectFrameInfo(interpreter))); + LoadSubCommand("select", + CommandObjectSP(new CommandObjectFrameSelect(interpreter))); + LoadSubCommand("variable", + CommandObjectSP(new CommandObjectFrameVariable(interpreter))); } CommandObjectMultiwordFrame::~CommandObjectMultiwordFrame() = default; diff --git a/lldb/source/Commands/CommandObjectFrame.h b/lldb/source/Commands/CommandObjectFrame.h index a729880..875bcc9 100644 --- a/lldb/source/Commands/CommandObjectFrame.h +++ b/lldb/source/Commands/CommandObjectFrame.h @@ -14,9 +14,9 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Interpreter/Options.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Interpreter/CommandObjectMultiword.h" +#include "lldb/Interpreter/Options.h" namespace lldb_private { @@ -24,13 +24,11 @@ namespace lldb_private { // CommandObjectMultiwordFrame //------------------------------------------------------------------------- -class CommandObjectMultiwordFrame : public CommandObjectMultiword -{ +class CommandObjectMultiwordFrame : public CommandObjectMultiword { public: + CommandObjectMultiwordFrame(CommandInterpreter &interpreter); - CommandObjectMultiwordFrame (CommandInterpreter &interpreter); - - ~CommandObjectMultiwordFrame() override; + ~CommandObjectMultiwordFrame() override; }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectGUI.cpp b/lldb/source/Commands/CommandObjectGUI.cpp index 0991c7e..d65e12e 100644 --- a/lldb/source/Commands/CommandObjectGUI.cpp +++ b/lldb/source/Commands/CommandObjectGUI.cpp @@ -13,9 +13,9 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/lldb-private.h" using namespace lldb; using namespace lldb_private; @@ -24,48 +24,35 @@ using namespace lldb_private; // CommandObjectGUI //------------------------------------------------------------------------- -CommandObjectGUI::CommandObjectGUI (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, "gui", "Switch into the curses based GUI mode.", "gui") -{ -} +CommandObjectGUI::CommandObjectGUI(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "gui", + "Switch into the curses based GUI mode.", "gui") {} -CommandObjectGUI::~CommandObjectGUI () -{ -} +CommandObjectGUI::~CommandObjectGUI() {} -bool -CommandObjectGUI::DoExecute (Args& args, CommandReturnObject &result) -{ +bool CommandObjectGUI::DoExecute(Args &args, CommandReturnObject &result) { #ifndef LLDB_DISABLE_CURSES - if (args.GetArgumentCount() == 0) - { - Debugger &debugger = m_interpreter.GetDebugger(); - - lldb::StreamFileSP input_sp = debugger.GetInputFile(); - if (input_sp && - input_sp->GetFile().GetIsRealTerminal() && - input_sp->GetFile().GetIsInteractive()) - { - IOHandlerSP io_handler_sp (new IOHandlerCursesGUI (debugger)); - if (io_handler_sp) - debugger.PushIOHandler(io_handler_sp); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendError("the gui command requires an interactive terminal."); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendError("the gui command takes no arguments."); - result.SetStatus (eReturnStatusFailed); + if (args.GetArgumentCount() == 0) { + Debugger &debugger = m_interpreter.GetDebugger(); + + lldb::StreamFileSP input_sp = debugger.GetInputFile(); + if (input_sp && input_sp->GetFile().GetIsRealTerminal() && + input_sp->GetFile().GetIsInteractive()) { + IOHandlerSP io_handler_sp(new IOHandlerCursesGUI(debugger)); + if (io_handler_sp) + debugger.PushIOHandler(io_handler_sp); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendError("the gui command requires an interactive terminal."); + result.SetStatus(eReturnStatusFailed); } - return true; + } else { + result.AppendError("the gui command takes no arguments."); + result.SetStatus(eReturnStatusFailed); + } + return true; #else - result.AppendError("lldb was not build with gui support"); - return false; + result.AppendError("lldb was not build with gui support"); + return false; #endif } - diff --git a/lldb/source/Commands/CommandObjectGUI.h b/lldb/source/Commands/CommandObjectGUI.h index 494bcc4..c71558f 100644 --- a/lldb/source/Commands/CommandObjectGUI.h +++ b/lldb/source/Commands/CommandObjectGUI.h @@ -22,18 +22,14 @@ namespace lldb_private { // CommandObjectGUI //------------------------------------------------------------------------- -class CommandObjectGUI : public CommandObjectParsed -{ +class CommandObjectGUI : public CommandObjectParsed { public: + CommandObjectGUI(CommandInterpreter &interpreter); - CommandObjectGUI (CommandInterpreter &interpreter); - - ~CommandObjectGUI() override; + ~CommandObjectGUI() override; protected: - bool - DoExecute(Args& args, - CommandReturnObject &result) override; + bool DoExecute(Args &args, CommandReturnObject &result) override; }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectHelp.cpp b/lldb/source/Commands/CommandObjectHelp.cpp index 91470f5..8e91888 100644 --- a/lldb/source/Commands/CommandObjectHelp.cpp +++ b/lldb/source/Commands/CommandObjectHelp.cpp @@ -12,10 +12,10 @@ // Other libraries and framework includes // Project includes #include "CommandObjectHelp.h" -#include "lldb/Interpreter/CommandObjectMultiword.h" #include "lldb/Interpreter/CommandInterpreter.h" -#include "lldb/Interpreter/Options.h" +#include "lldb/Interpreter/CommandObjectMultiword.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Interpreter/Options.h" using namespace lldb; using namespace lldb_private; @@ -24,254 +24,216 @@ using namespace lldb_private; // CommandObjectHelp //------------------------------------------------------------------------- -void -CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage (Stream *s, - const char* command, - const char* prefix, - const char* subcommand, - bool include_apropos, - bool include_type_lookup) -{ - if (s && command && *command) - { - s->Printf("'%s' is not a known command.\n", command); - s->Printf("Try '%shelp' to see a current list of commands.\n", prefix ? prefix : ""); - if (include_apropos) - { - s->Printf("Try '%sapropos %s' for a list of related commands.\n", - prefix ? prefix : "", subcommand ? subcommand : command); - } - if (include_type_lookup) - { - s->Printf("Try '%stype lookup %s' for information on types, methods, functions, modules, etc.", - prefix ? prefix : "", subcommand ? subcommand : command); - } +void CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage( + Stream *s, const char *command, const char *prefix, const char *subcommand, + bool include_apropos, bool include_type_lookup) { + if (s && command && *command) { + s->Printf("'%s' is not a known command.\n", command); + s->Printf("Try '%shelp' to see a current list of commands.\n", + prefix ? prefix : ""); + if (include_apropos) { + s->Printf("Try '%sapropos %s' for a list of related commands.\n", + prefix ? prefix : "", subcommand ? subcommand : command); + } + if (include_type_lookup) { + s->Printf("Try '%stype lookup %s' for information on types, methods, " + "functions, modules, etc.", + prefix ? prefix : "", subcommand ? subcommand : command); } + } } CommandObjectHelp::CommandObjectHelp(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "help", - "Show a list of all debugger commands, or give details about a specific command.", + : CommandObjectParsed(interpreter, "help", "Show a list of all debugger " + "commands, or give details " + "about a specific command.", "help [<cmd-name>]"), - m_options() -{ - CommandArgumentEntry arg; - CommandArgumentData command_arg; + m_options() { + CommandArgumentEntry arg; + CommandArgumentData command_arg; - // Define the first (and only) variant of this arg. - command_arg.arg_type = eArgTypeCommandName; - command_arg.arg_repetition = eArgRepeatStar; + // Define the first (and only) variant of this arg. + command_arg.arg_type = eArgTypeCommandName; + command_arg.arg_repetition = eArgRepeatStar; - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (command_arg); + // There is only one variant this argument could be; put it into the argument + // entry. + arg.push_back(command_arg); - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); } CommandObjectHelp::~CommandObjectHelp() = default; -OptionDefinition -CommandObjectHelp::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectHelp::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_ALL, false, "hide-aliases", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Hide aliases in the command list."}, {LLDB_OPT_SET_ALL, false, "hide-user-commands", 'u', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Hide user-defined commands from the list."}, {LLDB_OPT_SET_ALL, false, "show-hidden-commands", 'h', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Include commands prefixed with an underscore."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; -bool -CommandObjectHelp::DoExecute (Args& command, CommandReturnObject &result) -{ - CommandObject::CommandMap::iterator pos; - CommandObject *cmd_obj; - const size_t argc = command.GetArgumentCount (); - - // 'help' doesn't take any arguments, other than command names. If argc is 0, we show the user - // all commands (aliases and user commands if asked for). Otherwise every argument must be the name of a command or a sub-command. - if (argc == 0) - { - uint32_t cmd_types = CommandInterpreter::eCommandTypesBuiltin; - if (m_options.m_show_aliases) - cmd_types |= CommandInterpreter::eCommandTypesAliases; - if (m_options.m_show_user_defined) - cmd_types |= CommandInterpreter::eCommandTypesUserDef; - if (m_options.m_show_hidden) - cmd_types |= CommandInterpreter::eCommandTypesHidden; +bool CommandObjectHelp::DoExecute(Args &command, CommandReturnObject &result) { + CommandObject::CommandMap::iterator pos; + CommandObject *cmd_obj; + const size_t argc = command.GetArgumentCount(); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - m_interpreter.GetHelp (result, cmd_types); // General help - } - else - { - // Get command object for the first command argument. Only search built-in command dictionary. - StringList matches; - cmd_obj = m_interpreter.GetCommandObject (command.GetArgumentAtIndex (0), &matches); - bool is_alias_command = m_interpreter.AliasExists (command.GetArgumentAtIndex (0)); - std::string alias_name = command.GetArgumentAtIndex(0); - - if (cmd_obj != nullptr) - { - StringList matches; - bool all_okay = true; - CommandObject *sub_cmd_obj = cmd_obj; - // Loop down through sub_command dictionaries until we find the command object that corresponds - // to the help command entered. - std::string sub_command; - for (size_t i = 1; i < argc && all_okay; ++i) - { - sub_command = command.GetArgumentAtIndex(i); - matches.Clear(); - if (sub_cmd_obj->IsAlias()) - sub_cmd_obj = ((CommandAlias*)sub_cmd_obj)->GetUnderlyingCommand().get(); - if (! sub_cmd_obj->IsMultiwordObject ()) - { - all_okay = false; - } - else - { - CommandObject *found_cmd; - found_cmd = sub_cmd_obj->GetSubcommandObject(sub_command.c_str(), &matches); - if (found_cmd == nullptr) - all_okay = false; - else if (matches.GetSize() > 1) - all_okay = false; - else - sub_cmd_obj = found_cmd; - } - } - - if (!all_okay || (sub_cmd_obj == nullptr)) - { - std::string cmd_string; - command.GetCommandString (cmd_string); - if (matches.GetSize() >= 2) - { - StreamString s; - s.Printf ("ambiguous command %s", cmd_string.c_str()); - size_t num_matches = matches.GetSize(); - for (size_t match_idx = 0; match_idx < num_matches; match_idx++) - { - s.Printf ("\n\t%s", matches.GetStringAtIndex(match_idx)); - } - s.Printf ("\n"); - result.AppendError(s.GetData()); - result.SetStatus (eReturnStatusFailed); - return false; - } - else if (!sub_cmd_obj) - { - StreamString error_msg_stream; - GenerateAdditionalHelpAvenuesMessage(&error_msg_stream, - cmd_string.c_str(), - m_interpreter.GetCommandPrefix(), - sub_command.c_str()); - result.AppendErrorWithFormat("%s",error_msg_stream.GetData()); - result.SetStatus (eReturnStatusFailed); - return false; - } - else - { - GenerateAdditionalHelpAvenuesMessage(&result.GetOutputStream(), - cmd_string.c_str(), - m_interpreter.GetCommandPrefix(), - sub_command.c_str()); - result.GetOutputStream().Printf("\nThe closest match is '%s'. Help on it follows.\n\n", sub_cmd_obj->GetCommandName()); - } - } - - sub_cmd_obj->GenerateHelpText(result); - - if (is_alias_command) - { - StreamString sstr; - m_interpreter.GetAlias(alias_name.c_str())->GetAliasExpansion(sstr); - result.GetOutputStream().Printf ("\n'%s' is an abbreviation for %s\n", alias_name.c_str(), sstr.GetData()); - } - } - else if (matches.GetSize() > 0) - { - Stream &output_strm = result.GetOutputStream(); - output_strm.Printf("Help requested with ambiguous command name, possible completions:\n"); - const size_t match_count = matches.GetSize(); - for (size_t i = 0; i < match_count; i++) - { - output_strm.Printf("\t%s\n", matches.GetStringAtIndex(i)); - } + // 'help' doesn't take any arguments, other than command names. If argc is 0, + // we show the user + // all commands (aliases and user commands if asked for). Otherwise every + // argument must be the name of a command or a sub-command. + if (argc == 0) { + uint32_t cmd_types = CommandInterpreter::eCommandTypesBuiltin; + if (m_options.m_show_aliases) + cmd_types |= CommandInterpreter::eCommandTypesAliases; + if (m_options.m_show_user_defined) + cmd_types |= CommandInterpreter::eCommandTypesUserDef; + if (m_options.m_show_hidden) + cmd_types |= CommandInterpreter::eCommandTypesHidden; + + result.SetStatus(eReturnStatusSuccessFinishNoResult); + m_interpreter.GetHelp(result, cmd_types); // General help + } else { + // Get command object for the first command argument. Only search built-in + // command dictionary. + StringList matches; + cmd_obj = + m_interpreter.GetCommandObject(command.GetArgumentAtIndex(0), &matches); + bool is_alias_command = + m_interpreter.AliasExists(command.GetArgumentAtIndex(0)); + std::string alias_name = command.GetArgumentAtIndex(0); + + if (cmd_obj != nullptr) { + StringList matches; + bool all_okay = true; + CommandObject *sub_cmd_obj = cmd_obj; + // Loop down through sub_command dictionaries until we find the command + // object that corresponds + // to the help command entered. + std::string sub_command; + for (size_t i = 1; i < argc && all_okay; ++i) { + sub_command = command.GetArgumentAtIndex(i); + matches.Clear(); + if (sub_cmd_obj->IsAlias()) + sub_cmd_obj = + ((CommandAlias *)sub_cmd_obj)->GetUnderlyingCommand().get(); + if (!sub_cmd_obj->IsMultiwordObject()) { + all_okay = false; + } else { + CommandObject *found_cmd; + found_cmd = + sub_cmd_obj->GetSubcommandObject(sub_command.c_str(), &matches); + if (found_cmd == nullptr) + all_okay = false; + else if (matches.GetSize() > 1) + all_okay = false; + else + sub_cmd_obj = found_cmd; } - else - { - // Maybe the user is asking for help about a command argument rather than a command. - const CommandArgumentType arg_type = CommandObject::LookupArgumentName (command.GetArgumentAtIndex (0)); - if (arg_type != eArgTypeLastArg) - { - Stream &output_strm = result.GetOutputStream (); - CommandObject::GetArgumentHelp (output_strm, arg_type, m_interpreter); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - StreamString error_msg_stream; - GenerateAdditionalHelpAvenuesMessage(&error_msg_stream, command.GetArgumentAtIndex(0), m_interpreter.GetCommandPrefix()); - result.AppendErrorWithFormat("%s",error_msg_stream.GetData()); - result.SetStatus (eReturnStatusFailed); - } + } + + if (!all_okay || (sub_cmd_obj == nullptr)) { + std::string cmd_string; + command.GetCommandString(cmd_string); + if (matches.GetSize() >= 2) { + StreamString s; + s.Printf("ambiguous command %s", cmd_string.c_str()); + size_t num_matches = matches.GetSize(); + for (size_t match_idx = 0; match_idx < num_matches; match_idx++) { + s.Printf("\n\t%s", matches.GetStringAtIndex(match_idx)); + } + s.Printf("\n"); + result.AppendError(s.GetData()); + result.SetStatus(eReturnStatusFailed); + return false; + } else if (!sub_cmd_obj) { + StreamString error_msg_stream; + GenerateAdditionalHelpAvenuesMessage( + &error_msg_stream, cmd_string.c_str(), + m_interpreter.GetCommandPrefix(), sub_command.c_str()); + result.AppendErrorWithFormat("%s", error_msg_stream.GetData()); + result.SetStatus(eReturnStatusFailed); + return false; + } else { + GenerateAdditionalHelpAvenuesMessage( + &result.GetOutputStream(), cmd_string.c_str(), + m_interpreter.GetCommandPrefix(), sub_command.c_str()); + result.GetOutputStream().Printf( + "\nThe closest match is '%s'. Help on it follows.\n\n", + sub_cmd_obj->GetCommandName()); } + } + + sub_cmd_obj->GenerateHelpText(result); + + if (is_alias_command) { + StreamString sstr; + m_interpreter.GetAlias(alias_name.c_str())->GetAliasExpansion(sstr); + result.GetOutputStream().Printf("\n'%s' is an abbreviation for %s\n", + alias_name.c_str(), sstr.GetData()); + } + } else if (matches.GetSize() > 0) { + Stream &output_strm = result.GetOutputStream(); + output_strm.Printf("Help requested with ambiguous command name, possible " + "completions:\n"); + const size_t match_count = matches.GetSize(); + for (size_t i = 0; i < match_count; i++) { + output_strm.Printf("\t%s\n", matches.GetStringAtIndex(i)); + } + } else { + // Maybe the user is asking for help about a command argument rather than + // a command. + const CommandArgumentType arg_type = + CommandObject::LookupArgumentName(command.GetArgumentAtIndex(0)); + if (arg_type != eArgTypeLastArg) { + Stream &output_strm = result.GetOutputStream(); + CommandObject::GetArgumentHelp(output_strm, arg_type, m_interpreter); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + StreamString error_msg_stream; + GenerateAdditionalHelpAvenuesMessage(&error_msg_stream, + command.GetArgumentAtIndex(0), + m_interpreter.GetCommandPrefix()); + result.AppendErrorWithFormat("%s", error_msg_stream.GetData()); + result.SetStatus(eReturnStatusFailed); + } } - - return result.Succeeded(); + } + + return result.Succeeded(); } -int -CommandObjectHelp::HandleCompletion(Args &input, - int &cursor_index, - int &cursor_char_position, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) -{ - // Return the completions of the commands in the help system: - if (cursor_index == 0) - { - return m_interpreter.HandleCompletionMatches (input, - cursor_index, - cursor_char_position, - match_start_point, - max_return_elements, - word_complete, - matches); - } - else - { - CommandObject *cmd_obj = m_interpreter.GetCommandObject (input.GetArgumentAtIndex(0)); - - // The command that they are getting help on might be ambiguous, in which case we should complete that, - // otherwise complete with the command the user is getting help on... - - if (cmd_obj) - { - input.Shift(); - cursor_index--; - return cmd_obj->HandleCompletion (input, - cursor_index, - cursor_char_position, - match_start_point, - max_return_elements, - word_complete, - matches); - } - else - { - return m_interpreter.HandleCompletionMatches (input, - cursor_index, - cursor_char_position, - match_start_point, - max_return_elements, - word_complete, - matches); - } +int CommandObjectHelp::HandleCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) { + // Return the completions of the commands in the help system: + if (cursor_index == 0) { + return m_interpreter.HandleCompletionMatches( + input, cursor_index, cursor_char_position, match_start_point, + max_return_elements, word_complete, matches); + } else { + CommandObject *cmd_obj = + m_interpreter.GetCommandObject(input.GetArgumentAtIndex(0)); + + // The command that they are getting help on might be ambiguous, in which + // case we should complete that, + // otherwise complete with the command the user is getting help on... + + if (cmd_obj) { + input.Shift(); + cursor_index--; + return cmd_obj->HandleCompletion( + input, cursor_index, cursor_char_position, match_start_point, + max_return_elements, word_complete, matches); + } else { + return m_interpreter.HandleCompletionMatches( + input, cursor_index, cursor_char_position, match_start_point, + max_return_elements, word_complete, matches); } + } } diff --git a/lldb/source/Commands/CommandObjectHelp.h b/lldb/source/Commands/CommandObjectHelp.h index 6114aa1..827eb57 100644 --- a/lldb/source/Commands/CommandObjectHelp.h +++ b/lldb/source/Commands/CommandObjectHelp.h @@ -23,106 +23,78 @@ namespace lldb_private { // CommandObjectHelp //------------------------------------------------------------------------- -class CommandObjectHelp : public CommandObjectParsed -{ +class CommandObjectHelp : public CommandObjectParsed { public: + CommandObjectHelp(CommandInterpreter &interpreter); - CommandObjectHelp (CommandInterpreter &interpreter); - - ~CommandObjectHelp() override; - - int - HandleCompletion(Args &input, - int &cursor_index, - int &cursor_char_position, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) override; - - static void - GenerateAdditionalHelpAvenuesMessage (Stream *s, - const char* command, - const char* prefix = nullptr, - const char* subcommand = nullptr, - bool include_apropos = true, - bool include_type_lookup = true); - - class CommandOptions : public Options - { - public: - - CommandOptions() : - Options() - { - } - - ~CommandOptions() override {} - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'a': - m_show_aliases = false; - break; - case 'u': - m_show_user_defined = false; - break; - case 'h': - m_show_hidden = true; - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_show_aliases = true; - m_show_user_defined = true; - m_show_hidden = false; - } - - const OptionDefinition* - GetDefinitions() override - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - bool m_show_aliases; - bool m_show_user_defined; - bool m_show_hidden; - }; - - Options * - GetOptions() override - { - return &m_options; + ~CommandObjectHelp() override; + + int HandleCompletion(Args &input, int &cursor_index, + int &cursor_char_position, int match_start_point, + int max_return_elements, bool &word_complete, + StringList &matches) override; + + static void GenerateAdditionalHelpAvenuesMessage( + Stream *s, const char *command, const char *prefix = nullptr, + const char *subcommand = nullptr, bool include_apropos = true, + bool include_type_lookup = true); + + class CommandOptions : public Options { + public: + CommandOptions() : Options() {} + + ~CommandOptions() override {} + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'a': + m_show_aliases = false; + break; + case 'u': + m_show_user_defined = false; + break; + case 'h': + m_show_hidden = true; + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; + } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_show_aliases = true; + m_show_user_defined = true; + m_show_hidden = false; } - + + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + bool m_show_aliases; + bool m_show_user_defined; + bool m_show_hidden; + }; + + Options *GetOptions() override { return &m_options; } + protected: - bool - DoExecute(Args& command, - CommandReturnObject &result) override; - + bool DoExecute(Args &command, CommandReturnObject &result) override; + private: - CommandOptions m_options; + CommandOptions m_options; }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectLanguage.cpp b/lldb/source/Commands/CommandObjectLanguage.cpp index ebe3376..f0028d6 100644 --- a/lldb/source/Commands/CommandObjectLanguage.cpp +++ b/lldb/source/Commands/CommandObjectLanguage.cpp @@ -21,13 +21,11 @@ using namespace lldb; using namespace lldb_private; CommandObjectLanguage::CommandObjectLanguage(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "language", "Commands specific to a source language.", - "language <language-name> <subcommand> [<subcommand-options>]") -{ - //Let the LanguageRuntime populates this command with subcommands - LanguageRuntime::InitializeCommands(this); + : CommandObjectMultiword( + interpreter, "language", "Commands specific to a source language.", + "language <language-name> <subcommand> [<subcommand-options>]") { + // Let the LanguageRuntime populates this command with subcommands + LanguageRuntime::InitializeCommands(this); } -CommandObjectLanguage::~CommandObjectLanguage () -{ -} +CommandObjectLanguage::~CommandObjectLanguage() {} diff --git a/lldb/source/Commands/CommandObjectLanguage.h b/lldb/source/Commands/CommandObjectLanguage.h index 6003a59..b796c51 100644 --- a/lldb/source/Commands/CommandObjectLanguage.h +++ b/lldb/source/Commands/CommandObjectLanguage.h @@ -16,21 +16,19 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-types.h" #include "lldb/Interpreter/CommandObjectMultiword.h" +#include "lldb/lldb-types.h" namespace lldb_private { - class CommandObjectLanguage : public CommandObjectMultiword - { - public: - CommandObjectLanguage (CommandInterpreter &interpreter); - - ~CommandObjectLanguage() override; - - protected: - bool - DoExecute (Args& command, CommandReturnObject &result); - }; +class CommandObjectLanguage : public CommandObjectMultiword { +public: + CommandObjectLanguage(CommandInterpreter &interpreter); + + ~CommandObjectLanguage() override; + +protected: + bool DoExecute(Args &command, CommandReturnObject &result); +}; } // namespace lldb_private #endif // liblldb_CommandObjectLanguage_h_ diff --git a/lldb/source/Commands/CommandObjectLog.cpp b/lldb/source/Commands/CommandObjectLog.cpp index 7dbca57..e4c5a86 100644 --- a/lldb/source/Commands/CommandObjectLog.cpp +++ b/lldb/source/Commands/CommandObjectLog.cpp @@ -12,20 +12,20 @@ // Other libraries and framework includes // Project includes #include "CommandObjectLog.h" -#include "lldb/Interpreter/Args.h" #include "lldb/Core/Debugger.h" -#include "lldb/Host/FileSpec.h" +#include "lldb/Core/Debugger.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" -#include "lldb/Interpreter/Options.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/Timer.h" -#include "lldb/Core/Debugger.h" +#include "lldb/Host/FileSpec.h" #include "lldb/Host/StringConvert.h" +#include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Interpreter/Options.h" #include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolFile.h" @@ -36,171 +36,163 @@ using namespace lldb; using namespace lldb_private; -class CommandObjectLogEnable : public CommandObjectParsed -{ +class CommandObjectLogEnable : public CommandObjectParsed { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - CommandObjectLogEnable(CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "log enable", + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + CommandObjectLogEnable(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "log enable", "Enable logging for a single log channel.", nullptr), - m_options() - { - CommandArgumentEntry arg1; - CommandArgumentEntry arg2; - CommandArgumentData channel_arg; - CommandArgumentData category_arg; - - // Define the first (and only) variant of this arg. - channel_arg.arg_type = eArgTypeLogChannel; - channel_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg1.push_back (channel_arg); - - category_arg.arg_type = eArgTypeLogCategory; - category_arg.arg_repetition = eArgRepeatPlus; - - arg2.push_back (category_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg1); - m_arguments.push_back (arg2); + m_options() { + CommandArgumentEntry arg1; + CommandArgumentEntry arg2; + CommandArgumentData channel_arg; + CommandArgumentData category_arg; + + // Define the first (and only) variant of this arg. + channel_arg.arg_type = eArgTypeLogChannel; + channel_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg1.push_back(channel_arg); + + category_arg.arg_type = eArgTypeLogCategory; + category_arg.arg_repetition = eArgRepeatPlus; + + arg2.push_back(category_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg1); + m_arguments.push_back(arg2); + } + + ~CommandObjectLogEnable() override = default; + + Options *GetOptions() override { return &m_options; } + + // int + // HandleArgumentCompletion (Args &input, + // int &cursor_index, + // int &cursor_char_position, + // OptionElementVector &opt_element_vector, + // int match_start_point, + // int max_return_elements, + // bool &word_complete, + // StringList &matches) + // { + // std::string completion_str (input.GetArgumentAtIndex(cursor_index)); + // completion_str.erase (cursor_char_position); + // + // if (cursor_index == 1) + // { + // // + // Log::AutoCompleteChannelName (completion_str.c_str(), matches); + // } + // return matches.GetSize(); + // } + // + + class CommandOptions : public Options { + public: + CommandOptions() : Options(), log_file(), log_options(0) {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'f': + log_file.SetFile(option_arg, true); + break; + case 't': + log_options |= LLDB_LOG_OPTION_THREADSAFE; + break; + case 'v': + log_options |= LLDB_LOG_OPTION_VERBOSE; + break; + case 'g': + log_options |= LLDB_LOG_OPTION_DEBUG; + break; + case 's': + log_options |= LLDB_LOG_OPTION_PREPEND_SEQUENCE; + break; + case 'T': + log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP; + break; + case 'p': + log_options |= LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD; + break; + case 'n': + log_options |= LLDB_LOG_OPTION_PREPEND_THREAD_NAME; + break; + case 'S': + log_options |= LLDB_LOG_OPTION_BACKTRACE; + break; + case 'a': + log_options |= LLDB_LOG_OPTION_APPEND; + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; } - ~CommandObjectLogEnable() override = default; - - Options * - GetOptions () override - { - return &m_options; + void OptionParsingStarting(ExecutionContext *execution_context) override { + log_file.Clear(); + log_options = 0; } -// int -// HandleArgumentCompletion (Args &input, -// int &cursor_index, -// int &cursor_char_position, -// OptionElementVector &opt_element_vector, -// int match_start_point, -// int max_return_elements, -// bool &word_complete, -// StringList &matches) -// { -// std::string completion_str (input.GetArgumentAtIndex(cursor_index)); -// completion_str.erase (cursor_char_position); -// -// if (cursor_index == 1) -// { -// // -// Log::AutoCompleteChannelName (completion_str.c_str(), matches); -// } -// return matches.GetSize(); -// } -// + const OptionDefinition *GetDefinitions() override { return g_option_table; } - class CommandOptions : public Options - { - public: - CommandOptions() : - Options(), - log_file(), - log_options(0) - { - } + // Options table: Required for subclasses of Options. - ~CommandOptions () override = default; - - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'f': log_file.SetFile(option_arg, true); break; - case 't': log_options |= LLDB_LOG_OPTION_THREADSAFE; break; - case 'v': log_options |= LLDB_LOG_OPTION_VERBOSE; break; - case 'g': log_options |= LLDB_LOG_OPTION_DEBUG; break; - case 's': log_options |= LLDB_LOG_OPTION_PREPEND_SEQUENCE; break; - case 'T': log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP; break; - case 'p': log_options |= LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD;break; - case 'n': log_options |= LLDB_LOG_OPTION_PREPEND_THREAD_NAME; break; - case 'S': log_options |= LLDB_LOG_OPTION_BACKTRACE; break; - case 'a': log_options |= LLDB_LOG_OPTION_APPEND; break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } + static OptionDefinition g_option_table[]; - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - log_file.Clear(); - log_options = 0; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } + // Instance variables to hold the values for command options. - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - FileSpec log_file; - uint32_t log_options; - }; + FileSpec log_file; + uint32_t log_options; + }; protected: - bool - DoExecute (Args& args, - CommandReturnObject &result) override - { - if (args.GetArgumentCount() < 2) - { - result.AppendErrorWithFormat("%s takes a log channel and one or more log types.\n", m_cmd_name.c_str()); - } - else - { - std::string channel(args.GetArgumentAtIndex(0)); - args.Shift (); // Shift off the channel - char log_file[PATH_MAX]; - if (m_options.log_file) - m_options.log_file.GetPath(log_file, sizeof(log_file)); - else - log_file[0] = '\0'; - bool success = m_interpreter.GetDebugger().EnableLog (channel.c_str(), - args.GetConstArgumentVector(), - log_file, - m_options.log_options, - result.GetErrorStream()); - if (success) - result.SetStatus (eReturnStatusSuccessFinishNoResult); - else - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + bool DoExecute(Args &args, CommandReturnObject &result) override { + if (args.GetArgumentCount() < 2) { + result.AppendErrorWithFormat( + "%s takes a log channel and one or more log types.\n", + m_cmd_name.c_str()); + } else { + std::string channel(args.GetArgumentAtIndex(0)); + args.Shift(); // Shift off the channel + char log_file[PATH_MAX]; + if (m_options.log_file) + m_options.log_file.GetPath(log_file, sizeof(log_file)); + else + log_file[0] = '\0'; + bool success = m_interpreter.GetDebugger().EnableLog( + channel.c_str(), args.GetConstArgumentVector(), log_file, + m_options.log_options, result.GetErrorStream()); + if (success) + result.SetStatus(eReturnStatusSuccessFinishNoResult); + else + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } - CommandOptions m_options; + CommandOptions m_options; }; -OptionDefinition -CommandObjectLogEnable::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectLogEnable::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename, "Set the destination file to log to."}, {LLDB_OPT_SET_1, false, "threadsafe", 't', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable thread safe logging to avoid interweaved log lines."}, {LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable verbose logging."}, @@ -212,256 +204,219 @@ CommandObjectLogEnable::CommandOptions::g_option_table[] = {LLDB_OPT_SET_1, false, "stack", 'S', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Append a stack backtrace to each log line."}, {LLDB_OPT_SET_1, false, "append", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Append to the log file instead of overwriting."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; -class CommandObjectLogDisable : public CommandObjectParsed -{ +class CommandObjectLogDisable : public CommandObjectParsed { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - CommandObjectLogDisable(CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "log disable", + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + CommandObjectLogDisable(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "log disable", "Disable one or more log channel categories.", - nullptr) - { - CommandArgumentEntry arg1; - CommandArgumentEntry arg2; - CommandArgumentData channel_arg; - CommandArgumentData category_arg; - - // Define the first (and only) variant of this arg. - channel_arg.arg_type = eArgTypeLogChannel; - channel_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg1.push_back (channel_arg); - - category_arg.arg_type = eArgTypeLogCategory; - category_arg.arg_repetition = eArgRepeatPlus; - - arg2.push_back (category_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg1); - m_arguments.push_back (arg2); - } + nullptr) { + CommandArgumentEntry arg1; + CommandArgumentEntry arg2; + CommandArgumentData channel_arg; + CommandArgumentData category_arg; + + // Define the first (and only) variant of this arg. + channel_arg.arg_type = eArgTypeLogChannel; + channel_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg1.push_back(channel_arg); + + category_arg.arg_type = eArgTypeLogCategory; + category_arg.arg_repetition = eArgRepeatPlus; - ~CommandObjectLogDisable() override = default; + arg2.push_back(category_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg1); + m_arguments.push_back(arg2); + } + + ~CommandObjectLogDisable() override = default; protected: - bool - DoExecute (Args& args, - CommandReturnObject &result) override - { - const size_t argc = args.GetArgumentCount(); - if (argc == 0) - { - result.AppendErrorWithFormat("%s takes a log channel and one or more log types.\n", m_cmd_name.c_str()); - } - else - { - Log::Callbacks log_callbacks; - - std::string channel(args.GetArgumentAtIndex(0)); - args.Shift (); // Shift off the channel - if (Log::GetLogChannelCallbacks (ConstString(channel.c_str()), log_callbacks)) - { - log_callbacks.disable (args.GetConstArgumentVector(), &result.GetErrorStream()); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } - else if (channel == "all") - { - Log::DisableAllLogChannels(&result.GetErrorStream()); - } - else - { - LogChannelSP log_channel_sp (LogChannel::FindPlugin(channel.c_str())); - if (log_channel_sp) - { - log_channel_sp->Disable(args.GetConstArgumentVector(), &result.GetErrorStream()); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } - else - result.AppendErrorWithFormat("Invalid log channel '%s'.\n", args.GetArgumentAtIndex(0)); - } - } - return result.Succeeded(); + bool DoExecute(Args &args, CommandReturnObject &result) override { + const size_t argc = args.GetArgumentCount(); + if (argc == 0) { + result.AppendErrorWithFormat( + "%s takes a log channel and one or more log types.\n", + m_cmd_name.c_str()); + } else { + Log::Callbacks log_callbacks; + + std::string channel(args.GetArgumentAtIndex(0)); + args.Shift(); // Shift off the channel + if (Log::GetLogChannelCallbacks(ConstString(channel.c_str()), + log_callbacks)) { + log_callbacks.disable(args.GetConstArgumentVector(), + &result.GetErrorStream()); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else if (channel == "all") { + Log::DisableAllLogChannels(&result.GetErrorStream()); + } else { + LogChannelSP log_channel_sp(LogChannel::FindPlugin(channel.c_str())); + if (log_channel_sp) { + log_channel_sp->Disable(args.GetConstArgumentVector(), + &result.GetErrorStream()); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else + result.AppendErrorWithFormat("Invalid log channel '%s'.\n", + args.GetArgumentAtIndex(0)); + } } + return result.Succeeded(); + } }; -class CommandObjectLogList : public CommandObjectParsed -{ +class CommandObjectLogList : public CommandObjectParsed { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - CommandObjectLogList(CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "log list", - "List the log categories for one or more log channels. If none specified, lists them all.", - nullptr) - { - CommandArgumentEntry arg; - CommandArgumentData channel_arg; - - // Define the first (and only) variant of this arg. - channel_arg.arg_type = eArgTypeLogChannel; - channel_arg.arg_repetition = eArgRepeatStar; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (channel_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - } - - ~CommandObjectLogList() override = default; + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + CommandObjectLogList(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "log list", + "List the log categories for one or more log " + "channels. If none specified, lists them all.", + nullptr) { + CommandArgumentEntry arg; + CommandArgumentData channel_arg; + + // Define the first (and only) variant of this arg. + channel_arg.arg_type = eArgTypeLogChannel; + channel_arg.arg_repetition = eArgRepeatStar; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(channel_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectLogList() override = default; protected: - bool - DoExecute (Args& args, - CommandReturnObject &result) override - { - const size_t argc = args.GetArgumentCount(); - if (argc == 0) - { - Log::ListAllLogChannels (&result.GetOutputStream()); - result.SetStatus(eReturnStatusSuccessFinishResult); - } - else - { - for (size_t i=0; i<argc; ++i) - { - Log::Callbacks log_callbacks; - - std::string channel(args.GetArgumentAtIndex(i)); - if (Log::GetLogChannelCallbacks (ConstString(channel.c_str()), log_callbacks)) - { - log_callbacks.list_categories (&result.GetOutputStream()); - result.SetStatus(eReturnStatusSuccessFinishResult); - } - else if (channel == "all") - { - Log::ListAllLogChannels (&result.GetOutputStream()); - result.SetStatus(eReturnStatusSuccessFinishResult); - } - else - { - LogChannelSP log_channel_sp (LogChannel::FindPlugin(channel.c_str())); - if (log_channel_sp) - { - log_channel_sp->ListCategories(&result.GetOutputStream()); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } - else - result.AppendErrorWithFormat("Invalid log channel '%s'.\n", args.GetArgumentAtIndex(0)); - } - } + bool DoExecute(Args &args, CommandReturnObject &result) override { + const size_t argc = args.GetArgumentCount(); + if (argc == 0) { + Log::ListAllLogChannels(&result.GetOutputStream()); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + for (size_t i = 0; i < argc; ++i) { + Log::Callbacks log_callbacks; + + std::string channel(args.GetArgumentAtIndex(i)); + if (Log::GetLogChannelCallbacks(ConstString(channel.c_str()), + log_callbacks)) { + log_callbacks.list_categories(&result.GetOutputStream()); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else if (channel == "all") { + Log::ListAllLogChannels(&result.GetOutputStream()); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + LogChannelSP log_channel_sp(LogChannel::FindPlugin(channel.c_str())); + if (log_channel_sp) { + log_channel_sp->ListCategories(&result.GetOutputStream()); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else + result.AppendErrorWithFormat("Invalid log channel '%s'.\n", + args.GetArgumentAtIndex(0)); } - return result.Succeeded(); + } } + return result.Succeeded(); + } }; -class CommandObjectLogTimer : public CommandObjectParsed -{ +class CommandObjectLogTimer : 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 >") - { - } - - ~CommandObjectLogTimer() override = default; + //------------------------------------------------------------------ + // 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 >") {} + + ~CommandObjectLogTimer() override = default; protected: - bool - DoExecute (Args& args, - CommandReturnObject &result) override - { - const size_t argc = args.GetArgumentCount(); - result.SetStatus(eReturnStatusFailed); + bool DoExecute(Args &args, CommandReturnObject &result) override { + const size_t argc = args.GetArgumentCount(); + result.SetStatus(eReturnStatusFailed); + + if (argc == 1) { + const char *sub_command = args.GetArgumentAtIndex(0); + + if (strcasecmp(sub_command, "enable") == 0) { + Timer::SetDisplayDepth(UINT32_MAX); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else if (strcasecmp(sub_command, "disable") == 0) { + Timer::DumpCategoryTimes(&result.GetOutputStream()); + Timer::SetDisplayDepth(0); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else if (strcasecmp(sub_command, "dump") == 0) { + Timer::DumpCategoryTimes(&result.GetOutputStream()); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else if (strcasecmp(sub_command, "reset") == 0) { + Timer::ResetCategoryTimes(); + result.SetStatus(eReturnStatusSuccessFinishResult); + } + } else if (argc == 2) { + const char *sub_command = args.GetArgumentAtIndex(0); + + if (strcasecmp(sub_command, "enable") == 0) { + bool success; + uint32_t depth = + StringConvert::ToUInt32(args.GetArgumentAtIndex(1), 0, 0, &success); + if (success) { + Timer::SetDisplayDepth(depth); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else + result.AppendError( + "Could not convert enable depth to an unsigned integer."); + } + if (strcasecmp(sub_command, "increment") == 0) { + bool success; + bool increment = + Args::StringToBoolean(args.GetArgumentAtIndex(1), false, &success); + if (success) { + Timer::SetQuiet(!increment); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else + result.AppendError("Could not convert increment value to boolean."); + } + } - if (argc == 1) - { - const char *sub_command = args.GetArgumentAtIndex(0); - - if (strcasecmp(sub_command, "enable") == 0) - { - Timer::SetDisplayDepth (UINT32_MAX); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } - else if (strcasecmp(sub_command, "disable") == 0) - { - Timer::DumpCategoryTimes (&result.GetOutputStream()); - Timer::SetDisplayDepth (0); - result.SetStatus(eReturnStatusSuccessFinishResult); - } - else if (strcasecmp(sub_command, "dump") == 0) - { - Timer::DumpCategoryTimes (&result.GetOutputStream()); - result.SetStatus(eReturnStatusSuccessFinishResult); - } - else if (strcasecmp(sub_command, "reset") == 0) - { - Timer::ResetCategoryTimes (); - result.SetStatus(eReturnStatusSuccessFinishResult); - } - } - else if (argc == 2) - { - const char *sub_command = args.GetArgumentAtIndex(0); - - if (strcasecmp(sub_command, "enable") == 0) - { - bool success; - uint32_t depth = StringConvert::ToUInt32(args.GetArgumentAtIndex(1), 0, 0, &success); - if (success) - { - Timer::SetDisplayDepth (depth); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } - else - result.AppendError("Could not convert enable depth to an unsigned integer."); - } - if (strcasecmp(sub_command, "increment") == 0) - { - bool success; - bool increment = Args::StringToBoolean(args.GetArgumentAtIndex(1), false, &success); - if (success) - { - Timer::SetQuiet (!increment); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } - else - result.AppendError("Could not convert increment value to boolean."); - } - } - - if (!result.Succeeded()) - { - result.AppendError("Missing subcommand"); - result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str()); - } - return result.Succeeded(); + if (!result.Succeeded()) { + result.AppendError("Missing subcommand"); + result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str()); } + return result.Succeeded(); + } }; CommandObjectLog::CommandObjectLog(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "log", "Commands controlling LLDB internal logging.", - "log <subcommand> [<command-options>]") -{ - LoadSubCommand ("enable", CommandObjectSP (new CommandObjectLogEnable (interpreter))); - LoadSubCommand ("disable", CommandObjectSP (new CommandObjectLogDisable (interpreter))); - LoadSubCommand ("list", CommandObjectSP (new CommandObjectLogList (interpreter))); - LoadSubCommand ("timers", CommandObjectSP (new CommandObjectLogTimer (interpreter))); + : CommandObjectMultiword(interpreter, "log", + "Commands controlling LLDB internal logging.", + "log <subcommand> [<command-options>]") { + LoadSubCommand("enable", + CommandObjectSP(new CommandObjectLogEnable(interpreter))); + LoadSubCommand("disable", + CommandObjectSP(new CommandObjectLogDisable(interpreter))); + LoadSubCommand("list", + CommandObjectSP(new CommandObjectLogList(interpreter))); + LoadSubCommand("timers", + CommandObjectSP(new CommandObjectLogTimer(interpreter))); } CommandObjectLog::~CommandObjectLog() = default; diff --git a/lldb/source/Commands/CommandObjectLog.h b/lldb/source/Commands/CommandObjectLog.h index be5215f..1e24a4b 100644 --- a/lldb/source/Commands/CommandObjectLog.h +++ b/lldb/source/Commands/CommandObjectLog.h @@ -25,21 +25,20 @@ namespace lldb_private { // CommandObjectLog //------------------------------------------------------------------------- -class CommandObjectLog : public CommandObjectMultiword -{ +class CommandObjectLog : public CommandObjectMultiword { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - CommandObjectLog(CommandInterpreter &interpreter); + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + CommandObjectLog(CommandInterpreter &interpreter); - ~CommandObjectLog() override; + ~CommandObjectLog() override; private: - //------------------------------------------------------------------ - // For CommandObjectLog only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN (CommandObjectLog); + //------------------------------------------------------------------ + // For CommandObjectLog only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN(CommandObjectLog); }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp index 9c9abc5..54dfdd1 100644 --- a/lldb/source/Commands/CommandObjectMemory.cpp +++ b/lldb/source/Commands/CommandObjectMemory.cpp @@ -48,10 +48,8 @@ using namespace lldb; using namespace lldb_private; -static OptionDefinition -g_option_table[] = -{ - // clang-format off +static OptionDefinition g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "num-per-line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNumberPerLine, "The number of items per line to display." }, {LLDB_OPT_SET_2, false, "binary", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that " "uses the format, size, count and number per line settings." }, @@ -60,1766 +58,1634 @@ g_option_table[] = {LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "force", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Necessary if reading over target.max-memory-read-size bytes." }, - // clang-format on + // clang-format on }; -class OptionGroupReadMemory : public OptionGroup -{ +class OptionGroupReadMemory : public OptionGroup { public: - OptionGroupReadMemory () : - m_num_per_line (1,1), - m_output_as_binary (false), - m_view_as_type(), - m_offset(0,0) - { - } + OptionGroupReadMemory() + : m_num_per_line(1, 1), m_output_as_binary(false), m_view_as_type(), + m_offset(0, 0) {} - ~OptionGroupReadMemory() override = default; + ~OptionGroupReadMemory() override = default; - uint32_t - GetNumDefinitions () override - { - return sizeof (g_option_table) / sizeof (OptionDefinition); - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - Error - SetOptionValue (uint32_t option_idx, - const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = g_option_table[option_idx].short_option; - - switch (short_option) - { - case 'l': - error = m_num_per_line.SetValueFromString (option_arg); - if (m_num_per_line.GetCurrentValue() == 0) - error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg); - break; - - case 'b': - m_output_as_binary = true; - break; - - case 't': - error = m_view_as_type.SetValueFromString (option_arg); - break; - - case 'r': - m_force = true; - break; - - case 'E': - error = m_offset.SetValueFromString(option_arg); - break; - - default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); - break; - } - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_num_per_line.Clear(); - m_output_as_binary = false; - m_view_as_type.Clear(); - m_force = false; - m_offset.Clear(); + uint32_t GetNumDefinitions() override { + return sizeof(g_option_table) / sizeof(OptionDefinition); + } + + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = g_option_table[option_idx].short_option; + + switch (short_option) { + case 'l': + error = m_num_per_line.SetValueFromString(option_arg); + if (m_num_per_line.GetCurrentValue() == 0) + error.SetErrorStringWithFormat( + "invalid value for --num-per-line option '%s'", option_arg); + break; + + case 'b': + m_output_as_binary = true; + break; + + case 't': + error = m_view_as_type.SetValueFromString(option_arg); + break; + + case 'r': + m_force = true; + break; + + case 'E': + error = m_offset.SetValueFromString(option_arg); + break; + + default: + error.SetErrorStringWithFormat("unrecognized short option '%c'", + short_option); + break; } - - Error - FinalizeSettings (Target *target, OptionGroupFormat& format_options) - { - Error error; - OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue(); - OptionValueUInt64 &count_value = format_options.GetCountValue(); - const bool byte_size_option_set = byte_size_value.OptionWasSet(); - const bool num_per_line_option_set = m_num_per_line.OptionWasSet(); - const bool count_option_set = format_options.GetCountValue().OptionWasSet(); - - switch (format_options.GetFormat()) - { - default: - break; - - case eFormatBoolean: - if (!byte_size_option_set) - byte_size_value = 1; - if (!num_per_line_option_set) - m_num_per_line = 1; - if (!count_option_set) - format_options.GetCountValue() = 8; - break; - - case eFormatCString: - break; - - case eFormatInstruction: - if (count_option_set) - byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize(); - m_num_per_line = 1; - break; - - case eFormatAddressInfo: - if (!byte_size_option_set) - byte_size_value = target->GetArchitecture().GetAddressByteSize(); - m_num_per_line = 1; - if (!count_option_set) - format_options.GetCountValue() = 8; - break; - - case eFormatPointer: - byte_size_value = target->GetArchitecture().GetAddressByteSize(); - if (!num_per_line_option_set) - m_num_per_line = 4; - if (!count_option_set) - format_options.GetCountValue() = 8; - break; - - case eFormatBinary: - case eFormatFloat: - case eFormatOctal: - case eFormatDecimal: - case eFormatEnum: - case eFormatUnicode16: - case eFormatUnicode32: - case eFormatUnsigned: - case eFormatHexFloat: - if (!byte_size_option_set) - byte_size_value = 4; - if (!num_per_line_option_set) - m_num_per_line = 1; - if (!count_option_set) - format_options.GetCountValue() = 8; - break; - - case eFormatBytes: - case eFormatBytesWithASCII: - if (byte_size_option_set) - { - if (byte_size_value > 1) - error.SetErrorStringWithFormat( - "display format (bytes/bytes with ASCII) conflicts with the specified byte size %" PRIu64 - "\n" - "\tconsider using a different display format or don't specify the byte size.", - byte_size_value.GetCurrentValue()); - } - else - byte_size_value = 1; - if (!num_per_line_option_set) - m_num_per_line = 16; - if (!count_option_set) - format_options.GetCountValue() = 32; - break; - - case eFormatCharArray: - case eFormatChar: - case eFormatCharPrintable: - if (!byte_size_option_set) - byte_size_value = 1; - if (!num_per_line_option_set) - m_num_per_line = 32; - if (!count_option_set) - format_options.GetCountValue() = 64; - break; - - case eFormatComplex: - if (!byte_size_option_set) - byte_size_value = 8; - if (!num_per_line_option_set) - m_num_per_line = 1; - if (!count_option_set) - format_options.GetCountValue() = 8; - break; - - case eFormatComplexInteger: - if (!byte_size_option_set) - byte_size_value = 8; - if (!num_per_line_option_set) - m_num_per_line = 1; - if (!count_option_set) - format_options.GetCountValue() = 8; - break; - - case eFormatHex: - if (!byte_size_option_set) - byte_size_value = 4; - if (!num_per_line_option_set) - { - switch (byte_size_value) - { - case 1: - case 2: - m_num_per_line = 8; - break; - case 4: - m_num_per_line = 4; - break; - case 8: - m_num_per_line = 2; - break; - default: - m_num_per_line = 1; - break; - } - } - if (!count_option_set) - count_value = 8; - break; - - case eFormatVectorOfChar: - case eFormatVectorOfSInt8: - case eFormatVectorOfUInt8: - case eFormatVectorOfSInt16: - case eFormatVectorOfUInt16: - case eFormatVectorOfSInt32: - case eFormatVectorOfUInt32: - case eFormatVectorOfSInt64: - case eFormatVectorOfUInt64: - case eFormatVectorOfFloat16: - case eFormatVectorOfFloat32: - case eFormatVectorOfFloat64: - case eFormatVectorOfUInt128: - if (!byte_size_option_set) - byte_size_value = 128; - if (!num_per_line_option_set) - m_num_per_line = 1; - if (!count_option_set) - count_value = 4; - break; + return error; + } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_num_per_line.Clear(); + m_output_as_binary = false; + m_view_as_type.Clear(); + m_force = false; + m_offset.Clear(); + } + + Error FinalizeSettings(Target *target, OptionGroupFormat &format_options) { + Error error; + OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue(); + OptionValueUInt64 &count_value = format_options.GetCountValue(); + const bool byte_size_option_set = byte_size_value.OptionWasSet(); + const bool num_per_line_option_set = m_num_per_line.OptionWasSet(); + const bool count_option_set = format_options.GetCountValue().OptionWasSet(); + + switch (format_options.GetFormat()) { + default: + break; + + case eFormatBoolean: + if (!byte_size_option_set) + byte_size_value = 1; + if (!num_per_line_option_set) + m_num_per_line = 1; + if (!count_option_set) + format_options.GetCountValue() = 8; + break; + + case eFormatCString: + break; + + case eFormatInstruction: + if (count_option_set) + byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize(); + m_num_per_line = 1; + break; + + case eFormatAddressInfo: + if (!byte_size_option_set) + byte_size_value = target->GetArchitecture().GetAddressByteSize(); + m_num_per_line = 1; + if (!count_option_set) + format_options.GetCountValue() = 8; + break; + + case eFormatPointer: + byte_size_value = target->GetArchitecture().GetAddressByteSize(); + if (!num_per_line_option_set) + m_num_per_line = 4; + if (!count_option_set) + format_options.GetCountValue() = 8; + break; + + case eFormatBinary: + case eFormatFloat: + case eFormatOctal: + case eFormatDecimal: + case eFormatEnum: + case eFormatUnicode16: + case eFormatUnicode32: + case eFormatUnsigned: + case eFormatHexFloat: + if (!byte_size_option_set) + byte_size_value = 4; + if (!num_per_line_option_set) + m_num_per_line = 1; + if (!count_option_set) + format_options.GetCountValue() = 8; + break; + + case eFormatBytes: + case eFormatBytesWithASCII: + if (byte_size_option_set) { + if (byte_size_value > 1) + error.SetErrorStringWithFormat( + "display format (bytes/bytes with ASCII) conflicts with the " + "specified byte size %" PRIu64 "\n" + "\tconsider using a different display format or don't specify " + "the byte size.", + byte_size_value.GetCurrentValue()); + } else + byte_size_value = 1; + if (!num_per_line_option_set) + m_num_per_line = 16; + if (!count_option_set) + format_options.GetCountValue() = 32; + break; + + case eFormatCharArray: + case eFormatChar: + case eFormatCharPrintable: + if (!byte_size_option_set) + byte_size_value = 1; + if (!num_per_line_option_set) + m_num_per_line = 32; + if (!count_option_set) + format_options.GetCountValue() = 64; + break; + + case eFormatComplex: + if (!byte_size_option_set) + byte_size_value = 8; + if (!num_per_line_option_set) + m_num_per_line = 1; + if (!count_option_set) + format_options.GetCountValue() = 8; + break; + + case eFormatComplexInteger: + if (!byte_size_option_set) + byte_size_value = 8; + if (!num_per_line_option_set) + m_num_per_line = 1; + if (!count_option_set) + format_options.GetCountValue() = 8; + break; + + case eFormatHex: + if (!byte_size_option_set) + byte_size_value = 4; + if (!num_per_line_option_set) { + switch (byte_size_value) { + case 1: + case 2: + m_num_per_line = 8; + break; + case 4: + m_num_per_line = 4; + break; + case 8: + m_num_per_line = 2; + break; + default: + m_num_per_line = 1; + break; } - return error; + } + if (!count_option_set) + count_value = 8; + break; + + case eFormatVectorOfChar: + case eFormatVectorOfSInt8: + case eFormatVectorOfUInt8: + case eFormatVectorOfSInt16: + case eFormatVectorOfUInt16: + case eFormatVectorOfSInt32: + case eFormatVectorOfUInt32: + case eFormatVectorOfSInt64: + case eFormatVectorOfUInt64: + case eFormatVectorOfFloat16: + case eFormatVectorOfFloat32: + case eFormatVectorOfFloat64: + case eFormatVectorOfUInt128: + if (!byte_size_option_set) + byte_size_value = 128; + if (!num_per_line_option_set) + m_num_per_line = 1; + if (!count_option_set) + count_value = 4; + break; } + return error; + } - bool - AnyOptionWasSet () const - { - return m_num_per_line.OptionWasSet() || - m_output_as_binary || - m_view_as_type.OptionWasSet() || - m_offset.OptionWasSet(); - } - - OptionValueUInt64 m_num_per_line; - bool m_output_as_binary; - OptionValueString m_view_as_type; - bool m_force; - OptionValueUInt64 m_offset; + bool AnyOptionWasSet() const { + return m_num_per_line.OptionWasSet() || m_output_as_binary || + m_view_as_type.OptionWasSet() || m_offset.OptionWasSet(); + } + + OptionValueUInt64 m_num_per_line; + bool m_output_as_binary; + OptionValueString m_view_as_type; + bool m_force; + OptionValueUInt64 m_offset; }; //---------------------------------------------------------------------- // Read memory from the inferior process //---------------------------------------------------------------------- -class CommandObjectMemoryRead : public CommandObjectParsed -{ +class CommandObjectMemoryRead : public CommandObjectParsed { public: - CommandObjectMemoryRead(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "memory read", "Read from the memory of the current target process.", - nullptr, eCommandRequiresTarget | eCommandProcessMustBePaused), - m_option_group(), - m_format_options(eFormatBytesWithASCII, 1, 8), - m_memory_options(), - m_outfile_options(), - m_varobj_options(), - m_next_addr(LLDB_INVALID_ADDRESS), - m_prev_byte_size(0), - m_prev_format_options(eFormatBytesWithASCII, 1, 8), - m_prev_memory_options(), - m_prev_outfile_options(), - m_prev_varobj_options() - { - CommandArgumentEntry arg1; - CommandArgumentEntry arg2; - CommandArgumentData start_addr_arg; - CommandArgumentData end_addr_arg; - - // Define the first (and only) variant of this arg. - start_addr_arg.arg_type = eArgTypeAddressOrExpression; - start_addr_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg1.push_back (start_addr_arg); - - // Define the first (and only) variant of this arg. - end_addr_arg.arg_type = eArgTypeAddressOrExpression; - end_addr_arg.arg_repetition = eArgRepeatOptional; - - // There is only one variant this argument could be; put it into the argument entry. - arg2.push_back (end_addr_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg1); - m_arguments.push_back (arg2); - - // Add the "--format" and "--count" options to group 1 and 3 - m_option_group.Append (&m_format_options, - OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT, - LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); - m_option_group.Append (&m_format_options, - OptionGroupFormat::OPTION_GROUP_GDB_FMT, - LLDB_OPT_SET_1 | LLDB_OPT_SET_3); - // Add the "--size" option to group 1 and 2 - m_option_group.Append (&m_format_options, - OptionGroupFormat::OPTION_GROUP_SIZE, - LLDB_OPT_SET_1 | LLDB_OPT_SET_2); - m_option_group.Append (&m_memory_options); - m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); - m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3); - m_option_group.Finalize(); - } + CommandObjectMemoryRead(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "memory read", + "Read from the memory of the current target process.", nullptr, + eCommandRequiresTarget | eCommandProcessMustBePaused), + m_option_group(), m_format_options(eFormatBytesWithASCII, 1, 8), + m_memory_options(), m_outfile_options(), m_varobj_options(), + m_next_addr(LLDB_INVALID_ADDRESS), m_prev_byte_size(0), + m_prev_format_options(eFormatBytesWithASCII, 1, 8), + m_prev_memory_options(), m_prev_outfile_options(), + m_prev_varobj_options() { + CommandArgumentEntry arg1; + CommandArgumentEntry arg2; + CommandArgumentData start_addr_arg; + CommandArgumentData end_addr_arg; - ~CommandObjectMemoryRead() override = default; + // Define the first (and only) variant of this arg. + start_addr_arg.arg_type = eArgTypeAddressOrExpression; + start_addr_arg.arg_repetition = eArgRepeatPlain; - Options * - GetOptions () override - { - return &m_option_group; - } + // There is only one variant this argument could be; put it into the + // argument entry. + arg1.push_back(start_addr_arg); - const char * - GetRepeatCommand (Args ¤t_command_args, uint32_t index) override - { - return m_cmd_name.c_str(); - } + // Define the first (and only) variant of this arg. + end_addr_arg.arg_type = eArgTypeAddressOrExpression; + end_addr_arg.arg_repetition = eArgRepeatOptional; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg2.push_back(end_addr_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg1); + m_arguments.push_back(arg2); + + // Add the "--format" and "--count" options to group 1 and 3 + m_option_group.Append(&m_format_options, + OptionGroupFormat::OPTION_GROUP_FORMAT | + OptionGroupFormat::OPTION_GROUP_COUNT, + LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); + m_option_group.Append(&m_format_options, + OptionGroupFormat::OPTION_GROUP_GDB_FMT, + LLDB_OPT_SET_1 | LLDB_OPT_SET_3); + // Add the "--size" option to group 1 and 2 + m_option_group.Append(&m_format_options, + OptionGroupFormat::OPTION_GROUP_SIZE, + LLDB_OPT_SET_1 | LLDB_OPT_SET_2); + m_option_group.Append(&m_memory_options); + m_option_group.Append(&m_outfile_options, LLDB_OPT_SET_ALL, + LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); + m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3); + m_option_group.Finalize(); + } + + ~CommandObjectMemoryRead() override = default; + + Options *GetOptions() override { return &m_option_group; } + + const char *GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override { + return m_cmd_name.c_str(); + } protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - // No need to check "target" for validity as eCommandRequiresTarget ensures it is valid - Target *target = m_exe_ctx.GetTargetPtr(); - - const size_t argc = command.GetArgumentCount(); - - if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2) - { - result.AppendErrorWithFormat ("%s takes a start address expression with an optional end address expression.\n", m_cmd_name.c_str()); - result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n"); - result.SetStatus(eReturnStatusFailed); - return false; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + // No need to check "target" for validity as eCommandRequiresTarget ensures + // it is valid + Target *target = m_exe_ctx.GetTargetPtr(); + + const size_t argc = command.GetArgumentCount(); + + if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2) { + result.AppendErrorWithFormat("%s takes a start address expression with " + "an optional end address expression.\n", + m_cmd_name.c_str()); + result.AppendRawWarning("Expressions should be quoted if they contain " + "spaces or other special characters.\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } - CompilerType clang_ast_type; - Error error; + CompilerType clang_ast_type; + Error error; + + const char *view_as_type_cstr = + m_memory_options.m_view_as_type.GetCurrentValue(); + if (view_as_type_cstr && view_as_type_cstr[0]) { + // We are viewing memory as a type + + SymbolContext sc; + const bool exact_match = false; + TypeList type_list; + uint32_t reference_count = 0; + uint32_t pointer_count = 0; + size_t idx; + +#define ALL_KEYWORDS \ + KEYWORD("const") \ + KEYWORD("volatile") \ + KEYWORD("restrict") \ + KEYWORD("struct") \ + KEYWORD("class") \ + KEYWORD("union") - const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue(); - if (view_as_type_cstr && view_as_type_cstr[0]) - { - // We are viewing memory as a type - - SymbolContext sc; - const bool exact_match = false; - TypeList type_list; - uint32_t reference_count = 0; - uint32_t pointer_count = 0; - size_t idx; - -#define ALL_KEYWORDS \ - KEYWORD("const") \ - KEYWORD("volatile") \ - KEYWORD("restrict") \ - KEYWORD("struct") \ - KEYWORD("class") \ - KEYWORD("union") - #define KEYWORD(s) s, - static const char *g_keywords[] = - { - ALL_KEYWORDS - }; + static const char *g_keywords[] = {ALL_KEYWORDS}; #undef KEYWORD #define KEYWORD(s) (sizeof(s) - 1), - static const int g_keyword_lengths[] = - { - ALL_KEYWORDS - }; + static const int g_keyword_lengths[] = {ALL_KEYWORDS}; #undef KEYWORD - + #undef ALL_KEYWORDS - - static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *); - std::string type_str(view_as_type_cstr); - - // Remove all instances of g_keywords that are followed by spaces - for (size_t i = 0; i < g_num_keywords; ++i) - { - const char *keyword = g_keywords[i]; - int keyword_len = g_keyword_lengths[i]; - - idx = 0; - while ((idx = type_str.find (keyword, idx)) != std::string::npos) - { - if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t') - { - type_str.erase(idx, keyword_len+1); - idx = 0; - } - else - { - idx += keyword_len; - } - } - } - bool done = type_str.empty(); - // - idx = type_str.find_first_not_of (" \t"); - if (idx > 0 && idx != std::string::npos) - type_str.erase (0, idx); - while (!done) - { - // Strip trailing spaces - if (type_str.empty()) - done = true; - else - { - switch (type_str[type_str.size()-1]) - { - case '*': - ++pointer_count; - LLVM_FALLTHROUGH; - case ' ': - case '\t': - type_str.erase(type_str.size()-1); - break; - - case '&': - if (reference_count == 0) - { - reference_count = 1; - type_str.erase(type_str.size()-1); - } - else - { - result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr); - result.SetStatus(eReturnStatusFailed); - return false; - } - break; - - default: - done = true; - break; - } - } - } - - llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; - ConstString lookup_type_name(type_str.c_str()); - StackFrame *frame = m_exe_ctx.GetFramePtr(); - if (frame) - { - sc = frame->GetSymbolContext (eSymbolContextModule); - if (sc.module_sp) - { - sc.module_sp->FindTypes (sc, - lookup_type_name, - exact_match, - 1, - searched_symbol_files, - type_list); - } - } - if (type_list.GetSize() == 0) - { - target->GetImages().FindTypes (sc, - lookup_type_name, - exact_match, - 1, - searched_symbol_files, - type_list); - } - if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$') - { - if (ClangPersistentVariables *persistent_vars = llvm::dyn_cast_or_null<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))) - { - clang::TypeDecl *tdecl = llvm::dyn_cast_or_null<clang::TypeDecl>(persistent_vars->GetPersistentDecl(ConstString(lookup_type_name))); - - if (tdecl) - { - clang_ast_type.SetCompilerType(ClangASTContext::GetASTContext(&tdecl->getASTContext()), - reinterpret_cast<lldb::opaque_compiler_type_t>(const_cast<clang::Type*>(tdecl->getTypeForDecl()))); - } - } + static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *); + std::string type_str(view_as_type_cstr); + + // Remove all instances of g_keywords that are followed by spaces + for (size_t i = 0; i < g_num_keywords; ++i) { + const char *keyword = g_keywords[i]; + int keyword_len = g_keyword_lengths[i]; + + idx = 0; + while ((idx = type_str.find(keyword, idx)) != std::string::npos) { + if (type_str[idx + keyword_len] == ' ' || + type_str[idx + keyword_len] == '\t') { + type_str.erase(idx, keyword_len + 1); + idx = 0; + } else { + idx += keyword_len; + } + } + } + bool done = type_str.empty(); + // + idx = type_str.find_first_not_of(" \t"); + if (idx > 0 && idx != std::string::npos) + type_str.erase(0, idx); + while (!done) { + // Strip trailing spaces + if (type_str.empty()) + done = true; + else { + switch (type_str[type_str.size() - 1]) { + case '*': + ++pointer_count; + LLVM_FALLTHROUGH; + case ' ': + case '\t': + type_str.erase(type_str.size() - 1); + break; + + case '&': + if (reference_count == 0) { + reference_count = 1; + type_str.erase(type_str.size() - 1); + } else { + result.AppendErrorWithFormat("invalid type string: '%s'\n", + view_as_type_cstr); + result.SetStatus(eReturnStatusFailed); + return false; } + break; - if (!clang_ast_type.IsValid()) - { - if (type_list.GetSize() == 0) - { - result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n", - lookup_type_name.GetCString(), - view_as_type_cstr); - result.SetStatus(eReturnStatusFailed); - return false; - } - else - { - TypeSP type_sp (type_list.GetTypeAtIndex(0)); - clang_ast_type = type_sp->GetFullCompilerType (); - } - } - - while (pointer_count > 0) - { - CompilerType pointer_type = clang_ast_type.GetPointerType(); - if (pointer_type.IsValid()) - clang_ast_type = pointer_type; - else - { - result.AppendError ("unable make a pointer type\n"); - result.SetStatus(eReturnStatusFailed); - return false; - } - --pointer_count; - } + default: + done = true; + break; + } + } + } - m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize(nullptr); - - if (m_format_options.GetByteSizeValue() == 0) - { - result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n", - view_as_type_cstr); - result.SetStatus(eReturnStatusFailed); - return false; - } - - if (!m_format_options.GetCountValue().OptionWasSet()) - m_format_options.GetCountValue() = 1; + llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; + ConstString lookup_type_name(type_str.c_str()); + StackFrame *frame = m_exe_ctx.GetFramePtr(); + if (frame) { + sc = frame->GetSymbolContext(eSymbolContextModule); + if (sc.module_sp) { + sc.module_sp->FindTypes(sc, lookup_type_name, exact_match, 1, + searched_symbol_files, type_list); } - else - { - error = m_memory_options.FinalizeSettings (target, m_format_options); + } + if (type_list.GetSize() == 0) { + target->GetImages().FindTypes(sc, lookup_type_name, exact_match, 1, + searched_symbol_files, type_list); + } + + if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && + *lookup_type_name.GetCString() == '$') { + if (ClangPersistentVariables *persistent_vars = + llvm::dyn_cast_or_null<ClangPersistentVariables>( + target->GetPersistentExpressionStateForLanguage( + lldb::eLanguageTypeC))) { + clang::TypeDecl *tdecl = llvm::dyn_cast_or_null<clang::TypeDecl>( + persistent_vars->GetPersistentDecl( + ConstString(lookup_type_name))); + + if (tdecl) { + clang_ast_type.SetCompilerType( + ClangASTContext::GetASTContext(&tdecl->getASTContext()), + reinterpret_cast<lldb::opaque_compiler_type_t>( + const_cast<clang::Type *>(tdecl->getTypeForDecl()))); + } } + } - // Look for invalid combinations of settings - if (error.Fail()) - { - result.AppendError(error.AsCString()); - result.SetStatus(eReturnStatusFailed); - return false; + if (!clang_ast_type.IsValid()) { + if (type_list.GetSize() == 0) { + result.AppendErrorWithFormat("unable to find any types that match " + "the raw type '%s' for full type '%s'\n", + lookup_type_name.GetCString(), + view_as_type_cstr); + result.SetStatus(eReturnStatusFailed); + return false; + } else { + TypeSP type_sp(type_list.GetTypeAtIndex(0)); + clang_ast_type = type_sp->GetFullCompilerType(); } + } - lldb::addr_t addr; - size_t total_byte_size = 0; - if (argc == 0) - { - // Use the last address and byte size and all options as they were - // if no options have been set - addr = m_next_addr; - total_byte_size = m_prev_byte_size; - clang_ast_type = m_prev_clang_ast_type; - if (!m_format_options.AnyOptionWasSet() && - !m_memory_options.AnyOptionWasSet() && - !m_outfile_options.AnyOptionWasSet() && - !m_varobj_options.AnyOptionWasSet()) - { - m_format_options = m_prev_format_options; - m_memory_options = m_prev_memory_options; - m_outfile_options = m_prev_outfile_options; - m_varobj_options = m_prev_varobj_options; - } + while (pointer_count > 0) { + CompilerType pointer_type = clang_ast_type.GetPointerType(); + if (pointer_type.IsValid()) + clang_ast_type = pointer_type; + else { + result.AppendError("unable make a pointer type\n"); + result.SetStatus(eReturnStatusFailed); + return false; } + --pointer_count; + } - size_t item_count = m_format_options.GetCountValue().GetCurrentValue(); + m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize(nullptr); - // TODO For non-8-bit byte addressable architectures this needs to be - // revisited to fully support all lldb's range of formatting options. - // Furthermore code memory reads (for those architectures) will not - // be correctly formatted even w/o formatting options. - size_t item_byte_size = - target->GetArchitecture().GetDataByteSize() > 1 ? - target->GetArchitecture().GetDataByteSize() : - m_format_options.GetByteSizeValue().GetCurrentValue(); + if (m_format_options.GetByteSizeValue() == 0) { + result.AppendErrorWithFormat( + "unable to get the byte size of the type '%s'\n", + view_as_type_cstr); + result.SetStatus(eReturnStatusFailed); + return false; + } - const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue(); + if (!m_format_options.GetCountValue().OptionWasSet()) + m_format_options.GetCountValue() = 1; + } else { + error = m_memory_options.FinalizeSettings(target, m_format_options); + } - if (total_byte_size == 0) - { - total_byte_size = item_count * item_byte_size; - if (total_byte_size == 0) - total_byte_size = 32; - } + // Look for invalid combinations of settings + if (error.Fail()) { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } - if (argc > 0) - addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error); + lldb::addr_t addr; + size_t total_byte_size = 0; + if (argc == 0) { + // Use the last address and byte size and all options as they were + // if no options have been set + addr = m_next_addr; + total_byte_size = m_prev_byte_size; + clang_ast_type = m_prev_clang_ast_type; + if (!m_format_options.AnyOptionWasSet() && + !m_memory_options.AnyOptionWasSet() && + !m_outfile_options.AnyOptionWasSet() && + !m_varobj_options.AnyOptionWasSet()) { + m_format_options = m_prev_format_options; + m_memory_options = m_prev_memory_options; + m_outfile_options = m_prev_outfile_options; + m_varobj_options = m_prev_varobj_options; + } + } - if (addr == LLDB_INVALID_ADDRESS) - { - result.AppendError("invalid start address expression."); - result.AppendError(error.AsCString()); - result.SetStatus(eReturnStatusFailed); - return false; - } + size_t item_count = m_format_options.GetCountValue().GetCurrentValue(); - if (argc == 2) - { - lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), - LLDB_INVALID_ADDRESS, nullptr); - if (end_addr == LLDB_INVALID_ADDRESS) - { - result.AppendError("invalid end address expression."); - result.AppendError(error.AsCString()); - result.SetStatus(eReturnStatusFailed); - return false; - } - else if (end_addr <= addr) - { - result.AppendErrorWithFormat("end address (0x%" PRIx64 ") must be greater that the start address (0x%" PRIx64 ").\n", end_addr, addr); - result.SetStatus(eReturnStatusFailed); - return false; - } - else if (m_format_options.GetCountValue().OptionWasSet()) - { - result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %" PRIu64 "), not both.\n", end_addr, (uint64_t)item_count); - result.SetStatus(eReturnStatusFailed); - return false; - } + // TODO For non-8-bit byte addressable architectures this needs to be + // revisited to fully support all lldb's range of formatting options. + // Furthermore code memory reads (for those architectures) will not + // be correctly formatted even w/o formatting options. + size_t item_byte_size = + target->GetArchitecture().GetDataByteSize() > 1 + ? target->GetArchitecture().GetDataByteSize() + : m_format_options.GetByteSizeValue().GetCurrentValue(); - total_byte_size = end_addr - addr; - item_count = total_byte_size / item_byte_size; - } + const size_t num_per_line = + m_memory_options.m_num_per_line.GetCurrentValue(); - uint32_t max_unforced_size = target->GetMaximumMemReadSize(); - - if (total_byte_size > max_unforced_size && !m_memory_options.m_force) - { - result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size); - result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n"); - result.AppendErrorWithFormat("or set target.max-memory-read-size if you will often need a larger limit.\n"); - return false; - } - - DataBufferSP data_sp; - size_t bytes_read = 0; - if (clang_ast_type.GetOpaqueQualType()) - { - // Make sure we don't display our type as ASCII bytes like the default memory read - if (!m_format_options.GetFormatValue().OptionWasSet()) - m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault); - - bytes_read = clang_ast_type.GetByteSize(nullptr) * m_format_options.GetCountValue().GetCurrentValue(); - - if (argc > 0) - addr = addr + (clang_ast_type.GetByteSize(nullptr) * m_memory_options.m_offset.GetCurrentValue()); - } - else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString) - { - data_sp.reset (new DataBufferHeap (total_byte_size, '\0')); - if (data_sp->GetBytes() == nullptr) - { - result.AppendErrorWithFormat ("can't allocate 0x%" PRIx32 " bytes for the memory read buffer, specify a smaller size to read", (uint32_t)total_byte_size); - result.SetStatus(eReturnStatusFailed); - return false; - } + if (total_byte_size == 0) { + total_byte_size = item_count * item_byte_size; + if (total_byte_size == 0) + total_byte_size = 32; + } - Address address(addr, nullptr); - bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error); - if (bytes_read == 0) - { - const char *error_cstr = error.AsCString(); - if (error_cstr && error_cstr[0]) - { - result.AppendError(error_cstr); - } - else - { - result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr); - } - result.SetStatus(eReturnStatusFailed); - return false; - } - - if (bytes_read < total_byte_size) - result.AppendWarningWithFormat("Not all bytes (%" PRIu64 "/%" PRIu64 ") were able to be read from 0x%" PRIx64 ".\n", (uint64_t)bytes_read, (uint64_t)total_byte_size, addr); - } - else - { - // we treat c-strings as a special case because they do not have a fixed size - if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat()) - item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue(); - else - item_byte_size = target->GetMaximumSizeOfStringSummary(); - if (!m_format_options.GetCountValue().OptionWasSet()) - item_count = 1; - data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary - if (data_sp->GetBytes() == nullptr) - { - result.AppendErrorWithFormat ("can't allocate 0x%" PRIx64 " bytes for the memory read buffer, specify a smaller size to read", (uint64_t)((item_byte_size+1) * item_count)); - result.SetStatus(eReturnStatusFailed); - return false; - } - uint8_t *data_ptr = data_sp->GetBytes(); - auto data_addr = addr; - auto count = item_count; - item_count = 0; - bool break_on_no_NULL = false; - while (item_count < count) - { - std::string buffer; - buffer.resize(item_byte_size+1,0); - Error error; - size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error); - if (error.Fail()) - { - result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr); - result.SetStatus(eReturnStatusFailed); - return false; - } - - if (item_byte_size == read) - { - result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr); - --read; - break_on_no_NULL = true; - } - else - ++read; // account for final NULL byte - - memcpy(data_ptr, &buffer[0], read); - data_ptr += read; - data_addr += read; - bytes_read += read; - item_count++; // if we break early we know we only read item_count strings - - if (break_on_no_NULL) - break; - } - data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1)); - } + if (argc > 0) + addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), + LLDB_INVALID_ADDRESS, &error); - m_next_addr = addr + bytes_read; - m_prev_byte_size = bytes_read; - m_prev_format_options = m_format_options; - m_prev_memory_options = m_memory_options; - m_prev_outfile_options = m_outfile_options; - m_prev_varobj_options = m_varobj_options; - m_prev_clang_ast_type = clang_ast_type; - - StreamFile outfile_stream; - Stream *output_stream = nullptr; - const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue(); - if (outfile_spec) - { - char path[PATH_MAX]; - outfile_spec.GetPath (path, sizeof(path)); - - uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; - const bool append = m_outfile_options.GetAppend().GetCurrentValue(); - if (append) - open_options |= File::eOpenOptionAppend; - - if (outfile_stream.GetFile ().Open (path, open_options).Success()) - { - if (m_memory_options.m_output_as_binary) - { - const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read); - if (bytes_written > 0) - { - result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n", - bytes_written, - append ? "appended" : "written", - path); - return true; - } - else - { - result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - else - { - // We are going to write ASCII to the file just point the - // output_stream to our outfile_stream... - output_stream = &outfile_stream; - } - } - else - { - result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write"); - result.SetStatus(eReturnStatusFailed); - return false; - } + if (addr == LLDB_INVALID_ADDRESS) { + result.AppendError("invalid start address expression."); + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (argc == 2) { + lldb::addr_t end_addr = + Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), + LLDB_INVALID_ADDRESS, nullptr); + if (end_addr == LLDB_INVALID_ADDRESS) { + result.AppendError("invalid end address expression."); + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } else if (end_addr <= addr) { + result.AppendErrorWithFormat( + "end address (0x%" PRIx64 + ") must be greater that the start address (0x%" PRIx64 ").\n", + end_addr, addr); + result.SetStatus(eReturnStatusFailed); + return false; + } else if (m_format_options.GetCountValue().OptionWasSet()) { + result.AppendErrorWithFormat( + "specify either the end address (0x%" PRIx64 + ") or the count (--count %" PRIu64 "), not both.\n", + end_addr, (uint64_t)item_count); + result.SetStatus(eReturnStatusFailed); + return false; + } + + total_byte_size = end_addr - addr; + item_count = total_byte_size / item_byte_size; + } + + uint32_t max_unforced_size = target->GetMaximumMemReadSize(); + + if (total_byte_size > max_unforced_size && !m_memory_options.m_force) { + result.AppendErrorWithFormat( + "Normally, \'memory read\' will not read over %" PRIu32 + " bytes of data.\n", + max_unforced_size); + result.AppendErrorWithFormat( + "Please use --force to override this restriction just once.\n"); + result.AppendErrorWithFormat("or set target.max-memory-read-size if you " + "will often need a larger limit.\n"); + return false; + } + + DataBufferSP data_sp; + size_t bytes_read = 0; + if (clang_ast_type.GetOpaqueQualType()) { + // Make sure we don't display our type as ASCII bytes like the default + // memory read + if (!m_format_options.GetFormatValue().OptionWasSet()) + m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault); + + bytes_read = clang_ast_type.GetByteSize(nullptr) * + m_format_options.GetCountValue().GetCurrentValue(); + + if (argc > 0) + addr = addr + (clang_ast_type.GetByteSize(nullptr) * + m_memory_options.m_offset.GetCurrentValue()); + } else if (m_format_options.GetFormatValue().GetCurrentValue() != + eFormatCString) { + data_sp.reset(new DataBufferHeap(total_byte_size, '\0')); + if (data_sp->GetBytes() == nullptr) { + result.AppendErrorWithFormat( + "can't allocate 0x%" PRIx32 + " bytes for the memory read buffer, specify a smaller size to read", + (uint32_t)total_byte_size); + result.SetStatus(eReturnStatusFailed); + return false; + } + + Address address(addr, nullptr); + bytes_read = target->ReadMemory(address, false, data_sp->GetBytes(), + data_sp->GetByteSize(), error); + if (bytes_read == 0) { + const char *error_cstr = error.AsCString(); + if (error_cstr && error_cstr[0]) { + result.AppendError(error_cstr); + } else { + result.AppendErrorWithFormat( + "failed to read memory from 0x%" PRIx64 ".\n", addr); } - else - { - output_stream = &result.GetOutputStream(); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (bytes_read < total_byte_size) + result.AppendWarningWithFormat( + "Not all bytes (%" PRIu64 "/%" PRIu64 + ") were able to be read from 0x%" PRIx64 ".\n", + (uint64_t)bytes_read, (uint64_t)total_byte_size, addr); + } else { + // we treat c-strings as a special case because they do not have a fixed + // size + if (m_format_options.GetByteSizeValue().OptionWasSet() && + !m_format_options.HasGDBFormat()) + item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue(); + else + item_byte_size = target->GetMaximumSizeOfStringSummary(); + if (!m_format_options.GetCountValue().OptionWasSet()) + item_count = 1; + data_sp.reset(new DataBufferHeap((item_byte_size + 1) * item_count, + '\0')); // account for NULLs as necessary + if (data_sp->GetBytes() == nullptr) { + result.AppendErrorWithFormat( + "can't allocate 0x%" PRIx64 + " bytes for the memory read buffer, specify a smaller size to read", + (uint64_t)((item_byte_size + 1) * item_count)); + result.SetStatus(eReturnStatusFailed); + return false; + } + uint8_t *data_ptr = data_sp->GetBytes(); + auto data_addr = addr; + auto count = item_count; + item_count = 0; + bool break_on_no_NULL = false; + while (item_count < count) { + std::string buffer; + buffer.resize(item_byte_size + 1, 0); + Error error; + size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], + item_byte_size + 1, error); + if (error.Fail()) { + result.AppendErrorWithFormat( + "failed to read memory from 0x%" PRIx64 ".\n", addr); + result.SetStatus(eReturnStatusFailed); + return false; } - ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope(); - if (clang_ast_type.GetOpaqueQualType()) - { - for (uint32_t i = 0; i<item_count; ++i) - { - addr_t item_addr = addr + (i * item_byte_size); - Address address (item_addr); - StreamString name_strm; - name_strm.Printf ("0x%" PRIx64, item_addr); - ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope, - name_strm.GetString().c_str(), - address, - clang_ast_type)); - if (valobj_sp) - { - Format format = m_format_options.GetFormat(); - if (format != eFormatDefault) - valobj_sp->SetFormat (format); - - DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format)); - - valobj_sp->Dump(*output_stream,options); - } - else - { - result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n", - view_as_type_cstr, - name_strm.GetString().c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - } + if (item_byte_size == read) { + result.AppendWarningWithFormat( + "unable to find a NULL terminated string at 0x%" PRIx64 + ".Consider increasing the maximum read length.\n", + data_addr); + --read; + break_on_no_NULL = true; + } else + ++read; // account for final NULL byte + + memcpy(data_ptr, &buffer[0], read); + data_ptr += read; + data_addr += read; + bytes_read += read; + item_count++; // if we break early we know we only read item_count + // strings + + if (break_on_no_NULL) + break; + } + data_sp.reset(new DataBufferHeap(data_sp->GetBytes(), bytes_read + 1)); + } + + m_next_addr = addr + bytes_read; + m_prev_byte_size = bytes_read; + m_prev_format_options = m_format_options; + m_prev_memory_options = m_memory_options; + m_prev_outfile_options = m_outfile_options; + m_prev_varobj_options = m_varobj_options; + m_prev_clang_ast_type = clang_ast_type; + + StreamFile outfile_stream; + Stream *output_stream = nullptr; + const FileSpec &outfile_spec = + m_outfile_options.GetFile().GetCurrentValue(); + if (outfile_spec) { + char path[PATH_MAX]; + outfile_spec.GetPath(path, sizeof(path)); + + uint32_t open_options = + File::eOpenOptionWrite | File::eOpenOptionCanCreate; + const bool append = m_outfile_options.GetAppend().GetCurrentValue(); + if (append) + open_options |= File::eOpenOptionAppend; + + if (outfile_stream.GetFile().Open(path, open_options).Success()) { + if (m_memory_options.m_output_as_binary) { + const size_t bytes_written = + outfile_stream.Write(data_sp->GetBytes(), bytes_read); + if (bytes_written > 0) { + result.GetOutputStream().Printf( + "%zi bytes %s to '%s'\n", bytes_written, + append ? "appended" : "written", path); return true; + } else { + result.AppendErrorWithFormat("Failed to write %" PRIu64 + " bytes to '%s'.\n", + (uint64_t)bytes_read, path); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + // We are going to write ASCII to the file just point the + // output_stream to our outfile_stream... + output_stream = &outfile_stream; } + } else { + result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, + append ? "append" : "write"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + output_stream = &result.GetOutputStream(); + } - result.SetStatus(eReturnStatusSuccessFinishResult); - DataExtractor data (data_sp, - target->GetArchitecture().GetByteOrder(), - target->GetArchitecture().GetAddressByteSize(), - target->GetArchitecture().GetDataByteSize()); - - Format format = m_format_options.GetFormat(); - if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) ) - && (item_byte_size != 1)) - { - // if a count was not passed, or it is 1 - if (!m_format_options.GetCountValue().OptionWasSet() || item_count == 1) - { - // this turns requests such as - // memory read -fc -s10 -c1 *charPtrPtr - // which make no sense (what is a char of size 10?) - // into a request for fetching 10 chars of size 1 from the same memory location - format = eFormatCharArray; - item_count = item_byte_size; - item_byte_size = 1; - } - else - { - // here we passed a count, and it was not 1 - // so we have a byte_size and a count - // we could well multiply those, but instead let's just fail - result.AppendErrorWithFormat("reading memory as characters of size %" PRIu64 " is not supported", (uint64_t)item_byte_size); - result.SetStatus(eReturnStatusFailed); - return false; - } + ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope(); + if (clang_ast_type.GetOpaqueQualType()) { + for (uint32_t i = 0; i < item_count; ++i) { + addr_t item_addr = addr + (i * item_byte_size); + Address address(item_addr); + StreamString name_strm; + name_strm.Printf("0x%" PRIx64, item_addr); + ValueObjectSP valobj_sp(ValueObjectMemory::Create( + exe_scope, name_strm.GetString().c_str(), address, clang_ast_type)); + if (valobj_sp) { + Format format = m_format_options.GetFormat(); + if (format != eFormatDefault) + valobj_sp->SetFormat(format); + + DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions( + eLanguageRuntimeDescriptionDisplayVerbosityFull, format)); + + valobj_sp->Dump(*output_stream, options); + } else { + result.AppendErrorWithFormat( + "failed to create a value object for: (%s) %s\n", + view_as_type_cstr, name_strm.GetString().c_str()); + result.SetStatus(eReturnStatusFailed); + return false; } + } + return true; + } - assert (output_stream); - size_t bytes_dumped = data.Dump (output_stream, - 0, - format, - item_byte_size, - item_count, - num_per_line / target->GetArchitecture().GetDataByteSize(), - addr, - 0, - 0, - exe_scope); - m_next_addr = addr + bytes_dumped; - output_stream->EOL(); - return true; + result.SetStatus(eReturnStatusSuccessFinishResult); + DataExtractor data(data_sp, target->GetArchitecture().GetByteOrder(), + target->GetArchitecture().GetAddressByteSize(), + target->GetArchitecture().GetDataByteSize()); + + Format format = m_format_options.GetFormat(); + if (((format == eFormatChar) || (format == eFormatCharPrintable)) && + (item_byte_size != 1)) { + // if a count was not passed, or it is 1 + if (!m_format_options.GetCountValue().OptionWasSet() || item_count == 1) { + // this turns requests such as + // memory read -fc -s10 -c1 *charPtrPtr + // which make no sense (what is a char of size 10?) + // into a request for fetching 10 chars of size 1 from the same memory + // location + format = eFormatCharArray; + item_count = item_byte_size; + item_byte_size = 1; + } else { + // here we passed a count, and it was not 1 + // so we have a byte_size and a count + // we could well multiply those, but instead let's just fail + result.AppendErrorWithFormat( + "reading memory as characters of size %" PRIu64 " is not supported", + (uint64_t)item_byte_size); + result.SetStatus(eReturnStatusFailed); + return false; + } } - OptionGroupOptions m_option_group; - OptionGroupFormat m_format_options; - OptionGroupReadMemory m_memory_options; - OptionGroupOutputFile m_outfile_options; - OptionGroupValueObjectDisplay m_varobj_options; - lldb::addr_t m_next_addr; - lldb::addr_t m_prev_byte_size; - OptionGroupFormat m_prev_format_options; - OptionGroupReadMemory m_prev_memory_options; - OptionGroupOutputFile m_prev_outfile_options; - OptionGroupValueObjectDisplay m_prev_varobj_options; - CompilerType m_prev_clang_ast_type; + assert(output_stream); + size_t bytes_dumped = + data.Dump(output_stream, 0, format, item_byte_size, item_count, + num_per_line / target->GetArchitecture().GetDataByteSize(), + addr, 0, 0, exe_scope); + m_next_addr = addr + bytes_dumped; + output_stream->EOL(); + return true; + } + + OptionGroupOptions m_option_group; + OptionGroupFormat m_format_options; + OptionGroupReadMemory m_memory_options; + OptionGroupOutputFile m_outfile_options; + OptionGroupValueObjectDisplay m_varobj_options; + lldb::addr_t m_next_addr; + lldb::addr_t m_prev_byte_size; + OptionGroupFormat m_prev_format_options; + OptionGroupReadMemory m_prev_memory_options; + OptionGroupOutputFile m_prev_outfile_options; + OptionGroupValueObjectDisplay m_prev_varobj_options; + CompilerType m_prev_clang_ast_type; }; -OptionDefinition -g_memory_find_option_table[] = -{ - // clang-format off +OptionDefinition g_memory_find_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, true, "expression", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."}, {LLDB_OPT_SET_2, true, "string", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Use text to find a byte pattern."}, {LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "How many times to perform the search."}, {LLDB_OPT_SET_ALL, false, "dump-offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "When dumping memory for a match, an offset from the match location to start dumping from."}, - // clang-format on + // clang-format on }; //---------------------------------------------------------------------- // Find the specified data in memory //---------------------------------------------------------------------- -class CommandObjectMemoryFind : public CommandObjectParsed -{ +class CommandObjectMemoryFind : public CommandObjectParsed { public: - class OptionGroupFindMemory : public OptionGroup - { + class OptionGroupFindMemory : public OptionGroup { public: - OptionGroupFindMemory () : - OptionGroup(), - m_count(1), - m_offset(0) - { - } + OptionGroupFindMemory() : OptionGroup(), m_count(1), m_offset(0) {} ~OptionGroupFindMemory() override = default; - uint32_t - GetNumDefinitions () override - { - return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition); + uint32_t GetNumDefinitions() override { + return sizeof(g_memory_find_option_table) / sizeof(OptionDefinition); } - - const OptionDefinition* - GetDefinitions () override - { + + const OptionDefinition *GetDefinitions() override { return g_memory_find_option_table; } - - Error - SetOptionValue (uint32_t option_idx, - const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = g_memory_find_option_table[option_idx].short_option; - - switch (short_option) - { - case 'e': - m_expr.SetValueFromString(option_arg); - break; - - case 's': - m_string.SetValueFromString(option_arg); - break; - - case 'c': - if (m_count.SetValueFromString(option_arg).Fail()) - error.SetErrorString("unrecognized value for count"); - break; - - case 'o': - if (m_offset.SetValueFromString(option_arg).Fail()) - error.SetErrorString("unrecognized value for dump-offset"); - break; - default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); - break; - } - return error; + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = + g_memory_find_option_table[option_idx].short_option; + + switch (short_option) { + case 'e': + m_expr.SetValueFromString(option_arg); + break; + + case 's': + m_string.SetValueFromString(option_arg); + break; + + case 'c': + if (m_count.SetValueFromString(option_arg).Fail()) + error.SetErrorString("unrecognized value for count"); + break; + + case 'o': + if (m_offset.SetValueFromString(option_arg).Fail()) + error.SetErrorString("unrecognized value for dump-offset"); + break; + + default: + error.SetErrorStringWithFormat("unrecognized short option '%c'", + short_option); + break; + } + return error; } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_expr.Clear(); - m_string.Clear(); - m_count.Clear(); + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_expr.Clear(); + m_string.Clear(); + m_count.Clear(); } - - OptionValueString m_expr; - OptionValueString m_string; - OptionValueUInt64 m_count; - OptionValueUInt64 m_offset; + + OptionValueString m_expr; + OptionValueString m_string; + OptionValueUInt64 m_count; + OptionValueUInt64 m_offset; }; CommandObjectMemoryFind(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "memory find", "Find a value in the memory of the current target process.", - nullptr, eCommandRequiresProcess | eCommandProcessMustBeLaunched), - m_option_group(), - m_memory_options() - { + : CommandObjectParsed( + interpreter, "memory find", + "Find a value in the memory of the current target process.", + nullptr, eCommandRequiresProcess | eCommandProcessMustBeLaunched), + m_option_group(), m_memory_options() { CommandArgumentEntry arg1; CommandArgumentEntry arg2; CommandArgumentData addr_arg; CommandArgumentData value_arg; - + // Define the first (and only) variant of this arg. addr_arg.arg_type = eArgTypeAddressOrExpression; addr_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg1.push_back (addr_arg); - + + // There is only one variant this argument could be; put it into the + // argument entry. + arg1.push_back(addr_arg); + // Define the first (and only) variant of this arg. value_arg.arg_type = eArgTypeAddressOrExpression; value_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg2.push_back (value_arg); - + + // There is only one variant this argument could be; put it into the + // argument entry. + arg2.push_back(value_arg); + // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg1); - m_arguments.push_back (arg2); - - m_option_group.Append (&m_memory_options); + m_arguments.push_back(arg1); + m_arguments.push_back(arg2); + + m_option_group.Append(&m_memory_options); m_option_group.Finalize(); } ~CommandObjectMemoryFind() override = default; - Options * - GetOptions () override - { - return &m_option_group; - } - + Options *GetOptions() override { return &m_option_group; } + protected: - class ProcessMemoryIterator - { + class ProcessMemoryIterator { public: - ProcessMemoryIterator (ProcessSP process_sp, - lldb::addr_t base) : - m_process_sp(process_sp), - m_base_addr(base), - m_is_valid(true) - { - lldbassert(process_sp.get() != nullptr); - } - - bool - IsValid () - { - return m_is_valid; - } - - uint8_t - operator [](lldb::addr_t offset) - { - if (!IsValid()) - return 0; - - uint8_t retval = 0; - Error error; - if (0 == m_process_sp->ReadMemory(m_base_addr+offset, &retval, 1, error)) - { - m_is_valid = false; - return 0; - } + ProcessMemoryIterator(ProcessSP process_sp, lldb::addr_t base) + : m_process_sp(process_sp), m_base_addr(base), m_is_valid(true) { + lldbassert(process_sp.get() != nullptr); + } - return retval; + bool IsValid() { return m_is_valid; } + + uint8_t operator[](lldb::addr_t offset) { + if (!IsValid()) + return 0; + + uint8_t retval = 0; + Error error; + if (0 == + m_process_sp->ReadMemory(m_base_addr + offset, &retval, 1, error)) { + m_is_valid = false; + return 0; } + + return retval; + } + private: - ProcessSP m_process_sp; - lldb::addr_t m_base_addr; - bool m_is_valid; + ProcessSP m_process_sp; + lldb::addr_t m_base_addr; + bool m_is_valid; }; - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid - Process *process = m_exe_ctx.GetProcessPtr(); + bool DoExecute(Args &command, CommandReturnObject &result) override { + // No need to check "process" for validity as eCommandRequiresProcess + // ensures it is valid + Process *process = m_exe_ctx.GetProcessPtr(); - const size_t argc = command.GetArgumentCount(); + const size_t argc = command.GetArgumentCount(); - if (argc != 2) - { - result.AppendError("two addresses needed for memory find"); - return false; - } + if (argc != 2) { + result.AppendError("two addresses needed for memory find"); + return false; + } - Error error; - lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0),LLDB_INVALID_ADDRESS,&error); - if (low_addr == LLDB_INVALID_ADDRESS || error.Fail()) - { - result.AppendError("invalid low address"); + Error error; + lldb::addr_t low_addr = + Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), + LLDB_INVALID_ADDRESS, &error); + if (low_addr == LLDB_INVALID_ADDRESS || error.Fail()) { + result.AppendError("invalid low address"); + return false; + } + lldb::addr_t high_addr = + Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), + LLDB_INVALID_ADDRESS, &error); + if (high_addr == LLDB_INVALID_ADDRESS || error.Fail()) { + result.AppendError("invalid high address"); + return false; + } + + if (high_addr <= low_addr) { + result.AppendError( + "starting address must be smaller than ending address"); + return false; + } + + lldb::addr_t found_location = LLDB_INVALID_ADDRESS; + + DataBufferHeap buffer; + + if (m_memory_options.m_string.OptionWasSet()) + buffer.CopyData(m_memory_options.m_string.GetStringValue(), + strlen(m_memory_options.m_string.GetStringValue())); + else if (m_memory_options.m_expr.OptionWasSet()) { + StackFrame *frame = m_exe_ctx.GetFramePtr(); + ValueObjectSP result_sp; + if ((eExpressionCompleted == + process->GetTarget().EvaluateExpression( + m_memory_options.m_expr.GetStringValue(), frame, result_sp)) && + result_sp) { + uint64_t value = result_sp->GetValueAsUnsigned(0); + switch (result_sp->GetCompilerType().GetByteSize(nullptr)) { + case 1: { + uint8_t byte = (uint8_t)value; + buffer.CopyData(&byte, 1); + } break; + case 2: { + uint16_t word = (uint16_t)value; + buffer.CopyData(&word, 2); + } break; + case 4: { + uint32_t lword = (uint32_t)value; + buffer.CopyData(&lword, 4); + } break; + case 8: { + buffer.CopyData(&value, 8); + } break; + case 3: + case 5: + case 6: + case 7: + result.AppendError("unknown type. pass a string instead"); return false; - } - lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error); - if (high_addr == LLDB_INVALID_ADDRESS || error.Fail()) - { - result.AppendError("invalid high address"); + default: + result.AppendError( + "result size larger than 8 bytes. pass a string instead"); return false; + } + } else { + result.AppendError( + "expression evaluation failed. pass a string instead"); + return false; } + } else { + result.AppendError( + "please pass either a block of text, or an expression to evaluate."); + return false; + } - if (high_addr <= low_addr) - { - result.AppendError("starting address must be smaller than ending address"); - return false; + size_t count = m_memory_options.m_count.GetCurrentValue(); + found_location = low_addr; + bool ever_found = false; + while (count) { + found_location = FastSearch(found_location, high_addr, buffer.GetBytes(), + buffer.GetByteSize()); + if (found_location == LLDB_INVALID_ADDRESS) { + if (!ever_found) { + result.AppendMessage("data not found within the range.\n"); + result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); + } else + result.AppendMessage("no more matches within the range.\n"); + break; } - - lldb::addr_t found_location = LLDB_INVALID_ADDRESS; - - DataBufferHeap buffer; - - if (m_memory_options.m_string.OptionWasSet()) - buffer.CopyData(m_memory_options.m_string.GetStringValue(), strlen(m_memory_options.m_string.GetStringValue())); - else if (m_memory_options.m_expr.OptionWasSet()) - { - StackFrame* frame = m_exe_ctx.GetFramePtr(); - ValueObjectSP result_sp; - if ((eExpressionCompleted == process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp)) && - result_sp) - { - uint64_t value = result_sp->GetValueAsUnsigned(0); - switch (result_sp->GetCompilerType().GetByteSize(nullptr)) - { - case 1: { - uint8_t byte = (uint8_t)value; - buffer.CopyData(&byte,1); - } - break; - case 2: { - uint16_t word = (uint16_t)value; - buffer.CopyData(&word,2); - } - break; - case 4: { - uint32_t lword = (uint32_t)value; - buffer.CopyData(&lword,4); - } - break; - case 8: { - buffer.CopyData(&value, 8); - } - break; - case 3: - case 5: - case 6: - case 7: - result.AppendError("unknown type. pass a string instead"); - return false; - default: - result.AppendError("result size larger than 8 bytes. pass a string instead"); - return false; - } - } - else - { - result.AppendError("expression evaluation failed. pass a string instead"); - return false; - } + result.AppendMessageWithFormat("data found at location: 0x%" PRIx64 "\n", + found_location); + + DataBufferHeap dumpbuffer(32, 0); + process->ReadMemory( + found_location + m_memory_options.m_offset.GetCurrentValue(), + dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error); + if (!error.Fail()) { + DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), + process->GetByteOrder(), + process->GetAddressByteSize()); + data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, + dumpbuffer.GetByteSize(), 16, + found_location + m_memory_options.m_offset.GetCurrentValue(), + 0, 0); + result.GetOutputStream().EOL(); } - else - { - result.AppendError("please pass either a block of text, or an expression to evaluate."); - return false; - } - - size_t count = m_memory_options.m_count.GetCurrentValue(); - found_location = low_addr; - bool ever_found = false; - while (count) - { - found_location = FastSearch(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize()); - if (found_location == LLDB_INVALID_ADDRESS) - { - if (!ever_found) - { - result.AppendMessage("data not found within the range.\n"); - result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); - } - else - result.AppendMessage("no more matches within the range.\n"); - break; - } - result.AppendMessageWithFormat("data found at location: 0x%" PRIx64 "\n", found_location); - - DataBufferHeap dumpbuffer(32,0); - process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error); - if (!error.Fail()) - { - DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize()); - data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0); - result.GetOutputStream().EOL(); - } - --count; - found_location++; - ever_found = true; - } - - result.SetStatus(lldb::eReturnStatusSuccessFinishResult); - return true; + --count; + found_location++; + ever_found = true; + } + + result.SetStatus(lldb::eReturnStatusSuccessFinishResult); + return true; } - - lldb::addr_t - FastSearch (lldb::addr_t low, - lldb::addr_t high, - uint8_t *buffer, - size_t buffer_size) - { - const size_t region_size = high-low; - - if (region_size < buffer_size) - return LLDB_INVALID_ADDRESS; - - std::vector<size_t> bad_char_heuristic(256, buffer_size); - ProcessSP process_sp = m_exe_ctx.GetProcessSP(); - ProcessMemoryIterator iterator(process_sp, low); - - for (size_t idx = 0; - idx < buffer_size-1; - idx++) - { - decltype(bad_char_heuristic)::size_type bcu_idx = buffer[idx]; - bad_char_heuristic[bcu_idx] = buffer_size - idx - 1; - } - for (size_t s = 0; - s <= (region_size - buffer_size); - ) - { - int64_t j = buffer_size-1; - while (j >= 0 && buffer[j] == iterator[s + j]) - j--; - if (j < 0) - return low+s; - else - s += bad_char_heuristic[iterator[s + buffer_size - 1]]; - } - - return LLDB_INVALID_ADDRESS; + + lldb::addr_t FastSearch(lldb::addr_t low, lldb::addr_t high, uint8_t *buffer, + size_t buffer_size) { + const size_t region_size = high - low; + + if (region_size < buffer_size) + return LLDB_INVALID_ADDRESS; + + std::vector<size_t> bad_char_heuristic(256, buffer_size); + ProcessSP process_sp = m_exe_ctx.GetProcessSP(); + ProcessMemoryIterator iterator(process_sp, low); + + for (size_t idx = 0; idx < buffer_size - 1; idx++) { + decltype(bad_char_heuristic)::size_type bcu_idx = buffer[idx]; + bad_char_heuristic[bcu_idx] = buffer_size - idx - 1; } - - OptionGroupOptions m_option_group; - OptionGroupFindMemory m_memory_options; + for (size_t s = 0; s <= (region_size - buffer_size);) { + int64_t j = buffer_size - 1; + while (j >= 0 && buffer[j] == iterator[s + j]) + j--; + if (j < 0) + return low + s; + else + s += bad_char_heuristic[iterator[s + buffer_size - 1]]; + } + + return LLDB_INVALID_ADDRESS; + } + + OptionGroupOptions m_option_group; + OptionGroupFindMemory m_memory_options; }; -OptionDefinition -g_memory_write_option_table[] = -{ - // clang-format off +OptionDefinition g_memory_write_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename, "Write memory using the contents of a file."}, {LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "Start writing bytes from an offset within the input file."}, - // clang-format on + // clang-format on }; //---------------------------------------------------------------------- // Write memory to the inferior process //---------------------------------------------------------------------- -class CommandObjectMemoryWrite : public CommandObjectParsed -{ +class CommandObjectMemoryWrite : public CommandObjectParsed { public: - class OptionGroupWriteMemory : public OptionGroup - { - public: - OptionGroupWriteMemory () : - OptionGroup() - { - } + class OptionGroupWriteMemory : public OptionGroup { + public: + OptionGroupWriteMemory() : OptionGroup() {} - ~OptionGroupWriteMemory() override = default; + ~OptionGroupWriteMemory() override = default; - uint32_t - GetNumDefinitions () override - { - return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition); - } - - const OptionDefinition* - GetDefinitions () override - { - return g_memory_write_option_table; - } - - Error - SetOptionValue (uint32_t option_idx, - const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = g_memory_write_option_table[option_idx].short_option; - - switch (short_option) - { - case 'i': - m_infile.SetFile (option_arg, true); - if (!m_infile.Exists()) - { - m_infile.Clear(); - error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg); - } - break; - - case 'o': - { - bool success; - m_infile_offset = StringConvert::ToUInt64(option_arg, 0, 0, &success); - if (!success) - { - error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg); - } - } - break; - - default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); - break; - } - return error; + uint32_t GetNumDefinitions() override { + return sizeof(g_memory_write_option_table) / sizeof(OptionDefinition); + } + + const OptionDefinition *GetDefinitions() override { + return g_memory_write_option_table; + } + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = + g_memory_write_option_table[option_idx].short_option; + + switch (short_option) { + case 'i': + m_infile.SetFile(option_arg, true); + if (!m_infile.Exists()) { + m_infile.Clear(); + error.SetErrorStringWithFormat("input file does not exist: '%s'", + option_arg); } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_infile.Clear(); - m_infile_offset = 0; + break; + + case 'o': { + bool success; + m_infile_offset = StringConvert::ToUInt64(option_arg, 0, 0, &success); + if (!success) { + error.SetErrorStringWithFormat("invalid offset string '%s'", + option_arg); } + } break; - FileSpec m_infile; - off_t m_infile_offset; - }; - - CommandObjectMemoryWrite(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "memory write", "Write to the memory of the current target process.", - nullptr, eCommandRequiresProcess | eCommandProcessMustBeLaunched), - m_option_group(), - m_format_options(eFormatBytes, 1, UINT64_MAX), - m_memory_options() - { - CommandArgumentEntry arg1; - CommandArgumentEntry arg2; - CommandArgumentData addr_arg; - CommandArgumentData value_arg; - - // Define the first (and only) variant of this arg. - addr_arg.arg_type = eArgTypeAddress; - addr_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg1.push_back (addr_arg); - - // Define the first (and only) variant of this arg. - value_arg.arg_type = eArgTypeValue; - value_arg.arg_repetition = eArgRepeatPlus; - - // There is only one variant this argument could be; put it into the argument entry. - arg2.push_back (value_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg1); - m_arguments.push_back (arg2); - - m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1); - m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2); - m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2); - m_option_group.Finalize(); + default: + error.SetErrorStringWithFormat("unrecognized short option '%c'", + short_option); + break; + } + return error; } - ~CommandObjectMemoryWrite() override = default; - - Options * - GetOptions () override - { - return &m_option_group; + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_infile.Clear(); + m_infile_offset = 0; } - bool - UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size) - { - if (total_byte_size > 8) - return false; + FileSpec m_infile; + off_t m_infile_offset; + }; - if (total_byte_size == 8) - return true; + CommandObjectMemoryWrite(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "memory write", + "Write to the memory of the current target process.", nullptr, + eCommandRequiresProcess | eCommandProcessMustBeLaunched), + m_option_group(), m_format_options(eFormatBytes, 1, UINT64_MAX), + m_memory_options() { + CommandArgumentEntry arg1; + CommandArgumentEntry arg2; + CommandArgumentData addr_arg; + CommandArgumentData value_arg; - const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1; - return uval64 <= max; + // Define the first (and only) variant of this arg. + addr_arg.arg_type = eArgTypeAddress; + addr_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg1.push_back(addr_arg); + + // Define the first (and only) variant of this arg. + value_arg.arg_type = eArgTypeValue; + value_arg.arg_repetition = eArgRepeatPlus; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg2.push_back(value_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg1); + m_arguments.push_back(arg2); + + m_option_group.Append(&m_format_options, + OptionGroupFormat::OPTION_GROUP_FORMAT, + LLDB_OPT_SET_1); + m_option_group.Append(&m_format_options, + OptionGroupFormat::OPTION_GROUP_SIZE, + LLDB_OPT_SET_1 | LLDB_OPT_SET_2); + m_option_group.Append(&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2); + m_option_group.Finalize(); + } + + ~CommandObjectMemoryWrite() override = default; + + Options *GetOptions() override { return &m_option_group; } + + bool UIntValueIsValidForSize(uint64_t uval64, size_t total_byte_size) { + if (total_byte_size > 8) + return false; + + if (total_byte_size == 8) + return true; + + const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1; + return uval64 <= max; + } + + bool SIntValueIsValidForSize(int64_t sval64, size_t total_byte_size) { + if (total_byte_size > 8) + return false; + + if (total_byte_size == 8) + return true; + + const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1; + const int64_t min = ~(max); + return min <= sval64 && sval64 <= max; + } + +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + // No need to check "process" for validity as eCommandRequiresProcess + // ensures it is valid + Process *process = m_exe_ctx.GetProcessPtr(); + + const size_t argc = command.GetArgumentCount(); + + if (m_memory_options.m_infile) { + if (argc < 1) { + result.AppendErrorWithFormat( + "%s takes a destination address when writing file contents.\n", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else if (argc < 2) { + result.AppendErrorWithFormat( + "%s takes a destination address and at least one value.\n", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; } - bool - SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size) - { - if (total_byte_size > 8) - return false; + StreamString buffer( + Stream::eBinary, + process->GetTarget().GetArchitecture().GetAddressByteSize(), + process->GetTarget().GetArchitecture().GetByteOrder()); - if (total_byte_size == 8) - return true; + OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue(); + size_t item_byte_size = byte_size_value.GetCurrentValue(); + + Error error; + lldb::addr_t addr = + Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), + LLDB_INVALID_ADDRESS, &error); - const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1; - const int64_t min = ~(max); - return min <= sval64 && sval64 <= max; + if (addr == LLDB_INVALID_ADDRESS) { + result.AppendError("invalid address expression\n"); + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; } -protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid - Process *process = m_exe_ctx.GetProcessPtr(); - - const size_t argc = command.GetArgumentCount(); - - if (m_memory_options.m_infile) - { - if (argc < 1) - { - result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - else if (argc < 2) - { - result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str()); + if (m_memory_options.m_infile) { + size_t length = SIZE_MAX; + if (item_byte_size > 1) + length = item_byte_size; + lldb::DataBufferSP data_sp(m_memory_options.m_infile.ReadFileContents( + m_memory_options.m_infile_offset, length)); + if (data_sp) { + length = data_sp->GetByteSize(); + if (length > 0) { + Error error; + size_t bytes_written = + process->WriteMemory(addr, data_sp->GetBytes(), length, error); + + if (bytes_written == length) { + // All bytes written + result.GetOutputStream().Printf( + "%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", + (uint64_t)bytes_written, addr); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else if (bytes_written > 0) { + // Some byte written + result.GetOutputStream().Printf( + "%" PRIu64 " bytes of %" PRIu64 + " requested were written to 0x%" PRIx64 "\n", + (uint64_t)bytes_written, (uint64_t)length, addr); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat("Memory write to 0x%" PRIx64 + " failed: %s.\n", + addr, error.AsCString()); result.SetStatus(eReturnStatusFailed); - return false; + } } + } else { + result.AppendErrorWithFormat("Unable to read contents of file.\n"); + result.SetStatus(eReturnStatusFailed); + } + return result.Succeeded(); + } else if (item_byte_size == 0) { + if (m_format_options.GetFormat() == eFormatPointer) + item_byte_size = buffer.GetAddressByteSize(); + else + item_byte_size = 1; + } - StreamString buffer (Stream::eBinary, - process->GetTarget().GetArchitecture().GetAddressByteSize(), - process->GetTarget().GetArchitecture().GetByteOrder()); - - OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue(); - size_t item_byte_size = byte_size_value.GetCurrentValue(); - - Error error; - lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx, - command.GetArgumentAtIndex(0), - LLDB_INVALID_ADDRESS, - &error); - - if (addr == LLDB_INVALID_ADDRESS) - { - result.AppendError("invalid address expression\n"); - result.AppendError(error.AsCString()); + command.Shift(); // shift off the address argument + uint64_t uval64; + int64_t sval64; + bool success = false; + const size_t num_value_args = command.GetArgumentCount(); + for (size_t i = 0; i < num_value_args; ++i) { + const char *value_str = command.GetArgumentAtIndex(i); + + switch (m_format_options.GetFormat()) { + case kNumFormats: + case eFormatFloat: // TODO: add support for floats soon + case eFormatCharPrintable: + case eFormatBytesWithASCII: + case eFormatComplex: + case eFormatEnum: + case eFormatUnicode16: + case eFormatUnicode32: + case eFormatVectorOfChar: + case eFormatVectorOfSInt8: + case eFormatVectorOfUInt8: + case eFormatVectorOfSInt16: + case eFormatVectorOfUInt16: + case eFormatVectorOfSInt32: + case eFormatVectorOfUInt32: + case eFormatVectorOfSInt64: + case eFormatVectorOfUInt64: + case eFormatVectorOfFloat16: + case eFormatVectorOfFloat32: + case eFormatVectorOfFloat64: + case eFormatVectorOfUInt128: + case eFormatOSType: + case eFormatComplexInteger: + case eFormatAddressInfo: + case eFormatHexFloat: + case eFormatInstruction: + case eFormatVoid: + result.AppendError("unsupported format for writing memory"); + result.SetStatus(eReturnStatusFailed); + return false; + + case eFormatDefault: + case eFormatBytes: + case eFormatHex: + case eFormatHexUppercase: + case eFormatPointer: + // Decode hex bytes + uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 16, &success); + if (!success) { + result.AppendErrorWithFormat( + "'%s' is not a valid hex string value.\n", value_str); + result.SetStatus(eReturnStatusFailed); + return false; + } else if (!UIntValueIsValidForSize(uval64, item_byte_size)) { + result.AppendErrorWithFormat("Value 0x%" PRIx64 + " is too large to fit in a %" PRIu64 + " byte unsigned integer value.\n", + uval64, (uint64_t)item_byte_size); + result.SetStatus(eReturnStatusFailed); + return false; + } + buffer.PutMaxHex64(uval64, item_byte_size); + break; + + case eFormatBoolean: + uval64 = Args::StringToBoolean(value_str, false, &success); + if (!success) { + result.AppendErrorWithFormat( + "'%s' is not a valid boolean string value.\n", value_str); + result.SetStatus(eReturnStatusFailed); + return false; + } + buffer.PutMaxHex64(uval64, item_byte_size); + break; + + case eFormatBinary: + uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 2, &success); + if (!success) { + result.AppendErrorWithFormat( + "'%s' is not a valid binary string value.\n", value_str); + result.SetStatus(eReturnStatusFailed); + return false; + } else if (!UIntValueIsValidForSize(uval64, item_byte_size)) { + result.AppendErrorWithFormat("Value 0x%" PRIx64 + " is too large to fit in a %" PRIu64 + " byte unsigned integer value.\n", + uval64, (uint64_t)item_byte_size); + result.SetStatus(eReturnStatusFailed); + return false; + } + buffer.PutMaxHex64(uval64, item_byte_size); + break; + + case eFormatCharArray: + case eFormatChar: + case eFormatCString: + if (value_str[0]) { + size_t len = strlen(value_str); + // Include the NULL for C strings... + if (m_format_options.GetFormat() == eFormatCString) + ++len; + Error error; + if (process->WriteMemory(addr, value_str, len, error) == len) { + addr += len; + } else { + result.AppendErrorWithFormat("Memory write to 0x%" PRIx64 + " failed: %s.\n", + addr, error.AsCString()); result.SetStatus(eReturnStatusFailed); return false; + } } - - if (m_memory_options.m_infile) - { - size_t length = SIZE_MAX; - if (item_byte_size > 1) - length = item_byte_size; - lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length)); - if (data_sp) - { - length = data_sp->GetByteSize(); - if (length > 0) - { - Error error; - size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error); - - if (bytes_written == length) - { - // All bytes written - result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr); - result.SetStatus(eReturnStatusSuccessFinishResult); - } - else if (bytes_written > 0) - { - // Some byte written - result.GetOutputStream().Printf("%" PRIu64 " bytes of %" PRIu64 " requested were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, (uint64_t)length, addr); - result.SetStatus(eReturnStatusSuccessFinishResult); - } - else - { - result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); - result.SetStatus(eReturnStatusFailed); - } - } - } - else - { - result.AppendErrorWithFormat ("Unable to read contents of file.\n"); - result.SetStatus(eReturnStatusFailed); - } - return result.Succeeded(); + break; + + case eFormatDecimal: + sval64 = StringConvert::ToSInt64(value_str, INT64_MAX, 0, &success); + if (!success) { + result.AppendErrorWithFormat( + "'%s' is not a valid signed decimal value.\n", value_str); + result.SetStatus(eReturnStatusFailed); + return false; + } else if (!SIntValueIsValidForSize(sval64, item_byte_size)) { + result.AppendErrorWithFormat( + "Value %" PRIi64 " is too large or small to fit in a %" PRIu64 + " byte signed integer value.\n", + sval64, (uint64_t)item_byte_size); + result.SetStatus(eReturnStatusFailed); + return false; } - else if (item_byte_size == 0) - { - if (m_format_options.GetFormat() == eFormatPointer) - item_byte_size = buffer.GetAddressByteSize(); - else - item_byte_size = 1; + buffer.PutMaxHex64(sval64, item_byte_size); + break; + + case eFormatUnsigned: + uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 0, &success); + if (!success) { + result.AppendErrorWithFormat( + "'%s' is not a valid unsigned decimal string value.\n", + value_str); + result.SetStatus(eReturnStatusFailed); + return false; + } else if (!UIntValueIsValidForSize(uval64, item_byte_size)) { + result.AppendErrorWithFormat("Value %" PRIu64 + " is too large to fit in a %" PRIu64 + " byte unsigned integer value.\n", + uval64, (uint64_t)item_byte_size); + result.SetStatus(eReturnStatusFailed); + return false; } - - command.Shift(); // shift off the address argument - uint64_t uval64; - int64_t sval64; - bool success = false; - const size_t num_value_args = command.GetArgumentCount(); - for (size_t i=0; i<num_value_args; ++i) - { - const char *value_str = command.GetArgumentAtIndex(i); - - switch (m_format_options.GetFormat()) - { - case kNumFormats: - case eFormatFloat: // TODO: add support for floats soon - case eFormatCharPrintable: - case eFormatBytesWithASCII: - case eFormatComplex: - case eFormatEnum: - case eFormatUnicode16: - case eFormatUnicode32: - case eFormatVectorOfChar: - case eFormatVectorOfSInt8: - case eFormatVectorOfUInt8: - case eFormatVectorOfSInt16: - case eFormatVectorOfUInt16: - case eFormatVectorOfSInt32: - case eFormatVectorOfUInt32: - case eFormatVectorOfSInt64: - case eFormatVectorOfUInt64: - case eFormatVectorOfFloat16: - case eFormatVectorOfFloat32: - case eFormatVectorOfFloat64: - case eFormatVectorOfUInt128: - case eFormatOSType: - case eFormatComplexInteger: - case eFormatAddressInfo: - case eFormatHexFloat: - case eFormatInstruction: - case eFormatVoid: - result.AppendError("unsupported format for writing memory"); - result.SetStatus(eReturnStatusFailed); - return false; - - case eFormatDefault: - case eFormatBytes: - case eFormatHex: - case eFormatHexUppercase: - case eFormatPointer: - // Decode hex bytes - uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 16, &success); - if (!success) - { - result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str); - result.SetStatus(eReturnStatusFailed); - return false; - } - else if (!UIntValueIsValidForSize (uval64, item_byte_size)) - { - result.AppendErrorWithFormat("Value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size); - result.SetStatus(eReturnStatusFailed); - return false; - } - buffer.PutMaxHex64 (uval64, item_byte_size); - break; - - case eFormatBoolean: - uval64 = Args::StringToBoolean(value_str, false, &success); - if (!success) - { - result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str); - result.SetStatus(eReturnStatusFailed); - return false; - } - buffer.PutMaxHex64 (uval64, item_byte_size); - break; - - case eFormatBinary: - uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 2, &success); - if (!success) - { - result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str); - result.SetStatus(eReturnStatusFailed); - return false; - } - else if (!UIntValueIsValidForSize (uval64, item_byte_size)) - { - result.AppendErrorWithFormat("Value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size); - result.SetStatus(eReturnStatusFailed); - return false; - } - buffer.PutMaxHex64 (uval64, item_byte_size); - break; - - case eFormatCharArray: - case eFormatChar: - case eFormatCString: - if (value_str[0]) - { - size_t len = strlen (value_str); - // Include the NULL for C strings... - if (m_format_options.GetFormat() == eFormatCString) - ++len; - Error error; - if (process->WriteMemory (addr, value_str, len, error) == len) - { - addr += len; - } - else - { - result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - break; - - case eFormatDecimal: - sval64 = StringConvert::ToSInt64(value_str, INT64_MAX, 0, &success); - if (!success) - { - result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str); - result.SetStatus(eReturnStatusFailed); - return false; - } - else if (!SIntValueIsValidForSize (sval64, item_byte_size)) - { - result.AppendErrorWithFormat ("Value %" PRIi64 " is too large or small to fit in a %" PRIu64 " byte signed integer value.\n", sval64, (uint64_t)item_byte_size); - result.SetStatus(eReturnStatusFailed); - return false; - } - buffer.PutMaxHex64 (sval64, item_byte_size); - break; - - case eFormatUnsigned: - uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 0, &success); - if (!success) - { - result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str); - result.SetStatus(eReturnStatusFailed); - return false; - } - else if (!UIntValueIsValidForSize (uval64, item_byte_size)) - { - result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size); - result.SetStatus(eReturnStatusFailed); - return false; - } - buffer.PutMaxHex64 (uval64, item_byte_size); - break; - - case eFormatOctal: - uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 8, &success); - if (!success) - { - result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str); - result.SetStatus(eReturnStatusFailed); - return false; - } - else if (!UIntValueIsValidForSize (uval64, item_byte_size)) - { - result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size); - result.SetStatus(eReturnStatusFailed); - return false; - } - buffer.PutMaxHex64 (uval64, item_byte_size); - break; - } + buffer.PutMaxHex64(uval64, item_byte_size); + break; + + case eFormatOctal: + uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 8, &success); + if (!success) { + result.AppendErrorWithFormat( + "'%s' is not a valid octal string value.\n", value_str); + result.SetStatus(eReturnStatusFailed); + return false; + } else if (!UIntValueIsValidForSize(uval64, item_byte_size)) { + result.AppendErrorWithFormat("Value %" PRIo64 + " is too large to fit in a %" PRIu64 + " byte unsigned integer value.\n", + uval64, (uint64_t)item_byte_size); + result.SetStatus(eReturnStatusFailed); + return false; } + buffer.PutMaxHex64(uval64, item_byte_size); + break; + } + } - if (!buffer.GetString().empty()) - { - Error error; - if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size()) - return true; - else - { - result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); - result.SetStatus(eReturnStatusFailed); - return false; - } - } + if (!buffer.GetString().empty()) { + Error error; + if (process->WriteMemory(addr, buffer.GetString().c_str(), + buffer.GetString().size(), + error) == buffer.GetString().size()) return true; + else { + result.AppendErrorWithFormat("Memory write to 0x%" PRIx64 + " failed: %s.\n", + addr, error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } } + return true; + } - OptionGroupOptions m_option_group; - OptionGroupFormat m_format_options; - OptionGroupWriteMemory m_memory_options; + OptionGroupOptions m_option_group; + OptionGroupFormat m_format_options; + OptionGroupWriteMemory m_memory_options; }; //---------------------------------------------------------------------- // Get malloc/free history of a memory address. //---------------------------------------------------------------------- -class CommandObjectMemoryHistory : public CommandObjectParsed -{ +class CommandObjectMemoryHistory : public CommandObjectParsed { public: - CommandObjectMemoryHistory(CommandInterpreter &interpreter) - : CommandObjectParsed( - interpreter, "memory history", - "Print recorded stack traces for allocation/deallocation events associated with an address.", nullptr, - eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBePaused | - eCommandProcessMustBeLaunched) - { - CommandArgumentEntry arg1; - CommandArgumentData addr_arg; - - // Define the first (and only) variant of this arg. - addr_arg.arg_type = eArgTypeAddress; - addr_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg1.push_back (addr_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg1); + CommandObjectMemoryHistory(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "memory history", "Print recorded stack traces for " + "allocation/deallocation events " + "associated with an address.", + nullptr, + eCommandRequiresTarget | eCommandRequiresProcess | + eCommandProcessMustBePaused | eCommandProcessMustBeLaunched) { + CommandArgumentEntry arg1; + CommandArgumentData addr_arg; + + // Define the first (and only) variant of this arg. + addr_arg.arg_type = eArgTypeAddress; + addr_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg1.push_back(addr_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg1); + } + + ~CommandObjectMemoryHistory() override = default; + + const char *GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override { + return m_cmd_name.c_str(); + } + +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + const size_t argc = command.GetArgumentCount(); + + if (argc == 0 || argc > 1) { + result.AppendErrorWithFormat("%s takes an address expression", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; } - ~CommandObjectMemoryHistory() override = default; + Error error; + lldb::addr_t addr = + Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), + LLDB_INVALID_ADDRESS, &error); - const char * - GetRepeatCommand (Args ¤t_command_args, uint32_t index) override - { - return m_cmd_name.c_str(); + if (addr == LLDB_INVALID_ADDRESS) { + result.AppendError("invalid address expression"); + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; } - -protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - const size_t argc = command.GetArgumentCount(); - - if (argc == 0 || argc > 1) - { - result.AppendErrorWithFormat ("%s takes an address expression", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - Error error; - lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx, - command.GetArgumentAtIndex(0), - LLDB_INVALID_ADDRESS, - &error); - - if (addr == LLDB_INVALID_ADDRESS) - { - result.AppendError("invalid address expression"); - result.AppendError(error.AsCString()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - Stream *output_stream = &result.GetOutputStream(); - - const ProcessSP &process_sp = m_exe_ctx.GetProcessSP(); - const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(process_sp); - - if (!memory_history) - { - result.AppendError("no available memory history provider"); - result.SetStatus(eReturnStatusFailed); - return false; - } - - HistoryThreads thread_list = memory_history->GetHistoryThreads(addr); - - for (auto thread : thread_list) { - thread->GetStatus(*output_stream, 0, UINT32_MAX, 0); - } - - result.SetStatus(eReturnStatusSuccessFinishResult); - - return true; + + Stream *output_stream = &result.GetOutputStream(); + + const ProcessSP &process_sp = m_exe_ctx.GetProcessSP(); + const MemoryHistorySP &memory_history = + MemoryHistory::FindPlugin(process_sp); + + if (!memory_history) { + result.AppendError("no available memory history provider"); + result.SetStatus(eReturnStatusFailed); + return false; } + + HistoryThreads thread_list = memory_history->GetHistoryThreads(addr); + + for (auto thread : thread_list) { + thread->GetStatus(*output_stream, 0, UINT32_MAX, 0); + } + + result.SetStatus(eReturnStatusSuccessFinishResult); + + return true; + } }; //------------------------------------------------------------------------- @@ -1827,102 +1693,90 @@ protected: //------------------------------------------------------------------------- #pragma mark CommandObjectMemoryRegion -class CommandObjectMemoryRegion : public CommandObjectParsed -{ +class CommandObjectMemoryRegion : public CommandObjectParsed { public: - CommandObjectMemoryRegion(CommandInterpreter &interpreter) - : CommandObjectParsed( - interpreter, "memory region", - "Get information on the memory region containing an address in the current target process.", - "memory region ADDR", eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched), - m_prev_end_addr(LLDB_INVALID_ADDRESS) - { - } + CommandObjectMemoryRegion(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "memory region", + "Get information on the memory region containing " + "an address in the current target process.", + "memory region ADDR", + eCommandRequiresProcess | eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched), + m_prev_end_addr(LLDB_INVALID_ADDRESS) {} - ~CommandObjectMemoryRegion() override = default; + ~CommandObjectMemoryRegion() override = default; protected: - bool - DoExecute(Args &command, CommandReturnObject &result) override - { - ProcessSP process_sp = m_exe_ctx.GetProcessSP(); - if (process_sp) - { - Error error; - lldb::addr_t load_addr = m_prev_end_addr; - m_prev_end_addr = LLDB_INVALID_ADDRESS; - - const size_t argc = command.GetArgumentCount(); - if (argc > 1 || (argc == 0 && load_addr == LLDB_INVALID_ADDRESS)) - { - result.AppendErrorWithFormat("'%s' takes one argument:\nUsage: %s\n", m_cmd_name.c_str(), - m_cmd_syntax.c_str()); - result.SetStatus(eReturnStatusFailed); - } - else - { - const char *load_addr_cstr = command.GetArgumentAtIndex(0); - if (command.GetArgumentCount() == 1) - { - load_addr = Args::StringToAddress(&m_exe_ctx, load_addr_cstr, LLDB_INVALID_ADDRESS, &error); - if (error.Fail() || load_addr == LLDB_INVALID_ADDRESS) - { - result.AppendErrorWithFormat("invalid address argument \"%s\": %s\n", load_addr_cstr, - error.AsCString()); - result.SetStatus(eReturnStatusFailed); - } - } - - lldb_private::MemoryRegionInfo range_info; - error = process_sp->GetMemoryRegionInfo(load_addr, range_info); - if (error.Success()) - { - lldb_private::Address addr; - ConstString section_name; - if (process_sp->GetTarget().ResolveLoadAddress(load_addr, addr)) - { - SectionSP section_sp(addr.GetSection()); - if (section_sp) - { - // Got the top most section, not the deepest section - while (section_sp->GetParent()) - section_sp = section_sp->GetParent(); - section_name = section_sp->GetName(); - } - } - result.AppendMessageWithFormat( - "[0x%16.16" PRIx64 "-0x%16.16" PRIx64 ") %c%c%c%s%s\n", range_info.GetRange().GetRangeBase(), - range_info.GetRange().GetRangeEnd(), range_info.GetReadable() ? 'r' : '-', - range_info.GetWritable() ? 'w' : '-', range_info.GetExecutable() ? 'x' : '-', - section_name ? " " : "", section_name ? section_name.AsCString() : ""); - m_prev_end_addr = range_info.GetRange().GetRangeEnd(); - result.SetStatus(eReturnStatusSuccessFinishResult); - } - else - { - result.SetStatus(eReturnStatusFailed); - result.AppendErrorWithFormat("%s\n", error.AsCString()); - } - } - } - else - { - m_prev_end_addr = LLDB_INVALID_ADDRESS; - result.AppendError("invalid process"); + bool DoExecute(Args &command, CommandReturnObject &result) override { + ProcessSP process_sp = m_exe_ctx.GetProcessSP(); + if (process_sp) { + Error error; + lldb::addr_t load_addr = m_prev_end_addr; + m_prev_end_addr = LLDB_INVALID_ADDRESS; + + const size_t argc = command.GetArgumentCount(); + if (argc > 1 || (argc == 0 && load_addr == LLDB_INVALID_ADDRESS)) { + result.AppendErrorWithFormat("'%s' takes one argument:\nUsage: %s\n", + m_cmd_name.c_str(), m_cmd_syntax.c_str()); + result.SetStatus(eReturnStatusFailed); + } else { + const char *load_addr_cstr = command.GetArgumentAtIndex(0); + if (command.GetArgumentCount() == 1) { + load_addr = Args::StringToAddress(&m_exe_ctx, load_addr_cstr, + LLDB_INVALID_ADDRESS, &error); + if (error.Fail() || load_addr == LLDB_INVALID_ADDRESS) { + result.AppendErrorWithFormat( + "invalid address argument \"%s\": %s\n", load_addr_cstr, + error.AsCString()); result.SetStatus(eReturnStatusFailed); + } } - return result.Succeeded(); - } - const char * - GetRepeatCommand(Args ¤t_command_args, uint32_t index) override - { - // If we repeat this command, repeat it without any arguments so we can - // show the next memory range - return m_cmd_name.c_str(); + lldb_private::MemoryRegionInfo range_info; + error = process_sp->GetMemoryRegionInfo(load_addr, range_info); + if (error.Success()) { + lldb_private::Address addr; + ConstString section_name; + if (process_sp->GetTarget().ResolveLoadAddress(load_addr, addr)) { + SectionSP section_sp(addr.GetSection()); + if (section_sp) { + // Got the top most section, not the deepest section + while (section_sp->GetParent()) + section_sp = section_sp->GetParent(); + section_name = section_sp->GetName(); + } + } + result.AppendMessageWithFormat( + "[0x%16.16" PRIx64 "-0x%16.16" PRIx64 ") %c%c%c%s%s\n", + range_info.GetRange().GetRangeBase(), + range_info.GetRange().GetRangeEnd(), + range_info.GetReadable() ? 'r' : '-', + range_info.GetWritable() ? 'w' : '-', + range_info.GetExecutable() ? 'x' : '-', section_name ? " " : "", + section_name ? section_name.AsCString() : ""); + m_prev_end_addr = range_info.GetRange().GetRangeEnd(); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.SetStatus(eReturnStatusFailed); + result.AppendErrorWithFormat("%s\n", error.AsCString()); + } + } + } else { + m_prev_end_addr = LLDB_INVALID_ADDRESS; + result.AppendError("invalid process"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } + + const char *GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override { + // If we repeat this command, repeat it without any arguments so we can + // show the next memory range + return m_cmd_name.c_str(); + } - lldb::addr_t m_prev_end_addr; + lldb::addr_t m_prev_end_addr; }; //------------------------------------------------------------------------- @@ -1930,14 +1784,20 @@ protected: //------------------------------------------------------------------------- CommandObjectMemory::CommandObjectMemory(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "memory", "Commands for operating on memory in the current target process.", - "memory <subcommand> [<subcommand-options>]") -{ - LoadSubCommand("find", CommandObjectSP(new CommandObjectMemoryFind(interpreter))); - LoadSubCommand("read", CommandObjectSP(new CommandObjectMemoryRead(interpreter))); - LoadSubCommand("write", CommandObjectSP(new CommandObjectMemoryWrite(interpreter))); - LoadSubCommand("history", CommandObjectSP(new CommandObjectMemoryHistory(interpreter))); - LoadSubCommand("region", CommandObjectSP(new CommandObjectMemoryRegion(interpreter))); + : CommandObjectMultiword( + interpreter, "memory", + "Commands for operating on memory in the current target process.", + "memory <subcommand> [<subcommand-options>]") { + LoadSubCommand("find", + CommandObjectSP(new CommandObjectMemoryFind(interpreter))); + LoadSubCommand("read", + CommandObjectSP(new CommandObjectMemoryRead(interpreter))); + LoadSubCommand("write", + CommandObjectSP(new CommandObjectMemoryWrite(interpreter))); + LoadSubCommand("history", + CommandObjectSP(new CommandObjectMemoryHistory(interpreter))); + LoadSubCommand("region", + CommandObjectSP(new CommandObjectMemoryRegion(interpreter))); } CommandObjectMemory::~CommandObjectMemory() = default; diff --git a/lldb/source/Commands/CommandObjectMemory.h b/lldb/source/Commands/CommandObjectMemory.h index cf5b441..9f3978b 100644 --- a/lldb/source/Commands/CommandObjectMemory.h +++ b/lldb/source/Commands/CommandObjectMemory.h @@ -18,12 +18,11 @@ namespace lldb_private { -class CommandObjectMemory : public CommandObjectMultiword -{ +class CommandObjectMemory : public CommandObjectMultiword { public: - CommandObjectMemory (CommandInterpreter &interpreter); + CommandObjectMemory(CommandInterpreter &interpreter); - ~CommandObjectMemory() override; + ~CommandObjectMemory() override; }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectMultiword.cpp b/lldb/source/Commands/CommandObjectMultiword.cpp index c951e0b..dd60af0f 100644 --- a/lldb/source/Commands/CommandObjectMultiword.cpp +++ b/lldb/source/Commands/CommandObjectMultiword.cpp @@ -14,8 +14,8 @@ #include "lldb/Interpreter/CommandObjectMultiword.h" #include "lldb/Core/Debugger.h" #include "lldb/Interpreter/CommandInterpreter.h" -#include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Interpreter/Options.h" using namespace lldb; using namespace lldb_private; @@ -28,496 +28,388 @@ CommandObjectMultiword::CommandObjectMultiword(CommandInterpreter &interpreter, const char *name, const char *help, const char *syntax, - uint32_t flags) : - CommandObject (interpreter, name, help, syntax, flags), - m_can_be_removed(false) -{ -} + uint32_t flags) + : CommandObject(interpreter, name, help, syntax, flags), + m_can_be_removed(false) {} CommandObjectMultiword::~CommandObjectMultiword() = default; -CommandObjectSP -CommandObjectMultiword::GetSubcommandSP (const char *sub_cmd, StringList *matches) -{ - CommandObjectSP return_cmd_sp; - CommandObject::CommandMap::iterator pos; - - if (!m_subcommand_dict.empty()) - { - pos = m_subcommand_dict.find (sub_cmd); - if (pos != m_subcommand_dict.end()) { - // An exact match; append the sub_cmd to the 'matches' string list. - if (matches) - matches->AppendString(sub_cmd); - return_cmd_sp = pos->second; - } - else - { - StringList local_matches; - if (matches == nullptr) - matches = &local_matches; - int num_matches = AddNamesMatchingPartialString (m_subcommand_dict, sub_cmd, *matches); - - if (num_matches == 1) - { - // Cleaner, but slightly less efficient would be to call back into this function, since I now - // know I have an exact match... - - sub_cmd = matches->GetStringAtIndex(0); - pos = m_subcommand_dict.find(sub_cmd); - if (pos != m_subcommand_dict.end()) - return_cmd_sp = pos->second; - } - } +CommandObjectSP CommandObjectMultiword::GetSubcommandSP(const char *sub_cmd, + StringList *matches) { + CommandObjectSP return_cmd_sp; + CommandObject::CommandMap::iterator pos; + + if (!m_subcommand_dict.empty()) { + pos = m_subcommand_dict.find(sub_cmd); + if (pos != m_subcommand_dict.end()) { + // An exact match; append the sub_cmd to the 'matches' string list. + if (matches) + matches->AppendString(sub_cmd); + return_cmd_sp = pos->second; + } else { + StringList local_matches; + if (matches == nullptr) + matches = &local_matches; + int num_matches = + AddNamesMatchingPartialString(m_subcommand_dict, sub_cmd, *matches); + + if (num_matches == 1) { + // Cleaner, but slightly less efficient would be to call back into this + // function, since I now + // know I have an exact match... + + sub_cmd = matches->GetStringAtIndex(0); + pos = m_subcommand_dict.find(sub_cmd); + if (pos != m_subcommand_dict.end()) + return_cmd_sp = pos->second; + } } - return return_cmd_sp; + } + return return_cmd_sp; } CommandObject * -CommandObjectMultiword::GetSubcommandObject (const char *sub_cmd, StringList *matches) -{ - return GetSubcommandSP(sub_cmd, matches).get(); +CommandObjectMultiword::GetSubcommandObject(const char *sub_cmd, + StringList *matches) { + return GetSubcommandSP(sub_cmd, matches).get(); } -bool -CommandObjectMultiword::LoadSubCommand(const char *name, - const CommandObjectSP& cmd_obj) -{ - if (cmd_obj) - assert((&GetCommandInterpreter() == &cmd_obj->GetCommandInterpreter()) && "tried to add a CommandObject from a different interpreter"); - - CommandMap::iterator pos; - bool success = true; - - pos = m_subcommand_dict.find(name); - if (pos == m_subcommand_dict.end()) - { - m_subcommand_dict[name] = cmd_obj; - } - else - success = false; +bool CommandObjectMultiword::LoadSubCommand(const char *name, + const CommandObjectSP &cmd_obj) { + if (cmd_obj) + assert((&GetCommandInterpreter() == &cmd_obj->GetCommandInterpreter()) && + "tried to add a CommandObject from a different interpreter"); + + CommandMap::iterator pos; + bool success = true; + + pos = m_subcommand_dict.find(name); + if (pos == m_subcommand_dict.end()) { + m_subcommand_dict[name] = cmd_obj; + } else + success = false; - return success; + return success; } -bool -CommandObjectMultiword::Execute(const char *args_string, CommandReturnObject &result) -{ - Args args (args_string); - const size_t argc = args.GetArgumentCount(); - if (argc == 0) - { - this->CommandObject::GenerateHelpText (result); - } - else - { - const char *sub_command = args.GetArgumentAtIndex (0); - - if (sub_command) - { - if (::strcasecmp (sub_command, "help") == 0) - { - this->CommandObject::GenerateHelpText (result); - } - else if (!m_subcommand_dict.empty()) - { - StringList matches; - CommandObject *sub_cmd_obj = GetSubcommandObject(sub_command, &matches); - if (sub_cmd_obj != nullptr) - { - // Now call CommandObject::Execute to process and options in 'rest_of_line'. From there - // the command-specific version of Execute will be called, with the processed arguments. - - args.Shift(); - - sub_cmd_obj->Execute (args_string, result); - } - else - { - std::string error_msg; - const size_t num_subcmd_matches = matches.GetSize(); - if (num_subcmd_matches > 0) - error_msg.assign ("ambiguous command "); - else - error_msg.assign ("invalid command "); - - error_msg.append ("'"); - error_msg.append (GetCommandName()); - error_msg.append (" "); - error_msg.append (sub_command); - error_msg.append ("'."); - - if (num_subcmd_matches > 0) - { - error_msg.append (" Possible completions:"); - for (size_t i = 0; i < num_subcmd_matches; i++) - { - error_msg.append ("\n\t"); - error_msg.append (matches.GetStringAtIndex (i)); - } - } - error_msg.append ("\n"); - result.AppendRawError (error_msg.c_str()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendErrorWithFormat ("'%s' does not have any subcommands.\n", GetCommandName()); - result.SetStatus (eReturnStatusFailed); +bool CommandObjectMultiword::Execute(const char *args_string, + CommandReturnObject &result) { + Args args(args_string); + const size_t argc = args.GetArgumentCount(); + if (argc == 0) { + this->CommandObject::GenerateHelpText(result); + } else { + const char *sub_command = args.GetArgumentAtIndex(0); + + if (sub_command) { + if (::strcasecmp(sub_command, "help") == 0) { + this->CommandObject::GenerateHelpText(result); + } else if (!m_subcommand_dict.empty()) { + StringList matches; + CommandObject *sub_cmd_obj = GetSubcommandObject(sub_command, &matches); + if (sub_cmd_obj != nullptr) { + // Now call CommandObject::Execute to process and options in + // 'rest_of_line'. From there + // the command-specific version of Execute will be called, with the + // processed arguments. + + args.Shift(); + + sub_cmd_obj->Execute(args_string, result); + } else { + std::string error_msg; + const size_t num_subcmd_matches = matches.GetSize(); + if (num_subcmd_matches > 0) + error_msg.assign("ambiguous command "); + else + error_msg.assign("invalid command "); + + error_msg.append("'"); + error_msg.append(GetCommandName()); + error_msg.append(" "); + error_msg.append(sub_command); + error_msg.append("'."); + + if (num_subcmd_matches > 0) { + error_msg.append(" Possible completions:"); + for (size_t i = 0; i < num_subcmd_matches; i++) { + error_msg.append("\n\t"); + error_msg.append(matches.GetStringAtIndex(i)); } + } + error_msg.append("\n"); + result.AppendRawError(error_msg.c_str()); + result.SetStatus(eReturnStatusFailed); } + } else { + result.AppendErrorWithFormat("'%s' does not have any subcommands.\n", + GetCommandName()); + result.SetStatus(eReturnStatusFailed); + } } + } - return result.Succeeded(); + return result.Succeeded(); } -void -CommandObjectMultiword::GenerateHelpText (Stream &output_stream) -{ - // First time through here, generate the help text for the object and - // push it to the return result object as well - - CommandObject::GenerateHelpText(output_stream); - output_stream.PutCString("\nThe following subcommands are supported:\n\n"); - - CommandMap::iterator pos; - uint32_t max_len = FindLongestCommandWord (m_subcommand_dict); - - if (max_len) - max_len += 4; // Indent the output by 4 spaces. - - for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos) - { - std::string indented_command (" "); - indented_command.append (pos->first); - if (pos->second->WantsRawCommandString ()) - { - std::string help_text (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); - } - else - m_interpreter.OutputFormattedHelpText (output_stream, - indented_command.c_str(), - "--", - pos->second->GetHelp(), - max_len); - } - - output_stream.PutCString ("\nFor more help on any particular subcommand, type 'help <command> <subcommand>'.\n"); +void CommandObjectMultiword::GenerateHelpText(Stream &output_stream) { + // First time through here, generate the help text for the object and + // push it to the return result object as well + + CommandObject::GenerateHelpText(output_stream); + output_stream.PutCString("\nThe following subcommands are supported:\n\n"); + + CommandMap::iterator pos; + uint32_t max_len = FindLongestCommandWord(m_subcommand_dict); + + if (max_len) + max_len += 4; // Indent the output by 4 spaces. + + for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos) { + std::string indented_command(" "); + indented_command.append(pos->first); + if (pos->second->WantsRawCommandString()) { + std::string help_text(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); + } else + m_interpreter.OutputFormattedHelpText(output_stream, + indented_command.c_str(), "--", + pos->second->GetHelp(), max_len); + } + + output_stream.PutCString("\nFor more help on any particular subcommand, type " + "'help <command> <subcommand>'.\n"); } -int -CommandObjectMultiword::HandleCompletion(Args &input, - int &cursor_index, - int &cursor_char_position, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) -{ - // Any of the command matches will provide a complete word, otherwise the individual - // completers will override this. - word_complete = true; - - const char *arg0 = input.GetArgumentAtIndex(0); - if (cursor_index == 0) - { - AddNamesMatchingPartialString (m_subcommand_dict, - arg0, - matches); - - if (matches.GetSize() == 1 - && matches.GetStringAtIndex(0) != nullptr - && strcmp (arg0, matches.GetStringAtIndex(0)) == 0) - { - StringList temp_matches; - CommandObject *cmd_obj = GetSubcommandObject (arg0, - &temp_matches); - if (cmd_obj != nullptr) - { - if (input.GetArgumentCount() == 1) - { - word_complete = true; - } - else - { - matches.DeleteStringAtIndex (0); - input.Shift(); - cursor_char_position = 0; - input.AppendArgument (""); - return cmd_obj->HandleCompletion (input, - cursor_index, - cursor_char_position, - match_start_point, - max_return_elements, - word_complete, - matches); - } - } +int CommandObjectMultiword::HandleCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) { + // Any of the command matches will provide a complete word, otherwise the + // individual + // completers will override this. + word_complete = true; + + const char *arg0 = input.GetArgumentAtIndex(0); + if (cursor_index == 0) { + AddNamesMatchingPartialString(m_subcommand_dict, arg0, matches); + + if (matches.GetSize() == 1 && matches.GetStringAtIndex(0) != nullptr && + strcmp(arg0, matches.GetStringAtIndex(0)) == 0) { + StringList temp_matches; + CommandObject *cmd_obj = GetSubcommandObject(arg0, &temp_matches); + if (cmd_obj != nullptr) { + if (input.GetArgumentCount() == 1) { + word_complete = true; + } else { + matches.DeleteStringAtIndex(0); + input.Shift(); + cursor_char_position = 0; + input.AppendArgument(""); + return cmd_obj->HandleCompletion( + input, cursor_index, cursor_char_position, match_start_point, + max_return_elements, word_complete, matches); } - return matches.GetSize(); + } } - else - { - CommandObject *sub_command_object = GetSubcommandObject (arg0, - &matches); - if (sub_command_object == nullptr) - { - return matches.GetSize(); - } - else - { - // Remove the one match that we got from calling GetSubcommandObject. - matches.DeleteStringAtIndex(0); - input.Shift(); - cursor_index--; - return sub_command_object->HandleCompletion (input, - cursor_index, - cursor_char_position, - match_start_point, - max_return_elements, - word_complete, - matches); - } + return matches.GetSize(); + } else { + CommandObject *sub_command_object = GetSubcommandObject(arg0, &matches); + if (sub_command_object == nullptr) { + return matches.GetSize(); + } else { + // Remove the one match that we got from calling GetSubcommandObject. + matches.DeleteStringAtIndex(0); + input.Shift(); + cursor_index--; + return sub_command_object->HandleCompletion( + input, cursor_index, cursor_char_position, match_start_point, + max_return_elements, word_complete, matches); } + } } -const char * -CommandObjectMultiword::GetRepeatCommand (Args ¤t_command_args, uint32_t index) -{ - index++; - if (current_command_args.GetArgumentCount() <= index) - return nullptr; - CommandObject *sub_command_object = GetSubcommandObject (current_command_args.GetArgumentAtIndex(index)); - if (sub_command_object == nullptr) - return nullptr; - return sub_command_object->GetRepeatCommand(current_command_args, index); +const char *CommandObjectMultiword::GetRepeatCommand(Args ¤t_command_args, + uint32_t index) { + index++; + if (current_command_args.GetArgumentCount() <= index) + return nullptr; + CommandObject *sub_command_object = + GetSubcommandObject(current_command_args.GetArgumentAtIndex(index)); + if (sub_command_object == nullptr) + return nullptr; + return sub_command_object->GetRepeatCommand(current_command_args, index); } -void -CommandObjectMultiword::AproposAllSubCommands (const char *prefix, - const char *search_word, - StringList &commands_found, - StringList &commands_help) -{ - CommandObject::CommandMap::const_iterator pos; - - for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos) - { - const char * command_name = pos->first.c_str(); - CommandObject *sub_cmd_obj = pos->second.get(); - StreamString complete_command_name; - - complete_command_name.Printf ("%s %s", prefix, command_name); - - if (sub_cmd_obj->HelpTextContainsWord (search_word)) - { - commands_found.AppendString (complete_command_name.GetData()); - commands_help.AppendString (sub_cmd_obj->GetHelp()); - } - - if (sub_cmd_obj->IsMultiwordObject()) - sub_cmd_obj->AproposAllSubCommands (complete_command_name.GetData(), - search_word, - commands_found, - commands_help); +void CommandObjectMultiword::AproposAllSubCommands(const char *prefix, + const char *search_word, + StringList &commands_found, + StringList &commands_help) { + CommandObject::CommandMap::const_iterator pos; + + for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos) { + const char *command_name = pos->first.c_str(); + CommandObject *sub_cmd_obj = pos->second.get(); + StreamString complete_command_name; + + complete_command_name.Printf("%s %s", prefix, command_name); + + if (sub_cmd_obj->HelpTextContainsWord(search_word)) { + commands_found.AppendString(complete_command_name.GetData()); + commands_help.AppendString(sub_cmd_obj->GetHelp()); } -} -CommandObjectProxy::CommandObjectProxy (CommandInterpreter &interpreter, - const char *name, - const char *help, - const char *syntax, - uint32_t flags) : - CommandObject (interpreter, name, help, syntax, flags) -{ + if (sub_cmd_obj->IsMultiwordObject()) + sub_cmd_obj->AproposAllSubCommands(complete_command_name.GetData(), + search_word, commands_found, + commands_help); + } } +CommandObjectProxy::CommandObjectProxy(CommandInterpreter &interpreter, + const char *name, const char *help, + const char *syntax, uint32_t flags) + : CommandObject(interpreter, name, help, syntax, flags) {} + CommandObjectProxy::~CommandObjectProxy() = default; -const char * -CommandObjectProxy::GetHelpLong () -{ - CommandObject *proxy_command = GetProxyCommandObject(); - if (proxy_command) - return proxy_command->GetHelpLong(); - return nullptr; +const char *CommandObjectProxy::GetHelpLong() { + CommandObject *proxy_command = GetProxyCommandObject(); + if (proxy_command) + return proxy_command->GetHelpLong(); + return nullptr; } -bool -CommandObjectProxy::IsRemovable() const -{ - const CommandObject *proxy_command = const_cast<CommandObjectProxy *>(this)->GetProxyCommandObject(); - if (proxy_command) - return proxy_command->IsRemovable(); - return false; +bool CommandObjectProxy::IsRemovable() const { + const CommandObject *proxy_command = + const_cast<CommandObjectProxy *>(this)->GetProxyCommandObject(); + if (proxy_command) + return proxy_command->IsRemovable(); + return false; } -bool -CommandObjectProxy::IsMultiwordObject () -{ - CommandObject *proxy_command = GetProxyCommandObject(); - if (proxy_command) - return proxy_command->IsMultiwordObject(); - return false; +bool CommandObjectProxy::IsMultiwordObject() { + CommandObject *proxy_command = GetProxyCommandObject(); + if (proxy_command) + return proxy_command->IsMultiwordObject(); + return false; } -CommandObjectMultiword* -CommandObjectProxy::GetAsMultiwordCommand () -{ - CommandObject *proxy_command = GetProxyCommandObject(); - if (proxy_command) - return proxy_command->GetAsMultiwordCommand(); - return nullptr; +CommandObjectMultiword *CommandObjectProxy::GetAsMultiwordCommand() { + CommandObject *proxy_command = GetProxyCommandObject(); + if (proxy_command) + return proxy_command->GetAsMultiwordCommand(); + return nullptr; } -void -CommandObjectProxy::GenerateHelpText (Stream &result) -{ - CommandObject *proxy_command = GetProxyCommandObject(); - if (proxy_command) - return proxy_command->GenerateHelpText(result); +void CommandObjectProxy::GenerateHelpText(Stream &result) { + CommandObject *proxy_command = GetProxyCommandObject(); + if (proxy_command) + return proxy_command->GenerateHelpText(result); } -lldb::CommandObjectSP -CommandObjectProxy::GetSubcommandSP (const char *sub_cmd, StringList *matches) -{ - CommandObject *proxy_command = GetProxyCommandObject(); - if (proxy_command) - return proxy_command->GetSubcommandSP(sub_cmd, matches); - return lldb::CommandObjectSP(); +lldb::CommandObjectSP CommandObjectProxy::GetSubcommandSP(const char *sub_cmd, + StringList *matches) { + CommandObject *proxy_command = GetProxyCommandObject(); + if (proxy_command) + return proxy_command->GetSubcommandSP(sub_cmd, matches); + return lldb::CommandObjectSP(); } -CommandObject * -CommandObjectProxy::GetSubcommandObject (const char *sub_cmd, StringList *matches) -{ - CommandObject *proxy_command = GetProxyCommandObject(); - if (proxy_command) - return proxy_command->GetSubcommandObject(sub_cmd, matches); - return nullptr; +CommandObject *CommandObjectProxy::GetSubcommandObject(const char *sub_cmd, + StringList *matches) { + CommandObject *proxy_command = GetProxyCommandObject(); + if (proxy_command) + return proxy_command->GetSubcommandObject(sub_cmd, matches); + return nullptr; } -void -CommandObjectProxy::AproposAllSubCommands (const char *prefix, - const char *search_word, - StringList &commands_found, - StringList &commands_help) -{ - CommandObject *proxy_command = GetProxyCommandObject(); - if (proxy_command) - return proxy_command->AproposAllSubCommands (prefix, - search_word, - commands_found, - commands_help); +void CommandObjectProxy::AproposAllSubCommands(const char *prefix, + const char *search_word, + StringList &commands_found, + StringList &commands_help) { + CommandObject *proxy_command = GetProxyCommandObject(); + if (proxy_command) + return proxy_command->AproposAllSubCommands(prefix, search_word, + commands_found, commands_help); } -bool -CommandObjectProxy::LoadSubCommand (const char *cmd_name, - const lldb::CommandObjectSP& command_sp) -{ - CommandObject *proxy_command = GetProxyCommandObject(); - if (proxy_command) - return proxy_command->LoadSubCommand (cmd_name, command_sp); - return false; +bool CommandObjectProxy::LoadSubCommand( + const char *cmd_name, const lldb::CommandObjectSP &command_sp) { + CommandObject *proxy_command = GetProxyCommandObject(); + if (proxy_command) + return proxy_command->LoadSubCommand(cmd_name, command_sp); + return false; } -bool -CommandObjectProxy::WantsRawCommandString() -{ - CommandObject *proxy_command = GetProxyCommandObject(); - if (proxy_command) - return proxy_command->WantsRawCommandString(); - return false; +bool CommandObjectProxy::WantsRawCommandString() { + CommandObject *proxy_command = GetProxyCommandObject(); + if (proxy_command) + return proxy_command->WantsRawCommandString(); + return false; } -bool -CommandObjectProxy::WantsCompletion() -{ - CommandObject *proxy_command = GetProxyCommandObject(); - if (proxy_command) - return proxy_command->WantsCompletion(); - return false; +bool CommandObjectProxy::WantsCompletion() { + CommandObject *proxy_command = GetProxyCommandObject(); + if (proxy_command) + return proxy_command->WantsCompletion(); + return false; } -Options * -CommandObjectProxy::GetOptions () -{ - CommandObject *proxy_command = GetProxyCommandObject(); - if (proxy_command) - return proxy_command->GetOptions (); - return nullptr; +Options *CommandObjectProxy::GetOptions() { + CommandObject *proxy_command = GetProxyCommandObject(); + if (proxy_command) + return proxy_command->GetOptions(); + return nullptr; } -int -CommandObjectProxy::HandleCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) -{ - CommandObject *proxy_command = GetProxyCommandObject(); - if (proxy_command) - return proxy_command->HandleCompletion (input, - cursor_index, - cursor_char_position, - match_start_point, - max_return_elements, - word_complete, - matches); - matches.Clear(); - return 0; +int CommandObjectProxy::HandleCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) { + CommandObject *proxy_command = GetProxyCommandObject(); + if (proxy_command) + return proxy_command->HandleCompletion( + input, cursor_index, cursor_char_position, match_start_point, + max_return_elements, word_complete, matches); + matches.Clear(); + return 0; } -int -CommandObjectProxy::HandleArgumentCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - OptionElementVector &opt_element_vector, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) -{ - CommandObject *proxy_command = GetProxyCommandObject(); - if (proxy_command) - return proxy_command->HandleArgumentCompletion (input, - cursor_index, - cursor_char_position, - opt_element_vector, - match_start_point, - max_return_elements, - word_complete, - matches); - matches.Clear(); - return 0; +int CommandObjectProxy::HandleArgumentCompletion( + Args &input, int &cursor_index, int &cursor_char_position, + OptionElementVector &opt_element_vector, int match_start_point, + int max_return_elements, bool &word_complete, StringList &matches) { + CommandObject *proxy_command = GetProxyCommandObject(); + if (proxy_command) + return proxy_command->HandleArgumentCompletion( + input, cursor_index, cursor_char_position, opt_element_vector, + match_start_point, max_return_elements, word_complete, matches); + matches.Clear(); + return 0; } -const char * -CommandObjectProxy::GetRepeatCommand (Args ¤t_command_args, - uint32_t index) -{ - CommandObject *proxy_command = GetProxyCommandObject(); - if (proxy_command) - return proxy_command->GetRepeatCommand (current_command_args, index); - return nullptr; +const char *CommandObjectProxy::GetRepeatCommand(Args ¤t_command_args, + uint32_t index) { + CommandObject *proxy_command = GetProxyCommandObject(); + if (proxy_command) + return proxy_command->GetRepeatCommand(current_command_args, index); + return nullptr; } -bool -CommandObjectProxy::Execute (const char *args_string, - CommandReturnObject &result) -{ - CommandObject *proxy_command = GetProxyCommandObject(); - if (proxy_command) - return proxy_command->Execute (args_string, result); - result.AppendError ("command is not implemented"); - result.SetStatus (eReturnStatusFailed); - return false; +bool CommandObjectProxy::Execute(const char *args_string, + CommandReturnObject &result) { + CommandObject *proxy_command = GetProxyCommandObject(); + if (proxy_command) + return proxy_command->Execute(args_string, result); + result.AppendError("command is not implemented"); + result.SetStatus(eReturnStatusFailed); + return false; } diff --git a/lldb/source/Commands/CommandObjectPlatform.cpp b/lldb/source/Commands/CommandObjectPlatform.cpp index 8cb7c7a2..1a981ce 100644 --- a/lldb/source/Commands/CommandObjectPlatform.cpp +++ b/lldb/source/Commands/CommandObjectPlatform.cpp @@ -32,39 +32,34 @@ using namespace lldb; using namespace lldb_private; -static mode_t -ParsePermissionString(const char* permissions) -{ - if (strlen(permissions) != 9) - return (mode_t)(-1); - bool user_r,user_w,user_x, - group_r,group_w,group_x, - world_r,world_w,world_x; - - user_r = (permissions[0] == 'r'); - user_w = (permissions[1] == 'w'); - user_x = (permissions[2] == 'x'); - - group_r = (permissions[3] == 'r'); - group_w = (permissions[4] == 'w'); - group_x = (permissions[5] == 'x'); - - world_r = (permissions[6] == 'r'); - world_w = (permissions[7] == 'w'); - world_x = (permissions[8] == 'x'); - - mode_t user,group,world; - user = (user_r ? 4 : 0) | (user_w ? 2 : 0) | (user_x ? 1 : 0); - group = (group_r ? 4 : 0) | (group_w ? 2 : 0) | (group_x ? 1 : 0); - world = (world_r ? 4 : 0) | (world_w ? 2 : 0) | (world_x ? 1 : 0); - - return user | group | world; +static mode_t ParsePermissionString(const char *permissions) { + if (strlen(permissions) != 9) + return (mode_t)(-1); + bool user_r, user_w, user_x, group_r, group_w, group_x, world_r, world_w, + world_x; + + user_r = (permissions[0] == 'r'); + user_w = (permissions[1] == 'w'); + user_x = (permissions[2] == 'x'); + + group_r = (permissions[3] == 'r'); + group_w = (permissions[4] == 'w'); + group_x = (permissions[5] == 'x'); + + world_r = (permissions[6] == 'r'); + world_w = (permissions[7] == 'w'); + world_x = (permissions[8] == 'x'); + + mode_t user, group, world; + user = (user_r ? 4 : 0) | (user_w ? 2 : 0) | (user_x ? 1 : 0); + group = (group_r ? 4 : 0) | (group_w ? 2 : 0) | (group_x ? 1 : 0); + world = (world_r ? 4 : 0) | (world_w ? 2 : 0) | (world_x ? 1 : 0); + + return user | group | world; } -static OptionDefinition -g_permissions_options[] = -{ - // clang-format off +static OptionDefinition g_permissions_options[] = { + // clang-format off {LLDB_OPT_SET_ALL, false, "permissions-value", 'v', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePermissionsNumber, "Give out the numeric value for permissions (e.g. 757)"}, {LLDB_OPT_SET_ALL, false, "permissions-string", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePermissionsString, "Give out the string value for permissions (e.g. rwxr-xr--)."}, {LLDB_OPT_SET_ALL, false, "user-read", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow user to read."}, @@ -76,1549 +71,1334 @@ g_permissions_options[] = {LLDB_OPT_SET_ALL, false, "world-read", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow world to read."}, {LLDB_OPT_SET_ALL, false, "world-write", 't', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow world to write."}, {LLDB_OPT_SET_ALL, false, "world-exec", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow world to execute."}, - // clang-format on + // clang-format on }; -class OptionPermissions : public lldb_private::OptionGroup -{ +class OptionPermissions : public lldb_private::OptionGroup { public: - OptionPermissions () - { + OptionPermissions() {} + + ~OptionPermissions() override = default; + + lldb_private::Error + SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + char short_option = (char)GetDefinitions()[option_idx].short_option; + switch (short_option) { + case 'v': { + bool ok; + uint32_t perms = StringConvert::ToUInt32(option_arg, 777, 8, &ok); + if (!ok) + error.SetErrorStringWithFormat("invalid value for permissions: %s", + option_arg); + else + m_permissions = perms; + } break; + case 's': { + mode_t perms = ParsePermissionString(option_arg); + if (perms == (mode_t)-1) + error.SetErrorStringWithFormat("invalid value for permissions: %s", + option_arg); + else + m_permissions = perms; + } break; + case 'r': + m_permissions |= lldb::eFilePermissionsUserRead; + break; + case 'w': + m_permissions |= lldb::eFilePermissionsUserWrite; + break; + case 'x': + m_permissions |= lldb::eFilePermissionsUserExecute; + break; + case 'R': + m_permissions |= lldb::eFilePermissionsGroupRead; + break; + case 'W': + m_permissions |= lldb::eFilePermissionsGroupWrite; + break; + case 'X': + m_permissions |= lldb::eFilePermissionsGroupExecute; + break; + case 'd': + m_permissions |= lldb::eFilePermissionsWorldRead; + break; + case 't': + m_permissions |= lldb::eFilePermissionsWorldWrite; + break; + case 'e': + m_permissions |= lldb::eFilePermissionsWorldExecute; + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); + break; } - ~OptionPermissions() override = default; + return error; + } - lldb_private::Error - SetOptionValue(uint32_t option_idx, - const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - char short_option = (char) GetDefinitions()[option_idx].short_option; - switch (short_option) - { - case 'v': - { - bool ok; - uint32_t perms = StringConvert::ToUInt32(option_arg, 777, 8, &ok); - if (!ok) - error.SetErrorStringWithFormat("invalid value for permissions: %s", option_arg); - else - m_permissions = perms; - } - break; - case 's': - { - mode_t perms = ParsePermissionString(option_arg); - if (perms == (mode_t)-1) - error.SetErrorStringWithFormat("invalid value for permissions: %s", option_arg); - else - m_permissions = perms; - } - break; - case 'r': - m_permissions |= lldb::eFilePermissionsUserRead; - break; - case 'w': - m_permissions |= lldb::eFilePermissionsUserWrite; - break; - case 'x': - m_permissions |= lldb::eFilePermissionsUserExecute; - break; - case 'R': - m_permissions |= lldb::eFilePermissionsGroupRead; - break; - case 'W': - m_permissions |= lldb::eFilePermissionsGroupWrite; - break; - case 'X': - m_permissions |= lldb::eFilePermissionsGroupExecute; - break; - case 'd': - m_permissions |= lldb::eFilePermissionsWorldRead; - break; - case 't': - m_permissions |= lldb::eFilePermissionsWorldWrite; - break; - case 'e': - m_permissions |= lldb::eFilePermissionsWorldExecute; - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_permissions = 0; - } - - uint32_t - GetNumDefinitions () override - { - return llvm::array_lengthof(g_permissions_options); - } - - const lldb_private::OptionDefinition* - GetDefinitions () override - { - return g_permissions_options; - } - - // Instance variables to hold the values for command options. - - uint32_t m_permissions; + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_permissions = 0; + } + + uint32_t GetNumDefinitions() override { + return llvm::array_lengthof(g_permissions_options); + } + + const lldb_private::OptionDefinition *GetDefinitions() override { + return g_permissions_options; + } + + // Instance variables to hold the values for command options. + + uint32_t m_permissions; private: - DISALLOW_COPY_AND_ASSIGN(OptionPermissions); + DISALLOW_COPY_AND_ASSIGN(OptionPermissions); }; //---------------------------------------------------------------------- // "platform select <platform-name>" //---------------------------------------------------------------------- -class CommandObjectPlatformSelect : public CommandObjectParsed -{ +class CommandObjectPlatformSelect : public CommandObjectParsed { public: - CommandObjectPlatformSelect (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "platform select", - "Create a platform if needed and select it as the current platform.", - "platform select <platform-name>", - 0), - m_option_group (), - m_platform_options (false) // Don't include the "--platform" option by passing false - { - m_option_group.Append (&m_platform_options, LLDB_OPT_SET_ALL, 1); - m_option_group.Finalize(); - } - - ~CommandObjectPlatformSelect() override = default; - - int - HandleCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) override - { - std::string completion_str (input.GetArgumentAtIndex(cursor_index)); - completion_str.erase (cursor_char_position); - - CommandCompletions::PlatformPluginNames(GetCommandInterpreter(), - completion_str.c_str(), - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - return matches.GetSize(); - } - - Options * - GetOptions () override - { - return &m_option_group; - } + CommandObjectPlatformSelect(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "platform select", + "Create a platform if needed and select it as the " + "current platform.", + "platform select <platform-name>", 0), + m_option_group(), + m_platform_options( + false) // Don't include the "--platform" option by passing false + { + m_option_group.Append(&m_platform_options, LLDB_OPT_SET_ALL, 1); + m_option_group.Finalize(); + } + + ~CommandObjectPlatformSelect() override = default; + + int HandleCompletion(Args &input, int &cursor_index, + int &cursor_char_position, int match_start_point, + int max_return_elements, bool &word_complete, + StringList &matches) override { + std::string completion_str(input.GetArgumentAtIndex(cursor_index)); + completion_str.erase(cursor_char_position); + + CommandCompletions::PlatformPluginNames( + GetCommandInterpreter(), completion_str.c_str(), match_start_point, + max_return_elements, nullptr, word_complete, matches); + return matches.GetSize(); + } + + Options *GetOptions() override { return &m_option_group; } protected: - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - if (args.GetArgumentCount() == 1) - { - const char *platform_name = args.GetArgumentAtIndex (0); - if (platform_name && platform_name[0]) - { - const bool select = true; - m_platform_options.SetPlatformName (platform_name); - Error error; - ArchSpec platform_arch; - PlatformSP platform_sp (m_platform_options.CreatePlatformWithOptions (m_interpreter, ArchSpec(), select, error, platform_arch)); - if (platform_sp) - { - m_interpreter.GetDebugger().GetPlatformList().SetSelectedPlatform(platform_sp); - - platform_sp->GetStatus (result.GetOutputStream()); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendError(error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendError ("invalid platform name"); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendError ("platform create takes a platform name as an argument\n"); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + bool DoExecute(Args &args, CommandReturnObject &result) override { + if (args.GetArgumentCount() == 1) { + const char *platform_name = args.GetArgumentAtIndex(0); + if (platform_name && platform_name[0]) { + const bool select = true; + m_platform_options.SetPlatformName(platform_name); + Error error; + ArchSpec platform_arch; + PlatformSP platform_sp(m_platform_options.CreatePlatformWithOptions( + m_interpreter, ArchSpec(), select, error, platform_arch)); + if (platform_sp) { + m_interpreter.GetDebugger().GetPlatformList().SetSelectedPlatform( + platform_sp); + + platform_sp->GetStatus(result.GetOutputStream()); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendError("invalid platform name"); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendError( + "platform create takes a platform name as an argument\n"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } - OptionGroupOptions m_option_group; - OptionGroupPlatform m_platform_options; + OptionGroupOptions m_option_group; + OptionGroupPlatform m_platform_options; }; //---------------------------------------------------------------------- // "platform list" //---------------------------------------------------------------------- -class CommandObjectPlatformList : public CommandObjectParsed -{ +class CommandObjectPlatformList : public CommandObjectParsed { public: - CommandObjectPlatformList (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "platform list", - "List all platforms that are available.", - nullptr, - 0) - { - } + CommandObjectPlatformList(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "platform list", + "List all platforms that are available.", nullptr, + 0) {} - ~CommandObjectPlatformList() override = default; + ~CommandObjectPlatformList() override = default; protected: - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - Stream &ostrm = result.GetOutputStream(); - ostrm.Printf("Available platforms:\n"); - - PlatformSP host_platform_sp (Platform::GetHostPlatform()); - ostrm.Printf ("%s: %s\n", - host_platform_sp->GetPluginName().GetCString(), - host_platform_sp->GetDescription()); - - uint32_t idx; - for (idx = 0; 1; ++idx) - { - const char *plugin_name = PluginManager::GetPlatformPluginNameAtIndex (idx); - if (plugin_name == nullptr) - break; - const char *plugin_desc = PluginManager::GetPlatformPluginDescriptionAtIndex (idx); - if (plugin_desc == nullptr) - break; - ostrm.Printf("%s: %s\n", plugin_name, plugin_desc); - } - - if (idx == 0) - { - result.AppendError ("no platforms are available\n"); - result.SetStatus (eReturnStatusFailed); - } - else - result.SetStatus (eReturnStatusSuccessFinishResult); - return result.Succeeded(); + bool DoExecute(Args &args, CommandReturnObject &result) override { + Stream &ostrm = result.GetOutputStream(); + ostrm.Printf("Available platforms:\n"); + + PlatformSP host_platform_sp(Platform::GetHostPlatform()); + ostrm.Printf("%s: %s\n", host_platform_sp->GetPluginName().GetCString(), + host_platform_sp->GetDescription()); + + uint32_t idx; + for (idx = 0; 1; ++idx) { + const char *plugin_name = + PluginManager::GetPlatformPluginNameAtIndex(idx); + if (plugin_name == nullptr) + break; + const char *plugin_desc = + PluginManager::GetPlatformPluginDescriptionAtIndex(idx); + if (plugin_desc == nullptr) + break; + ostrm.Printf("%s: %s\n", plugin_name, plugin_desc); } + + if (idx == 0) { + result.AppendError("no platforms are available\n"); + result.SetStatus(eReturnStatusFailed); + } else + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); + } }; //---------------------------------------------------------------------- // "platform status" //---------------------------------------------------------------------- -class CommandObjectPlatformStatus : public CommandObjectParsed -{ +class CommandObjectPlatformStatus : public CommandObjectParsed { public: - CommandObjectPlatformStatus(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "platform status", "Display status for the current platform.", nullptr, 0) - { - } + CommandObjectPlatformStatus(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "platform status", + "Display status for the current platform.", nullptr, + 0) {} - ~CommandObjectPlatformStatus() override = default; + ~CommandObjectPlatformStatus() override = default; protected: - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - Stream &ostrm = result.GetOutputStream(); - - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - PlatformSP platform_sp; - if (target) - { - platform_sp = target->GetPlatform(); - } - if (!platform_sp) - { - platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform(); - } - if (platform_sp) - { - platform_sp->GetStatus (ostrm); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendError ("no platform us currently selected\n"); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + bool DoExecute(Args &args, CommandReturnObject &result) override { + Stream &ostrm = result.GetOutputStream(); + + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + PlatformSP platform_sp; + if (target) { + platform_sp = target->GetPlatform(); } + if (!platform_sp) { + platform_sp = + m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform(); + } + if (platform_sp) { + platform_sp->GetStatus(ostrm); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendError("no platform us currently selected\n"); + result.SetStatus(eReturnStatusFailed); + } + return result.Succeeded(); + } }; //---------------------------------------------------------------------- // "platform connect <connect-url>" //---------------------------------------------------------------------- -class CommandObjectPlatformConnect : public CommandObjectParsed -{ +class CommandObjectPlatformConnect : public CommandObjectParsed { public: - CommandObjectPlatformConnect(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "platform connect", - "Select the current platform by providing a connection URL.", - "platform connect <connect-url>", 0) - { - } + CommandObjectPlatformConnect(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "platform connect", + "Select the current platform by providing a connection URL.", + "platform connect <connect-url>", 0) {} - ~CommandObjectPlatformConnect() override = default; + ~CommandObjectPlatformConnect() override = default; protected: - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - Stream &ostrm = result.GetOutputStream(); - - PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); - if (platform_sp) - { - Error error (platform_sp->ConnectRemote (args)); - if (error.Success()) - { - platform_sp->GetStatus (ostrm); - result.SetStatus (eReturnStatusSuccessFinishResult); - - platform_sp->ConnectToWaitingProcesses(m_interpreter.GetDebugger(), error); - if (error.Fail()) - { - result.AppendError (error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendErrorWithFormat ("%s\n", error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendError ("no platform is currently selected\n"); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + bool DoExecute(Args &args, CommandReturnObject &result) override { + Stream &ostrm = result.GetOutputStream(); + + PlatformSP platform_sp( + m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (platform_sp) { + Error error(platform_sp->ConnectRemote(args)); + if (error.Success()) { + platform_sp->GetStatus(ostrm); + result.SetStatus(eReturnStatusSuccessFinishResult); + + platform_sp->ConnectToWaitingProcesses(m_interpreter.GetDebugger(), + error); + if (error.Fail()) { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendErrorWithFormat("%s\n", error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendError("no platform is currently selected\n"); + result.SetStatus(eReturnStatusFailed); } - - Options * - GetOptions () override - { - PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); - OptionGroupOptions* m_platform_options = nullptr; - if (platform_sp) - { - m_platform_options = platform_sp->GetConnectionOptions(m_interpreter); - if (m_platform_options != nullptr && !m_platform_options->m_did_finalize) - m_platform_options->Finalize(); - } - return m_platform_options; + return result.Succeeded(); + } + + Options *GetOptions() override { + PlatformSP platform_sp( + m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + OptionGroupOptions *m_platform_options = nullptr; + if (platform_sp) { + m_platform_options = platform_sp->GetConnectionOptions(m_interpreter); + if (m_platform_options != nullptr && !m_platform_options->m_did_finalize) + m_platform_options->Finalize(); } + return m_platform_options; + } }; //---------------------------------------------------------------------- // "platform disconnect" //---------------------------------------------------------------------- -class CommandObjectPlatformDisconnect : public CommandObjectParsed -{ +class CommandObjectPlatformDisconnect : public CommandObjectParsed { public: - CommandObjectPlatformDisconnect(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "platform disconnect", "Disconnect from the current platform.", - "platform disconnect", 0) - { - } + CommandObjectPlatformDisconnect(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "platform disconnect", + "Disconnect from the current platform.", + "platform disconnect", 0) {} - ~CommandObjectPlatformDisconnect() override = default; + ~CommandObjectPlatformDisconnect() override = default; protected: - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); - if (platform_sp) - { - if (args.GetArgumentCount() == 0) - { - Error error; - - if (platform_sp->IsConnected()) - { - // Cache the instance name if there is one since we are - // about to disconnect and the name might go with it. - const char *hostname_cstr = platform_sp->GetHostname(); - std::string hostname; - if (hostname_cstr) - hostname.assign (hostname_cstr); - - error = platform_sp->DisconnectRemote (); - if (error.Success()) - { - Stream &ostrm = result.GetOutputStream(); - if (hostname.empty()) - ostrm.Printf ("Disconnected from \"%s\"\n", platform_sp->GetPluginName().GetCString()); - else - ostrm.Printf ("Disconnected from \"%s\"\n", hostname.c_str()); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendErrorWithFormat ("%s", error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - // Not connected... - result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetPluginName().GetCString()); - result.SetStatus (eReturnStatusFailed); - } - } + bool DoExecute(Args &args, CommandReturnObject &result) override { + PlatformSP platform_sp( + m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (platform_sp) { + if (args.GetArgumentCount() == 0) { + Error error; + + if (platform_sp->IsConnected()) { + // Cache the instance name if there is one since we are + // about to disconnect and the name might go with it. + const char *hostname_cstr = platform_sp->GetHostname(); + std::string hostname; + if (hostname_cstr) + hostname.assign(hostname_cstr); + + error = platform_sp->DisconnectRemote(); + if (error.Success()) { + Stream &ostrm = result.GetOutputStream(); + if (hostname.empty()) + ostrm.Printf("Disconnected from \"%s\"\n", + platform_sp->GetPluginName().GetCString()); else - { - // Bad args - result.AppendError ("\"platform disconnect\" doesn't take any arguments"); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendError ("no platform is currently selected"); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + ostrm.Printf("Disconnected from \"%s\"\n", hostname.c_str()); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat("%s", error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + } else { + // Not connected... + result.AppendErrorWithFormat( + "not connected to '%s'", + platform_sp->GetPluginName().GetCString()); + result.SetStatus(eReturnStatusFailed); + } + } else { + // Bad args + result.AppendError( + "\"platform disconnect\" doesn't take any arguments"); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendError("no platform is currently selected"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } }; //---------------------------------------------------------------------- // "platform settings" //---------------------------------------------------------------------- -class CommandObjectPlatformSettings : public CommandObjectParsed -{ +class CommandObjectPlatformSettings : public CommandObjectParsed { public: - CommandObjectPlatformSettings (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "platform settings", - "Set settings for the current target's platform, or for a platform by name.", - "platform settings", - 0), + CommandObjectPlatformSettings(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "platform settings", + "Set settings for the current target's platform, " + "or for a platform by name.", + "platform settings", 0), m_options(), - m_option_working_dir (LLDB_OPT_SET_1, false, "working-dir", 'w', 0, eArgTypePath, "The working directory for the platform.") - { - m_options.Append (&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - } + m_option_working_dir(LLDB_OPT_SET_1, false, "working-dir", 'w', 0, + eArgTypePath, + "The working directory for the platform.") { + m_options.Append(&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + } - ~CommandObjectPlatformSettings() override = default; + ~CommandObjectPlatformSettings() override = default; protected: - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); - if (platform_sp) - { - if (m_option_working_dir.GetOptionValue().OptionWasSet()) - platform_sp->SetWorkingDirectory(m_option_working_dir.GetOptionValue().GetCurrentValue()); - } - else - { - result.AppendError ("no platform is currently selected"); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); - } - - Options * - GetOptions () override - { - if (!m_options.DidFinalize()) - m_options.Finalize(); - return &m_options; + bool DoExecute(Args &args, CommandReturnObject &result) override { + PlatformSP platform_sp( + m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (platform_sp) { + if (m_option_working_dir.GetOptionValue().OptionWasSet()) + platform_sp->SetWorkingDirectory( + m_option_working_dir.GetOptionValue().GetCurrentValue()); + } else { + result.AppendError("no platform is currently selected"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } + + Options *GetOptions() override { + if (!m_options.DidFinalize()) + m_options.Finalize(); + return &m_options; + } protected: - OptionGroupOptions m_options; - OptionGroupFile m_option_working_dir; + OptionGroupOptions m_options; + OptionGroupFile m_option_working_dir; }; //---------------------------------------------------------------------- // "platform mkdir" //---------------------------------------------------------------------- -class CommandObjectPlatformMkDir : public CommandObjectParsed -{ +class CommandObjectPlatformMkDir : public CommandObjectParsed { public: - CommandObjectPlatformMkDir (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "platform mkdir", - "Make a new directory on the remote end.", - nullptr, + CommandObjectPlatformMkDir(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "platform mkdir", + "Make a new directory on the remote end.", nullptr, 0), - m_options() - { + m_options() {} + + ~CommandObjectPlatformMkDir() override = default; + + bool DoExecute(Args &args, CommandReturnObject &result) override { + PlatformSP platform_sp( + m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (platform_sp) { + std::string cmd_line; + args.GetCommandString(cmd_line); + uint32_t mode; + const OptionPermissions *options_permissions = + (const OptionPermissions *)m_options.GetGroupWithOption('r'); + if (options_permissions) + mode = options_permissions->m_permissions; + else + mode = lldb::eFilePermissionsUserRWX | lldb::eFilePermissionsGroupRWX | + lldb::eFilePermissionsWorldRX; + Error error = platform_sp->MakeDirectory(FileSpec{cmd_line, false}, mode); + if (error.Success()) { + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendError("no platform currently selected\n"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } - ~CommandObjectPlatformMkDir() override = default; - - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); - if (platform_sp) - { - std::string cmd_line; - args.GetCommandString(cmd_line); - uint32_t mode; - const OptionPermissions* options_permissions = (const OptionPermissions*)m_options.GetGroupWithOption('r'); - if (options_permissions) - mode = options_permissions->m_permissions; - else - mode = lldb::eFilePermissionsUserRWX | lldb::eFilePermissionsGroupRWX | lldb::eFilePermissionsWorldRX; - Error error = platform_sp->MakeDirectory(FileSpec{cmd_line, false}, mode); - if (error.Success()) - { - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendError(error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendError ("no platform currently selected\n"); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); - } - - Options * - GetOptions () override - { - if (!m_options.DidFinalize()) - { - m_options.Append(new OptionPermissions()); - m_options.Finalize(); - } - return &m_options; + Options *GetOptions() override { + if (!m_options.DidFinalize()) { + m_options.Append(new OptionPermissions()); + m_options.Finalize(); } + return &m_options; + } - OptionGroupOptions m_options; + OptionGroupOptions m_options; }; //---------------------------------------------------------------------- // "platform fopen" //---------------------------------------------------------------------- -class CommandObjectPlatformFOpen : public CommandObjectParsed -{ +class CommandObjectPlatformFOpen : public CommandObjectParsed { public: - CommandObjectPlatformFOpen (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "platform file open", - "Open a file on the remote end.", - nullptr, - 0), - m_options() - { - } - - ~CommandObjectPlatformFOpen() override = default; - - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); - if (platform_sp) - { - Error error; - std::string cmd_line; - args.GetCommandString(cmd_line); - mode_t perms; - const OptionPermissions* options_permissions = (const OptionPermissions*)m_options.GetGroupWithOption('r'); - if (options_permissions) - perms = options_permissions->m_permissions; - else - perms = lldb::eFilePermissionsUserRW | lldb::eFilePermissionsGroupRW | lldb::eFilePermissionsWorldRead; - lldb::user_id_t fd = platform_sp->OpenFile(FileSpec(cmd_line.c_str(),false), - File::eOpenOptionRead | File::eOpenOptionWrite | - File::eOpenOptionAppend | File::eOpenOptionCanCreate, - perms, - error); - if (error.Success()) - { - result.AppendMessageWithFormat("File Descriptor = %" PRIu64 "\n",fd); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendError(error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendError ("no platform currently selected\n"); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + CommandObjectPlatformFOpen(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "platform file open", + "Open a file on the remote end.", nullptr, 0), + m_options() {} + + ~CommandObjectPlatformFOpen() override = default; + + bool DoExecute(Args &args, CommandReturnObject &result) override { + PlatformSP platform_sp( + m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (platform_sp) { + Error error; + std::string cmd_line; + args.GetCommandString(cmd_line); + mode_t perms; + const OptionPermissions *options_permissions = + (const OptionPermissions *)m_options.GetGroupWithOption('r'); + if (options_permissions) + perms = options_permissions->m_permissions; + else + perms = lldb::eFilePermissionsUserRW | lldb::eFilePermissionsGroupRW | + lldb::eFilePermissionsWorldRead; + lldb::user_id_t fd = platform_sp->OpenFile( + FileSpec(cmd_line.c_str(), false), + File::eOpenOptionRead | File::eOpenOptionWrite | + File::eOpenOptionAppend | File::eOpenOptionCanCreate, + perms, error); + if (error.Success()) { + result.AppendMessageWithFormat("File Descriptor = %" PRIu64 "\n", fd); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendError("no platform currently selected\n"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } - Options * - GetOptions () override - { - if (!m_options.DidFinalize()) - { - m_options.Append(new OptionPermissions()); - m_options.Finalize(); - } - return &m_options; + Options *GetOptions() override { + if (!m_options.DidFinalize()) { + m_options.Append(new OptionPermissions()); + m_options.Finalize(); } + return &m_options; + } - OptionGroupOptions m_options; + OptionGroupOptions m_options; }; //---------------------------------------------------------------------- // "platform fclose" //---------------------------------------------------------------------- -class CommandObjectPlatformFClose : public CommandObjectParsed -{ +class CommandObjectPlatformFClose : public CommandObjectParsed { public: - CommandObjectPlatformFClose (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "platform file close", - "Close a file on the remote end.", - nullptr, - 0) - { - } - - ~CommandObjectPlatformFClose() override = default; - - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); - 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); - Error error; - bool success = platform_sp->CloseFile(fd, error); - if (success) - { - result.AppendMessageWithFormat("file %" PRIu64 " closed.\n", fd); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendError(error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendError ("no platform currently selected\n"); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + CommandObjectPlatformFClose(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "platform file close", + "Close a file on the remote end.", nullptr, 0) {} + + ~CommandObjectPlatformFClose() override = default; + + bool DoExecute(Args &args, CommandReturnObject &result) override { + PlatformSP platform_sp( + m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + 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); + Error error; + bool success = platform_sp->CloseFile(fd, error); + if (success) { + result.AppendMessageWithFormat("file %" PRIu64 " closed.\n", fd); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendError("no platform currently selected\n"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } }; //---------------------------------------------------------------------- // "platform fread" //---------------------------------------------------------------------- -class CommandObjectPlatformFRead : public CommandObjectParsed -{ +class CommandObjectPlatformFRead : public CommandObjectParsed { public: - CommandObjectPlatformFRead (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "platform file read", - "Read data from a file on the remote end.", - nullptr, + CommandObjectPlatformFRead(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "platform file read", + "Read data from a file on the remote end.", nullptr, 0), - m_options() - { + m_options() {} + + ~CommandObjectPlatformFRead() override = default; + + bool DoExecute(Args &args, CommandReturnObject &result) override { + PlatformSP platform_sp( + m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + 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); + std::string buffer(m_options.m_count, 0); + Error error; + uint32_t retcode = platform_sp->ReadFile( + fd, m_options.m_offset, &buffer[0], m_options.m_count, error); + result.AppendMessageWithFormat("Return = %d\n", retcode); + result.AppendMessageWithFormat("Data = \"%s\"\n", buffer.c_str()); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendError("no platform currently selected\n"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } - ~CommandObjectPlatformFRead() override = default; + Options *GetOptions() override { return &m_options; } - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); - 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); - std::string buffer(m_options.m_count,0); - Error error; - uint32_t retcode = platform_sp->ReadFile(fd, m_options.m_offset, &buffer[0], m_options.m_count, error); - result.AppendMessageWithFormat("Return = %d\n",retcode); - result.AppendMessageWithFormat("Data = \"%s\"\n",buffer.c_str()); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendError ("no platform currently selected\n"); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); +protected: + class CommandOptions : public Options { + public: + CommandOptions() : Options() {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + char short_option = (char)m_getopt_table[option_idx].val; + bool success = false; + + switch (short_option) { + case 'o': + m_offset = StringConvert::ToUInt32(option_arg, 0, 0, &success); + if (!success) + error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg); + break; + case 'c': + m_count = StringConvert::ToUInt32(option_arg, 0, 0, &success); + if (!success) + error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg); + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; } - Options * - GetOptions () override - { - return &m_options; + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_offset = 0; + m_count = 1; } - -protected: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - } - ~CommandOptions() override = default; - - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - char short_option = (char) m_getopt_table[option_idx].val; - bool success = false; - - switch (short_option) - { - case 'o': - m_offset = StringConvert::ToUInt32(option_arg, 0, 0, &success); - if (!success) - error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg); - break; - case 'c': - m_count = StringConvert::ToUInt32(option_arg, 0, 0, &success); - if (!success) - error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg); - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_offset = 0; - m_count = 1; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - uint32_t m_offset; - uint32_t m_count; - }; - - CommandOptions m_options; + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + uint32_t m_offset; + uint32_t m_count; + }; + + CommandOptions m_options; }; -OptionDefinition -CommandObjectPlatformFRead::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectPlatformFRead::CommandOptions::g_option_table[] = + { + // clang-format off {LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeIndex, "Offset into the file at which to start reading."}, {LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Number of bytes to read from the file."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //---------------------------------------------------------------------- // "platform fwrite" //---------------------------------------------------------------------- -class CommandObjectPlatformFWrite : public CommandObjectParsed -{ +class CommandObjectPlatformFWrite : public CommandObjectParsed { public: - CommandObjectPlatformFWrite (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "platform file write", - "Write data to a file on the remote end.", - nullptr, + CommandObjectPlatformFWrite(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "platform file write", + "Write data to a file on the remote end.", nullptr, 0), - m_options() - { + m_options() {} + + ~CommandObjectPlatformFWrite() override = default; + + bool DoExecute(Args &args, CommandReturnObject &result) override { + PlatformSP platform_sp( + m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (platform_sp) { + std::string cmd_line; + args.GetCommandString(cmd_line); + Error error; + const lldb::user_id_t fd = + StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX); + uint32_t retcode = + platform_sp->WriteFile(fd, m_options.m_offset, &m_options.m_data[0], + m_options.m_data.size(), error); + result.AppendMessageWithFormat("Return = %d\n", retcode); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendError("no platform currently selected\n"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } - ~CommandObjectPlatformFWrite() override = default; + Options *GetOptions() override { return &m_options; } - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); - if (platform_sp) - { - std::string cmd_line; - args.GetCommandString(cmd_line); - Error error; - const lldb::user_id_t fd = StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX); - uint32_t retcode = platform_sp->WriteFile (fd, - m_options.m_offset, - &m_options.m_data[0], - m_options.m_data.size(), - error); - result.AppendMessageWithFormat("Return = %d\n",retcode); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendError ("no platform currently selected\n"); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); +protected: + class CommandOptions : public Options { + public: + CommandOptions() : Options() {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + char short_option = (char)m_getopt_table[option_idx].val; + bool success = false; + + switch (short_option) { + case 'o': + m_offset = StringConvert::ToUInt32(option_arg, 0, 0, &success); + if (!success) + error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg); + break; + case 'd': + m_data.assign(option_arg); + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; } - Options * - GetOptions () override - { - return &m_options; + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_offset = 0; + m_data.clear(); } - -protected: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - } - ~CommandOptions() override = default; - - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - char short_option = (char) m_getopt_table[option_idx].val; - bool success = false; - - switch (short_option) - { - case 'o': - m_offset = StringConvert::ToUInt32(option_arg, 0, 0, &success); - if (!success) - error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg); - break; - case 'd': - m_data.assign(option_arg); - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_offset = 0; - m_data.clear(); - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - uint32_t m_offset; - std::string m_data; - }; - - CommandOptions m_options; + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + uint32_t m_offset; + std::string m_data; + }; + + CommandOptions m_options; }; -OptionDefinition -CommandObjectPlatformFWrite::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectPlatformFWrite::CommandOptions::g_option_table[] = + { + // clang-format off {LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeIndex, "Offset into the file at which to start reading."}, {LLDB_OPT_SET_1, false, "data", 'd', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeValue, "Text to write to the file."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; -class CommandObjectPlatformFile : public CommandObjectMultiword -{ +class CommandObjectPlatformFile : public CommandObjectMultiword { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - CommandObjectPlatformFile(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "platform file", "Commands to access files on the current platform.", - "platform file [open|close|read|write] ...") - { - LoadSubCommand ("open", CommandObjectSP (new CommandObjectPlatformFOpen (interpreter))); - LoadSubCommand ("close", CommandObjectSP (new CommandObjectPlatformFClose (interpreter))); - LoadSubCommand ("read", CommandObjectSP (new CommandObjectPlatformFRead (interpreter))); - LoadSubCommand ("write", CommandObjectSP (new CommandObjectPlatformFWrite (interpreter))); - } - - ~CommandObjectPlatformFile() override = default; + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + CommandObjectPlatformFile(CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "platform file", + "Commands to access files on the current platform.", + "platform file [open|close|read|write] ...") { + LoadSubCommand( + "open", CommandObjectSP(new CommandObjectPlatformFOpen(interpreter))); + LoadSubCommand( + "close", CommandObjectSP(new CommandObjectPlatformFClose(interpreter))); + LoadSubCommand( + "read", CommandObjectSP(new CommandObjectPlatformFRead(interpreter))); + LoadSubCommand( + "write", CommandObjectSP(new CommandObjectPlatformFWrite(interpreter))); + } + + ~CommandObjectPlatformFile() override = default; private: - //------------------------------------------------------------------ - // For CommandObjectPlatform only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformFile); + //------------------------------------------------------------------ + // For CommandObjectPlatform only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN(CommandObjectPlatformFile); }; //---------------------------------------------------------------------- // "platform get-file remote-file-path host-file-path" //---------------------------------------------------------------------- -class CommandObjectPlatformGetFile : public CommandObjectParsed -{ +class CommandObjectPlatformGetFile : public CommandObjectParsed { public: - CommandObjectPlatformGetFile (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "platform get-file", - "Transfer a file from the remote end to the local host.", - "platform get-file <remote-file-spec> <local-file-spec>", - 0) - { - SetHelpLong( -R"(Examples: + CommandObjectPlatformGetFile(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "platform get-file", + "Transfer a file from the remote end to the local host.", + "platform get-file <remote-file-spec> <local-file-spec>", 0) { + SetHelpLong( + R"(Examples: (lldb) platform get-file /the/remote/file/path /the/local/file/path - Transfer a file from the remote end with file path /the/remote/file/path to the local host.)" - ); - - CommandArgumentEntry arg1, arg2; - CommandArgumentData file_arg_remote, file_arg_host; - - // Define the first (and only) variant of this arg. - file_arg_remote.arg_type = eArgTypeFilename; - file_arg_remote.arg_repetition = eArgRepeatPlain; - // There is only one variant this argument could be; put it into the argument entry. - arg1.push_back (file_arg_remote); - - // Define the second (and only) variant of this arg. - file_arg_host.arg_type = eArgTypeFilename; - file_arg_host.arg_repetition = eArgRepeatPlain; - // There is only one variant this argument could be; put it into the argument entry. - arg2.push_back (file_arg_host); - - // Push the data for the first and the second arguments into the m_arguments vector. - m_arguments.push_back (arg1); - m_arguments.push_back (arg2); + Transfer a file from the remote end with file path /the/remote/file/path to the local host.)"); + + CommandArgumentEntry arg1, arg2; + CommandArgumentData file_arg_remote, file_arg_host; + + // Define the first (and only) variant of this arg. + file_arg_remote.arg_type = eArgTypeFilename; + file_arg_remote.arg_repetition = eArgRepeatPlain; + // There is only one variant this argument could be; put it into the + // argument entry. + arg1.push_back(file_arg_remote); + + // Define the second (and only) variant of this arg. + file_arg_host.arg_type = eArgTypeFilename; + file_arg_host.arg_repetition = eArgRepeatPlain; + // There is only one variant this argument could be; put it into the + // argument entry. + arg2.push_back(file_arg_host); + + // Push the data for the first and the second arguments into the m_arguments + // vector. + m_arguments.push_back(arg1); + m_arguments.push_back(arg2); + } + + ~CommandObjectPlatformGetFile() override = default; + + bool DoExecute(Args &args, CommandReturnObject &result) override { + // If the number of arguments is incorrect, issue an error message. + if (args.GetArgumentCount() != 2) { + result.GetErrorStream().Printf("error: required arguments missing; " + "specify both the source and destination " + "file paths\n"); + result.SetStatus(eReturnStatusFailed); + return false; } - ~CommandObjectPlatformGetFile() override = default; - - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - // If the number of arguments is incorrect, issue an error message. - if (args.GetArgumentCount() != 2) - { - result.GetErrorStream().Printf("error: required arguments missing; specify both the source and destination file paths\n"); - result.SetStatus(eReturnStatusFailed); - return false; - } - - PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); - if (platform_sp) - { - const char *remote_file_path = args.GetArgumentAtIndex(0); - const char *local_file_path = args.GetArgumentAtIndex(1); - Error error = platform_sp->GetFile(FileSpec(remote_file_path, false), - FileSpec(local_file_path, false)); - if (error.Success()) - { - result.AppendMessageWithFormat("successfully get-file from %s (remote) to %s (host)\n", - remote_file_path, local_file_path); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendMessageWithFormat("get-file failed: %s\n", error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendError ("no platform currently selected\n"); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + PlatformSP platform_sp( + m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (platform_sp) { + const char *remote_file_path = args.GetArgumentAtIndex(0); + const char *local_file_path = args.GetArgumentAtIndex(1); + Error error = platform_sp->GetFile(FileSpec(remote_file_path, false), + FileSpec(local_file_path, false)); + if (error.Success()) { + result.AppendMessageWithFormat( + "successfully get-file from %s (remote) to %s (host)\n", + remote_file_path, local_file_path); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendMessageWithFormat("get-file failed: %s\n", + error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendError("no platform currently selected\n"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } }; //---------------------------------------------------------------------- // "platform get-size remote-file-path" //---------------------------------------------------------------------- -class CommandObjectPlatformGetSize : public CommandObjectParsed -{ +class CommandObjectPlatformGetSize : public CommandObjectParsed { public: - CommandObjectPlatformGetSize (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "platform get-size", - "Get the file size from the remote end.", - "platform get-size <remote-file-spec>", - 0) - { - SetHelpLong( -R"(Examples: + CommandObjectPlatformGetSize(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "platform get-size", + "Get the file size from the remote end.", + "platform get-size <remote-file-spec>", 0) { + SetHelpLong( + R"(Examples: (lldb) platform get-size /the/remote/file/path - Get the file size from the remote end with path /the/remote/file/path.)" - ); - - CommandArgumentEntry arg1; - CommandArgumentData file_arg_remote; - - // Define the first (and only) variant of this arg. - file_arg_remote.arg_type = eArgTypeFilename; - file_arg_remote.arg_repetition = eArgRepeatPlain; - // There is only one variant this argument could be; put it into the argument entry. - arg1.push_back (file_arg_remote); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg1); - } + Get the file size from the remote end with path /the/remote/file/path.)"); - ~CommandObjectPlatformGetSize() override = default; + CommandArgumentEntry arg1; + CommandArgumentData file_arg_remote; - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - // If the number of arguments is incorrect, issue an error message. - if (args.GetArgumentCount() != 1) - { - result.GetErrorStream().Printf("error: required argument missing; specify the source file path as the only argument\n"); - result.SetStatus(eReturnStatusFailed); - return false; - } + // Define the first (and only) variant of this arg. + file_arg_remote.arg_type = eArgTypeFilename; + file_arg_remote.arg_repetition = eArgRepeatPlain; + // There is only one variant this argument could be; put it into the + // argument entry. + arg1.push_back(file_arg_remote); - PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); - if (platform_sp) - { - std::string remote_file_path(args.GetArgumentAtIndex(0)); - user_id_t size = platform_sp->GetFileSize(FileSpec(remote_file_path.c_str(), false)); - if (size != UINT64_MAX) - { - result.AppendMessageWithFormat("File size of %s (remote): %" PRIu64 "\n", remote_file_path.c_str(), size); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendMessageWithFormat("Error getting file size of %s (remote)\n", remote_file_path.c_str()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendError ("no platform currently selected\n"); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg1); + } + + ~CommandObjectPlatformGetSize() override = default; + + bool DoExecute(Args &args, CommandReturnObject &result) override { + // If the number of arguments is incorrect, issue an error message. + if (args.GetArgumentCount() != 1) { + result.GetErrorStream().Printf("error: required argument missing; " + "specify the source file path as the only " + "argument\n"); + result.SetStatus(eReturnStatusFailed); + return false; } + + PlatformSP platform_sp( + m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (platform_sp) { + std::string remote_file_path(args.GetArgumentAtIndex(0)); + user_id_t size = + platform_sp->GetFileSize(FileSpec(remote_file_path.c_str(), false)); + if (size != UINT64_MAX) { + result.AppendMessageWithFormat("File size of %s (remote): %" PRIu64 + "\n", + remote_file_path.c_str(), size); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendMessageWithFormat( + "Error getting file size of %s (remote)\n", + remote_file_path.c_str()); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendError("no platform currently selected\n"); + result.SetStatus(eReturnStatusFailed); + } + return result.Succeeded(); + } }; //---------------------------------------------------------------------- // "platform put-file" //---------------------------------------------------------------------- -class CommandObjectPlatformPutFile : public CommandObjectParsed -{ +class CommandObjectPlatformPutFile : public CommandObjectParsed { public: - CommandObjectPlatformPutFile (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "platform put-file", - "Transfer a file from this system to the remote end.", - nullptr, - 0) - { - } - - ~CommandObjectPlatformPutFile() override = default; - - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - const char* src = args.GetArgumentAtIndex(0); - const char* dst = args.GetArgumentAtIndex(1); - - FileSpec src_fs(src, true); - FileSpec dst_fs(dst ? dst : src_fs.GetFilename().GetCString(), false); - - PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); - if (platform_sp) - { - Error error (platform_sp->PutFile(src_fs, dst_fs)); - if (error.Success()) - { - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendError (error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendError ("no platform currently selected\n"); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + CommandObjectPlatformPutFile(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "platform put-file", + "Transfer a file from this system to the remote end.", nullptr, 0) { + } + + ~CommandObjectPlatformPutFile() override = default; + + bool DoExecute(Args &args, CommandReturnObject &result) override { + const char *src = args.GetArgumentAtIndex(0); + const char *dst = args.GetArgumentAtIndex(1); + + FileSpec src_fs(src, true); + FileSpec dst_fs(dst ? dst : src_fs.GetFilename().GetCString(), false); + + PlatformSP platform_sp( + m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (platform_sp) { + Error error(platform_sp->PutFile(src_fs, dst_fs)); + if (error.Success()) { + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendError("no platform currently selected\n"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } }; //---------------------------------------------------------------------- // "platform process launch" //---------------------------------------------------------------------- -class CommandObjectPlatformProcessLaunch : public CommandObjectParsed -{ +class CommandObjectPlatformProcessLaunch : public CommandObjectParsed { public: - CommandObjectPlatformProcessLaunch (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "platform process launch", - "Launch a new process on a remote platform.", - "platform process launch program", - eCommandRequiresTarget | eCommandTryTargetAPILock), - m_options() - { - } + CommandObjectPlatformProcessLaunch(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "platform process launch", + "Launch a new process on a remote platform.", + "platform process launch program", + eCommandRequiresTarget | eCommandTryTargetAPILock), + m_options() {} - ~CommandObjectPlatformProcessLaunch() override = default; + ~CommandObjectPlatformProcessLaunch() override = default; + + Options *GetOptions() override { return &m_options; } - Options * - GetOptions () override - { - return &m_options; - } - protected: - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - PlatformSP platform_sp; - if (target) - { - platform_sp = target->GetPlatform(); - } - if (!platform_sp) - { - platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform(); - } - - if (platform_sp) - { - Error error; - const size_t argc = args.GetArgumentCount(); - Target *target = m_exe_ctx.GetTargetPtr(); - Module *exe_module = target->GetExecutableModulePointer(); - if (exe_module) - { - m_options.launch_info.GetExecutableFile () = exe_module->GetFileSpec(); - char exe_path[PATH_MAX]; - if (m_options.launch_info.GetExecutableFile ().GetPath (exe_path, sizeof(exe_path))) - m_options.launch_info.GetArguments().AppendArgument (exe_path); - m_options.launch_info.GetArchitecture() = exe_module->GetArchitecture(); - } + bool DoExecute(Args &args, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + PlatformSP platform_sp; + if (target) { + platform_sp = target->GetPlatform(); + } + if (!platform_sp) { + platform_sp = + m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform(); + } - if (argc > 0) - { - if (m_options.launch_info.GetExecutableFile ()) - { - // We already have an executable file, so we will use this - // and all arguments to this function are extra arguments - m_options.launch_info.GetArguments().AppendArguments (args); - } - else - { - // We don't have any file yet, so the first argument is our - // executable, and the rest are program arguments - const bool first_arg_is_executable = true; - m_options.launch_info.SetArguments (args, first_arg_is_executable); - } - } - - if (m_options.launch_info.GetExecutableFile ()) - { - Debugger &debugger = m_interpreter.GetDebugger(); - - if (argc == 0) - target->GetRunArguments(m_options.launch_info.GetArguments()); - - ProcessSP process_sp (platform_sp->DebugProcess (m_options.launch_info, - debugger, - target, - error)); - if (process_sp && process_sp->IsAlive()) - { - result.SetStatus (eReturnStatusSuccessFinishNoResult); - return true; - } - - if (error.Success()) - result.AppendError ("process launch failed"); - else - result.AppendError (error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - else - { - result.AppendError ("'platform process launch' uses the current target file and arguments, or the executable and its arguments can be specified in this command"); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (platform_sp) { + Error error; + const size_t argc = args.GetArgumentCount(); + Target *target = m_exe_ctx.GetTargetPtr(); + Module *exe_module = target->GetExecutableModulePointer(); + if (exe_module) { + m_options.launch_info.GetExecutableFile() = exe_module->GetFileSpec(); + char exe_path[PATH_MAX]; + if (m_options.launch_info.GetExecutableFile().GetPath(exe_path, + sizeof(exe_path))) + m_options.launch_info.GetArguments().AppendArgument(exe_path); + m_options.launch_info.GetArchitecture() = exe_module->GetArchitecture(); + } + + if (argc > 0) { + if (m_options.launch_info.GetExecutableFile()) { + // We already have an executable file, so we will use this + // and all arguments to this function are extra arguments + m_options.launch_info.GetArguments().AppendArguments(args); + } else { + // We don't have any file yet, so the first argument is our + // executable, and the rest are program arguments + const bool first_arg_is_executable = true; + m_options.launch_info.SetArguments(args, first_arg_is_executable); + } + } + + if (m_options.launch_info.GetExecutableFile()) { + Debugger &debugger = m_interpreter.GetDebugger(); + + if (argc == 0) + target->GetRunArguments(m_options.launch_info.GetArguments()); + + ProcessSP process_sp(platform_sp->DebugProcess( + m_options.launch_info, debugger, target, error)); + if (process_sp && process_sp->IsAlive()) { + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return true; } + + if (error.Success()) + result.AppendError("process launch failed"); else - { - result.AppendError ("no platform is selected\n"); - } - return result.Succeeded(); + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } else { + result.AppendError("'platform process launch' uses the current target " + "file and arguments, or the executable and its " + "arguments can be specified in this command"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + result.AppendError("no platform is selected\n"); } - + return result.Succeeded(); + } + protected: - ProcessLaunchCommandOptions m_options; + ProcessLaunchCommandOptions m_options; }; //---------------------------------------------------------------------- // "platform process list" //---------------------------------------------------------------------- -class CommandObjectPlatformProcessList : public CommandObjectParsed -{ +class CommandObjectPlatformProcessList : public CommandObjectParsed { public: - CommandObjectPlatformProcessList (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "platform process list", - "List processes on a remote platform by name, pid, or many other matching attributes.", - "platform process list", - 0), - m_options() - { - } + CommandObjectPlatformProcessList(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "platform process list", + "List processes on a remote platform by name, pid, " + "or many other matching attributes.", + "platform process list", 0), + m_options() {} - ~CommandObjectPlatformProcessList() override = default; + ~CommandObjectPlatformProcessList() override = default; + + Options *GetOptions() override { return &m_options; } - Options * - GetOptions () override - { - return &m_options; - } - protected: - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - PlatformSP platform_sp; - if (target) - { - platform_sp = target->GetPlatform(); - } - if (!platform_sp) - { - platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform(); - } - - if (platform_sp) - { - Error error; - if (args.GetArgumentCount() == 0) - { - if (platform_sp) - { - Stream &ostrm = result.GetOutputStream(); - - lldb::pid_t pid = m_options.match_info.GetProcessInfo().GetProcessID(); - if (pid != LLDB_INVALID_PROCESS_ID) - { - ProcessInstanceInfo proc_info; - if (platform_sp->GetProcessInfo (pid, proc_info)) - { - ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); - proc_info.DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendErrorWithFormat ("no process found with pid = %" PRIu64 "\n", pid); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - ProcessInstanceInfoList proc_infos; - const uint32_t matches = platform_sp->FindProcesses (m_options.match_info, proc_infos); - const char *match_desc = nullptr; - const char *match_name = m_options.match_info.GetProcessInfo().GetName(); - if (match_name && match_name[0]) - { - switch (m_options.match_info.GetNameMatchType()) - { - case eNameMatchIgnore: break; - case eNameMatchEquals: match_desc = "matched"; break; - case eNameMatchContains: match_desc = "contained"; break; - case eNameMatchStartsWith: match_desc = "started with"; break; - case eNameMatchEndsWith: match_desc = "ended with"; break; - case eNameMatchRegularExpression: match_desc = "matched the regular expression"; break; - } - } - - if (matches == 0) - { - if (match_desc) - result.AppendErrorWithFormat ("no processes were found that %s \"%s\" on the \"%s\" platform\n", - match_desc, - match_name, - platform_sp->GetPluginName().GetCString()); - else - result.AppendErrorWithFormat ("no processes were found on the \"%s\" platform\n", platform_sp->GetPluginName().GetCString()); - result.SetStatus (eReturnStatusFailed); - } - else - { - result.AppendMessageWithFormat ("%u matching process%s found on \"%s\"", - matches, - matches > 1 ? "es were" : " was", - platform_sp->GetName().GetCString()); - if (match_desc) - result.AppendMessageWithFormat (" whose name %s \"%s\"", - match_desc, - match_name); - result.AppendMessageWithFormat ("\n"); - ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); - for (uint32_t i=0; i<matches; ++i) - { - proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); - } - } - } - } + bool DoExecute(Args &args, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + PlatformSP platform_sp; + if (target) { + platform_sp = target->GetPlatform(); + } + if (!platform_sp) { + platform_sp = + m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform(); + } + + if (platform_sp) { + Error error; + if (args.GetArgumentCount() == 0) { + if (platform_sp) { + Stream &ostrm = result.GetOutputStream(); + + lldb::pid_t pid = + m_options.match_info.GetProcessInfo().GetProcessID(); + if (pid != LLDB_INVALID_PROCESS_ID) { + ProcessInstanceInfo proc_info; + if (platform_sp->GetProcessInfo(pid, proc_info)) { + ProcessInstanceInfo::DumpTableHeader(ostrm, platform_sp.get(), + m_options.show_args, + m_options.verbose); + proc_info.DumpAsTableRow(ostrm, platform_sp.get(), + m_options.show_args, m_options.verbose); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat( + "no process found with pid = %" PRIu64 "\n", pid); + result.SetStatus(eReturnStatusFailed); } - else - { - result.AppendError ("invalid args: process list takes only options\n"); - result.SetStatus (eReturnStatusFailed); + } else { + ProcessInstanceInfoList proc_infos; + const uint32_t matches = + platform_sp->FindProcesses(m_options.match_info, proc_infos); + const char *match_desc = nullptr; + const char *match_name = + m_options.match_info.GetProcessInfo().GetName(); + if (match_name && match_name[0]) { + switch (m_options.match_info.GetNameMatchType()) { + case eNameMatchIgnore: + break; + case eNameMatchEquals: + match_desc = "matched"; + break; + case eNameMatchContains: + match_desc = "contained"; + break; + case eNameMatchStartsWith: + match_desc = "started with"; + break; + case eNameMatchEndsWith: + match_desc = "ended with"; + break; + case eNameMatchRegularExpression: + match_desc = "matched the regular expression"; + break; + } } - } - else - { - result.AppendError ("no platform is selected\n"); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); - } - - class CommandOptions : public Options - { - public: - CommandOptions() : - Options(), - match_info(), - show_args(false), - verbose(false) - { - static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() { - PosixPlatformCommandOptionValidator *posix_validator = new PosixPlatformCommandOptionValidator(); - for (size_t i=0; g_option_table[i].short_option != 0; ++i) - { - switch (g_option_table[i].short_option) - { - case 'u': - case 'U': - case 'g': - case 'G': - g_option_table[i].validator = posix_validator; - break; - default: - break; - } - } - }); - } - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - bool success = false; - - switch (short_option) - { - case 'p': - match_info.GetProcessInfo().SetProcessID (StringConvert::ToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success)); - if (!success) - error.SetErrorStringWithFormat("invalid process ID string: '%s'", option_arg); - break; - - case 'P': - match_info.GetProcessInfo().SetParentProcessID (StringConvert::ToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success)); - if (!success) - error.SetErrorStringWithFormat("invalid parent process ID string: '%s'", option_arg); - break; - - case 'u': - match_info.GetProcessInfo().SetUserID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success)); - if (!success) - error.SetErrorStringWithFormat("invalid user ID string: '%s'", option_arg); - break; - - case 'U': - match_info.GetProcessInfo().SetEffectiveUserID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success)); - if (!success) - error.SetErrorStringWithFormat("invalid effective user ID string: '%s'", option_arg); - break; - - case 'g': - match_info.GetProcessInfo().SetGroupID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success)); - if (!success) - error.SetErrorStringWithFormat("invalid group ID string: '%s'", option_arg); - break; - - case 'G': - match_info.GetProcessInfo().SetEffectiveGroupID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success)); - if (!success) - error.SetErrorStringWithFormat("invalid effective group ID string: '%s'", option_arg); - break; - - case 'a': - { - TargetSP target_sp = execution_context ? - execution_context->GetTargetSP() : TargetSP(); - DebuggerSP debugger_sp = target_sp ? - target_sp->GetDebugger().shared_from_this() : - DebuggerSP(); - PlatformSP platform_sp = debugger_sp ? - debugger_sp->GetPlatformList().GetSelectedPlatform() : - PlatformSP(); - match_info.GetProcessInfo().GetArchitecture().SetTriple( - option_arg, platform_sp.get()); - } - break; - - case 'n': - match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); - match_info.SetNameMatchType (eNameMatchEquals); - break; - - case 'e': - match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); - match_info.SetNameMatchType (eNameMatchEndsWith); - break; - - case 's': - match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); - match_info.SetNameMatchType (eNameMatchStartsWith); - break; - - case 'c': - match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); - match_info.SetNameMatchType (eNameMatchContains); - break; - - case 'r': - match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); - match_info.SetNameMatchType (eNameMatchRegularExpression); - break; - - case 'A': - show_args = true; - break; - - case 'v': - verbose = true; - break; - - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; + if (matches == 0) { + if (match_desc) + result.AppendErrorWithFormat( + "no processes were found that %s \"%s\" on the \"%s\" " + "platform\n", + match_desc, match_name, + platform_sp->GetPluginName().GetCString()); + else + result.AppendErrorWithFormat( + "no processes were found on the \"%s\" platform\n", + platform_sp->GetPluginName().GetCString()); + result.SetStatus(eReturnStatusFailed); + } else { + result.AppendMessageWithFormat( + "%u matching process%s found on \"%s\"", matches, + matches > 1 ? "es were" : " was", + platform_sp->GetName().GetCString()); + if (match_desc) + result.AppendMessageWithFormat(" whose name %s \"%s\"", + match_desc, match_name); + result.AppendMessageWithFormat("\n"); + ProcessInstanceInfo::DumpTableHeader(ostrm, platform_sp.get(), + m_options.show_args, + m_options.verbose); + for (uint32_t i = 0; i < matches; ++i) { + proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow( + ostrm, platform_sp.get(), m_options.show_args, + m_options.verbose); + } } - - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - match_info.Clear(); - show_args = false; - verbose = false; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - ProcessInstanceInfoMatch match_info; - bool show_args; - bool verbose; - }; - - CommandOptions m_options; + } + } + } else { + result.AppendError("invalid args: process list takes only options\n"); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendError("no platform is selected\n"); + result.SetStatus(eReturnStatusFailed); + } + return result.Succeeded(); + } + + class CommandOptions : public Options { + public: + CommandOptions() + : Options(), match_info(), show_args(false), verbose(false) { + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + PosixPlatformCommandOptionValidator *posix_validator = + new PosixPlatformCommandOptionValidator(); + for (size_t i = 0; g_option_table[i].short_option != 0; ++i) { + switch (g_option_table[i].short_option) { + case 'u': + case 'U': + case 'g': + case 'G': + g_option_table[i].validator = posix_validator; + break; + default: + break; + } + } + }); + } + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + bool success = false; + + switch (short_option) { + case 'p': + match_info.GetProcessInfo().SetProcessID(StringConvert::ToUInt32( + option_arg, LLDB_INVALID_PROCESS_ID, 0, &success)); + if (!success) + error.SetErrorStringWithFormat("invalid process ID string: '%s'", + option_arg); + break; + + case 'P': + match_info.GetProcessInfo().SetParentProcessID(StringConvert::ToUInt32( + option_arg, LLDB_INVALID_PROCESS_ID, 0, &success)); + if (!success) + error.SetErrorStringWithFormat( + "invalid parent process ID string: '%s'", option_arg); + break; + + case 'u': + match_info.GetProcessInfo().SetUserID( + StringConvert::ToUInt32(option_arg, UINT32_MAX, 0, &success)); + if (!success) + error.SetErrorStringWithFormat("invalid user ID string: '%s'", + option_arg); + break; + + case 'U': + match_info.GetProcessInfo().SetEffectiveUserID( + StringConvert::ToUInt32(option_arg, UINT32_MAX, 0, &success)); + if (!success) + error.SetErrorStringWithFormat( + "invalid effective user ID string: '%s'", option_arg); + break; + + case 'g': + match_info.GetProcessInfo().SetGroupID( + StringConvert::ToUInt32(option_arg, UINT32_MAX, 0, &success)); + if (!success) + error.SetErrorStringWithFormat("invalid group ID string: '%s'", + option_arg); + break; + + case 'G': + match_info.GetProcessInfo().SetEffectiveGroupID( + StringConvert::ToUInt32(option_arg, UINT32_MAX, 0, &success)); + if (!success) + error.SetErrorStringWithFormat( + "invalid effective group ID string: '%s'", option_arg); + break; + + case 'a': { + TargetSP target_sp = + execution_context ? execution_context->GetTargetSP() : TargetSP(); + DebuggerSP debugger_sp = + target_sp ? target_sp->GetDebugger().shared_from_this() + : DebuggerSP(); + PlatformSP platform_sp = + debugger_sp ? debugger_sp->GetPlatformList().GetSelectedPlatform() + : PlatformSP(); + match_info.GetProcessInfo().GetArchitecture().SetTriple( + option_arg, platform_sp.get()); + } break; + + case 'n': + match_info.GetProcessInfo().GetExecutableFile().SetFile(option_arg, + false); + match_info.SetNameMatchType(eNameMatchEquals); + break; + + case 'e': + match_info.GetProcessInfo().GetExecutableFile().SetFile(option_arg, + false); + match_info.SetNameMatchType(eNameMatchEndsWith); + break; + + case 's': + match_info.GetProcessInfo().GetExecutableFile().SetFile(option_arg, + false); + match_info.SetNameMatchType(eNameMatchStartsWith); + break; + + case 'c': + match_info.GetProcessInfo().GetExecutableFile().SetFile(option_arg, + false); + match_info.SetNameMatchType(eNameMatchContains); + break; + + case 'r': + match_info.GetProcessInfo().GetExecutableFile().SetFile(option_arg, + false); + match_info.SetNameMatchType(eNameMatchRegularExpression); + break; + + case 'A': + show_args = true; + break; + + case 'v': + verbose = true; + break; + + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; + } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + match_info.Clear(); + show_args = false; + verbose = false; + } + + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + ProcessInstanceInfoMatch match_info; + bool show_args; + bool verbose; + }; + + CommandOptions m_options; }; OptionDefinition -CommandObjectPlatformProcessList::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectPlatformProcessList::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid, "List the process info for a specific process ID."}, {LLDB_OPT_SET_2, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "Find processes with executable basenames that match a string."}, {LLDB_OPT_SET_3, true, "ends-with", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "Find processes with executable basenames that end with a string."}, @@ -1634,596 +1414,519 @@ CommandObjectPlatformProcessList::CommandOptions::g_option_table[] = {LLDB_OPT_SET_FROM_TO(1, 6), false, "show-args", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show process arguments instead of the process executable basename."}, {LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable verbose output."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //---------------------------------------------------------------------- // "platform process info" //---------------------------------------------------------------------- -class CommandObjectPlatformProcessInfo : public CommandObjectParsed -{ +class CommandObjectPlatformProcessInfo : public CommandObjectParsed { public: - CommandObjectPlatformProcessInfo (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "platform process info", - "Get detailed information for one or more process by process ID.", - "platform process info <pid> [<pid> <pid> ...]", - 0) - { - CommandArgumentEntry arg; - CommandArgumentData pid_args; - - // Define the first (and only) variant of this arg. - pid_args.arg_type = eArgTypePid; - pid_args.arg_repetition = eArgRepeatStar; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (pid_args); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - } + CommandObjectPlatformProcessInfo(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "platform process info", + "Get detailed information for one or more process by process ID.", + "platform process info <pid> [<pid> <pid> ...]", 0) { + CommandArgumentEntry arg; + CommandArgumentData pid_args; + + // Define the first (and only) variant of this arg. + pid_args.arg_type = eArgTypePid; + pid_args.arg_repetition = eArgRepeatStar; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(pid_args); - ~CommandObjectPlatformProcessInfo() override = default; + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectPlatformProcessInfo() override = default; protected: - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - PlatformSP platform_sp; - if (target) - { - platform_sp = target->GetPlatform(); - } - if (!platform_sp) - { - platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform(); - } - - if (platform_sp) - { - const size_t argc = args.GetArgumentCount(); - if (argc > 0) - { - Error error; - - if (platform_sp->IsConnected()) - { - Stream &ostrm = result.GetOutputStream(); - bool success; - for (size_t i=0; i<argc; ++ i) - { - const char *arg = args.GetArgumentAtIndex(i); - lldb::pid_t pid = StringConvert::ToUInt32 (arg, LLDB_INVALID_PROCESS_ID, 0, &success); - if (success) - { - ProcessInstanceInfo proc_info; - if (platform_sp->GetProcessInfo (pid, proc_info)) - { - ostrm.Printf ("Process information for process %" PRIu64 ":\n", pid); - proc_info.Dump (ostrm, platform_sp.get()); - } - else - { - ostrm.Printf ("error: no process information is available for process %" PRIu64 "\n", pid); - } - ostrm.EOL(); - } - else - { - result.AppendErrorWithFormat ("invalid process ID argument '%s'", arg); - result.SetStatus (eReturnStatusFailed); - break; - } - } - } - else - { - // Not connected... - result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetPluginName().GetCString()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - // No args - result.AppendError ("one or more process id(s) must be specified"); - result.SetStatus (eReturnStatusFailed); + bool DoExecute(Args &args, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + PlatformSP platform_sp; + if (target) { + platform_sp = target->GetPlatform(); + } + if (!platform_sp) { + platform_sp = + m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform(); + } + + if (platform_sp) { + const size_t argc = args.GetArgumentCount(); + if (argc > 0) { + Error error; + + if (platform_sp->IsConnected()) { + Stream &ostrm = result.GetOutputStream(); + bool success; + for (size_t i = 0; i < argc; ++i) { + const char *arg = args.GetArgumentAtIndex(i); + lldb::pid_t pid = StringConvert::ToUInt32( + arg, LLDB_INVALID_PROCESS_ID, 0, &success); + if (success) { + ProcessInstanceInfo proc_info; + if (platform_sp->GetProcessInfo(pid, proc_info)) { + ostrm.Printf("Process information for process %" PRIu64 ":\n", + pid); + proc_info.Dump(ostrm, platform_sp.get()); + } else { + ostrm.Printf("error: no process information is available for " + "process %" PRIu64 "\n", + pid); + } + ostrm.EOL(); + } else { + result.AppendErrorWithFormat("invalid process ID argument '%s'", + arg); + result.SetStatus(eReturnStatusFailed); + break; } - } - else - { - result.AppendError ("no platform is currently selected"); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + } + } else { + // Not connected... + result.AppendErrorWithFormat( + "not connected to '%s'", + platform_sp->GetPluginName().GetCString()); + result.SetStatus(eReturnStatusFailed); + } + } else { + // No args + result.AppendError("one or more process id(s) must be specified"); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendError("no platform is currently selected"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } }; -class CommandObjectPlatformProcessAttach : public CommandObjectParsed -{ +class CommandObjectPlatformProcessAttach : public CommandObjectParsed { public: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - // Keep default values of all options in one place: OptionParsingStarting () - OptionParsingStarting(nullptr); - } + class CommandOptions : public Options { + public: + CommandOptions() : Options() { + // Keep default values of all options in one place: OptionParsingStarting + // () + OptionParsingStarting(nullptr); + } - ~CommandOptions() override = default; - - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - char short_option = (char) m_getopt_table[option_idx].val; - bool success = false; - switch (short_option) - { - case 'p': - { - lldb::pid_t pid = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success); - if (!success || pid == LLDB_INVALID_PROCESS_ID) - { - error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg); - } - else - { - attach_info.SetProcessID (pid); - } - } - break; - - case 'P': - attach_info.SetProcessPluginName (option_arg); - break; - - case 'n': - attach_info.GetExecutableFile().SetFile(option_arg, false); - break; - - case 'w': - attach_info.SetWaitForLaunch(true); - break; - - default: - error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); - break; - } - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - attach_info.Clear(); - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - bool - HandleOptionArgumentCompletion (Args &input, - int cursor_index, - int char_pos, - OptionElementVector &opt_element_vector, - int opt_element_index, - int match_start_point, - int max_return_elements, - CommandInterpreter &interpreter, - bool &word_complete, - StringList &matches) override - { - 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... - - const OptionDefinition *opt_defs = GetDefinitions(); - if (opt_defs[opt_defs_index].short_option == 'n') - { - // Are we in the name? - - // 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 = input.GetArgumentAtIndex(opt_arg_pos); - - PlatformSP platform_sp(interpreter.GetPlatform(true)); - if (platform_sp) - { - ProcessInstanceInfoList process_infos; - ProcessInstanceInfoMatch match_info; - if (partial_name) - { - match_info.GetProcessInfo().GetExecutableFile().SetFile(partial_name, false); - match_info.SetNameMatchType(eNameMatchStartsWith); - } - platform_sp->FindProcesses (match_info, process_infos); - const uint32_t num_matches = process_infos.GetSize(); - if (num_matches > 0) - { - for (uint32_t i=0; i<num_matches; ++i) - { - matches.AppendString (process_infos.GetProcessNameAtIndex(i), - process_infos.GetProcessNameLengthAtIndex(i)); - } - } - } - } - - return false; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - ProcessAttachInfo attach_info; - }; - - CommandObjectPlatformProcessAttach (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "platform process attach", - "Attach to a process.", - "platform process attach <cmd-options>"), - m_options() - { + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + char short_option = (char)m_getopt_table[option_idx].val; + bool success = false; + switch (short_option) { + case 'p': { + lldb::pid_t pid = StringConvert::ToUInt32( + option_arg, LLDB_INVALID_PROCESS_ID, 0, &success); + if (!success || pid == LLDB_INVALID_PROCESS_ID) { + error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg); + } else { + attach_info.SetProcessID(pid); + } + } break; + + case 'P': + attach_info.SetProcessPluginName(option_arg); + break; + + case 'n': + attach_info.GetExecutableFile().SetFile(option_arg, false); + break; + + case 'w': + attach_info.SetWaitForLaunch(true); + break; + + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", + short_option); + break; + } + return error; } - ~CommandObjectPlatformProcessAttach() override = default; + void OptionParsingStarting(ExecutionContext *execution_context) override { + attach_info.Clear(); + } - bool - DoExecute (Args& command, - CommandReturnObject &result) override - { - PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); - if (platform_sp) - { - Error err; - ProcessSP remote_process_sp = - platform_sp->Attach(m_options.attach_info, m_interpreter.GetDebugger(), nullptr, err); - if (err.Fail()) - { - result.AppendError(err.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - else if (!remote_process_sp) - { - result.AppendError("could not attach: unknown reason"); - result.SetStatus (eReturnStatusFailed); + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + bool HandleOptionArgumentCompletion( + Args &input, int cursor_index, int char_pos, + OptionElementVector &opt_element_vector, int opt_element_index, + int match_start_point, int max_return_elements, + CommandInterpreter &interpreter, bool &word_complete, + StringList &matches) override { + 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... + + const OptionDefinition *opt_defs = GetDefinitions(); + if (opt_defs[opt_defs_index].short_option == 'n') { + // Are we in the name? + + // 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 = input.GetArgumentAtIndex(opt_arg_pos); + + PlatformSP platform_sp(interpreter.GetPlatform(true)); + if (platform_sp) { + ProcessInstanceInfoList process_infos; + ProcessInstanceInfoMatch match_info; + if (partial_name) { + match_info.GetProcessInfo().GetExecutableFile().SetFile( + partial_name, false); + match_info.SetNameMatchType(eNameMatchStartsWith); + } + platform_sp->FindProcesses(match_info, process_infos); + const uint32_t num_matches = process_infos.GetSize(); + if (num_matches > 0) { + for (uint32_t i = 0; i < num_matches; ++i) { + matches.AppendString( + process_infos.GetProcessNameAtIndex(i), + process_infos.GetProcessNameLengthAtIndex(i)); } - else - result.SetStatus (eReturnStatusSuccessFinishResult); + } } - else - { - result.AppendError ("no platform is currently selected"); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + } + + return false; } - - Options * - GetOptions () override - { - return &m_options; + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + ProcessAttachInfo attach_info; + }; + + CommandObjectPlatformProcessAttach(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "platform process attach", + "Attach to a process.", + "platform process attach <cmd-options>"), + m_options() {} + + ~CommandObjectPlatformProcessAttach() override = default; + + bool DoExecute(Args &command, CommandReturnObject &result) override { + PlatformSP platform_sp( + m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (platform_sp) { + Error err; + ProcessSP remote_process_sp = platform_sp->Attach( + m_options.attach_info, m_interpreter.GetDebugger(), nullptr, err); + if (err.Fail()) { + result.AppendError(err.AsCString()); + result.SetStatus(eReturnStatusFailed); + } else if (!remote_process_sp) { + result.AppendError("could not attach: unknown reason"); + result.SetStatus(eReturnStatusFailed); + } else + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendError("no platform is currently selected"); + result.SetStatus(eReturnStatusFailed); } - + return result.Succeeded(); + } + + Options *GetOptions() override { return &m_options; } + protected: - CommandOptions m_options; + CommandOptions m_options; }; OptionDefinition -CommandObjectPlatformProcessAttach::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectPlatformProcessAttach::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, {LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid, "The process ID of an existing process to attach to."}, {LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "The name of the process to attach to."}, {LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Wait for the process with <process-name> to launch."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; -class CommandObjectPlatformProcess : public CommandObjectMultiword -{ +class CommandObjectPlatformProcess : public CommandObjectMultiword { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - CommandObjectPlatformProcess(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "platform process", - "Commands to query, launch and attach to processes on the current platform.", - "platform process [attach|launch|list] ...") - { - LoadSubCommand ("attach", CommandObjectSP (new CommandObjectPlatformProcessAttach (interpreter))); - LoadSubCommand ("launch", CommandObjectSP (new CommandObjectPlatformProcessLaunch (interpreter))); - LoadSubCommand ("info" , CommandObjectSP (new CommandObjectPlatformProcessInfo (interpreter))); - LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformProcessList (interpreter))); - } - - ~CommandObjectPlatformProcess() override = default; + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + CommandObjectPlatformProcess(CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "platform process", + "Commands to query, launch and attach to " + "processes on the current platform.", + "platform process [attach|launch|list] ...") { + LoadSubCommand( + "attach", + CommandObjectSP(new CommandObjectPlatformProcessAttach(interpreter))); + LoadSubCommand( + "launch", + CommandObjectSP(new CommandObjectPlatformProcessLaunch(interpreter))); + LoadSubCommand("info", CommandObjectSP(new CommandObjectPlatformProcessInfo( + interpreter))); + LoadSubCommand("list", CommandObjectSP(new CommandObjectPlatformProcessList( + interpreter))); + } + + ~CommandObjectPlatformProcess() override = default; private: - //------------------------------------------------------------------ - // For CommandObjectPlatform only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformProcess); + //------------------------------------------------------------------ + // For CommandObjectPlatform only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN(CommandObjectPlatformProcess); }; //---------------------------------------------------------------------- // "platform shell" //---------------------------------------------------------------------- -class CommandObjectPlatformShell : public CommandObjectRaw -{ +class CommandObjectPlatformShell : public CommandObjectRaw { public: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options(), - timeout(10) - { - } + class CommandOptions : public Options { + public: + CommandOptions() : Options(), timeout(10) {} + + ~CommandOptions() override = default; + + virtual uint32_t GetNumDefinitions() { return 1; } + + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + Error SetOptionValue(uint32_t option_idx, const char *option_value, + ExecutionContext *execution_context) override { + Error error; + + const char short_option = (char)g_option_table[option_idx].short_option; + + switch (short_option) { + case 't': { + bool success; + timeout = StringConvert::ToUInt32(option_value, 10, 10, &success); + if (!success) + error.SetErrorStringWithFormat( + "could not convert \"%s\" to a numeric value.", option_value); + break; + } + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", + short_option); + break; + } + + return error; + } - ~CommandOptions() override = default; + void OptionParsingStarting(ExecutionContext *execution_context) override {} - virtual uint32_t - GetNumDefinitions () - { - return 1; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - Error - SetOptionValue (uint32_t option_idx, - const char *option_value, - ExecutionContext *execution_context) override - { - Error error; - - const char short_option = (char) g_option_table[option_idx].short_option; - - switch (short_option) - { - case 't': - { - bool success; - timeout = StringConvert::ToUInt32(option_value, 10, 10, &success); - if (!success) - error.SetErrorStringWithFormat("could not convert \"%s\" to a numeric value.", option_value); - break; - } - default: - error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - uint32_t timeout; - }; - - CommandObjectPlatformShell(CommandInterpreter &interpreter) - : CommandObjectRaw(interpreter, "platform shell", "Run a shell command on the current platform.", - "platform shell <shell-command>", 0), - m_options() - { - } + // Options table: Required for subclasses of Options. - ~CommandObjectPlatformShell() override = default; + static OptionDefinition g_option_table[]; + uint32_t timeout; + }; - Options * - GetOptions () override - { - return &m_options; + CommandObjectPlatformShell(CommandInterpreter &interpreter) + : CommandObjectRaw(interpreter, "platform shell", + "Run a shell command on the current platform.", + "platform shell <shell-command>", 0), + m_options() {} + + ~CommandObjectPlatformShell() override = default; + + Options *GetOptions() override { return &m_options; } + + bool DoExecute(const char *raw_command_line, + CommandReturnObject &result) override { + ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext(); + m_options.NotifyOptionParsingStarting(&exe_ctx); + + const char *expr = nullptr; + + // Print out an usage syntax on an empty command line. + if (raw_command_line[0] == '\0') { + result.GetOutputStream().Printf("%s\n", this->GetSyntax()); + return true; } - - bool - DoExecute (const char *raw_command_line, CommandReturnObject &result) override - { - ExecutionContext exe_ctx = - GetCommandInterpreter().GetExecutionContext(); - m_options.NotifyOptionParsingStarting(&exe_ctx); - - const char* expr = nullptr; - - // Print out an usage syntax on an empty command line. - if (raw_command_line[0] == '\0') - { - result.GetOutputStream().Printf("%s\n", this->GetSyntax()); - return true; - } - if (raw_command_line[0] == '-') - { - // We have some options and these options MUST end with --. - const char *end_options = nullptr; - const char *s = raw_command_line; - while (s && s[0]) - { - end_options = ::strstr (s, "--"); - if (end_options) - { - end_options += 2; // Get past the "--" - if (::isspace (end_options[0])) - { - expr = end_options; - while (::isspace (*expr)) - ++expr; - break; - } - } - s = end_options; - } - - if (end_options) - { - Args args (llvm::StringRef(raw_command_line, end_options - raw_command_line)); - if (!ParseOptions (args, result)) - return false; - } - } - - if (expr == nullptr) - expr = raw_command_line; - - PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); - Error error; - if (platform_sp) - { - FileSpec working_dir{}; - std::string output; - int status = -1; - int signo = -1; - error = (platform_sp->RunShellCommand (expr, working_dir, &status, &signo, &output, m_options.timeout)); - if (!output.empty()) - result.GetOutputStream().PutCString(output.c_str()); - if (status > 0) - { - if (signo > 0) - { - const char *signo_cstr = Host::GetSignalAsCString(signo); - if (signo_cstr) - result.GetOutputStream().Printf("error: command returned with status %i and signal %s\n", status, signo_cstr); - else - result.GetOutputStream().Printf("error: command returned with status %i and signal %i\n", status, signo); - } - else - result.GetOutputStream().Printf("error: command returned with status %i\n", status); - } - } - else - { - result.GetOutputStream().Printf("error: cannot run remote shell commands without a platform\n"); - error.SetErrorString("error: cannot run remote shell commands without a platform"); - } + if (raw_command_line[0] == '-') { + // We have some options and these options MUST end with --. + const char *end_options = nullptr; + const char *s = raw_command_line; + while (s && s[0]) { + end_options = ::strstr(s, "--"); + if (end_options) { + end_options += 2; // Get past the "--" + if (::isspace(end_options[0])) { + expr = end_options; + while (::isspace(*expr)) + ++expr; + break; + } + } + s = end_options; + } + + if (end_options) { + Args args( + llvm::StringRef(raw_command_line, end_options - raw_command_line)); + if (!ParseOptions(args, result)) + return false; + } + } - if (error.Fail()) - { - result.AppendError(error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - else - { - result.SetStatus (eReturnStatusSuccessFinishResult); - } - return true; + if (expr == nullptr) + expr = raw_command_line; + + PlatformSP platform_sp( + m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + Error error; + if (platform_sp) { + FileSpec working_dir{}; + std::string output; + int status = -1; + int signo = -1; + error = (platform_sp->RunShellCommand(expr, working_dir, &status, &signo, + &output, m_options.timeout)); + if (!output.empty()) + result.GetOutputStream().PutCString(output.c_str()); + if (status > 0) { + if (signo > 0) { + const char *signo_cstr = Host::GetSignalAsCString(signo); + if (signo_cstr) + result.GetOutputStream().Printf( + "error: command returned with status %i and signal %s\n", + status, signo_cstr); + else + result.GetOutputStream().Printf( + "error: command returned with status %i and signal %i\n", + status, signo); + } else + result.GetOutputStream().Printf( + "error: command returned with status %i\n", status); + } + } else { + result.GetOutputStream().Printf( + "error: cannot run remote shell commands without a platform\n"); + error.SetErrorString( + "error: cannot run remote shell commands without a platform"); + } + + if (error.Fail()) { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } else { + result.SetStatus(eReturnStatusSuccessFinishResult); } + return true; + } - CommandOptions m_options; + CommandOptions m_options; }; -OptionDefinition -CommandObjectPlatformShell::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectPlatformShell::CommandOptions::g_option_table[] = + { + // clang-format off {LLDB_OPT_SET_ALL, false, "timeout", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeValue, "Seconds to wait for the remote host to finish running the command."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //---------------------------------------------------------------------- // "platform install" - install a target to a remote end //---------------------------------------------------------------------- -class CommandObjectPlatformInstall : public CommandObjectParsed -{ +class CommandObjectPlatformInstall : public CommandObjectParsed { public: - CommandObjectPlatformInstall (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "platform target-install", - "Install a target (bundle or executable file) to the remote end.", - "platform target-install <local-thing> <remote-sandbox>", - 0) - { + CommandObjectPlatformInstall(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "platform target-install", + "Install a target (bundle or executable file) to the remote end.", + "platform target-install <local-thing> <remote-sandbox>", 0) {} + + ~CommandObjectPlatformInstall() override = default; + + bool DoExecute(Args &args, CommandReturnObject &result) override { + if (args.GetArgumentCount() != 2) { + result.AppendError("platform target-install takes two arguments"); + result.SetStatus(eReturnStatusFailed); + return false; + } + // TODO: move the bulk of this code over to the platform itself + FileSpec src(args.GetArgumentAtIndex(0), true); + FileSpec dst(args.GetArgumentAtIndex(1), false); + if (!src.Exists()) { + result.AppendError("source location does not exist or is not accessible"); + result.SetStatus(eReturnStatusFailed); + return false; + } + PlatformSP platform_sp( + m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (!platform_sp) { + result.AppendError("no platform currently selected"); + result.SetStatus(eReturnStatusFailed); + return false; } - ~CommandObjectPlatformInstall() override = default; - - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - if (args.GetArgumentCount() != 2) - { - result.AppendError("platform target-install takes two arguments"); - result.SetStatus(eReturnStatusFailed); - return false; - } - // TODO: move the bulk of this code over to the platform itself - FileSpec src(args.GetArgumentAtIndex(0), true); - FileSpec dst(args.GetArgumentAtIndex(1), false); - if (!src.Exists()) - { - result.AppendError("source location does not exist or is not accessible"); - result.SetStatus(eReturnStatusFailed); - return false; - } - PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); - if (!platform_sp) - { - result.AppendError ("no platform currently selected"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - Error error = platform_sp->Install(src, dst); - if (error.Success()) - { - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendErrorWithFormat("install failed: %s", error.AsCString()); - result.SetStatus(eReturnStatusFailed); - } - return result.Succeeded(); + Error error = platform_sp->Install(src, dst); + if (error.Success()) { + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.AppendErrorWithFormat("install failed: %s", error.AsCString()); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } }; CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "platform", "Commands to manage and create platforms.", - "platform [connect|disconnect|info|list|status|select] ...") -{ - LoadSubCommand ("select", CommandObjectSP (new CommandObjectPlatformSelect (interpreter))); - LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformList (interpreter))); - LoadSubCommand ("status", CommandObjectSP (new CommandObjectPlatformStatus (interpreter))); - LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformConnect (interpreter))); - LoadSubCommand ("disconnect", CommandObjectSP (new CommandObjectPlatformDisconnect (interpreter))); - LoadSubCommand ("settings", CommandObjectSP (new CommandObjectPlatformSettings (interpreter))); - LoadSubCommand ("mkdir", CommandObjectSP (new CommandObjectPlatformMkDir (interpreter))); - LoadSubCommand ("file", CommandObjectSP (new CommandObjectPlatformFile (interpreter))); - LoadSubCommand ("get-file", CommandObjectSP (new CommandObjectPlatformGetFile (interpreter))); - LoadSubCommand ("get-size", CommandObjectSP (new CommandObjectPlatformGetSize (interpreter))); - LoadSubCommand ("put-file", CommandObjectSP (new CommandObjectPlatformPutFile (interpreter))); - LoadSubCommand ("process", CommandObjectSP (new CommandObjectPlatformProcess (interpreter))); - LoadSubCommand ("shell", CommandObjectSP (new CommandObjectPlatformShell (interpreter))); - LoadSubCommand ("target-install", CommandObjectSP (new CommandObjectPlatformInstall (interpreter))); + : CommandObjectMultiword( + interpreter, "platform", "Commands to manage and create platforms.", + "platform [connect|disconnect|info|list|status|select] ...") { + LoadSubCommand("select", + CommandObjectSP(new CommandObjectPlatformSelect(interpreter))); + LoadSubCommand("list", + CommandObjectSP(new CommandObjectPlatformList(interpreter))); + LoadSubCommand("status", + CommandObjectSP(new CommandObjectPlatformStatus(interpreter))); + LoadSubCommand("connect", CommandObjectSP( + new CommandObjectPlatformConnect(interpreter))); + LoadSubCommand( + "disconnect", + CommandObjectSP(new CommandObjectPlatformDisconnect(interpreter))); + LoadSubCommand("settings", CommandObjectSP(new CommandObjectPlatformSettings( + interpreter))); + LoadSubCommand("mkdir", + CommandObjectSP(new CommandObjectPlatformMkDir(interpreter))); + LoadSubCommand("file", + CommandObjectSP(new CommandObjectPlatformFile(interpreter))); + LoadSubCommand("get-file", CommandObjectSP(new CommandObjectPlatformGetFile( + interpreter))); + LoadSubCommand("get-size", CommandObjectSP(new CommandObjectPlatformGetSize( + interpreter))); + LoadSubCommand("put-file", CommandObjectSP(new CommandObjectPlatformPutFile( + interpreter))); + LoadSubCommand("process", CommandObjectSP( + new CommandObjectPlatformProcess(interpreter))); + LoadSubCommand("shell", + CommandObjectSP(new CommandObjectPlatformShell(interpreter))); + LoadSubCommand( + "target-install", + CommandObjectSP(new CommandObjectPlatformInstall(interpreter))); } CommandObjectPlatform::~CommandObjectPlatform() = default; diff --git a/lldb/source/Commands/CommandObjectPlatform.h b/lldb/source/Commands/CommandObjectPlatform.h index 023dff9..03b8ca0 100644 --- a/lldb/source/Commands/CommandObjectPlatform.h +++ b/lldb/source/Commands/CommandObjectPlatform.h @@ -23,15 +23,14 @@ namespace lldb_private { // CommandObjectPlatform //------------------------------------------------------------------------- -class CommandObjectPlatform : public CommandObjectMultiword -{ +class CommandObjectPlatform : public CommandObjectMultiword { public: - CommandObjectPlatform(CommandInterpreter &interpreter); + CommandObjectPlatform(CommandInterpreter &interpreter); - ~CommandObjectPlatform() override; + ~CommandObjectPlatform() override; private: - DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatform); + DISALLOW_COPY_AND_ASSIGN(CommandObjectPlatform); }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectPlugin.cpp b/lldb/source/Commands/CommandObjectPlugin.cpp index 8d1a5a5..598b5da 100644 --- a/lldb/source/Commands/CommandObjectPlugin.cpp +++ b/lldb/source/Commands/CommandObjectPlugin.cpp @@ -19,91 +19,78 @@ using namespace lldb; using namespace lldb_private; -class CommandObjectPluginLoad : public CommandObjectParsed -{ +class CommandObjectPluginLoad : public CommandObjectParsed { public: - CommandObjectPluginLoad (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "plugin load", + CommandObjectPluginLoad(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "plugin load", "Import a dylib that implements an LLDB plugin.", - nullptr) - { - CommandArgumentEntry arg1; - CommandArgumentData cmd_arg; - - // Define the first (and only) variant of this arg. - cmd_arg.arg_type = eArgTypeFilename; - cmd_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg1.push_back (cmd_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg1); - } + nullptr) { + CommandArgumentEntry arg1; + CommandArgumentData cmd_arg; - ~CommandObjectPluginLoad() override = default; - - int - HandleArgumentCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - OptionElementVector &opt_element_vector, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) override - { - std::string completion_str (input.GetArgumentAtIndex(cursor_index)); - completion_str.erase (cursor_char_position); - - CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(), - CommandCompletions::eDiskFileCompletion, - completion_str.c_str(), - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - return matches.GetSize(); - } + // Define the first (and only) variant of this arg. + cmd_arg.arg_type = eArgTypeFilename; + cmd_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg1.push_back(cmd_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg1); + } + + ~CommandObjectPluginLoad() override = default; + + int HandleArgumentCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, int max_return_elements, + bool &word_complete, + StringList &matches) override { + std::string completion_str(input.GetArgumentAtIndex(cursor_index)); + completion_str.erase(cursor_char_position); + + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, + completion_str.c_str(), match_start_point, max_return_elements, nullptr, + word_complete, matches); + return matches.GetSize(); + } protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - size_t argc = command.GetArgumentCount(); - - if (argc != 1) - { - result.AppendError ("'plugin load' requires one argument"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - const char* path = command.GetArgumentAtIndex(0); - - Error error; - - FileSpec dylib_fspec(path,true); - - if (m_interpreter.GetDebugger().LoadPlugin(dylib_fspec, error)) - result.SetStatus(eReturnStatusSuccessFinishResult); - else - { - result.AppendError(error.AsCString()); - result.SetStatus(eReturnStatusFailed); - } - - return result.Succeeded(); + bool DoExecute(Args &command, CommandReturnObject &result) override { + size_t argc = command.GetArgumentCount(); + + if (argc != 1) { + result.AppendError("'plugin load' requires one argument"); + result.SetStatus(eReturnStatusFailed); + return false; } + + const char *path = command.GetArgumentAtIndex(0); + + Error error; + + FileSpec dylib_fspec(path, true); + + if (m_interpreter.GetDebugger().LoadPlugin(dylib_fspec, error)) + result.SetStatus(eReturnStatusSuccessFinishResult); + else { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + + return result.Succeeded(); + } }; CommandObjectPlugin::CommandObjectPlugin(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "plugin", "Commands for managing LLDB plugins.", - "plugin <subcommand> [<subcommand-options>]") -{ - LoadSubCommand ("load", CommandObjectSP (new CommandObjectPluginLoad (interpreter))); + : CommandObjectMultiword(interpreter, "plugin", + "Commands for managing LLDB plugins.", + "plugin <subcommand> [<subcommand-options>]") { + LoadSubCommand("load", + CommandObjectSP(new CommandObjectPluginLoad(interpreter))); } - + CommandObjectPlugin::~CommandObjectPlugin() = default; diff --git a/lldb/source/Commands/CommandObjectPlugin.h b/lldb/source/Commands/CommandObjectPlugin.h index 0a96041..d67aa43 100644 --- a/lldb/source/Commands/CommandObjectPlugin.h +++ b/lldb/source/Commands/CommandObjectPlugin.h @@ -16,19 +16,18 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-types.h" #include "lldb/Interpreter/CommandObjectMultiword.h" +#include "lldb/lldb-types.h" namespace lldb_private { - - class CommandObjectPlugin : public CommandObjectMultiword - { - public: - CommandObjectPlugin (CommandInterpreter &interpreter); - - ~CommandObjectPlugin() override; - }; - + +class CommandObjectPlugin : public CommandObjectMultiword { +public: + CommandObjectPlugin(CommandInterpreter &interpreter); + + ~CommandObjectPlugin() override; +}; + } // namespace lldb_private #endif // liblldb_CommandObjectPlugin_h_ diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp index 6d97dbf..77305fcef 100644 --- a/lldb/source/Commands/CommandObjectProcess.cpp +++ b/lldb/source/Commands/CommandObjectProcess.cpp @@ -15,15 +15,15 @@ #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Breakpoint/BreakpointSite.h" -#include "lldb/Core/State.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Core/State.h" #include "lldb/Host/Host.h" #include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/Args.h" -#include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Interpreter/Options.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Target/StopInfo.h" @@ -34,284 +34,273 @@ using namespace lldb; using namespace lldb_private; -class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed -{ +class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed { public: - CommandObjectProcessLaunchOrAttach (CommandInterpreter &interpreter, - const char *name, - const char *help, - const char *syntax, - uint32_t flags, - const char *new_process_action) : - CommandObjectParsed (interpreter, name, help, syntax, flags), - m_new_process_action (new_process_action) {} + CommandObjectProcessLaunchOrAttach(CommandInterpreter &interpreter, + const char *name, const char *help, + const char *syntax, uint32_t flags, + const char *new_process_action) + : CommandObjectParsed(interpreter, name, help, syntax, flags), + m_new_process_action(new_process_action) {} - ~CommandObjectProcessLaunchOrAttach() override = default; + ~CommandObjectProcessLaunchOrAttach() override = default; protected: - bool - StopProcessIfNecessary (Process *process, StateType &state, CommandReturnObject &result) - { - state = eStateInvalid; - if (process) - { - state = process->GetState(); - - if (process->IsAlive() && state != eStateConnected) - { - char message[1024]; - if (process->GetState() == eStateAttaching) - ::snprintf (message, sizeof(message), "There is a pending attach, abort it and %s?", m_new_process_action.c_str()); - else if (process->GetShouldDetach()) - ::snprintf (message, sizeof(message), "There is a running process, detach from it and %s?", m_new_process_action.c_str()); - else - ::snprintf (message, sizeof(message), "There is a running process, kill it and %s?", m_new_process_action.c_str()); - - if (!m_interpreter.Confirm (message, true)) - { - result.SetStatus (eReturnStatusFailed); - return false; - } - else - { - if (process->GetShouldDetach()) - { - bool keep_stopped = false; - Error detach_error (process->Detach(keep_stopped)); - if (detach_error.Success()) - { - result.SetStatus (eReturnStatusSuccessFinishResult); - process = nullptr; - } - else - { - result.AppendErrorWithFormat ("Failed to detach from process: %s\n", detach_error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - Error destroy_error (process->Destroy(false)); - if (destroy_error.Success()) - { - result.SetStatus (eReturnStatusSuccessFinishResult); - process = nullptr; - } - else - { - result.AppendErrorWithFormat ("Failed to kill process: %s\n", destroy_error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - } + bool StopProcessIfNecessary(Process *process, StateType &state, + CommandReturnObject &result) { + state = eStateInvalid; + if (process) { + state = process->GetState(); + + if (process->IsAlive() && state != eStateConnected) { + char message[1024]; + if (process->GetState() == eStateAttaching) + ::snprintf(message, sizeof(message), + "There is a pending attach, abort it and %s?", + m_new_process_action.c_str()); + else if (process->GetShouldDetach()) + ::snprintf(message, sizeof(message), + "There is a running process, detach from it and %s?", + m_new_process_action.c_str()); + else + ::snprintf(message, sizeof(message), + "There is a running process, kill it and %s?", + m_new_process_action.c_str()); + + if (!m_interpreter.Confirm(message, true)) { + result.SetStatus(eReturnStatusFailed); + return false; + } else { + if (process->GetShouldDetach()) { + bool keep_stopped = false; + Error detach_error(process->Detach(keep_stopped)); + if (detach_error.Success()) { + result.SetStatus(eReturnStatusSuccessFinishResult); + process = nullptr; + } else { + result.AppendErrorWithFormat( + "Failed to detach from process: %s\n", + detach_error.AsCString()); + result.SetStatus(eReturnStatusFailed); } + } else { + Error destroy_error(process->Destroy(false)); + if (destroy_error.Success()) { + result.SetStatus(eReturnStatusSuccessFinishResult); + process = nullptr; + } else { + result.AppendErrorWithFormat("Failed to kill process: %s\n", + destroy_error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + } } - return result.Succeeded(); + } } + return result.Succeeded(); + } - std::string m_new_process_action; + std::string m_new_process_action; }; //------------------------------------------------------------------------- // CommandObjectProcessLaunch //------------------------------------------------------------------------- #pragma mark CommandObjectProcessLaunch -class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach -{ +class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach { public: - CommandObjectProcessLaunch (CommandInterpreter &interpreter) : - CommandObjectProcessLaunchOrAttach(interpreter, - "process launch", - "Launch the executable in the debugger.", - nullptr, - eCommandRequiresTarget, - "restart"), - m_options() - { - CommandArgumentEntry arg; - CommandArgumentData run_args_arg; - - // Define the first (and only) variant of this arg. - run_args_arg.arg_type = eArgTypeRunArgs; - run_args_arg.arg_repetition = eArgRepeatOptional; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (run_args_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - } + CommandObjectProcessLaunch(CommandInterpreter &interpreter) + : CommandObjectProcessLaunchOrAttach( + interpreter, "process launch", + "Launch the executable in the debugger.", nullptr, + eCommandRequiresTarget, "restart"), + m_options() { + CommandArgumentEntry arg; + CommandArgumentData run_args_arg; + + // Define the first (and only) variant of this arg. + run_args_arg.arg_type = eArgTypeRunArgs; + run_args_arg.arg_repetition = eArgRepeatOptional; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(run_args_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectProcessLaunch() override = default; + + int HandleArgumentCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, int max_return_elements, + bool &word_complete, + StringList &matches) override { + std::string completion_str(input.GetArgumentAtIndex(cursor_index)); + completion_str.erase(cursor_char_position); + + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, + completion_str.c_str(), match_start_point, max_return_elements, nullptr, + word_complete, matches); + return matches.GetSize(); + } + + Options *GetOptions() override { return &m_options; } + + const char *GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override { + // No repeat for "process launch"... + return ""; + } - ~CommandObjectProcessLaunch() override = default; - - int - HandleArgumentCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - OptionElementVector &opt_element_vector, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) override - { - std::string completion_str (input.GetArgumentAtIndex(cursor_index)); - completion_str.erase (cursor_char_position); - - CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(), - CommandCompletions::eDiskFileCompletion, - completion_str.c_str(), - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - return matches.GetSize(); +protected: + bool DoExecute(Args &launch_args, CommandReturnObject &result) override { + Debugger &debugger = m_interpreter.GetDebugger(); + Target *target = debugger.GetSelectedTarget().get(); + // If our listener is nullptr, users aren't allows to launch + ModuleSP exe_module_sp = target->GetExecutableModule(); + + if (exe_module_sp == nullptr) { + result.AppendError("no file in target, create a debug target using the " + "'target create' command"); + result.SetStatus(eReturnStatusFailed); + return false; } - Options * - GetOptions () override - { - return &m_options; + StateType state = eStateInvalid; + + if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result)) + return false; + + const char *target_settings_argv0 = target->GetArg0(); + + // Determine whether we will disable ASLR or leave it in the default state + // (i.e. enabled if the platform supports it). + // First check if the process launch options explicitly turn on/off + // disabling ASLR. If so, use that setting; + // otherwise, use the 'settings target.disable-aslr' setting. + bool disable_aslr = false; + if (m_options.disable_aslr != eLazyBoolCalculate) { + // The user specified an explicit setting on the process launch line. Use + // it. + disable_aslr = (m_options.disable_aslr == eLazyBoolYes); + } else { + // The user did not explicitly specify whether to disable ASLR. Fall back + // to the target.disable-aslr setting. + disable_aslr = target->GetDisableASLR(); } - const char * - GetRepeatCommand (Args ¤t_command_args, uint32_t index) override - { - // No repeat for "process launch"... - return ""; + if (disable_aslr) + m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR); + else + m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR); + + if (target->GetDetachOnError()) + m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError); + + if (target->GetDisableSTDIO()) + m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO); + + Args environment; + target->GetEnvironmentAsArgs(environment); + if (environment.GetArgumentCount() > 0) + m_options.launch_info.GetEnvironmentEntries().AppendArguments( + environment); + + if (target_settings_argv0) { + m_options.launch_info.GetArguments().AppendArgument( + target_settings_argv0); + m_options.launch_info.SetExecutableFile( + exe_module_sp->GetPlatformFileSpec(), false); + } else { + m_options.launch_info.SetExecutableFile( + exe_module_sp->GetPlatformFileSpec(), true); } -protected: - bool - DoExecute (Args& launch_args, CommandReturnObject &result) override - { - Debugger &debugger = m_interpreter.GetDebugger(); - Target *target = debugger.GetSelectedTarget().get(); - // If our listener is nullptr, users aren't allows to launch - ModuleSP exe_module_sp = target->GetExecutableModule(); - - if (exe_module_sp == nullptr) - { - result.AppendError ("no file in target, create a debug target using the 'target create' command"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - StateType state = eStateInvalid; - - if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result)) - return false; - - const char *target_settings_argv0 = target->GetArg0(); - - // Determine whether we will disable ASLR or leave it in the default state (i.e. enabled if the platform supports it). - // First check if the process launch options explicitly turn on/off disabling ASLR. If so, use that setting; - // otherwise, use the 'settings target.disable-aslr' setting. - bool disable_aslr = false; - if (m_options.disable_aslr != eLazyBoolCalculate) - { - // The user specified an explicit setting on the process launch line. Use it. - disable_aslr = (m_options.disable_aslr == eLazyBoolYes); - } - else - { - // The user did not explicitly specify whether to disable ASLR. Fall back to the target.disable-aslr setting. - disable_aslr = target->GetDisableASLR (); - } - - if (disable_aslr) - m_options.launch_info.GetFlags().Set (eLaunchFlagDisableASLR); - else - m_options.launch_info.GetFlags().Clear (eLaunchFlagDisableASLR); - - if (target->GetDetachOnError()) - m_options.launch_info.GetFlags().Set (eLaunchFlagDetachOnError); - - if (target->GetDisableSTDIO()) - m_options.launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO); - - Args environment; - target->GetEnvironmentAsArgs (environment); - if (environment.GetArgumentCount() > 0) - m_options.launch_info.GetEnvironmentEntries ().AppendArguments (environment); - - if (target_settings_argv0) - { - m_options.launch_info.GetArguments().AppendArgument (target_settings_argv0); - m_options.launch_info.SetExecutableFile(exe_module_sp->GetPlatformFileSpec(), false); - } - else - { - m_options.launch_info.SetExecutableFile(exe_module_sp->GetPlatformFileSpec(), true); - } - - if (launch_args.GetArgumentCount() == 0) - { - m_options.launch_info.GetArguments().AppendArguments (target->GetProcessLaunchInfo().GetArguments()); - } - else - { - m_options.launch_info.GetArguments().AppendArguments (launch_args); - // Save the arguments for subsequent runs in the current target. - target->SetRunArguments (launch_args); - } + if (launch_args.GetArgumentCount() == 0) { + m_options.launch_info.GetArguments().AppendArguments( + target->GetProcessLaunchInfo().GetArguments()); + } else { + m_options.launch_info.GetArguments().AppendArguments(launch_args); + // Save the arguments for subsequent runs in the current target. + target->SetRunArguments(launch_args); + } - StreamString stream; - Error error = target->Launch(m_options.launch_info, &stream); - - if (error.Success()) - { - ProcessSP process_sp (target->GetProcessSP()); - if (process_sp) - { - // There is a race condition where this thread will return up the call stack to the main command - // handler and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has - // a chance to call PushProcessIOHandler(). - process_sp->SyncIOHandler (0, 2000); - - const char *data = stream.GetData(); - if (data && strlen(data) > 0) - result.AppendMessage(stream.GetData()); - const char *archname = exe_module_sp->GetArchitecture().GetArchitectureName(); - result.AppendMessageWithFormat ("Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(), exe_module_sp->GetFileSpec().GetPath().c_str(), archname); - result.SetStatus (eReturnStatusSuccessFinishResult); - result.SetDidChangeProcessState (true); - } - else - { - result.AppendError("no error returned from Target::Launch, and target has no process"); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendError(error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + StreamString stream; + Error error = target->Launch(m_options.launch_info, &stream); + + if (error.Success()) { + ProcessSP process_sp(target->GetProcessSP()); + if (process_sp) { + // There is a race condition where this thread will return up the call + // stack to the main command + // handler and show an (lldb) prompt before HandlePrivateEvent (from + // PrivateStateThread) has + // a chance to call PushProcessIOHandler(). + process_sp->SyncIOHandler(0, 2000); + + const char *data = stream.GetData(); + if (data && strlen(data) > 0) + result.AppendMessage(stream.GetData()); + const char *archname = + exe_module_sp->GetArchitecture().GetArchitectureName(); + result.AppendMessageWithFormat( + "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(), + exe_module_sp->GetFileSpec().GetPath().c_str(), archname); + result.SetStatus(eReturnStatusSuccessFinishResult); + result.SetDidChangeProcessState(true); + } else { + result.AppendError( + "no error returned from Target::Launch, and target has no process"); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } protected: - ProcessLaunchCommandOptions m_options; + ProcessLaunchCommandOptions m_options; }; - //#define SET1 LLDB_OPT_SET_1 //#define SET2 LLDB_OPT_SET_2 //#define SET3 LLDB_OPT_SET_3 // -//OptionDefinition -//CommandObjectProcessLaunch::CommandOptions::g_option_table[] = +// OptionDefinition +// CommandObjectProcessLaunch::CommandOptions::g_option_table[] = //{ // // clang-format off -// {SET1 | SET2 | SET3, false, "stop-at-entry", 's', OptionParser::eNoArgument, nullptr, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."}, -// {SET1, false, "stdin", 'i', OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, "Redirect stdin for the process to <path>."}, -// {SET1, false, "stdout", 'o', OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, "Redirect stdout for the process to <path>."}, -// {SET1, false, "stderr", 'e', OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, "Redirect stderr for the process to <path>."}, -// {SET1 | SET2 | SET3, false, "plugin", 'p', OptionParser::eRequiredArgument, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, -// { SET2, false, "tty", 't', OptionParser::eOptionalArgument, nullptr, 0, eArgTypeDirectoryName, "Start the process in a terminal. If <path> is specified, look for a terminal whose name contains <path>, else start the process in a new terminal."}, -// { SET3, false, "no-stdio", 'n', OptionParser::eNoArgument, nullptr, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."}, -// {SET1 | SET2 | SET3, false, "working-dir", 'w', OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, "Set the current working directory to <path> when running the inferior."}, +// {SET1 | SET2 | SET3, false, "stop-at-entry", 's', OptionParser::eNoArgument, +// nullptr, 0, eArgTypeNone, "Stop at the entry point of the program +// when launching a process."}, +// {SET1, false, "stdin", 'i', +// OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, +// "Redirect stdin for the process to <path>."}, +// {SET1, false, "stdout", 'o', +// OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, +// "Redirect stdout for the process to <path>."}, +// {SET1, false, "stderr", 'e', +// OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, +// "Redirect stderr for the process to <path>."}, +// {SET1 | SET2 | SET3, false, "plugin", 'p', +// OptionParser::eRequiredArgument, nullptr, 0, eArgTypePlugin, "Name of +// the process plugin you want to use."}, +// { SET2, false, "tty", 't', +// OptionParser::eOptionalArgument, nullptr, 0, eArgTypeDirectoryName, "Start +// the process in a terminal. If <path> is specified, look for a terminal whose +// name contains <path>, else start the process in a new terminal."}, +// { SET3, false, "no-stdio", 'n', OptionParser::eNoArgument, +// nullptr, 0, eArgTypeNone, "Do not set up for terminal I/O to go to +// running process."}, +// {SET1 | SET2 | SET3, false, "working-dir", 'w', +// OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, "Set the +// current working directory to <path> when running the inferior."}, // {0, false, nullptr, 0, 0, nullptr, 0, eArgTypeNone, nullptr} // // clang-format on //}; @@ -324,293 +313,255 @@ protected: // CommandObjectProcessAttach //------------------------------------------------------------------------- #pragma mark CommandObjectProcessAttach -class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach -{ +class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach { public: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - // Keep default values of all options in one place: OptionParsingStarting () - OptionParsingStarting(nullptr); - } - - ~CommandOptions() override = default; - - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - bool success = false; - switch (short_option) - { - case 'c': - attach_info.SetContinueOnceAttached(true); - break; - - case 'p': - { - lldb::pid_t pid = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success); - if (!success || pid == LLDB_INVALID_PROCESS_ID) - { - error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg); - } - else - { - attach_info.SetProcessID (pid); - } - } - break; - - case 'P': - attach_info.SetProcessPluginName (option_arg); - break; - - case 'n': - attach_info.GetExecutableFile().SetFile(option_arg, false); - break; - - case 'w': - attach_info.SetWaitForLaunch(true); - break; - - case 'i': - attach_info.SetIgnoreExisting(false); - break; - - default: - error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); - break; - } - return error; - } + class CommandOptions : public Options { + public: + CommandOptions() : Options() { + // Keep default values of all options in one place: OptionParsingStarting + // () + OptionParsingStarting(nullptr); + } - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - attach_info.Clear(); - } + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + bool success = false; + switch (short_option) { + case 'c': + attach_info.SetContinueOnceAttached(true); + break; + + case 'p': { + lldb::pid_t pid = StringConvert::ToUInt32( + option_arg, LLDB_INVALID_PROCESS_ID, 0, &success); + if (!success || pid == LLDB_INVALID_PROCESS_ID) { + error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg); + } else { + attach_info.SetProcessID(pid); + } + } break; + + case 'P': + attach_info.SetProcessPluginName(option_arg); + break; + + case 'n': + attach_info.GetExecutableFile().SetFile(option_arg, false); + break; + + case 'w': + attach_info.SetWaitForLaunch(true); + break; + + case 'i': + attach_info.SetIgnoreExisting(false); + break; + + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", + short_option); + break; + } + return error; + } - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } + void OptionParsingStarting(ExecutionContext *execution_context) override { + attach_info.Clear(); + } - bool - HandleOptionArgumentCompletion (Args &input, - int cursor_index, - int char_pos, - OptionElementVector &opt_element_vector, - int opt_element_index, - int match_start_point, - int max_return_elements, - CommandInterpreter &interpreter, - bool &word_complete, - StringList &matches) override - { - 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... - - const OptionDefinition *opt_defs = GetDefinitions(); - if (opt_defs[opt_defs_index].short_option == 'n') - { - // Are we in the name? - - // 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 = input.GetArgumentAtIndex(opt_arg_pos); - - PlatformSP platform_sp(interpreter.GetPlatform(true)); - if (platform_sp) - { - ProcessInstanceInfoList process_infos; - ProcessInstanceInfoMatch match_info; - if (partial_name) - { - match_info.GetProcessInfo().GetExecutableFile().SetFile(partial_name, false); - match_info.SetNameMatchType(eNameMatchStartsWith); - } - platform_sp->FindProcesses (match_info, process_infos); - const size_t num_matches = process_infos.GetSize(); - if (num_matches > 0) - { - for (size_t i = 0; i < num_matches; ++i) - { - matches.AppendString (process_infos.GetProcessNameAtIndex(i), - process_infos.GetProcessNameLengthAtIndex(i)); - } - } - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + bool HandleOptionArgumentCompletion( + Args &input, int cursor_index, int char_pos, + OptionElementVector &opt_element_vector, int opt_element_index, + int match_start_point, int max_return_elements, + CommandInterpreter &interpreter, bool &word_complete, + StringList &matches) override { + 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... + + const OptionDefinition *opt_defs = GetDefinitions(); + if (opt_defs[opt_defs_index].short_option == 'n') { + // Are we in the name? + + // 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 = input.GetArgumentAtIndex(opt_arg_pos); + + PlatformSP platform_sp(interpreter.GetPlatform(true)); + if (platform_sp) { + ProcessInstanceInfoList process_infos; + ProcessInstanceInfoMatch match_info; + if (partial_name) { + match_info.GetProcessInfo().GetExecutableFile().SetFile( + partial_name, false); + match_info.SetNameMatchType(eNameMatchStartsWith); + } + platform_sp->FindProcesses(match_info, process_infos); + const size_t num_matches = process_infos.GetSize(); + if (num_matches > 0) { + for (size_t i = 0; i < num_matches; ++i) { + matches.AppendString( + process_infos.GetProcessNameAtIndex(i), + process_infos.GetProcessNameLengthAtIndex(i)); } - - return false; + } } + } - // Options table: Required for subclasses of Options. + return false; + } - static OptionDefinition g_option_table[]; + // Options table: Required for subclasses of Options. - // Instance variables to hold the values for command options. + static OptionDefinition g_option_table[]; - ProcessAttachInfo attach_info; - }; + // Instance variables to hold the values for command options. - CommandObjectProcessAttach (CommandInterpreter &interpreter) : - CommandObjectProcessLaunchOrAttach (interpreter, - "process attach", - "Attach to a process.", - "process attach <cmd-options>", - 0, - "attach"), - m_options() - { - } + ProcessAttachInfo attach_info; + }; - ~CommandObjectProcessAttach() override = default; + CommandObjectProcessAttach(CommandInterpreter &interpreter) + : CommandObjectProcessLaunchOrAttach( + interpreter, "process attach", "Attach to a process.", + "process attach <cmd-options>", 0, "attach"), + m_options() {} - Options * - GetOptions () override - { - return &m_options; - } + ~CommandObjectProcessAttach() override = default; -protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); - - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - // N.B. The attach should be synchronous. It doesn't help much to get the prompt back between initiating the attach - // and the target actually stopping. So even if the interpreter is set to be asynchronous, we wait for the stop - // ourselves here. - - StateType state = eStateInvalid; - Process *process = m_exe_ctx.GetProcessPtr(); - - if (!StopProcessIfNecessary (process, state, result)) - return false; - - if (target == nullptr) - { - // If there isn't a current target create one. - TargetSP new_target_sp; - Error error; - - error = m_interpreter.GetDebugger().GetTargetList().CreateTarget(m_interpreter.GetDebugger(), - nullptr, - nullptr, - false, - nullptr, // No platform options - new_target_sp); - target = new_target_sp.get(); - if (target == nullptr || error.Fail()) - { - result.AppendError(error.AsCString("Error creating target")); - return false; - } - m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target); - } - - // Record the old executable module, we want to issue a warning if the process of attaching changed the - // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.) - - ModuleSP old_exec_module_sp = target->GetExecutableModule(); - ArchSpec old_arch_spec = target->GetArchitecture(); - - if (command.GetArgumentCount()) - { - result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); - result.SetStatus (eReturnStatusFailed); - return false; - } + Options *GetOptions() override { return &m_options; } - m_interpreter.UpdateExecutionContext(nullptr); - StreamString stream; - const auto error = target->Attach(m_options.attach_info, &stream); - if (error.Success()) - { - ProcessSP process_sp (target->GetProcessSP()); - if (process_sp) - { - if (stream.GetData()) - result.AppendMessage(stream.GetData()); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - result.SetDidChangeProcessState (true); - result.SetAbnormalStopWasExpected(true); - } - else - { - result.AppendError("no error returned from Target::Attach, and target has no process"); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendErrorWithFormat ("attach failed: %s\n", error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + PlatformSP platform_sp( + m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + // N.B. The attach should be synchronous. It doesn't help much to get the + // prompt back between initiating the attach + // and the target actually stopping. So even if the interpreter is set to + // be asynchronous, we wait for the stop + // ourselves here. + + StateType state = eStateInvalid; + Process *process = m_exe_ctx.GetProcessPtr(); + + if (!StopProcessIfNecessary(process, state, result)) + return false; + + if (target == nullptr) { + // If there isn't a current target create one. + TargetSP new_target_sp; + Error error; + + error = m_interpreter.GetDebugger().GetTargetList().CreateTarget( + m_interpreter.GetDebugger(), nullptr, nullptr, false, + nullptr, // No platform options + new_target_sp); + target = new_target_sp.get(); + if (target == nullptr || error.Fail()) { + result.AppendError(error.AsCString("Error creating target")); + return false; + } + m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target); + } - if (!result.Succeeded()) - return false; - - // Okay, we're done. Last step is to warn if the executable module has changed: - char new_path[PATH_MAX]; - ModuleSP new_exec_module_sp (target->GetExecutableModule()); - if (!old_exec_module_sp) - { - // We might not have a module if we attached to a raw pid... - if (new_exec_module_sp) - { - new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); - result.AppendMessageWithFormat("Executable module set to \"%s\".\n", new_path); - } - } - else if (old_exec_module_sp->GetFileSpec() != new_exec_module_sp->GetFileSpec()) - { - char old_path[PATH_MAX]; + // Record the old executable module, we want to issue a warning if the + // process of attaching changed the + // current executable (like somebody said "file foo" then attached to a PID + // whose executable was bar.) - old_exec_module_sp->GetFileSpec().GetPath (old_path, PATH_MAX); - new_exec_module_sp->GetFileSpec().GetPath (new_path, PATH_MAX); + ModuleSP old_exec_module_sp = target->GetExecutableModule(); + ArchSpec old_arch_spec = target->GetArchitecture(); - result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n", - old_path, new_path); - } + if (command.GetArgumentCount()) { + result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", + m_cmd_name.c_str(), m_cmd_syntax.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } - if (!old_arch_spec.IsValid()) - { - result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().GetTriple().getTriple().c_str()); - } - else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) - { - result.AppendWarningWithFormat("Architecture changed from %s to %s.\n", - old_arch_spec.GetTriple().getTriple().c_str(), - target->GetArchitecture().GetTriple().getTriple().c_str()); - } + m_interpreter.UpdateExecutionContext(nullptr); + StreamString stream; + const auto error = target->Attach(m_options.attach_info, &stream); + if (error.Success()) { + ProcessSP process_sp(target->GetProcessSP()); + if (process_sp) { + if (stream.GetData()) + result.AppendMessage(stream.GetData()); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + result.SetDidChangeProcessState(true); + result.SetAbnormalStopWasExpected(true); + } else { + result.AppendError( + "no error returned from Target::Attach, and target has no process"); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } - // This supports the use-case scenario of immediately continuing the process once attached. - if (m_options.attach_info.GetContinueOnceAttached()) - m_interpreter.HandleCommand("process continue", eLazyBoolNo, result); + if (!result.Succeeded()) + return false; + + // Okay, we're done. Last step is to warn if the executable module has + // changed: + char new_path[PATH_MAX]; + ModuleSP new_exec_module_sp(target->GetExecutableModule()); + if (!old_exec_module_sp) { + // We might not have a module if we attached to a raw pid... + if (new_exec_module_sp) { + new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); + result.AppendMessageWithFormat("Executable module set to \"%s\".\n", + new_path); + } + } else if (old_exec_module_sp->GetFileSpec() != + new_exec_module_sp->GetFileSpec()) { + char old_path[PATH_MAX]; + + old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX); + new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); + + result.AppendWarningWithFormat( + "Executable module changed from \"%s\" to \"%s\".\n", old_path, + new_path); + } - return result.Succeeded(); + if (!old_arch_spec.IsValid()) { + result.AppendMessageWithFormat( + "Architecture set to: %s.\n", + target->GetArchitecture().GetTriple().getTriple().c_str()); + } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) { + result.AppendWarningWithFormat( + "Architecture changed from %s to %s.\n", + old_arch_spec.GetTriple().getTriple().c_str(), + target->GetArchitecture().GetTriple().getTriple().c_str()); } - - CommandOptions m_options; + + // This supports the use-case scenario of immediately continuing the process + // once attached. + if (m_options.attach_info.GetContinueOnceAttached()) + m_interpreter.HandleCommand("process continue", eLazyBoolNo, result); + + return result.Succeeded(); + } + + CommandOptions m_options; }; -OptionDefinition -CommandObjectProcessAttach::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectProcessAttach::CommandOptions::g_option_table[] = + { + // clang-format off {LLDB_OPT_SET_ALL, false, "continue", 'c', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Immediately continue the process once attached."}, {LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, {LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid, "The process ID of an existing process to attach to."}, @@ -618,7 +569,7 @@ CommandObjectProcessAttach::CommandOptions::g_option_table[] = {LLDB_OPT_SET_2, false, "include-existing", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Include existing processes when doing attach -w."}, {LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Wait for the process with <process-name> to launch."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- @@ -626,193 +577,170 @@ CommandObjectProcessAttach::CommandOptions::g_option_table[] = //------------------------------------------------------------------------- #pragma mark CommandObjectProcessContinue -class CommandObjectProcessContinue : public CommandObjectParsed -{ +class CommandObjectProcessContinue : public CommandObjectParsed { public: - CommandObjectProcessContinue (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "process continue", - "Continue execution of all threads in the current process.", - "process continue", - eCommandRequiresProcess | - eCommandTryTargetAPILock | - eCommandProcessMustBeLaunched | - eCommandProcessMustBePaused ), - m_options() - { - } + CommandObjectProcessContinue(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "process continue", + "Continue execution of all threads in the current process.", + "process continue", + eCommandRequiresProcess | eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), + m_options() {} - ~CommandObjectProcessContinue() override = default; + ~CommandObjectProcessContinue() override = default; protected: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - // Keep default values of all options in one place: OptionParsingStarting () - OptionParsingStarting(nullptr); - } - - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - bool success = false; - switch (short_option) - { - case 'i': - m_ignore = StringConvert::ToUInt32 (option_arg, 0, 0, &success); - if (!success) - error.SetErrorStringWithFormat ("invalid value for ignore option: \"%s\", should be a number.", option_arg); - break; - - default: - error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); - break; - } - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_ignore = 0; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; + class CommandOptions : public Options { + public: + CommandOptions() : Options() { + // Keep default values of all options in one place: OptionParsingStarting + // () + OptionParsingStarting(nullptr); + } - uint32_t m_ignore; - }; - - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Process *process = m_exe_ctx.GetProcessPtr(); - bool synchronous_execution = m_interpreter.GetSynchronous (); - StateType state = process->GetState(); - if (state == eStateStopped) - { - if (command.GetArgumentCount() != 0) - { - result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str()); - result.SetStatus (eReturnStatusFailed); - return false; - } + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + bool success = false; + switch (short_option) { + case 'i': + m_ignore = StringConvert::ToUInt32(option_arg, 0, 0, &success); + if (!success) + error.SetErrorStringWithFormat( + "invalid value for ignore option: \"%s\", should be a number.", + option_arg); + break; + + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", + short_option); + break; + } + return error; + } - if (m_options.m_ignore > 0) - { - ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this()); - if (sel_thread_sp) - { - StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo(); - if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint) - { - lldb::break_id_t bp_site_id = (lldb::break_id_t)stop_info_sp->GetValue(); - BreakpointSiteSP bp_site_sp(process->GetBreakpointSiteList().FindByID(bp_site_id)); - if (bp_site_sp) - { - const size_t num_owners = bp_site_sp->GetNumberOfOwners(); - for (size_t i = 0; i < num_owners; i++) - { - Breakpoint &bp_ref = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); - if (!bp_ref.IsInternal()) - { - bp_ref.SetIgnoreCount(m_options.m_ignore); - } - } - } - } - } - } - - { // Scope for thread list mutex: - std::lock_guard<std::recursive_mutex> guard(process->GetThreadList().GetMutex()); - const uint32_t num_threads = process->GetThreadList().GetSize(); - - // Set the actions that the threads should each take when resuming - for (uint32_t idx=0; idx<num_threads; ++idx) - { - const bool override_suspend = false; - process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning, override_suspend); - } - } + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_ignore = 0; + } - const uint32_t iohandler_id = process->GetIOHandlerID(); - - StreamString stream; - Error error; - if (synchronous_execution) - error = process->ResumeSynchronous (&stream); - else - error = process->Resume (); - - if (error.Success()) - { - // There is a race condition where this thread will return up the call stack to the main command - // handler and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has - // a chance to call PushProcessIOHandler(). - process->SyncIOHandler(iohandler_id, 2000); - - result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID()); - if (synchronous_execution) - { - // If any state changed events had anything to say, add that to the result - if (stream.GetData()) - result.AppendMessage(stream.GetData()); - - result.SetDidChangeProcessState (true); - result.SetStatus (eReturnStatusSuccessFinishNoResult); + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + uint32_t m_ignore; + }; + + bool DoExecute(Args &command, CommandReturnObject &result) override { + Process *process = m_exe_ctx.GetProcessPtr(); + bool synchronous_execution = m_interpreter.GetSynchronous(); + StateType state = process->GetState(); + if (state == eStateStopped) { + if (command.GetArgumentCount() != 0) { + result.AppendErrorWithFormat( + "The '%s' command does not take any arguments.\n", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (m_options.m_ignore > 0) { + ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this()); + if (sel_thread_sp) { + StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo(); + if (stop_info_sp && + stop_info_sp->GetStopReason() == eStopReasonBreakpoint) { + lldb::break_id_t bp_site_id = + (lldb::break_id_t)stop_info_sp->GetValue(); + BreakpointSiteSP bp_site_sp( + process->GetBreakpointSiteList().FindByID(bp_site_id)); + if (bp_site_sp) { + const size_t num_owners = bp_site_sp->GetNumberOfOwners(); + for (size_t i = 0; i < num_owners; i++) { + Breakpoint &bp_ref = + bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); + if (!bp_ref.IsInternal()) { + bp_ref.SetIgnoreCount(m_options.m_ignore); } - else - { - result.SetStatus (eReturnStatusSuccessContinuingNoResult); - } - } - else - { - result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); - result.SetStatus (eReturnStatusFailed); + } } - } - else - { - result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n", - StateAsCString(state)); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + } + } + } + + { // Scope for thread list mutex: + std::lock_guard<std::recursive_mutex> guard( + process->GetThreadList().GetMutex()); + const uint32_t num_threads = process->GetThreadList().GetSize(); + + // Set the actions that the threads should each take when resuming + for (uint32_t idx = 0; idx < num_threads; ++idx) { + const bool override_suspend = false; + process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState( + eStateRunning, override_suspend); + } + } + + const uint32_t iohandler_id = process->GetIOHandlerID(); + + StreamString stream; + Error error; + if (synchronous_execution) + error = process->ResumeSynchronous(&stream); + else + error = process->Resume(); + + if (error.Success()) { + // There is a race condition where this thread will return up the call + // stack to the main command + // handler and show an (lldb) prompt before HandlePrivateEvent (from + // PrivateStateThread) has + // a chance to call PushProcessIOHandler(). + process->SyncIOHandler(iohandler_id, 2000); + + result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n", + process->GetID()); + if (synchronous_execution) { + // If any state changed events had anything to say, add that to the + // result + if (stream.GetData()) + result.AppendMessage(stream.GetData()); + + result.SetDidChangeProcessState(true); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.SetStatus(eReturnStatusSuccessContinuingNoResult); + } + } else { + result.AppendErrorWithFormat("Failed to resume process: %s.\n", + error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendErrorWithFormat( + "Process cannot be continued from its current state (%s).\n", + StateAsCString(state)); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } - Options * - GetOptions () override - { - return &m_options; - } - - CommandOptions m_options; + Options *GetOptions() override { return &m_options; } + + CommandOptions m_options; }; OptionDefinition -CommandObjectProcessContinue::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectProcessContinue::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_ALL, false, "ignore-count",'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Ignore <N> crossings of the breakpoint (if it exists) for the currently selected thread."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- @@ -820,127 +748,101 @@ CommandObjectProcessContinue::CommandOptions::g_option_table[] = //------------------------------------------------------------------------- #pragma mark CommandObjectProcessDetach -class CommandObjectProcessDetach : public CommandObjectParsed -{ +class CommandObjectProcessDetach : public CommandObjectParsed { public: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - OptionParsingStarting(nullptr); - } - - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 's': - bool tmp_result; - bool success; - tmp_result = Args::StringToBoolean(option_arg, false, &success); - if (!success) - error.SetErrorStringWithFormat("invalid boolean option: \"%s\"", option_arg); - else - { - if (tmp_result) - m_keep_stopped = eLazyBoolYes; - else - m_keep_stopped = eLazyBoolNo; - } - break; - default: - error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); - break; - } - return error; - } + class CommandOptions : public Options { + public: + CommandOptions() : Options() { OptionParsingStarting(nullptr); } + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 's': + bool tmp_result; + bool success; + tmp_result = Args::StringToBoolean(option_arg, false, &success); + if (!success) + error.SetErrorStringWithFormat("invalid boolean option: \"%s\"", + option_arg); + else { + if (tmp_result) + m_keep_stopped = eLazyBoolYes; + else + m_keep_stopped = eLazyBoolNo; + } + break; + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", + short_option); + break; + } + return error; + } - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_keep_stopped = eLazyBoolCalculate; - } + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_keep_stopped = eLazyBoolCalculate; + } - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } - // Options table: Required for subclasses of Options. + // Options table: Required for subclasses of Options. - static OptionDefinition g_option_table[]; + static OptionDefinition g_option_table[]; - // Instance variables to hold the values for command options. - LazyBool m_keep_stopped; - }; + // Instance variables to hold the values for command options. + LazyBool m_keep_stopped; + }; - CommandObjectProcessDetach(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "process detach", "Detach from the current target process.", - "process detach", - eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched), - m_options() - { - } + CommandObjectProcessDetach(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "process detach", + "Detach from the current target process.", + "process detach", + eCommandRequiresProcess | eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched), + m_options() {} - ~CommandObjectProcessDetach() override = default; + ~CommandObjectProcessDetach() override = default; - Options * - GetOptions () override - { - return &m_options; - } + Options *GetOptions() override { return &m_options; } protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Process *process = m_exe_ctx.GetProcessPtr(); - // FIXME: This will be a Command Option: - bool keep_stopped; - if (m_options.m_keep_stopped == eLazyBoolCalculate) - { - // Check the process default: - keep_stopped = process->GetDetachKeepsStopped(); - } - else if (m_options.m_keep_stopped == eLazyBoolYes) - keep_stopped = true; - else - keep_stopped = false; - - Error error (process->Detach(keep_stopped)); - if (error.Success()) - { - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString()); - result.SetStatus (eReturnStatusFailed); - return false; - } - return result.Succeeded(); + bool DoExecute(Args &command, CommandReturnObject &result) override { + Process *process = m_exe_ctx.GetProcessPtr(); + // FIXME: This will be a Command Option: + bool keep_stopped; + if (m_options.m_keep_stopped == eLazyBoolCalculate) { + // Check the process default: + keep_stopped = process->GetDetachKeepsStopped(); + } else if (m_options.m_keep_stopped == eLazyBoolYes) + keep_stopped = true; + else + keep_stopped = false; + + Error error(process->Detach(keep_stopped)); + if (error.Success()) { + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; } + return result.Succeeded(); + } - CommandOptions m_options; + CommandOptions m_options; }; -OptionDefinition -CommandObjectProcessDetach::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectProcessDetach::CommandOptions::g_option_table[] = + { + // clang-format off {LLDB_OPT_SET_1, false, "keep-stopped", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Whether or not the process should be kept stopped on detach (if possible)."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- @@ -948,133 +850,108 @@ CommandObjectProcessDetach::CommandOptions::g_option_table[] = //------------------------------------------------------------------------- #pragma mark CommandObjectProcessConnect -class CommandObjectProcessConnect : public CommandObjectParsed -{ +class CommandObjectProcessConnect : public CommandObjectParsed { public: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - // Keep default values of all options in one place: OptionParsingStarting () - OptionParsingStarting(nullptr); - } - - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'p': - plugin_name.assign (option_arg); - break; - - default: - error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); - break; - } - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - plugin_name.clear(); - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - std::string plugin_name; - }; - - CommandObjectProcessConnect (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "process connect", - "Connect to a remote debug service.", - "process connect <remote-url>", - 0), - m_options() - { + class CommandOptions : public Options { + public: + CommandOptions() : Options() { + // Keep default values of all options in one place: OptionParsingStarting + // () + OptionParsingStarting(nullptr); } - ~CommandObjectProcessConnect() override = default; + ~CommandOptions() override = default; - Options * - GetOptions () override - { - return &m_options; + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'p': + plugin_name.assign(option_arg); + break; + + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", + short_option); + break; + } + return error; + } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + plugin_name.clear(); } - + + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + std::string plugin_name; + }; + + CommandObjectProcessConnect(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "process connect", + "Connect to a remote debug service.", + "process connect <remote-url>", 0), + m_options() {} + + ~CommandObjectProcessConnect() override = default; + + Options *GetOptions() override { return &m_options; } + protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - if (command.GetArgumentCount() != 1) - { - result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: %s\n", - m_cmd_name.c_str(), - m_cmd_syntax.c_str()); - result.SetStatus (eReturnStatusFailed); - return false; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + if (command.GetArgumentCount() != 1) { + result.AppendErrorWithFormat( + "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(), + m_cmd_syntax.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } - Process *process = m_exe_ctx.GetProcessPtr(); - if (process && process->IsAlive()) - { - result.AppendErrorWithFormat ("Process %" PRIu64 " is currently being debugged, kill the process before connecting.\n", - process->GetID()); - result.SetStatus (eReturnStatusFailed); - return false; - } + Process *process = m_exe_ctx.GetProcessPtr(); + if (process && process->IsAlive()) { + result.AppendErrorWithFormat( + "Process %" PRIu64 + " is currently being debugged, kill the process before connecting.\n", + process->GetID()); + result.SetStatus(eReturnStatusFailed); + return false; + } - const char *plugin_name = nullptr; - if (!m_options.plugin_name.empty()) - plugin_name = m_options.plugin_name.c_str(); - - Error error; - Debugger& debugger = m_interpreter.GetDebugger(); - PlatformSP platform_sp = m_interpreter.GetPlatform(true); - ProcessSP process_sp = platform_sp->ConnectProcess(command.GetArgumentAtIndex(0), - plugin_name, - debugger, - debugger.GetSelectedTarget().get(), - error); - if (error.Fail() || process_sp == nullptr) - { - result.AppendError(error.AsCString("Error connecting to the process")); - result.SetStatus (eReturnStatusFailed); - return false; - } - return true; + const char *plugin_name = nullptr; + if (!m_options.plugin_name.empty()) + plugin_name = m_options.plugin_name.c_str(); + + Error error; + Debugger &debugger = m_interpreter.GetDebugger(); + PlatformSP platform_sp = m_interpreter.GetPlatform(true); + ProcessSP process_sp = platform_sp->ConnectProcess( + command.GetArgumentAtIndex(0), plugin_name, debugger, + debugger.GetSelectedTarget().get(), error); + if (error.Fail() || process_sp == nullptr) { + result.AppendError(error.AsCString("Error connecting to the process")); + result.SetStatus(eReturnStatusFailed); + return false; } + return true; + } - CommandOptions m_options; + CommandOptions m_options; }; -OptionDefinition -CommandObjectProcessConnect::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectProcessConnect::CommandOptions::g_option_table[] = + { + // clang-format off {LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- @@ -1082,25 +959,22 @@ CommandObjectProcessConnect::CommandOptions::g_option_table[] = //------------------------------------------------------------------------- #pragma mark CommandObjectProcessPlugin -class CommandObjectProcessPlugin : public CommandObjectProxy -{ +class CommandObjectProcessPlugin : public CommandObjectProxy { public: - CommandObjectProcessPlugin(CommandInterpreter &interpreter) - : CommandObjectProxy(interpreter, "process plugin", - "Send a custom command to the current target process plug-in.", "process plugin <args>", 0) - { - } - - ~CommandObjectProcessPlugin() override = default; - - CommandObject * - GetProxyCommandObject() override - { - Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); - if (process) - return process->GetPluginCommandObject(); - return nullptr; - } + CommandObjectProcessPlugin(CommandInterpreter &interpreter) + : CommandObjectProxy( + interpreter, "process plugin", + "Send a custom command to the current target process plug-in.", + "process plugin <args>", 0) {} + + ~CommandObjectProcessPlugin() override = default; + + CommandObject *GetProxyCommandObject() override { + Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); + if (process) + return process->GetPluginCommandObject(); + return nullptr; + } }; //------------------------------------------------------------------------- @@ -1108,139 +982,113 @@ public: //------------------------------------------------------------------------- #pragma mark CommandObjectProcessLoad -class CommandObjectProcessLoad : public CommandObjectParsed -{ +class CommandObjectProcessLoad : public CommandObjectParsed { public: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - // Keep default values of all options in one place: OptionParsingStarting () - OptionParsingStarting(nullptr); - } + class CommandOptions : public Options { + public: + CommandOptions() : Options() { + // Keep default values of all options in one place: OptionParsingStarting + // () + OptionParsingStarting(nullptr); + } - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - switch (short_option) - { - case 'i': - do_install = true; - if (option_arg && option_arg[0]) - install_path.SetFile(option_arg, false); - break; - default: - error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); - break; - } - return error; - } + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + switch (short_option) { + case 'i': + do_install = true; + if (option_arg && option_arg[0]) + install_path.SetFile(option_arg, false); + break; + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", + short_option); + break; + } + return error; + } - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - do_install = false; - install_path.Clear(); - } + void OptionParsingStarting(ExecutionContext *execution_context) override { + do_install = false; + install_path.Clear(); + } - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } - // Options table: Required for subclasses of Options. - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - bool do_install; - FileSpec install_path; - }; - - CommandObjectProcessLoad (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "process load", - "Load a shared library into the current process.", - "process load <filename> [<filename> ...]", - eCommandRequiresProcess | - eCommandTryTargetAPILock | - eCommandProcessMustBeLaunched | - eCommandProcessMustBePaused ), - m_options() - { - } + // Options table: Required for subclasses of Options. + static OptionDefinition g_option_table[]; - ~CommandObjectProcessLoad() override = default; + // Instance variables to hold the values for command options. + bool do_install; + FileSpec install_path; + }; - Options * - GetOptions () override - { - return &m_options; - } + CommandObjectProcessLoad(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "process load", + "Load a shared library into the current process.", + "process load <filename> [<filename> ...]", + eCommandRequiresProcess | eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused), + m_options() {} -protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Process *process = m_exe_ctx.GetProcessPtr(); - - const size_t argc = command.GetArgumentCount(); - for (uint32_t i = 0; i < argc; ++i) - { - Error error; - PlatformSP platform = process->GetTarget().GetPlatform(); - const char *image_path = command.GetArgumentAtIndex(i); - uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN; - - if (!m_options.do_install) - { - FileSpec image_spec (image_path, false); - platform->ResolveRemotePath(image_spec, image_spec); - image_token = platform->LoadImage(process, FileSpec(), image_spec, error); - } - else if (m_options.install_path) - { - FileSpec image_spec (image_path, true); - platform->ResolveRemotePath(m_options.install_path, m_options.install_path); - image_token = platform->LoadImage(process, image_spec, m_options.install_path, error); - } - else - { - FileSpec image_spec (image_path, true); - image_token = platform->LoadImage(process, image_spec, FileSpec(), error); - } + ~CommandObjectProcessLoad() override = default; - if (image_token != LLDB_INVALID_IMAGE_TOKEN) - { - result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendErrorWithFormat ("failed to load '%s': %s", image_path, error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - return result.Succeeded(); + Options *GetOptions() override { return &m_options; } + +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + Process *process = m_exe_ctx.GetProcessPtr(); + + const size_t argc = command.GetArgumentCount(); + for (uint32_t i = 0; i < argc; ++i) { + Error error; + PlatformSP platform = process->GetTarget().GetPlatform(); + const char *image_path = command.GetArgumentAtIndex(i); + uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN; + + if (!m_options.do_install) { + FileSpec image_spec(image_path, false); + platform->ResolveRemotePath(image_spec, image_spec); + image_token = + platform->LoadImage(process, FileSpec(), image_spec, error); + } else if (m_options.install_path) { + FileSpec image_spec(image_path, true); + platform->ResolveRemotePath(m_options.install_path, + m_options.install_path); + image_token = platform->LoadImage(process, image_spec, + m_options.install_path, error); + } else { + FileSpec image_spec(image_path, true); + image_token = + platform->LoadImage(process, image_spec, FileSpec(), error); + } + + if (image_token != LLDB_INVALID_IMAGE_TOKEN) { + result.AppendMessageWithFormat( + "Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat("failed to load '%s': %s", image_path, + error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } } - - CommandOptions m_options; + return result.Succeeded(); + } + + CommandOptions m_options; }; -OptionDefinition -CommandObjectProcessLoad::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectProcessLoad::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_ALL, false, "install", 'i', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypePath, "Install the shared library to the target. If specified without an argument then the library will installed in the current working directory."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- @@ -1248,60 +1096,51 @@ CommandObjectProcessLoad::CommandOptions::g_option_table[] = //------------------------------------------------------------------------- #pragma mark CommandObjectProcessUnload -class CommandObjectProcessUnload : public CommandObjectParsed -{ +class CommandObjectProcessUnload : public CommandObjectParsed { public: + CommandObjectProcessUnload(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "process unload", + "Unload a shared library from the current process using the index " + "returned by a previous call to \"process load\".", + "process unload <index>", + eCommandRequiresProcess | eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} - CommandObjectProcessUnload (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "process unload", - "Unload a shared library from the current process using the index returned by a previous call to \"process load\".", - "process unload <index>", - eCommandRequiresProcess | - eCommandTryTargetAPILock | - eCommandProcessMustBeLaunched | - eCommandProcessMustBePaused ) - { - } - - ~CommandObjectProcessUnload() override = default; + ~CommandObjectProcessUnload() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Process *process = m_exe_ctx.GetProcessPtr(); - - const size_t argc = command.GetArgumentCount(); - - for (uint32_t i = 0; i < argc; ++i) - { - const char *image_token_cstr = command.GetArgumentAtIndex(i); - uint32_t image_token = StringConvert::ToUInt32(image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0); - if (image_token == LLDB_INVALID_IMAGE_TOKEN) - { - result.AppendErrorWithFormat ("invalid image index argument '%s'", image_token_cstr); - result.SetStatus (eReturnStatusFailed); - break; - } - else - { - Error error (process->GetTarget().GetPlatform()->UnloadImage(process, image_token)); - if (error.Success()) - { - result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendErrorWithFormat ("failed to unload image: %s", error.AsCString()); - result.SetStatus (eReturnStatusFailed); - break; - } - } - } - return result.Succeeded(); + bool DoExecute(Args &command, CommandReturnObject &result) override { + Process *process = m_exe_ctx.GetProcessPtr(); + + const size_t argc = command.GetArgumentCount(); + + for (uint32_t i = 0; i < argc; ++i) { + const char *image_token_cstr = command.GetArgumentAtIndex(i); + uint32_t image_token = StringConvert::ToUInt32( + image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0); + if (image_token == LLDB_INVALID_IMAGE_TOKEN) { + result.AppendErrorWithFormat("invalid image index argument '%s'", + image_token_cstr); + result.SetStatus(eReturnStatusFailed); + break; + } else { + Error error(process->GetTarget().GetPlatform()->UnloadImage( + process, image_token)); + if (error.Success()) { + result.AppendMessageWithFormat( + "Unloading shared library with index %u...ok\n", image_token); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat("failed to unload image: %s", + error.AsCString()); + result.SetStatus(eReturnStatusFailed); + break; + } + } } + return result.Succeeded(); + } }; //------------------------------------------------------------------------- @@ -1309,72 +1148,66 @@ protected: //------------------------------------------------------------------------- #pragma mark CommandObjectProcessSignal -class CommandObjectProcessSignal : public CommandObjectParsed -{ +class CommandObjectProcessSignal : public CommandObjectParsed { public: - CommandObjectProcessSignal(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "process signal", "Send a UNIX signal to the current target process.", - nullptr, eCommandRequiresProcess | eCommandTryTargetAPILock) - { - CommandArgumentEntry arg; - CommandArgumentData signal_arg; - - // Define the first (and only) variant of this arg. - signal_arg.arg_type = eArgTypeUnixSignal; - signal_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (signal_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - } + CommandObjectProcessSignal(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "process signal", + "Send a UNIX signal to the current target process.", + nullptr, eCommandRequiresProcess | + eCommandTryTargetAPILock) { + CommandArgumentEntry arg; + CommandArgumentData signal_arg; + + // Define the first (and only) variant of this arg. + signal_arg.arg_type = eArgTypeUnixSignal; + signal_arg.arg_repetition = eArgRepeatPlain; - ~CommandObjectProcessSignal() override = default; + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(signal_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectProcessSignal() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Process *process = m_exe_ctx.GetProcessPtr(); - - if (command.GetArgumentCount() == 1) - { - 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 - signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name); - - if (signo == LLDB_INVALID_SIGNAL_NUMBER) - { - result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0)); - result.SetStatus (eReturnStatusFailed); - } - else - { - Error error (process->Signal (signo)); - if (error.Success()) - { - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - } - else - { - result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: %s\n", m_cmd_name.c_str(), - m_cmd_syntax.c_str()); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + bool DoExecute(Args &command, CommandReturnObject &result) override { + Process *process = m_exe_ctx.GetProcessPtr(); + + if (command.GetArgumentCount() == 1) { + 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 + signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name); + + if (signo == LLDB_INVALID_SIGNAL_NUMBER) { + result.AppendErrorWithFormat("Invalid signal argument '%s'.\n", + command.GetArgumentAtIndex(0)); + result.SetStatus(eReturnStatusFailed); + } else { + Error error(process->Signal(signo)); + if (error.Success()) { + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo, + error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + } + } else { + result.AppendErrorWithFormat( + "'%s' takes exactly one signal number argument:\nUsage: %s\n", + m_cmd_name.c_str(), m_cmd_syntax.c_str()); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } }; //------------------------------------------------------------------------- @@ -1382,53 +1215,43 @@ protected: //------------------------------------------------------------------------- #pragma mark CommandObjectProcessInterrupt -class CommandObjectProcessInterrupt : public CommandObjectParsed -{ +class CommandObjectProcessInterrupt : public CommandObjectParsed { public: - CommandObjectProcessInterrupt(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "process interrupt", "Interrupt the current target process.", - "process interrupt", - eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched) - { - } + CommandObjectProcessInterrupt(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "process interrupt", + "Interrupt the current target process.", + "process interrupt", + eCommandRequiresProcess | eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched) {} - ~CommandObjectProcessInterrupt() override = default; + ~CommandObjectProcessInterrupt() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Process *process = m_exe_ctx.GetProcessPtr(); - if (process == nullptr) - { - result.AppendError ("no process to halt"); - result.SetStatus (eReturnStatusFailed); - return false; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + Process *process = m_exe_ctx.GetProcessPtr(); + if (process == nullptr) { + result.AppendError("no process to halt"); + result.SetStatus(eReturnStatusFailed); + return false; + } - if (command.GetArgumentCount() == 0) - { - bool clear_thread_plans = true; - Error error(process->Halt (clear_thread_plans)); - if (error.Success()) - { - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", - m_cmd_name.c_str(), - m_cmd_syntax.c_str()); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + if (command.GetArgumentCount() == 0) { + bool clear_thread_plans = true; + Error error(process->Halt(clear_thread_plans)); + if (error.Success()) { + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat("Failed to halt process: %s\n", + error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", + m_cmd_name.c_str(), m_cmd_syntax.c_str()); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } }; //------------------------------------------------------------------------- @@ -1436,51 +1259,42 @@ protected: //------------------------------------------------------------------------- #pragma mark CommandObjectProcessKill -class CommandObjectProcessKill : public CommandObjectParsed -{ +class CommandObjectProcessKill : public CommandObjectParsed { public: - CommandObjectProcessKill(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "process kill", "Terminate the current target process.", "process kill", - eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched) - { - } + CommandObjectProcessKill(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "process kill", + "Terminate the current target process.", + "process kill", + eCommandRequiresProcess | eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched) {} - ~CommandObjectProcessKill() override = default; + ~CommandObjectProcessKill() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Process *process = m_exe_ctx.GetProcessPtr(); - if (process == nullptr) - { - result.AppendError ("no process to kill"); - result.SetStatus (eReturnStatusFailed); - return false; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + Process *process = m_exe_ctx.GetProcessPtr(); + if (process == nullptr) { + result.AppendError("no process to kill"); + result.SetStatus(eReturnStatusFailed); + return false; + } - if (command.GetArgumentCount() == 0) - { - Error error (process->Destroy(true)); - if (error.Success()) - { - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", - m_cmd_name.c_str(), - m_cmd_syntax.c_str()); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + if (command.GetArgumentCount() == 0) { + Error error(process->Destroy(true)); + if (error.Success()) { + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat("Failed to kill process: %s\n", + error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", + m_cmd_name.c_str(), m_cmd_syntax.c_str()); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } }; //------------------------------------------------------------------------- @@ -1488,61 +1302,45 @@ protected: //------------------------------------------------------------------------- #pragma mark CommandObjectProcessSaveCore -class CommandObjectProcessSaveCore : public CommandObjectParsed -{ +class CommandObjectProcessSaveCore : public CommandObjectParsed { public: - CommandObjectProcessSaveCore (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "process save-core", - "Save the current process as a core file using an appropriate file type.", - "process save-core FILE", - eCommandRequiresProcess | - eCommandTryTargetAPILock | - eCommandProcessMustBeLaunched) - { - } + CommandObjectProcessSaveCore(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "process save-core", + "Save the current process as a core file using an " + "appropriate file type.", + "process save-core FILE", + eCommandRequiresProcess | eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched) {} - ~CommandObjectProcessSaveCore() override = default; + ~CommandObjectProcessSaveCore() override = default; protected: - bool - DoExecute (Args& command, - CommandReturnObject &result) override - { - ProcessSP process_sp = m_exe_ctx.GetProcessSP(); - if (process_sp) - { - if (command.GetArgumentCount() == 1) - { - FileSpec output_file(command.GetArgumentAtIndex(0), false); - Error error = PluginManager::SaveCore(process_sp, output_file); - if (error.Success()) - { - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendErrorWithFormat ("Failed to save core file for process: %s\n", error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendErrorWithFormat ("'%s' takes one arguments:\nUsage: %s\n", - m_cmd_name.c_str(), - m_cmd_syntax.c_str()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendError ("invalid process"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - return result.Succeeded(); + bool DoExecute(Args &command, CommandReturnObject &result) override { + ProcessSP process_sp = m_exe_ctx.GetProcessSP(); + if (process_sp) { + if (command.GetArgumentCount() == 1) { + FileSpec output_file(command.GetArgumentAtIndex(0), false); + Error error = PluginManager::SaveCore(process_sp, output_file); + if (error.Success()) { + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat( + "Failed to save core file for process: %s\n", error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n", + m_cmd_name.c_str(), m_cmd_syntax.c_str()); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendError("invalid process"); + result.SetStatus(eReturnStatusFailed); + return false; } + + return result.Succeeded(); + } }; //------------------------------------------------------------------------- @@ -1550,37 +1348,32 @@ protected: //------------------------------------------------------------------------- #pragma mark CommandObjectProcessStatus -class CommandObjectProcessStatus : public CommandObjectParsed -{ +class CommandObjectProcessStatus : public CommandObjectParsed { public: - CommandObjectProcessStatus(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "process status", - "Show status and stop location for the current target process.", "process status", - eCommandRequiresProcess | eCommandTryTargetAPILock) - { - } - - ~CommandObjectProcessStatus() override = default; - - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Stream &strm = result.GetOutputStream(); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid - Process *process = m_exe_ctx.GetProcessPtr(); - const bool only_threads_with_stop_reason = true; - const uint32_t start_frame = 0; - const uint32_t num_frames = 1; - const uint32_t num_frames_with_source = 1; - process->GetStatus(strm); - process->GetThreadStatus (strm, - only_threads_with_stop_reason, - start_frame, - num_frames, - num_frames_with_source); - return result.Succeeded(); - } + CommandObjectProcessStatus(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "process status", + "Show status and stop location for the current target process.", + "process status", + eCommandRequiresProcess | eCommandTryTargetAPILock) {} + + ~CommandObjectProcessStatus() override = default; + + bool DoExecute(Args &command, CommandReturnObject &result) override { + Stream &strm = result.GetOutputStream(); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + // No need to check "process" for validity as eCommandRequiresProcess + // ensures it is valid + Process *process = m_exe_ctx.GetProcessPtr(); + const bool only_threads_with_stop_reason = true; + const uint32_t start_frame = 0; + const uint32_t num_frames = 1; + const uint32_t num_frames_with_source = 1; + process->GetStatus(strm); + process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame, + num_frames, num_frames_with_source); + return result.Succeeded(); + } }; //------------------------------------------------------------------------- @@ -1588,324 +1381,303 @@ public: //------------------------------------------------------------------------- #pragma mark CommandObjectProcessHandle -class CommandObjectProcessHandle : public CommandObjectParsed -{ +class CommandObjectProcessHandle : public CommandObjectParsed { public: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - OptionParsingStarting(nullptr); - } - - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 's': - stop = option_arg; - break; - case 'n': - notify = option_arg; - break; - case 'p': - pass = option_arg; - break; - default: - error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); - break; - } - return error; - } + class CommandOptions : public Options { + public: + CommandOptions() : Options() { OptionParsingStarting(nullptr); } + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 's': + stop = option_arg; + break; + case 'n': + notify = option_arg; + break; + case 'p': + pass = option_arg; + break; + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", + short_option); + break; + } + return error; + } - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - stop.clear(); - notify.clear(); - pass.clear(); - } + void OptionParsingStarting(ExecutionContext *execution_context) override { + stop.clear(); + notify.clear(); + pass.clear(); + } - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } - // Options table: Required for subclasses of Options. + // Options table: Required for subclasses of Options. - static OptionDefinition g_option_table[]; + static OptionDefinition g_option_table[]; - // Instance variables to hold the values for command options. + // Instance variables to hold the values for command options. - std::string stop; - std::string notify; - std::string pass; - }; + std::string stop; + std::string notify; + std::string pass; + }; - CommandObjectProcessHandle(CommandInterpreter &interpreter) - : CommandObjectParsed( - interpreter, "process handle", - "Manage LLDB handling of OS signals for the current target process. Defaults to showing current policy.", - nullptr), - m_options() - { - SetHelpLong ("\nIf no signals are specified, update them all. If no update " - "option is specified, list the current values."); - CommandArgumentEntry arg; - CommandArgumentData signal_arg; + CommandObjectProcessHandle(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "process handle", + "Manage LLDB handling of OS signals for the " + "current target process. Defaults to showing " + "current policy.", + nullptr), + m_options() { + SetHelpLong("\nIf no signals are specified, update them all. If no update " + "option is specified, list the current values."); + CommandArgumentEntry arg; + CommandArgumentData signal_arg; - signal_arg.arg_type = eArgTypeUnixSignal; - signal_arg.arg_repetition = eArgRepeatStar; + signal_arg.arg_type = eArgTypeUnixSignal; + signal_arg.arg_repetition = eArgRepeatStar; - arg.push_back (signal_arg); - - m_arguments.push_back (arg); - } + arg.push_back(signal_arg); - ~CommandObjectProcessHandle() override = default; + m_arguments.push_back(arg); + } - Options * - GetOptions () override - { - return &m_options; - } + ~CommandObjectProcessHandle() override = default; - bool - VerifyCommandOptionValue (const std::string &option, int &real_value) - { - bool okay = true; - bool success = false; - bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success); - - if (success && tmp_value) - real_value = 1; - else if (success && !tmp_value) - 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 (real_value != 0 && real_value != 1) - okay = false; - } - - return okay; - } + Options *GetOptions() override { return &m_options; } - void - PrintSignalHeader (Stream &str) - { - str.Printf ("NAME PASS STOP NOTIFY\n"); - str.Printf ("=========== ===== ===== ======\n"); - } + bool VerifyCommandOptionValue(const std::string &option, int &real_value) { + bool okay = true; + bool success = false; + bool tmp_value = Args::StringToBoolean(option.c_str(), false, &success); - void - PrintSignal(Stream &str, int32_t signo, const char *sig_name, const UnixSignalsSP &signals_sp) - { - bool stop; - bool suppress; - bool notify; - - str.Printf ("%-11s ", sig_name); - if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) - { - bool pass = !suppress; - str.Printf ("%s %s %s", - (pass ? "true " : "false"), - (stop ? "true " : "false"), - (notify ? "true " : "false")); - } - str.Printf ("\n"); + if (success && tmp_value) + real_value = 1; + else if (success && !tmp_value) + 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 (real_value != 0 && real_value != 1) + okay = false; } - void - PrintSignalInformation(Stream &str, Args &signal_args, int num_valid_signals, const UnixSignalsSP &signals_sp) + return okay; + } + + void PrintSignalHeader(Stream &str) { + str.Printf("NAME PASS STOP NOTIFY\n"); + str.Printf("=========== ===== ===== ======\n"); + } + + void PrintSignal(Stream &str, int32_t signo, const char *sig_name, + const UnixSignalsSP &signals_sp) { + bool stop; + bool suppress; + bool notify; + + str.Printf("%-11s ", sig_name); + if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) { + bool pass = !suppress; + str.Printf("%s %s %s", (pass ? "true " : "false"), + (stop ? "true " : "false"), (notify ? "true " : "false")); + } + str.Printf("\n"); + } + + void PrintSignalInformation(Stream &str, Args &signal_args, + int num_valid_signals, + const UnixSignalsSP &signals_sp) { + PrintSignalHeader(str); + + if (num_valid_signals > 0) { + size_t num_args = signal_args.GetArgumentCount(); + for (size_t i = 0; i < num_args; ++i) { + int32_t signo = signals_sp->GetSignalNumberFromName( + signal_args.GetArgumentAtIndex(i)); + if (signo != LLDB_INVALID_SIGNAL_NUMBER) + PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i), + signals_sp); + } + } else // Print info for ALL signals { - PrintSignalHeader (str); - - if (num_valid_signals > 0) - { - size_t num_args = signal_args.GetArgumentCount(); - for (size_t i = 0; i < num_args; ++i) - { - int32_t signo = signals_sp->GetSignalNumberFromName(signal_args.GetArgumentAtIndex(i)); - if (signo != LLDB_INVALID_SIGNAL_NUMBER) - PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals_sp); - } - } - else // Print info for ALL signals - { - int32_t signo = signals_sp->GetFirstSignalNumber(); - while (signo != LLDB_INVALID_SIGNAL_NUMBER) - { - PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo), signals_sp); - signo = signals_sp->GetNextSignalNumber(signo); - } - } + int32_t signo = signals_sp->GetFirstSignalNumber(); + while (signo != LLDB_INVALID_SIGNAL_NUMBER) { + PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo), + signals_sp); + signo = signals_sp->GetNextSignalNumber(signo); + } } + } protected: - bool - DoExecute (Args &signal_args, CommandReturnObject &result) override - { - TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); - - if (!target_sp) - { - result.AppendError ("No current target;" - " cannot handle signals until you have a valid target and process.\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - ProcessSP process_sp = target_sp->GetProcessSP(); - - if (!process_sp) - { - result.AppendError ("No current process; cannot handle signals until you have a valid process.\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } + bool DoExecute(Args &signal_args, CommandReturnObject &result) override { + TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); + + if (!target_sp) { + result.AppendError("No current target;" + " cannot handle signals until you have a valid target " + "and process.\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } - int stop_action = -1; // -1 means leave the current setting alone - int pass_action = -1; // -1 means leave the current setting alone - int notify_action = -1; // -1 means leave the current setting alone + ProcessSP process_sp = target_sp->GetProcessSP(); - if (! m_options.stop.empty() - && ! VerifyCommandOptionValue (m_options.stop, stop_action)) - { - result.AppendError ("Invalid argument for command option --stop; must be true or false.\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (!process_sp) { + result.AppendError("No current process; cannot handle signals until you " + "have a valid process.\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } - if (! m_options.notify.empty() - && ! VerifyCommandOptionValue (m_options.notify, notify_action)) - { - result.AppendError ("Invalid argument for command option --notify; must be true or false.\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } + int stop_action = -1; // -1 means leave the current setting alone + int pass_action = -1; // -1 means leave the current setting alone + int notify_action = -1; // -1 means leave the current setting alone - if (! m_options.pass.empty() - && ! VerifyCommandOptionValue (m_options.pass, pass_action)) - { - result.AppendError ("Invalid argument for command option --pass; must be true or false.\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (!m_options.stop.empty() && + !VerifyCommandOptionValue(m_options.stop, stop_action)) { + result.AppendError("Invalid argument for command option --stop; must be " + "true or false.\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } - size_t num_args = signal_args.GetArgumentCount(); - UnixSignalsSP signals_sp = process_sp->GetUnixSignals(); - int num_signals_set = 0; - - if (num_args > 0) - { - for (size_t i = 0; i < num_args; ++i) - { - int32_t signo = signals_sp->GetSignalNumberFromName(signal_args.GetArgumentAtIndex(i)); - if (signo != LLDB_INVALID_SIGNAL_NUMBER) - { - // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees - // the value is either 0 or 1. - if (stop_action != -1) - signals_sp->SetShouldStop(signo, stop_action); - if (pass_action != -1) - { - bool suppress = !pass_action; - signals_sp->SetShouldSuppress(signo, suppress); - } - if (notify_action != -1) - signals_sp->SetShouldNotify(signo, notify_action); - ++num_signals_set; - } - else - { - result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i)); - } - } - } - else - { - // No signal specified, if any command options were specified, update ALL signals. - if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) - { - if (m_interpreter.Confirm ("Do you really want to update all the signals?", false)) - { - int32_t signo = signals_sp->GetFirstSignalNumber(); - while (signo != LLDB_INVALID_SIGNAL_NUMBER) - { - if (notify_action != -1) - signals_sp->SetShouldNotify(signo, notify_action); - if (stop_action != -1) - signals_sp->SetShouldStop(signo, stop_action); - if (pass_action != -1) - { - bool suppress = !pass_action; - signals_sp->SetShouldSuppress(signo, suppress); - } - signo = signals_sp->GetNextSignalNumber(signo); - } - } + if (!m_options.notify.empty() && + !VerifyCommandOptionValue(m_options.notify, notify_action)) { + result.AppendError("Invalid argument for command option --notify; must " + "be true or false.\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (!m_options.pass.empty() && + !VerifyCommandOptionValue(m_options.pass, pass_action)) { + result.AppendError("Invalid argument for command option --pass; must be " + "true or false.\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + size_t num_args = signal_args.GetArgumentCount(); + UnixSignalsSP signals_sp = process_sp->GetUnixSignals(); + int num_signals_set = 0; + + if (num_args > 0) { + for (size_t i = 0; i < num_args; ++i) { + int32_t signo = signals_sp->GetSignalNumberFromName( + signal_args.GetArgumentAtIndex(i)); + if (signo != LLDB_INVALID_SIGNAL_NUMBER) { + // Casting the actions as bools here should be okay, because + // VerifyCommandOptionValue guarantees + // the value is either 0 or 1. + if (stop_action != -1) + signals_sp->SetShouldStop(signo, stop_action); + if (pass_action != -1) { + bool suppress = !pass_action; + signals_sp->SetShouldSuppress(signo, suppress); + } + if (notify_action != -1) + signals_sp->SetShouldNotify(signo, notify_action); + ++num_signals_set; + } else { + result.AppendErrorWithFormat("Invalid signal name '%s'\n", + signal_args.GetArgumentAtIndex(i)); + } + } + } else { + // No signal specified, if any command options were specified, update ALL + // signals. + if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) { + if (m_interpreter.Confirm( + "Do you really want to update all the signals?", false)) { + int32_t signo = signals_sp->GetFirstSignalNumber(); + while (signo != LLDB_INVALID_SIGNAL_NUMBER) { + if (notify_action != -1) + signals_sp->SetShouldNotify(signo, notify_action); + if (stop_action != -1) + signals_sp->SetShouldStop(signo, stop_action); + if (pass_action != -1) { + bool suppress = !pass_action; + signals_sp->SetShouldSuppress(signo, suppress); } + signo = signals_sp->GetNextSignalNumber(signo); + } } + } + } - PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals_sp); + PrintSignalInformation(result.GetOutputStream(), signal_args, + num_signals_set, signals_sp); - if (num_signals_set > 0) - result.SetStatus (eReturnStatusSuccessFinishNoResult); - else - result.SetStatus (eReturnStatusFailed); + if (num_signals_set > 0) + result.SetStatus(eReturnStatusSuccessFinishNoResult); + else + result.SetStatus(eReturnStatusFailed); - return result.Succeeded(); - } + return result.Succeeded(); + } - CommandOptions m_options; + CommandOptions m_options; }; -OptionDefinition -CommandObjectProcessHandle::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectProcessHandle::CommandOptions::g_option_table[] = + { + // clang-format off {LLDB_OPT_SET_1, false, "stop", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received."}, {LLDB_OPT_SET_1, false, "notify", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Whether or not the debugger should notify the user if the signal is received."}, {LLDB_OPT_SET_1, false, "pass", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- // CommandObjectMultiwordProcess //------------------------------------------------------------------------- -CommandObjectMultiwordProcess::CommandObjectMultiwordProcess(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "process", "Commands for interacting with processes on the current platform.", - "process <subcommand> [<subcommand-options>]") -{ - LoadSubCommand ("attach", CommandObjectSP (new CommandObjectProcessAttach (interpreter))); - LoadSubCommand ("launch", CommandObjectSP (new CommandObjectProcessLaunch (interpreter))); - LoadSubCommand ("continue", CommandObjectSP (new CommandObjectProcessContinue (interpreter))); - LoadSubCommand ("connect", CommandObjectSP (new CommandObjectProcessConnect (interpreter))); - LoadSubCommand ("detach", CommandObjectSP (new CommandObjectProcessDetach (interpreter))); - LoadSubCommand ("load", CommandObjectSP (new CommandObjectProcessLoad (interpreter))); - LoadSubCommand ("unload", CommandObjectSP (new CommandObjectProcessUnload (interpreter))); - LoadSubCommand ("signal", CommandObjectSP (new CommandObjectProcessSignal (interpreter))); - LoadSubCommand ("handle", CommandObjectSP (new CommandObjectProcessHandle (interpreter))); - LoadSubCommand ("status", CommandObjectSP (new CommandObjectProcessStatus (interpreter))); - LoadSubCommand ("interrupt", CommandObjectSP (new CommandObjectProcessInterrupt (interpreter))); - LoadSubCommand ("kill", CommandObjectSP (new CommandObjectProcessKill (interpreter))); - LoadSubCommand ("plugin", CommandObjectSP (new CommandObjectProcessPlugin (interpreter))); - LoadSubCommand ("save-core", CommandObjectSP (new CommandObjectProcessSaveCore (interpreter))); +CommandObjectMultiwordProcess::CommandObjectMultiwordProcess( + CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "process", + "Commands for interacting with processes on the current platform.", + "process <subcommand> [<subcommand-options>]") { + LoadSubCommand("attach", + CommandObjectSP(new CommandObjectProcessAttach(interpreter))); + LoadSubCommand("launch", + CommandObjectSP(new CommandObjectProcessLaunch(interpreter))); + LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue( + interpreter))); + LoadSubCommand("connect", + CommandObjectSP(new CommandObjectProcessConnect(interpreter))); + LoadSubCommand("detach", + CommandObjectSP(new CommandObjectProcessDetach(interpreter))); + LoadSubCommand("load", + CommandObjectSP(new CommandObjectProcessLoad(interpreter))); + LoadSubCommand("unload", + CommandObjectSP(new CommandObjectProcessUnload(interpreter))); + LoadSubCommand("signal", + CommandObjectSP(new CommandObjectProcessSignal(interpreter))); + LoadSubCommand("handle", + CommandObjectSP(new CommandObjectProcessHandle(interpreter))); + LoadSubCommand("status", + CommandObjectSP(new CommandObjectProcessStatus(interpreter))); + LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt( + interpreter))); + LoadSubCommand("kill", + CommandObjectSP(new CommandObjectProcessKill(interpreter))); + LoadSubCommand("plugin", + CommandObjectSP(new CommandObjectProcessPlugin(interpreter))); + LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore( + interpreter))); } CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default; diff --git a/lldb/source/Commands/CommandObjectProcess.h b/lldb/source/Commands/CommandObjectProcess.h index 804c342..0f520f6 100644 --- a/lldb/source/Commands/CommandObjectProcess.h +++ b/lldb/source/Commands/CommandObjectProcess.h @@ -22,12 +22,11 @@ namespace lldb_private { // CommandObjectMultiwordProcess //------------------------------------------------------------------------- -class CommandObjectMultiwordProcess : public CommandObjectMultiword -{ +class CommandObjectMultiwordProcess : public CommandObjectMultiword { public: - CommandObjectMultiwordProcess (CommandInterpreter &interpreter); + CommandObjectMultiwordProcess(CommandInterpreter &interpreter); - ~CommandObjectMultiwordProcess() override; + ~CommandObjectMultiwordProcess() override; }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectQuit.cpp b/lldb/source/Commands/CommandObjectQuit.cpp index a650398..2f258b7 100644 --- a/lldb/source/Commands/CommandObjectQuit.cpp +++ b/lldb/source/Commands/CommandObjectQuit.cpp @@ -25,75 +25,62 @@ using namespace lldb_private; //------------------------------------------------------------------------- CommandObjectQuit::CommandObjectQuit(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "quit", "Quit the LLDB debugger.", "quit") -{ -} + : CommandObjectParsed(interpreter, "quit", "Quit the LLDB debugger.", + "quit") {} -CommandObjectQuit::~CommandObjectQuit () -{ -} +CommandObjectQuit::~CommandObjectQuit() {} // returns true if there is at least one alive process -// is_a_detach will be true if all alive processes will be detached when you quit +// is_a_detach will be true if all alive processes will be detached when you +// quit // and false if at least one process will be killed instead -bool -CommandObjectQuit::ShouldAskForConfirmation (bool& is_a_detach) -{ - if (m_interpreter.GetPromptOnQuit() == false) - return false; - bool should_prompt = false; - is_a_detach = true; - for (uint32_t debugger_idx = 0; - debugger_idx < Debugger::GetNumDebuggers(); - debugger_idx++) - { - DebuggerSP debugger_sp(Debugger::GetDebuggerAtIndex(debugger_idx)); - if (!debugger_sp) - continue; - const TargetList& target_list(debugger_sp->GetTargetList()); - for (uint32_t target_idx = 0; - target_idx < static_cast<uint32_t>(target_list.GetNumTargets()); - target_idx++) - { - TargetSP target_sp(target_list.GetTargetAtIndex(target_idx)); - if (!target_sp) - continue; - ProcessSP process_sp(target_sp->GetProcessSP()); - if (process_sp - && process_sp->IsValid() - && process_sp->IsAlive() - && process_sp->WarnBeforeDetach()) - { - should_prompt = true; - if (process_sp->GetShouldDetach() == false) - { - // if we need to kill at least one process, just say so and return - is_a_detach = false; - return should_prompt; - } - } +bool CommandObjectQuit::ShouldAskForConfirmation(bool &is_a_detach) { + if (m_interpreter.GetPromptOnQuit() == false) + return false; + bool should_prompt = false; + is_a_detach = true; + for (uint32_t debugger_idx = 0; debugger_idx < Debugger::GetNumDebuggers(); + debugger_idx++) { + DebuggerSP debugger_sp(Debugger::GetDebuggerAtIndex(debugger_idx)); + if (!debugger_sp) + continue; + const TargetList &target_list(debugger_sp->GetTargetList()); + for (uint32_t target_idx = 0; + target_idx < static_cast<uint32_t>(target_list.GetNumTargets()); + target_idx++) { + TargetSP target_sp(target_list.GetTargetAtIndex(target_idx)); + if (!target_sp) + continue; + ProcessSP process_sp(target_sp->GetProcessSP()); + if (process_sp && process_sp->IsValid() && process_sp->IsAlive() && + process_sp->WarnBeforeDetach()) { + should_prompt = true; + if (process_sp->GetShouldDetach() == false) { + // if we need to kill at least one process, just say so and return + is_a_detach = false; + return should_prompt; } + } } - return should_prompt; + } + return should_prompt; } -bool -CommandObjectQuit::DoExecute (Args& command, CommandReturnObject &result) -{ - bool is_a_detach = true; - if (ShouldAskForConfirmation (is_a_detach)) - { - StreamString message; - message.Printf("Quitting LLDB will %s one or more processes. Do you really want to proceed", (is_a_detach ? "detach from" : "kill")); - if (!m_interpreter.Confirm(message.GetData(), true)) - { - result.SetStatus(eReturnStatusFailed); - return false; - } +bool CommandObjectQuit::DoExecute(Args &command, CommandReturnObject &result) { + bool is_a_detach = true; + if (ShouldAskForConfirmation(is_a_detach)) { + StreamString message; + message.Printf("Quitting LLDB will %s one or more processes. Do you really " + "want to proceed", + (is_a_detach ? "detach from" : "kill")); + if (!m_interpreter.Confirm(message.GetData(), true)) { + result.SetStatus(eReturnStatusFailed); + return false; } - const uint32_t event_type = CommandInterpreter::eBroadcastBitQuitCommandReceived; - m_interpreter.BroadcastEvent (event_type); - result.SetStatus (eReturnStatusQuit); - return true; + } + const uint32_t event_type = + CommandInterpreter::eBroadcastBitQuitCommandReceived; + m_interpreter.BroadcastEvent(event_type); + result.SetStatus(eReturnStatusQuit); + return true; } - diff --git a/lldb/source/Commands/CommandObjectQuit.h b/lldb/source/Commands/CommandObjectQuit.h index df9216b..f2998f8 100644 --- a/lldb/source/Commands/CommandObjectQuit.h +++ b/lldb/source/Commands/CommandObjectQuit.h @@ -22,21 +22,16 @@ namespace lldb_private { // CommandObjectQuit //------------------------------------------------------------------------- -class CommandObjectQuit : public CommandObjectParsed -{ +class CommandObjectQuit : public CommandObjectParsed { public: + CommandObjectQuit(CommandInterpreter &interpreter); - CommandObjectQuit (CommandInterpreter &interpreter); - - ~CommandObjectQuit() override; + ~CommandObjectQuit() override; protected: - bool - DoExecute(Args& args, - CommandReturnObject &result) override; - - bool - ShouldAskForConfirmation (bool& is_a_detach); + bool DoExecute(Args &args, CommandReturnObject &result) override; + + bool ShouldAskForConfirmation(bool &is_a_detach); }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectRegister.cpp b/lldb/source/Commands/CommandObjectRegister.cpp index cc5c161..47a079d 100644 --- a/lldb/source/Commands/CommandObjectRegister.cpp +++ b/lldb/source/Commands/CommandObjectRegister.cpp @@ -15,17 +15,17 @@ // Project includes #include "CommandObjectRegister.h" #include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Debugger.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" -#include "lldb/Core/Debugger.h" #include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/OptionGroupFormat.h" #include "lldb/Interpreter/OptionValueArray.h" #include "lldb/Interpreter/OptionValueBoolean.h" #include "lldb/Interpreter/OptionValueUInt64.h" +#include "lldb/Interpreter/Options.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -38,432 +38,377 @@ using namespace lldb_private; //---------------------------------------------------------------------- // "register read" //---------------------------------------------------------------------- -class CommandObjectRegisterRead : public CommandObjectParsed -{ +class CommandObjectRegisterRead : public CommandObjectParsed { public: - CommandObjectRegisterRead (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "register read", - "Dump the contents of one or more register values from the current frame. If no register is specified, dumps them all.", - nullptr, - eCommandRequiresFrame | - eCommandRequiresRegContext | - eCommandProcessMustBeLaunched | - eCommandProcessMustBePaused ), - m_option_group(), - m_format_options (eFormatDefault), - m_command_options () - { - CommandArgumentEntry arg; - CommandArgumentData register_arg; - - // Define the first (and only) variant of this arg. - register_arg.arg_type = eArgTypeRegisterName; - register_arg.arg_repetition = eArgRepeatStar; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (register_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - - // Add the "--format" - m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_ALL); - m_option_group.Append (&m_command_options); - m_option_group.Finalize(); - } - - ~CommandObjectRegisterRead() override = default; - - Options * - GetOptions () override - { - return &m_option_group; - } - - bool - DumpRegister (const ExecutionContext &exe_ctx, - Stream &strm, - RegisterContext *reg_ctx, - const RegisterInfo *reg_info) - { - if (reg_info) - { - RegisterValue reg_value; - - if (reg_ctx->ReadRegister (reg_info, reg_value)) - { - strm.Indent (); - - bool prefix_with_altname = (bool)m_command_options.alternate_name; - bool prefix_with_name = !prefix_with_altname; - reg_value.Dump(&strm, reg_info, prefix_with_name, prefix_with_altname, m_format_options.GetFormat(), 8); - if ((reg_info->encoding == eEncodingUint) || (reg_info->encoding == eEncodingSint)) - { - Process *process = exe_ctx.GetProcessPtr(); - if (process && reg_info->byte_size == process->GetAddressByteSize()) - { - addr_t reg_addr = reg_value.GetAsUInt64(LLDB_INVALID_ADDRESS); - if (reg_addr != LLDB_INVALID_ADDRESS) - { - Address so_reg_addr; - if (exe_ctx.GetTargetRef().GetSectionLoadList().ResolveLoadAddress(reg_addr, so_reg_addr)) - { - strm.PutCString (" "); - so_reg_addr.Dump(&strm, exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription); - } - } - } - } - strm.EOL(); - return true; + CommandObjectRegisterRead(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "register read", + "Dump the contents of one or more register values from the current " + "frame. If no register is specified, dumps them all.", + nullptr, + eCommandRequiresFrame | eCommandRequiresRegContext | + eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), + m_option_group(), m_format_options(eFormatDefault), + m_command_options() { + CommandArgumentEntry arg; + CommandArgumentData register_arg; + + // Define the first (and only) variant of this arg. + register_arg.arg_type = eArgTypeRegisterName; + register_arg.arg_repetition = eArgRepeatStar; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(register_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + + // Add the "--format" + m_option_group.Append(&m_format_options, + OptionGroupFormat::OPTION_GROUP_FORMAT | + OptionGroupFormat::OPTION_GROUP_GDB_FMT, + LLDB_OPT_SET_ALL); + m_option_group.Append(&m_command_options); + m_option_group.Finalize(); + } + + ~CommandObjectRegisterRead() override = default; + + Options *GetOptions() override { return &m_option_group; } + + bool DumpRegister(const ExecutionContext &exe_ctx, Stream &strm, + RegisterContext *reg_ctx, const RegisterInfo *reg_info) { + if (reg_info) { + RegisterValue reg_value; + + if (reg_ctx->ReadRegister(reg_info, reg_value)) { + strm.Indent(); + + bool prefix_with_altname = (bool)m_command_options.alternate_name; + bool prefix_with_name = !prefix_with_altname; + reg_value.Dump(&strm, reg_info, prefix_with_name, prefix_with_altname, + m_format_options.GetFormat(), 8); + if ((reg_info->encoding == eEncodingUint) || + (reg_info->encoding == eEncodingSint)) { + Process *process = exe_ctx.GetProcessPtr(); + if (process && reg_info->byte_size == process->GetAddressByteSize()) { + addr_t reg_addr = reg_value.GetAsUInt64(LLDB_INVALID_ADDRESS); + if (reg_addr != LLDB_INVALID_ADDRESS) { + Address so_reg_addr; + if (exe_ctx.GetTargetRef() + .GetSectionLoadList() + .ResolveLoadAddress(reg_addr, so_reg_addr)) { + strm.PutCString(" "); + so_reg_addr.Dump(&strm, exe_ctx.GetBestExecutionContextScope(), + Address::DumpStyleResolvedDescription); + } } + } } - return false; + strm.EOL(); + return true; + } } - - bool - DumpRegisterSet (const ExecutionContext &exe_ctx, - Stream &strm, - RegisterContext *reg_ctx, - size_t set_idx, - bool primitive_only=false) - { - uint32_t unavailable_count = 0; - uint32_t available_count = 0; - - if (!reg_ctx) - return false; // thread has no registers (i.e. core files are corrupt, incomplete crash logs...) - - const RegisterSet * const reg_set = reg_ctx->GetRegisterSet(set_idx); - if (reg_set) - { - strm.Printf ("%s:\n", (reg_set->name ? reg_set->name : "unknown") ); - strm.IndentMore (); - const size_t num_registers = reg_set->num_registers; - for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) - { - const uint32_t reg = reg_set->registers[reg_idx]; - const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg); - // Skip the dumping of derived register if primitive_only is true. - if (primitive_only && reg_info && reg_info->value_regs) - continue; - - if (DumpRegister (exe_ctx, strm, reg_ctx, reg_info)) - ++available_count; - else - ++unavailable_count; - } - strm.IndentLess (); - if (unavailable_count) - { - strm.Indent (); - strm.Printf("%u registers were unavailable.\n", unavailable_count); - } - strm.EOL(); - } - return available_count > 0; + return false; + } + + bool DumpRegisterSet(const ExecutionContext &exe_ctx, Stream &strm, + RegisterContext *reg_ctx, size_t set_idx, + bool primitive_only = false) { + uint32_t unavailable_count = 0; + uint32_t available_count = 0; + + if (!reg_ctx) + return false; // thread has no registers (i.e. core files are corrupt, + // incomplete crash logs...) + + const RegisterSet *const reg_set = reg_ctx->GetRegisterSet(set_idx); + if (reg_set) { + strm.Printf("%s:\n", (reg_set->name ? reg_set->name : "unknown")); + strm.IndentMore(); + const size_t num_registers = reg_set->num_registers; + for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) { + const uint32_t reg = reg_set->registers[reg_idx]; + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg); + // Skip the dumping of derived register if primitive_only is true. + if (primitive_only && reg_info && reg_info->value_regs) + continue; + + if (DumpRegister(exe_ctx, strm, reg_ctx, reg_info)) + ++available_count; + else + ++unavailable_count; + } + strm.IndentLess(); + if (unavailable_count) { + strm.Indent(); + strm.Printf("%u registers were unavailable.\n", unavailable_count); + } + strm.EOL(); } + return available_count > 0; + } protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Stream &strm = result.GetOutputStream(); - RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext (); - - const RegisterInfo *reg_info = nullptr; - if (command.GetArgumentCount() == 0) - { - size_t set_idx; - - size_t num_register_sets = 1; - const size_t set_array_size = m_command_options.set_indexes.GetSize(); - if (set_array_size > 0) - { - for (size_t i = 0; i < set_array_size; ++i) - { - set_idx = m_command_options.set_indexes[i]->GetUInt64Value(UINT32_MAX, nullptr); - if (set_idx < reg_ctx->GetRegisterSetCount()) - { - if (!DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx)) - { - if (errno) - result.AppendErrorWithFormat ("register read failed: %s\n", strerror(errno)); - else - result.AppendError ("unknown error while reading registers.\n"); - result.SetStatus (eReturnStatusFailed); - break; - } - } - else - { - result.AppendErrorWithFormat("invalid register set index: %" PRIu64 "\n", (uint64_t)set_idx); - result.SetStatus (eReturnStatusFailed); - break; - } - } - } - else - { - if (m_command_options.dump_all_sets) - num_register_sets = reg_ctx->GetRegisterSetCount(); - - for (set_idx = 0; set_idx < num_register_sets; ++set_idx) - { - // When dump_all_sets option is set, dump primitive as well as derived registers. - DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx, !m_command_options.dump_all_sets.GetCurrentValue()); - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + Stream &strm = result.GetOutputStream(); + RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); + + const RegisterInfo *reg_info = nullptr; + if (command.GetArgumentCount() == 0) { + size_t set_idx; + + size_t num_register_sets = 1; + const size_t set_array_size = m_command_options.set_indexes.GetSize(); + if (set_array_size > 0) { + for (size_t i = 0; i < set_array_size; ++i) { + set_idx = m_command_options.set_indexes[i]->GetUInt64Value(UINT32_MAX, + nullptr); + if (set_idx < reg_ctx->GetRegisterSetCount()) { + if (!DumpRegisterSet(m_exe_ctx, strm, reg_ctx, set_idx)) { + if (errno) + result.AppendErrorWithFormat("register read failed: %s\n", + strerror(errno)); + else + result.AppendError("unknown error while reading registers.\n"); + result.SetStatus(eReturnStatusFailed); + break; } + } else { + result.AppendErrorWithFormat( + "invalid register set index: %" PRIu64 "\n", (uint64_t)set_idx); + result.SetStatus(eReturnStatusFailed); + break; + } } - else - { - if (m_command_options.dump_all_sets) - { - result.AppendError ("the --all option can't be used when registers names are supplied as arguments\n"); - result.SetStatus (eReturnStatusFailed); - } - else if (m_command_options.set_indexes.GetSize() > 0) - { - result.AppendError ("the --set <set> option can't be used when registers names are supplied as arguments\n"); - result.SetStatus (eReturnStatusFailed); - } - else - { - const char *arg_cstr; - for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; ++arg_idx) - { - // in most LLDB commands we accept $rbx as the name for register RBX - and here we would - // reject it and non-existant. we should be more consistent towards the user and allow them - // to say reg read $rbx - internally, however, we should be strict and not allow ourselves - // to call our registers $rbx in our own API - if (*arg_cstr == '$') - arg_cstr = arg_cstr+1; - reg_info = reg_ctx->GetRegisterInfoByName(arg_cstr); - - if (reg_info) - { - if (!DumpRegister (m_exe_ctx, strm, reg_ctx, reg_info)) - strm.Printf("%-12s = error: unavailable\n", reg_info->name); - } - else - { - result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr); - } - } - } + } else { + if (m_command_options.dump_all_sets) + num_register_sets = reg_ctx->GetRegisterSetCount(); + + for (set_idx = 0; set_idx < num_register_sets; ++set_idx) { + // When dump_all_sets option is set, dump primitive as well as derived + // registers. + DumpRegisterSet(m_exe_ctx, strm, reg_ctx, set_idx, + !m_command_options.dump_all_sets.GetCurrentValue()); } - return result.Succeeded(); + } + } else { + if (m_command_options.dump_all_sets) { + result.AppendError("the --all option can't be used when registers " + "names are supplied as arguments\n"); + result.SetStatus(eReturnStatusFailed); + } else if (m_command_options.set_indexes.GetSize() > 0) { + result.AppendError("the --set <set> option can't be used when " + "registers names are supplied as arguments\n"); + result.SetStatus(eReturnStatusFailed); + } else { + const char *arg_cstr; + for (int arg_idx = 0; + (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; + ++arg_idx) { + // in most LLDB commands we accept $rbx as the name for register RBX - + // and here we would + // reject it and non-existant. we should be more consistent towards + // the user and allow them + // to say reg read $rbx - internally, however, we should be strict and + // not allow ourselves + // to call our registers $rbx in our own API + if (*arg_cstr == '$') + arg_cstr = arg_cstr + 1; + reg_info = reg_ctx->GetRegisterInfoByName(arg_cstr); + + if (reg_info) { + if (!DumpRegister(m_exe_ctx, strm, reg_ctx, reg_info)) + strm.Printf("%-12s = error: unavailable\n", reg_info->name); + } else { + result.AppendErrorWithFormat("Invalid register name '%s'.\n", + arg_cstr); + } + } + } } + return result.Succeeded(); + } - class CommandOptions : public OptionGroup - { - public: - CommandOptions () : - OptionGroup(), - set_indexes (OptionValue::ConvertTypeToMask (OptionValue::eTypeUInt64)), - dump_all_sets (false, false), // Initial and default values are false - alternate_name (false, false) - { - } + class CommandOptions : public OptionGroup { + public: + CommandOptions() + : OptionGroup(), + set_indexes(OptionValue::ConvertTypeToMask(OptionValue::eTypeUInt64)), + dump_all_sets(false, false), // Initial and default values are false + alternate_name(false, false) {} - ~CommandOptions() override = default; + ~CommandOptions() override = default; - uint32_t - GetNumDefinitions () override; + uint32_t GetNumDefinitions() override; - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - set_indexes.Clear(); - dump_all_sets.Clear(); - alternate_name.Clear(); - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } - Error - SetOptionValue (uint32_t option_idx, - const char *option_value, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = g_option_table[option_idx].short_option; - switch (short_option) - { - case 's': - { - OptionValueSP value_sp (OptionValueUInt64::Create (option_value, error)); - if (value_sp) - set_indexes.AppendValue (value_sp); - } - break; - - case 'a': - // When we don't use OptionValue::SetValueFromCString(const char *) to - // set an option value, it won't be marked as being set in the options - // so we make a call to let users know the value was set via option - dump_all_sets.SetCurrentValue (true); - dump_all_sets.SetOptionWasSet (); - break; - - case 'A': - // When we don't use OptionValue::SetValueFromCString(const char *) to - // set an option value, it won't be marked as being set in the options - // so we make a call to let users know the value was set via option - alternate_name.SetCurrentValue (true); - dump_all_sets.SetOptionWasSet (); - break; - - default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); - break; - } - return error; - } - - // Options table: Required for subclasses of Options. - - static const OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - OptionValueArray set_indexes; - OptionValueBoolean dump_all_sets; - OptionValueBoolean alternate_name; - }; - - OptionGroupOptions m_option_group; - OptionGroupFormat m_format_options; - CommandOptions m_command_options; + void OptionParsingStarting(ExecutionContext *execution_context) override { + set_indexes.Clear(); + dump_all_sets.Clear(); + alternate_name.Clear(); + } + + Error SetOptionValue(uint32_t option_idx, const char *option_value, + ExecutionContext *execution_context) override { + Error error; + const int short_option = g_option_table[option_idx].short_option; + switch (short_option) { + case 's': { + OptionValueSP value_sp(OptionValueUInt64::Create(option_value, error)); + if (value_sp) + set_indexes.AppendValue(value_sp); + } break; + + case 'a': + // When we don't use OptionValue::SetValueFromCString(const char *) to + // set an option value, it won't be marked as being set in the options + // so we make a call to let users know the value was set via option + dump_all_sets.SetCurrentValue(true); + dump_all_sets.SetOptionWasSet(); + break; + + case 'A': + // When we don't use OptionValue::SetValueFromCString(const char *) to + // set an option value, it won't be marked as being set in the options + // so we make a call to let users know the value was set via option + alternate_name.SetCurrentValue(true); + dump_all_sets.SetOptionWasSet(); + break; + + default: + error.SetErrorStringWithFormat("unrecognized short option '%c'", + short_option); + break; + } + return error; + } + + // Options table: Required for subclasses of Options. + + static const OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + OptionValueArray set_indexes; + OptionValueBoolean dump_all_sets; + OptionValueBoolean alternate_name; + }; + + OptionGroupOptions m_option_group; + OptionGroupFormat m_format_options; + CommandOptions m_command_options; }; const OptionDefinition -CommandObjectRegisterRead::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectRegisterRead::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_ALL, false, "alternate", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display register names using the alternate register name if there is one."}, {LLDB_OPT_SET_1, false, "set", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeIndex, "Specify which register sets to dump by index."}, {LLDB_OPT_SET_2, false, "all", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show all register sets."}, - // clang-format on + // clang-format on }; -uint32_t -CommandObjectRegisterRead::CommandOptions::GetNumDefinitions () -{ - return llvm::array_lengthof(g_option_table); +uint32_t CommandObjectRegisterRead::CommandOptions::GetNumDefinitions() { + return llvm::array_lengthof(g_option_table); } //---------------------------------------------------------------------- // "register write" //---------------------------------------------------------------------- -class CommandObjectRegisterWrite : public CommandObjectParsed -{ +class CommandObjectRegisterWrite : public CommandObjectParsed { public: - CommandObjectRegisterWrite (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "register write", - "Modify a single register value.", - nullptr, - eCommandRequiresFrame | - eCommandRequiresRegContext | - eCommandProcessMustBeLaunched | - eCommandProcessMustBePaused) - { - CommandArgumentEntry arg1; - CommandArgumentEntry arg2; - CommandArgumentData register_arg; - CommandArgumentData value_arg; - - // Define the first (and only) variant of this arg. - register_arg.arg_type = eArgTypeRegisterName; - register_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg1.push_back (register_arg); - - // Define the first (and only) variant of this arg. - value_arg.arg_type = eArgTypeValue; - value_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg2.push_back (value_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg1); - m_arguments.push_back (arg2); - } - - ~CommandObjectRegisterWrite() override = default; + CommandObjectRegisterWrite(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "register write", + "Modify a single register value.", nullptr, + eCommandRequiresFrame | eCommandRequiresRegContext | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused) { + CommandArgumentEntry arg1; + CommandArgumentEntry arg2; + CommandArgumentData register_arg; + CommandArgumentData value_arg; + + // Define the first (and only) variant of this arg. + register_arg.arg_type = eArgTypeRegisterName; + register_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg1.push_back(register_arg); + + // Define the first (and only) variant of this arg. + value_arg.arg_type = eArgTypeValue; + value_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg2.push_back(value_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg1); + m_arguments.push_back(arg2); + } + + ~CommandObjectRegisterWrite() override = default; protected: - bool - DoExecute(Args& command, CommandReturnObject &result) override - { - DataExtractor reg_data; - RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext (); - - if (command.GetArgumentCount() != 2) - { - result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>"); - result.SetStatus (eReturnStatusFailed); + bool DoExecute(Args &command, CommandReturnObject &result) override { + DataExtractor reg_data; + RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); + + if (command.GetArgumentCount() != 2) { + result.AppendError( + "register write takes exactly 2 arguments: <reg-name> <value>"); + result.SetStatus(eReturnStatusFailed); + } else { + const char *reg_name = command.GetArgumentAtIndex(0); + const char *value_str = command.GetArgumentAtIndex(1); + + // in most LLDB commands we accept $rbx as the name for register RBX - and + // here we would + // reject it and non-existant. we should be more consistent towards the + // user and allow them + // to say reg write $rbx - internally, however, we should be strict and + // not allow ourselves + // to call our registers $rbx in our own API + if (reg_name && *reg_name == '$') + reg_name = reg_name + 1; + + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); + + if (reg_info) { + RegisterValue reg_value; + + Error error(reg_value.SetValueFromCString(reg_info, value_str)); + if (error.Success()) { + if (reg_ctx->WriteRegister(reg_info, reg_value)) { + // Toss all frames and anything else in the thread + // after a register has been written. + m_exe_ctx.GetThreadRef().Flush(); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return true; + } } - else - { - const char *reg_name = command.GetArgumentAtIndex(0); - const char *value_str = command.GetArgumentAtIndex(1); - - // in most LLDB commands we accept $rbx as the name for register RBX - and here we would - // reject it and non-existant. we should be more consistent towards the user and allow them - // to say reg write $rbx - internally, however, we should be strict and not allow ourselves - // to call our registers $rbx in our own API - if (reg_name && *reg_name == '$') - reg_name = reg_name+1; - - const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); - - if (reg_info) - { - RegisterValue reg_value; - - Error error (reg_value.SetValueFromCString (reg_info, value_str)); - if (error.Success()) - { - if (reg_ctx->WriteRegister (reg_info, reg_value)) - { - // Toss all frames and anything else in the thread - // after a register has been written. - m_exe_ctx.GetThreadRef().Flush(); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - return true; - } - } - if (error.AsCString()) - { - result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n", - reg_name, - value_str, - error.AsCString()); - } - else - { - result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s'", - reg_name, - value_str); - } - result.SetStatus (eReturnStatusFailed); - } - else - { - result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name); - result.SetStatus (eReturnStatusFailed); - } + if (error.AsCString()) { + result.AppendErrorWithFormat( + "Failed to write register '%s' with value '%s': %s\n", reg_name, + value_str, error.AsCString()); + } else { + result.AppendErrorWithFormat( + "Failed to write register '%s' with value '%s'", reg_name, + value_str); } - return result.Succeeded(); + result.SetStatus(eReturnStatusFailed); + } else { + result.AppendErrorWithFormat("Register not found for '%s'.\n", + reg_name); + result.SetStatus(eReturnStatusFailed); + } } + return result.Succeeded(); + } }; //---------------------------------------------------------------------- @@ -471,11 +416,13 @@ protected: //---------------------------------------------------------------------- CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter) : CommandObjectMultiword(interpreter, "register", - "Commands to access registers for the current thread and stack frame.", - "register [read|write] ...") -{ - LoadSubCommand ("read", CommandObjectSP (new CommandObjectRegisterRead (interpreter))); - LoadSubCommand ("write", CommandObjectSP (new CommandObjectRegisterWrite (interpreter))); + "Commands to access registers for the current " + "thread and stack frame.", + "register [read|write] ...") { + LoadSubCommand("read", + CommandObjectSP(new CommandObjectRegisterRead(interpreter))); + LoadSubCommand("write", + CommandObjectSP(new CommandObjectRegisterWrite(interpreter))); } CommandObjectRegister::~CommandObjectRegister() = default; diff --git a/lldb/source/Commands/CommandObjectRegister.h b/lldb/source/Commands/CommandObjectRegister.h index e7b6974..81f2f6b 100644 --- a/lldb/source/Commands/CommandObjectRegister.h +++ b/lldb/source/Commands/CommandObjectRegister.h @@ -22,21 +22,20 @@ namespace lldb_private { // CommandObjectRegister //------------------------------------------------------------------------- -class CommandObjectRegister : public CommandObjectMultiword -{ +class CommandObjectRegister : public CommandObjectMultiword { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - CommandObjectRegister(CommandInterpreter &interpreter); + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + CommandObjectRegister(CommandInterpreter &interpreter); - ~CommandObjectRegister() override; + ~CommandObjectRegister() override; private: - //------------------------------------------------------------------ - // For CommandObjectRegister only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN (CommandObjectRegister); + //------------------------------------------------------------------ + // For CommandObjectRegister only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN(CommandObjectRegister); }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectSettings.cpp b/lldb/source/Commands/CommandObjectSettings.cpp index 4c33f1d8..4d545d7 100644 --- a/lldb/source/Commands/CommandObjectSettings.cpp +++ b/lldb/source/Commands/CommandObjectSettings.cpp @@ -15,9 +15,9 @@ #include "llvm/ADT/StringRef.h" // Project includes +#include "lldb/Interpreter/CommandCompletions.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Interpreter/CommandCompletions.h" #include "lldb/Interpreter/OptionValueProperties.h" using namespace lldb; @@ -27,39 +27,42 @@ using namespace lldb_private; // CommandObjectSettingsSet //------------------------------------------------------------------------- -class CommandObjectSettingsSet : public CommandObjectRaw -{ +class CommandObjectSettingsSet : public CommandObjectRaw { public: - CommandObjectSettingsSet(CommandInterpreter &interpreter) - : CommandObjectRaw(interpreter, "settings set", "Set the value of the specified debugger setting.", nullptr), - m_options() - { - CommandArgumentEntry arg1; - CommandArgumentEntry arg2; - CommandArgumentData var_name_arg; - CommandArgumentData value_arg; - - // Define the first (and only) variant of this arg. - var_name_arg.arg_type = eArgTypeSettingVariableName; - var_name_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg1.push_back (var_name_arg); - - // Define the first (and only) variant of this arg. - value_arg.arg_type = eArgTypeValue; - value_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg2.push_back (value_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg1); - m_arguments.push_back (arg2); - - SetHelpLong ( -"\nWhen setting a dictionary or array variable, you can set multiple entries \ -at once by giving the values to the set command. For example:" R"( + CommandObjectSettingsSet(CommandInterpreter &interpreter) + : CommandObjectRaw(interpreter, "settings set", + "Set the value of the specified debugger setting.", + nullptr), + m_options() { + CommandArgumentEntry arg1; + CommandArgumentEntry arg2; + CommandArgumentData var_name_arg; + CommandArgumentData value_arg; + + // Define the first (and only) variant of this arg. + var_name_arg.arg_type = eArgTypeSettingVariableName; + var_name_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg1.push_back(var_name_arg); + + // Define the first (and only) variant of this arg. + value_arg.arg_type = eArgTypeValue; + value_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg2.push_back(value_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg1); + m_arguments.push_back(arg2); + + SetHelpLong( + "\nWhen setting a dictionary or array variable, you can set multiple entries \ +at once by giving the values to the set command. For example:" + R"( (lldb) settings set target.run-args value1 value2 value3 (lldb) settings set target.env-vars MYPATH=~/.:/usr/bin SOME_ENV_VAR=12345 @@ -72,1108 +75,987 @@ at once by giving the values to the set command. For example:" R"( 'MYPATH=~/.:/usr/bin' 'SOME_ENV_VAR=12345' -)" "Warning: The 'set' command re-sets the entire array or dictionary. If you \ +)" + "Warning: The 'set' command re-sets the entire array or dictionary. If you \ just want to add, remove or update individual values (or add something to \ the end), use one of the other settings sub-commands: append, replace, \ -insert-before or insert-after." - ); +insert-before or insert-after."); + } - } + ~CommandObjectSettingsSet() override = default; + + // Overrides base class's behavior where WantsCompletion = + // !WantsRawCommandString. + bool WantsCompletion() override { return true; } + + Options *GetOptions() override { return &m_options; } + + class CommandOptions : public Options { + public: + CommandOptions() : Options(), m_global(false) {} + + ~CommandOptions() override = default; - ~CommandObjectSettingsSet() override = default; + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; - // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString. - bool - WantsCompletion() override { return true; } + switch (short_option) { + case 'g': + m_global = true; + break; + default: + error.SetErrorStringWithFormat("unrecognized options '%c'", + short_option); + break; + } - Options * - GetOptions () override - { - return &m_options; + return error; } - - class CommandOptions : public Options - { - public: - CommandOptions() : - Options(), - m_global(false) - { - } - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'g': - m_global = true; - break; - default: - error.SetErrorStringWithFormat ("unrecognized options '%c'", short_option); - break; - } - - return error; - } + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_global = false; + } - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_global = false; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - bool m_global; - }; - - int - HandleArgumentCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - OptionElementVector &opt_element_vector, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) override - { - std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position); - - const size_t argc = input.GetArgumentCount(); - const char *arg = nullptr; - int setting_var_idx; - for (setting_var_idx = 1; setting_var_idx < static_cast<int>(argc); - ++setting_var_idx) - { - arg = input.GetArgumentAtIndex(setting_var_idx); - if (arg && arg[0] != '-') - break; // We found our setting variable name index - } - if (cursor_index == setting_var_idx) - { - // Attempting to complete setting variable name - CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(), - CommandCompletions::eSettingsNameCompletion, - completion_str.c_str(), - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - } - else - { - arg = input.GetArgumentAtIndex(cursor_index); - - if (arg) - { - if (arg[0] == '-') - { - // Complete option name - } - else - { - // Complete setting value - const char *setting_var_name = input.GetArgumentAtIndex(setting_var_idx); - Error error; - lldb::OptionValueSP value_sp (m_interpreter.GetDebugger().GetPropertyValue(&m_exe_ctx, setting_var_name, false, error)); - if (value_sp) - { - value_sp->AutoComplete (m_interpreter, - completion_str.c_str(), - match_start_point, - max_return_elements, - word_complete, - matches); - } - } - } + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + bool m_global; + }; + + int HandleArgumentCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, int max_return_elements, + bool &word_complete, + StringList &matches) override { + std::string completion_str(input.GetArgumentAtIndex(cursor_index), + cursor_char_position); + + const size_t argc = input.GetArgumentCount(); + const char *arg = nullptr; + int setting_var_idx; + for (setting_var_idx = 1; setting_var_idx < static_cast<int>(argc); + ++setting_var_idx) { + arg = input.GetArgumentAtIndex(setting_var_idx); + if (arg && arg[0] != '-') + break; // We found our setting variable name index + } + if (cursor_index == setting_var_idx) { + // Attempting to complete setting variable name + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, + completion_str.c_str(), match_start_point, max_return_elements, + nullptr, word_complete, matches); + } else { + arg = input.GetArgumentAtIndex(cursor_index); + + if (arg) { + if (arg[0] == '-') { + // Complete option name + } else { + // Complete setting value + const char *setting_var_name = + input.GetArgumentAtIndex(setting_var_idx); + Error error; + lldb::OptionValueSP value_sp( + m_interpreter.GetDebugger().GetPropertyValue( + &m_exe_ctx, setting_var_name, false, error)); + if (value_sp) { + value_sp->AutoComplete(m_interpreter, completion_str.c_str(), + match_start_point, max_return_elements, + word_complete, matches); + } } - return matches.GetSize(); + } } - + return matches.GetSize(); + } + protected: - bool - DoExecute (const char *command, CommandReturnObject &result) override - { - Args cmd_args(command); - - // Process possible options. - if (!ParseOptions (cmd_args, result)) - return false; - - const size_t argc = cmd_args.GetArgumentCount (); - if ((argc < 2) && (!m_options.m_global)) - { - result.AppendError ("'settings set' takes more arguments"); - result.SetStatus (eReturnStatusFailed); - return false; - } + bool DoExecute(const char *command, CommandReturnObject &result) override { + Args cmd_args(command); + + // Process possible options. + if (!ParseOptions(cmd_args, result)) + return false; + + const size_t argc = cmd_args.GetArgumentCount(); + if ((argc < 2) && (!m_options.m_global)) { + result.AppendError("'settings set' takes more arguments"); + result.SetStatus(eReturnStatusFailed); + return false; + } - const char *var_name = cmd_args.GetArgumentAtIndex (0); - if ((var_name == nullptr) || (var_name[0] == '\0')) - { - result.AppendError ("'settings set' command requires a valid variable name"); - result.SetStatus (eReturnStatusFailed); - return false; - } + const char *var_name = cmd_args.GetArgumentAtIndex(0); + if ((var_name == nullptr) || (var_name[0] == '\0')) { + result.AppendError( + "'settings set' command requires a valid variable name"); + result.SetStatus(eReturnStatusFailed); + return false; + } - // Split the raw command into var_name and value pair. - llvm::StringRef raw_str(command); - std::string var_value_string = raw_str.split(var_name).second.str(); - const char *var_value_cstr = Args::StripSpaces(var_value_string, true, false, false); - - Error error; - if (m_options.m_global) - { - error = m_interpreter.GetDebugger().SetPropertyValue(nullptr, - eVarSetOperationAssign, - var_name, - var_value_cstr); - } - - if (error.Success()) - { - // FIXME this is the same issue as the one in commands script import - // we could be setting target.load-script-from-symbol-file which would cause - // Python scripts to be loaded, which could run LLDB commands - // (e.g. settings set target.process.python-os-plugin-path) and cause a crash - // if we did not clear the command's exe_ctx first - ExecutionContext exe_ctx(m_exe_ctx); - m_exe_ctx.Clear(); - error = m_interpreter.GetDebugger().SetPropertyValue (&exe_ctx, - eVarSetOperationAssign, - var_name, - var_value_cstr); - } + // Split the raw command into var_name and value pair. + llvm::StringRef raw_str(command); + std::string var_value_string = raw_str.split(var_name).second.str(); + const char *var_value_cstr = + Args::StripSpaces(var_value_string, true, false, false); - if (error.Fail()) - { - result.AppendError (error.AsCString()); - result.SetStatus (eReturnStatusFailed); - return false; - } - else - { - result.SetStatus (eReturnStatusSuccessFinishResult); - } + Error error; + if (m_options.m_global) { + error = m_interpreter.GetDebugger().SetPropertyValue( + nullptr, eVarSetOperationAssign, var_name, var_value_cstr); + } + + if (error.Success()) { + // FIXME this is the same issue as the one in commands script import + // we could be setting target.load-script-from-symbol-file which would + // cause + // Python scripts to be loaded, which could run LLDB commands + // (e.g. settings set target.process.python-os-plugin-path) and cause a + // crash + // if we did not clear the command's exe_ctx first + ExecutionContext exe_ctx(m_exe_ctx); + m_exe_ctx.Clear(); + error = m_interpreter.GetDebugger().SetPropertyValue( + &exe_ctx, eVarSetOperationAssign, var_name, var_value_cstr); + } - return result.Succeeded(); + if (error.Fail()) { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } else { + result.SetStatus(eReturnStatusSuccessFinishResult); } + return result.Succeeded(); + } + private: - CommandOptions m_options; + CommandOptions m_options; }; -OptionDefinition -CommandObjectSettingsSet::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectSettingsSet::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_2, false, "global", 'g', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Apply the new value to the global default value."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- // CommandObjectSettingsShow -- Show current values //------------------------------------------------------------------------- -class CommandObjectSettingsShow : public CommandObjectParsed -{ +class CommandObjectSettingsShow : public CommandObjectParsed { public: - CommandObjectSettingsShow(CommandInterpreter &interpreter) - : CommandObjectParsed( - interpreter, "settings show", - "Show matching debugger settings and their current values. Defaults to showing all settings.", nullptr) - { - CommandArgumentEntry arg1; - CommandArgumentData var_name_arg; - - // Define the first (and only) variant of this arg. - var_name_arg.arg_type = eArgTypeSettingVariableName; - var_name_arg.arg_repetition = eArgRepeatOptional; - - // There is only one variant this argument could be; put it into the argument entry. - arg1.push_back (var_name_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg1); - } - - ~CommandObjectSettingsShow() override = default; - - int - HandleArgumentCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - OptionElementVector &opt_element_vector, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) override - { - std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position); - - CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(), - CommandCompletions::eSettingsNameCompletion, - completion_str.c_str(), - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - return matches.GetSize(); - } + CommandObjectSettingsShow(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "settings show", + "Show matching debugger settings and their current " + "values. Defaults to showing all settings.", + nullptr) { + CommandArgumentEntry arg1; + CommandArgumentData var_name_arg; + + // Define the first (and only) variant of this arg. + var_name_arg.arg_type = eArgTypeSettingVariableName; + var_name_arg.arg_repetition = eArgRepeatOptional; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg1.push_back(var_name_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg1); + } + + ~CommandObjectSettingsShow() override = default; + + int HandleArgumentCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, int max_return_elements, + bool &word_complete, + StringList &matches) override { + std::string completion_str(input.GetArgumentAtIndex(cursor_index), + cursor_char_position); + + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, + completion_str.c_str(), match_start_point, max_return_elements, nullptr, + word_complete, matches); + return matches.GetSize(); + } protected: - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - result.SetStatus (eReturnStatusSuccessFinishResult); - - const size_t argc = args.GetArgumentCount (); - if (argc > 0) - { - for (size_t i = 0; i < argc; ++i) - { - const char *property_path = args.GetArgumentAtIndex (i); - - Error error(m_interpreter.GetDebugger().DumpPropertyValue (&m_exe_ctx, result.GetOutputStream(), property_path, OptionValue::eDumpGroupValue)); - if (error.Success()) - { - result.GetOutputStream().EOL(); - } - else - { - result.AppendError (error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - } - else - { - m_interpreter.GetDebugger().DumpAllPropertyValues (&m_exe_ctx, result.GetOutputStream(), OptionValue::eDumpGroupValue); + bool DoExecute(Args &args, CommandReturnObject &result) override { + result.SetStatus(eReturnStatusSuccessFinishResult); + + const size_t argc = args.GetArgumentCount(); + if (argc > 0) { + for (size_t i = 0; i < argc; ++i) { + const char *property_path = args.GetArgumentAtIndex(i); + + Error error(m_interpreter.GetDebugger().DumpPropertyValue( + &m_exe_ctx, result.GetOutputStream(), property_path, + OptionValue::eDumpGroupValue)); + if (error.Success()) { + result.GetOutputStream().EOL(); + } else { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); } - - return result.Succeeded(); + } + } else { + m_interpreter.GetDebugger().DumpAllPropertyValues( + &m_exe_ctx, result.GetOutputStream(), OptionValue::eDumpGroupValue); } + + return result.Succeeded(); + } }; //------------------------------------------------------------------------- // CommandObjectSettingsList -- List settable variables //------------------------------------------------------------------------- -class CommandObjectSettingsList : public CommandObjectParsed -{ +class CommandObjectSettingsList : public CommandObjectParsed { public: - CommandObjectSettingsList(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "settings list", - "List and describe matching debugger settings. Defaults to all listing all settings.", - nullptr) - { - CommandArgumentEntry arg; - CommandArgumentData var_name_arg; - CommandArgumentData prefix_name_arg; - - // Define the first variant of this arg. - var_name_arg.arg_type = eArgTypeSettingVariableName; - var_name_arg.arg_repetition = eArgRepeatOptional; - - // Define the second variant of this arg. - prefix_name_arg.arg_type = eArgTypeSettingPrefix; - prefix_name_arg.arg_repetition = eArgRepeatOptional; - - arg.push_back (var_name_arg); - arg.push_back (prefix_name_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - } - - ~CommandObjectSettingsList() override = default; - - int - HandleArgumentCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - OptionElementVector &opt_element_vector, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) override - { - std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position); - - CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(), - CommandCompletions::eSettingsNameCompletion, - completion_str.c_str(), - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - return matches.GetSize(); - } + CommandObjectSettingsList(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "settings list", + "List and describe matching debugger settings. " + "Defaults to all listing all settings.", + nullptr) { + CommandArgumentEntry arg; + CommandArgumentData var_name_arg; + CommandArgumentData prefix_name_arg; + + // Define the first variant of this arg. + var_name_arg.arg_type = eArgTypeSettingVariableName; + var_name_arg.arg_repetition = eArgRepeatOptional; + + // Define the second variant of this arg. + prefix_name_arg.arg_type = eArgTypeSettingPrefix; + prefix_name_arg.arg_repetition = eArgRepeatOptional; + + arg.push_back(var_name_arg); + arg.push_back(prefix_name_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectSettingsList() override = default; + + int HandleArgumentCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, int max_return_elements, + bool &word_complete, + StringList &matches) override { + std::string completion_str(input.GetArgumentAtIndex(cursor_index), + cursor_char_position); + + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, + completion_str.c_str(), match_start_point, max_return_elements, nullptr, + word_complete, matches); + return matches.GetSize(); + } protected: - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - result.SetStatus (eReturnStatusSuccessFinishResult); - - const bool will_modify = false; - const size_t argc = args.GetArgumentCount (); - if (argc > 0) - { - const bool dump_qualified_name = true; - - for (size_t i = 0; i < argc; ++i) - { - const char *property_path = args.GetArgumentAtIndex (i); - - const Property *property = m_interpreter.GetDebugger().GetValueProperties()->GetPropertyAtPath (&m_exe_ctx, will_modify, property_path); - - if (property) - { - property->DumpDescription (m_interpreter, result.GetOutputStream(), 0, dump_qualified_name); - } - else - { - result.AppendErrorWithFormat ("invalid property path '%s'", property_path); - result.SetStatus (eReturnStatusFailed); - } - } - } - else - { - m_interpreter.GetDebugger().DumpAllDescriptions (m_interpreter, result.GetOutputStream()); + bool DoExecute(Args &args, CommandReturnObject &result) override { + result.SetStatus(eReturnStatusSuccessFinishResult); + + const bool will_modify = false; + const size_t argc = args.GetArgumentCount(); + if (argc > 0) { + const bool dump_qualified_name = true; + + for (size_t i = 0; i < argc; ++i) { + const char *property_path = args.GetArgumentAtIndex(i); + + const Property *property = + m_interpreter.GetDebugger().GetValueProperties()->GetPropertyAtPath( + &m_exe_ctx, will_modify, property_path); + + if (property) { + property->DumpDescription(m_interpreter, result.GetOutputStream(), 0, + dump_qualified_name); + } else { + result.AppendErrorWithFormat("invalid property path '%s'", + property_path); + result.SetStatus(eReturnStatusFailed); } - - return result.Succeeded(); + } + } else { + m_interpreter.GetDebugger().DumpAllDescriptions(m_interpreter, + result.GetOutputStream()); } + + return result.Succeeded(); + } }; //------------------------------------------------------------------------- // CommandObjectSettingsRemove //------------------------------------------------------------------------- -class CommandObjectSettingsRemove : public CommandObjectRaw -{ +class CommandObjectSettingsRemove : public CommandObjectRaw { public: - CommandObjectSettingsRemove(CommandInterpreter &interpreter) - : CommandObjectRaw(interpreter, "settings remove", - "Remove a value from a setting, specified by array index or dictionary key.", nullptr) - { - CommandArgumentEntry arg1; - CommandArgumentEntry arg2; - CommandArgumentData var_name_arg; - CommandArgumentData index_arg; - CommandArgumentData key_arg; - - // Define the first (and only) variant of this arg. - var_name_arg.arg_type = eArgTypeSettingVariableName; - var_name_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg1.push_back (var_name_arg); - - // Define the first variant of this arg. - index_arg.arg_type = eArgTypeSettingIndex; - index_arg.arg_repetition = eArgRepeatPlain; - - // Define the second variant of this arg. - key_arg.arg_type = eArgTypeSettingKey; - key_arg.arg_repetition = eArgRepeatPlain; - - // Push both variants into this arg - arg2.push_back (index_arg); - arg2.push_back (key_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg1); - m_arguments.push_back (arg2); + CommandObjectSettingsRemove(CommandInterpreter &interpreter) + : CommandObjectRaw(interpreter, "settings remove", + "Remove a value from a setting, specified by array " + "index or dictionary key.", + nullptr) { + CommandArgumentEntry arg1; + CommandArgumentEntry arg2; + CommandArgumentData var_name_arg; + CommandArgumentData index_arg; + CommandArgumentData key_arg; + + // Define the first (and only) variant of this arg. + var_name_arg.arg_type = eArgTypeSettingVariableName; + var_name_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg1.push_back(var_name_arg); + + // Define the first variant of this arg. + index_arg.arg_type = eArgTypeSettingIndex; + index_arg.arg_repetition = eArgRepeatPlain; + + // Define the second variant of this arg. + key_arg.arg_type = eArgTypeSettingKey; + key_arg.arg_repetition = eArgRepeatPlain; + + // Push both variants into this arg + arg2.push_back(index_arg); + arg2.push_back(key_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg1); + m_arguments.push_back(arg2); + } + + ~CommandObjectSettingsRemove() override = default; + + int HandleArgumentCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, int max_return_elements, + bool &word_complete, + StringList &matches) override { + std::string completion_str(input.GetArgumentAtIndex(cursor_index), + cursor_char_position); + + // Attempting to complete variable name + if (cursor_index < 2) + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, + completion_str.c_str(), match_start_point, max_return_elements, + nullptr, word_complete, matches); + return matches.GetSize(); + } + +protected: + bool DoExecute(const char *command, CommandReturnObject &result) override { + result.SetStatus(eReturnStatusSuccessFinishNoResult); + + Args cmd_args(command); + + // Process possible options. + if (!ParseOptions(cmd_args, result)) + return false; + + const size_t argc = cmd_args.GetArgumentCount(); + if (argc == 0) { + result.AppendError("'settings set' takes an array or dictionary item, or " + "an array followed by one or more indexes, or a " + "dictionary followed by one or more key names to " + "remove"); + result.SetStatus(eReturnStatusFailed); + return false; } - ~CommandObjectSettingsRemove() override = default; - - int - HandleArgumentCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - OptionElementVector &opt_element_vector, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) override - { - std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position); - - // Attempting to complete variable name - if (cursor_index < 2) - CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(), - CommandCompletions::eSettingsNameCompletion, - completion_str.c_str(), - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - return matches.GetSize(); + const char *var_name = cmd_args.GetArgumentAtIndex(0); + if ((var_name == nullptr) || (var_name[0] == '\0')) { + result.AppendError( + "'settings set' command requires a valid variable name"); + result.SetStatus(eReturnStatusFailed); + return false; } -protected: - bool - DoExecute (const char *command, CommandReturnObject &result) override - { - result.SetStatus (eReturnStatusSuccessFinishNoResult); - - Args cmd_args(command); - - // Process possible options. - if (!ParseOptions (cmd_args, result)) - return false; - - const size_t argc = cmd_args.GetArgumentCount (); - if (argc == 0) - { - result.AppendError ("'settings set' takes an array or dictionary item, or an array followed by one or more indexes, or a dictionary followed by one or more key names to remove"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - const char *var_name = cmd_args.GetArgumentAtIndex (0); - if ((var_name == nullptr) || (var_name[0] == '\0')) - { - result.AppendError ("'settings set' command requires a valid variable name"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - // Split the raw command into var_name and value pair. - llvm::StringRef raw_str(command); - std::string var_value_string = raw_str.split(var_name).second.str(); - const char *var_value_cstr = Args::StripSpaces(var_value_string, true, true, false); - - Error error (m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx, - eVarSetOperationRemove, - var_name, - var_value_cstr)); - if (error.Fail()) - { - result.AppendError (error.AsCString()); - result.SetStatus (eReturnStatusFailed); - return false; - } - - return result.Succeeded(); + // Split the raw command into var_name and value pair. + llvm::StringRef raw_str(command); + std::string var_value_string = raw_str.split(var_name).second.str(); + const char *var_value_cstr = + Args::StripSpaces(var_value_string, true, true, false); + + Error error(m_interpreter.GetDebugger().SetPropertyValue( + &m_exe_ctx, eVarSetOperationRemove, var_name, var_value_cstr)); + if (error.Fail()) { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; } + + return result.Succeeded(); + } }; //------------------------------------------------------------------------- // CommandObjectSettingsReplace //------------------------------------------------------------------------- -class CommandObjectSettingsReplace : public CommandObjectRaw -{ +class CommandObjectSettingsReplace : public CommandObjectRaw { public: - CommandObjectSettingsReplace(CommandInterpreter &interpreter) - : CommandObjectRaw(interpreter, "settings replace", - "Replace the debugger setting value specified by array index or dictionary key.", nullptr) - { - CommandArgumentEntry arg1; - CommandArgumentEntry arg2; - CommandArgumentEntry arg3; - CommandArgumentData var_name_arg; - CommandArgumentData index_arg; - CommandArgumentData key_arg; - CommandArgumentData value_arg; - - // Define the first (and only) variant of this arg. - var_name_arg.arg_type = eArgTypeSettingVariableName; - var_name_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg1.push_back (var_name_arg); - - // Define the first (variant of this arg. - index_arg.arg_type = eArgTypeSettingIndex; - index_arg.arg_repetition = eArgRepeatPlain; - - // Define the second (variant of this arg. - key_arg.arg_type = eArgTypeSettingKey; - key_arg.arg_repetition = eArgRepeatPlain; - - // Put both variants into this arg - arg2.push_back (index_arg); - arg2.push_back (key_arg); - - // Define the first (and only) variant of this arg. - value_arg.arg_type = eArgTypeValue; - value_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg3.push_back (value_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg1); - m_arguments.push_back (arg2); - m_arguments.push_back (arg3); - } - - ~CommandObjectSettingsReplace() override = default; - - // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString. - bool - WantsCompletion() override { return true; } - - int - HandleArgumentCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - OptionElementVector &opt_element_vector, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) override - { - std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position); - - // Attempting to complete variable name - if (cursor_index < 2) - CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(), - CommandCompletions::eSettingsNameCompletion, - completion_str.c_str(), - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - - return matches.GetSize(); - } + CommandObjectSettingsReplace(CommandInterpreter &interpreter) + : CommandObjectRaw(interpreter, "settings replace", + "Replace the debugger setting value specified by " + "array index or dictionary key.", + nullptr) { + CommandArgumentEntry arg1; + CommandArgumentEntry arg2; + CommandArgumentEntry arg3; + CommandArgumentData var_name_arg; + CommandArgumentData index_arg; + CommandArgumentData key_arg; + CommandArgumentData value_arg; + + // Define the first (and only) variant of this arg. + var_name_arg.arg_type = eArgTypeSettingVariableName; + var_name_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg1.push_back(var_name_arg); + + // Define the first (variant of this arg. + index_arg.arg_type = eArgTypeSettingIndex; + index_arg.arg_repetition = eArgRepeatPlain; + + // Define the second (variant of this arg. + key_arg.arg_type = eArgTypeSettingKey; + key_arg.arg_repetition = eArgRepeatPlain; + + // Put both variants into this arg + arg2.push_back(index_arg); + arg2.push_back(key_arg); + + // Define the first (and only) variant of this arg. + value_arg.arg_type = eArgTypeValue; + value_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg3.push_back(value_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg1); + m_arguments.push_back(arg2); + m_arguments.push_back(arg3); + } + + ~CommandObjectSettingsReplace() override = default; + + // Overrides base class's behavior where WantsCompletion = + // !WantsRawCommandString. + bool WantsCompletion() override { return true; } + + int HandleArgumentCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, int max_return_elements, + bool &word_complete, + StringList &matches) override { + std::string completion_str(input.GetArgumentAtIndex(cursor_index), + cursor_char_position); + + // Attempting to complete variable name + if (cursor_index < 2) + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, + completion_str.c_str(), match_start_point, max_return_elements, + nullptr, word_complete, matches); + + return matches.GetSize(); + } protected: - bool - DoExecute (const char *command, CommandReturnObject &result) override - { - result.SetStatus (eReturnStatusSuccessFinishNoResult); - - Args cmd_args(command); - const char *var_name = cmd_args.GetArgumentAtIndex (0); - if ((var_name == nullptr) || (var_name[0] == '\0')) - { - result.AppendError ("'settings replace' command requires a valid variable name; No value supplied"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - // Split the raw command into var_name, index_value, and value triple. - llvm::StringRef raw_str(command); - std::string var_value_string = raw_str.split(var_name).second.str(); - const char *var_value_cstr = Args::StripSpaces(var_value_string, true, true, false); - - Error error(m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx, - eVarSetOperationReplace, - var_name, - var_value_cstr)); - if (error.Fail()) - { - result.AppendError (error.AsCString()); - result.SetStatus (eReturnStatusFailed); - return false; - } - else - { - result.SetStatus (eReturnStatusSuccessFinishNoResult); - - } + bool DoExecute(const char *command, CommandReturnObject &result) override { + result.SetStatus(eReturnStatusSuccessFinishNoResult); + + Args cmd_args(command); + const char *var_name = cmd_args.GetArgumentAtIndex(0); + if ((var_name == nullptr) || (var_name[0] == '\0')) { + result.AppendError("'settings replace' command requires a valid variable " + "name; No value supplied"); + result.SetStatus(eReturnStatusFailed); + return false; + } - return result.Succeeded(); + // Split the raw command into var_name, index_value, and value triple. + llvm::StringRef raw_str(command); + std::string var_value_string = raw_str.split(var_name).second.str(); + const char *var_value_cstr = + Args::StripSpaces(var_value_string, true, true, false); + + Error error(m_interpreter.GetDebugger().SetPropertyValue( + &m_exe_ctx, eVarSetOperationReplace, var_name, var_value_cstr)); + if (error.Fail()) { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } else { + result.SetStatus(eReturnStatusSuccessFinishNoResult); } + + return result.Succeeded(); + } }; //------------------------------------------------------------------------- // CommandObjectSettingsInsertBefore //------------------------------------------------------------------------- -class CommandObjectSettingsInsertBefore : public CommandObjectRaw -{ +class CommandObjectSettingsInsertBefore : public CommandObjectRaw { public: - CommandObjectSettingsInsertBefore(CommandInterpreter &interpreter) - : CommandObjectRaw(interpreter, "settings insert-before", "Insert one or more values into an debugger array " - "setting immediately before the specified element " - "index.", - nullptr) - { - CommandArgumentEntry arg1; - CommandArgumentEntry arg2; - CommandArgumentEntry arg3; - CommandArgumentData var_name_arg; - CommandArgumentData index_arg; - CommandArgumentData value_arg; - - // Define the first (and only) variant of this arg. - var_name_arg.arg_type = eArgTypeSettingVariableName; - var_name_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg1.push_back (var_name_arg); - - // Define the first (variant of this arg. - index_arg.arg_type = eArgTypeSettingIndex; - index_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg2.push_back (index_arg); - - // Define the first (and only) variant of this arg. - value_arg.arg_type = eArgTypeValue; - value_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg3.push_back (value_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg1); - m_arguments.push_back (arg2); - m_arguments.push_back (arg3); - } - - ~CommandObjectSettingsInsertBefore() override = default; - - // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString. - bool - WantsCompletion() override { return true; } - - int - HandleArgumentCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - OptionElementVector &opt_element_vector, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) override - { - std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position); - - // Attempting to complete variable name - if (cursor_index < 2) - CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(), - CommandCompletions::eSettingsNameCompletion, - completion_str.c_str(), - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - - return matches.GetSize(); - } + CommandObjectSettingsInsertBefore(CommandInterpreter &interpreter) + : CommandObjectRaw(interpreter, "settings insert-before", + "Insert one or more values into an debugger array " + "setting immediately before the specified element " + "index.", + nullptr) { + CommandArgumentEntry arg1; + CommandArgumentEntry arg2; + CommandArgumentEntry arg3; + CommandArgumentData var_name_arg; + CommandArgumentData index_arg; + CommandArgumentData value_arg; + + // Define the first (and only) variant of this arg. + var_name_arg.arg_type = eArgTypeSettingVariableName; + var_name_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg1.push_back(var_name_arg); + + // Define the first (variant of this arg. + index_arg.arg_type = eArgTypeSettingIndex; + index_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg2.push_back(index_arg); + + // Define the first (and only) variant of this arg. + value_arg.arg_type = eArgTypeValue; + value_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg3.push_back(value_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg1); + m_arguments.push_back(arg2); + m_arguments.push_back(arg3); + } + + ~CommandObjectSettingsInsertBefore() override = default; + + // Overrides base class's behavior where WantsCompletion = + // !WantsRawCommandString. + bool WantsCompletion() override { return true; } + + int HandleArgumentCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, int max_return_elements, + bool &word_complete, + StringList &matches) override { + std::string completion_str(input.GetArgumentAtIndex(cursor_index), + cursor_char_position); + + // Attempting to complete variable name + if (cursor_index < 2) + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, + completion_str.c_str(), match_start_point, max_return_elements, + nullptr, word_complete, matches); + + return matches.GetSize(); + } protected: - bool - DoExecute (const char *command, CommandReturnObject &result) override - { - result.SetStatus (eReturnStatusSuccessFinishNoResult); - - Args cmd_args(command); - const size_t argc = cmd_args.GetArgumentCount (); - - if (argc < 3) - { - result.AppendError ("'settings insert-before' takes more arguments"); - result.SetStatus (eReturnStatusFailed); - return false; - } + bool DoExecute(const char *command, CommandReturnObject &result) override { + result.SetStatus(eReturnStatusSuccessFinishNoResult); - const char *var_name = cmd_args.GetArgumentAtIndex (0); - if ((var_name == nullptr) || (var_name[0] == '\0')) - { - result.AppendError ("'settings insert-before' command requires a valid variable name; No value supplied"); - result.SetStatus (eReturnStatusFailed); - return false; - } + Args cmd_args(command); + const size_t argc = cmd_args.GetArgumentCount(); - // Split the raw command into var_name, index_value, and value triple. - llvm::StringRef raw_str(command); - std::string var_value_string = raw_str.split(var_name).second.str(); - const char *var_value_cstr = Args::StripSpaces(var_value_string, true, true, false); - - Error error(m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx, - eVarSetOperationInsertBefore, - var_name, - var_value_cstr)); - if (error.Fail()) - { - result.AppendError (error.AsCString()); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (argc < 3) { + result.AppendError("'settings insert-before' takes more arguments"); + result.SetStatus(eReturnStatusFailed); + return false; + } - return result.Succeeded(); + const char *var_name = cmd_args.GetArgumentAtIndex(0); + if ((var_name == nullptr) || (var_name[0] == '\0')) { + result.AppendError("'settings insert-before' command requires a valid " + "variable name; No value supplied"); + result.SetStatus(eReturnStatusFailed); + return false; } + + // Split the raw command into var_name, index_value, and value triple. + llvm::StringRef raw_str(command); + std::string var_value_string = raw_str.split(var_name).second.str(); + const char *var_value_cstr = + Args::StripSpaces(var_value_string, true, true, false); + + Error error(m_interpreter.GetDebugger().SetPropertyValue( + &m_exe_ctx, eVarSetOperationInsertBefore, var_name, var_value_cstr)); + if (error.Fail()) { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + return result.Succeeded(); + } }; //------------------------------------------------------------------------- // CommandObjectSettingInsertAfter //------------------------------------------------------------------------- -class CommandObjectSettingsInsertAfter : public CommandObjectRaw -{ +class CommandObjectSettingsInsertAfter : public CommandObjectRaw { public: - CommandObjectSettingsInsertAfter(CommandInterpreter &interpreter) - : CommandObjectRaw( - interpreter, "settings insert-after", - "Insert one or more values into a debugger array settings after the specified element index.", nullptr) - { - CommandArgumentEntry arg1; - CommandArgumentEntry arg2; - CommandArgumentEntry arg3; - CommandArgumentData var_name_arg; - CommandArgumentData index_arg; - CommandArgumentData value_arg; - - // Define the first (and only) variant of this arg. - var_name_arg.arg_type = eArgTypeSettingVariableName; - var_name_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg1.push_back (var_name_arg); - - // Define the first (variant of this arg. - index_arg.arg_type = eArgTypeSettingIndex; - index_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg2.push_back (index_arg); - - // Define the first (and only) variant of this arg. - value_arg.arg_type = eArgTypeValue; - value_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg3.push_back (value_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg1); - m_arguments.push_back (arg2); - m_arguments.push_back (arg3); - } + CommandObjectSettingsInsertAfter(CommandInterpreter &interpreter) + : CommandObjectRaw(interpreter, "settings insert-after", + "Insert one or more values into a debugger array " + "settings after the specified element index.", + nullptr) { + CommandArgumentEntry arg1; + CommandArgumentEntry arg2; + CommandArgumentEntry arg3; + CommandArgumentData var_name_arg; + CommandArgumentData index_arg; + CommandArgumentData value_arg; + + // Define the first (and only) variant of this arg. + var_name_arg.arg_type = eArgTypeSettingVariableName; + var_name_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg1.push_back(var_name_arg); + + // Define the first (variant of this arg. + index_arg.arg_type = eArgTypeSettingIndex; + index_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg2.push_back(index_arg); + + // Define the first (and only) variant of this arg. + value_arg.arg_type = eArgTypeValue; + value_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg3.push_back(value_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg1); + m_arguments.push_back(arg2); + m_arguments.push_back(arg3); + } + + ~CommandObjectSettingsInsertAfter() override = default; + + // Overrides base class's behavior where WantsCompletion = + // !WantsRawCommandString. + bool WantsCompletion() override { return true; } + + int HandleArgumentCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, int max_return_elements, + bool &word_complete, + StringList &matches) override { + std::string completion_str(input.GetArgumentAtIndex(cursor_index), + cursor_char_position); + + // Attempting to complete variable name + if (cursor_index < 2) + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, + completion_str.c_str(), match_start_point, max_return_elements, + nullptr, word_complete, matches); + + return matches.GetSize(); + } - ~CommandObjectSettingsInsertAfter() override = default; - - // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString. - bool - WantsCompletion() override { return true; } - - int - HandleArgumentCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - OptionElementVector &opt_element_vector, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) override - { - std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position); - - // Attempting to complete variable name - if (cursor_index < 2) - CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(), - CommandCompletions::eSettingsNameCompletion, - completion_str.c_str(), - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - - return matches.GetSize(); - } - protected: - bool - DoExecute (const char *command, CommandReturnObject &result) override - { - result.SetStatus (eReturnStatusSuccessFinishNoResult); - - Args cmd_args(command); - const size_t argc = cmd_args.GetArgumentCount (); - - if (argc < 3) - { - result.AppendError ("'settings insert-after' takes more arguments"); - result.SetStatus (eReturnStatusFailed); - return false; - } + bool DoExecute(const char *command, CommandReturnObject &result) override { + result.SetStatus(eReturnStatusSuccessFinishNoResult); - const char *var_name = cmd_args.GetArgumentAtIndex (0); - if ((var_name == nullptr) || (var_name[0] == '\0')) - { - result.AppendError ("'settings insert-after' command requires a valid variable name; No value supplied"); - result.SetStatus (eReturnStatusFailed); - return false; - } + Args cmd_args(command); + const size_t argc = cmd_args.GetArgumentCount(); - // Split the raw command into var_name, index_value, and value triple. - llvm::StringRef raw_str(command); - std::string var_value_string = raw_str.split(var_name).second.str(); - const char *var_value_cstr = Args::StripSpaces(var_value_string, true, true, false); - - Error error(m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx, - eVarSetOperationInsertAfter, - var_name, - var_value_cstr)); - if (error.Fail()) - { - result.AppendError (error.AsCString()); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (argc < 3) { + result.AppendError("'settings insert-after' takes more arguments"); + result.SetStatus(eReturnStatusFailed); + return false; + } - return result.Succeeded(); + const char *var_name = cmd_args.GetArgumentAtIndex(0); + if ((var_name == nullptr) || (var_name[0] == '\0')) { + result.AppendError("'settings insert-after' command requires a valid " + "variable name; No value supplied"); + result.SetStatus(eReturnStatusFailed); + return false; } + + // Split the raw command into var_name, index_value, and value triple. + llvm::StringRef raw_str(command); + std::string var_value_string = raw_str.split(var_name).second.str(); + const char *var_value_cstr = + Args::StripSpaces(var_value_string, true, true, false); + + Error error(m_interpreter.GetDebugger().SetPropertyValue( + &m_exe_ctx, eVarSetOperationInsertAfter, var_name, var_value_cstr)); + if (error.Fail()) { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + return result.Succeeded(); + } }; //------------------------------------------------------------------------- // CommandObjectSettingsAppend //------------------------------------------------------------------------- -class CommandObjectSettingsAppend : public CommandObjectRaw -{ +class CommandObjectSettingsAppend : public CommandObjectRaw { public: - CommandObjectSettingsAppend(CommandInterpreter &interpreter) - : CommandObjectRaw(interpreter, "settings append", - "Append one or more values to a debugger array, dictionary, or string setting.", nullptr) - { - CommandArgumentEntry arg1; - CommandArgumentEntry arg2; - CommandArgumentData var_name_arg; - CommandArgumentData value_arg; - - // Define the first (and only) variant of this arg. - var_name_arg.arg_type = eArgTypeSettingVariableName; - var_name_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg1.push_back (var_name_arg); - - // Define the first (and only) variant of this arg. - value_arg.arg_type = eArgTypeValue; - value_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg2.push_back (value_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg1); - m_arguments.push_back (arg2); - } - - ~CommandObjectSettingsAppend() override = default; - - // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString. - bool - WantsCompletion() override { return true; } - - int - HandleArgumentCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - OptionElementVector &opt_element_vector, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) override - { - std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position); - - // Attempting to complete variable name - if (cursor_index < 2) - CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(), - CommandCompletions::eSettingsNameCompletion, - completion_str.c_str(), - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - - return matches.GetSize(); - } + CommandObjectSettingsAppend(CommandInterpreter &interpreter) + : CommandObjectRaw(interpreter, "settings append", + "Append one or more values to a debugger array, " + "dictionary, or string setting.", + nullptr) { + CommandArgumentEntry arg1; + CommandArgumentEntry arg2; + CommandArgumentData var_name_arg; + CommandArgumentData value_arg; + + // Define the first (and only) variant of this arg. + var_name_arg.arg_type = eArgTypeSettingVariableName; + var_name_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg1.push_back(var_name_arg); + + // Define the first (and only) variant of this arg. + value_arg.arg_type = eArgTypeValue; + value_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg2.push_back(value_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg1); + m_arguments.push_back(arg2); + } + + ~CommandObjectSettingsAppend() override = default; + + // Overrides base class's behavior where WantsCompletion = + // !WantsRawCommandString. + bool WantsCompletion() override { return true; } + + int HandleArgumentCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, int max_return_elements, + bool &word_complete, + StringList &matches) override { + std::string completion_str(input.GetArgumentAtIndex(cursor_index), + cursor_char_position); + + // Attempting to complete variable name + if (cursor_index < 2) + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, + completion_str.c_str(), match_start_point, max_return_elements, + nullptr, word_complete, matches); + + return matches.GetSize(); + } protected: - bool - DoExecute (const char *command, CommandReturnObject &result) override - { - result.SetStatus (eReturnStatusSuccessFinishNoResult); - Args cmd_args(command); - const size_t argc = cmd_args.GetArgumentCount (); - - if (argc < 2) - { - result.AppendError ("'settings append' takes more arguments"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - const char *var_name = cmd_args.GetArgumentAtIndex (0); - if ((var_name == nullptr) || (var_name[0] == '\0')) - { - result.AppendError ("'settings append' command requires a valid variable name; No value supplied"); - result.SetStatus (eReturnStatusFailed); - return false; - } + bool DoExecute(const char *command, CommandReturnObject &result) override { + result.SetStatus(eReturnStatusSuccessFinishNoResult); + Args cmd_args(command); + const size_t argc = cmd_args.GetArgumentCount(); + + if (argc < 2) { + result.AppendError("'settings append' takes more arguments"); + result.SetStatus(eReturnStatusFailed); + return false; + } - // Do not perform cmd_args.Shift() since StringRef is manipulating the - // raw character string later on. - - // Split the raw command into var_name and value pair. - llvm::StringRef raw_str(command); - std::string var_value_string = raw_str.split(var_name).second.str(); - const char *var_value_cstr = Args::StripSpaces(var_value_string, true, true, false); - - Error error(m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx, - eVarSetOperationAppend, - var_name, - var_value_cstr)); - if (error.Fail()) - { - result.AppendError (error.AsCString()); - result.SetStatus (eReturnStatusFailed); - return false; - } + const char *var_name = cmd_args.GetArgumentAtIndex(0); + if ((var_name == nullptr) || (var_name[0] == '\0')) { + result.AppendError("'settings append' command requires a valid variable " + "name; No value supplied"); + result.SetStatus(eReturnStatusFailed); + return false; + } - return result.Succeeded(); + // Do not perform cmd_args.Shift() since StringRef is manipulating the + // raw character string later on. + + // Split the raw command into var_name and value pair. + llvm::StringRef raw_str(command); + std::string var_value_string = raw_str.split(var_name).second.str(); + const char *var_value_cstr = + Args::StripSpaces(var_value_string, true, true, false); + + Error error(m_interpreter.GetDebugger().SetPropertyValue( + &m_exe_ctx, eVarSetOperationAppend, var_name, var_value_cstr)); + if (error.Fail()) { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; } + + return result.Succeeded(); + } }; //------------------------------------------------------------------------- // CommandObjectSettingsClear //------------------------------------------------------------------------- -class CommandObjectSettingsClear : public CommandObjectParsed -{ +class CommandObjectSettingsClear : public CommandObjectParsed { public: - CommandObjectSettingsClear(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "settings clear", "Clear a debugger setting array, dictionary, or string.", - nullptr) - { - CommandArgumentEntry arg; - CommandArgumentData var_name_arg; - - // Define the first (and only) variant of this arg. - var_name_arg.arg_type = eArgTypeSettingVariableName; - var_name_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (var_name_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - } - - ~CommandObjectSettingsClear() override = default; - - int - HandleArgumentCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - OptionElementVector &opt_element_vector, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) override - { - std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position); - - // Attempting to complete variable name - if (cursor_index < 2) - CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(), - CommandCompletions::eSettingsNameCompletion, - completion_str.c_str(), - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - - return matches.GetSize(); - } + CommandObjectSettingsClear(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "settings clear", + "Clear a debugger setting array, dictionary, or string.", nullptr) { + CommandArgumentEntry arg; + CommandArgumentData var_name_arg; + + // Define the first (and only) variant of this arg. + var_name_arg.arg_type = eArgTypeSettingVariableName; + var_name_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(var_name_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectSettingsClear() override = default; + + int HandleArgumentCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, int max_return_elements, + bool &word_complete, + StringList &matches) override { + std::string completion_str(input.GetArgumentAtIndex(cursor_index), + cursor_char_position); + + // Attempting to complete variable name + if (cursor_index < 2) + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, + completion_str.c_str(), match_start_point, max_return_elements, + nullptr, word_complete, matches); + + return matches.GetSize(); + } protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - result.SetStatus (eReturnStatusSuccessFinishNoResult); - const size_t argc = command.GetArgumentCount (); - - if (argc != 1) - { - result.AppendError ("'settings clear' takes exactly one argument"); - result.SetStatus (eReturnStatusFailed); - return false; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + result.SetStatus(eReturnStatusSuccessFinishNoResult); + const size_t argc = command.GetArgumentCount(); + + if (argc != 1) { + result.AppendError("'settings clear' takes exactly one argument"); + result.SetStatus(eReturnStatusFailed); + return false; + } - const char *var_name = command.GetArgumentAtIndex (0); - if ((var_name == nullptr) || (var_name[0] == '\0')) - { - result.AppendError ("'settings clear' command requires a valid variable name; No value supplied"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - Error error(m_interpreter.GetDebugger().SetPropertyValue(&m_exe_ctx, - eVarSetOperationClear, - var_name, - nullptr)); - if (error.Fail()) - { - result.AppendError (error.AsCString()); - result.SetStatus (eReturnStatusFailed); - return false; - } + const char *var_name = command.GetArgumentAtIndex(0); + if ((var_name == nullptr) || (var_name[0] == '\0')) { + result.AppendError("'settings clear' command requires a valid variable " + "name; No value supplied"); + result.SetStatus(eReturnStatusFailed); + return false; + } - return result.Succeeded(); + Error error(m_interpreter.GetDebugger().SetPropertyValue( + &m_exe_ctx, eVarSetOperationClear, var_name, nullptr)); + if (error.Fail()) { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; } + + return result.Succeeded(); + } }; //------------------------------------------------------------------------- // CommandObjectMultiwordSettings //------------------------------------------------------------------------- -CommandObjectMultiwordSettings::CommandObjectMultiwordSettings(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "settings", "Commands for managing LLDB settings.", - "settings <subcommand> [<command-options>]") -{ - LoadSubCommand ("set", CommandObjectSP (new CommandObjectSettingsSet (interpreter))); - LoadSubCommand ("show", CommandObjectSP (new CommandObjectSettingsShow (interpreter))); - LoadSubCommand ("list", CommandObjectSP (new CommandObjectSettingsList (interpreter))); - LoadSubCommand ("remove", CommandObjectSP (new CommandObjectSettingsRemove (interpreter))); - LoadSubCommand ("replace", CommandObjectSP (new CommandObjectSettingsReplace (interpreter))); - LoadSubCommand ("insert-before", CommandObjectSP (new CommandObjectSettingsInsertBefore (interpreter))); - LoadSubCommand ("insert-after", CommandObjectSP (new CommandObjectSettingsInsertAfter (interpreter))); - LoadSubCommand ("append", CommandObjectSP (new CommandObjectSettingsAppend (interpreter))); - LoadSubCommand ("clear", CommandObjectSP (new CommandObjectSettingsClear (interpreter))); +CommandObjectMultiwordSettings::CommandObjectMultiwordSettings( + CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "settings", + "Commands for managing LLDB settings.", + "settings <subcommand> [<command-options>]") { + LoadSubCommand("set", + CommandObjectSP(new CommandObjectSettingsSet(interpreter))); + LoadSubCommand("show", + CommandObjectSP(new CommandObjectSettingsShow(interpreter))); + LoadSubCommand("list", + CommandObjectSP(new CommandObjectSettingsList(interpreter))); + LoadSubCommand("remove", + CommandObjectSP(new CommandObjectSettingsRemove(interpreter))); + LoadSubCommand("replace", CommandObjectSP( + new CommandObjectSettingsReplace(interpreter))); + LoadSubCommand( + "insert-before", + CommandObjectSP(new CommandObjectSettingsInsertBefore(interpreter))); + LoadSubCommand( + "insert-after", + CommandObjectSP(new CommandObjectSettingsInsertAfter(interpreter))); + LoadSubCommand("append", + CommandObjectSP(new CommandObjectSettingsAppend(interpreter))); + LoadSubCommand("clear", + CommandObjectSP(new CommandObjectSettingsClear(interpreter))); } CommandObjectMultiwordSettings::~CommandObjectMultiwordSettings() = default; diff --git a/lldb/source/Commands/CommandObjectSettings.h b/lldb/source/Commands/CommandObjectSettings.h index 93ee919..3376ccc 100644 --- a/lldb/source/Commands/CommandObjectSettings.h +++ b/lldb/source/Commands/CommandObjectSettings.h @@ -18,20 +18,17 @@ #include "lldb/Interpreter/CommandObjectMultiword.h" #include "lldb/Interpreter/Options.h" - namespace lldb_private { //------------------------------------------------------------------------- // CommandObjectMultiwordSettings //------------------------------------------------------------------------- -class CommandObjectMultiwordSettings : public CommandObjectMultiword -{ +class CommandObjectMultiwordSettings : public CommandObjectMultiword { public: + CommandObjectMultiwordSettings(CommandInterpreter &interpreter); - CommandObjectMultiwordSettings (CommandInterpreter &interpreter); - - ~CommandObjectMultiwordSettings() override; + ~CommandObjectMultiwordSettings() override; }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectSource.cpp b/lldb/source/Commands/CommandObjectSource.cpp index d35cba4..6085168 100644 --- a/lldb/source/Commands/CommandObjectSource.cpp +++ b/lldb/source/Commands/CommandObjectSource.cpp @@ -18,10 +18,12 @@ #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/SourceManager.h" -#include "lldb/Interpreter/CommandInterpreter.h" -#include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/StringConvert.h" +#include "lldb/Interpreter/CommandCompletions.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Interpreter/Options.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" @@ -29,8 +31,6 @@ #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/TargetList.h" -#include "lldb/Interpreter/CommandCompletions.h" -#include "lldb/Interpreter/Options.h" using namespace lldb; using namespace lldb_private; @@ -40,668 +40,617 @@ using namespace lldb_private; // CommandObjectSourceInfo - debug line entries dumping command //---------------------------------------------------------------------- -class CommandObjectSourceInfo : public CommandObjectParsed -{ - class CommandOptions : public Options - { - public: - CommandOptions() : Options() {} - - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = g_option_table[option_idx].short_option; - switch (short_option) - { - case 'l': - start_line = StringConvert::ToUInt32(option_arg, 0); - if (start_line == 0) - error.SetErrorStringWithFormat("invalid line number: '%s'", option_arg); - break; - - case 'e': - end_line = StringConvert::ToUInt32(option_arg, 0); - if (end_line == 0) - error.SetErrorStringWithFormat("invalid line number: '%s'", option_arg); - break; - - case 'c': - num_lines = StringConvert::ToUInt32(option_arg, 0); - if (num_lines == 0) - error.SetErrorStringWithFormat("invalid line count: '%s'", option_arg); - break; - - case 'f': - file_name = option_arg; - break; - - case 'n': - symbol_name = option_arg; - break; - - case 'a': - { - address = Args::StringToAddress(execution_context, - option_arg, - LLDB_INVALID_ADDRESS, - &error); - } - break; - case 's': - modules.push_back(std::string(option_arg)); - break; - default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); - break; - } - - return error; - } +class CommandObjectSourceInfo : public CommandObjectParsed { + class CommandOptions : public Options { + public: + CommandOptions() : Options() {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = g_option_table[option_idx].short_option; + switch (short_option) { + case 'l': + start_line = StringConvert::ToUInt32(option_arg, 0); + if (start_line == 0) + error.SetErrorStringWithFormat("invalid line number: '%s'", + option_arg); + break; + + case 'e': + end_line = StringConvert::ToUInt32(option_arg, 0); + if (end_line == 0) + error.SetErrorStringWithFormat("invalid line number: '%s'", + option_arg); + break; + + case 'c': + num_lines = StringConvert::ToUInt32(option_arg, 0); + if (num_lines == 0) + error.SetErrorStringWithFormat("invalid line count: '%s'", + option_arg); + break; + + case 'f': + file_name = option_arg; + break; + + case 'n': + symbol_name = option_arg; + break; + + case 'a': { + address = Args::StringToAddress(execution_context, option_arg, + LLDB_INVALID_ADDRESS, &error); + } break; + case 's': + modules.push_back(std::string(option_arg)); + break; + default: + error.SetErrorStringWithFormat("unrecognized short option '%c'", + short_option); + break; + } + + return error; + } - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - file_spec.Clear(); - file_name.clear(); - symbol_name.clear(); - address = LLDB_INVALID_ADDRESS; - start_line = 0; - end_line = 0; - num_lines = 0; - modules.clear(); - } + void OptionParsingStarting(ExecutionContext *execution_context) override { + file_spec.Clear(); + file_name.clear(); + symbol_name.clear(); + address = LLDB_INVALID_ADDRESS; + start_line = 0; + end_line = 0; + num_lines = 0; + modules.clear(); + } - const OptionDefinition * - GetDefinitions () override - { - return g_option_table; - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } - static OptionDefinition g_option_table[]; + static OptionDefinition g_option_table[]; - // Instance variables to hold the values for command options. - FileSpec file_spec; - std::string file_name; - std::string symbol_name; - lldb::addr_t address; - uint32_t start_line; - uint32_t end_line; - uint32_t num_lines; - STLStringArray modules; - }; + // Instance variables to hold the values for command options. + FileSpec file_spec; + std::string file_name; + std::string symbol_name; + lldb::addr_t address; + uint32_t start_line; + uint32_t end_line; + uint32_t num_lines; + STLStringArray modules; + }; public: - CommandObjectSourceInfo(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "source info", "Display source line information for the current target " - "process. Defaults to instruction pointer in current stack " - "frame.", - nullptr, eCommandRequiresTarget), - m_options() - { - } + CommandObjectSourceInfo(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "source info", + "Display source line information for the current target " + "process. Defaults to instruction pointer in current stack " + "frame.", + nullptr, eCommandRequiresTarget), + m_options() {} - ~CommandObjectSourceInfo() override = default; + ~CommandObjectSourceInfo() override = default; - Options * - GetOptions () override - { - return &m_options; - } + Options *GetOptions() override { return &m_options; } protected: - // Dump the line entries in each symbol context. - // Return the number of entries found. - // If module_list is set, only dump lines contained in one of the modules. - // If file_spec is set, only dump lines in the file. - // If the start_line option was specified, don't print lines less than start_line. - // If the end_line option was specified, don't print lines greater than end_line. - // If the num_lines option was specified, dont print more than num_lines entries. - uint32_t - DumpLinesInSymbolContexts (Stream &strm, const SymbolContextList &sc_list, - const ModuleList &module_list, const FileSpec &file_spec) - { - uint32_t start_line = m_options.start_line; - uint32_t end_line = m_options.end_line; - uint32_t num_lines = m_options.num_lines; - Target *target = m_exe_ctx.GetTargetPtr(); - - uint32_t num_matches = 0; - bool has_path = false; - if (file_spec) - { - assert(file_spec.GetFilename().AsCString()); - has_path = (file_spec.GetDirectory().AsCString() != nullptr); - } - - // Dump all the line entries for the file in the list. - ConstString last_module_file_name; - uint32_t num_scs = sc_list.GetSize(); - for (uint32_t i = 0; i < num_scs; ++i) - { - SymbolContext sc; - sc_list.GetContextAtIndex(i, sc); - if (sc.comp_unit) - { - Module *module = sc.module_sp.get(); - CompileUnit *cu = sc.comp_unit; - const LineEntry &line_entry = sc.line_entry; - assert(module && cu); - - // Are we looking for specific modules, files or lines? - if (module_list.GetSize() && module_list.GetIndexForModule(module) == LLDB_INVALID_INDEX32) - continue; - if (file_spec && !lldb_private::FileSpec::Equal(file_spec, line_entry.file, has_path)) - continue; - if (start_line > 0 && line_entry.line < start_line) - continue; - if (end_line > 0 && line_entry.line > end_line) - continue; - if (num_lines > 0 && num_matches > num_lines) - continue; - - // Print a new header if the module changed. - const ConstString &module_file_name = module->GetFileSpec().GetFilename(); - assert(module_file_name); - if (module_file_name != last_module_file_name) - { - if (num_matches > 0) - strm << "\n\n"; - strm << "Lines found in module `" << module_file_name << "\n"; - } - // Dump the line entry. - line_entry.GetDescription(&strm, lldb::eDescriptionLevelBrief, cu, - target, /*show_address_only=*/false); - strm << "\n"; - last_module_file_name = module_file_name; - num_matches++; - } - } - return num_matches; + // Dump the line entries in each symbol context. + // Return the number of entries found. + // If module_list is set, only dump lines contained in one of the modules. + // If file_spec is set, only dump lines in the file. + // If the start_line option was specified, don't print lines less than + // start_line. + // If the end_line option was specified, don't print lines greater than + // end_line. + // If the num_lines option was specified, dont print more than num_lines + // entries. + uint32_t DumpLinesInSymbolContexts(Stream &strm, + const SymbolContextList &sc_list, + const ModuleList &module_list, + const FileSpec &file_spec) { + uint32_t start_line = m_options.start_line; + uint32_t end_line = m_options.end_line; + uint32_t num_lines = m_options.num_lines; + Target *target = m_exe_ctx.GetTargetPtr(); + + uint32_t num_matches = 0; + bool has_path = false; + if (file_spec) { + assert(file_spec.GetFilename().AsCString()); + has_path = (file_spec.GetDirectory().AsCString() != nullptr); } - - // Dump the requested line entries for the file in the compilation unit. - // Return the number of entries found. - // If module_list is set, only dump lines contained in one of the modules. - // If the start_line option was specified, don't print lines less than start_line. - // If the end_line option was specified, don't print lines greater than end_line. - // If the num_lines option was specified, dont print more than num_lines entries. - uint32_t - DumpFileLinesInCompUnit (Stream &strm, Module *module, CompileUnit *cu, const FileSpec &file_spec) - { - uint32_t start_line = m_options.start_line; - uint32_t end_line = m_options.end_line; - uint32_t num_lines = m_options.num_lines; - Target *target = m_exe_ctx.GetTargetPtr(); - - uint32_t num_matches = 0; - assert(module); - if (cu) - { - assert(file_spec.GetFilename().AsCString()); - bool has_path = (file_spec.GetDirectory().AsCString() != nullptr); - const FileSpecList &cu_file_list = cu->GetSupportFiles(); - size_t file_idx = cu_file_list.FindFileIndex(0, file_spec, has_path); - if (file_idx != UINT32_MAX) - { - // Update the file to how it appears in the CU. - const FileSpec &cu_file_spec = cu_file_list.GetFileSpecAtIndex(file_idx); - - // Dump all matching lines at or above start_line for the file in the CU. - const ConstString &file_spec_name = file_spec.GetFilename(); - const ConstString &module_file_name = module->GetFileSpec().GetFilename(); - bool cu_header_printed = false; - uint32_t line = start_line; - while (true) - { - LineEntry line_entry; - - // Find the lowest index of a line entry with a line equal to - // or higher than 'line'. - uint32_t start_idx = 0; - start_idx = cu->FindLineEntry(start_idx, line, &cu_file_spec, - /*exact=*/false, &line_entry); - if (start_idx == UINT32_MAX) - // No more line entries for our file in this CU. - break; - - if (end_line > 0 && line_entry.line > end_line) - break; - - // Loop through to find any other entries for this line, dumping each. - line = line_entry.line; - do - { - num_matches++; - if (num_lines > 0 && num_matches > num_lines) - break; - assert(lldb_private::FileSpec::Equal(cu_file_spec, line_entry.file, has_path)); - if (!cu_header_printed) - { - if (num_matches > 0) - strm << "\n\n"; - strm << "Lines found for file " << file_spec_name - << " in compilation unit " << cu->GetFilename() - << " in `" << module_file_name << "\n"; - cu_header_printed = true; - } - line_entry.GetDescription(&strm, lldb::eDescriptionLevelBrief, cu, - target, /*show_address_only=*/false); - strm << "\n"; - - // Anymore after this one? - start_idx++; - start_idx = cu->FindLineEntry(start_idx, line, &cu_file_spec, - /*exact=*/true, &line_entry); - } while (start_idx != UINT32_MAX); - - // Try the next higher line, starting over at start_idx 0. - line++; - } - } + + // Dump all the line entries for the file in the list. + ConstString last_module_file_name; + uint32_t num_scs = sc_list.GetSize(); + for (uint32_t i = 0; i < num_scs; ++i) { + SymbolContext sc; + sc_list.GetContextAtIndex(i, sc); + if (sc.comp_unit) { + Module *module = sc.module_sp.get(); + CompileUnit *cu = sc.comp_unit; + const LineEntry &line_entry = sc.line_entry; + assert(module && cu); + + // Are we looking for specific modules, files or lines? + if (module_list.GetSize() && + module_list.GetIndexForModule(module) == LLDB_INVALID_INDEX32) + continue; + if (file_spec && + !lldb_private::FileSpec::Equal(file_spec, line_entry.file, + has_path)) + continue; + if (start_line > 0 && line_entry.line < start_line) + continue; + if (end_line > 0 && line_entry.line > end_line) + continue; + if (num_lines > 0 && num_matches > num_lines) + continue; + + // Print a new header if the module changed. + const ConstString &module_file_name = + module->GetFileSpec().GetFilename(); + assert(module_file_name); + if (module_file_name != last_module_file_name) { + if (num_matches > 0) + strm << "\n\n"; + strm << "Lines found in module `" << module_file_name << "\n"; } - return num_matches; + // Dump the line entry. + line_entry.GetDescription(&strm, lldb::eDescriptionLevelBrief, cu, + target, /*show_address_only=*/false); + strm << "\n"; + last_module_file_name = module_file_name; + num_matches++; + } } - - // Dump the requested line entries for the file in the module. - // Return the number of entries found. - // If module_list is set, only dump lines contained in one of the modules. - // If the start_line option was specified, don't print lines less than start_line. - // If the end_line option was specified, don't print lines greater than end_line. - // If the num_lines option was specified, dont print more than num_lines entries. - uint32_t - DumpFileLinesInModule (Stream &strm, Module *module, const FileSpec &file_spec) - { - uint32_t num_matches = 0; - if (module) - { - // Look through all the compilation units (CUs) in this module for ones that - // contain lines of code from this source file. - for (size_t i = 0; i < module->GetNumCompileUnits(); i++) - { - // Look for a matching source file in this CU. - CompUnitSP cu_sp(module->GetCompileUnitAtIndex(i)); - if (cu_sp) - { - num_matches += DumpFileLinesInCompUnit(strm, module, cu_sp.get(), file_spec); - } + return num_matches; + } + + // Dump the requested line entries for the file in the compilation unit. + // Return the number of entries found. + // If module_list is set, only dump lines contained in one of the modules. + // If the start_line option was specified, don't print lines less than + // start_line. + // If the end_line option was specified, don't print lines greater than + // end_line. + // If the num_lines option was specified, dont print more than num_lines + // entries. + uint32_t DumpFileLinesInCompUnit(Stream &strm, Module *module, + CompileUnit *cu, const FileSpec &file_spec) { + uint32_t start_line = m_options.start_line; + uint32_t end_line = m_options.end_line; + uint32_t num_lines = m_options.num_lines; + Target *target = m_exe_ctx.GetTargetPtr(); + + uint32_t num_matches = 0; + assert(module); + if (cu) { + assert(file_spec.GetFilename().AsCString()); + bool has_path = (file_spec.GetDirectory().AsCString() != nullptr); + const FileSpecList &cu_file_list = cu->GetSupportFiles(); + size_t file_idx = cu_file_list.FindFileIndex(0, file_spec, has_path); + if (file_idx != UINT32_MAX) { + // Update the file to how it appears in the CU. + const FileSpec &cu_file_spec = + cu_file_list.GetFileSpecAtIndex(file_idx); + + // Dump all matching lines at or above start_line for the file in the + // CU. + const ConstString &file_spec_name = file_spec.GetFilename(); + const ConstString &module_file_name = + module->GetFileSpec().GetFilename(); + bool cu_header_printed = false; + uint32_t line = start_line; + while (true) { + LineEntry line_entry; + + // Find the lowest index of a line entry with a line equal to + // or higher than 'line'. + uint32_t start_idx = 0; + start_idx = cu->FindLineEntry(start_idx, line, &cu_file_spec, + /*exact=*/false, &line_entry); + if (start_idx == UINT32_MAX) + // No more line entries for our file in this CU. + break; + + if (end_line > 0 && line_entry.line > end_line) + break; + + // Loop through to find any other entries for this line, dumping each. + line = line_entry.line; + do { + num_matches++; + if (num_lines > 0 && num_matches > num_lines) + break; + assert(lldb_private::FileSpec::Equal(cu_file_spec, line_entry.file, + has_path)); + if (!cu_header_printed) { + if (num_matches > 0) + strm << "\n\n"; + strm << "Lines found for file " << file_spec_name + << " in compilation unit " << cu->GetFilename() << " in `" + << module_file_name << "\n"; + cu_header_printed = true; } + line_entry.GetDescription(&strm, lldb::eDescriptionLevelBrief, cu, + target, /*show_address_only=*/false); + strm << "\n"; + + // Anymore after this one? + start_idx++; + start_idx = cu->FindLineEntry(start_idx, line, &cu_file_spec, + /*exact=*/true, &line_entry); + } while (start_idx != UINT32_MAX); + + // Try the next higher line, starting over at start_idx 0. + line++; } - return num_matches; + } } - - // Given an address and a list of modules, append the symbol contexts of all line entries - // containing the address found in the modules and return the count of matches. If none - // is found, return an error in 'error_strm'. - size_t - GetSymbolContextsForAddress (const ModuleList &module_list, lldb::addr_t addr, - SymbolContextList &sc_list, StreamString &error_strm) - { - Address so_addr; - size_t num_matches = 0; - assert(module_list.GetSize() > 0); - Target *target = m_exe_ctx.GetTargetPtr(); - if (target->GetSectionLoadList().IsEmpty()) - { - // The target isn't loaded yet, we need to lookup the file address in - // all modules. Note: the module list option does not apply to addresses. - const size_t num_modules = module_list.GetSize(); - for (size_t i = 0; i < num_modules; ++i) - { - ModuleSP module_sp(module_list.GetModuleAtIndex(i)); - if (!module_sp) - continue; - if (module_sp->ResolveFileAddress(addr, so_addr)) - { - SymbolContext sc; - sc.Clear(true); - if (module_sp->ResolveSymbolContextForAddress(so_addr, eSymbolContextEverything, sc) & - eSymbolContextLineEntry) - { - sc_list.AppendIfUnique(sc, /*merge_symbol_into_function=*/false); - ++num_matches; - } - } - } - if (num_matches == 0) - error_strm.Printf("Source information for file address 0x%" PRIx64 - " not found in any modules.\n", addr); - } - else - { - // The target has some things loaded, resolve this address to a - // compile unit + file + line and display - if (target->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) - { - ModuleSP module_sp(so_addr.GetModule()); - // Check to make sure this module is in our list. - if (module_sp && - module_list.GetIndexForModule(module_sp.get()) != LLDB_INVALID_INDEX32) - { - SymbolContext sc; - sc.Clear(true); - if (module_sp->ResolveSymbolContextForAddress(so_addr, eSymbolContextEverything, sc) & - eSymbolContextLineEntry) - { - sc_list.AppendIfUnique(sc, /*merge_symbol_into_function=*/false); - ++num_matches; - } - else - { - StreamString addr_strm; - so_addr.Dump(&addr_strm, nullptr, Address::DumpStyleModuleWithFileAddress); - error_strm.Printf("Address 0x%" PRIx64 " resolves to %s, but there is" - " no source information available for this address.\n", - addr, addr_strm.GetData()); - } - } - else - { - StreamString addr_strm; - so_addr.Dump(&addr_strm, nullptr, Address::DumpStyleModuleWithFileAddress); - error_strm.Printf("Address 0x%" PRIx64 " resolves to %s, but it cannot" - " be found in any modules.\n", - addr, addr_strm.GetData()); - } - } - else - error_strm.Printf("Unable to resolve address 0x%" PRIx64 ".\n", addr); + return num_matches; + } + + // Dump the requested line entries for the file in the module. + // Return the number of entries found. + // If module_list is set, only dump lines contained in one of the modules. + // If the start_line option was specified, don't print lines less than + // start_line. + // If the end_line option was specified, don't print lines greater than + // end_line. + // If the num_lines option was specified, dont print more than num_lines + // entries. + uint32_t DumpFileLinesInModule(Stream &strm, Module *module, + const FileSpec &file_spec) { + uint32_t num_matches = 0; + if (module) { + // Look through all the compilation units (CUs) in this module for ones + // that + // contain lines of code from this source file. + for (size_t i = 0; i < module->GetNumCompileUnits(); i++) { + // Look for a matching source file in this CU. + CompUnitSP cu_sp(module->GetCompileUnitAtIndex(i)); + if (cu_sp) { + num_matches += + DumpFileLinesInCompUnit(strm, module, cu_sp.get(), file_spec); } - return num_matches; + } } - - // Dump the line entries found in functions matching the name specified in the option. - bool - DumpLinesInFunctions (CommandReturnObject &result) - { - SymbolContextList sc_list_funcs; - ConstString name(m_options.symbol_name.c_str()); - SymbolContextList sc_list_lines; - Target *target = m_exe_ctx.GetTargetPtr(); - uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); - - // Note: module_list can't be const& because FindFunctionSymbols isn't const. - ModuleList module_list = (m_module_list.GetSize() > 0) ? - m_module_list : target->GetImages(); - size_t num_matches = module_list.FindFunctions(name, - eFunctionNameTypeAuto, - /*include_symbols=*/false, - /*include_inlines=*/true, - /*append=*/true, - sc_list_funcs); - if (!num_matches) - { - // If we didn't find any functions with that name, try searching for - // symbols that line up exactly with function addresses. - SymbolContextList sc_list_symbols; - size_t num_symbol_matches = module_list.FindFunctionSymbols(name, - eFunctionNameTypeAuto, - sc_list_symbols); - for (size_t i = 0; i < num_symbol_matches; i++) - { - SymbolContext sc; - sc_list_symbols.GetContextAtIndex(i, sc); - if (sc.symbol && sc.symbol->ValueIsAddress()) - { - const Address &base_address = sc.symbol->GetAddressRef(); - Function *function = base_address.CalculateSymbolContextFunction(); - if (function) - { - sc_list_funcs.Append(SymbolContext(function)); - num_matches++; - } - } - } - } - if (num_matches == 0) - { - result.AppendErrorWithFormat("Could not find function named \'%s\'.\n", - m_options.symbol_name.c_str()); - return false; + return num_matches; + } + + // Given an address and a list of modules, append the symbol contexts of all + // line entries + // containing the address found in the modules and return the count of + // matches. If none + // is found, return an error in 'error_strm'. + size_t GetSymbolContextsForAddress(const ModuleList &module_list, + lldb::addr_t addr, + SymbolContextList &sc_list, + StreamString &error_strm) { + Address so_addr; + size_t num_matches = 0; + assert(module_list.GetSize() > 0); + Target *target = m_exe_ctx.GetTargetPtr(); + if (target->GetSectionLoadList().IsEmpty()) { + // The target isn't loaded yet, we need to lookup the file address in + // all modules. Note: the module list option does not apply to addresses. + const size_t num_modules = module_list.GetSize(); + for (size_t i = 0; i < num_modules; ++i) { + ModuleSP module_sp(module_list.GetModuleAtIndex(i)); + if (!module_sp) + continue; + if (module_sp->ResolveFileAddress(addr, so_addr)) { + SymbolContext sc; + sc.Clear(true); + if (module_sp->ResolveSymbolContextForAddress( + so_addr, eSymbolContextEverything, sc) & + eSymbolContextLineEntry) { + sc_list.AppendIfUnique(sc, /*merge_symbol_into_function=*/false); + ++num_matches; + } } - for (size_t i = 0; i < num_matches; i++) - { - SymbolContext sc; - sc_list_funcs.GetContextAtIndex(i, sc); - bool context_found_for_symbol = false; - // Loop through all the ranges in the function. - AddressRange range; - for (uint32_t r = 0; - sc.GetAddressRange(eSymbolContextEverything, - r, - /*use_inline_block_range=*/true, - range); - ++r) - { - // Append the symbol contexts for each address in the range to sc_list_lines. - const Address &base_address = range.GetBaseAddress(); - const addr_t size = range.GetByteSize(); - lldb::addr_t start_addr = base_address.GetLoadAddress(target); - if (start_addr == LLDB_INVALID_ADDRESS) - start_addr = base_address.GetFileAddress(); - lldb::addr_t end_addr = start_addr + size; - for (lldb::addr_t addr = start_addr; addr < end_addr; addr += addr_byte_size) - { - StreamString error_strm; - if (!GetSymbolContextsForAddress(module_list, addr, sc_list_lines, error_strm)) - result.AppendWarningWithFormat("in symbol '%s': %s", - sc.GetFunctionName().AsCString(), - error_strm.GetData()); - else - context_found_for_symbol = true; - } - } - if (!context_found_for_symbol) - result.AppendWarningWithFormat("Unable to find line information" - " for matching symbol '%s'.\n", - sc.GetFunctionName().AsCString()); - } - if (sc_list_lines.GetSize() == 0) - { - result.AppendErrorWithFormat("No line information could be found" - " for any symbols matching '%s'.\n", - name.AsCString()); - return false; + } + if (num_matches == 0) + error_strm.Printf("Source information for file address 0x%" PRIx64 + " not found in any modules.\n", + addr); + } else { + // The target has some things loaded, resolve this address to a + // compile unit + file + line and display + if (target->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) { + ModuleSP module_sp(so_addr.GetModule()); + // Check to make sure this module is in our list. + if (module_sp && + module_list.GetIndexForModule(module_sp.get()) != + LLDB_INVALID_INDEX32) { + SymbolContext sc; + sc.Clear(true); + if (module_sp->ResolveSymbolContextForAddress( + so_addr, eSymbolContextEverything, sc) & + eSymbolContextLineEntry) { + sc_list.AppendIfUnique(sc, /*merge_symbol_into_function=*/false); + ++num_matches; + } else { + StreamString addr_strm; + so_addr.Dump(&addr_strm, nullptr, + Address::DumpStyleModuleWithFileAddress); + error_strm.Printf( + "Address 0x%" PRIx64 " resolves to %s, but there is" + " no source information available for this address.\n", + addr, addr_strm.GetData()); + } + } else { + StreamString addr_strm; + so_addr.Dump(&addr_strm, nullptr, + Address::DumpStyleModuleWithFileAddress); + error_strm.Printf("Address 0x%" PRIx64 + " resolves to %s, but it cannot" + " be found in any modules.\n", + addr, addr_strm.GetData()); } - FileSpec file_spec; - if (!DumpLinesInSymbolContexts(result.GetOutputStream(), - sc_list_lines, module_list, file_spec)) - { - result.AppendErrorWithFormat("Unable to dump line information for symbol '%s'.\n", - name.AsCString()); - return false; - } - return true; + } else + error_strm.Printf("Unable to resolve address 0x%" PRIx64 ".\n", addr); } - - // Dump the line entries found for the address specified in the option. - bool - DumpLinesForAddress (CommandReturnObject &result) - { - Target *target = m_exe_ctx.GetTargetPtr(); - SymbolContextList sc_list; - - StreamString error_strm; - if (!GetSymbolContextsForAddress(target->GetImages(), m_options.address, sc_list, error_strm)) - { - result.AppendErrorWithFormat("%s.\n", error_strm.GetData()); - return false; + return num_matches; + } + + // Dump the line entries found in functions matching the name specified in the + // option. + bool DumpLinesInFunctions(CommandReturnObject &result) { + SymbolContextList sc_list_funcs; + ConstString name(m_options.symbol_name.c_str()); + SymbolContextList sc_list_lines; + Target *target = m_exe_ctx.GetTargetPtr(); + uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); + + // Note: module_list can't be const& because FindFunctionSymbols isn't + // const. + ModuleList module_list = + (m_module_list.GetSize() > 0) ? m_module_list : target->GetImages(); + size_t num_matches = + module_list.FindFunctions(name, eFunctionNameTypeAuto, + /*include_symbols=*/false, + /*include_inlines=*/true, + /*append=*/true, sc_list_funcs); + if (!num_matches) { + // If we didn't find any functions with that name, try searching for + // symbols that line up exactly with function addresses. + SymbolContextList sc_list_symbols; + size_t num_symbol_matches = module_list.FindFunctionSymbols( + name, eFunctionNameTypeAuto, sc_list_symbols); + for (size_t i = 0; i < num_symbol_matches; i++) { + SymbolContext sc; + sc_list_symbols.GetContextAtIndex(i, sc); + if (sc.symbol && sc.symbol->ValueIsAddress()) { + const Address &base_address = sc.symbol->GetAddressRef(); + Function *function = base_address.CalculateSymbolContextFunction(); + if (function) { + sc_list_funcs.Append(SymbolContext(function)); + num_matches++; + } } - ModuleList module_list; - FileSpec file_spec; - if (!DumpLinesInSymbolContexts(result.GetOutputStream(), - sc_list, module_list, file_spec)) - { - result.AppendErrorWithFormat("No modules contain load address 0x%" PRIx64 ".\n", - m_options.address); - return false; + } + } + if (num_matches == 0) { + result.AppendErrorWithFormat("Could not find function named \'%s\'.\n", + m_options.symbol_name.c_str()); + return false; + } + for (size_t i = 0; i < num_matches; i++) { + SymbolContext sc; + sc_list_funcs.GetContextAtIndex(i, sc); + bool context_found_for_symbol = false; + // Loop through all the ranges in the function. + AddressRange range; + for (uint32_t r = 0; + sc.GetAddressRange(eSymbolContextEverything, r, + /*use_inline_block_range=*/true, range); + ++r) { + // Append the symbol contexts for each address in the range to + // sc_list_lines. + const Address &base_address = range.GetBaseAddress(); + const addr_t size = range.GetByteSize(); + lldb::addr_t start_addr = base_address.GetLoadAddress(target); + if (start_addr == LLDB_INVALID_ADDRESS) + start_addr = base_address.GetFileAddress(); + lldb::addr_t end_addr = start_addr + size; + for (lldb::addr_t addr = start_addr; addr < end_addr; + addr += addr_byte_size) { + StreamString error_strm; + if (!GetSymbolContextsForAddress(module_list, addr, sc_list_lines, + error_strm)) + result.AppendWarningWithFormat("in symbol '%s': %s", + sc.GetFunctionName().AsCString(), + error_strm.GetData()); + else + context_found_for_symbol = true; } - return true; + } + if (!context_found_for_symbol) + result.AppendWarningWithFormat("Unable to find line information" + " for matching symbol '%s'.\n", + sc.GetFunctionName().AsCString()); + } + if (sc_list_lines.GetSize() == 0) { + result.AppendErrorWithFormat("No line information could be found" + " for any symbols matching '%s'.\n", + name.AsCString()); + return false; } + FileSpec file_spec; + if (!DumpLinesInSymbolContexts(result.GetOutputStream(), sc_list_lines, + module_list, file_spec)) { + result.AppendErrorWithFormat( + "Unable to dump line information for symbol '%s'.\n", + name.AsCString()); + return false; + } + return true; + } + + // Dump the line entries found for the address specified in the option. + bool DumpLinesForAddress(CommandReturnObject &result) { + Target *target = m_exe_ctx.GetTargetPtr(); + SymbolContextList sc_list; + + StreamString error_strm; + if (!GetSymbolContextsForAddress(target->GetImages(), m_options.address, + sc_list, error_strm)) { + result.AppendErrorWithFormat("%s.\n", error_strm.GetData()); + return false; + } + ModuleList module_list; + FileSpec file_spec; + if (!DumpLinesInSymbolContexts(result.GetOutputStream(), sc_list, + module_list, file_spec)) { + result.AppendErrorWithFormat("No modules contain load address 0x%" PRIx64 + ".\n", + m_options.address); + return false; + } + return true; + } + + // Dump the line entries found in the file specified in the option. + bool DumpLinesForFile(CommandReturnObject &result) { + FileSpec file_spec(m_options.file_name, false); + const char *filename = m_options.file_name.c_str(); + Target *target = m_exe_ctx.GetTargetPtr(); + const ModuleList &module_list = + (m_module_list.GetSize() > 0) ? m_module_list : target->GetImages(); + + bool displayed_something = false; + const size_t num_modules = module_list.GetSize(); + for (uint32_t i = 0; i < num_modules; ++i) { + // Dump lines for this module. + Module *module = module_list.GetModulePointerAtIndex(i); + assert(module); + if (DumpFileLinesInModule(result.GetOutputStream(), module, file_spec)) + displayed_something = true; + } + if (!displayed_something) { + result.AppendErrorWithFormat("No source filenames matched '%s'.\n", + filename); + return false; + } + return true; + } + + // Dump the line entries for the current frame. + bool DumpLinesForFrame(CommandReturnObject &result) { + StackFrame *cur_frame = m_exe_ctx.GetFramePtr(); + if (cur_frame == nullptr) { + result.AppendError( + "No selected frame to use to find the default source."); + return false; + } else if (!cur_frame->HasDebugInformation()) { + result.AppendError("No debug info for the selected frame."); + return false; + } else { + const SymbolContext &sc = + cur_frame->GetSymbolContext(eSymbolContextLineEntry); + SymbolContextList sc_list; + sc_list.Append(sc); + ModuleList module_list; + FileSpec file_spec; + if (!DumpLinesInSymbolContexts(result.GetOutputStream(), sc_list, + module_list, file_spec)) { + result.AppendError( + "No source line info available for the selected frame."); + return false; + } + } + return true; + } - // Dump the line entries found in the file specified in the option. - bool - DumpLinesForFile (CommandReturnObject &result) - { - FileSpec file_spec(m_options.file_name, false); - const char *filename = m_options.file_name.c_str(); - Target *target = m_exe_ctx.GetTargetPtr(); - const ModuleList &module_list = (m_module_list.GetSize() > 0) ? - m_module_list : target->GetImages(); + bool DoExecute(Args &command, CommandReturnObject &result) override { + const size_t argc = command.GetArgumentCount(); - bool displayed_something = false; - const size_t num_modules = module_list.GetSize(); - for (uint32_t i = 0; i < num_modules; ++i) - { - // Dump lines for this module. - Module *module = module_list.GetModulePointerAtIndex(i); - assert(module); - if (DumpFileLinesInModule(result.GetOutputStream(), module, file_spec)) - displayed_something = true; - } - if (!displayed_something) - { - result.AppendErrorWithFormat("No source filenames matched '%s'.\n", filename); - return false; - } - return true; + if (argc != 0) { + result.AppendErrorWithFormat("'%s' takes no arguments, only flags.\n", + GetCommandName()); + result.SetStatus(eReturnStatusFailed); + return false; } - // Dump the line entries for the current frame. - bool - DumpLinesForFrame (CommandReturnObject &result) - { - StackFrame *cur_frame = m_exe_ctx.GetFramePtr(); - if (cur_frame == nullptr) - { - result.AppendError("No selected frame to use to find the default source."); - return false; - } - else if (!cur_frame->HasDebugInformation()) - { - result.AppendError("No debug info for the selected frame."); - return false; - } - else - { - const SymbolContext &sc = cur_frame->GetSymbolContext(eSymbolContextLineEntry); - SymbolContextList sc_list; - sc_list.Append(sc); - ModuleList module_list; - FileSpec file_spec; - if (!DumpLinesInSymbolContexts(result.GetOutputStream(), sc_list, module_list, file_spec)) - { - result.AppendError("No source line info available for the selected frame."); - return false; - } - } - return true; + Target *target = m_exe_ctx.GetTargetPtr(); + if (target == nullptr) { + target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (target == nullptr) { + result.AppendError("invalid target, create a debug target using the " + "'target create' command."); + result.SetStatus(eReturnStatusFailed); + return false; + } } - bool - DoExecute (Args &command, CommandReturnObject &result) override - { - const size_t argc = command.GetArgumentCount(); - - if (argc != 0) - { - result.AppendErrorWithFormat("'%s' takes no arguments, only flags.\n", - GetCommandName()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - Target *target = m_exe_ctx.GetTargetPtr(); - if (target == nullptr) - { - target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) - { - result.AppendError("invalid target, create a debug target using the " - "'target create' command."); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - - uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); - result.GetOutputStream().SetAddressByteSize(addr_byte_size); - result.GetErrorStream().SetAddressByteSize(addr_byte_size); - - // Collect the list of modules to search. - m_module_list.Clear(); - if (!m_options.modules.empty()) - { - for (size_t i = 0, e = m_options.modules.size(); i < e; ++i) - { - FileSpec module_file_spec(m_options.modules[i].c_str(), false); - if (module_file_spec) - { - ModuleSpec module_spec(module_file_spec); - if (target->GetImages().FindModules(module_spec, m_module_list) == 0) - result.AppendWarningWithFormat("No module found for '%s'.\n", - m_options.modules[i].c_str()); - } - } - if (!m_module_list.GetSize()) - { - result.AppendError("No modules match the input."); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - else if (target->GetImages().GetSize() == 0) - { - result.AppendError("The target has no associated executable images."); - result.SetStatus(eReturnStatusFailed); - return false; + uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); + result.GetOutputStream().SetAddressByteSize(addr_byte_size); + result.GetErrorStream().SetAddressByteSize(addr_byte_size); + + // Collect the list of modules to search. + m_module_list.Clear(); + if (!m_options.modules.empty()) { + for (size_t i = 0, e = m_options.modules.size(); i < e; ++i) { + FileSpec module_file_spec(m_options.modules[i].c_str(), false); + if (module_file_spec) { + ModuleSpec module_spec(module_file_spec); + if (target->GetImages().FindModules(module_spec, m_module_list) == 0) + result.AppendWarningWithFormat("No module found for '%s'.\n", + m_options.modules[i].c_str()); } + } + if (!m_module_list.GetSize()) { + result.AppendError("No modules match the input."); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else if (target->GetImages().GetSize() == 0) { + result.AppendError("The target has no associated executable images."); + result.SetStatus(eReturnStatusFailed); + return false; + } - // Check the arguments to see what lines we should dump. - if (!m_options.symbol_name.empty()) - { - // Print lines for symbol. - if (DumpLinesInFunctions(result)) - result.SetStatus(eReturnStatusSuccessFinishResult); - else - result.SetStatus(eReturnStatusFailed); - } - else if (m_options.address != LLDB_INVALID_ADDRESS) - { - // Print lines for an address. - if (DumpLinesForAddress(result)) - result.SetStatus(eReturnStatusSuccessFinishResult); - else - result.SetStatus(eReturnStatusFailed); - } - else if (!m_options.file_name.empty()) - { - // Dump lines for a file. - if (DumpLinesForFile(result)) - result.SetStatus(eReturnStatusSuccessFinishResult); - else - result.SetStatus(eReturnStatusFailed); - } - else - { - // Dump the line for the current frame. - if (DumpLinesForFrame(result)) - result.SetStatus(eReturnStatusSuccessFinishResult); - else - result.SetStatus(eReturnStatusFailed); - } - return result.Succeeded(); + // Check the arguments to see what lines we should dump. + if (!m_options.symbol_name.empty()) { + // Print lines for symbol. + if (DumpLinesInFunctions(result)) + result.SetStatus(eReturnStatusSuccessFinishResult); + else + result.SetStatus(eReturnStatusFailed); + } else if (m_options.address != LLDB_INVALID_ADDRESS) { + // Print lines for an address. + if (DumpLinesForAddress(result)) + result.SetStatus(eReturnStatusSuccessFinishResult); + else + result.SetStatus(eReturnStatusFailed); + } else if (!m_options.file_name.empty()) { + // Dump lines for a file. + if (DumpLinesForFile(result)) + result.SetStatus(eReturnStatusSuccessFinishResult); + else + result.SetStatus(eReturnStatusFailed); + } else { + // Dump the line for the current frame. + if (DumpLinesForFrame(result)) + result.SetStatus(eReturnStatusSuccessFinishResult); + else + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } - CommandOptions m_options; - ModuleList m_module_list; + CommandOptions m_options; + ModuleList m_module_list; }; OptionDefinition CommandObjectSourceInfo::CommandOptions::g_option_table[] = { - // clang-format off + // clang-format off {LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "The number of line entries to display."}, {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Look up the source in the given module or shared library (can be specified more than once)."}, {LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source."}, @@ -710,7 +659,7 @@ OptionDefinition CommandObjectSourceInfo::CommandOptions::g_option_table[] = { {LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeSymbol, "The name of a function whose source to display."}, {LLDB_OPT_SET_3, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Lookup the address and display the source information for the corresponding file and line."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; #pragma mark CommandObjectSourceList @@ -718,748 +667,638 @@ OptionDefinition CommandObjectSourceInfo::CommandOptions::g_option_table[] = { // CommandObjectSourceList //------------------------------------------------------------------------- -class CommandObjectSourceList : public CommandObjectParsed -{ - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - } +class CommandObjectSourceList : public CommandObjectParsed { + class CommandOptions : public Options { + public: + CommandOptions() : Options() {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = g_option_table[option_idx].short_option; + switch (short_option) { + case 'l': + start_line = StringConvert::ToUInt32(option_arg, 0); + if (start_line == 0) + error.SetErrorStringWithFormat("invalid line number: '%s'", + option_arg); + break; + + case 'c': + num_lines = StringConvert::ToUInt32(option_arg, 0); + if (num_lines == 0) + error.SetErrorStringWithFormat("invalid line count: '%s'", + option_arg); + break; + + case 'f': + file_name = option_arg; + break; + + case 'n': + symbol_name = option_arg; + break; + + case 'a': { + address = Args::StringToAddress(execution_context, option_arg, + LLDB_INVALID_ADDRESS, &error); + } break; + case 's': + modules.push_back(std::string(option_arg)); + break; + + case 'b': + show_bp_locs = true; + break; + case 'r': + reverse = true; + break; + default: + error.SetErrorStringWithFormat("unrecognized short option '%c'", + short_option); + break; + } + + return error; + } - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = g_option_table[option_idx].short_option; - switch (short_option) - { - case 'l': - start_line = StringConvert::ToUInt32 (option_arg, 0); - if (start_line == 0) - error.SetErrorStringWithFormat("invalid line number: '%s'", option_arg); - break; - - case 'c': - num_lines = StringConvert::ToUInt32 (option_arg, 0); - if (num_lines == 0) - error.SetErrorStringWithFormat("invalid line count: '%s'", option_arg); - break; - - case 'f': - file_name = option_arg; - break; - - case 'n': - symbol_name = option_arg; - break; - - case 'a': - { - address = Args::StringToAddress(execution_context, - option_arg, - LLDB_INVALID_ADDRESS, - &error); - } - break; - case 's': - modules.push_back (std::string (option_arg)); - break; - - case 'b': - show_bp_locs = true; - break; - case 'r': - reverse = true; - break; - default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); - break; - } + void OptionParsingStarting(ExecutionContext *execution_context) override { + file_spec.Clear(); + file_name.clear(); + symbol_name.clear(); + address = LLDB_INVALID_ADDRESS; + start_line = 0; + num_lines = 0; + show_bp_locs = false; + reverse = false; + modules.clear(); + } - return error; - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - file_spec.Clear(); - file_name.clear(); - symbol_name.clear(); - address = LLDB_INVALID_ADDRESS; - start_line = 0; - num_lines = 0; - show_bp_locs = false; - reverse = false; - modules.clear(); - } + static OptionDefinition g_option_table[]; - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } + // Instance variables to hold the values for command options. + FileSpec file_spec; + std::string file_name; + std::string symbol_name; + lldb::addr_t address; + uint32_t start_line; + uint32_t num_lines; + STLStringArray modules; + bool show_bp_locs; + bool reverse; + }; - static OptionDefinition g_option_table[]; +public: + CommandObjectSourceList(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "source list", + "Display source code for the current target " + "process as specified by options.", + nullptr, eCommandRequiresTarget), + m_options() {} + + ~CommandObjectSourceList() override = default; + + Options *GetOptions() override { return &m_options; } + + const char *GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override { + // This is kind of gross, but the command hasn't been parsed yet so we can't + // look at the option + // values for this invocation... I have to scan the arguments directly. + size_t num_args = current_command_args.GetArgumentCount(); + bool is_reverse = false; + for (size_t i = 0; i < num_args; i++) { + const char *arg = current_command_args.GetArgumentAtIndex(i); + if (arg && (strcmp(arg, "-r") == 0 || strcmp(arg, "--reverse") == 0)) { + is_reverse = true; + } + } + if (is_reverse) { + if (m_reverse_name.empty()) { + m_reverse_name = m_cmd_name; + m_reverse_name.append(" -r"); + } + return m_reverse_name.c_str(); + } else + return m_cmd_name.c_str(); + } - // Instance variables to hold the values for command options. - FileSpec file_spec; - std::string file_name; - std::string symbol_name; - lldb::addr_t address; - uint32_t start_line; - uint32_t num_lines; - STLStringArray modules; - bool show_bp_locs; - bool reverse; - }; +protected: + struct SourceInfo { + ConstString function; + LineEntry line_entry; -public: - CommandObjectSourceList(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "source list", - "Display source code for the current target process as specified by options.", nullptr, - eCommandRequiresTarget), - m_options() - { + SourceInfo(const ConstString &name, const LineEntry &line_entry) + : function(name), line_entry(line_entry) {} + + SourceInfo() : function(), line_entry() {} + + bool IsValid() const { return (bool)function && line_entry.IsValid(); } + + bool operator==(const SourceInfo &rhs) const { + return function == rhs.function && + line_entry.original_file == rhs.line_entry.original_file && + line_entry.line == rhs.line_entry.line; } - ~CommandObjectSourceList() override = default; + bool operator!=(const SourceInfo &rhs) const { + return function != rhs.function || + line_entry.original_file != rhs.line_entry.original_file || + line_entry.line != rhs.line_entry.line; + } - Options * - GetOptions () override - { - return &m_options; + bool operator<(const SourceInfo &rhs) const { + if (function.GetCString() < rhs.function.GetCString()) + return true; + if (line_entry.file.GetDirectory().GetCString() < + rhs.line_entry.file.GetDirectory().GetCString()) + return true; + if (line_entry.file.GetFilename().GetCString() < + rhs.line_entry.file.GetFilename().GetCString()) + return true; + if (line_entry.line < rhs.line_entry.line) + return true; + return false; } + }; - const char * - GetRepeatCommand (Args ¤t_command_args, uint32_t index) override - { - // This is kind of gross, but the command hasn't been parsed yet so we can't look at the option - // values for this invocation... I have to scan the arguments directly. - size_t num_args = current_command_args.GetArgumentCount(); - bool is_reverse = false; - for (size_t i = 0; i < num_args; i++) - { - const char *arg = current_command_args.GetArgumentAtIndex(i); - if (arg && (strcmp(arg, "-r") == 0 || strcmp(arg, "--reverse") == 0)) - { - is_reverse = true; - } - } - if (is_reverse) - { - if (m_reverse_name.empty()) - { - m_reverse_name = m_cmd_name; - m_reverse_name.append (" -r"); - } - return m_reverse_name.c_str(); - } - else - return m_cmd_name.c_str(); + size_t DisplayFunctionSource(const SymbolContext &sc, SourceInfo &source_info, + CommandReturnObject &result) { + if (!source_info.IsValid()) { + source_info.function = sc.GetFunctionName(); + source_info.line_entry = sc.GetFunctionStartLineEntry(); } -protected: - struct SourceInfo - { - ConstString function; - LineEntry line_entry; - - SourceInfo (const ConstString &name, const LineEntry &line_entry) : - function(name), - line_entry(line_entry) - { - } - - SourceInfo () : - function(), - line_entry() - { - } - - bool - IsValid () const - { - return (bool)function && line_entry.IsValid(); + if (sc.function) { + Target *target = m_exe_ctx.GetTargetPtr(); + + FileSpec start_file; + uint32_t start_line; + uint32_t end_line; + FileSpec end_file; + + if (sc.block == nullptr) { + // Not an inlined function + sc.function->GetStartLineSourceInfo(start_file, start_line); + if (start_line == 0) { + result.AppendErrorWithFormat("Could not find line information for " + "start of function: \"%s\".\n", + source_info.function.GetCString()); + result.SetStatus(eReturnStatusFailed); + return 0; } - - bool - operator == (const SourceInfo &rhs) const - { - return function == rhs.function && - line_entry.original_file == rhs.line_entry.original_file && - line_entry.line == rhs.line_entry.line; - } - - bool - operator != (const SourceInfo &rhs) const - { - return function != rhs.function || - line_entry.original_file != rhs.line_entry.original_file || - line_entry.line != rhs.line_entry.line; - } - - bool - operator < (const SourceInfo &rhs) const - { - if (function.GetCString() < rhs.function.GetCString()) - return true; - if (line_entry.file.GetDirectory().GetCString() < rhs.line_entry.file.GetDirectory().GetCString()) - return true; - if (line_entry.file.GetFilename().GetCString() < rhs.line_entry.file.GetFilename().GetCString()) - return true; - if (line_entry.line < rhs.line_entry.line) - return true; - return false; + sc.function->GetEndLineSourceInfo(end_file, end_line); + } else { + // We have an inlined function + start_file = source_info.line_entry.file; + start_line = source_info.line_entry.line; + end_line = start_line + m_options.num_lines; + } + + // This is a little hacky, but the first line table entry for a function + // points to the "{" that + // starts the function block. It would be nice to actually get the + // function + // declaration in there too. So back up a bit, but not further than what + // you're going to display. + uint32_t extra_lines; + if (m_options.num_lines >= 10) + extra_lines = 5; + else + extra_lines = m_options.num_lines / 2; + uint32_t line_no; + if (start_line <= extra_lines) + line_no = 1; + else + line_no = start_line - extra_lines; + + // For fun, if the function is shorter than the number of lines we're + // supposed to display, + // only display the function... + if (end_line != 0) { + if (m_options.num_lines > end_line - line_no) + m_options.num_lines = end_line - line_no + extra_lines; + } + + m_breakpoint_locations.Clear(); + + if (m_options.show_bp_locs) { + const bool show_inlines = true; + m_breakpoint_locations.Reset(start_file, 0, show_inlines); + SearchFilterForUnconstrainedSearches target_search_filter( + m_exe_ctx.GetTargetSP()); + target_search_filter.Search(m_breakpoint_locations); + } + + result.AppendMessageWithFormat("File: %s\n", + start_file.GetPath().c_str()); + return target->GetSourceManager().DisplaySourceLinesWithLineNumbers( + start_file, line_no, 0, m_options.num_lines, "", + &result.GetOutputStream(), GetBreakpointLocations()); + } else { + result.AppendErrorWithFormat( + "Could not find function info for: \"%s\".\n", + m_options.symbol_name.c_str()); + } + return 0; + } + + // From Jim: The FindMatchingFunctions / FindMatchingFunctionSymbols functions + // "take a possibly empty vector of strings which are names of modules, and + // run the two search functions on the subset of the full module list that + // matches the strings in the input vector". If we wanted to put these + // somewhere, + // there should probably be a module-filter-list that can be passed to the + // various ModuleList::Find* calls, which would either be a vector of string + // names or a ModuleSpecList. + size_t FindMatchingFunctions(Target *target, const ConstString &name, + SymbolContextList &sc_list) { + // Displaying the source for a symbol: + bool include_inlines = true; + bool append = true; + bool include_symbols = false; + size_t num_matches = 0; + + if (m_options.num_lines == 0) + m_options.num_lines = 10; + + const size_t num_modules = m_options.modules.size(); + if (num_modules > 0) { + ModuleList matching_modules; + for (size_t i = 0; i < num_modules; ++i) { + FileSpec module_file_spec(m_options.modules[i].c_str(), false); + if (module_file_spec) { + ModuleSpec module_spec(module_file_spec); + matching_modules.Clear(); + target->GetImages().FindModules(module_spec, matching_modules); + num_matches += matching_modules.FindFunctions( + name, eFunctionNameTypeAuto, include_symbols, include_inlines, + append, sc_list); } - }; - - size_t - DisplayFunctionSource (const SymbolContext &sc, - SourceInfo &source_info, - CommandReturnObject &result) - { - if (!source_info.IsValid()) - { - source_info.function = sc.GetFunctionName(); - source_info.line_entry = sc.GetFunctionStartLineEntry(); + } + } else { + num_matches = target->GetImages().FindFunctions( + name, eFunctionNameTypeAuto, include_symbols, include_inlines, append, + sc_list); + } + return num_matches; + } + + size_t FindMatchingFunctionSymbols(Target *target, const ConstString &name, + SymbolContextList &sc_list) { + size_t num_matches = 0; + const size_t num_modules = m_options.modules.size(); + if (num_modules > 0) { + ModuleList matching_modules; + for (size_t i = 0; i < num_modules; ++i) { + FileSpec module_file_spec(m_options.modules[i].c_str(), false); + if (module_file_spec) { + ModuleSpec module_spec(module_file_spec); + matching_modules.Clear(); + target->GetImages().FindModules(module_spec, matching_modules); + num_matches += matching_modules.FindFunctionSymbols( + name, eFunctionNameTypeAuto, sc_list); } - - if (sc.function) - { - Target *target = m_exe_ctx.GetTargetPtr(); - - FileSpec start_file; - uint32_t start_line; - uint32_t end_line; - FileSpec end_file; - - if (sc.block == nullptr) - { - // Not an inlined function - sc.function->GetStartLineSourceInfo (start_file, start_line); - if (start_line == 0) - { - result.AppendErrorWithFormat("Could not find line information for start of function: \"%s\".\n", source_info.function.GetCString()); - result.SetStatus (eReturnStatusFailed); - return 0; - } - sc.function->GetEndLineSourceInfo (end_file, end_line); - } - else - { - // We have an inlined function - start_file = source_info.line_entry.file; - start_line = source_info.line_entry.line; - end_line = start_line + m_options.num_lines; - } + } + } else { + num_matches = target->GetImages().FindFunctionSymbols( + name, eFunctionNameTypeAuto, sc_list); + } + return num_matches; + } - // This is a little hacky, but the first line table entry for a function points to the "{" that - // starts the function block. It would be nice to actually get the function - // declaration in there too. So back up a bit, but not further than what you're going to display. - uint32_t extra_lines; - if (m_options.num_lines >= 10) - extra_lines = 5; - else - extra_lines = m_options.num_lines/2; - uint32_t line_no; - if (start_line <= extra_lines) - line_no = 1; - else - line_no = start_line - extra_lines; - - // For fun, if the function is shorter than the number of lines we're supposed to display, - // only display the function... - if (end_line != 0) - { - if (m_options.num_lines > end_line - line_no) - m_options.num_lines = end_line - line_no + extra_lines; - } - - m_breakpoint_locations.Clear(); + bool DoExecute(Args &command, CommandReturnObject &result) override { + const size_t argc = command.GetArgumentCount(); + + if (argc != 0) { + result.AppendErrorWithFormat("'%s' takes no arguments, only flags.\n", + GetCommandName()); + result.SetStatus(eReturnStatusFailed); + return false; + } - if (m_options.show_bp_locs) - { - const bool show_inlines = true; - m_breakpoint_locations.Reset (start_file, 0, show_inlines); - SearchFilterForUnconstrainedSearches target_search_filter (m_exe_ctx.GetTargetSP()); - target_search_filter.Search (m_breakpoint_locations); + Target *target = m_exe_ctx.GetTargetPtr(); + + if (!m_options.symbol_name.empty()) { + SymbolContextList sc_list; + ConstString name(m_options.symbol_name.c_str()); + + // Displaying the source for a symbol. Search for function named name. + size_t num_matches = FindMatchingFunctions(target, name, sc_list); + if (!num_matches) { + // If we didn't find any functions with that name, try searching for + // symbols + // that line up exactly with function addresses. + SymbolContextList sc_list_symbols; + size_t num_symbol_matches = + FindMatchingFunctionSymbols(target, name, sc_list_symbols); + for (size_t i = 0; i < num_symbol_matches; i++) { + SymbolContext sc; + sc_list_symbols.GetContextAtIndex(i, sc); + if (sc.symbol && sc.symbol->ValueIsAddress()) { + const Address &base_address = sc.symbol->GetAddressRef(); + Function *function = base_address.CalculateSymbolContextFunction(); + if (function) { + sc_list.Append(SymbolContext(function)); + num_matches++; + break; } - - result.AppendMessageWithFormat("File: %s\n", start_file.GetPath().c_str()); - return target->GetSourceManager().DisplaySourceLinesWithLineNumbers (start_file, - line_no, - 0, - m_options.num_lines, - "", - &result.GetOutputStream(), - GetBreakpointLocations ()); - } - else - { - result.AppendErrorWithFormat("Could not find function info for: \"%s\".\n", m_options.symbol_name.c_str()); + } } - return 0; - } + } - // From Jim: The FindMatchingFunctions / FindMatchingFunctionSymbols functions - // "take a possibly empty vector of strings which are names of modules, and - // run the two search functions on the subset of the full module list that - // matches the strings in the input vector". If we wanted to put these somewhere, - // there should probably be a module-filter-list that can be passed to the - // various ModuleList::Find* calls, which would either be a vector of string - // names or a ModuleSpecList. - size_t FindMatchingFunctions (Target *target, const ConstString &name, SymbolContextList& sc_list) - { - // Displaying the source for a symbol: - bool include_inlines = true; - bool append = true; - bool include_symbols = false; - size_t num_matches = 0; - - if (m_options.num_lines == 0) - m_options.num_lines = 10; + if (num_matches == 0) { + result.AppendErrorWithFormat("Could not find function named: \"%s\".\n", + m_options.symbol_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (num_matches > 1) { + std::set<SourceInfo> source_match_set; - const size_t num_modules = m_options.modules.size(); - if (num_modules > 0) - { - ModuleList matching_modules; - for (size_t i = 0; i < num_modules; ++i) - { - FileSpec module_file_spec(m_options.modules[i].c_str(), false); - if (module_file_spec) - { - ModuleSpec module_spec (module_file_spec); - matching_modules.Clear(); - target->GetImages().FindModules (module_spec, matching_modules); - num_matches += matching_modules.FindFunctions (name, eFunctionNameTypeAuto, include_symbols, include_inlines, append, sc_list); - } + bool displayed_something = false; + for (size_t i = 0; i < num_matches; i++) { + SymbolContext sc; + sc_list.GetContextAtIndex(i, sc); + SourceInfo source_info(sc.GetFunctionName(), + sc.GetFunctionStartLineEntry()); + + if (source_info.IsValid()) { + if (source_match_set.find(source_info) == source_match_set.end()) { + source_match_set.insert(source_info); + if (DisplayFunctionSource(sc, source_info, result)) + displayed_something = true; } + } } + + if (displayed_something) + result.SetStatus(eReturnStatusSuccessFinishResult); else - { - num_matches = target->GetImages().FindFunctions (name, eFunctionNameTypeAuto, include_symbols, include_inlines, append, sc_list); + result.SetStatus(eReturnStatusFailed); + } else { + SymbolContext sc; + sc_list.GetContextAtIndex(0, sc); + SourceInfo source_info; + + if (DisplayFunctionSource(sc, source_info, result)) { + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.SetStatus(eReturnStatusFailed); + } + } + return result.Succeeded(); + } else if (m_options.address != LLDB_INVALID_ADDRESS) { + Address so_addr; + StreamString error_strm; + SymbolContextList sc_list; + + if (target->GetSectionLoadList().IsEmpty()) { + // The target isn't loaded yet, we need to lookup the file address + // in all modules + const ModuleList &module_list = target->GetImages(); + const size_t num_modules = module_list.GetSize(); + for (size_t i = 0; i < num_modules; ++i) { + ModuleSP module_sp(module_list.GetModuleAtIndex(i)); + if (module_sp && + module_sp->ResolveFileAddress(m_options.address, so_addr)) { + SymbolContext sc; + sc.Clear(true); + if (module_sp->ResolveSymbolContextForAddress( + so_addr, eSymbolContextEverything, sc) & + eSymbolContextLineEntry) + sc_list.Append(sc); + } } - return num_matches; - } - size_t FindMatchingFunctionSymbols (Target *target, const ConstString &name, SymbolContextList& sc_list) - { - size_t num_matches = 0; - const size_t num_modules = m_options.modules.size(); - if (num_modules > 0) - { - ModuleList matching_modules; - for (size_t i = 0; i < num_modules; ++i) - { - FileSpec module_file_spec(m_options.modules[i].c_str(), false); - if (module_file_spec) - { - ModuleSpec module_spec (module_file_spec); - matching_modules.Clear(); - target->GetImages().FindModules (module_spec, matching_modules); - num_matches += matching_modules.FindFunctionSymbols (name, eFunctionNameTypeAuto, sc_list); - } - } + if (sc_list.GetSize() == 0) { + result.AppendErrorWithFormat( + "no modules have source information for file address 0x%" PRIx64 + ".\n", + m_options.address); + result.SetStatus(eReturnStatusFailed); + return false; } - else - { - num_matches = target->GetImages().FindFunctionSymbols (name, eFunctionNameTypeAuto, sc_list); + } else { + // The target has some things loaded, resolve this address to a + // compile unit + file + line and display + if (target->GetSectionLoadList().ResolveLoadAddress(m_options.address, + so_addr)) { + ModuleSP module_sp(so_addr.GetModule()); + if (module_sp) { + SymbolContext sc; + sc.Clear(true); + if (module_sp->ResolveSymbolContextForAddress( + so_addr, eSymbolContextEverything, sc) & + eSymbolContextLineEntry) { + sc_list.Append(sc); + } else { + so_addr.Dump(&error_strm, nullptr, + Address::DumpStyleModuleWithFileAddress); + result.AppendErrorWithFormat("address resolves to %s, but there " + "is no line table information " + "available for this address.\n", + error_strm.GetData()); + result.SetStatus(eReturnStatusFailed); + return false; + } + } } - return num_matches; - } - - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - const size_t argc = command.GetArgumentCount(); - if (argc != 0) - { - result.AppendErrorWithFormat("'%s' takes no arguments, only flags.\n", GetCommandName()); - result.SetStatus (eReturnStatusFailed); - return false; + if (sc_list.GetSize() == 0) { + result.AppendErrorWithFormat( + "no modules contain load address 0x%" PRIx64 ".\n", + m_options.address); + result.SetStatus(eReturnStatusFailed); + return false; } + } + uint32_t num_matches = sc_list.GetSize(); + for (uint32_t i = 0; i < num_matches; ++i) { + SymbolContext sc; + sc_list.GetContextAtIndex(i, sc); + if (sc.comp_unit) { + if (m_options.show_bp_locs) { + m_breakpoint_locations.Clear(); + const bool show_inlines = true; + m_breakpoint_locations.Reset(*sc.comp_unit, 0, show_inlines); + SearchFilterForUnconstrainedSearches target_search_filter( + target->shared_from_this()); + target_search_filter.Search(m_breakpoint_locations); + } + + bool show_fullpaths = true; + bool show_module = true; + bool show_inlined_frames = true; + const bool show_function_arguments = true; + const bool show_function_name = true; + sc.DumpStopContext(&result.GetOutputStream(), + m_exe_ctx.GetBestExecutionContextScope(), + sc.line_entry.range.GetBaseAddress(), + show_fullpaths, show_module, show_inlined_frames, + show_function_arguments, show_function_name); + result.GetOutputStream().EOL(); + + if (m_options.num_lines == 0) + m_options.num_lines = 10; - Target *target = m_exe_ctx.GetTargetPtr(); - - if (!m_options.symbol_name.empty()) - { - SymbolContextList sc_list; - ConstString name(m_options.symbol_name.c_str()); - - // Displaying the source for a symbol. Search for function named name. - size_t num_matches = FindMatchingFunctions (target, name, sc_list); - if (!num_matches) - { - // If we didn't find any functions with that name, try searching for symbols - // that line up exactly with function addresses. - SymbolContextList sc_list_symbols; - size_t num_symbol_matches = FindMatchingFunctionSymbols (target, name, sc_list_symbols); - for (size_t i = 0; i < num_symbol_matches; i++) - { - SymbolContext sc; - sc_list_symbols.GetContextAtIndex (i, sc); - if (sc.symbol && sc.symbol->ValueIsAddress()) - { - const Address &base_address = sc.symbol->GetAddressRef(); - Function *function = base_address.CalculateSymbolContextFunction(); - if (function) - { - sc_list.Append (SymbolContext(function)); - num_matches++; - break; - } - } - } - } - - if (num_matches == 0) - { - result.AppendErrorWithFormat("Could not find function named: \"%s\".\n", m_options.symbol_name.c_str()); - result.SetStatus (eReturnStatusFailed); - return false; - } + size_t lines_to_back_up = + m_options.num_lines >= 10 ? 5 : m_options.num_lines / 2; - if (num_matches > 1) - { - std::set<SourceInfo> source_match_set; - - bool displayed_something = false; - for (size_t i = 0; i < num_matches; i++) - { - SymbolContext sc; - sc_list.GetContextAtIndex (i, sc); - SourceInfo source_info (sc.GetFunctionName(), - sc.GetFunctionStartLineEntry()); - - if (source_info.IsValid()) - { - if (source_match_set.find(source_info) == source_match_set.end()) - { - source_match_set.insert(source_info); - if (DisplayFunctionSource (sc, source_info, result)) - displayed_something = true; - } - } - } - - if (displayed_something) - result.SetStatus (eReturnStatusSuccessFinishResult); - else - result.SetStatus (eReturnStatusFailed); - } - else - { - SymbolContext sc; - sc_list.GetContextAtIndex (0, sc); - SourceInfo source_info; - - if (DisplayFunctionSource (sc, source_info, result)) - { - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.SetStatus (eReturnStatusFailed); - } - } - return result.Succeeded(); + target->GetSourceManager().DisplaySourceLinesWithLineNumbers( + sc.comp_unit, sc.line_entry.line, lines_to_back_up, + m_options.num_lines - lines_to_back_up, "->", + &result.GetOutputStream(), GetBreakpointLocations()); + result.SetStatus(eReturnStatusSuccessFinishResult); } - else if (m_options.address != LLDB_INVALID_ADDRESS) - { - Address so_addr; - StreamString error_strm; - SymbolContextList sc_list; - - if (target->GetSectionLoadList().IsEmpty()) - { - // The target isn't loaded yet, we need to lookup the file address - // in all modules - const ModuleList &module_list = target->GetImages(); - const size_t num_modules = module_list.GetSize(); - for (size_t i = 0; i < num_modules; ++i) - { - ModuleSP module_sp (module_list.GetModuleAtIndex(i)); - if (module_sp && module_sp->ResolveFileAddress(m_options.address, so_addr)) - { - SymbolContext sc; - sc.Clear(true); - if (module_sp->ResolveSymbolContextForAddress (so_addr, eSymbolContextEverything, sc) & eSymbolContextLineEntry) - sc_list.Append(sc); - } - } - - if (sc_list.GetSize() == 0) - { - result.AppendErrorWithFormat("no modules have source information for file address 0x%" PRIx64 ".\n", - m_options.address); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - else - { - // The target has some things loaded, resolve this address to a - // compile unit + file + line and display - if (target->GetSectionLoadList().ResolveLoadAddress (m_options.address, so_addr)) - { - ModuleSP module_sp (so_addr.GetModule()); - if (module_sp) - { - SymbolContext sc; - sc.Clear(true); - if (module_sp->ResolveSymbolContextForAddress (so_addr, eSymbolContextEverything, sc) & eSymbolContextLineEntry) - { - sc_list.Append(sc); - } - else - { - so_addr.Dump(&error_strm, nullptr, Address::DumpStyleModuleWithFileAddress); - result.AppendErrorWithFormat("address resolves to %s, but there is no line table information available for this address.\n", - error_strm.GetData()); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - } - - if (sc_list.GetSize() == 0) - { - result.AppendErrorWithFormat("no modules contain load address 0x%" PRIx64 ".\n", m_options.address); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - uint32_t num_matches = sc_list.GetSize(); - for (uint32_t i = 0; i < num_matches; ++i) - { - SymbolContext sc; - sc_list.GetContextAtIndex(i, sc); - if (sc.comp_unit) - { - if (m_options.show_bp_locs) - { - m_breakpoint_locations.Clear(); - const bool show_inlines = true; - m_breakpoint_locations.Reset (*sc.comp_unit, 0, show_inlines); - SearchFilterForUnconstrainedSearches target_search_filter (target->shared_from_this()); - target_search_filter.Search (m_breakpoint_locations); - } - - bool show_fullpaths = true; - bool show_module = true; - bool show_inlined_frames = true; - const bool show_function_arguments = true; - const bool show_function_name = true; - sc.DumpStopContext(&result.GetOutputStream(), - m_exe_ctx.GetBestExecutionContextScope(), - sc.line_entry.range.GetBaseAddress(), - show_fullpaths, - show_module, - show_inlined_frames, - show_function_arguments, - show_function_name); - result.GetOutputStream().EOL(); - - if (m_options.num_lines == 0) - m_options.num_lines = 10; - - size_t lines_to_back_up = m_options.num_lines >= 10 ? 5 : m_options.num_lines/2; - - target->GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.comp_unit, - sc.line_entry.line, - lines_to_back_up, - m_options.num_lines - lines_to_back_up, - "->", - &result.GetOutputStream(), - GetBreakpointLocations ()); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - } + } + } else if (m_options.file_name.empty()) { + // Last valid source manager context, or the current frame if no + // valid last context in source manager. + // One little trick here, if you type the exact same list command twice in + // a row, it is + // more likely because you typed it once, then typed it again + if (m_options.start_line == 0) { + if (target->GetSourceManager().DisplayMoreWithLineNumbers( + &result.GetOutputStream(), m_options.num_lines, + m_options.reverse, GetBreakpointLocations())) { + result.SetStatus(eReturnStatusSuccessFinishResult); } - else if (m_options.file_name.empty()) - { - // Last valid source manager context, or the current frame if no - // valid last context in source manager. - // One little trick here, if you type the exact same list command twice in a row, it is - // more likely because you typed it once, then typed it again - if (m_options.start_line == 0) - { - if (target->GetSourceManager().DisplayMoreWithLineNumbers (&result.GetOutputStream(), - m_options.num_lines, - m_options.reverse, - GetBreakpointLocations ())) - { - result.SetStatus (eReturnStatusSuccessFinishResult); - } - } - else - { - if (m_options.num_lines == 0) - m_options.num_lines = 10; - - if (m_options.show_bp_locs) - { - SourceManager::FileSP last_file_sp (target->GetSourceManager().GetLastFile ()); - if (last_file_sp) - { - const bool show_inlines = true; - m_breakpoint_locations.Reset (last_file_sp->GetFileSpec(), 0, show_inlines); - SearchFilterForUnconstrainedSearches target_search_filter (target->shared_from_this()); - target_search_filter.Search (m_breakpoint_locations); - } - } - else - m_breakpoint_locations.Clear(); - - if (target->GetSourceManager().DisplaySourceLinesWithLineNumbersUsingLastFile( - m_options.start_line, // Line to display - m_options.num_lines, // Lines after line to - UINT32_MAX, // Don't mark "line" - "", // Don't mark "line" - &result.GetOutputStream(), - GetBreakpointLocations ())) - { - result.SetStatus (eReturnStatusSuccessFinishResult); - } - } + } else { + if (m_options.num_lines == 0) + m_options.num_lines = 10; + + if (m_options.show_bp_locs) { + SourceManager::FileSP last_file_sp( + target->GetSourceManager().GetLastFile()); + if (last_file_sp) { + const bool show_inlines = true; + m_breakpoint_locations.Reset(last_file_sp->GetFileSpec(), 0, + show_inlines); + SearchFilterForUnconstrainedSearches target_search_filter( + target->shared_from_this()); + target_search_filter.Search(m_breakpoint_locations); + } + } else + m_breakpoint_locations.Clear(); + + if (target->GetSourceManager() + .DisplaySourceLinesWithLineNumbersUsingLastFile( + m_options.start_line, // Line to display + m_options.num_lines, // Lines after line to + UINT32_MAX, // Don't mark "line" + "", // Don't mark "line" + &result.GetOutputStream(), GetBreakpointLocations())) { + result.SetStatus(eReturnStatusSuccessFinishResult); } - else - { - const char *filename = m_options.file_name.c_str(); - - bool check_inlines = false; - SymbolContextList sc_list; - size_t num_matches = 0; - - if (!m_options.modules.empty()) - { - ModuleList matching_modules; - for (size_t i = 0, e = m_options.modules.size(); i < e; ++i) - { - FileSpec module_file_spec(m_options.modules[i].c_str(), false); - if (module_file_spec) - { - ModuleSpec module_spec (module_file_spec); - matching_modules.Clear(); - target->GetImages().FindModules (module_spec, matching_modules); - num_matches += matching_modules.ResolveSymbolContextForFilePath (filename, - 0, - check_inlines, - eSymbolContextModule | eSymbolContextCompUnit, - sc_list); - } - } - } - else - { - num_matches = target->GetImages().ResolveSymbolContextForFilePath (filename, - 0, - check_inlines, - eSymbolContextModule | eSymbolContextCompUnit, - sc_list); - } - - if (num_matches == 0) - { - result.AppendErrorWithFormat("Could not find source file \"%s\".\n", - m_options.file_name.c_str()); - result.SetStatus (eReturnStatusFailed); - return false; - } + } + } else { + const char *filename = m_options.file_name.c_str(); + + bool check_inlines = false; + SymbolContextList sc_list; + size_t num_matches = 0; + + if (!m_options.modules.empty()) { + ModuleList matching_modules; + for (size_t i = 0, e = m_options.modules.size(); i < e; ++i) { + FileSpec module_file_spec(m_options.modules[i].c_str(), false); + if (module_file_spec) { + ModuleSpec module_spec(module_file_spec); + matching_modules.Clear(); + target->GetImages().FindModules(module_spec, matching_modules); + num_matches += matching_modules.ResolveSymbolContextForFilePath( + filename, 0, check_inlines, + eSymbolContextModule | eSymbolContextCompUnit, sc_list); + } + } + } else { + num_matches = target->GetImages().ResolveSymbolContextForFilePath( + filename, 0, check_inlines, + eSymbolContextModule | eSymbolContextCompUnit, sc_list); + } + + if (num_matches == 0) { + result.AppendErrorWithFormat("Could not find source file \"%s\".\n", + m_options.file_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (num_matches > 1) { + bool got_multiple = false; + FileSpec *test_cu_spec = nullptr; + + for (unsigned i = 0; i < num_matches; i++) { + SymbolContext sc; + sc_list.GetContextAtIndex(i, sc); + if (sc.comp_unit) { + if (test_cu_spec) { + if (test_cu_spec != static_cast<FileSpec *>(sc.comp_unit)) + got_multiple = true; + break; + } else + test_cu_spec = sc.comp_unit; + } + } + if (got_multiple) { + result.AppendErrorWithFormat( + "Multiple source files found matching: \"%s.\"\n", + m_options.file_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + + SymbolContext sc; + if (sc_list.GetContextAtIndex(0, sc)) { + if (sc.comp_unit) { + if (m_options.show_bp_locs) { + const bool show_inlines = true; + m_breakpoint_locations.Reset(*sc.comp_unit, 0, show_inlines); + SearchFilterForUnconstrainedSearches target_search_filter( + target->shared_from_this()); + target_search_filter.Search(m_breakpoint_locations); + } else + m_breakpoint_locations.Clear(); - if (num_matches > 1) - { - bool got_multiple = false; - FileSpec *test_cu_spec = nullptr; - - for (unsigned i = 0; i < num_matches; i++) - { - SymbolContext sc; - sc_list.GetContextAtIndex(i, sc); - if (sc.comp_unit) - { - if (test_cu_spec) - { - if (test_cu_spec != static_cast<FileSpec *> (sc.comp_unit)) - got_multiple = true; - break; - } - else - test_cu_spec = sc.comp_unit; - } - } - if (got_multiple) - { - result.AppendErrorWithFormat("Multiple source files found matching: \"%s.\"\n", - m_options.file_name.c_str()); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - - SymbolContext sc; - if (sc_list.GetContextAtIndex(0, sc)) - { - if (sc.comp_unit) - { - if (m_options.show_bp_locs) - { - const bool show_inlines = true; - m_breakpoint_locations.Reset (*sc.comp_unit, 0, show_inlines); - SearchFilterForUnconstrainedSearches target_search_filter (target->shared_from_this()); - target_search_filter.Search (m_breakpoint_locations); - } - else - m_breakpoint_locations.Clear(); - - if (m_options.num_lines == 0) - m_options.num_lines = 10; - - target->GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.comp_unit, - m_options.start_line, - 0, - m_options.num_lines, - "", - &result.GetOutputStream(), - GetBreakpointLocations ()); - - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendErrorWithFormat("No comp unit found for: \"%s.\"\n", - m_options.file_name.c_str()); - result.SetStatus (eReturnStatusFailed); - return false; - } - } + if (m_options.num_lines == 0) + m_options.num_lines = 10; + + target->GetSourceManager().DisplaySourceLinesWithLineNumbers( + sc.comp_unit, m_options.start_line, 0, m_options.num_lines, "", + &result.GetOutputStream(), GetBreakpointLocations()); + + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat("No comp unit found for: \"%s.\"\n", + m_options.file_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; } - return result.Succeeded(); + } } - - const SymbolContextList * - GetBreakpointLocations () - { - if (m_breakpoint_locations.GetFileLineMatches().GetSize() > 0) - return &m_breakpoint_locations.GetFileLineMatches(); - return nullptr; - } - - CommandOptions m_options; - FileLineResolver m_breakpoint_locations; - std::string m_reverse_name; + return result.Succeeded(); + } + + const SymbolContextList *GetBreakpointLocations() { + if (m_breakpoint_locations.GetFileLineMatches().GetSize() > 0) + return &m_breakpoint_locations.GetFileLineMatches(); + return nullptr; + } + + CommandOptions m_options; + FileLineResolver m_breakpoint_locations; + std::string m_reverse_name; }; -OptionDefinition -CommandObjectSourceList::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectSourceList::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "The number of source lines to display."}, {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Look up the source file in the given shared library."}, {LLDB_OPT_SET_ALL, false, "show-breakpoints", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show the line table locations from the debug information that indicate valid places to set source level breakpoints."}, @@ -1469,7 +1308,7 @@ CommandObjectSourceList::CommandOptions::g_option_table[] = {LLDB_OPT_SET_3, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Lookup the address and display the source information for the corresponding file and line."}, {LLDB_OPT_SET_4, false, "reverse", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Reverse the listing to look backwards from the last displayed block of source."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; #pragma mark CommandObjectMultiwordSource @@ -1477,14 +1316,17 @@ CommandObjectSourceList::CommandOptions::g_option_table[] = // CommandObjectMultiwordSource //------------------------------------------------------------------------- -CommandObjectMultiwordSource::CommandObjectMultiwordSource(CommandInterpreter &interpreter) - : CommandObjectMultiword( - interpreter, "source", - "Commands for examining source code described by debug information for the current target process.", - "source <subcommand> [<subcommand-options>]") -{ - LoadSubCommand ("info", CommandObjectSP (new CommandObjectSourceInfo (interpreter))); - LoadSubCommand ("list", CommandObjectSP (new CommandObjectSourceList (interpreter))); +CommandObjectMultiwordSource::CommandObjectMultiwordSource( + CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "source", "Commands for examining " + "source code described by " + "debug information for the " + "current target process.", + "source <subcommand> [<subcommand-options>]") { + LoadSubCommand("info", + CommandObjectSP(new CommandObjectSourceInfo(interpreter))); + LoadSubCommand("list", + CommandObjectSP(new CommandObjectSourceList(interpreter))); } CommandObjectMultiwordSource::~CommandObjectMultiwordSource() = default; diff --git a/lldb/source/Commands/CommandObjectSource.h b/lldb/source/Commands/CommandObjectSource.h index 7ed08cd..e81ac19 100644 --- a/lldb/source/Commands/CommandObjectSource.h +++ b/lldb/source/Commands/CommandObjectSource.h @@ -1,4 +1,5 @@ -//===-- CommandObjectSource.h.h -----------------------------------*- C++ -*-===// +//===-- CommandObjectSource.h.h -----------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -14,9 +15,9 @@ // C++ Includes // Other libraries and framework includes // Project includes +#include "lldb/Core/STLUtils.h" #include "lldb/Interpreter/CommandObject.h" #include "lldb/Interpreter/CommandObjectMultiword.h" -#include "lldb/Core/STLUtils.h" namespace lldb_private { @@ -24,13 +25,11 @@ namespace lldb_private { // CommandObjectMultiwordSource //------------------------------------------------------------------------- -class CommandObjectMultiwordSource : public CommandObjectMultiword -{ +class CommandObjectMultiwordSource : public CommandObjectMultiword { public: + CommandObjectMultiwordSource(CommandInterpreter &interpreter); - CommandObjectMultiwordSource (CommandInterpreter &interpreter); - - ~CommandObjectMultiwordSource() override; + ~CommandObjectMultiwordSource() override; }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectSyntax.cpp b/lldb/source/Commands/CommandObjectSyntax.cpp index c238bcc..6594906 100644 --- a/lldb/source/Commands/CommandObjectSyntax.cpp +++ b/lldb/source/Commands/CommandObjectSyntax.cpp @@ -14,10 +14,10 @@ #include "CommandObjectSyntax.h" #include "CommandObjectHelp.h" #include "lldb/Interpreter/Args.h" -#include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/CommandInterpreter.h" -#include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/CommandObjectMultiword.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Interpreter/Options.h" using namespace lldb; using namespace lldb_private; @@ -26,97 +26,80 @@ using namespace lldb_private; // CommandObjectSyntax //------------------------------------------------------------------------- -CommandObjectSyntax::CommandObjectSyntax (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "syntax", - "Shows the correct syntax for a given debugger command.", - "syntax <command>") -{ - CommandArgumentEntry arg; - CommandArgumentData command_arg; +CommandObjectSyntax::CommandObjectSyntax(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "syntax", + "Shows the correct syntax for a given debugger command.", + "syntax <command>") { + CommandArgumentEntry arg; + CommandArgumentData command_arg; - // Define the first (and only) variant of this arg. - command_arg.arg_type = eArgTypeCommandName; - command_arg.arg_repetition = eArgRepeatPlain; + // Define the first (and only) variant of this arg. + command_arg.arg_type = eArgTypeCommandName; + command_arg.arg_repetition = eArgRepeatPlain; - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (command_arg); + // There is only one variant this argument could be; put it into the argument + // entry. + arg.push_back(command_arg); - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); } CommandObjectSyntax::~CommandObjectSyntax() = default; -bool -CommandObjectSyntax::DoExecute (Args& command, CommandReturnObject &result) -{ - CommandObject::CommandMap::iterator pos; - CommandObject *cmd_obj; - const size_t argc = command.GetArgumentCount(); +bool CommandObjectSyntax::DoExecute(Args &command, + CommandReturnObject &result) { + CommandObject::CommandMap::iterator pos; + CommandObject *cmd_obj; + const size_t argc = command.GetArgumentCount(); - if (argc > 0) - { - cmd_obj = m_interpreter.GetCommandObject (command.GetArgumentAtIndex(0)); - bool all_okay = true; - for (size_t i = 1; i < argc; ++i) - { - std::string sub_command = command.GetArgumentAtIndex (i); - if (!cmd_obj->IsMultiwordObject()) - { - all_okay = false; - break; - } - else - { - cmd_obj = cmd_obj->GetSubcommandObject(sub_command.c_str()); - if (!cmd_obj) - { - all_okay = false; - break; - } - } - } - - if (all_okay && (cmd_obj != nullptr)) - { - Stream &output_strm = result.GetOutputStream(); - if (cmd_obj->GetOptions() != nullptr) - { - output_strm.Printf ("\nSyntax: %s\n", cmd_obj->GetSyntax()); - output_strm.Printf ("(Try 'help %s' for more information on command options syntax.)\n", - cmd_obj->GetCommandName()); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - output_strm.Printf ("\nSyntax: %s\n", cmd_obj->GetSyntax()); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - } - else - { - std::string cmd_string; - command.GetCommandString (cmd_string); - - StreamString error_msg_stream; - const bool generate_apropos = true; - const bool generate_type_lookup = false; - CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(&error_msg_stream, - cmd_string.c_str(), - nullptr, - nullptr, - generate_apropos, - generate_type_lookup); - result.AppendErrorWithFormat ("%s", error_msg_stream.GetData()); - result.SetStatus (eReturnStatusFailed); + if (argc > 0) { + cmd_obj = m_interpreter.GetCommandObject(command.GetArgumentAtIndex(0)); + bool all_okay = true; + for (size_t i = 1; i < argc; ++i) { + std::string sub_command = command.GetArgumentAtIndex(i); + if (!cmd_obj->IsMultiwordObject()) { + all_okay = false; + break; + } else { + cmd_obj = cmd_obj->GetSubcommandObject(sub_command.c_str()); + if (!cmd_obj) { + all_okay = false; + break; } + } } - else - { - result.AppendError ("Must call 'syntax' with a valid command."); - result.SetStatus (eReturnStatusFailed); + + if (all_okay && (cmd_obj != nullptr)) { + Stream &output_strm = result.GetOutputStream(); + if (cmd_obj->GetOptions() != nullptr) { + output_strm.Printf("\nSyntax: %s\n", cmd_obj->GetSyntax()); + output_strm.Printf( + "(Try 'help %s' for more information on command options syntax.)\n", + cmd_obj->GetCommandName()); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + output_strm.Printf("\nSyntax: %s\n", cmd_obj->GetSyntax()); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } + } else { + std::string cmd_string; + command.GetCommandString(cmd_string); + + StreamString error_msg_stream; + const bool generate_apropos = true; + const bool generate_type_lookup = false; + CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage( + &error_msg_stream, cmd_string.c_str(), nullptr, nullptr, + generate_apropos, generate_type_lookup); + result.AppendErrorWithFormat("%s", error_msg_stream.GetData()); + result.SetStatus(eReturnStatusFailed); } + } else { + result.AppendError("Must call 'syntax' with a valid command."); + result.SetStatus(eReturnStatusFailed); + } - return result.Succeeded(); + return result.Succeeded(); } diff --git a/lldb/source/Commands/CommandObjectSyntax.h b/lldb/source/Commands/CommandObjectSyntax.h index 1a3e4e0..b65e9b1 100644 --- a/lldb/source/Commands/CommandObjectSyntax.h +++ b/lldb/source/Commands/CommandObjectSyntax.h @@ -22,18 +22,14 @@ namespace lldb_private { // CommandObjectSyntax //------------------------------------------------------------------------- -class CommandObjectSyntax : public CommandObjectParsed -{ +class CommandObjectSyntax : public CommandObjectParsed { public: + CommandObjectSyntax(CommandInterpreter &interpreter); - CommandObjectSyntax (CommandInterpreter &interpreter); + ~CommandObjectSyntax() override; - ~CommandObjectSyntax() override; - protected: - bool - DoExecute(Args& command, - CommandReturnObject &result) override; + bool DoExecute(Args &command, CommandReturnObject &result) override; }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index dc67e50..d7e4dfa 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -15,7 +15,6 @@ // Other libraries and framework includes // Project includes -#include "lldb/Interpreter/Args.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/IOHandler.h" #include "lldb/Core/Module.h" @@ -27,19 +26,20 @@ #include "lldb/DataFormatters/ValueObjectPrinter.h" #include "lldb/Host/StringConvert.h" #include "lldb/Host/Symbols.h" +#include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/OptionGroupArchitecture.h" #include "lldb/Interpreter/OptionGroupBoolean.h" #include "lldb/Interpreter/OptionGroupFile.h" #include "lldb/Interpreter/OptionGroupFormat.h" -#include "lldb/Interpreter/OptionGroupVariable.h" #include "lldb/Interpreter/OptionGroupPlatform.h" +#include "lldb/Interpreter/OptionGroupString.h" #include "lldb/Interpreter/OptionGroupUInt64.h" #include "lldb/Interpreter/OptionGroupUUID.h" -#include "lldb/Interpreter/OptionGroupString.h" #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" +#include "lldb/Interpreter/OptionGroupVariable.h" +#include "lldb/Interpreter/Options.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/FuncUnwinders.h" #include "lldb/Symbol/LineTable.h" @@ -58,89 +58,78 @@ using namespace lldb; using namespace lldb_private; -static void -DumpTargetInfo (uint32_t target_idx, Target *target, const char *prefix_cstr, bool show_stopped_process_status, Stream &strm) -{ - const ArchSpec &target_arch = target->GetArchitecture(); - - Module *exe_module = target->GetExecutableModulePointer(); - char exe_path[PATH_MAX]; - bool exe_valid = false; - if (exe_module) - exe_valid = exe_module->GetFileSpec().GetPath (exe_path, sizeof(exe_path)); - - if (!exe_valid) - ::strcpy (exe_path, "<none>"); - - strm.Printf ("%starget #%u: %s", prefix_cstr ? prefix_cstr : "", target_idx, exe_path); - - uint32_t properties = 0; - if (target_arch.IsValid()) - { - strm.Printf ("%sarch=", properties++ > 0 ? ", " : " ( "); - target_arch.DumpTriple (strm); - properties++; - } - PlatformSP platform_sp (target->GetPlatform()); - if (platform_sp) - strm.Printf ("%splatform=%s", properties++ > 0 ? ", " : " ( ", platform_sp->GetName().GetCString()); - - ProcessSP process_sp (target->GetProcessSP()); - bool show_process_status = false; - if (process_sp) - { - lldb::pid_t pid = process_sp->GetID(); - StateType state = process_sp->GetState(); - if (show_stopped_process_status) - show_process_status = StateIsStoppedState(state, true); - const char *state_cstr = StateAsCString (state); - if (pid != LLDB_INVALID_PROCESS_ID) - strm.Printf ("%spid=%" PRIu64, properties++ > 0 ? ", " : " ( ", pid); - strm.Printf ("%sstate=%s", properties++ > 0 ? ", " : " ( ", state_cstr); - } - if (properties > 0) - strm.PutCString (" )\n"); - else - strm.EOL(); - if (show_process_status) - { - const bool only_threads_with_stop_reason = true; - const uint32_t start_frame = 0; - const uint32_t num_frames = 1; - const uint32_t num_frames_with_source = 1; - process_sp->GetStatus (strm); - process_sp->GetThreadStatus (strm, - only_threads_with_stop_reason, - start_frame, - num_frames, - num_frames_with_source); - - } +static void DumpTargetInfo(uint32_t target_idx, Target *target, + const char *prefix_cstr, + bool show_stopped_process_status, Stream &strm) { + const ArchSpec &target_arch = target->GetArchitecture(); + + Module *exe_module = target->GetExecutableModulePointer(); + char exe_path[PATH_MAX]; + bool exe_valid = false; + if (exe_module) + exe_valid = exe_module->GetFileSpec().GetPath(exe_path, sizeof(exe_path)); + + if (!exe_valid) + ::strcpy(exe_path, "<none>"); + + strm.Printf("%starget #%u: %s", prefix_cstr ? prefix_cstr : "", target_idx, + exe_path); + + uint32_t properties = 0; + if (target_arch.IsValid()) { + strm.Printf("%sarch=", properties++ > 0 ? ", " : " ( "); + target_arch.DumpTriple(strm); + properties++; + } + PlatformSP platform_sp(target->GetPlatform()); + if (platform_sp) + strm.Printf("%splatform=%s", properties++ > 0 ? ", " : " ( ", + platform_sp->GetName().GetCString()); + + ProcessSP process_sp(target->GetProcessSP()); + bool show_process_status = false; + if (process_sp) { + lldb::pid_t pid = process_sp->GetID(); + StateType state = process_sp->GetState(); + if (show_stopped_process_status) + show_process_status = StateIsStoppedState(state, true); + const char *state_cstr = StateAsCString(state); + if (pid != LLDB_INVALID_PROCESS_ID) + strm.Printf("%spid=%" PRIu64, properties++ > 0 ? ", " : " ( ", pid); + strm.Printf("%sstate=%s", properties++ > 0 ? ", " : " ( ", state_cstr); + } + if (properties > 0) + strm.PutCString(" )\n"); + else + strm.EOL(); + if (show_process_status) { + const bool only_threads_with_stop_reason = true; + const uint32_t start_frame = 0; + const uint32_t num_frames = 1; + const uint32_t num_frames_with_source = 1; + process_sp->GetStatus(strm); + process_sp->GetThreadStatus(strm, only_threads_with_stop_reason, + start_frame, num_frames, + num_frames_with_source); + } } -static uint32_t -DumpTargetList (TargetList &target_list, bool show_stopped_process_status, Stream &strm) -{ - const uint32_t num_targets = target_list.GetNumTargets(); - if (num_targets) - { - TargetSP selected_target_sp (target_list.GetSelectedTarget()); - strm.PutCString ("Current targets:\n"); - for (uint32_t i = 0; i < num_targets; ++i) - { - TargetSP target_sp (target_list.GetTargetAtIndex (i)); - if (target_sp) - { - bool is_selected = target_sp.get() == selected_target_sp.get(); - DumpTargetInfo (i, - target_sp.get(), - is_selected ? "* " : " ", - show_stopped_process_status, - strm); - } - } +static uint32_t DumpTargetList(TargetList &target_list, + bool show_stopped_process_status, Stream &strm) { + const uint32_t num_targets = target_list.GetNumTargets(); + if (num_targets) { + TargetSP selected_target_sp(target_list.GetSelectedTarget()); + strm.PutCString("Current targets:\n"); + for (uint32_t i = 0; i < num_targets; ++i) { + TargetSP target_sp(target_list.GetTargetAtIndex(i)); + if (target_sp) { + bool is_selected = target_sp.get() == selected_target_sp.get(); + DumpTargetInfo(i, target_sp.get(), is_selected ? "* " : " ", + show_stopped_process_status, strm); + } } - return num_targets; + } + return num_targets; } #pragma mark CommandObjectTargetCreate @@ -149,312 +138,283 @@ DumpTargetList (TargetList &target_list, bool show_stopped_process_status, Strea // "target create" //------------------------------------------------------------------------- -class CommandObjectTargetCreate : public CommandObjectParsed -{ +class CommandObjectTargetCreate : public CommandObjectParsed { public: - CommandObjectTargetCreate(CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "target create", - "Create a target using the argument as the main executable.", - nullptr), - m_option_group (), - m_arch_option (), - m_core_file (LLDB_OPT_SET_1, false, "core", 'c', 0, eArgTypeFilename, "Fullpath to a core file to use for this target."), - m_platform_path (LLDB_OPT_SET_1, false, "platform-path", 'P', 0, eArgTypePath, "Path to the remote file to use for this target."), - m_symbol_file (LLDB_OPT_SET_1, false, "symfile", 's', 0, eArgTypeFilename, "Fullpath to a stand alone debug symbols file for when debug symbols are not in the executable."), - m_remote_file (LLDB_OPT_SET_1, false, "remote-file", 'r', 0, eArgTypeFilename, "Fullpath to the file on the remote host if debugging remotely."), - m_add_dependents (LLDB_OPT_SET_1, false, "no-dependents", 'd', "Don't load dependent files when creating the target, just add the specified executable.", true, true) - { - CommandArgumentEntry arg; - CommandArgumentData file_arg; - - // Define the first (and only) variant of this arg. - file_arg.arg_type = eArgTypeFilename; - file_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (file_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - - m_option_group.Append (&m_arch_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Append (&m_core_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Append (&m_platform_path, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Append (&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Append (&m_remote_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Append (&m_add_dependents, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Finalize(); - } - - ~CommandObjectTargetCreate() override = default; - - Options * - GetOptions () override - { - return &m_option_group; - } + CommandObjectTargetCreate(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "target create", + "Create a target using the argument as the main executable.", + nullptr), + m_option_group(), m_arch_option(), + m_core_file(LLDB_OPT_SET_1, false, "core", 'c', 0, eArgTypeFilename, + "Fullpath to a core file to use for this target."), + m_platform_path(LLDB_OPT_SET_1, false, "platform-path", 'P', 0, + eArgTypePath, + "Path to the remote file to use for this target."), + m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0, + eArgTypeFilename, "Fullpath to a stand alone debug " + "symbols file for when debug symbols " + "are not in the executable."), + m_remote_file( + LLDB_OPT_SET_1, false, "remote-file", 'r', 0, eArgTypeFilename, + "Fullpath to the file on the remote host if debugging remotely."), + m_add_dependents(LLDB_OPT_SET_1, false, "no-dependents", 'd', + "Don't load dependent files when creating the target, " + "just add the specified executable.", + true, true) { + CommandArgumentEntry arg; + CommandArgumentData file_arg; + + // Define the first (and only) variant of this arg. + file_arg.arg_type = eArgTypeFilename; + file_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(file_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + + m_option_group.Append(&m_arch_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append(&m_core_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append(&m_platform_path, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append(&m_remote_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append(&m_add_dependents, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Finalize(); + } + + ~CommandObjectTargetCreate() override = default; + + Options *GetOptions() override { return &m_option_group; } + + int HandleArgumentCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, int max_return_elements, + bool &word_complete, + StringList &matches) override { + std::string completion_str(input.GetArgumentAtIndex(cursor_index)); + completion_str.erase(cursor_char_position); + + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, + completion_str.c_str(), match_start_point, max_return_elements, nullptr, + word_complete, matches); + return matches.GetSize(); + } - int - HandleArgumentCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - OptionElementVector &opt_element_vector, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) override - { - std::string completion_str (input.GetArgumentAtIndex(cursor_index)); - completion_str.erase (cursor_char_position); - - CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(), - CommandCompletions::eDiskFileCompletion, - completion_str.c_str(), - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - return matches.GetSize(); +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + const size_t argc = command.GetArgumentCount(); + FileSpec core_file(m_core_file.GetOptionValue().GetCurrentValue()); + FileSpec remote_file(m_remote_file.GetOptionValue().GetCurrentValue()); + + if (core_file) { + if (!core_file.Exists()) { + result.AppendErrorWithFormat("core file '%s' doesn't exist", + core_file.GetPath().c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + if (!core_file.Readable()) { + result.AppendErrorWithFormat("core file '%s' is not readable", + core_file.GetPath().c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } } -protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - const size_t argc = command.GetArgumentCount(); - FileSpec core_file (m_core_file.GetOptionValue().GetCurrentValue()); - FileSpec remote_file (m_remote_file.GetOptionValue().GetCurrentValue()); - - if (core_file) - { - if (!core_file.Exists()) - { - result.AppendErrorWithFormat("core file '%s' doesn't exist", core_file.GetPath().c_str()); - result.SetStatus (eReturnStatusFailed); + if (argc == 1 || core_file || remote_file) { + FileSpec symfile(m_symbol_file.GetOptionValue().GetCurrentValue()); + if (symfile) { + if (symfile.Exists()) { + if (!symfile.Readable()) { + 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); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + + const char *file_path = command.GetArgumentAtIndex(0); + Timer scoped_timer(LLVM_PRETTY_FUNCTION, "(lldb) target create '%s'", + file_path); + FileSpec file_spec; + + if (file_path) + file_spec.SetFile(file_path, true); + + bool must_set_platform_path = false; + + Debugger &debugger = m_interpreter.GetDebugger(); + + TargetSP target_sp; + const char *arch_cstr = m_arch_option.GetArchitectureName(); + const bool get_dependent_files = + m_add_dependents.GetOptionValue().GetCurrentValue(); + Error error(debugger.GetTargetList().CreateTarget( + debugger, file_path, arch_cstr, get_dependent_files, nullptr, + target_sp)); + + if (target_sp) { + // Only get the platform after we create the target because we might + // have + // switched platforms depending on what the arguments were to + // CreateTarget() + // we can't rely on the selected platform. + + PlatformSP platform_sp = target_sp->GetPlatform(); + + if (remote_file) { + if (platform_sp) { + // I have a remote file.. two possible cases + if (file_spec && file_spec.Exists()) { + // if the remote file does not exist, push it there + if (!platform_sp->GetFileExists(remote_file)) { + Error err = platform_sp->PutFile(file_spec, remote_file); + if (err.Fail()) { + result.AppendError(err.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + } else { + // there is no local file and we need one + // in order to make the remote ---> local transfer we need a + // platform + // TODO: if the user has passed in a --platform argument, use it + // to fetch the right platform + if (!platform_sp) { + result.AppendError( + "unable to perform remote debugging without a platform"); + result.SetStatus(eReturnStatusFailed); return false; - - } - if (!core_file.Readable()) - { - result.AppendErrorWithFormat("core file '%s' is not readable", core_file.GetPath().c_str()); - result.SetStatus (eReturnStatusFailed); + } + if (file_path) { + // copy the remote file to the local file + Error err = platform_sp->GetFile(remote_file, file_spec); + if (err.Fail()) { + result.AppendError(err.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + // make up a local file + result.AppendError("remote --> local transfer without local " + "path is not implemented yet"); + result.SetStatus(eReturnStatusFailed); return false; + } } + } else { + result.AppendError("no platform found for target"); + result.SetStatus(eReturnStatusFailed); + return false; + } } - if (argc == 1 || core_file || remote_file) - { - FileSpec symfile (m_symbol_file.GetOptionValue().GetCurrentValue()); + if (symfile || remote_file) { + ModuleSP module_sp(target_sp->GetExecutableModule()); + if (module_sp) { if (symfile) - { - if (symfile.Exists()) - { - if (!symfile.Readable()) - { - 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); - result.SetStatus (eReturnStatusFailed); - return false; - } + module_sp->SetSymbolFileFileSpec(symfile); + if (remote_file) { + std::string remote_path = remote_file.GetPath(); + target_sp->SetArg0(remote_path.c_str()); + module_sp->SetPlatformFileSpec(remote_file); } + } + } - const char *file_path = command.GetArgumentAtIndex(0); - Timer scoped_timer(LLVM_PRETTY_FUNCTION, "(lldb) target create '%s'", file_path); - FileSpec file_spec; - - if (file_path) - file_spec.SetFile (file_path, true); - - bool must_set_platform_path = false; - - Debugger &debugger = m_interpreter.GetDebugger(); - - TargetSP target_sp; - const char *arch_cstr = m_arch_option.GetArchitectureName(); - const bool get_dependent_files = m_add_dependents.GetOptionValue().GetCurrentValue(); - Error error(debugger.GetTargetList().CreateTarget(debugger, - file_path, - arch_cstr, - get_dependent_files, - nullptr, - target_sp)); - - if (target_sp) - { - // Only get the platform after we create the target because we might have - // switched platforms depending on what the arguments were to CreateTarget() - // we can't rely on the selected platform. - - PlatformSP platform_sp = target_sp->GetPlatform(); - - if (remote_file) - { - if (platform_sp) - { - // I have a remote file.. two possible cases - if (file_spec && file_spec.Exists()) - { - // if the remote file does not exist, push it there - if (!platform_sp->GetFileExists (remote_file)) - { - Error err = platform_sp->PutFile(file_spec, remote_file); - if (err.Fail()) - { - result.AppendError(err.AsCString()); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - } - else - { - // there is no local file and we need one - // in order to make the remote ---> local transfer we need a platform - // TODO: if the user has passed in a --platform argument, use it to fetch the right platform - if (!platform_sp) - { - result.AppendError("unable to perform remote debugging without a platform"); - result.SetStatus (eReturnStatusFailed); - return false; - } - if (file_path) - { - // copy the remote file to the local file - Error err = platform_sp->GetFile(remote_file, file_spec); - if (err.Fail()) - { - result.AppendError(err.AsCString()); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - else - { - // make up a local file - result.AppendError("remote --> local transfer without local path is not implemented yet"); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - } - else - { - result.AppendError("no platform found for target"); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - - if (symfile || remote_file) - { - ModuleSP module_sp (target_sp->GetExecutableModule()); - if (module_sp) - { - if (symfile) - module_sp->SetSymbolFileFileSpec(symfile); - if (remote_file) - { - std::string remote_path = remote_file.GetPath(); - target_sp->SetArg0(remote_path.c_str()); - module_sp->SetPlatformFileSpec(remote_file); - } - } - } - - debugger.GetTargetList().SetSelectedTarget(target_sp.get()); - if (must_set_platform_path) - { - ModuleSpec main_module_spec(file_spec); - ModuleSP module_sp = target_sp->GetSharedModule(main_module_spec); - 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 (core_file.Exists()) - { - if (!core_file.Readable()) - { - 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->GetExecutableSearchPaths ().Append (core_file_dir); - - ProcessSP process_sp(target_sp->CreateProcess(m_interpreter.GetDebugger().GetListener(), nullptr, &core_file)); - - 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); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendErrorWithFormat ("Core file '%s' does not exist\n", core_path); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendMessageWithFormat ("Current executable set to '%s' (%s).\n", file_path, target_sp->GetArchitecture().GetArchitectureName()); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } + debugger.GetTargetList().SetSelectedTarget(target_sp.get()); + if (must_set_platform_path) { + ModuleSpec main_module_spec(file_spec); + ModuleSP module_sp = target_sp->GetSharedModule(main_module_spec); + 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 (core_file.Exists()) { + if (!core_file.Readable()) { + result.AppendMessageWithFormat( + "Core file '%s' is not readable.\n", core_path); + result.SetStatus(eReturnStatusFailed); + return false; } - else - { - result.AppendError(error.AsCString()); - result.SetStatus (eReturnStatusFailed); + FileSpec core_file_dir; + core_file_dir.GetDirectory() = core_file.GetDirectory(); + target_sp->GetExecutableSearchPaths().Append(core_file_dir); + + ProcessSP process_sp(target_sp->CreateProcess( + m_interpreter.GetDebugger().GetListener(), nullptr, + &core_file)); + + 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); + result.SetStatus(eReturnStatusFailed); } + } else { + result.AppendErrorWithFormat("Core file '%s' does not exist\n", + core_path); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendMessageWithFormat( + "Current executable set to '%s' (%s).\n", file_path, + target_sp->GetArchitecture().GetArchitectureName()); + result.SetStatus(eReturnStatusSuccessFinishNoResult); } - else - { - result.AppendErrorWithFormat("'%s' takes exactly one executable path argument, or use the --core option.\n", m_cmd_name.c_str()); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + } else { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendErrorWithFormat("'%s' takes exactly one executable path " + "argument, or use the --core option.\n", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } private: - OptionGroupOptions m_option_group; - OptionGroupArchitecture m_arch_option; - OptionGroupFile m_core_file; - OptionGroupFile m_platform_path; - OptionGroupFile m_symbol_file; - OptionGroupFile m_remote_file; - OptionGroupBoolean m_add_dependents; + OptionGroupOptions m_option_group; + OptionGroupArchitecture m_arch_option; + OptionGroupFile m_core_file; + OptionGroupFile m_platform_path; + OptionGroupFile m_symbol_file; + OptionGroupFile m_remote_file; + OptionGroupBoolean m_add_dependents; }; #pragma mark CommandObjectTargetList @@ -463,41 +423,33 @@ private: // "target list" //---------------------------------------------------------------------- -class CommandObjectTargetList : public CommandObjectParsed -{ +class CommandObjectTargetList : public CommandObjectParsed { public: - CommandObjectTargetList (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "target list", - "List all current targets in the current debug session.", - nullptr) - { - } + CommandObjectTargetList(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "target list", + "List all current targets in the current debug session.", nullptr) { + } - ~CommandObjectTargetList() override = default; + ~CommandObjectTargetList() override = default; protected: - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - if (args.GetArgumentCount() == 0) - { - Stream &strm = result.GetOutputStream(); - - bool show_stopped_process_status = false; - if (DumpTargetList (m_interpreter.GetDebugger().GetTargetList(), show_stopped_process_status, strm) == 0) - { - strm.PutCString ("No targets.\n"); - } - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendError ("the 'target list' command takes no arguments\n"); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + bool DoExecute(Args &args, CommandReturnObject &result) override { + if (args.GetArgumentCount() == 0) { + Stream &strm = result.GetOutputStream(); + + bool show_stopped_process_status = false; + if (DumpTargetList(m_interpreter.GetDebugger().GetTargetList(), + show_stopped_process_status, strm) == 0) { + strm.PutCString("No targets.\n"); + } + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendError("the 'target list' command takes no arguments\n"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } }; #pragma mark CommandObjectTargetSelect @@ -506,78 +458,63 @@ protected: // "target select" //---------------------------------------------------------------------- -class CommandObjectTargetSelect : public CommandObjectParsed -{ +class CommandObjectTargetSelect : public CommandObjectParsed { public: - CommandObjectTargetSelect (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "target select", - "Select a target as the current target by target index.", - nullptr) - { - } + CommandObjectTargetSelect(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "target select", + "Select a target as the current target by target index.", nullptr) { + } - ~CommandObjectTargetSelect() override = default; + ~CommandObjectTargetSelect() override = default; 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) - { - TargetList &target_list = m_interpreter.GetDebugger().GetTargetList(); - const uint32_t num_targets = target_list.GetNumTargets(); - if (target_idx < num_targets) - { - TargetSP target_sp (target_list.GetTargetAtIndex (target_idx)); - if (target_sp) - { - Stream &strm = result.GetOutputStream(); - target_list.SetSelectedTarget (target_sp.get()); - bool show_stopped_process_status = false; - DumpTargetList (target_list, show_stopped_process_status, strm); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendErrorWithFormat ("target #%u is NULL in target list\n", target_idx); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - if (num_targets > 0) - { - result.AppendErrorWithFormat ("index %u is out of range, valid target indexes are 0 - %u\n", - target_idx, - num_targets - 1); - } - else - { - result.AppendErrorWithFormat ("index %u is out of range since there are no active targets\n", - target_idx); - } - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendErrorWithFormat("invalid index string value '%s'\n", target_idx_arg); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendError ("'target select' takes a single argument: a target index\n"); - result.SetStatus (eReturnStatusFailed); + 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) { + TargetList &target_list = m_interpreter.GetDebugger().GetTargetList(); + const uint32_t num_targets = target_list.GetNumTargets(); + if (target_idx < num_targets) { + TargetSP target_sp(target_list.GetTargetAtIndex(target_idx)); + if (target_sp) { + Stream &strm = result.GetOutputStream(); + target_list.SetSelectedTarget(target_sp.get()); + bool show_stopped_process_status = false; + DumpTargetList(target_list, show_stopped_process_status, strm); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat("target #%u is NULL in target list\n", + target_idx); + result.SetStatus(eReturnStatusFailed); + } + } else { + if (num_targets > 0) { + result.AppendErrorWithFormat( + "index %u is out of range, valid target indexes are 0 - %u\n", + target_idx, num_targets - 1); + } else { + result.AppendErrorWithFormat( + "index %u is out of range since there are no active targets\n", + target_idx); + } + result.SetStatus(eReturnStatusFailed); } - return result.Succeeded(); + } else { + result.AppendErrorWithFormat("invalid index string value '%s'\n", + target_idx_arg); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendError( + "'target select' takes a single argument: a target index\n"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } }; #pragma mark CommandObjectTargetSelect @@ -586,130 +523,114 @@ protected: // "target delete" //---------------------------------------------------------------------- -class CommandObjectTargetDelete : public CommandObjectParsed -{ +class CommandObjectTargetDelete : public CommandObjectParsed { public: - CommandObjectTargetDelete (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "target delete", + CommandObjectTargetDelete(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "target delete", "Delete one or more targets by target index.", nullptr), - m_option_group(), - m_all_option(LLDB_OPT_SET_1, false, "all", 'a', "Delete all targets.", false, true), + m_option_group(), m_all_option(LLDB_OPT_SET_1, false, "all", 'a', + "Delete all targets.", false, true), m_cleanup_option( - LLDB_OPT_SET_1, - false, - "clean", 'c', - "Perform extra cleanup to minimize memory consumption after deleting the target. " - "By default, LLDB will keep in memory any modules previously loaded by the target as well " - "as all of its debug info. Specifying --clean will unload all of these shared modules and " + LLDB_OPT_SET_1, false, "clean", 'c', + "Perform extra cleanup to minimize memory consumption after " + "deleting the target. " + "By default, LLDB will keep in memory any modules previously " + "loaded by the target as well " + "as all of its debug info. Specifying --clean will unload all of " + "these shared modules and " "cause them to be reparsed again the next time the target is run", - false, true) - { - m_option_group.Append(&m_all_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Append(&m_cleanup_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Finalize(); - } + false, true) { + m_option_group.Append(&m_all_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append(&m_cleanup_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Finalize(); + } - ~CommandObjectTargetDelete() override = default; + ~CommandObjectTargetDelete() override = default; - Options * - GetOptions () override - { - return &m_option_group; - } + Options *GetOptions() override { return &m_option_group; } protected: - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - const size_t argc = args.GetArgumentCount(); - std::vector<TargetSP> delete_target_list; - TargetList &target_list = m_interpreter.GetDebugger().GetTargetList(); - TargetSP target_sp; - - if (m_all_option.GetOptionValue()) - { - for (int i = 0; i < target_list.GetNumTargets(); ++i) - delete_target_list.push_back(target_list.GetTargetAtIndex(i)); + bool DoExecute(Args &args, CommandReturnObject &result) override { + const size_t argc = args.GetArgumentCount(); + std::vector<TargetSP> delete_target_list; + TargetList &target_list = m_interpreter.GetDebugger().GetTargetList(); + TargetSP target_sp; + + if (m_all_option.GetOptionValue()) { + for (int i = 0; i < target_list.GetNumTargets(); ++i) + delete_target_list.push_back(target_list.GetTargetAtIndex(i)); + } else if (argc > 0) { + const uint32_t num_targets = target_list.GetNumTargets(); + // Bail out if don't have any targets. + if (num_targets == 0) { + result.AppendError("no targets to delete"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + for (uint32_t arg_idx = 0; arg_idx < argc; ++arg_idx) { + const char *target_idx_arg = args.GetArgumentAtIndex(arg_idx); + bool success = false; + uint32_t target_idx = + StringConvert::ToUInt32(target_idx_arg, UINT32_MAX, 0, &success); + if (!success) { + result.AppendErrorWithFormat("invalid target index '%s'\n", + target_idx_arg); + result.SetStatus(eReturnStatusFailed); + return false; } - else if (argc > 0) - { - const uint32_t num_targets = target_list.GetNumTargets(); - // Bail out if don't have any targets. - if (num_targets == 0) { - result.AppendError("no targets to delete"); - result.SetStatus(eReturnStatusFailed); - return false; - } - - for (uint32_t arg_idx = 0; arg_idx < argc; ++arg_idx) - { - const char *target_idx_arg = args.GetArgumentAtIndex(arg_idx); - bool success = false; - uint32_t target_idx = StringConvert::ToUInt32 (target_idx_arg, UINT32_MAX, 0, &success); - if (!success) - { - result.AppendErrorWithFormat("invalid target index '%s'\n", target_idx_arg); - result.SetStatus (eReturnStatusFailed); - return false; - } - if (target_idx < num_targets) - { - target_sp = target_list.GetTargetAtIndex (target_idx); - if (target_sp) - { - delete_target_list.push_back (target_sp); - continue; - } - } - if (num_targets > 1) - result.AppendErrorWithFormat ("target index %u is out of range, valid target indexes are 0 - %u\n", - target_idx, - num_targets - 1); - else - result.AppendErrorWithFormat("target index %u is out of range, the only valid index is 0\n", - target_idx); - - result.SetStatus (eReturnStatusFailed); - return false; - } + if (target_idx < num_targets) { + target_sp = target_list.GetTargetAtIndex(target_idx); + if (target_sp) { + delete_target_list.push_back(target_sp); + continue; + } } + if (num_targets > 1) + result.AppendErrorWithFormat("target index %u is out of range, valid " + "target indexes are 0 - %u\n", + target_idx, num_targets - 1); else - { - target_sp = target_list.GetSelectedTarget(); - if (!target_sp) - { - result.AppendErrorWithFormat("no target is currently selected\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } - delete_target_list.push_back (target_sp); - } + result.AppendErrorWithFormat( + "target index %u is out of range, the only valid index is 0\n", + target_idx); - const size_t num_targets_to_delete = delete_target_list.size(); - for (size_t idx = 0; idx < num_targets_to_delete; ++idx) - { - target_sp = delete_target_list[idx]; - target_list.DeleteTarget(target_sp); - target_sp->Destroy(); - } - // If "--clean" was specified, prune any orphaned shared modules from - // the global shared module list - if (m_cleanup_option.GetOptionValue ()) - { - const bool mandatory = true; - ModuleList::RemoveOrphanSharedModules(mandatory); - } - result.GetOutputStream().Printf("%u targets deleted.\n", (uint32_t)num_targets_to_delete); - result.SetStatus(eReturnStatusSuccessFinishResult); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + target_sp = target_list.GetSelectedTarget(); + if (!target_sp) { + result.AppendErrorWithFormat("no target is currently selected\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } + delete_target_list.push_back(target_sp); + } - return true; + const size_t num_targets_to_delete = delete_target_list.size(); + for (size_t idx = 0; idx < num_targets_to_delete; ++idx) { + target_sp = delete_target_list[idx]; + target_list.DeleteTarget(target_sp); + target_sp->Destroy(); } + // If "--clean" was specified, prune any orphaned shared modules from + // the global shared module list + if (m_cleanup_option.GetOptionValue()) { + const bool mandatory = true; + ModuleList::RemoveOrphanSharedModules(mandatory); + } + result.GetOutputStream().Printf("%u targets deleted.\n", + (uint32_t)num_targets_to_delete); + result.SetStatus(eReturnStatusSuccessFinishResult); + + return true; + } - OptionGroupOptions m_option_group; - OptionGroupBoolean m_all_option; - OptionGroupBoolean m_cleanup_option; + OptionGroupOptions m_option_group; + OptionGroupBoolean m_all_option; + OptionGroupBoolean m_cleanup_option; }; #pragma mark CommandObjectTargetVariable @@ -718,1308 +639,1138 @@ protected: // "target variable" //---------------------------------------------------------------------- -class CommandObjectTargetVariable : public CommandObjectParsed -{ - static const uint32_t SHORT_OPTION_FILE = 0x66696c65; // 'file' - static const uint32_t SHORT_OPTION_SHLB = 0x73686c62; // 'shlb' +class CommandObjectTargetVariable : public CommandObjectParsed { + static const uint32_t SHORT_OPTION_FILE = 0x66696c65; // 'file' + static const uint32_t SHORT_OPTION_SHLB = 0x73686c62; // 'shlb' public: - CommandObjectTargetVariable(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "target variable", - "Read global variables for the current target, before or while running a process.", - nullptr, eCommandRequiresTarget), - m_option_group(), - m_option_variable(false), // Don't include frame options - m_option_format(eFormatDefault), - m_option_compile_units(LLDB_OPT_SET_1, false, "file", SHORT_OPTION_FILE, 0, eArgTypeFilename, - "A basename or fullpath to a file that contains global variables. This option can be " - "specified multiple times."), - m_option_shared_libraries(LLDB_OPT_SET_1, false, "shlib", SHORT_OPTION_SHLB, 0, eArgTypeFilename, - "A basename or fullpath to a shared library to use in the search for global " - "variables. This option can be specified multiple times."), - m_varobj_options() - { - CommandArgumentEntry arg; - CommandArgumentData var_name_arg; - - // Define the first (and only) variant of this arg. - var_name_arg.arg_type = eArgTypeVarName; - var_name_arg.arg_repetition = eArgRepeatPlus; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (var_name_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - - m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Append (&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Append (&m_option_format, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_1); - m_option_group.Append (&m_option_compile_units, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Append (&m_option_shared_libraries, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Finalize(); + CommandObjectTargetVariable(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "target variable", + "Read global variables for the current target, " + "before or while running a process.", + nullptr, eCommandRequiresTarget), + m_option_group(), + m_option_variable(false), // Don't include frame options + m_option_format(eFormatDefault), + m_option_compile_units(LLDB_OPT_SET_1, false, "file", SHORT_OPTION_FILE, + 0, eArgTypeFilename, + "A basename or fullpath to a file that contains " + "global variables. This option can be " + "specified multiple times."), + m_option_shared_libraries( + LLDB_OPT_SET_1, false, "shlib", SHORT_OPTION_SHLB, 0, + eArgTypeFilename, + "A basename or fullpath to a shared library to use in the search " + "for global " + "variables. This option can be specified multiple times."), + m_varobj_options() { + CommandArgumentEntry arg; + CommandArgumentData var_name_arg; + + // Define the first (and only) variant of this arg. + var_name_arg.arg_type = eArgTypeVarName; + var_name_arg.arg_repetition = eArgRepeatPlus; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(var_name_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + + m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append(&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append(&m_option_format, + OptionGroupFormat::OPTION_GROUP_FORMAT | + OptionGroupFormat::OPTION_GROUP_GDB_FMT, + LLDB_OPT_SET_1); + m_option_group.Append(&m_option_compile_units, LLDB_OPT_SET_ALL, + LLDB_OPT_SET_1); + m_option_group.Append(&m_option_shared_libraries, LLDB_OPT_SET_ALL, + LLDB_OPT_SET_1); + m_option_group.Finalize(); + } + + ~CommandObjectTargetVariable() override = default; + + void DumpValueObject(Stream &s, VariableSP &var_sp, ValueObjectSP &valobj_sp, + const char *root_name) { + DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions()); + + if (!valobj_sp->GetTargetSP()->GetDisplayRuntimeSupportValues() && + valobj_sp->IsRuntimeSupportValue()) + return; + + switch (var_sp->GetScope()) { + case eValueTypeVariableGlobal: + if (m_option_variable.show_scope) + s.PutCString("GLOBAL: "); + break; + + case eValueTypeVariableStatic: + if (m_option_variable.show_scope) + s.PutCString("STATIC: "); + break; + + case eValueTypeVariableArgument: + if (m_option_variable.show_scope) + s.PutCString(" ARG: "); + break; + + case eValueTypeVariableLocal: + if (m_option_variable.show_scope) + s.PutCString(" LOCAL: "); + break; + + case eValueTypeVariableThreadLocal: + if (m_option_variable.show_scope) + s.PutCString("THREAD: "); + break; + + default: + break; } - ~CommandObjectTargetVariable() override = default; - - void - DumpValueObject (Stream &s, VariableSP &var_sp, ValueObjectSP &valobj_sp, const char *root_name) - { - DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions()); + if (m_option_variable.show_decl) { + bool show_fullpaths = false; + bool show_module = true; + if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module)) + s.PutCString(": "); + } - if (!valobj_sp->GetTargetSP()->GetDisplayRuntimeSupportValues() && - valobj_sp->IsRuntimeSupportValue()) - return; - - switch (var_sp->GetScope()) - { - case eValueTypeVariableGlobal: - if (m_option_variable.show_scope) - s.PutCString("GLOBAL: "); - break; + const Format format = m_option_format.GetFormat(); + if (format != eFormatDefault) + options.SetFormat(format); - case eValueTypeVariableStatic: - if (m_option_variable.show_scope) - s.PutCString("STATIC: "); - break; + options.SetRootValueObjectName(root_name); - case eValueTypeVariableArgument: - if (m_option_variable.show_scope) - s.PutCString(" ARG: "); - break; + valobj_sp->Dump(s, options); + } - case eValueTypeVariableLocal: - if (m_option_variable.show_scope) - s.PutCString(" LOCAL: "); - break; + static size_t GetVariableCallback(void *baton, const char *name, + VariableList &variable_list) { + Target *target = static_cast<Target *>(baton); + if (target) { + return target->GetImages().FindGlobalVariables(ConstString(name), true, + UINT32_MAX, variable_list); + } + return 0; + } - case eValueTypeVariableThreadLocal: - if (m_option_variable.show_scope) - s.PutCString("THREAD: "); - break; + Options *GetOptions() override { return &m_option_group; } - default: - break; +protected: + void DumpGlobalVariableList(const ExecutionContext &exe_ctx, + const SymbolContext &sc, + const VariableList &variable_list, Stream &s) { + size_t count = variable_list.GetSize(); + if (count > 0) { + if (sc.module_sp) { + if (sc.comp_unit) { + s.Printf("Global variables for %s in %s:\n", + sc.comp_unit->GetPath().c_str(), + sc.module_sp->GetFileSpec().GetPath().c_str()); + } else { + s.Printf("Global variables for %s\n", + sc.module_sp->GetFileSpec().GetPath().c_str()); } - - if (m_option_variable.show_decl) - { - bool show_fullpaths = false; - bool show_module = true; - if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module)) - s.PutCString (": "); + } else if (sc.comp_unit) { + s.Printf("Global variables for %s\n", sc.comp_unit->GetPath().c_str()); + } + + for (uint32_t i = 0; i < count; ++i) { + VariableSP var_sp(variable_list.GetVariableAtIndex(i)); + if (var_sp) { + ValueObjectSP valobj_sp(ValueObjectVariable::Create( + exe_ctx.GetBestExecutionContextScope(), var_sp)); + + if (valobj_sp) + DumpValueObject(s, var_sp, valobj_sp, + var_sp->GetName().GetCString()); } - - const Format format = m_option_format.GetFormat(); - if (format != eFormatDefault) - options.SetFormat(format); - - options.SetRootValueObjectName(root_name); - - valobj_sp->Dump(s,options); + } } - - static size_t GetVariableCallback (void *baton, - const char *name, - VariableList &variable_list) - { - Target *target = static_cast<Target *>(baton); - if (target) - { - return target->GetImages().FindGlobalVariables (ConstString(name), - true, - UINT32_MAX, - variable_list); + } + + bool DoExecute(Args &args, CommandReturnObject &result) override { + Target *target = m_exe_ctx.GetTargetPtr(); + const size_t argc = args.GetArgumentCount(); + Stream &s = result.GetOutputStream(); + + if (argc > 0) { + + for (size_t idx = 0; idx < argc; ++idx) { + 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(arg); + if (!regex.IsValid()) { + result.GetErrorStream().Printf( + "error: invalid regular expression: '%s'\n", arg); + result.SetStatus(eReturnStatusFailed); + return false; + } + use_var_name = true; + matches = target->GetImages().FindGlobalVariables( + regex, true, UINT32_MAX, variable_list); + } else { + Error error(Variable::GetValuesForVariableExpressionPath( + arg, m_exe_ctx.GetBestExecutionContextScope(), + GetVariableCallback, target, variable_list, valobj_list)); + matches = variable_list.GetSize(); } - return 0; - } - - Options * - GetOptions () override - { - return &m_option_group; - } -protected: - void - DumpGlobalVariableList(const ExecutionContext &exe_ctx, const SymbolContext &sc, const VariableList &variable_list, Stream &s) - { - size_t count = variable_list.GetSize(); - if (count > 0) - { - if (sc.module_sp) - { - if (sc.comp_unit) - { - s.Printf ("Global variables for %s in %s:\n", - sc.comp_unit->GetPath().c_str(), - sc.module_sp->GetFileSpec().GetPath().c_str()); - } - else - { - s.Printf ("Global variables for %s\n", - sc.module_sp->GetFileSpec().GetPath().c_str()); - } - } - else if (sc.comp_unit) - { - s.Printf ("Global variables for %s\n", - sc.comp_unit->GetPath().c_str()); - } - - for (uint32_t i = 0; i < count; ++i) - { - VariableSP var_sp (variable_list.GetVariableAtIndex(i)); - if (var_sp) - { - ValueObjectSP valobj_sp (ValueObjectVariable::Create (exe_ctx.GetBestExecutionContextScope(), var_sp)); - - if (valobj_sp) - DumpValueObject (s, var_sp, valobj_sp, var_sp->GetName().GetCString()); - } + if (matches == 0) { + result.GetErrorStream().Printf( + "error: can't find global variable '%s'\n", arg); + result.SetStatus(eReturnStatusFailed); + return false; + } else { + for (uint32_t global_idx = 0; global_idx < matches; ++global_idx) { + VariableSP var_sp(variable_list.GetVariableAtIndex(global_idx)); + if (var_sp) { + ValueObjectSP valobj_sp( + valobj_list.GetValueObjectAtIndex(global_idx)); + if (!valobj_sp) + valobj_sp = ValueObjectVariable::Create( + m_exe_ctx.GetBestExecutionContextScope(), var_sp); + + if (valobj_sp) + DumpValueObject(s, var_sp, valobj_sp, + use_var_name ? var_sp->GetName().GetCString() + : arg); } + } } - } - - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - Target *target = m_exe_ctx.GetTargetPtr(); - const size_t argc = args.GetArgumentCount(); - Stream &s = result.GetOutputStream(); - - if (argc > 0) - { - - for (size_t idx = 0; idx < argc; ++idx) - { - 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(arg); - if (!regex.IsValid ()) - { - result.GetErrorStream().Printf ("error: invalid regular expression: '%s'\n", arg); - result.SetStatus (eReturnStatusFailed); - return false; - } - use_var_name = true; - matches = target->GetImages().FindGlobalVariables (regex, - true, - UINT32_MAX, - variable_list); - } - else - { - Error error (Variable::GetValuesForVariableExpressionPath (arg, - 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); - result.SetStatus (eReturnStatusFailed); - return false; - } - else - { - for (uint32_t global_idx=0; global_idx<matches; ++global_idx) - { - VariableSP var_sp (variable_list.GetVariableAtIndex(global_idx)); - if (var_sp) - { - ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(global_idx)); - if (!valobj_sp) - valobj_sp = ValueObjectVariable::Create (m_exe_ctx.GetBestExecutionContextScope(), var_sp); - - if (valobj_sp) - DumpValueObject (s, var_sp, valobj_sp, use_var_name ? var_sp->GetName().GetCString() : arg); - } - } - } + } + } else { + const FileSpecList &compile_units = + m_option_compile_units.GetOptionValue().GetCurrentValue(); + const FileSpecList &shlibs = + m_option_shared_libraries.GetOptionValue().GetCurrentValue(); + SymbolContextList sc_list; + const size_t num_compile_units = compile_units.GetSize(); + const size_t num_shlibs = shlibs.GetSize(); + if (num_compile_units == 0 && num_shlibs == 0) { + bool success = false; + StackFrame *frame = m_exe_ctx.GetFramePtr(); + CompileUnit *comp_unit = nullptr; + if (frame) { + SymbolContext sc = frame->GetSymbolContext(eSymbolContextCompUnit); + if (sc.comp_unit) { + const bool can_create = true; + VariableListSP comp_unit_varlist_sp( + sc.comp_unit->GetVariableList(can_create)); + if (comp_unit_varlist_sp) { + size_t count = comp_unit_varlist_sp->GetSize(); + if (count > 0) { + DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp, s); + success = true; + } } + } } - else - { - const FileSpecList &compile_units = m_option_compile_units.GetOptionValue().GetCurrentValue(); - const FileSpecList &shlibs = m_option_shared_libraries.GetOptionValue().GetCurrentValue(); - SymbolContextList sc_list; - const size_t num_compile_units = compile_units.GetSize(); - const size_t num_shlibs = shlibs.GetSize(); - if (num_compile_units == 0 && num_shlibs == 0) - { - bool success = false; - StackFrame *frame = m_exe_ctx.GetFramePtr(); - CompileUnit *comp_unit = nullptr; - if (frame) - { - SymbolContext sc = frame->GetSymbolContext (eSymbolContextCompUnit); - if (sc.comp_unit) - { - const bool can_create = true; - VariableListSP comp_unit_varlist_sp (sc.comp_unit->GetVariableList(can_create)); - if (comp_unit_varlist_sp) - { - size_t count = comp_unit_varlist_sp->GetSize(); - if (count > 0) - { - DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp, s); - success = true; - } - } - } - } - if (!success) - { - if (frame) - { - if (comp_unit) - result.AppendErrorWithFormat ("no global variables in current compile unit: %s\n", - comp_unit->GetPath().c_str()); - else - result.AppendErrorWithFormat ("no debug information for frame %u\n", frame->GetFrameIndex()); - } - else - result.AppendError ("'target variable' takes one or more global variable names as arguments\n"); - result.SetStatus (eReturnStatusFailed); - } - } + if (!success) { + if (frame) { + if (comp_unit) + result.AppendErrorWithFormat( + "no global variables in current compile unit: %s\n", + comp_unit->GetPath().c_str()); else - { - SymbolContextList sc_list; - const bool append = true; - // We have one or more compile unit or shlib - if (num_shlibs > 0) - { - for (size_t shlib_idx=0; shlib_idx<num_shlibs; ++shlib_idx) - { - const FileSpec module_file(shlibs.GetFileSpecAtIndex(shlib_idx)); - ModuleSpec module_spec (module_file); - - ModuleSP module_sp (target->GetImages().FindFirstModule(module_spec)); - if (module_sp) - { - if (num_compile_units > 0) - { - for (size_t cu_idx=0; cu_idx<num_compile_units; ++cu_idx) - module_sp->FindCompileUnits(compile_units.GetFileSpecAtIndex(cu_idx), append, sc_list); - } - else - { - SymbolContext sc; - sc.module_sp = module_sp; - sc_list.Append(sc); - } - } - else - { - // Didn't find matching shlib/module in target... - result.AppendErrorWithFormat ("target doesn't contain the specified shared library: %s\n", - module_file.GetPath().c_str()); - } - } - } - else - { - // No shared libraries, we just want to find globals for the compile units files that were specified - for (size_t cu_idx=0; cu_idx<num_compile_units; ++cu_idx) - target->GetImages().FindCompileUnits(compile_units.GetFileSpecAtIndex(cu_idx), append, sc_list); - } - - const uint32_t num_scs = sc_list.GetSize(); - if (num_scs > 0) - { - SymbolContext sc; - for (uint32_t sc_idx=0; sc_idx<num_scs; ++sc_idx) - { - if (sc_list.GetContextAtIndex(sc_idx, sc)) - { - if (sc.comp_unit) - { - const bool can_create = true; - VariableListSP comp_unit_varlist_sp (sc.comp_unit->GetVariableList(can_create)); - if (comp_unit_varlist_sp) - DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp, s); - } - else if (sc.module_sp) - { - // Get all global variables for this module - lldb_private::RegularExpression all_globals_regex("."); // Any global with at least one character - VariableList variable_list; - sc.module_sp->FindGlobalVariables(all_globals_regex, append, UINT32_MAX, variable_list); - DumpGlobalVariableList(m_exe_ctx, sc, variable_list, s); - } - } - } - } + result.AppendErrorWithFormat( + "no debug information for frame %u\n", + frame->GetFrameIndex()); + } else + result.AppendError("'target variable' takes one or more global " + "variable names as arguments\n"); + result.SetStatus(eReturnStatusFailed); + } + } else { + SymbolContextList sc_list; + const bool append = true; + // We have one or more compile unit or shlib + if (num_shlibs > 0) { + for (size_t shlib_idx = 0; shlib_idx < num_shlibs; ++shlib_idx) { + const FileSpec module_file(shlibs.GetFileSpecAtIndex(shlib_idx)); + ModuleSpec module_spec(module_file); + + ModuleSP module_sp( + target->GetImages().FindFirstModule(module_spec)); + if (module_sp) { + if (num_compile_units > 0) { + for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) + module_sp->FindCompileUnits( + compile_units.GetFileSpecAtIndex(cu_idx), append, + sc_list); + } else { + SymbolContext sc; + sc.module_sp = module_sp; + sc_list.Append(sc); + } + } else { + // Didn't find matching shlib/module in target... + result.AppendErrorWithFormat( + "target doesn't contain the specified shared library: %s\n", + module_file.GetPath().c_str()); } + } + } else { + // No shared libraries, we just want to find globals for the compile + // units files that were specified + for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) + target->GetImages().FindCompileUnits( + compile_units.GetFileSpecAtIndex(cu_idx), append, sc_list); } - if (m_interpreter.TruncationWarningNecessary()) - { - result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(), - m_cmd_name.c_str()); - m_interpreter.TruncationWarningGiven(); + const uint32_t num_scs = sc_list.GetSize(); + if (num_scs > 0) { + SymbolContext sc; + for (uint32_t sc_idx = 0; sc_idx < num_scs; ++sc_idx) { + if (sc_list.GetContextAtIndex(sc_idx, sc)) { + if (sc.comp_unit) { + const bool can_create = true; + VariableListSP comp_unit_varlist_sp( + sc.comp_unit->GetVariableList(can_create)); + if (comp_unit_varlist_sp) + DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp, + s); + } else if (sc.module_sp) { + // Get all global variables for this module + lldb_private::RegularExpression all_globals_regex( + "."); // Any global with at least one character + VariableList variable_list; + sc.module_sp->FindGlobalVariables(all_globals_regex, append, + UINT32_MAX, variable_list); + DumpGlobalVariableList(m_exe_ctx, sc, variable_list, s); + } + } + } } + } + } - return result.Succeeded(); + if (m_interpreter.TruncationWarningNecessary()) { + result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(), + m_cmd_name.c_str()); + m_interpreter.TruncationWarningGiven(); } - OptionGroupOptions m_option_group; - OptionGroupVariable m_option_variable; - OptionGroupFormat m_option_format; - OptionGroupFileList m_option_compile_units; - OptionGroupFileList m_option_shared_libraries; - OptionGroupValueObjectDisplay m_varobj_options; + return result.Succeeded(); + } + + OptionGroupOptions m_option_group; + OptionGroupVariable m_option_variable; + OptionGroupFormat m_option_format; + OptionGroupFileList m_option_compile_units; + OptionGroupFileList m_option_shared_libraries; + OptionGroupValueObjectDisplay m_varobj_options; }; #pragma mark CommandObjectTargetModulesSearchPathsAdd -class CommandObjectTargetModulesSearchPathsAdd : public CommandObjectParsed -{ +class CommandObjectTargetModulesSearchPathsAdd : public CommandObjectParsed { public: - CommandObjectTargetModulesSearchPathsAdd (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "target modules search-paths add", - "Add new image search paths substitution pairs to the current target.", - nullptr) - { - CommandArgumentEntry arg; - CommandArgumentData old_prefix_arg; - CommandArgumentData new_prefix_arg; - - // Define the first variant of this arg pair. - old_prefix_arg.arg_type = eArgTypeOldPathPrefix; - old_prefix_arg.arg_repetition = eArgRepeatPairPlus; - - // Define the first variant of this arg pair. - new_prefix_arg.arg_type = eArgTypeNewPathPrefix; - new_prefix_arg.arg_repetition = eArgRepeatPairPlus; - - // There are two required arguments that must always occur together, i.e. an argument "pair". Because they - // must always occur together, they are treated as two variants of one argument rather than two independent - // arguments. Push them both into the first argument position for m_arguments... - - arg.push_back (old_prefix_arg); - arg.push_back (new_prefix_arg); - - m_arguments.push_back (arg); - } - - ~CommandObjectTargetModulesSearchPathsAdd() override = default; + CommandObjectTargetModulesSearchPathsAdd(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "target modules search-paths add", + "Add new image search paths substitution pairs to " + "the current target.", + nullptr) { + CommandArgumentEntry arg; + CommandArgumentData old_prefix_arg; + CommandArgumentData new_prefix_arg; + + // Define the first variant of this arg pair. + old_prefix_arg.arg_type = eArgTypeOldPathPrefix; + old_prefix_arg.arg_repetition = eArgRepeatPairPlus; + + // Define the first variant of this arg pair. + new_prefix_arg.arg_type = eArgTypeNewPathPrefix; + new_prefix_arg.arg_repetition = eArgRepeatPairPlus; + + // There are two required arguments that must always occur together, i.e. an + // argument "pair". Because they + // must always occur together, they are treated as two variants of one + // argument rather than two independent + // arguments. Push them both into the first argument position for + // m_arguments... + + arg.push_back(old_prefix_arg); + arg.push_back(new_prefix_arg); + + m_arguments.push_back(arg); + } + + ~CommandObjectTargetModulesSearchPathsAdd() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (target) - { - const size_t argc = command.GetArgumentCount(); - if (argc & 1) - { - result.AppendError ("add requires an even number of arguments\n"); - result.SetStatus (eReturnStatusFailed); + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (target) { + const size_t argc = command.GetArgumentCount(); + if (argc & 1) { + result.AppendError("add requires an even number of arguments\n"); + result.SetStatus(eReturnStatusFailed); + } else { + for (size_t i = 0; i < argc; i += 2) { + const char *from = command.GetArgumentAtIndex(i); + const char *to = command.GetArgumentAtIndex(i + 1); + + if (from[0] && to[0]) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) { + log->Printf("target modules search path adding ImageSearchPath " + "pair: '%s' -> '%s'", + from, to); } + bool last_pair = ((argc - i) == 2); + target->GetImageSearchPathList().Append( + ConstString(from), ConstString(to), + last_pair); // Notify if this is the last pair + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + if (from[0]) + result.AppendError("<path-prefix> can't be empty\n"); else - { - for (size_t i = 0; i < argc; i+=2) - { - const char *from = command.GetArgumentAtIndex(i); - const char *to = command.GetArgumentAtIndex(i+1); - - if (from[0] && to[0]) - { - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - { - log->Printf ("target modules search path adding ImageSearchPath pair: '%s' -> '%s'", - from, to); - } - bool last_pair = ((argc - i) == 2); - target->GetImageSearchPathList().Append (ConstString(from), - ConstString(to), - last_pair); // Notify if this is the last pair - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - if (from[0]) - result.AppendError ("<path-prefix> can't be empty\n"); - else - result.AppendError ("<new-path-prefix> can't be empty\n"); - result.SetStatus (eReturnStatusFailed); - } - } - } - } - else - { - result.AppendError ("invalid target\n"); - result.SetStatus (eReturnStatusFailed); + result.AppendError("<new-path-prefix> can't be empty\n"); + result.SetStatus(eReturnStatusFailed); + } } - return result.Succeeded(); + } + } else { + result.AppendError("invalid target\n"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } }; #pragma mark CommandObjectTargetModulesSearchPathsClear -class CommandObjectTargetModulesSearchPathsClear : public CommandObjectParsed -{ +class CommandObjectTargetModulesSearchPathsClear : public CommandObjectParsed { public: - CommandObjectTargetModulesSearchPathsClear (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "target modules search-paths clear", - "Clear all current image search path substitution pairs from the current target.", - "target modules search-paths clear") - { - } + CommandObjectTargetModulesSearchPathsClear(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "target modules search-paths clear", + "Clear all current image search path substitution " + "pairs from the current target.", + "target modules search-paths clear") {} - ~CommandObjectTargetModulesSearchPathsClear() override = default; + ~CommandObjectTargetModulesSearchPathsClear() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (target) - { - bool notify = true; - target->GetImageSearchPathList().Clear(notify); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendError ("invalid target\n"); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (target) { + bool notify = true; + target->GetImageSearchPathList().Clear(notify); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.AppendError("invalid target\n"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } }; #pragma mark CommandObjectTargetModulesSearchPathsInsert -class CommandObjectTargetModulesSearchPathsInsert : public CommandObjectParsed -{ +class CommandObjectTargetModulesSearchPathsInsert : public CommandObjectParsed { public: - CommandObjectTargetModulesSearchPathsInsert (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "target modules search-paths insert", - "Insert a new image search path substitution pair into the current target at the specified index.", - nullptr) - { - CommandArgumentEntry arg1; - CommandArgumentEntry arg2; - CommandArgumentData index_arg; - CommandArgumentData old_prefix_arg; - CommandArgumentData new_prefix_arg; - - // Define the first and only variant of this arg. - index_arg.arg_type = eArgTypeIndex; - index_arg.arg_repetition = eArgRepeatPlain; - - // Put the one and only variant into the first arg for m_arguments: - arg1.push_back (index_arg); - - // Define the first variant of this arg pair. - old_prefix_arg.arg_type = eArgTypeOldPathPrefix; - old_prefix_arg.arg_repetition = eArgRepeatPairPlus; - - // Define the first variant of this arg pair. - new_prefix_arg.arg_type = eArgTypeNewPathPrefix; - new_prefix_arg.arg_repetition = eArgRepeatPairPlus; - - // There are two required arguments that must always occur together, i.e. an argument "pair". Because they - // must always occur together, they are treated as two variants of one argument rather than two independent - // arguments. Push them both into the same argument position for m_arguments... - - arg2.push_back (old_prefix_arg); - arg2.push_back (new_prefix_arg); - - // Add arguments to m_arguments. - m_arguments.push_back (arg1); - m_arguments.push_back (arg2); - } - - ~CommandObjectTargetModulesSearchPathsInsert() override = default; + CommandObjectTargetModulesSearchPathsInsert(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "target modules search-paths insert", + "Insert a new image search path substitution pair " + "into the current target at the specified index.", + nullptr) { + CommandArgumentEntry arg1; + CommandArgumentEntry arg2; + CommandArgumentData index_arg; + CommandArgumentData old_prefix_arg; + CommandArgumentData new_prefix_arg; + + // Define the first and only variant of this arg. + index_arg.arg_type = eArgTypeIndex; + index_arg.arg_repetition = eArgRepeatPlain; + + // Put the one and only variant into the first arg for m_arguments: + arg1.push_back(index_arg); + + // Define the first variant of this arg pair. + old_prefix_arg.arg_type = eArgTypeOldPathPrefix; + old_prefix_arg.arg_repetition = eArgRepeatPairPlus; + + // Define the first variant of this arg pair. + new_prefix_arg.arg_type = eArgTypeNewPathPrefix; + new_prefix_arg.arg_repetition = eArgRepeatPairPlus; + + // There are two required arguments that must always occur together, i.e. an + // argument "pair". Because they + // must always occur together, they are treated as two variants of one + // argument rather than two independent + // arguments. Push them both into the same argument position for + // m_arguments... + + arg2.push_back(old_prefix_arg); + arg2.push_back(new_prefix_arg); + + // Add arguments to m_arguments. + m_arguments.push_back(arg1); + m_arguments.push_back(arg2); + } + + ~CommandObjectTargetModulesSearchPathsInsert() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (target) - { - 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); - - if (!success) - { - result.AppendErrorWithFormat("<index> parameter is not an integer: '%s'.\n", command.GetArgumentAtIndex(0)); - result.SetStatus (eReturnStatusFailed); - return result.Succeeded(); - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (target) { + 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); + + if (!success) { + result.AppendErrorWithFormat( + "<index> parameter is not an integer: '%s'.\n", + command.GetArgumentAtIndex(0)); + result.SetStatus(eReturnStatusFailed); + return result.Succeeded(); + } - // shift off the index - command.Shift(); - argc = command.GetArgumentCount(); - - for (uint32_t i = 0; i < argc; i += 2, ++insert_idx) - { - const char *from = command.GetArgumentAtIndex(i); - const char *to = command.GetArgumentAtIndex(i+1); - - if (from[0] && to[0]) - { - bool last_pair = ((argc - i) == 2); - target->GetImageSearchPathList().Insert (ConstString(from), - ConstString(to), - insert_idx, - last_pair); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - if (from[0]) - result.AppendError ("<path-prefix> can't be empty\n"); - else - result.AppendError ("<new-path-prefix> can't be empty\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - } + // shift off the index + command.Shift(); + argc = command.GetArgumentCount(); + + for (uint32_t i = 0; i < argc; i += 2, ++insert_idx) { + const char *from = command.GetArgumentAtIndex(i); + const char *to = command.GetArgumentAtIndex(i + 1); + + if (from[0] && to[0]) { + bool last_pair = ((argc - i) == 2); + target->GetImageSearchPathList().Insert( + ConstString(from), ConstString(to), insert_idx, last_pair); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + if (from[0]) + result.AppendError("<path-prefix> can't be empty\n"); else - { - result.AppendError ("insert requires at least three arguments\n"); - result.SetStatus (eReturnStatusFailed); - return result.Succeeded(); - } - - } - else - { - result.AppendError ("invalid target\n"); - result.SetStatus (eReturnStatusFailed); + result.AppendError("<new-path-prefix> can't be empty\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } } + } else { + result.AppendError("insert requires at least three arguments\n"); + result.SetStatus(eReturnStatusFailed); return result.Succeeded(); + } + + } else { + result.AppendError("invalid target\n"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } }; #pragma mark CommandObjectTargetModulesSearchPathsList -class CommandObjectTargetModulesSearchPathsList : public CommandObjectParsed -{ +class CommandObjectTargetModulesSearchPathsList : public CommandObjectParsed { public: - CommandObjectTargetModulesSearchPathsList (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "target modules search-paths list", - "List all current image search path substitution pairs in the current target.", - "target modules search-paths list") - { - } + CommandObjectTargetModulesSearchPathsList(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "target modules search-paths list", + "List all current image search path substitution " + "pairs in the current target.", + "target modules search-paths list") {} - ~CommandObjectTargetModulesSearchPathsList() override = default; + ~CommandObjectTargetModulesSearchPathsList() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (target) - { - if (command.GetArgumentCount() != 0) - { - result.AppendError ("list takes no arguments\n"); - result.SetStatus (eReturnStatusFailed); - return result.Succeeded(); - } - - target->GetImageSearchPathList().Dump(&result.GetOutputStream()); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendError ("invalid target\n"); - result.SetStatus (eReturnStatusFailed); - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (target) { + if (command.GetArgumentCount() != 0) { + result.AppendError("list takes no arguments\n"); + result.SetStatus(eReturnStatusFailed); return result.Succeeded(); + } + + target->GetImageSearchPathList().Dump(&result.GetOutputStream()); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendError("invalid target\n"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } }; #pragma mark CommandObjectTargetModulesSearchPathsQuery -class CommandObjectTargetModulesSearchPathsQuery : public CommandObjectParsed -{ +class CommandObjectTargetModulesSearchPathsQuery : public CommandObjectParsed { public: - CommandObjectTargetModulesSearchPathsQuery (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "target modules search-paths query", - "Transform a path using the first applicable image search path.", - nullptr) - { - CommandArgumentEntry arg; - CommandArgumentData path_arg; - - // Define the first (and only) variant of this arg. - path_arg.arg_type = eArgTypeDirectoryName; - path_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (path_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - } + CommandObjectTargetModulesSearchPathsQuery(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "target modules search-paths query", + "Transform a path using the first applicable image search path.", + nullptr) { + CommandArgumentEntry arg; + CommandArgumentData path_arg; - ~CommandObjectTargetModulesSearchPathsQuery() override = default; + // Define the first (and only) variant of this arg. + path_arg.arg_type = eArgTypeDirectoryName; + path_arg.arg_repetition = eArgRepeatPlain; -protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (target) - { - if (command.GetArgumentCount() != 1) - { - result.AppendError ("query requires one argument\n"); - result.SetStatus (eReturnStatusFailed); - return result.Succeeded(); - } + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(path_arg); - ConstString orig(command.GetArgumentAtIndex(0)); - ConstString transformed; - if (target->GetImageSearchPathList().RemapPath(orig, transformed)) - result.GetOutputStream().Printf("%s\n", transformed.GetCString()); - else - result.GetOutputStream().Printf("%s\n", orig.GetCString()); + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendError ("invalid target\n"); - result.SetStatus (eReturnStatusFailed); - } + ~CommandObjectTargetModulesSearchPathsQuery() override = default; + +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (target) { + if (command.GetArgumentCount() != 1) { + result.AppendError("query requires one argument\n"); + result.SetStatus(eReturnStatusFailed); return result.Succeeded(); + } + + ConstString orig(command.GetArgumentAtIndex(0)); + ConstString transformed; + if (target->GetImageSearchPathList().RemapPath(orig, transformed)) + result.GetOutputStream().Printf("%s\n", transformed.GetCString()); + else + result.GetOutputStream().Printf("%s\n", orig.GetCString()); + + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendError("invalid target\n"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } }; //---------------------------------------------------------------------- // Static Helper functions //---------------------------------------------------------------------- -static void -DumpModuleArchitecture (Stream &strm, Module *module, bool full_triple, uint32_t width) -{ - if (module) - { - StreamString arch_strm; - - if (full_triple) - module->GetArchitecture().DumpTriple(arch_strm); - else - arch_strm.PutCString(module->GetArchitecture().GetArchitectureName()); - std::string arch_str = arch_strm.GetString(); +static void DumpModuleArchitecture(Stream &strm, Module *module, + bool full_triple, uint32_t width) { + if (module) { + StreamString arch_strm; - if (width) - strm.Printf("%-*s", width, arch_str.c_str()); - else - strm.PutCString(arch_str.c_str()); - } -} + if (full_triple) + module->GetArchitecture().DumpTriple(arch_strm); + else + arch_strm.PutCString(module->GetArchitecture().GetArchitectureName()); + std::string arch_str = arch_strm.GetString(); -static void -DumpModuleUUID (Stream &strm, Module *module) -{ - if (module && module->GetUUID().IsValid()) - module->GetUUID().Dump (&strm); + if (width) + strm.Printf("%-*s", width, arch_str.c_str()); else - strm.PutCString(" "); + strm.PutCString(arch_str.c_str()); + } } -static uint32_t -DumpCompileUnitLineTable (CommandInterpreter &interpreter, - Stream &strm, - Module *module, - const FileSpec &file_spec, - bool load_addresses) -{ - uint32_t num_matches = 0; - if (module) - { - SymbolContextList sc_list; - num_matches = module->ResolveSymbolContextsForFileSpec (file_spec, - 0, - false, - eSymbolContextCompUnit, - sc_list); - - for (uint32_t i = 0; i < num_matches; ++i) - { - SymbolContext sc; - if (sc_list.GetContextAtIndex(i, sc)) - { - if (i > 0) - strm << "\n\n"; - - strm << "Line table for " << *static_cast<FileSpec*> (sc.comp_unit) << " in `" - << module->GetFileSpec().GetFilename() << "\n"; - LineTable *line_table = sc.comp_unit->GetLineTable(); - if (line_table) - line_table->GetDescription (&strm, - interpreter.GetExecutionContext().GetTargetPtr(), - lldb::eDescriptionLevelBrief); - else - strm << "No line table"; - } - } - } - return num_matches; +static void DumpModuleUUID(Stream &strm, Module *module) { + if (module && module->GetUUID().IsValid()) + module->GetUUID().Dump(&strm); + else + strm.PutCString(" "); } -static void -DumpFullpath (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width) -{ - if (file_spec_ptr) - { - if (width > 0) - { - std::string fullpath = file_spec_ptr->GetPath(); - strm.Printf("%-*s", width, fullpath.c_str()); - return; - } +static uint32_t DumpCompileUnitLineTable(CommandInterpreter &interpreter, + Stream &strm, Module *module, + const FileSpec &file_spec, + bool load_addresses) { + uint32_t num_matches = 0; + if (module) { + SymbolContextList sc_list; + num_matches = module->ResolveSymbolContextsForFileSpec( + file_spec, 0, false, eSymbolContextCompUnit, sc_list); + + for (uint32_t i = 0; i < num_matches; ++i) { + SymbolContext sc; + if (sc_list.GetContextAtIndex(i, sc)) { + if (i > 0) + strm << "\n\n"; + + strm << "Line table for " << *static_cast<FileSpec *>(sc.comp_unit) + << " in `" << module->GetFileSpec().GetFilename() << "\n"; + LineTable *line_table = sc.comp_unit->GetLineTable(); + if (line_table) + line_table->GetDescription( + &strm, interpreter.GetExecutionContext().GetTargetPtr(), + lldb::eDescriptionLevelBrief); else - { - file_spec_ptr->Dump(&strm); - return; - } + strm << "No line table"; + } } - // Keep the width spacing correct if things go wrong... - if (width > 0) - strm.Printf("%-*s", width, ""); + } + return num_matches; } -static void -DumpDirectory (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width) -{ - if (file_spec_ptr) - { - if (width > 0) - strm.Printf("%-*s", width, file_spec_ptr->GetDirectory().AsCString("")); - else - file_spec_ptr->GetDirectory().Dump(&strm); - return; +static void DumpFullpath(Stream &strm, const FileSpec *file_spec_ptr, + uint32_t width) { + if (file_spec_ptr) { + if (width > 0) { + std::string fullpath = file_spec_ptr->GetPath(); + strm.Printf("%-*s", width, fullpath.c_str()); + return; + } else { + file_spec_ptr->Dump(&strm); + return; } - // Keep the width spacing correct if things go wrong... - if (width > 0) - strm.Printf("%-*s", width, ""); + } + // Keep the width spacing correct if things go wrong... + if (width > 0) + strm.Printf("%-*s", width, ""); } -static void -DumpBasename (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width) -{ - if (file_spec_ptr) - { - if (width > 0) - strm.Printf("%-*s", width, file_spec_ptr->GetFilename().AsCString("")); - else - file_spec_ptr->GetFilename().Dump(&strm); - return; - } - // Keep the width spacing correct if things go wrong... +static void DumpDirectory(Stream &strm, const FileSpec *file_spec_ptr, + uint32_t width) { + if (file_spec_ptr) { if (width > 0) - strm.Printf("%-*s", width, ""); + strm.Printf("%-*s", width, file_spec_ptr->GetDirectory().AsCString("")); + else + file_spec_ptr->GetDirectory().Dump(&strm); + return; + } + // Keep the width spacing correct if things go wrong... + if (width > 0) + strm.Printf("%-*s", width, ""); } -static size_t -DumpModuleObjfileHeaders(Stream &strm, ModuleList &module_list) -{ - size_t num_dumped = 0; - std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex()); - const size_t num_modules = module_list.GetSize(); - if (num_modules > 0) - { - strm.Printf("Dumping headers for %" PRIu64 " module(s).\n", static_cast<uint64_t>(num_modules)); - strm.IndentMore(); - for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) - { - Module *module = module_list.GetModulePointerAtIndexUnlocked(image_idx); - if (module) - { - if (num_dumped++ > 0) - { - strm.EOL(); - strm.EOL(); - } - ObjectFile *objfile = module->GetObjectFile(); - objfile->Dump(&strm); - } - } - strm.IndentLess(); - } - return num_dumped; +static void DumpBasename(Stream &strm, const FileSpec *file_spec_ptr, + uint32_t width) { + if (file_spec_ptr) { + if (width > 0) + strm.Printf("%-*s", width, file_spec_ptr->GetFilename().AsCString("")); + else + file_spec_ptr->GetFilename().Dump(&strm); + return; + } + // Keep the width spacing correct if things go wrong... + if (width > 0) + strm.Printf("%-*s", width, ""); } -static void -DumpModuleSymtab (CommandInterpreter &interpreter, Stream &strm, Module *module, SortOrder sort_order) -{ - if (module) - { - SymbolVendor *sym_vendor = module->GetSymbolVendor (); - if (sym_vendor) - { - Symtab *symtab = sym_vendor->GetSymtab(); - if (symtab) - symtab->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(), sort_order); +static size_t DumpModuleObjfileHeaders(Stream &strm, ModuleList &module_list) { + size_t num_dumped = 0; + std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex()); + const size_t num_modules = module_list.GetSize(); + if (num_modules > 0) { + strm.Printf("Dumping headers for %" PRIu64 " module(s).\n", + static_cast<uint64_t>(num_modules)); + strm.IndentMore(); + for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { + Module *module = module_list.GetModulePointerAtIndexUnlocked(image_idx); + if (module) { + if (num_dumped++ > 0) { + strm.EOL(); + strm.EOL(); } + ObjectFile *objfile = module->GetObjectFile(); + objfile->Dump(&strm); + } } + strm.IndentLess(); + } + return num_dumped; } -static void -DumpModuleSections (CommandInterpreter &interpreter, Stream &strm, Module *module) -{ - if (module) - { - SectionList *section_list = module->GetSectionList(); - if (section_list) - { - strm.Printf ("Sections for '%s' (%s):\n", - module->GetSpecificationDescription().c_str(), - module->GetArchitecture().GetArchitectureName()); - strm.IndentMore(); - section_list->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(), true, UINT32_MAX); - strm.IndentLess(); - } +static void DumpModuleSymtab(CommandInterpreter &interpreter, Stream &strm, + Module *module, SortOrder sort_order) { + if (module) { + SymbolVendor *sym_vendor = module->GetSymbolVendor(); + if (sym_vendor) { + Symtab *symtab = sym_vendor->GetSymtab(); + if (symtab) + symtab->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(), + sort_order); } + } } -static bool -DumpModuleSymbolVendor (Stream &strm, Module *module) -{ - if (module) - { - SymbolVendor *symbol_vendor = module->GetSymbolVendor(true); - if (symbol_vendor) - { - symbol_vendor->Dump(&strm); - return true; - } +static void DumpModuleSections(CommandInterpreter &interpreter, Stream &strm, + Module *module) { + if (module) { + SectionList *section_list = module->GetSectionList(); + if (section_list) { + strm.Printf("Sections for '%s' (%s):\n", + module->GetSpecificationDescription().c_str(), + module->GetArchitecture().GetArchitectureName()); + strm.IndentMore(); + section_list->Dump(&strm, + interpreter.GetExecutionContext().GetTargetPtr(), true, + UINT32_MAX); + strm.IndentLess(); } - return false; + } } -static void -DumpAddress (ExecutionContextScope *exe_scope, const Address &so_addr, bool verbose, Stream &strm) -{ - strm.IndentMore(); - strm.Indent (" Address: "); - so_addr.Dump (&strm, exe_scope, Address::DumpStyleModuleWithFileAddress); - strm.PutCString (" ("); - so_addr.Dump (&strm, exe_scope, Address::DumpStyleSectionNameOffset); - strm.PutCString (")\n"); - strm.Indent (" Summary: "); - const uint32_t save_indent = strm.GetIndentLevel (); - strm.SetIndentLevel (save_indent + 13); - so_addr.Dump (&strm, exe_scope, Address::DumpStyleResolvedDescription); - strm.SetIndentLevel (save_indent); - // Print out detailed address information when verbose is enabled - if (verbose) - { - strm.EOL(); - so_addr.Dump (&strm, exe_scope, Address::DumpStyleDetailedSymbolContext); +static bool DumpModuleSymbolVendor(Stream &strm, Module *module) { + if (module) { + SymbolVendor *symbol_vendor = module->GetSymbolVendor(true); + if (symbol_vendor) { + symbol_vendor->Dump(&strm); + return true; } - strm.IndentLess(); + } + return false; } -static bool -LookupAddressInModule (CommandInterpreter &interpreter, - Stream &strm, - Module *module, - uint32_t resolve_mask, - lldb::addr_t raw_addr, - lldb::addr_t offset, - bool verbose) -{ - if (module) - { - lldb::addr_t addr = raw_addr - offset; - Address so_addr; - SymbolContext sc; - Target *target = interpreter.GetExecutionContext().GetTargetPtr(); - if (target && !target->GetSectionLoadList().IsEmpty()) - { - if (!target->GetSectionLoadList().ResolveLoadAddress (addr, so_addr)) - return false; - else if (so_addr.GetModule().get() != module) - return false; - } - else - { - if (!module->ResolveFileAddress (addr, so_addr)) - return false; - } +static void DumpAddress(ExecutionContextScope *exe_scope, + const Address &so_addr, bool verbose, Stream &strm) { + strm.IndentMore(); + strm.Indent(" Address: "); + so_addr.Dump(&strm, exe_scope, Address::DumpStyleModuleWithFileAddress); + strm.PutCString(" ("); + so_addr.Dump(&strm, exe_scope, Address::DumpStyleSectionNameOffset); + strm.PutCString(")\n"); + strm.Indent(" Summary: "); + const uint32_t save_indent = strm.GetIndentLevel(); + strm.SetIndentLevel(save_indent + 13); + so_addr.Dump(&strm, exe_scope, Address::DumpStyleResolvedDescription); + strm.SetIndentLevel(save_indent); + // Print out detailed address information when verbose is enabled + if (verbose) { + strm.EOL(); + so_addr.Dump(&strm, exe_scope, Address::DumpStyleDetailedSymbolContext); + } + strm.IndentLess(); +} - ExecutionContextScope *exe_scope = interpreter.GetExecutionContext().GetBestExecutionContextScope(); - DumpAddress (exe_scope, so_addr, verbose, strm); -// strm.IndentMore(); -// strm.Indent (" Address: "); -// so_addr.Dump (&strm, exe_scope, Address::DumpStyleModuleWithFileAddress); -// strm.PutCString (" ("); -// so_addr.Dump (&strm, exe_scope, Address::DumpStyleSectionNameOffset); -// strm.PutCString (")\n"); -// strm.Indent (" Summary: "); -// const uint32_t save_indent = strm.GetIndentLevel (); -// strm.SetIndentLevel (save_indent + 13); -// so_addr.Dump (&strm, exe_scope, Address::DumpStyleResolvedDescription); -// strm.SetIndentLevel (save_indent); -// // Print out detailed address information when verbose is enabled -// if (verbose) -// { -// strm.EOL(); -// so_addr.Dump (&strm, exe_scope, Address::DumpStyleDetailedSymbolContext); -// } -// strm.IndentLess(); - return true; +static bool LookupAddressInModule(CommandInterpreter &interpreter, Stream &strm, + Module *module, uint32_t resolve_mask, + lldb::addr_t raw_addr, lldb::addr_t offset, + bool verbose) { + if (module) { + lldb::addr_t addr = raw_addr - offset; + Address so_addr; + SymbolContext sc; + Target *target = interpreter.GetExecutionContext().GetTargetPtr(); + if (target && !target->GetSectionLoadList().IsEmpty()) { + if (!target->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) + return false; + else if (so_addr.GetModule().get() != module) + return false; + } else { + if (!module->ResolveFileAddress(addr, so_addr)) + return false; } - return false; + ExecutionContextScope *exe_scope = + interpreter.GetExecutionContext().GetBestExecutionContextScope(); + DumpAddress(exe_scope, so_addr, verbose, strm); + // strm.IndentMore(); + // strm.Indent (" Address: "); + // so_addr.Dump (&strm, exe_scope, + // Address::DumpStyleModuleWithFileAddress); + // strm.PutCString (" ("); + // so_addr.Dump (&strm, exe_scope, + // Address::DumpStyleSectionNameOffset); + // strm.PutCString (")\n"); + // strm.Indent (" Summary: "); + // const uint32_t save_indent = strm.GetIndentLevel (); + // strm.SetIndentLevel (save_indent + 13); + // so_addr.Dump (&strm, exe_scope, + // Address::DumpStyleResolvedDescription); + // strm.SetIndentLevel (save_indent); + // // Print out detailed address information when verbose is enabled + // if (verbose) + // { + // strm.EOL(); + // so_addr.Dump (&strm, exe_scope, + // Address::DumpStyleDetailedSymbolContext); + // } + // strm.IndentLess(); + return true; + } + + return false; } -static uint32_t -LookupSymbolInModule (CommandInterpreter &interpreter, Stream &strm, Module *module, const char *name, bool name_is_regex, bool verbose) -{ - if (module) - { - SymbolContext sc; - - SymbolVendor *sym_vendor = module->GetSymbolVendor (); - if (sym_vendor) - { - Symtab *symtab = sym_vendor->GetSymtab(); - if (symtab) - { - std::vector<uint32_t> match_indexes; - ConstString symbol_name (name); - uint32_t num_matches = 0; - if (name_is_regex) - { - RegularExpression name_regexp(name); - num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType (name_regexp, - eSymbolTypeAny, - match_indexes); - } - else - { - num_matches = symtab->AppendSymbolIndexesWithName (symbol_name, match_indexes); - } +static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter, + Stream &strm, Module *module, + const char *name, bool name_is_regex, + bool verbose) { + if (module) { + SymbolContext sc; + + SymbolVendor *sym_vendor = module->GetSymbolVendor(); + if (sym_vendor) { + Symtab *symtab = sym_vendor->GetSymtab(); + if (symtab) { + std::vector<uint32_t> match_indexes; + ConstString symbol_name(name); + uint32_t num_matches = 0; + if (name_is_regex) { + RegularExpression name_regexp(name); + num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType( + name_regexp, eSymbolTypeAny, match_indexes); + } else { + num_matches = + symtab->AppendSymbolIndexesWithName(symbol_name, match_indexes); + } - if (num_matches > 0) - { - strm.Indent (); - strm.Printf("%u symbols match %s'%s' in ", num_matches, - name_is_regex ? "the regular expression " : "", name); - DumpFullpath (strm, &module->GetFileSpec(), 0); - strm.PutCString(":\n"); - strm.IndentMore (); - for (uint32_t i = 0; i < num_matches; ++i) - { - Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]); - if (symbol && symbol->ValueIsAddress()) - { - DumpAddress (interpreter.GetExecutionContext().GetBestExecutionContextScope(), - symbol->GetAddressRef(), - verbose, - strm); - } - } - strm.IndentLess (); - return num_matches; - } + if (num_matches > 0) { + strm.Indent(); + strm.Printf("%u symbols match %s'%s' in ", num_matches, + name_is_regex ? "the regular expression " : "", name); + DumpFullpath(strm, &module->GetFileSpec(), 0); + strm.PutCString(":\n"); + strm.IndentMore(); + for (uint32_t i = 0; i < num_matches; ++i) { + Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]); + if (symbol && symbol->ValueIsAddress()) { + DumpAddress(interpreter.GetExecutionContext() + .GetBestExecutionContextScope(), + symbol->GetAddressRef(), verbose, strm); } + } + strm.IndentLess(); + return num_matches; } + } } - return 0; + } + return 0; } -static void -DumpSymbolContextList (ExecutionContextScope *exe_scope, Stream &strm, SymbolContextList &sc_list, bool verbose) -{ - strm.IndentMore (); +static void DumpSymbolContextList(ExecutionContextScope *exe_scope, + Stream &strm, SymbolContextList &sc_list, + bool verbose) { + strm.IndentMore(); - const uint32_t num_matches = sc_list.GetSize(); + const uint32_t num_matches = sc_list.GetSize(); - for (uint32_t i = 0; i < num_matches; ++i) - { - SymbolContext sc; - if (sc_list.GetContextAtIndex(i, sc)) - { - AddressRange range; + for (uint32_t i = 0; i < num_matches; ++i) { + SymbolContext sc; + if (sc_list.GetContextAtIndex(i, sc)) { + AddressRange range; - sc.GetAddressRange(eSymbolContextEverything, - 0, - true, - range); + sc.GetAddressRange(eSymbolContextEverything, 0, true, range); - DumpAddress (exe_scope, range.GetBaseAddress(), verbose, strm); - } + DumpAddress(exe_scope, range.GetBaseAddress(), verbose, strm); } - strm.IndentLess (); + } + strm.IndentLess(); } -static size_t -LookupFunctionInModule (CommandInterpreter &interpreter, - Stream &strm, - Module *module, - const char *name, - bool name_is_regex, - bool include_inlines, - bool include_symbols, - bool verbose) -{ - if (module && name && name[0]) - { - SymbolContextList sc_list; - const bool append = true; - size_t num_matches = 0; - if (name_is_regex) - { - RegularExpression function_name_regex (name); - num_matches = module->FindFunctions (function_name_regex, - include_symbols, - include_inlines, - append, - sc_list); - } - else - { - ConstString function_name (name); - num_matches = module->FindFunctions(function_name, - nullptr, - eFunctionNameTypeAuto, - include_symbols, - include_inlines, - append, - sc_list); - } - - if (num_matches) - { - strm.Indent (); - strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches, num_matches > 1 ? "es" : ""); - DumpFullpath (strm, &module->GetFileSpec(), 0); - strm.PutCString(":\n"); - DumpSymbolContextList (interpreter.GetExecutionContext().GetBestExecutionContextScope(), strm, sc_list, verbose); - } - return num_matches; +static size_t LookupFunctionInModule(CommandInterpreter &interpreter, + Stream &strm, Module *module, + const char *name, bool name_is_regex, + bool include_inlines, bool include_symbols, + bool verbose) { + if (module && name && name[0]) { + SymbolContextList sc_list; + const bool append = true; + size_t num_matches = 0; + if (name_is_regex) { + RegularExpression function_name_regex(name); + num_matches = module->FindFunctions(function_name_regex, include_symbols, + include_inlines, append, sc_list); + } else { + ConstString function_name(name); + num_matches = module->FindFunctions( + function_name, nullptr, eFunctionNameTypeAuto, include_symbols, + include_inlines, append, sc_list); } - return 0; -} - -static size_t -LookupTypeInModule (CommandInterpreter &interpreter, - Stream &strm, - Module *module, - const char *name_cstr, - bool name_is_regex) -{ - if (module && name_cstr && name_cstr[0]) - { - TypeList type_list; - const uint32_t max_num_matches = UINT32_MAX; - size_t num_matches = 0; - bool name_is_fully_qualified = false; - SymbolContext sc; - ConstString name(name_cstr); - llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; - num_matches = module->FindTypes(sc, name, name_is_fully_qualified, max_num_matches, searched_symbol_files, type_list); - - if (num_matches) - { - strm.Indent (); - strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches, num_matches > 1 ? "es" : ""); - DumpFullpath (strm, &module->GetFileSpec(), 0); - strm.PutCString(":\n"); - for (TypeSP type_sp : type_list.Types()) - { - if (type_sp) - { - // Resolve the clang type so that any forward references - // to types that haven't yet been parsed will get parsed. - type_sp->GetFullCompilerType (); - type_sp->GetDescription (&strm, eDescriptionLevelFull, true); - // Print all typedef chains - TypeSP typedef_type_sp (type_sp); - TypeSP typedefed_type_sp (typedef_type_sp->GetTypedefType()); - while (typedefed_type_sp) - { - strm.EOL(); - strm.Printf(" typedef '%s': ", typedef_type_sp->GetName().GetCString()); - typedefed_type_sp->GetFullCompilerType (); - typedefed_type_sp->GetDescription (&strm, eDescriptionLevelFull, true); - typedef_type_sp = typedefed_type_sp; - typedefed_type_sp = typedef_type_sp->GetTypedefType(); - } - } - strm.EOL(); - } - } - return num_matches; + if (num_matches) { + strm.Indent(); + strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches, + num_matches > 1 ? "es" : ""); + DumpFullpath(strm, &module->GetFileSpec(), 0); + strm.PutCString(":\n"); + DumpSymbolContextList( + interpreter.GetExecutionContext().GetBestExecutionContextScope(), + strm, sc_list, verbose); } - return 0; + return num_matches; + } + return 0; } -static size_t -LookupTypeHere (CommandInterpreter &interpreter, - Stream &strm, - const SymbolContext &sym_ctx, - const char *name_cstr, - bool name_is_regex) -{ - if (!sym_ctx.module_sp) - return 0; - +static size_t LookupTypeInModule(CommandInterpreter &interpreter, Stream &strm, + Module *module, const char *name_cstr, + bool name_is_regex) { + if (module && name_cstr && name_cstr[0]) { TypeList type_list; const uint32_t max_num_matches = UINT32_MAX; - size_t num_matches = 1; + size_t num_matches = 0; bool name_is_fully_qualified = false; + SymbolContext sc; ConstString name(name_cstr); - llvm::DenseSet<SymbolFile *> searched_symbol_files; - num_matches = sym_ctx.module_sp->FindTypes(sym_ctx, name, name_is_fully_qualified, max_num_matches, searched_symbol_files, type_list); - - if (num_matches) - { - strm.Indent (); - strm.PutCString("Best match found in "); - DumpFullpath (strm, &sym_ctx.module_sp->GetFileSpec(), 0); - strm.PutCString(":\n"); - - TypeSP type_sp (type_list.GetTypeAtIndex(0)); - if (type_sp) - { - // Resolve the clang type so that any forward references - // to types that haven't yet been parsed will get parsed. - type_sp->GetFullCompilerType (); - type_sp->GetDescription (&strm, eDescriptionLevelFull, true); - // Print all typedef chains - TypeSP typedef_type_sp (type_sp); - TypeSP typedefed_type_sp (typedef_type_sp->GetTypedefType()); - while (typedefed_type_sp) - { - strm.EOL(); - strm.Printf(" typedef '%s': ", typedef_type_sp->GetName().GetCString()); - typedefed_type_sp->GetFullCompilerType (); - typedefed_type_sp->GetDescription (&strm, eDescriptionLevelFull, true); - typedef_type_sp = typedefed_type_sp; - typedefed_type_sp = typedef_type_sp->GetTypedefType(); - } + llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; + num_matches = + module->FindTypes(sc, name, name_is_fully_qualified, max_num_matches, + searched_symbol_files, type_list); + + if (num_matches) { + strm.Indent(); + strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches, + num_matches > 1 ? "es" : ""); + DumpFullpath(strm, &module->GetFileSpec(), 0); + strm.PutCString(":\n"); + for (TypeSP type_sp : type_list.Types()) { + if (type_sp) { + // Resolve the clang type so that any forward references + // to types that haven't yet been parsed will get parsed. + type_sp->GetFullCompilerType(); + type_sp->GetDescription(&strm, eDescriptionLevelFull, true); + // Print all typedef chains + TypeSP typedef_type_sp(type_sp); + TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType()); + while (typedefed_type_sp) { + strm.EOL(); + strm.Printf(" typedef '%s': ", + typedef_type_sp->GetName().GetCString()); + typedefed_type_sp->GetFullCompilerType(); + typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, + true); + typedef_type_sp = typedefed_type_sp; + typedefed_type_sp = typedef_type_sp->GetTypedefType(); + } } strm.EOL(); + } } return num_matches; + } + return 0; } -static uint32_t -LookupFileAndLineInModule (CommandInterpreter &interpreter, - Stream &strm, - Module *module, - const FileSpec &file_spec, - uint32_t line, - bool check_inlines, - bool verbose) -{ - if (module && file_spec) - { - SymbolContextList sc_list; - const uint32_t num_matches = module->ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines, - eSymbolContextEverything, sc_list); - if (num_matches > 0) - { - strm.Indent (); - strm.Printf("%u match%s found in ", num_matches, num_matches > 1 ? "es" : ""); - strm << file_spec; - if (line > 0) - strm.Printf (":%u", line); - strm << " in "; - DumpFullpath (strm, &module->GetFileSpec(), 0); - strm.PutCString(":\n"); - DumpSymbolContextList (interpreter.GetExecutionContext().GetBestExecutionContextScope(), strm, sc_list, verbose); - return num_matches; - } - } +static size_t LookupTypeHere(CommandInterpreter &interpreter, Stream &strm, + const SymbolContext &sym_ctx, + const char *name_cstr, bool name_is_regex) { + if (!sym_ctx.module_sp) return 0; + + TypeList type_list; + const uint32_t max_num_matches = UINT32_MAX; + size_t num_matches = 1; + bool name_is_fully_qualified = false; + + ConstString name(name_cstr); + llvm::DenseSet<SymbolFile *> searched_symbol_files; + num_matches = sym_ctx.module_sp->FindTypes( + sym_ctx, name, name_is_fully_qualified, max_num_matches, + searched_symbol_files, type_list); + + if (num_matches) { + strm.Indent(); + strm.PutCString("Best match found in "); + DumpFullpath(strm, &sym_ctx.module_sp->GetFileSpec(), 0); + strm.PutCString(":\n"); + + TypeSP type_sp(type_list.GetTypeAtIndex(0)); + if (type_sp) { + // Resolve the clang type so that any forward references + // to types that haven't yet been parsed will get parsed. + type_sp->GetFullCompilerType(); + type_sp->GetDescription(&strm, eDescriptionLevelFull, true); + // Print all typedef chains + TypeSP typedef_type_sp(type_sp); + TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType()); + while (typedefed_type_sp) { + strm.EOL(); + strm.Printf(" typedef '%s': ", + typedef_type_sp->GetName().GetCString()); + typedefed_type_sp->GetFullCompilerType(); + typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true); + typedef_type_sp = typedefed_type_sp; + typedefed_type_sp = typedef_type_sp->GetTypedefType(); + } + } + strm.EOL(); + } + return num_matches; } -static size_t -FindModulesByName (Target *target, - const char *module_name, - ModuleList &module_list, - bool check_global_list) -{ - FileSpec module_file_spec(module_name, false); - ModuleSpec module_spec (module_file_spec); - - const size_t initial_size = module_list.GetSize (); - - if (check_global_list) - { - // Check the global list - std::lock_guard<std::recursive_mutex> guard(Module::GetAllocationModuleCollectionMutex()); - const size_t num_modules = Module::GetNumberAllocatedModules(); - ModuleSP module_sp; - for (size_t image_idx = 0; image_idx<num_modules; ++image_idx) - { - Module *module = Module::GetAllocatedModuleAtIndex(image_idx); - - if (module) - { - if (module->MatchesModuleSpec (module_spec)) - { - module_sp = module->shared_from_this(); - module_list.AppendIfNeeded(module_sp); - } - } - } +static uint32_t LookupFileAndLineInModule(CommandInterpreter &interpreter, + Stream &strm, Module *module, + const FileSpec &file_spec, + uint32_t line, bool check_inlines, + bool verbose) { + if (module && file_spec) { + SymbolContextList sc_list; + const uint32_t num_matches = module->ResolveSymbolContextsForFileSpec( + file_spec, line, check_inlines, eSymbolContextEverything, sc_list); + if (num_matches > 0) { + strm.Indent(); + strm.Printf("%u match%s found in ", num_matches, + num_matches > 1 ? "es" : ""); + strm << file_spec; + if (line > 0) + strm.Printf(":%u", line); + strm << " in "; + DumpFullpath(strm, &module->GetFileSpec(), 0); + strm.PutCString(":\n"); + DumpSymbolContextList( + interpreter.GetExecutionContext().GetBestExecutionContextScope(), + strm, sc_list, verbose); + return num_matches; } - else - { - if (target) - { - const size_t num_matches = target->GetImages().FindModules (module_spec, module_list); + } + return 0; +} - // Not found in our module list for our target, check the main - // shared module list in case it is a extra file used somewhere - // else - if (num_matches == 0) - { - module_spec.GetArchitecture() = target->GetArchitecture(); - ModuleList::FindSharedModules (module_spec, module_list); - } - } - else - { - ModuleList::FindSharedModules (module_spec,module_list); +static size_t FindModulesByName(Target *target, const char *module_name, + ModuleList &module_list, + bool check_global_list) { + FileSpec module_file_spec(module_name, false); + ModuleSpec module_spec(module_file_spec); + + const size_t initial_size = module_list.GetSize(); + + if (check_global_list) { + // Check the global list + std::lock_guard<std::recursive_mutex> guard( + Module::GetAllocationModuleCollectionMutex()); + const size_t num_modules = Module::GetNumberAllocatedModules(); + ModuleSP module_sp; + for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { + Module *module = Module::GetAllocatedModuleAtIndex(image_idx); + + if (module) { + if (module->MatchesModuleSpec(module_spec)) { + module_sp = module->shared_from_this(); + module_list.AppendIfNeeded(module_sp); } + } + } + } else { + if (target) { + const size_t num_matches = + target->GetImages().FindModules(module_spec, module_list); + + // Not found in our module list for our target, check the main + // shared module list in case it is a extra file used somewhere + // else + if (num_matches == 0) { + module_spec.GetArchitecture() = target->GetArchitecture(); + ModuleList::FindSharedModules(module_spec, module_list); + } + } else { + ModuleList::FindSharedModules(module_spec, module_list); } + } - return module_list.GetSize () - initial_size; + return module_list.GetSize() - initial_size; } #pragma mark CommandObjectTargetModulesModuleAutoComplete @@ -2029,55 +1780,47 @@ FindModulesByName (Target *target, // paths //---------------------------------------------------------------------- -class CommandObjectTargetModulesModuleAutoComplete : public CommandObjectParsed -{ +class CommandObjectTargetModulesModuleAutoComplete + : public CommandObjectParsed { public: - CommandObjectTargetModulesModuleAutoComplete (CommandInterpreter &interpreter, - const char *name, - const char *help, - const char *syntax) : - CommandObjectParsed (interpreter, name, help, syntax) - { - CommandArgumentEntry arg; - CommandArgumentData file_arg; - - // Define the first (and only) variant of this arg. - file_arg.arg_type = eArgTypeFilename; - file_arg.arg_repetition = eArgRepeatStar; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (file_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - } - - ~CommandObjectTargetModulesModuleAutoComplete() override = default; - - int - HandleArgumentCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - OptionElementVector &opt_element_vector, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) override - { - // Arguments are the standard module completer. - std::string completion_str (input.GetArgumentAtIndex(cursor_index)); - completion_str.erase (cursor_char_position); - - CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(), - CommandCompletions::eModuleCompletion, - completion_str.c_str(), - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - return matches.GetSize(); - } + CommandObjectTargetModulesModuleAutoComplete(CommandInterpreter &interpreter, + const char *name, + const char *help, + const char *syntax) + : CommandObjectParsed(interpreter, name, help, syntax) { + CommandArgumentEntry arg; + CommandArgumentData file_arg; + + // Define the first (and only) variant of this arg. + file_arg.arg_type = eArgTypeFilename; + file_arg.arg_repetition = eArgRepeatStar; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(file_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectTargetModulesModuleAutoComplete() override = default; + + int HandleArgumentCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, int max_return_elements, + bool &word_complete, + StringList &matches) override { + // Arguments are the standard module completer. + std::string completion_str(input.GetArgumentAtIndex(cursor_index)); + completion_str.erase(cursor_char_position); + + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eModuleCompletion, + completion_str.c_str(), match_start_point, max_return_elements, nullptr, + word_complete, matches); + return matches.GetSize(); + } }; #pragma mark CommandObjectTargetModulesSourceFileAutoComplete @@ -2087,311 +1830,260 @@ public: // file paths //---------------------------------------------------------------------- -class CommandObjectTargetModulesSourceFileAutoComplete : public CommandObjectParsed -{ +class CommandObjectTargetModulesSourceFileAutoComplete + : public CommandObjectParsed { public: - CommandObjectTargetModulesSourceFileAutoComplete (CommandInterpreter &interpreter, - const char *name, - const char *help, - const char *syntax, - uint32_t flags) : - CommandObjectParsed (interpreter, name, help, syntax, flags) - { - CommandArgumentEntry arg; - CommandArgumentData source_file_arg; - - // Define the first (and only) variant of this arg. - source_file_arg.arg_type = eArgTypeSourceFile; - source_file_arg.arg_repetition = eArgRepeatPlus; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (source_file_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - } - - ~CommandObjectTargetModulesSourceFileAutoComplete() override = default; - - int - HandleArgumentCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - OptionElementVector &opt_element_vector, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) override - { - // Arguments are the standard source file completer. - std::string completion_str (input.GetArgumentAtIndex(cursor_index)); - completion_str.erase (cursor_char_position); - - CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(), - CommandCompletions::eSourceFileCompletion, - completion_str.c_str(), - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - return matches.GetSize(); - } + CommandObjectTargetModulesSourceFileAutoComplete( + CommandInterpreter &interpreter, const char *name, const char *help, + const char *syntax, uint32_t flags) + : CommandObjectParsed(interpreter, name, help, syntax, flags) { + CommandArgumentEntry arg; + CommandArgumentData source_file_arg; + + // Define the first (and only) variant of this arg. + source_file_arg.arg_type = eArgTypeSourceFile; + source_file_arg.arg_repetition = eArgRepeatPlus; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(source_file_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectTargetModulesSourceFileAutoComplete() override = default; + + int HandleArgumentCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, int max_return_elements, + bool &word_complete, + StringList &matches) override { + // Arguments are the standard source file completer. + std::string completion_str(input.GetArgumentAtIndex(cursor_index)); + completion_str.erase(cursor_char_position); + + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eSourceFileCompletion, + completion_str.c_str(), match_start_point, max_return_elements, nullptr, + word_complete, matches); + return matches.GetSize(); + } }; #pragma mark CommandObjectTargetModulesDumpObjfile -class CommandObjectTargetModulesDumpObjfile : public CommandObjectTargetModulesModuleAutoComplete -{ +class CommandObjectTargetModulesDumpObjfile + : public CommandObjectTargetModulesModuleAutoComplete { public: - CommandObjectTargetModulesDumpObjfile(CommandInterpreter &interpreter) - : CommandObjectTargetModulesModuleAutoComplete(interpreter, "target modules dump objfile", - "Dump the object file headers from one or more target modules.", - nullptr) - { - } + CommandObjectTargetModulesDumpObjfile(CommandInterpreter &interpreter) + : CommandObjectTargetModulesModuleAutoComplete( + interpreter, "target modules dump objfile", + "Dump the object file headers from one or more target modules.", + nullptr) {} - ~CommandObjectTargetModulesDumpObjfile() override = default; + ~CommandObjectTargetModulesDumpObjfile() override = default; protected: - bool - DoExecute(Args &command, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) - { - result.AppendError("invalid target, create a debug target using the 'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (target == nullptr) { + result.AppendError("invalid target, create a debug target using the " + "'target create' command"); + result.SetStatus(eReturnStatusFailed); + return false; + } - uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); - result.GetOutputStream().SetAddressByteSize(addr_byte_size); - result.GetErrorStream().SetAddressByteSize(addr_byte_size); + uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); + result.GetOutputStream().SetAddressByteSize(addr_byte_size); + result.GetErrorStream().SetAddressByteSize(addr_byte_size); - size_t num_dumped = 0; - if (command.GetArgumentCount() == 0) - { - // Dump all headers for all modules images - num_dumped = DumpModuleObjfileHeaders(result.GetOutputStream(), target->GetImages()); - if (num_dumped == 0) - { - result.AppendError("the target has no associated executable images"); - result.SetStatus(eReturnStatusFailed); - } - } - else - { - // Find the modules that match the basename or full path. - ModuleList module_list; - const char *arg_cstr; - for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; ++arg_idx) - { - size_t num_matched = FindModulesByName(target, arg_cstr, module_list, true); - if (num_matched == 0) - { - result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr); - } - } - // Dump all the modules we found. - num_dumped = DumpModuleObjfileHeaders(result.GetOutputStream(), module_list); + size_t num_dumped = 0; + if (command.GetArgumentCount() == 0) { + // Dump all headers for all modules images + num_dumped = DumpModuleObjfileHeaders(result.GetOutputStream(), + target->GetImages()); + if (num_dumped == 0) { + result.AppendError("the target has no associated executable images"); + result.SetStatus(eReturnStatusFailed); + } + } else { + // Find the modules that match the basename or full path. + ModuleList module_list; + const char *arg_cstr; + for (int arg_idx = 0; + (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; + ++arg_idx) { + size_t num_matched = + FindModulesByName(target, arg_cstr, module_list, true); + if (num_matched == 0) { + result.AppendWarningWithFormat( + "Unable to find an image that matches '%s'.\n", arg_cstr); } + } + // Dump all the modules we found. + num_dumped = + DumpModuleObjfileHeaders(result.GetOutputStream(), module_list); + } - if (num_dumped > 0) - { - result.SetStatus(eReturnStatusSuccessFinishResult); - } - else - { - result.AppendError("no matching executable images found"); - result.SetStatus(eReturnStatusFailed); - } - return result.Succeeded(); + if (num_dumped > 0) { + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendError("no matching executable images found"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } }; #pragma mark CommandObjectTargetModulesDumpSymtab -class CommandObjectTargetModulesDumpSymtab : public CommandObjectTargetModulesModuleAutoComplete -{ +class CommandObjectTargetModulesDumpSymtab + : public CommandObjectTargetModulesModuleAutoComplete { public: - CommandObjectTargetModulesDumpSymtab (CommandInterpreter &interpreter) : - CommandObjectTargetModulesModuleAutoComplete(interpreter, - "target modules dump symtab", - "Dump the symbol table from one or more target modules.", - nullptr), - m_options() - { + CommandObjectTargetModulesDumpSymtab(CommandInterpreter &interpreter) + : CommandObjectTargetModulesModuleAutoComplete( + interpreter, "target modules dump symtab", + "Dump the symbol table from one or more target modules.", nullptr), + m_options() {} + + ~CommandObjectTargetModulesDumpSymtab() override = default; + + Options *GetOptions() override { return &m_options; } + + class CommandOptions : public Options { + public: + CommandOptions() : Options(), m_sort_order(eSortOrderNone) {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 's': + m_sort_order = (SortOrder)Args::StringToOptionEnum( + option_arg, g_option_table[option_idx].enum_values, eSortOrderNone, + error); + break; + + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", + short_option); + break; + } + return error; } - ~CommandObjectTargetModulesDumpSymtab() override = default; - - Options * - GetOptions () override - { - return &m_options; + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_sort_order = eSortOrderNone; } - class CommandOptions : public Options - { - public: - CommandOptions() : - Options(), - m_sort_order(eSortOrderNone) - { - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 's': - m_sort_order = (SortOrder) Args::StringToOptionEnum (option_arg, - g_option_table[option_idx].enum_values, - eSortOrderNone, - error); - break; - - default: - error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); - break; - } - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_sort_order = eSortOrderNone; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } + // Options table: Required for subclasses of Options. + static OptionDefinition g_option_table[]; - // Options table: Required for subclasses of Options. - static OptionDefinition g_option_table[]; - - SortOrder m_sort_order; - }; + SortOrder m_sort_order; + }; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) - { - result.AppendError ("invalid target, create a debug target using the 'target create' command"); - result.SetStatus (eReturnStatusFailed); - return false; - } - else - { - uint32_t num_dumped = 0; - - uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); - result.GetOutputStream().SetAddressByteSize(addr_byte_size); - result.GetErrorStream().SetAddressByteSize(addr_byte_size); - - if (command.GetArgumentCount() == 0) - { - // Dump all sections for all modules images - std::lock_guard<std::recursive_mutex> guard(target->GetImages().GetMutex()); - const size_t num_modules = target->GetImages().GetSize(); - if (num_modules > 0) - { - result.GetOutputStream().Printf("Dumping symbol table for %" PRIu64 " modules.\n", (uint64_t)num_modules); - for (size_t image_idx = 0; image_idx<num_modules; ++image_idx) - { - if (num_dumped > 0) - { - result.GetOutputStream().EOL(); - result.GetOutputStream().EOL(); - } - num_dumped++; - DumpModuleSymtab (m_interpreter, - result.GetOutputStream(), - target->GetImages().GetModulePointerAtIndexUnlocked(image_idx), - m_options.m_sort_order); - } - } - else - { - result.AppendError ("the target has no associated executable images"); - result.SetStatus (eReturnStatusFailed); - return false; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (target == nullptr) { + result.AppendError("invalid target, create a debug target using the " + "'target create' command"); + result.SetStatus(eReturnStatusFailed); + return false; + } else { + uint32_t num_dumped = 0; + + uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); + result.GetOutputStream().SetAddressByteSize(addr_byte_size); + result.GetErrorStream().SetAddressByteSize(addr_byte_size); + + if (command.GetArgumentCount() == 0) { + // Dump all sections for all modules images + std::lock_guard<std::recursive_mutex> guard( + target->GetImages().GetMutex()); + const size_t num_modules = target->GetImages().GetSize(); + if (num_modules > 0) { + result.GetOutputStream().Printf("Dumping symbol table for %" PRIu64 + " modules.\n", + (uint64_t)num_modules); + for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { + if (num_dumped > 0) { + result.GetOutputStream().EOL(); + result.GetOutputStream().EOL(); } - else - { - // Dump specified images (by basename or fullpath) - const char *arg_cstr; - for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; ++arg_idx) - { - ModuleList module_list; - const size_t num_matches = FindModulesByName (target, arg_cstr, module_list, true); - if (num_matches > 0) - { - for (size_t i = 0; i < num_matches; ++i) - { - Module *module = module_list.GetModulePointerAtIndex(i); - if (module) - { - if (num_dumped > 0) - { - result.GetOutputStream().EOL(); - result.GetOutputStream().EOL(); - } - num_dumped++; - DumpModuleSymtab (m_interpreter, result.GetOutputStream(), module, m_options.m_sort_order); - } - } - } - else - result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr); + num_dumped++; + DumpModuleSymtab( + m_interpreter, result.GetOutputStream(), + target->GetImages().GetModulePointerAtIndexUnlocked(image_idx), + m_options.m_sort_order); + } + } else { + result.AppendError("the target has no associated executable images"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + // Dump specified images (by basename or fullpath) + const char *arg_cstr; + for (int arg_idx = 0; + (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; + ++arg_idx) { + ModuleList module_list; + const size_t num_matches = + FindModulesByName(target, arg_cstr, module_list, true); + if (num_matches > 0) { + for (size_t i = 0; i < num_matches; ++i) { + Module *module = module_list.GetModulePointerAtIndex(i); + if (module) { + if (num_dumped > 0) { + result.GetOutputStream().EOL(); + result.GetOutputStream().EOL(); } + num_dumped++; + DumpModuleSymtab(m_interpreter, result.GetOutputStream(), + module, m_options.m_sort_order); + } } - - if (num_dumped > 0) - result.SetStatus (eReturnStatusSuccessFinishResult); - else - { - result.AppendError ("no matching executable images found"); - result.SetStatus (eReturnStatusFailed); - } + } else + result.AppendWarningWithFormat( + "Unable to find an image that matches '%s'.\n", arg_cstr); } - return result.Succeeded(); + } + + if (num_dumped > 0) + result.SetStatus(eReturnStatusSuccessFinishResult); + else { + result.AppendError("no matching executable images found"); + result.SetStatus(eReturnStatusFailed); + } } + return result.Succeeded(); + } - CommandOptions m_options; + CommandOptions m_options; }; -static OptionEnumValueElement -g_sort_option_enumeration[4] = -{ - { eSortOrderNone, "none", "No sorting, use the original symbol table order."}, - { eSortOrderByAddress, "address", "Sort output by symbol address."}, - { eSortOrderByName, "name", "Sort output by symbol name."}, - { 0, nullptr, nullptr } -}; +static OptionEnumValueElement g_sort_option_enumeration[4] = { + {eSortOrderNone, "none", + "No sorting, use the original symbol table order."}, + {eSortOrderByAddress, "address", "Sort output by symbol address."}, + {eSortOrderByName, "name", "Sort output by symbol name."}, + {0, nullptr, nullptr}}; OptionDefinition -CommandObjectTargetModulesDumpSymtab::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectTargetModulesDumpSymtab::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "sort", 's', OptionParser::eRequiredArgument, nullptr, g_sort_option_enumeration, 0, eArgTypeSortOrder, "Supply a sort order when dumping the symbol table."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; #pragma mark CommandObjectTargetModulesDumpSections @@ -2400,99 +2092,89 @@ CommandObjectTargetModulesDumpSymtab::CommandOptions::g_option_table[] = // Image section dumping command //---------------------------------------------------------------------- -class CommandObjectTargetModulesDumpSections : public CommandObjectTargetModulesModuleAutoComplete -{ +class CommandObjectTargetModulesDumpSections + : public CommandObjectTargetModulesModuleAutoComplete { public: - CommandObjectTargetModulesDumpSections (CommandInterpreter &interpreter) : - CommandObjectTargetModulesModuleAutoComplete(interpreter, - "target modules dump sections", - "Dump the sections from one or more target modules.", - //"target modules dump sections [<file1> ...]") - nullptr) - { - } + CommandObjectTargetModulesDumpSections(CommandInterpreter &interpreter) + : CommandObjectTargetModulesModuleAutoComplete( + interpreter, "target modules dump sections", + "Dump the sections from one or more target modules.", + //"target modules dump sections [<file1> ...]") + nullptr) {} - ~CommandObjectTargetModulesDumpSections() override = default; + ~CommandObjectTargetModulesDumpSections() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) - { - result.AppendError ("invalid target, create a debug target using the 'target create' command"); - result.SetStatus (eReturnStatusFailed); - return false; + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (target == nullptr) { + result.AppendError("invalid target, create a debug target using the " + "'target create' command"); + result.SetStatus(eReturnStatusFailed); + return false; + } else { + uint32_t num_dumped = 0; + + uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); + result.GetOutputStream().SetAddressByteSize(addr_byte_size); + result.GetErrorStream().SetAddressByteSize(addr_byte_size); + + if (command.GetArgumentCount() == 0) { + // Dump all sections for all modules images + const size_t num_modules = target->GetImages().GetSize(); + if (num_modules > 0) { + result.GetOutputStream().Printf("Dumping sections for %" PRIu64 + " modules.\n", + (uint64_t)num_modules); + for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { + num_dumped++; + DumpModuleSections( + m_interpreter, result.GetOutputStream(), + target->GetImages().GetModulePointerAtIndex(image_idx)); + } + } else { + result.AppendError("the target has no associated executable images"); + result.SetStatus(eReturnStatusFailed); + return false; } - else - { - uint32_t num_dumped = 0; - - uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); - result.GetOutputStream().SetAddressByteSize(addr_byte_size); - result.GetErrorStream().SetAddressByteSize(addr_byte_size); - - if (command.GetArgumentCount() == 0) - { - // Dump all sections for all modules images - const size_t num_modules = target->GetImages().GetSize(); - if (num_modules > 0) - { - result.GetOutputStream().Printf("Dumping sections for %" PRIu64 " modules.\n", (uint64_t)num_modules); - for (size_t image_idx = 0; image_idx<num_modules; ++image_idx) - { - num_dumped++; - DumpModuleSections (m_interpreter, result.GetOutputStream(), target->GetImages().GetModulePointerAtIndex(image_idx)); - } - } - else - { - result.AppendError ("the target has no associated executable images"); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - else - { - // Dump specified images (by basename or fullpath) - const char *arg_cstr; - for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; ++arg_idx) - { - ModuleList module_list; - const size_t num_matches = FindModulesByName (target, arg_cstr, module_list, true); - if (num_matches > 0) - { - for (size_t i = 0; i < num_matches; ++i) - { - Module *module = module_list.GetModulePointerAtIndex(i); - if (module) - { - num_dumped++; - DumpModuleSections (m_interpreter, result.GetOutputStream(), module); - } - } - } - else - { - // Check the global list - std::lock_guard<std::recursive_mutex> guard(Module::GetAllocationModuleCollectionMutex()); - - result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr); - } - } - } - - if (num_dumped > 0) - result.SetStatus (eReturnStatusSuccessFinishResult); - else - { - result.AppendError ("no matching executable images found"); - result.SetStatus (eReturnStatusFailed); + } else { + // Dump specified images (by basename or fullpath) + const char *arg_cstr; + for (int arg_idx = 0; + (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; + ++arg_idx) { + ModuleList module_list; + const size_t num_matches = + FindModulesByName(target, arg_cstr, module_list, true); + if (num_matches > 0) { + for (size_t i = 0; i < num_matches; ++i) { + Module *module = module_list.GetModulePointerAtIndex(i); + if (module) { + num_dumped++; + DumpModuleSections(m_interpreter, result.GetOutputStream(), + module); + } } + } else { + // Check the global list + std::lock_guard<std::recursive_mutex> guard( + Module::GetAllocationModuleCollectionMutex()); + + result.AppendWarningWithFormat( + "Unable to find an image that matches '%s'.\n", arg_cstr); + } } - return result.Succeeded(); + } + + if (num_dumped > 0) + result.SetStatus(eReturnStatusSuccessFinishResult); + else { + result.AppendError("no matching executable images found"); + result.SetStatus(eReturnStatusFailed); + } } + return result.Succeeded(); + } }; #pragma mark CommandObjectTargetModulesDumpSymfile @@ -2501,96 +2183,85 @@ protected: // Image debug symbol dumping command //---------------------------------------------------------------------- -class CommandObjectTargetModulesDumpSymfile : public CommandObjectTargetModulesModuleAutoComplete -{ +class CommandObjectTargetModulesDumpSymfile + : public CommandObjectTargetModulesModuleAutoComplete { public: - CommandObjectTargetModulesDumpSymfile (CommandInterpreter &interpreter) : - CommandObjectTargetModulesModuleAutoComplete(interpreter, - "target modules dump symfile", - "Dump the debug symbol file for one or more target modules.", - //"target modules dump symfile [<file1> ...]") - nullptr) - { - } + CommandObjectTargetModulesDumpSymfile(CommandInterpreter &interpreter) + : CommandObjectTargetModulesModuleAutoComplete( + interpreter, "target modules dump symfile", + "Dump the debug symbol file for one or more target modules.", + //"target modules dump symfile [<file1> ...]") + nullptr) {} - ~CommandObjectTargetModulesDumpSymfile() override = default; + ~CommandObjectTargetModulesDumpSymfile() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) - { - result.AppendError ("invalid target, create a debug target using the 'target create' command"); - result.SetStatus (eReturnStatusFailed); - return false; + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (target == nullptr) { + result.AppendError("invalid target, create a debug target using the " + "'target create' command"); + result.SetStatus(eReturnStatusFailed); + return false; + } else { + uint32_t num_dumped = 0; + + uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); + result.GetOutputStream().SetAddressByteSize(addr_byte_size); + result.GetErrorStream().SetAddressByteSize(addr_byte_size); + + if (command.GetArgumentCount() == 0) { + // Dump all sections for all modules images + const ModuleList &target_modules = target->GetImages(); + std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); + const size_t num_modules = target_modules.GetSize(); + if (num_modules > 0) { + result.GetOutputStream().Printf("Dumping debug symbols for %" PRIu64 + " modules.\n", + (uint64_t)num_modules); + for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) { + if (DumpModuleSymbolVendor( + result.GetOutputStream(), + target_modules.GetModulePointerAtIndexUnlocked(image_idx))) + num_dumped++; + } + } else { + result.AppendError("the target has no associated executable images"); + result.SetStatus(eReturnStatusFailed); + return false; } - else - { - uint32_t num_dumped = 0; - - uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); - result.GetOutputStream().SetAddressByteSize(addr_byte_size); - result.GetErrorStream().SetAddressByteSize(addr_byte_size); - - if (command.GetArgumentCount() == 0) - { - // Dump all sections for all modules images - const ModuleList &target_modules = target->GetImages(); - std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); - const size_t num_modules = target_modules.GetSize(); - if (num_modules > 0) - { - result.GetOutputStream().Printf("Dumping debug symbols for %" PRIu64 " modules.\n", (uint64_t)num_modules); - for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx) - { - if (DumpModuleSymbolVendor (result.GetOutputStream(), target_modules.GetModulePointerAtIndexUnlocked(image_idx))) - num_dumped++; - } - } - else - { - result.AppendError ("the target has no associated executable images"); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - else - { - // Dump specified images (by basename or fullpath) - const char *arg_cstr; - for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; ++arg_idx) - { - ModuleList module_list; - const size_t num_matches = FindModulesByName (target, arg_cstr, module_list, true); - if (num_matches > 0) - { - for (size_t i = 0; i < num_matches; ++i) - { - Module *module = module_list.GetModulePointerAtIndex(i); - if (module) - { - if (DumpModuleSymbolVendor (result.GetOutputStream(), module)) - num_dumped++; - } - } - } - else - result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr); - } - } - - if (num_dumped > 0) - result.SetStatus (eReturnStatusSuccessFinishResult); - else - { - result.AppendError ("no matching executable images found"); - result.SetStatus (eReturnStatusFailed); + } else { + // Dump specified images (by basename or fullpath) + const char *arg_cstr; + for (int arg_idx = 0; + (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; + ++arg_idx) { + ModuleList module_list; + const size_t num_matches = + FindModulesByName(target, arg_cstr, module_list, true); + if (num_matches > 0) { + for (size_t i = 0; i < num_matches; ++i) { + Module *module = module_list.GetModulePointerAtIndex(i); + if (module) { + if (DumpModuleSymbolVendor(result.GetOutputStream(), module)) + num_dumped++; + } } + } else + result.AppendWarningWithFormat( + "Unable to find an image that matches '%s'.\n", arg_cstr); } - return result.Succeeded(); + } + + if (num_dumped > 0) + result.SetStatus(eReturnStatusSuccessFinishResult); + else { + result.AppendError("no matching executable images found"); + result.SetStatus(eReturnStatusFailed); + } } + return result.Succeeded(); + } }; #pragma mark CommandObjectTargetModulesDumpLineTable @@ -2599,77 +2270,68 @@ protected: // Image debug line table dumping command //---------------------------------------------------------------------- -class CommandObjectTargetModulesDumpLineTable : public CommandObjectTargetModulesSourceFileAutoComplete -{ +class CommandObjectTargetModulesDumpLineTable + : public CommandObjectTargetModulesSourceFileAutoComplete { public: - CommandObjectTargetModulesDumpLineTable (CommandInterpreter &interpreter) : - CommandObjectTargetModulesSourceFileAutoComplete(interpreter, - "target modules dump line-table", - "Dump the line table for one or more compilation units.", - nullptr, - eCommandRequiresTarget) - { - } + CommandObjectTargetModulesDumpLineTable(CommandInterpreter &interpreter) + : CommandObjectTargetModulesSourceFileAutoComplete( + interpreter, "target modules dump line-table", + "Dump the line table for one or more compilation units.", nullptr, + eCommandRequiresTarget) {} - ~CommandObjectTargetModulesDumpLineTable() override = default; + ~CommandObjectTargetModulesDumpLineTable() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = m_exe_ctx.GetTargetPtr(); - uint32_t total_num_dumped = 0; - - uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); - result.GetOutputStream().SetAddressByteSize(addr_byte_size); - result.GetErrorStream().SetAddressByteSize(addr_byte_size); - - if (command.GetArgumentCount() == 0) - { - result.AppendError ("file option must be specified."); - result.SetStatus (eReturnStatusFailed); - return result.Succeeded(); - } - else - { - // Dump specified images (by basename or fullpath) - const char *arg_cstr; - for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; ++arg_idx) - { - FileSpec file_spec(arg_cstr, false); - - const ModuleList &target_modules = target->GetImages(); - std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); - const size_t num_modules = target_modules.GetSize(); - if (num_modules > 0) - { - uint32_t num_dumped = 0; - for (uint32_t i = 0; i<num_modules; ++i) - { - if (DumpCompileUnitLineTable (m_interpreter, - result.GetOutputStream(), - target_modules.GetModulePointerAtIndexUnlocked(i), - file_spec, - m_exe_ctx.GetProcessPtr() && m_exe_ctx.GetProcessRef().IsAlive())) - num_dumped++; - } - if (num_dumped == 0) - result.AppendWarningWithFormat ("No source filenames matched '%s'.\n", arg_cstr); - else - total_num_dumped += num_dumped; - } - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_exe_ctx.GetTargetPtr(); + uint32_t total_num_dumped = 0; + + uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); + result.GetOutputStream().SetAddressByteSize(addr_byte_size); + result.GetErrorStream().SetAddressByteSize(addr_byte_size); + + if (command.GetArgumentCount() == 0) { + result.AppendError("file option must be specified."); + result.SetStatus(eReturnStatusFailed); + return result.Succeeded(); + } else { + // Dump specified images (by basename or fullpath) + const char *arg_cstr; + for (int arg_idx = 0; + (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; + ++arg_idx) { + FileSpec file_spec(arg_cstr, false); + + const ModuleList &target_modules = target->GetImages(); + std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); + const size_t num_modules = target_modules.GetSize(); + if (num_modules > 0) { + uint32_t num_dumped = 0; + for (uint32_t i = 0; i < num_modules; ++i) { + if (DumpCompileUnitLineTable( + m_interpreter, result.GetOutputStream(), + target_modules.GetModulePointerAtIndexUnlocked(i), + file_spec, m_exe_ctx.GetProcessPtr() && + m_exe_ctx.GetProcessRef().IsAlive())) + num_dumped++; + } + if (num_dumped == 0) + result.AppendWarningWithFormat( + "No source filenames matched '%s'.\n", arg_cstr); + else + total_num_dumped += num_dumped; } + } + } - if (total_num_dumped > 0) - result.SetStatus (eReturnStatusSuccessFinishResult); - else - { - result.AppendError ("no source filenames matched any command arguments"); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + if (total_num_dumped > 0) + result.SetStatus(eReturnStatusSuccessFinishResult); + else { + result.AppendError("no source filenames matched any command arguments"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } }; #pragma mark CommandObjectTargetModulesDump @@ -2678,889 +2340,784 @@ protected: // Dump multi-word command for target modules //---------------------------------------------------------------------- -class CommandObjectTargetModulesDump : public CommandObjectMultiword -{ +class CommandObjectTargetModulesDump : public CommandObjectMultiword { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - CommandObjectTargetModulesDump(CommandInterpreter &interpreter) - : CommandObjectMultiword( - interpreter, "target modules dump", "Commands for dumping information about one or more target modules.", - "target modules dump [headers|symtab|sections|symfile|line-table] [<file1> <file2> ...]") - { - LoadSubCommand("objfile", CommandObjectSP(new CommandObjectTargetModulesDumpObjfile(interpreter))); - LoadSubCommand ("symtab", CommandObjectSP (new CommandObjectTargetModulesDumpSymtab (interpreter))); - LoadSubCommand ("sections", CommandObjectSP (new CommandObjectTargetModulesDumpSections (interpreter))); - LoadSubCommand ("symfile", CommandObjectSP (new CommandObjectTargetModulesDumpSymfile (interpreter))); - LoadSubCommand ("line-table", CommandObjectSP (new CommandObjectTargetModulesDumpLineTable (interpreter))); - } - - ~CommandObjectTargetModulesDump() override = default; + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + CommandObjectTargetModulesDump(CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "target modules dump", + "Commands for dumping information about one or " + "more target modules.", + "target modules dump " + "[headers|symtab|sections|symfile|line-table] " + "[<file1> <file2> ...]") { + LoadSubCommand("objfile", + CommandObjectSP( + new CommandObjectTargetModulesDumpObjfile(interpreter))); + LoadSubCommand( + "symtab", + CommandObjectSP(new CommandObjectTargetModulesDumpSymtab(interpreter))); + LoadSubCommand("sections", + CommandObjectSP(new CommandObjectTargetModulesDumpSections( + interpreter))); + LoadSubCommand("symfile", + CommandObjectSP( + new CommandObjectTargetModulesDumpSymfile(interpreter))); + LoadSubCommand("line-table", + CommandObjectSP(new CommandObjectTargetModulesDumpLineTable( + interpreter))); + } + + ~CommandObjectTargetModulesDump() override = default; }; -class CommandObjectTargetModulesAdd : public CommandObjectParsed -{ +class CommandObjectTargetModulesAdd : public CommandObjectParsed { public: - CommandObjectTargetModulesAdd (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "target modules add", - "Add a new module to the current target's modules.", - "target modules add [<module>]"), + CommandObjectTargetModulesAdd(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "target modules add", + "Add a new module to the current target's modules.", + "target modules add [<module>]"), m_option_group(), - m_symbol_file (LLDB_OPT_SET_1, false, "symfile", 's', 0, eArgTypeFilename, "Fullpath to a stand alone debug symbols file for when debug symbols are not in the executable.") - { - m_option_group.Append (&m_uuid_option_group, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Append (&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Finalize(); - } - - ~CommandObjectTargetModulesAdd() override = default; - - Options * - GetOptions () override - { - return &m_option_group; - } - - int - HandleArgumentCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - OptionElementVector &opt_element_vector, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) override - { - std::string completion_str (input.GetArgumentAtIndex(cursor_index)); - completion_str.erase (cursor_char_position); - - CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(), - CommandCompletions::eDiskFileCompletion, - completion_str.c_str(), - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - return matches.GetSize(); - } + m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0, + eArgTypeFilename, "Fullpath to a stand alone debug " + "symbols file for when debug symbols " + "are not in the executable.") { + m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL, + LLDB_OPT_SET_1); + m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Finalize(); + } + + ~CommandObjectTargetModulesAdd() override = default; + + Options *GetOptions() override { return &m_option_group; } + + int HandleArgumentCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, int max_return_elements, + bool &word_complete, + StringList &matches) override { + std::string completion_str(input.GetArgumentAtIndex(cursor_index)); + completion_str.erase(cursor_char_position); + + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, + completion_str.c_str(), match_start_point, max_return_elements, nullptr, + word_complete, matches); + return matches.GetSize(); + } protected: - OptionGroupOptions m_option_group; - OptionGroupUUID m_uuid_option_group; - OptionGroupFile m_symbol_file; - - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) - { - result.AppendError ("invalid target, create a debug target using the 'target create' command"); - result.SetStatus (eReturnStatusFailed); + OptionGroupOptions m_option_group; + OptionGroupUUID m_uuid_option_group; + OptionGroupFile m_symbol_file; + + bool DoExecute(Args &args, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (target == nullptr) { + result.AppendError("invalid target, create a debug target using the " + "'target create' command"); + result.SetStatus(eReturnStatusFailed); + return false; + } else { + bool flush = false; + + const size_t argc = args.GetArgumentCount(); + if (argc == 0) { + if (m_uuid_option_group.GetOptionValue().OptionWasSet()) { + // We are given a UUID only, go locate the file + ModuleSpec module_spec; + module_spec.GetUUID() = + m_uuid_option_group.GetOptionValue().GetCurrentValue(); + if (m_symbol_file.GetOptionValue().OptionWasSet()) + module_spec.GetSymbolFileSpec() = + m_symbol_file.GetOptionValue().GetCurrentValue(); + if (Symbols::DownloadObjectAndSymbolFile(module_spec)) { + ModuleSP module_sp(target->GetSharedModule(module_spec)); + if (module_sp) { + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } else { + StreamString strm; + module_spec.GetUUID().Dump(&strm); + if (module_spec.GetFileSpec()) { + if (module_spec.GetSymbolFileSpec()) { + result.AppendErrorWithFormat( + "Unable to create the executable or symbol file with " + "UUID %s with path %s and symbol file %s", + strm.GetString().c_str(), + module_spec.GetFileSpec().GetPath().c_str(), + module_spec.GetSymbolFileSpec().GetPath().c_str()); + } else { + result.AppendErrorWithFormat( + "Unable to create the executable or symbol file with " + "UUID %s with path %s", + strm.GetString().c_str(), + module_spec.GetFileSpec().GetPath().c_str()); + } + } else { + result.AppendErrorWithFormat("Unable to create the executable " + "or symbol file with UUID %s", + strm.GetString().c_str()); + } + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + StreamString strm; + module_spec.GetUUID().Dump(&strm); + result.AppendErrorWithFormat( + "Unable to locate the executable or symbol file with UUID %s", + strm.GetString().c_str()); + result.SetStatus(eReturnStatusFailed); return false; + } + } else { + result.AppendError( + "one or more executable image paths must be specified"); + result.SetStatus(eReturnStatusFailed); + return false; } - else - { - bool flush = false; - - const size_t argc = args.GetArgumentCount(); - if (argc == 0) - { - if (m_uuid_option_group.GetOptionValue ().OptionWasSet()) - { - // We are given a UUID only, go locate the file - ModuleSpec module_spec; - module_spec.GetUUID() = m_uuid_option_group.GetOptionValue ().GetCurrentValue(); - if (m_symbol_file.GetOptionValue().OptionWasSet()) - module_spec.GetSymbolFileSpec() = m_symbol_file.GetOptionValue().GetCurrentValue(); - if (Symbols::DownloadObjectAndSymbolFile (module_spec)) - { - ModuleSP module_sp (target->GetSharedModule (module_spec)); - if (module_sp) - { - result.SetStatus (eReturnStatusSuccessFinishResult); - return true; - } - else - { - StreamString strm; - module_spec.GetUUID().Dump (&strm); - if (module_spec.GetFileSpec()) - { - if (module_spec.GetSymbolFileSpec()) - { - result.AppendErrorWithFormat ("Unable to create the executable or symbol file with UUID %s with path %s and symbol file %s", - strm.GetString().c_str(), - module_spec.GetFileSpec().GetPath().c_str(), - module_spec.GetSymbolFileSpec().GetPath().c_str()); - } - else - { - result.AppendErrorWithFormat ("Unable to create the executable or symbol file with UUID %s with path %s", - strm.GetString().c_str(), - module_spec.GetFileSpec().GetPath().c_str()); - } - } - else - { - result.AppendErrorWithFormat ("Unable to create the executable or symbol file with UUID %s", - strm.GetString().c_str()); - } - result.SetStatus (eReturnStatusFailed); - return false; - } - } - else - { - StreamString strm; - module_spec.GetUUID().Dump (&strm); - result.AppendErrorWithFormat ("Unable to locate the executable or symbol file with UUID %s", strm.GetString().c_str()); - result.SetStatus (eReturnStatusFailed); - return false; - } - } + } else { + for (size_t i = 0; i < argc; ++i) { + const char *path = args.GetArgumentAtIndex(i); + if (path) { + FileSpec file_spec(path, true); + if (file_spec.Exists()) { + ModuleSpec module_spec(file_spec); + if (m_uuid_option_group.GetOptionValue().OptionWasSet()) + module_spec.GetUUID() = + m_uuid_option_group.GetOptionValue().GetCurrentValue(); + if (m_symbol_file.GetOptionValue().OptionWasSet()) + module_spec.GetSymbolFileSpec() = + m_symbol_file.GetOptionValue().GetCurrentValue(); + if (!module_spec.GetArchitecture().IsValid()) + module_spec.GetArchitecture() = target->GetArchitecture(); + Error error; + ModuleSP module_sp(target->GetSharedModule(module_spec, &error)); + if (!module_sp) { + const char *error_cstr = error.AsCString(); + if (error_cstr) + result.AppendError(error_cstr); else - { - result.AppendError ("one or more executable image paths must be specified"); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - else - { - for (size_t i = 0; i < argc; ++i) - { - const char *path = args.GetArgumentAtIndex(i); - if (path) - { - FileSpec file_spec(path, true); - if (file_spec.Exists()) - { - ModuleSpec module_spec (file_spec); - if (m_uuid_option_group.GetOptionValue ().OptionWasSet()) - module_spec.GetUUID() = m_uuid_option_group.GetOptionValue ().GetCurrentValue(); - if (m_symbol_file.GetOptionValue().OptionWasSet()) - module_spec.GetSymbolFileSpec() = m_symbol_file.GetOptionValue().GetCurrentValue(); - if (!module_spec.GetArchitecture().IsValid()) - module_spec.GetArchitecture() = target->GetArchitecture(); - Error error; - ModuleSP module_sp (target->GetSharedModule (module_spec, &error)); - if (!module_sp) - { - const char *error_cstr = error.AsCString(); - if (error_cstr) - result.AppendError (error_cstr); - else - result.AppendErrorWithFormat ("unsupported module: %s", path); - result.SetStatus (eReturnStatusFailed); - return false; - } - else - { - flush = true; - } - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - char resolved_path[PATH_MAX]; - result.SetStatus (eReturnStatusFailed); - if (file_spec.GetPath (resolved_path, sizeof(resolved_path))) - { - if (strcmp (resolved_path, path) != 0) - { - result.AppendErrorWithFormat ("invalid module path '%s' with resolved path '%s'\n", path, resolved_path); - break; - } - } - result.AppendErrorWithFormat ("invalid module path '%s'\n", path); - break; - } - } + result.AppendErrorWithFormat("unsupported module: %s", path); + result.SetStatus(eReturnStatusFailed); + return false; + } else { + flush = true; + } + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + char resolved_path[PATH_MAX]; + result.SetStatus(eReturnStatusFailed); + if (file_spec.GetPath(resolved_path, sizeof(resolved_path))) { + if (strcmp(resolved_path, path) != 0) { + result.AppendErrorWithFormat( + "invalid module path '%s' with resolved path '%s'\n", + path, resolved_path); + break; } + } + result.AppendErrorWithFormat("invalid module path '%s'\n", path); + break; } - - if (flush) - { - ProcessSP process = target->GetProcessSP(); - if (process) - process->Flush(); - } + } } + } - return result.Succeeded(); + if (flush) { + ProcessSP process = target->GetProcessSP(); + if (process) + process->Flush(); + } } + + return result.Succeeded(); + } }; -class CommandObjectTargetModulesLoad : public CommandObjectTargetModulesModuleAutoComplete -{ +class CommandObjectTargetModulesLoad + : public CommandObjectTargetModulesModuleAutoComplete { public: - CommandObjectTargetModulesLoad (CommandInterpreter &interpreter) : - CommandObjectTargetModulesModuleAutoComplete (interpreter, - "target modules load", - "Set the load addresses for one or more sections in a target module.", - "target modules load [--file <module> --uuid <uuid>] <sect-name> <address> [<sect-name> <address> ....]"), + CommandObjectTargetModulesLoad(CommandInterpreter &interpreter) + : CommandObjectTargetModulesModuleAutoComplete( + interpreter, "target modules load", "Set the load addresses for " + "one or more sections in a " + "target module.", + "target modules load [--file <module> --uuid <uuid>] <sect-name> " + "<address> [<sect-name> <address> ....]"), m_option_group(), - m_file_option (LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypeName, "Fullpath or basename for module to load.", ""), - m_slide_option(LLDB_OPT_SET_1, false, "slide", 's', 0, eArgTypeOffset, "Set the load address for all sections to be the virtual address in the file plus the offset.", 0) - { - m_option_group.Append (&m_uuid_option_group, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Append (&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Append (&m_slide_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Finalize(); - } - - ~CommandObjectTargetModulesLoad() override = default; - - Options * - GetOptions () override - { - return &m_option_group; - } + m_file_option(LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypeName, + "Fullpath or basename for module to load.", ""), + m_slide_option(LLDB_OPT_SET_1, false, "slide", 's', 0, eArgTypeOffset, + "Set the load address for all sections to be the " + "virtual address in the file plus the offset.", + 0) { + m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL, + LLDB_OPT_SET_1); + m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append(&m_slide_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Finalize(); + } + + ~CommandObjectTargetModulesLoad() override = default; + + Options *GetOptions() override { return &m_option_group; } protected: - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) - { - result.AppendError ("invalid target, create a debug target using the 'target create' command"); - result.SetStatus (eReturnStatusFailed); - return false; + bool DoExecute(Args &args, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (target == nullptr) { + result.AppendError("invalid target, create a debug target using the " + "'target create' command"); + result.SetStatus(eReturnStatusFailed); + return false; + } else { + const size_t argc = args.GetArgumentCount(); + ModuleSpec module_spec; + bool search_using_module_spec = false; + if (m_file_option.GetOptionValue().OptionWasSet()) { + search_using_module_spec = true; + const char *arg_cstr = m_file_option.GetOptionValue().GetCurrentValue(); + const bool use_global_module_list = true; + ModuleList module_list; + const size_t num_matches = FindModulesByName( + target, arg_cstr, module_list, use_global_module_list); + if (num_matches == 1) { + module_spec.GetFileSpec() = + module_list.GetModuleAtIndex(0)->GetFileSpec(); + } else if (num_matches > 1) { + search_using_module_spec = false; + result.AppendErrorWithFormat( + "more than 1 module matched by name '%s'\n", arg_cstr); + result.SetStatus(eReturnStatusFailed); + } else { + search_using_module_spec = false; + result.AppendErrorWithFormat("no object file for module '%s'\n", + arg_cstr); + result.SetStatus(eReturnStatusFailed); } - else - { - const size_t argc = args.GetArgumentCount(); - ModuleSpec module_spec; - bool search_using_module_spec = false; - if (m_file_option.GetOptionValue().OptionWasSet()) - { - search_using_module_spec = true; - const char *arg_cstr = m_file_option.GetOptionValue().GetCurrentValue(); - const bool use_global_module_list = true; - ModuleList module_list; - const size_t num_matches = FindModulesByName (target, arg_cstr, module_list, use_global_module_list); - if (num_matches == 1) - { - module_spec.GetFileSpec() = module_list.GetModuleAtIndex(0)->GetFileSpec(); - } - else if (num_matches > 1 ) - { - search_using_module_spec = false; - result.AppendErrorWithFormat ("more than 1 module matched by name '%s'\n", arg_cstr); - result.SetStatus (eReturnStatusFailed); - } - else - { - search_using_module_spec = false; - result.AppendErrorWithFormat ("no object file for module '%s'\n", arg_cstr); - result.SetStatus (eReturnStatusFailed); - } - } - - if (m_uuid_option_group.GetOptionValue().OptionWasSet()) - { - search_using_module_spec = true; - module_spec.GetUUID() = m_uuid_option_group.GetOptionValue().GetCurrentValue(); - } - - if (search_using_module_spec) - { - ModuleList matching_modules; - const size_t num_matches = target->GetImages().FindModules (module_spec, matching_modules); - - char path[PATH_MAX]; - if (num_matches == 1) - { - Module *module = matching_modules.GetModulePointerAtIndex(0); - if (module) - { - ObjectFile *objfile = module->GetObjectFile(); - if (objfile) - { - SectionList *section_list = module->GetSectionList(); - if (section_list) - { - bool changed = false; - if (argc == 0) - { - if (m_slide_option.GetOptionValue().OptionWasSet()) - { - const addr_t slide = m_slide_option.GetOptionValue().GetCurrentValue(); - const bool slide_is_offset = true; - module->SetLoadAddress (*target, slide, slide_is_offset, changed); - } - else - { - result.AppendError ("one or more section name + load address pair must be specified"); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - else - { - if (m_slide_option.GetOptionValue().OptionWasSet()) - { - result.AppendError ("The \"--slide <offset>\" option can't be used in conjunction with setting section load addresses.\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - for (size_t i = 0; i < argc; i += 2) - { - const char *sect_name = args.GetArgumentAtIndex(i); - 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) - { - SectionSP section_sp (section_list->FindSectionByName(const_sect_name)); - if (section_sp) - { - if (section_sp->IsThreadSpecific()) - { - result.AppendErrorWithFormat ("thread specific sections are not yet supported (section '%s')\n", sect_name); - result.SetStatus (eReturnStatusFailed); - break; - } - else - { - if (target->GetSectionLoadList().SetSectionLoadAddress (section_sp, load_addr)) - changed = true; - result.AppendMessageWithFormat("section '%s' loaded at 0x%" PRIx64 "\n", sect_name, load_addr); - } - } - else - { - result.AppendErrorWithFormat ("no section found that matches the section name '%s'\n", sect_name); - result.SetStatus (eReturnStatusFailed); - break; - } - } - else - { - result.AppendErrorWithFormat ("invalid load address string '%s'\n", load_addr_cstr); - result.SetStatus (eReturnStatusFailed); - break; - } - } - else - { - if (sect_name) - result.AppendError ("section names must be followed by a load address.\n"); - else - result.AppendError ("one or more section name + load address pair must be specified.\n"); - result.SetStatus (eReturnStatusFailed); - break; - } - } - } - - if (changed) - { - target->ModulesDidLoad (matching_modules); - Process *process = m_exe_ctx.GetProcessPtr(); - if (process) - process->Flush(); - } - } - else - { - module->GetFileSpec().GetPath (path, sizeof(path)); - result.AppendErrorWithFormat ("no sections in object file '%s'\n", path); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - module->GetFileSpec().GetPath (path, sizeof(path)); - result.AppendErrorWithFormat ("no object file for module '%s'\n", path); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - FileSpec *module_spec_file = module_spec.GetFileSpecPtr(); - if (module_spec_file) - { - module_spec_file->GetPath (path, sizeof(path)); - result.AppendErrorWithFormat ("invalid module '%s'.\n", path); + } + + if (m_uuid_option_group.GetOptionValue().OptionWasSet()) { + search_using_module_spec = true; + module_spec.GetUUID() = + m_uuid_option_group.GetOptionValue().GetCurrentValue(); + } + + if (search_using_module_spec) { + ModuleList matching_modules; + const size_t num_matches = + target->GetImages().FindModules(module_spec, matching_modules); + + char path[PATH_MAX]; + if (num_matches == 1) { + Module *module = matching_modules.GetModulePointerAtIndex(0); + if (module) { + ObjectFile *objfile = module->GetObjectFile(); + if (objfile) { + SectionList *section_list = module->GetSectionList(); + if (section_list) { + bool changed = false; + if (argc == 0) { + if (m_slide_option.GetOptionValue().OptionWasSet()) { + const addr_t slide = + m_slide_option.GetOptionValue().GetCurrentValue(); + const bool slide_is_offset = true; + module->SetLoadAddress(*target, slide, slide_is_offset, + changed); + } else { + result.AppendError("one or more section name + load " + "address pair must be specified"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + if (m_slide_option.GetOptionValue().OptionWasSet()) { + result.AppendError("The \"--slide <offset>\" option can't " + "be used in conjunction with setting " + "section load addresses.\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + for (size_t i = 0; i < argc; i += 2) { + const char *sect_name = args.GetArgumentAtIndex(i); + 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) { + SectionSP section_sp( + section_list->FindSectionByName(const_sect_name)); + if (section_sp) { + if (section_sp->IsThreadSpecific()) { + result.AppendErrorWithFormat( + "thread specific sections are not yet " + "supported (section '%s')\n", + sect_name); + result.SetStatus(eReturnStatusFailed); + break; + } else { + if (target->GetSectionLoadList() + .SetSectionLoadAddress(section_sp, + load_addr)) + changed = true; + result.AppendMessageWithFormat( + "section '%s' loaded at 0x%" PRIx64 "\n", + sect_name, load_addr); + } + } else { + result.AppendErrorWithFormat("no section found that " + "matches the section " + "name '%s'\n", + sect_name); + result.SetStatus(eReturnStatusFailed); + break; } - else - result.AppendError ("no module spec"); - result.SetStatus (eReturnStatusFailed); + } else { + result.AppendErrorWithFormat( + "invalid load address string '%s'\n", + load_addr_cstr); + result.SetStatus(eReturnStatusFailed); + break; + } + } else { + if (sect_name) + result.AppendError("section names must be followed by " + "a load address.\n"); + else + result.AppendError("one or more section name + load " + "address pair must be specified.\n"); + result.SetStatus(eReturnStatusFailed); + break; } + } } - else - { - std::string uuid_str; - - if (module_spec.GetFileSpec()) - module_spec.GetFileSpec().GetPath (path, sizeof(path)); - else - path[0] = '\0'; - - if (module_spec.GetUUIDPtr()) - uuid_str = module_spec.GetUUID().GetAsString(); - if (num_matches > 1) - { - result.AppendErrorWithFormat ("multiple modules match%s%s%s%s:\n", - path[0] ? " file=" : "", - path, - !uuid_str.empty() ? " uuid=" : "", - uuid_str.c_str()); - for (size_t i = 0; i < num_matches; ++i) - { - if (matching_modules.GetModulePointerAtIndex(i)->GetFileSpec().GetPath (path, sizeof(path))) - result.AppendMessageWithFormat("%s\n", path); - } - } - else - { - result.AppendErrorWithFormat ("no modules were found that match%s%s%s%s.\n", - path[0] ? " file=" : "", - path, - !uuid_str.empty() ? " uuid=" : "", - uuid_str.c_str()); - } - result.SetStatus (eReturnStatusFailed); + + if (changed) { + target->ModulesDidLoad(matching_modules); + Process *process = m_exe_ctx.GetProcessPtr(); + if (process) + process->Flush(); } + } else { + module->GetFileSpec().GetPath(path, sizeof(path)); + result.AppendErrorWithFormat( + "no sections in object file '%s'\n", path); + result.SetStatus(eReturnStatusFailed); + } + } else { + module->GetFileSpec().GetPath(path, sizeof(path)); + result.AppendErrorWithFormat("no object file for module '%s'\n", + path); + result.SetStatus(eReturnStatusFailed); } - else - { - result.AppendError ("either the \"--file <module>\" or the \"--uuid <uuid>\" option must be specified.\n"); - result.SetStatus (eReturnStatusFailed); - return false; + } else { + FileSpec *module_spec_file = module_spec.GetFileSpecPtr(); + if (module_spec_file) { + module_spec_file->GetPath(path, sizeof(path)); + result.AppendErrorWithFormat("invalid module '%s'.\n", path); + } else + result.AppendError("no module spec"); + result.SetStatus(eReturnStatusFailed); + } + } else { + std::string uuid_str; + + if (module_spec.GetFileSpec()) + module_spec.GetFileSpec().GetPath(path, sizeof(path)); + else + path[0] = '\0'; + + if (module_spec.GetUUIDPtr()) + uuid_str = module_spec.GetUUID().GetAsString(); + if (num_matches > 1) { + result.AppendErrorWithFormat( + "multiple modules match%s%s%s%s:\n", path[0] ? " file=" : "", + path, !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str()); + for (size_t i = 0; i < num_matches; ++i) { + if (matching_modules.GetModulePointerAtIndex(i) + ->GetFileSpec() + .GetPath(path, sizeof(path))) + result.AppendMessageWithFormat("%s\n", path); } + } else { + result.AppendErrorWithFormat( + "no modules were found that match%s%s%s%s.\n", + path[0] ? " file=" : "", path, + !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str()); + } + result.SetStatus(eReturnStatusFailed); } - return result.Succeeded(); + } else { + result.AppendError("either the \"--file <module>\" or the \"--uuid " + "<uuid>\" option must be specified.\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } } + return result.Succeeded(); + } - OptionGroupOptions m_option_group; - OptionGroupUUID m_uuid_option_group; - OptionGroupString m_file_option; - OptionGroupUInt64 m_slide_option; + OptionGroupOptions m_option_group; + OptionGroupUUID m_uuid_option_group; + OptionGroupString m_file_option; + OptionGroupUInt64 m_slide_option; }; //---------------------------------------------------------------------- // List images with associated information //---------------------------------------------------------------------- -class CommandObjectTargetModulesList : public CommandObjectParsed -{ +class CommandObjectTargetModulesList : public CommandObjectParsed { public: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options(), - m_format_array(), - m_use_global_module_list (false), - m_module_addr (LLDB_INVALID_ADDRESS) - { - } - - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - - const int short_option = m_getopt_table[option_idx].val; - if (short_option == 'g') - { - m_use_global_module_list = true; - } - else if (short_option == 'a') - { - m_module_addr = Args::StringToAddress(execution_context, - option_arg, - LLDB_INVALID_ADDRESS, - &error); - } - else - { - unsigned long width = 0; - if (option_arg) - width = strtoul(option_arg, nullptr, 0); - m_format_array.push_back(std::make_pair(short_option, width)); - } - return error; - } + class CommandOptions : public Options { + public: + CommandOptions() + : Options(), m_format_array(), m_use_global_module_list(false), + m_module_addr(LLDB_INVALID_ADDRESS) {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + + const int short_option = m_getopt_table[option_idx].val; + if (short_option == 'g') { + m_use_global_module_list = true; + } else if (short_option == 'a') { + m_module_addr = Args::StringToAddress(execution_context, option_arg, + LLDB_INVALID_ADDRESS, &error); + } else { + unsigned long width = 0; + if (option_arg) + width = strtoul(option_arg, nullptr, 0); + m_format_array.push_back(std::make_pair(short_option, width)); + } + return error; + } - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_format_array.clear(); - m_use_global_module_list = false; - m_module_addr = LLDB_INVALID_ADDRESS; - } + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_format_array.clear(); + m_use_global_module_list = false; + m_module_addr = LLDB_INVALID_ADDRESS; + } - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } - // Options table: Required for subclasses of Options. + // Options table: Required for subclasses of Options. - static OptionDefinition g_option_table[]; + static OptionDefinition g_option_table[]; - // Instance variables to hold the values for command options. - typedef std::vector< std::pair<char, uint32_t> > FormatWidthCollection; - FormatWidthCollection m_format_array; - bool m_use_global_module_list; - lldb::addr_t m_module_addr; - }; + // Instance variables to hold the values for command options. + typedef std::vector<std::pair<char, uint32_t>> FormatWidthCollection; + FormatWidthCollection m_format_array; + bool m_use_global_module_list; + lldb::addr_t m_module_addr; + }; - CommandObjectTargetModulesList (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "target modules list", - "List current executable and dependent shared library images.", - "target modules list [<cmd-options>]"), - m_options() - { - } + CommandObjectTargetModulesList(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "target modules list", + "List current executable and dependent shared library images.", + "target modules list [<cmd-options>]"), + m_options() {} - ~CommandObjectTargetModulesList() override = default; + ~CommandObjectTargetModulesList() override = default; - Options * - GetOptions () override - { - return &m_options; - } + Options *GetOptions() override { return &m_options; } protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - const bool use_global_module_list = m_options.m_use_global_module_list; - // Define a local module list here to ensure it lives longer than any "locker" - // object which might lock its contents below (through the "module_list_ptr" - // variable). - ModuleList module_list; - if (target == nullptr && !use_global_module_list) - { - result.AppendError ("invalid target, create a debug target using the 'target create' command"); - result.SetStatus (eReturnStatusFailed); - return false; - } - else - { - if (target) - { - uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); - result.GetOutputStream().SetAddressByteSize(addr_byte_size); - result.GetErrorStream().SetAddressByteSize(addr_byte_size); - } - // Dump all sections for all modules images - Stream &strm = result.GetOutputStream(); - - if (m_options.m_module_addr != LLDB_INVALID_ADDRESS) - { - if (target) - { - Address module_address; - if (module_address.SetLoadAddress(m_options.m_module_addr, target)) - { - ModuleSP module_sp (module_address.GetModule()); - if (module_sp) - { - PrintModule (target, module_sp.get(), 0, strm); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendErrorWithFormat ("Couldn't find module matching address: 0x%" PRIx64 ".", m_options.m_module_addr); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendErrorWithFormat ("Couldn't find module containing address: 0x%" PRIx64 ".", m_options.m_module_addr); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendError ("Can only look up modules by address with a valid target."); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); - } - - size_t num_modules = 0; - - // This locker will be locked on the mutex in module_list_ptr if it is non-nullptr. - // Otherwise it will lock the AllocationModuleCollectionMutex when accessing - // the global module list directly. - std::unique_lock<std::recursive_mutex> guard(Module::GetAllocationModuleCollectionMutex(), std::defer_lock); - - const ModuleList *module_list_ptr = nullptr; - const size_t argc = command.GetArgumentCount(); - if (argc == 0) - { - if (use_global_module_list) - { - guard.lock(); - num_modules = Module::GetNumberAllocatedModules(); - } - else - { - module_list_ptr = &target->GetImages(); - } - } - else - { - for (size_t i = 0; i < argc; ++i) - { - // 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); - if (num_matches == 0) - { - if (argc == 1) - { - result.AppendErrorWithFormat ("no modules found that match '%s'", arg_cstr); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - } - - module_list_ptr = &module_list; + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + const bool use_global_module_list = m_options.m_use_global_module_list; + // Define a local module list here to ensure it lives longer than any + // "locker" + // object which might lock its contents below (through the "module_list_ptr" + // variable). + ModuleList module_list; + if (target == nullptr && !use_global_module_list) { + result.AppendError("invalid target, create a debug target using the " + "'target create' command"); + result.SetStatus(eReturnStatusFailed); + return false; + } else { + if (target) { + uint32_t addr_byte_size = + target->GetArchitecture().GetAddressByteSize(); + result.GetOutputStream().SetAddressByteSize(addr_byte_size); + result.GetErrorStream().SetAddressByteSize(addr_byte_size); + } + // Dump all sections for all modules images + Stream &strm = result.GetOutputStream(); + + if (m_options.m_module_addr != LLDB_INVALID_ADDRESS) { + if (target) { + Address module_address; + if (module_address.SetLoadAddress(m_options.m_module_addr, target)) { + ModuleSP module_sp(module_address.GetModule()); + if (module_sp) { + PrintModule(target, module_sp.get(), 0, strm); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat( + "Couldn't find module matching address: 0x%" PRIx64 ".", + m_options.m_module_addr); + result.SetStatus(eReturnStatusFailed); } - - std::unique_lock<std::recursive_mutex> lock; - if (module_list_ptr != nullptr) - { - lock = std::unique_lock<std::recursive_mutex>(module_list_ptr->GetMutex()); - - num_modules = module_list_ptr->GetSize(); + } else { + result.AppendErrorWithFormat( + "Couldn't find module containing address: 0x%" PRIx64 ".", + m_options.m_module_addr); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendError( + "Can only look up modules by address with a valid target."); + result.SetStatus(eReturnStatusFailed); + } + return result.Succeeded(); + } + + size_t num_modules = 0; + + // This locker will be locked on the mutex in module_list_ptr if it is + // non-nullptr. + // Otherwise it will lock the AllocationModuleCollectionMutex when + // accessing + // the global module list directly. + std::unique_lock<std::recursive_mutex> guard( + Module::GetAllocationModuleCollectionMutex(), std::defer_lock); + + const ModuleList *module_list_ptr = nullptr; + const size_t argc = command.GetArgumentCount(); + if (argc == 0) { + if (use_global_module_list) { + guard.lock(); + num_modules = Module::GetNumberAllocatedModules(); + } else { + module_list_ptr = &target->GetImages(); + } + } else { + for (size_t i = 0; i < argc; ++i) { + // 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); + if (num_matches == 0) { + if (argc == 1) { + result.AppendErrorWithFormat("no modules found that match '%s'", + arg_cstr); + result.SetStatus(eReturnStatusFailed); + return false; } + } + } - if (num_modules > 0) - { - for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx) - { - ModuleSP module_sp; - Module *module; - if (module_list_ptr) - { - module_sp = module_list_ptr->GetModuleAtIndexUnlocked(image_idx); - module = module_sp.get(); - } - else - { - module = Module::GetAllocatedModuleAtIndex(image_idx); - module_sp = module->shared_from_this(); - } + module_list_ptr = &module_list; + } + + std::unique_lock<std::recursive_mutex> lock; + if (module_list_ptr != nullptr) { + lock = + std::unique_lock<std::recursive_mutex>(module_list_ptr->GetMutex()); + + num_modules = module_list_ptr->GetSize(); + } + + if (num_modules > 0) { + for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) { + ModuleSP module_sp; + Module *module; + if (module_list_ptr) { + module_sp = module_list_ptr->GetModuleAtIndexUnlocked(image_idx); + module = module_sp.get(); + } else { + module = Module::GetAllocatedModuleAtIndex(image_idx); + module_sp = module->shared_from_this(); + } + + const size_t indent = strm.Printf("[%3u] ", image_idx); + PrintModule(target, module, indent, strm); + } + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + if (argc) { + if (use_global_module_list) + result.AppendError( + "the global module list has no matching modules"); + else + result.AppendError("the target has no matching modules"); + } else { + if (use_global_module_list) + result.AppendError("the global module list is empty"); + else + result.AppendError( + "the target has no associated executable images"); + } + result.SetStatus(eReturnStatusFailed); + return false; + } + } + return result.Succeeded(); + } - const size_t indent = strm.Printf("[%3u] ", image_idx); - PrintModule (target, module, indent, strm); + void PrintModule(Target *target, Module *module, int indent, Stream &strm) { + if (module == nullptr) { + strm.PutCString("Null module"); + return; + } + bool dump_object_name = false; + if (m_options.m_format_array.empty()) { + m_options.m_format_array.push_back(std::make_pair('u', 0)); + m_options.m_format_array.push_back(std::make_pair('h', 0)); + m_options.m_format_array.push_back(std::make_pair('f', 0)); + m_options.m_format_array.push_back(std::make_pair('S', 0)); + } + const size_t num_entries = m_options.m_format_array.size(); + bool print_space = false; + for (size_t i = 0; i < num_entries; ++i) { + if (print_space) + strm.PutChar(' '); + print_space = true; + const char format_char = m_options.m_format_array[i].first; + uint32_t width = m_options.m_format_array[i].second; + switch (format_char) { + case 'A': + DumpModuleArchitecture(strm, module, false, width); + break; + + case 't': + DumpModuleArchitecture(strm, module, true, width); + break; + + case 'f': + DumpFullpath(strm, &module->GetFileSpec(), width); + dump_object_name = true; + break; + + case 'd': + DumpDirectory(strm, &module->GetFileSpec(), width); + break; + + case 'b': + DumpBasename(strm, &module->GetFileSpec(), width); + dump_object_name = true; + break; + + case 'h': + case 'o': + // Image header address + { + uint32_t addr_nibble_width = + target ? (target->GetArchitecture().GetAddressByteSize() * 2) + : 16; + + ObjectFile *objfile = module->GetObjectFile(); + if (objfile) { + Address header_addr(objfile->GetHeaderAddress()); + if (header_addr.IsValid()) { + if (target && !target->GetSectionLoadList().IsEmpty()) { + lldb::addr_t header_load_addr = + header_addr.GetLoadAddress(target); + if (header_load_addr == LLDB_INVALID_ADDRESS) { + header_addr.Dump(&strm, target, + Address::DumpStyleModuleWithFileAddress, + Address::DumpStyleFileAddress); + } else { + if (format_char == 'o') { + // Show the offset of slide for the image + strm.Printf( + "0x%*.*" PRIx64, addr_nibble_width, addr_nibble_width, + header_load_addr - header_addr.GetFileAddress()); + } else { + // Show the load address of the image + strm.Printf("0x%*.*" PRIx64, addr_nibble_width, + addr_nibble_width, header_load_addr); + } } - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - if (argc) - { - if (use_global_module_list) - result.AppendError ("the global module list has no matching modules"); - else - result.AppendError ("the target has no matching modules"); - } - else - { - if (use_global_module_list) - result.AppendError ("the global module list is empty"); - else - result.AppendError ("the target has no associated executable images"); - } - result.SetStatus (eReturnStatusFailed); - return false; + break; + } + // The address was valid, but the image isn't loaded, output the + // address in an appropriate format + header_addr.Dump(&strm, target, Address::DumpStyleFileAddress); + break; } + } + strm.Printf("%*s", addr_nibble_width + 2, ""); } - return result.Succeeded(); - } - - void - PrintModule (Target *target, Module *module, int indent, Stream &strm) - { - if (module == nullptr) - { - strm.PutCString("Null module"); - return; + break; + + case 'r': { + size_t ref_count = 0; + ModuleSP module_sp(module->shared_from_this()); + if (module_sp) { + // Take one away to make sure we don't count our local "module_sp" + ref_count = module_sp.use_count() - 1; } - - bool dump_object_name = false; - if (m_options.m_format_array.empty()) - { - m_options.m_format_array.push_back(std::make_pair('u', 0)); - m_options.m_format_array.push_back(std::make_pair('h', 0)); - m_options.m_format_array.push_back(std::make_pair('f', 0)); - m_options.m_format_array.push_back(std::make_pair('S', 0)); + if (width) + strm.Printf("{%*" PRIu64 "}", width, (uint64_t)ref_count); + else + strm.Printf("{%" PRIu64 "}", (uint64_t)ref_count); + } break; + + case 's': + case 'S': { + const SymbolVendor *symbol_vendor = module->GetSymbolVendor(); + if (symbol_vendor) { + const FileSpec symfile_spec = symbol_vendor->GetMainFileSpec(); + if (format_char == 'S') { + // Dump symbol file only if different from module file + if (!symfile_spec || symfile_spec == module->GetFileSpec()) { + print_space = false; + break; + } + // Add a newline and indent past the index + strm.Printf("\n%*s", indent, ""); + } + DumpFullpath(strm, &symfile_spec, width); + dump_object_name = true; + break; } - const size_t num_entries = m_options.m_format_array.size(); - bool print_space = false; - for (size_t i = 0; i < num_entries; ++i) - { - if (print_space) - strm.PutChar(' '); - print_space = true; - const char format_char = m_options.m_format_array[i].first; - uint32_t width = m_options.m_format_array[i].second; - switch (format_char) - { - case 'A': - DumpModuleArchitecture (strm, module, false, width); - break; - - case 't': - DumpModuleArchitecture (strm, module, true, width); - break; - - case 'f': - DumpFullpath (strm, &module->GetFileSpec(), width); - dump_object_name = true; - break; - - case 'd': - DumpDirectory (strm, &module->GetFileSpec(), width); - break; - - case 'b': - DumpBasename (strm, &module->GetFileSpec(), width); - dump_object_name = true; - break; - - case 'h': - case 'o': - // Image header address - { - uint32_t addr_nibble_width = target ? (target->GetArchitecture().GetAddressByteSize() * 2) : 16; - - ObjectFile *objfile = module->GetObjectFile (); - if (objfile) - { - Address header_addr(objfile->GetHeaderAddress()); - if (header_addr.IsValid()) - { - if (target && !target->GetSectionLoadList().IsEmpty()) - { - lldb::addr_t header_load_addr = header_addr.GetLoadAddress (target); - if (header_load_addr == LLDB_INVALID_ADDRESS) - { - header_addr.Dump (&strm, target, Address::DumpStyleModuleWithFileAddress, Address::DumpStyleFileAddress); - } - else - { - if (format_char == 'o') - { - // Show the offset of slide for the image - strm.Printf ("0x%*.*" PRIx64, addr_nibble_width, addr_nibble_width, header_load_addr - header_addr.GetFileAddress()); - } - else - { - // Show the load address of the image - strm.Printf ("0x%*.*" PRIx64, addr_nibble_width, addr_nibble_width, header_load_addr); - } - } - break; - } - // The address was valid, but the image isn't loaded, output the address in an appropriate format - header_addr.Dump (&strm, target, Address::DumpStyleFileAddress); - break; - } - } - strm.Printf ("%*s", addr_nibble_width + 2, ""); - } - break; - - case 'r': - { - size_t ref_count = 0; - ModuleSP module_sp (module->shared_from_this()); - if (module_sp) - { - // Take one away to make sure we don't count our local "module_sp" - ref_count = module_sp.use_count() - 1; - } - if (width) - strm.Printf("{%*" PRIu64 "}", width, (uint64_t)ref_count); - else - strm.Printf("{%" PRIu64 "}", (uint64_t)ref_count); - } - break; - - case 's': - case 'S': - { - const SymbolVendor *symbol_vendor = module->GetSymbolVendor(); - if (symbol_vendor) - { - const FileSpec symfile_spec = symbol_vendor->GetMainFileSpec(); - if (format_char == 'S') - { - // Dump symbol file only if different from module file - if (!symfile_spec || symfile_spec == module->GetFileSpec()) - { - print_space = false; - break; - } - // Add a newline and indent past the index - strm.Printf ("\n%*s", indent, ""); - } - DumpFullpath (strm, &symfile_spec, width); - dump_object_name = true; - break; - } - strm.Printf("%.*s", width, "<NONE>"); - } - break; + strm.Printf("%.*s", width, "<NONE>"); + } break; - case 'm': - module->GetModificationTime().Dump(&strm, width); - break; + case 'm': + module->GetModificationTime().Dump(&strm, width); + break; - case 'p': - strm.Printf("%p", static_cast<void*>(module)); - break; + case 'p': + strm.Printf("%p", static_cast<void *>(module)); + break; - case 'u': - DumpModuleUUID(strm, module); - break; + case 'u': + DumpModuleUUID(strm, module); + break; - default: - break; - } - } - if (dump_object_name) - { - const char *object_name = module->GetObjectName().GetCString(); - if (object_name) - strm.Printf ("(%s)", object_name); - } - strm.EOL(); + default: + break; + } + } + if (dump_object_name) { + const char *object_name = module->GetObjectName().GetCString(); + if (object_name) + strm.Printf("(%s)", object_name); } + strm.EOL(); + } - CommandOptions m_options; + CommandOptions m_options; }; OptionDefinition -CommandObjectTargetModulesList::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectTargetModulesList::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Display the image at this address."}, {LLDB_OPT_SET_1, false, "arch", 'A', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the architecture when listing images."}, {LLDB_OPT_SET_1, false, "triple", 't', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the triple when listing images."}, @@ -3577,7 +3134,7 @@ CommandObjectTargetModulesList::CommandOptions::g_option_table[] = {LLDB_OPT_SET_1, false, "pointer", 'p', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the module pointer."}, {LLDB_OPT_SET_1, false, "global", 'g', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the modules from the global module list, not just the current target."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; #pragma mark CommandObjectTargetModulesShowUnwind @@ -3586,746 +3143,668 @@ CommandObjectTargetModulesList::CommandOptions::g_option_table[] = // Lookup unwind information in images //---------------------------------------------------------------------- -class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed -{ +class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed { public: - enum - { - eLookupTypeInvalid = -1, - eLookupTypeAddress = 0, - eLookupTypeSymbol, - eLookupTypeFunction, - eLookupTypeFunctionOrSymbol, - kNumLookupTypes - }; - - class CommandOptions : public Options - { - public: - CommandOptions() : - Options(), - m_type(eLookupTypeInvalid), - m_str(), - m_addr(LLDB_INVALID_ADDRESS) - { - } + enum { + eLookupTypeInvalid = -1, + eLookupTypeAddress = 0, + eLookupTypeSymbol, + eLookupTypeFunction, + eLookupTypeFunctionOrSymbol, + kNumLookupTypes + }; + + class CommandOptions : public Options { + public: + CommandOptions() + : Options(), m_type(eLookupTypeInvalid), m_str(), + m_addr(LLDB_INVALID_ADDRESS) {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'a': { + m_str = option_arg; + m_type = eLookupTypeAddress; + m_addr = Args::StringToAddress(execution_context, option_arg, + LLDB_INVALID_ADDRESS, &error); + if (m_addr == LLDB_INVALID_ADDRESS) + error.SetErrorStringWithFormat("invalid address string '%s'", + option_arg); + break; + } + + case 'n': + m_str = option_arg; + m_type = eLookupTypeFunctionOrSymbol; + break; + + default: + error.SetErrorStringWithFormat("unrecognized option %c.", short_option); + break; + } + + return error; + } - ~CommandOptions() override = default; + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_type = eLookupTypeInvalid; + m_str.clear(); + m_addr = LLDB_INVALID_ADDRESS; + } - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'a': - { - m_str = option_arg; - m_type = eLookupTypeAddress; - m_addr = Args::StringToAddress(execution_context, - option_arg, - LLDB_INVALID_ADDRESS, - &error); - if (m_addr == LLDB_INVALID_ADDRESS) - error.SetErrorStringWithFormat ("invalid address string '%s'", option_arg); - break; - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } - case 'n': - m_str = option_arg; - m_type = eLookupTypeFunctionOrSymbol; - break; + // Options table: Required for subclasses of Options. - default: - error.SetErrorStringWithFormat ("unrecognized option %c.", short_option); - break; - } + static OptionDefinition g_option_table[]; - return error; - } + // Instance variables to hold the values for command options. - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_type = eLookupTypeInvalid; - m_str.clear(); - m_addr = LLDB_INVALID_ADDRESS; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. + int m_type; // Should be a eLookupTypeXXX enum after parsing options + std::string m_str; // Holds name lookup + lldb::addr_t m_addr; // Holds the address to lookup + }; - static OptionDefinition g_option_table[]; + CommandObjectTargetModulesShowUnwind(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "target modules show-unwind", + "Show synthesized unwind instructions for a function.", nullptr, + eCommandRequiresTarget | eCommandRequiresProcess | + eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), + m_options() {} - // Instance variables to hold the values for command options. + ~CommandObjectTargetModulesShowUnwind() override = default; - int m_type; // Should be a eLookupTypeXXX enum after parsing options - std::string m_str; // Holds name lookup - lldb::addr_t m_addr; // Holds the address to lookup - }; + Options *GetOptions() override { return &m_options; } - CommandObjectTargetModulesShowUnwind (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "target modules show-unwind", - "Show synthesized unwind instructions for a function.", - nullptr, - eCommandRequiresTarget | - eCommandRequiresProcess | - eCommandProcessMustBeLaunched | - eCommandProcessMustBePaused ), - m_options() - { +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_exe_ctx.GetTargetPtr(); + Process *process = m_exe_ctx.GetProcessPtr(); + ABI *abi = nullptr; + if (process) + abi = process->GetABI().get(); + + if (process == nullptr) { + result.AppendError( + "You must have a process running to use this command."); + result.SetStatus(eReturnStatusFailed); + return false; } - ~CommandObjectTargetModulesShowUnwind() override = default; - - Options * - GetOptions () override - { - return &m_options; + ThreadList threads(process->GetThreadList()); + if (threads.GetSize() == 0) { + result.AppendError("The process must be paused to use this command."); + result.SetStatus(eReturnStatusFailed); + return false; } -protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = m_exe_ctx.GetTargetPtr(); - Process *process = m_exe_ctx.GetProcessPtr(); - ABI *abi = nullptr; - if (process) - abi = process->GetABI().get(); - - if (process == nullptr) - { - result.AppendError ("You must have a process running to use this command."); - result.SetStatus (eReturnStatusFailed); - return false; - } + ThreadSP thread(threads.GetThreadAtIndex(0)); + if (!thread) { + result.AppendError("The process must be paused to use this command."); + result.SetStatus(eReturnStatusFailed); + return false; + } - ThreadList threads(process->GetThreadList()); - if (threads.GetSize() == 0) - { - result.AppendError ("The process must be paused to use this command."); - result.SetStatus (eReturnStatusFailed); - return false; - } + SymbolContextList sc_list; - ThreadSP thread(threads.GetThreadAtIndex(0)); - if (!thread) - { - result.AppendError ("The process must be paused to use this command."); - result.SetStatus (eReturnStatusFailed); - return false; + if (m_options.m_type == eLookupTypeFunctionOrSymbol) { + ConstString function_name(m_options.m_str.c_str()); + target->GetImages().FindFunctions(function_name, eFunctionNameTypeAuto, + true, false, true, sc_list); + } else if (m_options.m_type == eLookupTypeAddress && target) { + Address addr; + if (target->GetSectionLoadList().ResolveLoadAddress(m_options.m_addr, + addr)) { + SymbolContext sc; + ModuleSP module_sp(addr.GetModule()); + module_sp->ResolveSymbolContextForAddress(addr, + eSymbolContextEverything, sc); + if (sc.function || sc.symbol) { + sc_list.Append(sc); } + } + } else { + result.AppendError( + "address-expression or function name option must be specified."); + result.SetStatus(eReturnStatusFailed); + return false; + } - SymbolContextList sc_list; + size_t num_matches = sc_list.GetSize(); + if (num_matches == 0) { + result.AppendErrorWithFormat("no unwind data found that matches '%s'.", + m_options.m_str.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } - if (m_options.m_type == eLookupTypeFunctionOrSymbol) - { - ConstString function_name (m_options.m_str.c_str()); - target->GetImages().FindFunctions (function_name, eFunctionNameTypeAuto, true, false, true, sc_list); - } - else if (m_options.m_type == eLookupTypeAddress && target) - { - Address addr; - if (target->GetSectionLoadList().ResolveLoadAddress (m_options.m_addr, addr)) - { - SymbolContext sc; - ModuleSP module_sp (addr.GetModule()); - module_sp->ResolveSymbolContextForAddress (addr, eSymbolContextEverything, sc); - if (sc.function || sc.symbol) - { - sc_list.Append(sc); - } - } - } - else - { - result.AppendError ("address-expression or function name option must be specified."); - result.SetStatus (eReturnStatusFailed); - return false; + for (uint32_t idx = 0; idx < num_matches; idx++) { + SymbolContext sc; + sc_list.GetContextAtIndex(idx, sc); + if (sc.symbol == nullptr && sc.function == nullptr) + continue; + if (!sc.module_sp || sc.module_sp->GetObjectFile() == nullptr) + continue; + AddressRange range; + if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, + false, range)) + continue; + if (!range.GetBaseAddress().IsValid()) + continue; + ConstString funcname(sc.GetFunctionName()); + if (funcname.IsEmpty()) + continue; + addr_t start_addr = range.GetBaseAddress().GetLoadAddress(target); + if (abi) + start_addr = abi->FixCodeAddress(start_addr); + + FuncUnwindersSP func_unwinders_sp( + sc.module_sp->GetObjectFile() + ->GetUnwindTable() + .GetUncachedFuncUnwindersContainingAddress(start_addr, sc)); + if (!func_unwinders_sp) + continue; + + result.GetOutputStream().Printf( + "UNWIND PLANS for %s`%s (start addr 0x%" PRIx64 ")\n\n", + sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), + funcname.AsCString(), start_addr); + + UnwindPlanSP non_callsite_unwind_plan = + func_unwinders_sp->GetUnwindPlanAtNonCallSite(*target, *thread, -1); + if (non_callsite_unwind_plan) { + result.GetOutputStream().Printf( + "Asynchronous (not restricted to call-sites) UnwindPlan is '%s'\n", + non_callsite_unwind_plan->GetSourceName().AsCString()); + } + UnwindPlanSP callsite_unwind_plan = + func_unwinders_sp->GetUnwindPlanAtCallSite(*target, -1); + if (callsite_unwind_plan) { + result.GetOutputStream().Printf( + "Synchronous (restricted to call-sites) UnwindPlan is '%s'\n", + callsite_unwind_plan->GetSourceName().AsCString()); + } + UnwindPlanSP fast_unwind_plan = + func_unwinders_sp->GetUnwindPlanFastUnwind(*target, *thread); + if (fast_unwind_plan) { + result.GetOutputStream().Printf( + "Fast UnwindPlan is '%s'\n", + fast_unwind_plan->GetSourceName().AsCString()); + } + + result.GetOutputStream().Printf("\n"); + + UnwindPlanSP assembly_sp = + func_unwinders_sp->GetAssemblyUnwindPlan(*target, *thread, 0); + if (assembly_sp) { + result.GetOutputStream().Printf( + "Assembly language inspection UnwindPlan:\n"); + assembly_sp->Dump(result.GetOutputStream(), thread.get(), + LLDB_INVALID_ADDRESS); + result.GetOutputStream().Printf("\n"); + } + + UnwindPlanSP ehframe_sp = + func_unwinders_sp->GetEHFrameUnwindPlan(*target, 0); + if (ehframe_sp) { + result.GetOutputStream().Printf("eh_frame UnwindPlan:\n"); + ehframe_sp->Dump(result.GetOutputStream(), thread.get(), + LLDB_INVALID_ADDRESS); + result.GetOutputStream().Printf("\n"); + } + + UnwindPlanSP ehframe_augmented_sp = + func_unwinders_sp->GetEHFrameAugmentedUnwindPlan(*target, *thread, 0); + if (ehframe_augmented_sp) { + result.GetOutputStream().Printf("eh_frame augmented UnwindPlan:\n"); + ehframe_augmented_sp->Dump(result.GetOutputStream(), thread.get(), + LLDB_INVALID_ADDRESS); + result.GetOutputStream().Printf("\n"); + } + + UnwindPlanSP arm_unwind_sp = + func_unwinders_sp->GetArmUnwindUnwindPlan(*target, 0); + if (arm_unwind_sp) { + result.GetOutputStream().Printf("ARM.exidx unwind UnwindPlan:\n"); + arm_unwind_sp->Dump(result.GetOutputStream(), thread.get(), + LLDB_INVALID_ADDRESS); + result.GetOutputStream().Printf("\n"); + } + + UnwindPlanSP compact_unwind_sp = + func_unwinders_sp->GetCompactUnwindUnwindPlan(*target, 0); + if (compact_unwind_sp) { + result.GetOutputStream().Printf("Compact unwind UnwindPlan:\n"); + compact_unwind_sp->Dump(result.GetOutputStream(), thread.get(), + LLDB_INVALID_ADDRESS); + result.GetOutputStream().Printf("\n"); + } + + if (fast_unwind_plan) { + result.GetOutputStream().Printf("Fast UnwindPlan:\n"); + fast_unwind_plan->Dump(result.GetOutputStream(), thread.get(), + LLDB_INVALID_ADDRESS); + result.GetOutputStream().Printf("\n"); + } + + ABISP abi_sp = process->GetABI(); + if (abi_sp) { + UnwindPlan arch_default(lldb::eRegisterKindGeneric); + if (abi_sp->CreateDefaultUnwindPlan(arch_default)) { + result.GetOutputStream().Printf("Arch default UnwindPlan:\n"); + arch_default.Dump(result.GetOutputStream(), thread.get(), + LLDB_INVALID_ADDRESS); + result.GetOutputStream().Printf("\n"); } - size_t num_matches = sc_list.GetSize(); - if (num_matches == 0) - { - result.AppendErrorWithFormat ("no unwind data found that matches '%s'.", m_options.m_str.c_str()); - result.SetStatus (eReturnStatusFailed); - return false; + UnwindPlan arch_entry(lldb::eRegisterKindGeneric); + if (abi_sp->CreateFunctionEntryUnwindPlan(arch_entry)) { + result.GetOutputStream().Printf( + "Arch default at entry point UnwindPlan:\n"); + arch_entry.Dump(result.GetOutputStream(), thread.get(), + LLDB_INVALID_ADDRESS); + result.GetOutputStream().Printf("\n"); } + } - for (uint32_t idx = 0; idx < num_matches; idx++) - { - SymbolContext sc; - sc_list.GetContextAtIndex(idx, sc); - if (sc.symbol == nullptr && sc.function == nullptr) - continue; - if (!sc.module_sp || sc.module_sp->GetObjectFile() == nullptr) - continue; - AddressRange range; - if (!sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, range)) - continue; - if (!range.GetBaseAddress().IsValid()) - continue; - ConstString funcname(sc.GetFunctionName()); - if (funcname.IsEmpty()) - continue; - addr_t start_addr = range.GetBaseAddress().GetLoadAddress(target); - if (abi) - start_addr = abi->FixCodeAddress(start_addr); - - FuncUnwindersSP func_unwinders_sp (sc.module_sp->GetObjectFile()->GetUnwindTable().GetUncachedFuncUnwindersContainingAddress(start_addr, sc)); - if (!func_unwinders_sp) - continue; - - result.GetOutputStream().Printf("UNWIND PLANS for %s`%s (start addr 0x%" PRIx64 ")\n\n", sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), funcname.AsCString(), start_addr); - - UnwindPlanSP non_callsite_unwind_plan = func_unwinders_sp->GetUnwindPlanAtNonCallSite(*target, *thread, -1); - if (non_callsite_unwind_plan) - { - result.GetOutputStream().Printf("Asynchronous (not restricted to call-sites) UnwindPlan is '%s'\n", non_callsite_unwind_plan->GetSourceName().AsCString()); - } - UnwindPlanSP callsite_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(*target, -1); - if (callsite_unwind_plan) - { - result.GetOutputStream().Printf("Synchronous (restricted to call-sites) UnwindPlan is '%s'\n", callsite_unwind_plan->GetSourceName().AsCString()); - } - UnwindPlanSP fast_unwind_plan = func_unwinders_sp->GetUnwindPlanFastUnwind(*target, *thread); - if (fast_unwind_plan) - { - result.GetOutputStream().Printf("Fast UnwindPlan is '%s'\n", fast_unwind_plan->GetSourceName().AsCString()); - } - - result.GetOutputStream().Printf("\n"); - - UnwindPlanSP assembly_sp = func_unwinders_sp->GetAssemblyUnwindPlan(*target, *thread, 0); - if (assembly_sp) - { - result.GetOutputStream().Printf("Assembly language inspection UnwindPlan:\n"); - assembly_sp->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); - result.GetOutputStream().Printf("\n"); - } - - UnwindPlanSP ehframe_sp = func_unwinders_sp->GetEHFrameUnwindPlan(*target, 0); - if (ehframe_sp) - { - result.GetOutputStream().Printf("eh_frame UnwindPlan:\n"); - ehframe_sp->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); - result.GetOutputStream().Printf("\n"); - } - - UnwindPlanSP ehframe_augmented_sp = func_unwinders_sp->GetEHFrameAugmentedUnwindPlan(*target, *thread, 0); - if (ehframe_augmented_sp) - { - result.GetOutputStream().Printf("eh_frame augmented UnwindPlan:\n"); - ehframe_augmented_sp->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); - result.GetOutputStream().Printf("\n"); - } - - UnwindPlanSP arm_unwind_sp = func_unwinders_sp->GetArmUnwindUnwindPlan(*target, 0); - if (arm_unwind_sp) - { - result.GetOutputStream().Printf("ARM.exidx unwind UnwindPlan:\n"); - arm_unwind_sp->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); - result.GetOutputStream().Printf("\n"); - } - - UnwindPlanSP compact_unwind_sp = func_unwinders_sp->GetCompactUnwindUnwindPlan(*target, 0); - if (compact_unwind_sp) - { - result.GetOutputStream().Printf("Compact unwind UnwindPlan:\n"); - compact_unwind_sp->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); - result.GetOutputStream().Printf("\n"); - } - - if (fast_unwind_plan) - { - result.GetOutputStream().Printf("Fast UnwindPlan:\n"); - fast_unwind_plan->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); - result.GetOutputStream().Printf("\n"); - } - - ABISP abi_sp = process->GetABI(); - if (abi_sp) - { - UnwindPlan arch_default(lldb::eRegisterKindGeneric); - if (abi_sp->CreateDefaultUnwindPlan (arch_default)) - { - result.GetOutputStream().Printf("Arch default UnwindPlan:\n"); - arch_default.Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); - result.GetOutputStream().Printf("\n"); - } - - UnwindPlan arch_entry(lldb::eRegisterKindGeneric); - if (abi_sp->CreateFunctionEntryUnwindPlan (arch_entry)) - { - result.GetOutputStream().Printf("Arch default at entry point UnwindPlan:\n"); - arch_entry.Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); - result.GetOutputStream().Printf("\n"); - } - } - - result.GetOutputStream().Printf ("\n"); - } - return result.Succeeded(); + result.GetOutputStream().Printf("\n"); } + return result.Succeeded(); + } - CommandOptions m_options; + CommandOptions m_options; }; OptionDefinition -CommandObjectTargetModulesShowUnwind::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectTargetModulesShowUnwind::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFunctionName, "Show unwind instructions for a function or symbol name."}, {LLDB_OPT_SET_2, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Show unwind instructions for a function or symbol containing an address"}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //---------------------------------------------------------------------- // Lookup information in images //---------------------------------------------------------------------- -class CommandObjectTargetModulesLookup : public CommandObjectParsed -{ +class CommandObjectTargetModulesLookup : public CommandObjectParsed { public: - enum - { - eLookupTypeInvalid = -1, - eLookupTypeAddress = 0, - eLookupTypeSymbol, - eLookupTypeFileLine, // Line is optional - eLookupTypeFunction, - eLookupTypeFunctionOrSymbol, - eLookupTypeType, - kNumLookupTypes - }; - - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - OptionParsingStarting(nullptr); - } - - ~CommandOptions() override = default; - - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'a': - { - m_type = eLookupTypeAddress; - m_addr = Args::StringToAddress(execution_context, - option_arg, - LLDB_INVALID_ADDRESS, - &error); - } - break; - - case 'o': - m_offset = StringConvert::ToUInt64(option_arg, LLDB_INVALID_ADDRESS); - if (m_offset == LLDB_INVALID_ADDRESS) - error.SetErrorStringWithFormat ("invalid offset string '%s'", option_arg); - break; - - case 's': - m_str = option_arg; - m_type = eLookupTypeSymbol; - break; - - case 'f': - m_file.SetFile (option_arg, false); - m_type = eLookupTypeFileLine; - break; - - case 'i': - m_include_inlines = false; - break; - - case 'l': - m_line_number = StringConvert::ToUInt32(option_arg, UINT32_MAX); - if (m_line_number == UINT32_MAX) - error.SetErrorStringWithFormat ("invalid line number string '%s'", option_arg); - else if (m_line_number == 0) - error.SetErrorString ("zero is an invalid line number"); - m_type = eLookupTypeFileLine; - break; - - case 'F': - m_str = option_arg; - m_type = eLookupTypeFunction; - break; - - case 'n': - m_str = option_arg; - m_type = eLookupTypeFunctionOrSymbol; - break; - - case 't': - m_str = option_arg; - m_type = eLookupTypeType; - break; - - case 'v': - m_verbose = 1; - break; - - case 'A': - m_print_all = true; - break; - - case 'r': - m_use_regex = true; - break; - } - - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_type = eLookupTypeInvalid; - m_str.clear(); - m_file.Clear(); - m_addr = LLDB_INVALID_ADDRESS; - m_offset = 0; - m_line_number = 0; - m_use_regex = false; - m_include_inlines = true; - m_verbose = false; - m_print_all = false; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - int m_type; // Should be a eLookupTypeXXX enum after parsing options - std::string m_str; // Holds name lookup - FileSpec m_file; // Files for file lookups - lldb::addr_t m_addr; // Holds the address to lookup - lldb::addr_t m_offset; // Subtract this offset from m_addr before doing lookups. - uint32_t m_line_number; // Line number for file+line lookups - bool m_use_regex; // Name lookups in m_str are regular expressions. - bool m_include_inlines;// Check for inline entries when looking up by file/line. - bool m_verbose; // Enable verbose lookup info - bool m_print_all; // Print all matches, even in cases where there's a best match. - }; - - CommandObjectTargetModulesLookup (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "target modules lookup", - "Look up information within executable and dependent shared library images.", - nullptr, - eCommandRequiresTarget), - m_options() - { - CommandArgumentEntry arg; - CommandArgumentData file_arg; - - // Define the first (and only) variant of this arg. - file_arg.arg_type = eArgTypeFilename; - file_arg.arg_repetition = eArgRepeatStar; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (file_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); + enum { + eLookupTypeInvalid = -1, + eLookupTypeAddress = 0, + eLookupTypeSymbol, + eLookupTypeFileLine, // Line is optional + eLookupTypeFunction, + eLookupTypeFunctionOrSymbol, + eLookupTypeType, + kNumLookupTypes + }; + + class CommandOptions : public Options { + public: + CommandOptions() : Options() { OptionParsingStarting(nullptr); } + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'a': { + m_type = eLookupTypeAddress; + m_addr = Args::StringToAddress(execution_context, option_arg, + LLDB_INVALID_ADDRESS, &error); + } break; + + case 'o': + m_offset = StringConvert::ToUInt64(option_arg, LLDB_INVALID_ADDRESS); + if (m_offset == LLDB_INVALID_ADDRESS) + error.SetErrorStringWithFormat("invalid offset string '%s'", + option_arg); + break; + + case 's': + m_str = option_arg; + m_type = eLookupTypeSymbol; + break; + + case 'f': + m_file.SetFile(option_arg, false); + m_type = eLookupTypeFileLine; + break; + + case 'i': + m_include_inlines = false; + break; + + case 'l': + m_line_number = StringConvert::ToUInt32(option_arg, UINT32_MAX); + if (m_line_number == UINT32_MAX) + error.SetErrorStringWithFormat("invalid line number string '%s'", + option_arg); + else if (m_line_number == 0) + error.SetErrorString("zero is an invalid line number"); + m_type = eLookupTypeFileLine; + break; + + case 'F': + m_str = option_arg; + m_type = eLookupTypeFunction; + break; + + case 'n': + m_str = option_arg; + m_type = eLookupTypeFunctionOrSymbol; + break; + + case 't': + m_str = option_arg; + m_type = eLookupTypeType; + break; + + case 'v': + m_verbose = 1; + break; + + case 'A': + m_print_all = true; + break; + + case 'r': + m_use_regex = true; + break; + } + + return error; } - ~CommandObjectTargetModulesLookup() override = default; - - Options * - GetOptions () override - { - return &m_options; + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_type = eLookupTypeInvalid; + m_str.clear(); + m_file.Clear(); + m_addr = LLDB_INVALID_ADDRESS; + m_offset = 0; + m_line_number = 0; + m_use_regex = false; + m_include_inlines = true; + m_verbose = false; + m_print_all = false; } - bool - LookupHere (CommandInterpreter &interpreter, CommandReturnObject &result, bool &syntax_error) - { - switch (m_options.m_type) - { - case eLookupTypeAddress: - case eLookupTypeFileLine: - case eLookupTypeFunction: - case eLookupTypeFunctionOrSymbol: - case eLookupTypeSymbol: - default: - return false; - case eLookupTypeType: - break; - } - - StackFrameSP frame = m_exe_ctx.GetFrameSP(); + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + int m_type; // Should be a eLookupTypeXXX enum after parsing options + std::string m_str; // Holds name lookup + FileSpec m_file; // Files for file lookups + lldb::addr_t m_addr; // Holds the address to lookup + lldb::addr_t + m_offset; // Subtract this offset from m_addr before doing lookups. + uint32_t m_line_number; // Line number for file+line lookups + bool m_use_regex; // Name lookups in m_str are regular expressions. + bool m_include_inlines; // Check for inline entries when looking up by + // file/line. + bool m_verbose; // Enable verbose lookup info + bool m_print_all; // Print all matches, even in cases where there's a best + // match. + }; + + CommandObjectTargetModulesLookup(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "target modules lookup", + "Look up information within executable and " + "dependent shared library images.", + nullptr, eCommandRequiresTarget), + m_options() { + CommandArgumentEntry arg; + CommandArgumentData file_arg; + + // Define the first (and only) variant of this arg. + file_arg.arg_type = eArgTypeFilename; + file_arg.arg_repetition = eArgRepeatStar; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(file_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectTargetModulesLookup() override = default; + + Options *GetOptions() override { return &m_options; } + + bool LookupHere(CommandInterpreter &interpreter, CommandReturnObject &result, + bool &syntax_error) { + switch (m_options.m_type) { + case eLookupTypeAddress: + case eLookupTypeFileLine: + case eLookupTypeFunction: + case eLookupTypeFunctionOrSymbol: + case eLookupTypeSymbol: + default: + return false; + case eLookupTypeType: + break; + } - if (!frame) - return false; + StackFrameSP frame = m_exe_ctx.GetFrameSP(); - const SymbolContext &sym_ctx(frame->GetSymbolContext(eSymbolContextModule)); + if (!frame) + return false; - if (!sym_ctx.module_sp) - return false; + const SymbolContext &sym_ctx(frame->GetSymbolContext(eSymbolContextModule)); - switch (m_options.m_type) - { - default: - return false; - case eLookupTypeType: - if (!m_options.m_str.empty()) - { - if (LookupTypeHere (m_interpreter, - result.GetOutputStream(), - sym_ctx, - m_options.m_str.c_str(), - m_options.m_use_regex)) - { - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } - } - break; + if (!sym_ctx.module_sp) + return false; + + switch (m_options.m_type) { + default: + return false; + case eLookupTypeType: + if (!m_options.m_str.empty()) { + if (LookupTypeHere(m_interpreter, result.GetOutputStream(), sym_ctx, + m_options.m_str.c_str(), m_options.m_use_regex)) { + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; } - - return true; + } + break; } - bool - LookupInModule (CommandInterpreter &interpreter, Module *module, CommandReturnObject &result, bool &syntax_error) - { - switch (m_options.m_type) - { - case eLookupTypeAddress: - if (m_options.m_addr != LLDB_INVALID_ADDRESS) - { - if (LookupAddressInModule (m_interpreter, - result.GetOutputStream(), - module, - eSymbolContextEverything | (m_options.m_verbose ? static_cast<int>(eSymbolContextVariable) : 0), - m_options.m_addr, - m_options.m_offset, - m_options.m_verbose)) - { - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } - } - break; - - case eLookupTypeSymbol: - if (!m_options.m_str.empty()) - { - if (LookupSymbolInModule (m_interpreter, - result.GetOutputStream(), - module, - m_options.m_str.c_str(), - m_options.m_use_regex, - m_options.m_verbose)) - { - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } - } - break; - - case eLookupTypeFileLine: - if (m_options.m_file) - { - if (LookupFileAndLineInModule (m_interpreter, - result.GetOutputStream(), - module, - m_options.m_file, - m_options.m_line_number, - m_options.m_include_inlines, - m_options.m_verbose)) - { - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } - } - break; - - case eLookupTypeFunctionOrSymbol: - case eLookupTypeFunction: - if (!m_options.m_str.empty()) - { - if (LookupFunctionInModule (m_interpreter, - result.GetOutputStream(), - module, - m_options.m_str.c_str(), - m_options.m_use_regex, - m_options.m_include_inlines, - m_options.m_type == eLookupTypeFunctionOrSymbol, // include symbols - m_options.m_verbose)) - { - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } - } - break; - - case eLookupTypeType: - if (!m_options.m_str.empty()) - { - if (LookupTypeInModule (m_interpreter, - result.GetOutputStream(), - module, - m_options.m_str.c_str(), - m_options.m_use_regex)) - { - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } - } - break; - - default: - m_options.GenerateOptionUsage(result.GetErrorStream(), this, - GetCommandInterpreter() - .GetDebugger() - .GetTerminalWidth()); - syntax_error = true; - break; + return true; + } + + bool LookupInModule(CommandInterpreter &interpreter, Module *module, + CommandReturnObject &result, bool &syntax_error) { + switch (m_options.m_type) { + case eLookupTypeAddress: + if (m_options.m_addr != LLDB_INVALID_ADDRESS) { + if (LookupAddressInModule( + m_interpreter, result.GetOutputStream(), module, + eSymbolContextEverything | + (m_options.m_verbose + ? static_cast<int>(eSymbolContextVariable) + : 0), + m_options.m_addr, m_options.m_offset, m_options.m_verbose)) { + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; } - - result.SetStatus (eReturnStatusFailed); - return false; + } + break; + + case eLookupTypeSymbol: + if (!m_options.m_str.empty()) { + if (LookupSymbolInModule(m_interpreter, result.GetOutputStream(), + module, m_options.m_str.c_str(), + m_options.m_use_regex, m_options.m_verbose)) { + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } + } + break; + + case eLookupTypeFileLine: + if (m_options.m_file) { + if (LookupFileAndLineInModule( + m_interpreter, result.GetOutputStream(), module, + m_options.m_file, m_options.m_line_number, + m_options.m_include_inlines, m_options.m_verbose)) { + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } + } + break; + + case eLookupTypeFunctionOrSymbol: + case eLookupTypeFunction: + if (!m_options.m_str.empty()) { + if (LookupFunctionInModule( + m_interpreter, result.GetOutputStream(), module, + m_options.m_str.c_str(), m_options.m_use_regex, + m_options.m_include_inlines, + m_options.m_type == + eLookupTypeFunctionOrSymbol, // include symbols + m_options.m_verbose)) { + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } + } + break; + + case eLookupTypeType: + if (!m_options.m_str.empty()) { + if (LookupTypeInModule(m_interpreter, result.GetOutputStream(), module, + m_options.m_str.c_str(), + m_options.m_use_regex)) { + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } + } + break; + + default: + m_options.GenerateOptionUsage( + result.GetErrorStream(), this, + GetCommandInterpreter().GetDebugger().GetTerminalWidth()); + syntax_error = true; + break; } + result.SetStatus(eReturnStatusFailed); + return false; + } + protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) - { - result.AppendError ("invalid target, create a debug target using the 'target create' command"); - result.SetStatus (eReturnStatusFailed); - return false; + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (target == nullptr) { + result.AppendError("invalid target, create a debug target using the " + "'target create' command"); + result.SetStatus(eReturnStatusFailed); + return false; + } else { + bool syntax_error = false; + uint32_t i; + uint32_t num_successful_lookups = 0; + uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); + result.GetOutputStream().SetAddressByteSize(addr_byte_size); + result.GetErrorStream().SetAddressByteSize(addr_byte_size); + // Dump all sections for all modules images + + if (command.GetArgumentCount() == 0) { + ModuleSP current_module; + + // Where it is possible to look in the current symbol context + // first, try that. If this search was successful and --all + // was not passed, don't print anything else. + if (LookupHere(m_interpreter, result, syntax_error)) { + result.GetOutputStream().EOL(); + num_successful_lookups++; + if (!m_options.m_print_all) { + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); + } } - else - { - bool syntax_error = false; - uint32_t i; - uint32_t num_successful_lookups = 0; - uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); - result.GetOutputStream().SetAddressByteSize(addr_byte_size); - result.GetErrorStream().SetAddressByteSize(addr_byte_size); - // Dump all sections for all modules images - - if (command.GetArgumentCount() == 0) - { - ModuleSP current_module; - - // Where it is possible to look in the current symbol context - // first, try that. If this search was successful and --all - // was not passed, don't print anything else. - if (LookupHere (m_interpreter, result, syntax_error)) - { - result.GetOutputStream().EOL(); - num_successful_lookups++; - if (!m_options.m_print_all) - { - result.SetStatus (eReturnStatusSuccessFinishResult); - return result.Succeeded(); - } - } - // Dump all sections for all other modules - - const ModuleList &target_modules = target->GetImages(); - std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); - const size_t num_modules = target_modules.GetSize(); - if (num_modules > 0) - { - for (i = 0; i < num_modules && !syntax_error; ++i) - { - Module *module_pointer = target_modules.GetModulePointerAtIndexUnlocked(i); - - if (module_pointer != current_module.get() && - LookupInModule (m_interpreter, target_modules.GetModulePointerAtIndexUnlocked(i), result, syntax_error)) - { - result.GetOutputStream().EOL(); - num_successful_lookups++; - } - } - } - else - { - result.AppendError ("the target has no associated executable images"); - result.SetStatus (eReturnStatusFailed); - return false; - } + // Dump all sections for all other modules + + const ModuleList &target_modules = target->GetImages(); + std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); + const size_t num_modules = target_modules.GetSize(); + if (num_modules > 0) { + for (i = 0; i < num_modules && !syntax_error; ++i) { + Module *module_pointer = + target_modules.GetModulePointerAtIndexUnlocked(i); + + if (module_pointer != current_module.get() && + LookupInModule( + m_interpreter, + target_modules.GetModulePointerAtIndexUnlocked(i), result, + syntax_error)) { + result.GetOutputStream().EOL(); + num_successful_lookups++; } - else - { - // Dump specified images (by basename or fullpath) - const char *arg_cstr; - for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != nullptr && !syntax_error; ++i) - { - ModuleList module_list; - const size_t num_matches = FindModulesByName (target, arg_cstr, module_list, false); - if (num_matches > 0) - { - for (size_t j=0; j<num_matches; ++j) - { - Module *module = module_list.GetModulePointerAtIndex(j); - if (module) - { - if (LookupInModule (m_interpreter, module, result, syntax_error)) - { - result.GetOutputStream().EOL(); - num_successful_lookups++; - } - } - } - } - else - result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr); + } + } else { + result.AppendError("the target has no associated executable images"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + // Dump specified images (by basename or fullpath) + const char *arg_cstr; + for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != nullptr && + !syntax_error; + ++i) { + ModuleList module_list; + const size_t num_matches = + FindModulesByName(target, arg_cstr, module_list, false); + if (num_matches > 0) { + for (size_t j = 0; j < num_matches; ++j) { + Module *module = module_list.GetModulePointerAtIndex(j); + if (module) { + if (LookupInModule(m_interpreter, module, result, + syntax_error)) { + result.GetOutputStream().EOL(); + num_successful_lookups++; } + } } - - if (num_successful_lookups > 0) - result.SetStatus (eReturnStatusSuccessFinishResult); - else - result.SetStatus (eReturnStatusFailed); + } else + result.AppendWarningWithFormat( + "Unable to find an image that matches '%s'.\n", arg_cstr); } - return result.Succeeded(); + } + + if (num_successful_lookups > 0) + result.SetStatus(eReturnStatusSuccessFinishResult); + else + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } - CommandOptions m_options; + CommandOptions m_options; }; OptionDefinition -CommandObjectTargetModulesLookup::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectTargetModulesLookup::CommandOptions::g_option_table[] = + { + // clang-format off {LLDB_OPT_SET_1, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Lookup an address in one or more target modules."}, {LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "When looking up an address subtract <offset> from any addresses before doing the lookup."}, /* FIXME: re-enable regex for types when the LookupTypeInModule actually uses the regex option: | LLDB_OPT_SET_6 */ @@ -4340,7 +3819,7 @@ CommandObjectTargetModulesLookup::CommandOptions::g_option_table[] = {LLDB_OPT_SET_ALL, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable verbose lookup information."}, {LLDB_OPT_SET_ALL, false, "all", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Print all matches, not just the best match, if a best match is available."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; #pragma mark CommandObjectMultiwordImageSearchPaths @@ -4349,22 +3828,33 @@ CommandObjectTargetModulesLookup::CommandOptions::g_option_table[] = // CommandObjectMultiwordImageSearchPaths //------------------------------------------------------------------------- -class CommandObjectTargetModulesImageSearchPaths : public CommandObjectMultiword -{ +class CommandObjectTargetModulesImageSearchPaths + : public CommandObjectMultiword { public: - CommandObjectTargetModulesImageSearchPaths(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "target modules search-paths", - "Commands for managing module search paths for a target.", - "target modules search-paths <subcommand> [<subcommand-options>]") - { - LoadSubCommand ("add", CommandObjectSP (new CommandObjectTargetModulesSearchPathsAdd (interpreter))); - LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTargetModulesSearchPathsClear (interpreter))); - LoadSubCommand ("insert", CommandObjectSP (new CommandObjectTargetModulesSearchPathsInsert (interpreter))); - LoadSubCommand ("list", CommandObjectSP (new CommandObjectTargetModulesSearchPathsList (interpreter))); - LoadSubCommand ("query", CommandObjectSP (new CommandObjectTargetModulesSearchPathsQuery (interpreter))); - } - - ~CommandObjectTargetModulesImageSearchPaths() override = default; + CommandObjectTargetModulesImageSearchPaths(CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "target modules search-paths", + "Commands for managing module search paths for a target.", + "target modules search-paths <subcommand> [<subcommand-options>]") { + LoadSubCommand( + "add", CommandObjectSP( + new CommandObjectTargetModulesSearchPathsAdd(interpreter))); + LoadSubCommand( + "clear", CommandObjectSP(new CommandObjectTargetModulesSearchPathsClear( + interpreter))); + LoadSubCommand( + "insert", + CommandObjectSP( + new CommandObjectTargetModulesSearchPathsInsert(interpreter))); + LoadSubCommand( + "list", CommandObjectSP(new CommandObjectTargetModulesSearchPathsList( + interpreter))); + LoadSubCommand( + "query", CommandObjectSP(new CommandObjectTargetModulesSearchPathsQuery( + interpreter))); + } + + ~CommandObjectTargetModulesImageSearchPaths() override = default; }; #pragma mark CommandObjectTargetModules @@ -4373,455 +3863,431 @@ public: // CommandObjectTargetModules //------------------------------------------------------------------------- -class CommandObjectTargetModules : public CommandObjectMultiword -{ +class CommandObjectTargetModules : public CommandObjectMultiword { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - CommandObjectTargetModules(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "target modules", - "Commands for accessing information for one or more target modules.", - "target modules <sub-command> ...") - { - LoadSubCommand ("add", CommandObjectSP (new CommandObjectTargetModulesAdd (interpreter))); - LoadSubCommand ("load", CommandObjectSP (new CommandObjectTargetModulesLoad (interpreter))); - LoadSubCommand ("dump", CommandObjectSP (new CommandObjectTargetModulesDump (interpreter))); - LoadSubCommand ("list", CommandObjectSP (new CommandObjectTargetModulesList (interpreter))); - LoadSubCommand ("lookup", CommandObjectSP (new CommandObjectTargetModulesLookup (interpreter))); - LoadSubCommand ("search-paths", CommandObjectSP (new CommandObjectTargetModulesImageSearchPaths (interpreter))); - LoadSubCommand ("show-unwind", CommandObjectSP (new CommandObjectTargetModulesShowUnwind (interpreter))); - - } - - ~CommandObjectTargetModules() override = default; + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + CommandObjectTargetModules(CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "target modules", + "Commands for accessing information for one or " + "more target modules.", + "target modules <sub-command> ...") { + LoadSubCommand( + "add", CommandObjectSP(new CommandObjectTargetModulesAdd(interpreter))); + LoadSubCommand("load", CommandObjectSP(new CommandObjectTargetModulesLoad( + interpreter))); + LoadSubCommand("dump", CommandObjectSP(new CommandObjectTargetModulesDump( + interpreter))); + LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetModulesList( + interpreter))); + LoadSubCommand( + "lookup", + CommandObjectSP(new CommandObjectTargetModulesLookup(interpreter))); + LoadSubCommand( + "search-paths", + CommandObjectSP( + new CommandObjectTargetModulesImageSearchPaths(interpreter))); + LoadSubCommand( + "show-unwind", + CommandObjectSP(new CommandObjectTargetModulesShowUnwind(interpreter))); + } + + ~CommandObjectTargetModules() override = default; private: - //------------------------------------------------------------------ - // For CommandObjectTargetModules only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN (CommandObjectTargetModules); + //------------------------------------------------------------------ + // For CommandObjectTargetModules only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN(CommandObjectTargetModules); }; -class CommandObjectTargetSymbolsAdd : public CommandObjectParsed -{ +class CommandObjectTargetSymbolsAdd : public CommandObjectParsed { public: - CommandObjectTargetSymbolsAdd (CommandInterpreter &interpreter) : - 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.", - "target symbols add [<symfile>]", eCommandRequiresTarget), + CommandObjectTargetSymbolsAdd(CommandInterpreter &interpreter) + : 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.", + "target symbols add [<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."), - m_current_frame_option (LLDB_OPT_SET_2, false, "frame", 'F', "Locate the debug symbols the currently selected frame.", false, true) - - { - m_option_group.Append (&m_uuid_option_group, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Append (&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Append (&m_current_frame_option, LLDB_OPT_SET_2, LLDB_OPT_SET_2); - m_option_group.Finalize(); - } - - ~CommandObjectTargetSymbolsAdd() override = default; - - int - HandleArgumentCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - OptionElementVector &opt_element_vector, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) override - { - std::string completion_str (input.GetArgumentAtIndex(cursor_index)); - completion_str.erase (cursor_char_position); - - CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(), - CommandCompletions::eDiskFileCompletion, - completion_str.c_str(), - match_start_point, - max_return_elements, - nullptr, - word_complete, - matches); - return matches.GetSize(); - } - - Options * - GetOptions () override - { - return &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."), + m_current_frame_option( + LLDB_OPT_SET_2, false, "frame", 'F', + "Locate the debug symbols the currently selected frame.", false, + true) + + { + m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL, + LLDB_OPT_SET_1); + m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append(&m_current_frame_option, LLDB_OPT_SET_2, + LLDB_OPT_SET_2); + m_option_group.Finalize(); + } + + ~CommandObjectTargetSymbolsAdd() override = default; + + int HandleArgumentCompletion(Args &input, int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, int max_return_elements, + bool &word_complete, + StringList &matches) override { + std::string completion_str(input.GetArgumentAtIndex(cursor_index)); + completion_str.erase(cursor_char_position); + + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, + completion_str.c_str(), match_start_point, max_return_elements, nullptr, + word_complete, matches); + return matches.GetSize(); + } + + Options *GetOptions() override { return &m_option_group; } protected: - bool - AddModuleSymbols (Target *target, - ModuleSpec &module_spec, - bool &flush, - CommandReturnObject &result) - { - const FileSpec &symbol_fspec = module_spec.GetSymbolFileSpec(); - if (symbol_fspec) - { - char symfile_path[PATH_MAX]; - symbol_fspec.GetPath (symfile_path, sizeof(symfile_path)); - - if (!module_spec.GetUUID().IsValid()) - { - if (!module_spec.GetFileSpec() && !module_spec.GetPlatformFileSpec()) - 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; - - 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(), 0, 0, symfile_module_specs)) - { - // Now extract the module spec that matches the target architecture - ModuleSpec target_arch_module_spec; - ModuleSpec symfile_module_spec; - 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(); - num_matches = target->GetImages().FindModules (symfile_uuid_module_spec, matching_module_list); - } - } - - 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 (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 - ModuleSpec symfile_uuid_module_spec; - symfile_uuid_module_spec.GetUUID() = symfile_module_spec.GetUUID(); - num_matches = target->GetImages().FindModules (symfile_uuid_module_spec, matching_module_list); - } - } - } - } - } - - // Just try to match up the file by basename if we have no matches at this point - if (num_matches == 0) - num_matches = target->GetImages().FindModules (module_spec, matching_module_list); - - while (num_matches == 0) - { - ConstString filename_no_extension(module_spec.GetFileSpec().GetFileNameStrippingExtension()); - // Empty string returned, lets bail - if (!filename_no_extension) - break; - - // Check if there was no extension to strip and the basename is the same - if (filename_no_extension == module_spec.GetFileSpec().GetFilename()) - break; - - // Replace basename with one less extension - module_spec.GetFileSpec().GetFilename() = filename_no_extension; + bool AddModuleSymbols(Target *target, ModuleSpec &module_spec, bool &flush, + CommandReturnObject &result) { + const FileSpec &symbol_fspec = module_spec.GetSymbolFileSpec(); + if (symbol_fspec) { + char symfile_path[PATH_MAX]; + symbol_fspec.GetPath(symfile_path, sizeof(symfile_path)); + + if (!module_spec.GetUUID().IsValid()) { + if (!module_spec.GetFileSpec() && !module_spec.GetPlatformFileSpec()) + 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; + + 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(), + 0, 0, symfile_module_specs)) { + // Now extract the module spec that matches the target architecture + ModuleSpec target_arch_module_spec; + ModuleSpec symfile_module_spec; + 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(); + num_matches = target->GetImages().FindModules( + symfile_uuid_module_spec, matching_module_list); + } + } - num_matches = target->GetImages().FindModules (module_spec, matching_module_list); + 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 (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 + ModuleSpec symfile_uuid_module_spec; + symfile_uuid_module_spec.GetUUID() = + symfile_module_spec.GetUUID(); + num_matches = target->GetImages().FindModules( + symfile_uuid_module_spec, matching_module_list); + } } - - if (num_matches > 1) - { - result.AppendErrorWithFormat ("multiple modules match symbol file '%s', use the --uuid option to resolve the ambiguity.\n", symfile_path); + } + } + } + + // Just try to match up the file by basename if we have no matches at this + // point + if (num_matches == 0) + num_matches = + target->GetImages().FindModules(module_spec, matching_module_list); + + while (num_matches == 0) { + ConstString filename_no_extension( + module_spec.GetFileSpec().GetFileNameStrippingExtension()); + // Empty string returned, lets bail + if (!filename_no_extension) + break; + + // Check if there was no extension to strip and the basename is the same + if (filename_no_extension == module_spec.GetFileSpec().GetFilename()) + break; + + // Replace basename with one less extension + module_spec.GetFileSpec().GetFilename() = filename_no_extension; + + num_matches = + target->GetImages().FindModules(module_spec, matching_module_list); + } + + if (num_matches > 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)); + + // 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 decides to create it! + module_sp->SetSymbolFileFileSpec(symbol_fspec); + + SymbolVendor *symbol_vendor = + module_sp->GetSymbolVendor(true, &result.GetErrorStream()); + if (symbol_vendor) { + SymbolFile *symbol_file = symbol_vendor->GetSymbolFile(); + + 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(); + result.AppendMessageWithFormat( + "symbol file '%s' has been added to '%s'\n", symfile_path, + module_fs.GetPath().c_str()); + + // Let clients know something changed in the module + // if it is currently loaded + ModuleList module_list; + module_list.Append(module_sp); + target->SymbolsDidLoad(module_list); + + // Make sure we load any scripting resources that may be embedded + // in the debug info files in case the platform supports that. + Error error; + StreamString feedback_stream; + module_sp->LoadScriptingResourceInTarget(target, error, + &feedback_stream); + if (error.Fail() && error.AsCString()) + result.AppendWarningWithFormat( + "unable to load scripting data for module %s - error " + "reported was %s", + module_sp->GetFileSpec() + .GetFileNameStrippingExtension() + .GetCString(), + error.AsCString()); + else if (feedback_stream.GetSize()) + result.AppendWarningWithFormat("%s", feedback_stream.GetData()); + + flush = true; + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; } - else if (num_matches == 1) - { - ModuleSP module_sp (matching_module_list.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 decides to create it! - module_sp->SetSymbolFileFileSpec (symbol_fspec); - - SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(true, &result.GetErrorStream()); - if (symbol_vendor) - { - SymbolFile *symbol_file = symbol_vendor->GetSymbolFile(); - - 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(); - result.AppendMessageWithFormat("symbol file '%s' has been added to '%s'\n", - symfile_path, - module_fs.GetPath().c_str()); - - // Let clients know something changed in the module - // if it is currently loaded - ModuleList module_list; - module_list.Append (module_sp); - target->SymbolsDidLoad (module_list); - - // Make sure we load any scripting resources that may be embedded - // in the debug info files in case the platform supports that. - Error error; - StreamString feedback_stream; - module_sp->LoadScriptingResourceInTarget (target, error,&feedback_stream); - if (error.Fail() && error.AsCString()) - result.AppendWarningWithFormat("unable to load scripting data for module %s - error reported was %s", - module_sp->GetFileSpec().GetFileNameStrippingExtension().GetCString(), - error.AsCString()); - else if (feedback_stream.GetSize()) - result.AppendWarningWithFormat("%s",feedback_stream.GetData()); - - flush = true; - result.SetStatus (eReturnStatusSuccessFinishResult); - return true; - } - } + } + } + // Clear the symbol file spec if anything went wrong + module_sp->SetSymbolFileFileSpec(FileSpec()); + } + + if (module_spec.GetUUID().IsValid()) { + StreamString ss_symfile_uuid; + module_spec.GetUUID().Dump(&ss_symfile_uuid); + result.AppendErrorWithFormat( + "symbol file '%s' (%s) does not match any existing module%s\n", + symfile_path, ss_symfile_uuid.GetData(), + (symbol_fspec.GetFileType() != FileSpec::eFileTypeRegular) + ? "\n please specify the full path to the symbol file" + : ""); + } else { + result.AppendErrorWithFormat( + "symbol file '%s' does not match any existing module%s\n", + symfile_path, + (symbol_fspec.GetFileType() != FileSpec::eFileTypeRegular) + ? "\n please specify the full path to the symbol file" + : ""); + } + } else { + result.AppendError( + "one or more executable image paths must be specified"); + } + result.SetStatus(eReturnStatusFailed); + return false; + } + + bool DoExecute(Args &args, CommandReturnObject &result) override { + Target *target = m_exe_ctx.GetTargetPtr(); + result.SetStatus(eReturnStatusFailed); + bool flush = false; + ModuleSpec module_spec; + const bool uuid_option_set = + m_uuid_option_group.GetOptionValue().OptionWasSet(); + const bool file_option_set = m_file_option.GetOptionValue().OptionWasSet(); + const bool frame_option_set = + m_current_frame_option.GetOptionValue().OptionWasSet(); + const size_t argc = args.GetArgumentCount(); + + if (argc == 0) { + if (uuid_option_set || file_option_set || frame_option_set) { + bool success = false; + bool error_set = false; + if (frame_option_set) { + Process *process = m_exe_ctx.GetProcessPtr(); + if (process) { + const StateType process_state = process->GetState(); + if (StateIsStoppedState(process_state, true)) { + StackFrame *frame = m_exe_ctx.GetFramePtr(); + if (frame) { + ModuleSP frame_module_sp( + frame->GetSymbolContext(eSymbolContextModule).module_sp); + if (frame_module_sp) { + if (frame_module_sp->GetPlatformFileSpec().Exists()) { + module_spec.GetArchitecture() = + frame_module_sp->GetArchitecture(); + module_spec.GetFileSpec() = + frame_module_sp->GetPlatformFileSpec(); + } + module_spec.GetUUID() = frame_module_sp->GetUUID(); + success = module_spec.GetUUID().IsValid() || + module_spec.GetFileSpec(); + } else { + result.AppendError("frame has no module"); + error_set = true; } - // Clear the symbol file spec if anything went wrong - module_sp->SetSymbolFileFileSpec (FileSpec()); - } - - if (module_spec.GetUUID().IsValid()) - { - StreamString ss_symfile_uuid; - module_spec.GetUUID().Dump(&ss_symfile_uuid); - result.AppendErrorWithFormat ("symbol file '%s' (%s) does not match any existing module%s\n", - symfile_path, - ss_symfile_uuid.GetData(), - (symbol_fspec.GetFileType() != FileSpec::eFileTypeRegular) - ? "\n please specify the full path to the symbol file" - : ""); + } else { + result.AppendError("invalid current frame"); + error_set = true; + } + } else { + result.AppendErrorWithFormat("process is not stopped: %s", + StateAsCString(process_state)); + error_set = true; } - else - { - result.AppendErrorWithFormat ("symbol file '%s' does not match any existing module%s\n", - symfile_path, - (symbol_fspec.GetFileType() != FileSpec::eFileTypeRegular) - ? "\n please specify the full path to the symbol file" - : ""); + } else { + result.AppendError( + "a process must exist in order to use the --frame option"); + error_set = true; + } + } else { + if (uuid_option_set) { + module_spec.GetUUID() = + m_uuid_option_group.GetOptionValue().GetCurrentValue(); + success |= module_spec.GetUUID().IsValid(); + } else if (file_option_set) { + module_spec.GetFileSpec() = + m_file_option.GetOptionValue().GetCurrentValue(); + ModuleSP module_sp( + target->GetImages().FindFirstModule(module_spec)); + if (module_sp) { + module_spec.GetFileSpec() = module_sp->GetFileSpec(); + module_spec.GetPlatformFileSpec() = + module_sp->GetPlatformFileSpec(); + module_spec.GetUUID() = module_sp->GetUUID(); + module_spec.GetArchitecture() = module_sp->GetArchitecture(); + } else { + module_spec.GetArchitecture() = target->GetArchitecture(); } + success |= module_spec.GetUUID().IsValid() || + module_spec.GetFileSpec().Exists(); + } } - else - { - result.AppendError ("one or more executable image paths must be specified"); - } - result.SetStatus (eReturnStatusFailed); - return false; - } - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - Target *target = m_exe_ctx.GetTargetPtr(); - result.SetStatus (eReturnStatusFailed); - bool flush = false; - ModuleSpec module_spec; - const bool uuid_option_set = m_uuid_option_group.GetOptionValue().OptionWasSet(); - const bool file_option_set = m_file_option.GetOptionValue().OptionWasSet(); - const bool frame_option_set = m_current_frame_option.GetOptionValue().OptionWasSet(); - const size_t argc = args.GetArgumentCount(); - - if (argc == 0) - { - if (uuid_option_set || file_option_set || frame_option_set) - { - bool success = false; - bool error_set = false; - if (frame_option_set) - { - Process *process = m_exe_ctx.GetProcessPtr(); - if (process) - { - const StateType process_state = process->GetState(); - if (StateIsStoppedState (process_state, true)) - { - StackFrame *frame = m_exe_ctx.GetFramePtr(); - if (frame) - { - ModuleSP frame_module_sp (frame->GetSymbolContext(eSymbolContextModule).module_sp); - if (frame_module_sp) - { - if (frame_module_sp->GetPlatformFileSpec().Exists()) - { - module_spec.GetArchitecture() = frame_module_sp->GetArchitecture(); - module_spec.GetFileSpec() = frame_module_sp->GetPlatformFileSpec(); - } - module_spec.GetUUID() = frame_module_sp->GetUUID(); - success = module_spec.GetUUID().IsValid() || module_spec.GetFileSpec(); - } - else - { - result.AppendError ("frame has no module"); - error_set = true; - } - } - else - { - result.AppendError ("invalid current frame"); - error_set = true; - } - } - else - { - result.AppendErrorWithFormat ("process is not stopped: %s", StateAsCString(process_state)); - error_set = true; - } - } - else - { - result.AppendError ("a process must exist in order to use the --frame option"); - error_set = true; - } - } - else - { - if (uuid_option_set) - { - module_spec.GetUUID() = m_uuid_option_group.GetOptionValue().GetCurrentValue(); - success |= module_spec.GetUUID().IsValid(); - } - else if (file_option_set) - { - module_spec.GetFileSpec() = m_file_option.GetOptionValue().GetCurrentValue(); - ModuleSP module_sp (target->GetImages().FindFirstModule(module_spec)); - if (module_sp) - { - module_spec.GetFileSpec() = module_sp->GetFileSpec(); - module_spec.GetPlatformFileSpec() = module_sp->GetPlatformFileSpec(); - module_spec.GetUUID() = module_sp->GetUUID(); - module_spec.GetArchitecture() = module_sp->GetArchitecture(); - } - else - { - module_spec.GetArchitecture() = target->GetArchitecture(); - } - success |= module_spec.GetUUID().IsValid() || module_spec.GetFileSpec().Exists(); - } - } - - if (success) - { - if (Symbols::DownloadObjectAndSymbolFile (module_spec)) - { - if (module_spec.GetSymbolFileSpec()) - success = AddModuleSymbols (target, module_spec, flush, result); - } - } + if (success) { + if (Symbols::DownloadObjectAndSymbolFile(module_spec)) { + if (module_spec.GetSymbolFileSpec()) + success = AddModuleSymbols(target, module_spec, flush, result); + } + } - if (!success && !error_set) - { - StreamString error_strm; - if (uuid_option_set) - { - error_strm.PutCString("unable to find debug symbols for UUID "); - module_spec.GetUUID().Dump (&error_strm); - } - else if (file_option_set) - { - error_strm.PutCString("unable to find debug symbols for the executable file "); - error_strm << module_spec.GetFileSpec(); - } - else if (frame_option_set) - { - error_strm.PutCString("unable to find debug symbols for the current frame"); - } - result.AppendError (error_strm.GetData()); - } - } - else - { - result.AppendError ("one or more symbol file paths must be specified, or options must be specified"); - } + if (!success && !error_set) { + StreamString error_strm; + if (uuid_option_set) { + error_strm.PutCString("unable to find debug symbols for UUID "); + module_spec.GetUUID().Dump(&error_strm); + } else if (file_option_set) { + error_strm.PutCString( + "unable to find debug symbols for the executable file "); + error_strm << module_spec.GetFileSpec(); + } else if (frame_option_set) { + error_strm.PutCString( + "unable to find debug symbols for the current frame"); + } + result.AppendError(error_strm.GetData()); } - else - { - if (uuid_option_set) - { - result.AppendError ("specify either one or more paths to symbol files or use the --uuid option without arguments"); - } - else if (file_option_set) - { - result.AppendError ("specify either one or more paths to symbol files or use the --file option without arguments"); + } else { + result.AppendError("one or more symbol file paths must be specified, " + "or options must be specified"); + } + } else { + if (uuid_option_set) { + result.AppendError("specify either one or more paths to symbol files " + "or use the --uuid option without arguments"); + } else if (file_option_set) { + result.AppendError("specify either one or more paths to symbol files " + "or use the --file option without arguments"); + } else if (frame_option_set) { + result.AppendError("specify either one or more paths to symbol files " + "or use the --frame option without arguments"); + } else { + PlatformSP platform_sp(target->GetPlatform()); + + for (size_t i = 0; i < argc; ++i) { + const char *symfile_path = args.GetArgumentAtIndex(i); + if (symfile_path) { + module_spec.GetSymbolFileSpec().SetFile(symfile_path, true); + if (platform_sp) { + FileSpec symfile_spec; + if (platform_sp + ->ResolveSymbolFile(*target, module_spec, symfile_spec) + .Success()) + module_spec.GetSymbolFileSpec() = symfile_spec; } - else if (frame_option_set) - { - result.AppendError ("specify either one or more paths to symbol files or use the --frame option without arguments"); - } - else - { - PlatformSP platform_sp (target->GetPlatform()); - - for (size_t i = 0; i < argc; ++i) - { - const char *symfile_path = args.GetArgumentAtIndex(i); - if (symfile_path) - { - module_spec.GetSymbolFileSpec().SetFile(symfile_path, true); - if (platform_sp) - { - FileSpec symfile_spec; - if (platform_sp->ResolveSymbolFile(*target, module_spec, symfile_spec).Success()) - module_spec.GetSymbolFileSpec() = symfile_spec; - } - ArchSpec arch; - bool symfile_exists = module_spec.GetSymbolFileSpec().Exists(); + ArchSpec arch; + bool symfile_exists = module_spec.GetSymbolFileSpec().Exists(); - if (symfile_exists) - { - if (!AddModuleSymbols (target, module_spec, flush, result)) - break; - } - else - { - char resolved_symfile_path[PATH_MAX]; - if (module_spec.GetSymbolFileSpec().GetPath (resolved_symfile_path, sizeof(resolved_symfile_path))) - { - if (strcmp (resolved_symfile_path, symfile_path) != 0) - { - result.AppendErrorWithFormat ("invalid module path '%s' with resolved path '%s'\n", symfile_path, resolved_symfile_path); - break; - } - } - result.AppendErrorWithFormat ("invalid module path '%s'\n", symfile_path); - break; - } - } + if (symfile_exists) { + if (!AddModuleSymbols(target, module_spec, flush, result)) + break; + } else { + char resolved_symfile_path[PATH_MAX]; + if (module_spec.GetSymbolFileSpec().GetPath( + resolved_symfile_path, sizeof(resolved_symfile_path))) { + if (strcmp(resolved_symfile_path, symfile_path) != 0) { + result.AppendErrorWithFormat( + "invalid module path '%s' with resolved path '%s'\n", + symfile_path, resolved_symfile_path); + break; } + } + result.AppendErrorWithFormat("invalid module path '%s'\n", + symfile_path); + break; } + } } + } + } - if (flush) - { - Process *process = m_exe_ctx.GetProcessPtr(); - if (process) - process->Flush(); - } - return result.Succeeded(); + if (flush) { + Process *process = m_exe_ctx.GetProcessPtr(); + if (process) + process->Flush(); } + return result.Succeeded(); + } - OptionGroupOptions m_option_group; - OptionGroupUUID m_uuid_option_group; - OptionGroupFile m_file_option; - OptionGroupBoolean m_current_frame_option; + OptionGroupOptions m_option_group; + OptionGroupUUID m_uuid_option_group; + OptionGroupFile m_file_option; + OptionGroupBoolean m_current_frame_option; }; #pragma mark CommandObjectTargetSymbols @@ -4830,26 +4296,27 @@ protected: // CommandObjectTargetSymbols //------------------------------------------------------------------------- -class CommandObjectTargetSymbols : public CommandObjectMultiword -{ +class CommandObjectTargetSymbols : public CommandObjectMultiword { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - CommandObjectTargetSymbols(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "target symbols", "Commands for adding and managing debug symbol files.", - "target symbols <sub-command> ...") - { - LoadSubCommand ("add", CommandObjectSP (new CommandObjectTargetSymbolsAdd (interpreter))); - } - - ~CommandObjectTargetSymbols() override = default; + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + CommandObjectTargetSymbols(CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "target symbols", + "Commands for adding and managing debug symbol files.", + "target symbols <sub-command> ...") { + LoadSubCommand( + "add", CommandObjectSP(new CommandObjectTargetSymbolsAdd(interpreter))); + } + + ~CommandObjectTargetSymbols() override = default; private: - //------------------------------------------------------------------ - // For CommandObjectTargetModules only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN (CommandObjectTargetSymbols); + //------------------------------------------------------------------ + // For CommandObjectTargetModules only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN(CommandObjectTargetSymbols); }; #pragma mark CommandObjectTargetStopHookAdd @@ -4858,339 +4325,308 @@ private: // CommandObjectTargetStopHookAdd //------------------------------------------------------------------------- -class CommandObjectTargetStopHookAdd : - public CommandObjectParsed, - public IOHandlerDelegateMultiline -{ +class CommandObjectTargetStopHookAdd : public CommandObjectParsed, + public IOHandlerDelegateMultiline { public: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options(), - m_line_start(0), - m_line_end (UINT_MAX), - m_func_name_type_mask (eFunctionNameTypeAuto), - m_sym_ctx_specified (false), - m_thread_specified (false), - m_use_one_liner (false), - m_one_liner() - { - } - - ~CommandOptions() override = default; - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - bool success; - - switch (short_option) - { - case 'c': - m_class_name = option_arg; - m_sym_ctx_specified = true; - break; - - case 'e': - m_line_end = StringConvert::ToUInt32 (option_arg, UINT_MAX, 0, &success); - if (!success) - { - error.SetErrorStringWithFormat ("invalid end line number: \"%s\"", option_arg); - break; - } - m_sym_ctx_specified = true; - break; - - case 'l': - m_line_start = StringConvert::ToUInt32 (option_arg, 0, 0, &success); - if (!success) - { - error.SetErrorStringWithFormat ("invalid start line number: \"%s\"", option_arg); - break; - } - m_sym_ctx_specified = true; - break; - - case 'i': - m_no_inlines = true; - break; - - case 'n': - m_function_name = option_arg; - m_func_name_type_mask |= eFunctionNameTypeAuto; - m_sym_ctx_specified = true; - break; - - case 'f': - m_file_name = option_arg; - m_sym_ctx_specified = true; - break; - - case 's': - m_module_name = option_arg; - m_sym_ctx_specified = true; - break; - - case 't' : - m_thread_id = StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); - if (m_thread_id == LLDB_INVALID_THREAD_ID) - error.SetErrorStringWithFormat ("invalid thread id string '%s'", option_arg); - m_thread_specified = true; - break; - - case 'T': - m_thread_name = option_arg; - m_thread_specified = true; - break; - - case 'q': - m_queue_name = option_arg; - m_thread_specified = true; - break; - - case 'x': - m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); - if (m_thread_id == UINT32_MAX) - error.SetErrorStringWithFormat ("invalid thread index string '%s'", option_arg); - m_thread_specified = true; - break; - - case 'o': - m_use_one_liner = true; - m_one_liner = option_arg; - break; - - default: - error.SetErrorStringWithFormat ("unrecognized option %c.", short_option); - break; - } - return error; + class CommandOptions : public Options { + public: + CommandOptions() + : Options(), m_line_start(0), m_line_end(UINT_MAX), + m_func_name_type_mask(eFunctionNameTypeAuto), + m_sym_ctx_specified(false), m_thread_specified(false), + m_use_one_liner(false), m_one_liner() {} + + ~CommandOptions() override = default; + + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + bool success; + + switch (short_option) { + case 'c': + m_class_name = option_arg; + m_sym_ctx_specified = true; + break; + + case 'e': + m_line_end = StringConvert::ToUInt32(option_arg, UINT_MAX, 0, &success); + if (!success) { + error.SetErrorStringWithFormat("invalid end line number: \"%s\"", + option_arg); + break; } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_class_name.clear(); - m_function_name.clear(); - m_line_start = 0; - m_line_end = UINT_MAX; - m_file_name.clear(); - m_module_name.clear(); - m_func_name_type_mask = eFunctionNameTypeAuto; - m_thread_id = LLDB_INVALID_THREAD_ID; - m_thread_index = UINT32_MAX; - m_thread_name.clear(); - m_queue_name.clear(); - - m_no_inlines = false; - m_sym_ctx_specified = false; - m_thread_specified = false; - - m_use_one_liner = false; - m_one_liner.clear(); + m_sym_ctx_specified = true; + break; + + case 'l': + m_line_start = StringConvert::ToUInt32(option_arg, 0, 0, &success); + if (!success) { + error.SetErrorStringWithFormat("invalid start line number: \"%s\"", + option_arg); + break; } - - static OptionDefinition g_option_table[]; - - std::string m_class_name; - std::string m_function_name; - uint32_t m_line_start; - uint32_t m_line_end; - std::string m_file_name; - std::string m_module_name; - uint32_t m_func_name_type_mask; // A pick from lldb::FunctionNameType. - lldb::tid_t m_thread_id; - uint32_t m_thread_index; - std::string m_thread_name; - std::string m_queue_name; - bool m_sym_ctx_specified; - bool m_no_inlines; - bool m_thread_specified; - // Instance variables to hold the values for one_liner options. - bool m_use_one_liner; - std::string m_one_liner; - }; - - CommandObjectTargetStopHookAdd (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "target stop-hook add", - "Add a hook to be executed when the target stops.", - "target stop-hook add"), - IOHandlerDelegateMultiline ("DONE", IOHandlerDelegate::Completion::LLDBCommand), - m_options() - { + m_sym_ctx_specified = true; + break; + + case 'i': + m_no_inlines = true; + break; + + case 'n': + m_function_name = option_arg; + m_func_name_type_mask |= eFunctionNameTypeAuto; + m_sym_ctx_specified = true; + break; + + case 'f': + m_file_name = option_arg; + m_sym_ctx_specified = true; + break; + + case 's': + m_module_name = option_arg; + m_sym_ctx_specified = true; + break; + + case 't': + m_thread_id = + StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); + if (m_thread_id == LLDB_INVALID_THREAD_ID) + error.SetErrorStringWithFormat("invalid thread id string '%s'", + option_arg); + m_thread_specified = true; + break; + + case 'T': + m_thread_name = option_arg; + m_thread_specified = true; + break; + + case 'q': + m_queue_name = option_arg; + m_thread_specified = true; + break; + + case 'x': + m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); + if (m_thread_id == UINT32_MAX) + error.SetErrorStringWithFormat("invalid thread index string '%s'", + option_arg); + m_thread_specified = true; + break; + + case 'o': + m_use_one_liner = true; + m_one_liner = option_arg; + break; + + default: + error.SetErrorStringWithFormat("unrecognized option %c.", short_option); + break; + } + return error; } - ~CommandObjectTargetStopHookAdd() override = default; - - Options * - GetOptions () override - { - return &m_options; + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_class_name.clear(); + m_function_name.clear(); + m_line_start = 0; + m_line_end = UINT_MAX; + m_file_name.clear(); + m_module_name.clear(); + m_func_name_type_mask = eFunctionNameTypeAuto; + m_thread_id = LLDB_INVALID_THREAD_ID; + m_thread_index = UINT32_MAX; + m_thread_name.clear(); + m_queue_name.clear(); + + m_no_inlines = false; + m_sym_ctx_specified = false; + m_thread_specified = false; + + m_use_one_liner = false; + m_one_liner.clear(); } + static OptionDefinition g_option_table[]; + + std::string m_class_name; + std::string m_function_name; + uint32_t m_line_start; + uint32_t m_line_end; + std::string m_file_name; + std::string m_module_name; + uint32_t m_func_name_type_mask; // A pick from lldb::FunctionNameType. + lldb::tid_t m_thread_id; + uint32_t m_thread_index; + std::string m_thread_name; + std::string m_queue_name; + bool m_sym_ctx_specified; + bool m_no_inlines; + bool m_thread_specified; + // Instance variables to hold the values for one_liner options. + bool m_use_one_liner; + std::string m_one_liner; + }; + + CommandObjectTargetStopHookAdd(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "target stop-hook add", + "Add a hook to be executed when the target stops.", + "target stop-hook add"), + IOHandlerDelegateMultiline("DONE", + IOHandlerDelegate::Completion::LLDBCommand), + m_options() {} + + ~CommandObjectTargetStopHookAdd() override = default; + + Options *GetOptions() override { return &m_options; } + protected: - void - IOHandlerActivated (IOHandler &io_handler) override - { + void IOHandlerActivated(IOHandler &io_handler) override { + StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + if (output_sp) { + output_sp->PutCString( + "Enter your stop hook command(s). Type 'DONE' to end.\n"); + output_sp->Flush(); + } + } + + void IOHandlerInputComplete(IOHandler &io_handler, + std::string &line) override { + if (m_stop_hook_sp) { + if (line.empty()) { + StreamFileSP error_sp(io_handler.GetErrorStreamFile()); + if (error_sp) { + error_sp->Printf("error: stop hook #%" PRIu64 + " aborted, no commands.\n", + m_stop_hook_sp->GetID()); + error_sp->Flush(); + } + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (target) + target->RemoveStopHookByID(m_stop_hook_sp->GetID()); + } else { + m_stop_hook_sp->GetCommandPointer()->SplitIntoLines(line); StreamFileSP output_sp(io_handler.GetOutputStreamFile()); - if (output_sp) - { - output_sp->PutCString("Enter your stop hook command(s). Type 'DONE' to end.\n"); - output_sp->Flush(); + if (output_sp) { + output_sp->Printf("Stop hook #%" PRIu64 " added.\n", + m_stop_hook_sp->GetID()); + output_sp->Flush(); } + } + m_stop_hook_sp.reset(); } - - void - IOHandlerInputComplete (IOHandler &io_handler, std::string &line) override - { - if (m_stop_hook_sp) - { - if (line.empty()) - { - StreamFileSP error_sp(io_handler.GetErrorStreamFile()); - if (error_sp) - { - error_sp->Printf("error: stop hook #%" PRIu64 " aborted, no commands.\n", m_stop_hook_sp->GetID()); - error_sp->Flush(); - } - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (target) - target->RemoveStopHookByID(m_stop_hook_sp->GetID()); - } - else - { - m_stop_hook_sp->GetCommandPointer()->SplitIntoLines(line); - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); - if (output_sp) - { - output_sp->Printf("Stop hook #%" PRIu64 " added.\n", m_stop_hook_sp->GetID()); - output_sp->Flush(); - } - } - m_stop_hook_sp.reset(); + io_handler.SetIsDone(true); + } + + bool DoExecute(Args &command, CommandReturnObject &result) override { + m_stop_hook_sp.reset(); + + Target *target = GetSelectedOrDummyTarget(); + if (target) { + Target::StopHookSP new_hook_sp = target->CreateStopHook(); + + // First step, make the specifier. + std::unique_ptr<SymbolContextSpecifier> specifier_ap; + if (m_options.m_sym_ctx_specified) { + specifier_ap.reset(new SymbolContextSpecifier( + m_interpreter.GetDebugger().GetSelectedTarget())); + + if (!m_options.m_module_name.empty()) { + specifier_ap->AddSpecification( + m_options.m_module_name.c_str(), + SymbolContextSpecifier::eModuleSpecified); } - io_handler.SetIsDone(true); - } - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - m_stop_hook_sp.reset(); - - Target *target = GetSelectedOrDummyTarget(); - if (target) - { - Target::StopHookSP new_hook_sp = target->CreateStopHook(); - - // First step, make the specifier. - std::unique_ptr<SymbolContextSpecifier> specifier_ap; - if (m_options.m_sym_ctx_specified) - { - specifier_ap.reset(new SymbolContextSpecifier(m_interpreter.GetDebugger().GetSelectedTarget())); - - if (!m_options.m_module_name.empty()) - { - specifier_ap->AddSpecification (m_options.m_module_name.c_str(), SymbolContextSpecifier::eModuleSpecified); - } - - if (!m_options.m_class_name.empty()) - { - specifier_ap->AddSpecification (m_options.m_class_name.c_str(), SymbolContextSpecifier::eClassOrNamespaceSpecified); - } - - if (!m_options.m_file_name.empty()) - { - specifier_ap->AddSpecification (m_options.m_file_name.c_str(), SymbolContextSpecifier::eFileSpecified); - } - - if (m_options.m_line_start != 0) - { - specifier_ap->AddLineSpecification (m_options.m_line_start, SymbolContextSpecifier::eLineStartSpecified); - } - - if (m_options.m_line_end != UINT_MAX) - { - specifier_ap->AddLineSpecification (m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified); - } - - if (!m_options.m_function_name.empty()) - { - specifier_ap->AddSpecification (m_options.m_function_name.c_str(), SymbolContextSpecifier::eFunctionSpecified); - } - } - - if (specifier_ap) - new_hook_sp->SetSpecifier (specifier_ap.release()); - - // Next see if any of the thread options have been entered: + if (!m_options.m_class_name.empty()) { + specifier_ap->AddSpecification( + m_options.m_class_name.c_str(), + SymbolContextSpecifier::eClassOrNamespaceSpecified); + } - if (m_options.m_thread_specified) - { - ThreadSpec *thread_spec = new ThreadSpec(); + if (!m_options.m_file_name.empty()) { + specifier_ap->AddSpecification( + m_options.m_file_name.c_str(), + SymbolContextSpecifier::eFileSpecified); + } - if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) - { - thread_spec->SetTID (m_options.m_thread_id); - } + if (m_options.m_line_start != 0) { + specifier_ap->AddLineSpecification( + m_options.m_line_start, + SymbolContextSpecifier::eLineStartSpecified); + } - if (m_options.m_thread_index != UINT32_MAX) - thread_spec->SetIndex (m_options.m_thread_index); + if (m_options.m_line_end != UINT_MAX) { + specifier_ap->AddLineSpecification( + m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified); + } - if (!m_options.m_thread_name.empty()) - thread_spec->SetName (m_options.m_thread_name.c_str()); + if (!m_options.m_function_name.empty()) { + specifier_ap->AddSpecification( + m_options.m_function_name.c_str(), + SymbolContextSpecifier::eFunctionSpecified); + } + } - if (!m_options.m_queue_name.empty()) - thread_spec->SetQueueName (m_options.m_queue_name.c_str()); + if (specifier_ap) + new_hook_sp->SetSpecifier(specifier_ap.release()); - new_hook_sp->SetThreadSpecifier (thread_spec); + // Next see if any of the thread options have been entered: - } - if (m_options.m_use_one_liner) - { - // Use one-liner. - new_hook_sp->GetCommandPointer()->AppendString (m_options.m_one_liner.c_str()); - result.AppendMessageWithFormat("Stop hook #%" PRIu64 " added.\n", new_hook_sp->GetID()); - } - else - { - m_stop_hook_sp = new_hook_sp; - m_interpreter.GetLLDBCommandsFromIOHandler("> ", // Prompt - *this, // IOHandlerDelegate - true, // Run IOHandler in async mode - nullptr); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions + if (m_options.m_thread_specified) { + ThreadSpec *thread_spec = new ThreadSpec(); - } - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendError ("invalid target\n"); - result.SetStatus (eReturnStatusFailed); + if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) { + thread_spec->SetTID(m_options.m_thread_id); } - return result.Succeeded(); + if (m_options.m_thread_index != UINT32_MAX) + thread_spec->SetIndex(m_options.m_thread_index); + + if (!m_options.m_thread_name.empty()) + thread_spec->SetName(m_options.m_thread_name.c_str()); + + if (!m_options.m_queue_name.empty()) + thread_spec->SetQueueName(m_options.m_queue_name.c_str()); + + new_hook_sp->SetThreadSpecifier(thread_spec); + } + if (m_options.m_use_one_liner) { + // Use one-liner. + new_hook_sp->GetCommandPointer()->AppendString( + m_options.m_one_liner.c_str()); + result.AppendMessageWithFormat("Stop hook #%" PRIu64 " added.\n", + new_hook_sp->GetID()); + } else { + m_stop_hook_sp = new_hook_sp; + m_interpreter.GetLLDBCommandsFromIOHandler( + "> ", // Prompt + *this, // IOHandlerDelegate + true, // Run IOHandler in async mode + nullptr); // Baton for the "io_handler" that will be passed back + // into our IOHandlerDelegate functions + } + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.AppendError("invalid target\n"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } + private: - CommandOptions m_options; - Target::StopHookSP m_stop_hook_sp; + CommandOptions m_options; + Target::StopHookSP m_stop_hook_sp; }; OptionDefinition -CommandObjectTargetStopHookAdd::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectTargetStopHookAdd::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_ALL, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOneLiner, "Specify a one-line breakpoint command inline. Be sure to surround it with quotes."}, {LLDB_OPT_SET_ALL, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the module within which the stop-hook is to be run."}, {LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The stop hook is run only for the thread whose index matches this argument."}, @@ -5203,7 +4639,7 @@ CommandObjectTargetStopHookAdd::CommandOptions::g_option_table[] = {LLDB_OPT_SET_2, false, "classname", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeClassName, "Specify the class within which the stop-hook is to be run."}, {LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the function name within which the stop hook will be run."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } - // clang-format on + // clang-format on }; #pragma mark CommandObjectTargetStopHookDelete @@ -5212,71 +4648,56 @@ CommandObjectTargetStopHookAdd::CommandOptions::g_option_table[] = // CommandObjectTargetStopHookDelete //------------------------------------------------------------------------- -class CommandObjectTargetStopHookDelete : public CommandObjectParsed -{ +class CommandObjectTargetStopHookDelete : public CommandObjectParsed { public: - CommandObjectTargetStopHookDelete (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "target stop-hook delete", - "Delete a stop-hook.", - "target stop-hook delete [<idx>]") - { - } + CommandObjectTargetStopHookDelete(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "target stop-hook delete", + "Delete a stop-hook.", + "target stop-hook delete [<idx>]") {} - ~CommandObjectTargetStopHookDelete() override = default; + ~CommandObjectTargetStopHookDelete() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = GetSelectedOrDummyTarget(); - if (target) - { - // FIXME: see if we can use the breakpoint id style parser? - size_t num_args = command.GetArgumentCount(); - if (num_args == 0) - { - if (!m_interpreter.Confirm ("Delete all stop hooks?", true)) - { - result.SetStatus (eReturnStatusFailed); - return false; - } - else - { - 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) - { - result.AppendErrorWithFormat ("invalid stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i)); - result.SetStatus(eReturnStatusFailed); - return false; - } - success = target->RemoveStopHookByID (user_id); - if (!success) - { - result.AppendErrorWithFormat ("unknown stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i)); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - } - result.SetStatus (eReturnStatusSuccessFinishNoResult); + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = GetSelectedOrDummyTarget(); + if (target) { + // FIXME: see if we can use the breakpoint id style parser? + size_t num_args = command.GetArgumentCount(); + if (num_args == 0) { + if (!m_interpreter.Confirm("Delete all stop hooks?", true)) { + result.SetStatus(eReturnStatusFailed); + return false; + } else { + target->RemoveAllStopHooks(); } - else - { - result.AppendError ("invalid target\n"); - result.SetStatus (eReturnStatusFailed); + } 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) { + result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n", + command.GetArgumentAtIndex(i)); + result.SetStatus(eReturnStatusFailed); + return false; + } + success = target->RemoveStopHookByID(user_id); + if (!success) { + result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n", + command.GetArgumentAtIndex(i)); + result.SetStatus(eReturnStatusFailed); + return false; + } } - - return result.Succeeded(); + } + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.AppendError("invalid target\n"); + result.SetStatus(eReturnStatusFailed); } + + return result.Succeeded(); + } }; #pragma mark CommandObjectTargetStopHookEnableDisable @@ -5285,66 +4706,55 @@ protected: // CommandObjectTargetStopHookEnableDisable //------------------------------------------------------------------------- -class CommandObjectTargetStopHookEnableDisable : public CommandObjectParsed -{ +class CommandObjectTargetStopHookEnableDisable : public CommandObjectParsed { public: - CommandObjectTargetStopHookEnableDisable (CommandInterpreter &interpreter, bool enable, const char *name, const char *help, const char *syntax) : - CommandObjectParsed (interpreter, - name, - help, - syntax), - m_enable (enable) - { - } + CommandObjectTargetStopHookEnableDisable(CommandInterpreter &interpreter, + bool enable, const char *name, + const char *help, const char *syntax) + : CommandObjectParsed(interpreter, name, help, syntax), m_enable(enable) { + } - ~CommandObjectTargetStopHookEnableDisable() override = default; + ~CommandObjectTargetStopHookEnableDisable() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = GetSelectedOrDummyTarget(); - if (target) - { - // FIXME: see if we can use the breakpoint id style parser? - size_t num_args = command.GetArgumentCount(); - bool success; - - if (num_args == 0) - { - 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) - { - result.AppendErrorWithFormat ("invalid stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i)); - result.SetStatus(eReturnStatusFailed); - return false; - } - success = target->SetStopHookActiveStateByID (user_id, m_enable); - if (!success) - { - result.AppendErrorWithFormat ("unknown stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i)); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - } - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendError ("invalid target\n"); - result.SetStatus (eReturnStatusFailed); + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = GetSelectedOrDummyTarget(); + if (target) { + // FIXME: see if we can use the breakpoint id style parser? + size_t num_args = command.GetArgumentCount(); + bool success; + + if (num_args == 0) { + 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) { + result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n", + command.GetArgumentAtIndex(i)); + result.SetStatus(eReturnStatusFailed); + return false; + } + success = target->SetStopHookActiveStateByID(user_id, m_enable); + if (!success) { + result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n", + command.GetArgumentAtIndex(i)); + result.SetStatus(eReturnStatusFailed); + return false; + } } - return result.Succeeded(); + } + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.AppendError("invalid target\n"); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } + private: - bool m_enable; + bool m_enable; }; #pragma mark CommandObjectTargetStopHookList @@ -5353,49 +4763,39 @@ private: // CommandObjectTargetStopHookList //------------------------------------------------------------------------- -class CommandObjectTargetStopHookList : public CommandObjectParsed -{ +class CommandObjectTargetStopHookList : public CommandObjectParsed { public: - CommandObjectTargetStopHookList (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "target stop-hook list", - "List all stop-hooks.", - "target stop-hook list [<type>]") - { - } + CommandObjectTargetStopHookList(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "target stop-hook list", + "List all stop-hooks.", + "target stop-hook list [<type>]") {} - ~CommandObjectTargetStopHookList() override = default; + ~CommandObjectTargetStopHookList() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = GetSelectedOrDummyTarget(); - if (!target) - { - result.AppendError ("invalid target\n"); - result.SetStatus (eReturnStatusFailed); - return result.Succeeded(); - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = GetSelectedOrDummyTarget(); + if (!target) { + result.AppendError("invalid target\n"); + result.SetStatus(eReturnStatusFailed); + return result.Succeeded(); + } - size_t num_hooks = target->GetNumStopHooks (); - if (num_hooks == 0) - { - result.GetOutputStream().PutCString ("No stop hooks.\n"); - } - else - { - for (size_t i = 0; i < num_hooks; i++) - { - Target::StopHookSP this_hook = target->GetStopHookAtIndex (i); - if (i > 0) - result.GetOutputStream().PutCString ("\n"); - this_hook->GetDescription (&(result.GetOutputStream()), eDescriptionLevelFull); - } - } - result.SetStatus (eReturnStatusSuccessFinishResult); - return result.Succeeded(); + size_t num_hooks = target->GetNumStopHooks(); + if (num_hooks == 0) { + result.GetOutputStream().PutCString("No stop hooks.\n"); + } else { + for (size_t i = 0; i < num_hooks; i++) { + Target::StopHookSP this_hook = target->GetStopHookAtIndex(i); + if (i > 0) + result.GetOutputStream().PutCString("\n"); + this_hook->GetDescription(&(result.GetOutputStream()), + eDescriptionLevelFull); + } } + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); + } }; #pragma mark CommandObjectMultiwordTargetStopHooks @@ -5404,30 +4804,31 @@ protected: // CommandObjectMultiwordTargetStopHooks //------------------------------------------------------------------------- -class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword -{ +class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword { public: - CommandObjectMultiwordTargetStopHooks(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "target stop-hook", - "Commands for operating on debugger target stop-hooks.", - "target stop-hook <subcommand> [<subcommand-options>]") - { - LoadSubCommand ("add", CommandObjectSP (new CommandObjectTargetStopHookAdd (interpreter))); - LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTargetStopHookDelete (interpreter))); - LoadSubCommand ("disable", CommandObjectSP (new CommandObjectTargetStopHookEnableDisable (interpreter, - false, - "target stop-hook disable [<id>]", - "Disable a stop-hook.", - "target stop-hook disable"))); - LoadSubCommand ("enable", CommandObjectSP (new CommandObjectTargetStopHookEnableDisable (interpreter, - true, - "target stop-hook enable [<id>]", - "Enable a stop-hook.", - "target stop-hook enable"))); - LoadSubCommand ("list", CommandObjectSP (new CommandObjectTargetStopHookList (interpreter))); - } - - ~CommandObjectMultiwordTargetStopHooks() override = default; + CommandObjectMultiwordTargetStopHooks(CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "target stop-hook", + "Commands for operating on debugger target stop-hooks.", + "target stop-hook <subcommand> [<subcommand-options>]") { + LoadSubCommand("add", CommandObjectSP( + new CommandObjectTargetStopHookAdd(interpreter))); + LoadSubCommand( + "delete", + CommandObjectSP(new CommandObjectTargetStopHookDelete(interpreter))); + LoadSubCommand("disable", + CommandObjectSP(new CommandObjectTargetStopHookEnableDisable( + interpreter, false, "target stop-hook disable [<id>]", + "Disable a stop-hook.", "target stop-hook disable"))); + LoadSubCommand("enable", + CommandObjectSP(new CommandObjectTargetStopHookEnableDisable( + interpreter, true, "target stop-hook enable [<id>]", + "Enable a stop-hook.", "target stop-hook enable"))); + LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetStopHookList( + interpreter))); + } + + ~CommandObjectMultiwordTargetStopHooks() override = default; }; #pragma mark CommandObjectMultiwordTarget @@ -5436,18 +4837,28 @@ public: // CommandObjectMultiwordTarget //------------------------------------------------------------------------- -CommandObjectMultiwordTarget::CommandObjectMultiwordTarget(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "target", "Commands for operating on debugger targets.", - "target <subcommand> [<subcommand-options>]") -{ - LoadSubCommand ("create", CommandObjectSP (new CommandObjectTargetCreate (interpreter))); - LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTargetDelete (interpreter))); - LoadSubCommand ("list", CommandObjectSP (new CommandObjectTargetList (interpreter))); - LoadSubCommand ("select", CommandObjectSP (new CommandObjectTargetSelect (interpreter))); - LoadSubCommand ("stop-hook", CommandObjectSP (new CommandObjectMultiwordTargetStopHooks (interpreter))); - LoadSubCommand ("modules", CommandObjectSP (new CommandObjectTargetModules (interpreter))); - LoadSubCommand ("symbols", CommandObjectSP (new CommandObjectTargetSymbols (interpreter))); - LoadSubCommand ("variable", CommandObjectSP (new CommandObjectTargetVariable (interpreter))); +CommandObjectMultiwordTarget::CommandObjectMultiwordTarget( + CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "target", + "Commands for operating on debugger targets.", + "target <subcommand> [<subcommand-options>]") { + LoadSubCommand("create", + CommandObjectSP(new CommandObjectTargetCreate(interpreter))); + LoadSubCommand("delete", + CommandObjectSP(new CommandObjectTargetDelete(interpreter))); + LoadSubCommand("list", + CommandObjectSP(new CommandObjectTargetList(interpreter))); + LoadSubCommand("select", + CommandObjectSP(new CommandObjectTargetSelect(interpreter))); + LoadSubCommand( + "stop-hook", + CommandObjectSP(new CommandObjectMultiwordTargetStopHooks(interpreter))); + LoadSubCommand("modules", + CommandObjectSP(new CommandObjectTargetModules(interpreter))); + LoadSubCommand("symbols", + CommandObjectSP(new CommandObjectTargetSymbols(interpreter))); + LoadSubCommand("variable", + CommandObjectSP(new CommandObjectTargetVariable(interpreter))); } CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget() = default; diff --git a/lldb/source/Commands/CommandObjectTarget.h b/lldb/source/Commands/CommandObjectTarget.h index d99a2b0..8655341 100644 --- a/lldb/source/Commands/CommandObjectTarget.h +++ b/lldb/source/Commands/CommandObjectTarget.h @@ -14,9 +14,9 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Interpreter/Options.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Interpreter/CommandObjectMultiword.h" +#include "lldb/Interpreter/Options.h" namespace lldb_private { @@ -24,13 +24,11 @@ namespace lldb_private { // CommandObjectMultiwordTarget //------------------------------------------------------------------------- -class CommandObjectMultiwordTarget : public CommandObjectMultiword -{ +class CommandObjectMultiwordTarget : public CommandObjectMultiword { public: + CommandObjectMultiwordTarget(CommandInterpreter &interpreter); - CommandObjectMultiwordTarget (CommandInterpreter &interpreter); - - ~CommandObjectMultiwordTarget() override; + ~CommandObjectMultiwordTarget() override; }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index 9199c97..f2f7cdc 100644 --- a/lldb/source/Commands/CommandObjectThread.cpp +++ b/lldb/source/Commands/CommandObjectThread.cpp @@ -13,9 +13,8 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" -#include "lldb/Core/State.h" #include "lldb/Core/SourceManager.h" +#include "lldb/Core/State.h" #include "lldb/Core/ValueObject.h" #include "lldb/Host/Host.h" #include "lldb/Host/StringConvert.h" @@ -24,18 +23,19 @@ #include "lldb/Interpreter/Options.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" -#include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/LineEntry.h" +#include "lldb/Symbol/LineTable.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/SystemRuntime.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanStepInRange.h" #include "lldb/Target/ThreadPlanStepInstruction.h" #include "lldb/Target/ThreadPlanStepOut.h" #include "lldb/Target/ThreadPlanStepRange.h" -#include "lldb/Target/ThreadPlanStepInRange.h" +#include "lldb/lldb-private.h" using namespace lldb; using namespace lldb_private; @@ -44,750 +44,663 @@ using namespace lldb_private; // CommandObjectThreadBacktrace //------------------------------------------------------------------------- -class CommandObjectIterateOverThreads : public CommandObjectParsed -{ +class CommandObjectIterateOverThreads : public CommandObjectParsed { public: - CommandObjectIterateOverThreads (CommandInterpreter &interpreter, - const char *name, - const char *help, - const char *syntax, - uint32_t flags) : - CommandObjectParsed (interpreter, name, help, syntax, flags) - { + CommandObjectIterateOverThreads(CommandInterpreter &interpreter, + const char *name, const char *help, + const char *syntax, uint32_t flags) + : CommandObjectParsed(interpreter, name, help, syntax, flags) {} + + ~CommandObjectIterateOverThreads() override = default; + + bool DoExecute(Args &command, CommandReturnObject &result) override { + result.SetStatus(m_success_return); + + if (command.GetArgumentCount() == 0) { + Thread *thread = m_exe_ctx.GetThreadPtr(); + if (!HandleOneThread(thread->GetID(), result)) + return false; + return result.Succeeded(); } - ~CommandObjectIterateOverThreads() override = default; + // Use tids instead of ThreadSPs to prevent deadlocking problems which + // result from JIT-ing + // code while iterating over the (locked) ThreadSP list. + std::vector<lldb::tid_t> tids; - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - result.SetStatus (m_success_return); + if (command.GetArgumentCount() == 1 && + ::strcmp(command.GetArgumentAtIndex(0), "all") == 0) { + Process *process = m_exe_ctx.GetProcessPtr(); - if (command.GetArgumentCount() == 0) - { - Thread *thread = m_exe_ctx.GetThreadPtr(); - if (!HandleOneThread (thread->GetID(), result)) - return false; - return result.Succeeded(); - } + for (ThreadSP thread_sp : process->Threads()) + tids.push_back(thread_sp->GetID()); + } else { + const size_t num_args = command.GetArgumentCount(); + Process *process = m_exe_ctx.GetProcessPtr(); - // Use tids instead of ThreadSPs to prevent deadlocking problems which result from JIT-ing - // code while iterating over the (locked) ThreadSP list. - std::vector<lldb::tid_t> tids; + std::lock_guard<std::recursive_mutex> guard( + process->GetThreadList().GetMutex()); - if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0) - { - Process *process = m_exe_ctx.GetProcessPtr(); + for (size_t i = 0; i < num_args; i++) { + bool success; - for (ThreadSP thread_sp : process->Threads()) - tids.push_back(thread_sp->GetID()); + uint32_t thread_idx = StringConvert::ToUInt32( + command.GetArgumentAtIndex(i), 0, 0, &success); + if (!success) { + result.AppendErrorWithFormat("invalid thread specification: \"%s\"\n", + command.GetArgumentAtIndex(i)); + result.SetStatus(eReturnStatusFailed); + return false; } - else - { - const size_t num_args = command.GetArgumentCount(); - Process *process = m_exe_ctx.GetProcessPtr(); - - std::lock_guard<std::recursive_mutex> guard(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) - { - result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i)); - result.SetStatus (eReturnStatusFailed); - return false; - } - - ThreadSP thread = process->GetThreadList().FindThreadByIndexID(thread_idx); - - if (!thread) - { - result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i)); - result.SetStatus (eReturnStatusFailed); - return false; - } - - tids.push_back(thread->GetID()); - } + + ThreadSP thread = + process->GetThreadList().FindThreadByIndexID(thread_idx); + + if (!thread) { + result.AppendErrorWithFormat("no thread with index: \"%s\"\n", + command.GetArgumentAtIndex(i)); + result.SetStatus(eReturnStatusFailed); + return false; } - uint32_t idx = 0; - for (const lldb::tid_t &tid : tids) - { - if (idx != 0 && m_add_return) - result.AppendMessage(""); + tids.push_back(thread->GetID()); + } + } - if (!HandleOneThread (tid, result)) - return false; + uint32_t idx = 0; + for (const lldb::tid_t &tid : tids) { + if (idx != 0 && m_add_return) + result.AppendMessage(""); - ++idx; - } - return result.Succeeded(); + if (!HandleOneThread(tid, result)) + return false; + + ++idx; } + return result.Succeeded(); + } protected: - // Override this to do whatever you need to do for one thread. - // - // If you return false, the iteration will stop, otherwise it will proceed. - // The result is set to m_success_return (defaults to eReturnStatusSuccessFinishResult) before the iteration, - // so you only need to set the return status in HandleOneThread if you want to indicate an error. - // If m_add_return is true, a blank line will be inserted between each of the listings (except the last one.) - - virtual bool - HandleOneThread (lldb::tid_t, CommandReturnObject &result) = 0; - - ReturnStatus m_success_return = eReturnStatusSuccessFinishResult; - bool m_add_return = true; + // Override this to do whatever you need to do for one thread. + // + // If you return false, the iteration will stop, otherwise it will proceed. + // The result is set to m_success_return (defaults to + // eReturnStatusSuccessFinishResult) before the iteration, + // so you only need to set the return status in HandleOneThread if you want to + // indicate an error. + // If m_add_return is true, a blank line will be inserted between each of the + // listings (except the last one.) + + virtual bool HandleOneThread(lldb::tid_t, CommandReturnObject &result) = 0; + + ReturnStatus m_success_return = eReturnStatusSuccessFinishResult; + bool m_add_return = true; }; //------------------------------------------------------------------------- // CommandObjectThreadBacktrace //------------------------------------------------------------------------- -class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads -{ +class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads { public: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - // Keep default values of all options in one place: OptionParsingStarting () - OptionParsingStarting(nullptr); - } + class CommandOptions : public Options { + public: + CommandOptions() : Options() { + // Keep default values of all options in one place: OptionParsingStarting + // () + OptionParsingStarting(nullptr); + } - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'c': - { - bool success; - int32_t input_count = StringConvert::ToSInt32 (option_arg, -1, 0, &success); - if (!success) - error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option); - if (input_count < -1) - m_count = UINT32_MAX; - else - m_count = input_count; - } - break; - case 's': - { - bool success; - m_start = StringConvert::ToUInt32 (option_arg, 0, 0, &success); - if (!success) - error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option); - } - break; - case 'e': - { - bool success; - m_extended_backtrace = Args::StringToBoolean (option_arg, false, &success); - if (!success) - error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option); - } - break; - default: - error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); - break; - } - return error; - } + ~CommandOptions() override = default; - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_count = UINT32_MAX; - m_start = 0; - m_extended_backtrace = false; - } + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } + switch (short_option) { + case 'c': { + bool success; + int32_t input_count = + StringConvert::ToSInt32(option_arg, -1, 0, &success); + if (!success) + error.SetErrorStringWithFormat( + "invalid integer value for option '%c'", short_option); + if (input_count < -1) + m_count = UINT32_MAX; + else + m_count = input_count; + } break; + case 's': { + bool success; + m_start = StringConvert::ToUInt32(option_arg, 0, 0, &success); + if (!success) + error.SetErrorStringWithFormat( + "invalid integer value for option '%c'", short_option); + } break; + case 'e': { + bool success; + m_extended_backtrace = + Args::StringToBoolean(option_arg, false, &success); + if (!success) + error.SetErrorStringWithFormat( + "invalid boolean value for option '%c'", short_option); + } break; + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", + short_option); + break; + } + return error; + } - // Options table: Required for subclasses of Options. + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_count = UINT32_MAX; + m_start = 0; + m_extended_backtrace = false; + } - static OptionDefinition g_option_table[]; + const OptionDefinition *GetDefinitions() override { return g_option_table; } - // Instance variables to hold the values for command options. - uint32_t m_count; - uint32_t m_start; - bool m_extended_backtrace; - }; + // Options table: Required for subclasses of Options. - CommandObjectThreadBacktrace(CommandInterpreter &interpreter) - : CommandObjectIterateOverThreads( - interpreter, "thread backtrace", "Show thread call stacks. Defaults to the current thread, thread " - "indexes can be specified as arguments. Use the thread-index \"all\" " - "to see all threads.", - nullptr, eCommandRequiresProcess | eCommandRequiresThread | eCommandTryTargetAPILock | - eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), - m_options() - { - } + static OptionDefinition g_option_table[]; - ~CommandObjectThreadBacktrace() override = default; + // Instance variables to hold the values for command options. + uint32_t m_count; + uint32_t m_start; + bool m_extended_backtrace; + }; - Options * - GetOptions () override - { - return &m_options; - } + CommandObjectThreadBacktrace(CommandInterpreter &interpreter) + : CommandObjectIterateOverThreads( + interpreter, "thread backtrace", + "Show thread call stacks. Defaults to the current thread, thread " + "indexes can be specified as arguments. Use the thread-index " + "\"all\" " + "to see all threads.", + nullptr, + eCommandRequiresProcess | eCommandRequiresThread | + eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused), + m_options() {} -protected: - void - DoExtendedBacktrace (Thread *thread, CommandReturnObject &result) - { - SystemRuntime *runtime = thread->GetProcess()->GetSystemRuntime(); - if (runtime) - { - Stream &strm = result.GetOutputStream(); - const std::vector<ConstString> &types = runtime->GetExtendedBacktraceTypes(); - for (auto type : types) - { - ThreadSP ext_thread_sp = runtime->GetExtendedBacktraceThread (thread->shared_from_this(), type); - if (ext_thread_sp && ext_thread_sp->IsValid ()) - { - const uint32_t num_frames_with_source = 0; - if (ext_thread_sp->GetStatus (strm, - m_options.m_start, - m_options.m_count, - num_frames_with_source)) - { - DoExtendedBacktrace (ext_thread_sp.get(), result); - } - } - } - } - } + ~CommandObjectThreadBacktrace() override = default; - 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 disappeared while computing backtraces: 0x%" PRIx64 "\n", tid); - result.SetStatus (eReturnStatusFailed); - return false; - } + Options *GetOptions() override { return &m_options; } - Thread *thread = thread_sp.get(); +protected: + void DoExtendedBacktrace(Thread *thread, CommandReturnObject &result) { + SystemRuntime *runtime = thread->GetProcess()->GetSystemRuntime(); + if (runtime) { + Stream &strm = result.GetOutputStream(); + const std::vector<ConstString> &types = + runtime->GetExtendedBacktraceTypes(); + for (auto type : types) { + ThreadSP ext_thread_sp = runtime->GetExtendedBacktraceThread( + thread->shared_from_this(), type); + if (ext_thread_sp && ext_thread_sp->IsValid()) { + const uint32_t num_frames_with_source = 0; + if (ext_thread_sp->GetStatus(strm, m_options.m_start, + m_options.m_count, + num_frames_with_source)) { + DoExtendedBacktrace(ext_thread_sp.get(), result); + } + } + } + } + } + + 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 disappeared while computing backtraces: 0x%" PRIx64 "\n", + tid); + result.SetStatus(eReturnStatusFailed); + return false; + } - Stream &strm = result.GetOutputStream(); + Thread *thread = thread_sp.get(); - // Don't show source context when doing backtraces. - const uint32_t num_frames_with_source = 0; + Stream &strm = result.GetOutputStream(); - if (!thread->GetStatus (strm, - m_options.m_start, - m_options.m_count, - num_frames_with_source)) - { - result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", thread->GetIndexID()); - result.SetStatus (eReturnStatusFailed); - return false; - } - if (m_options.m_extended_backtrace) - { - DoExtendedBacktrace (thread, result); - } + // Don't show source context when doing backtraces. + const uint32_t num_frames_with_source = 0; - return true; + if (!thread->GetStatus(strm, m_options.m_start, m_options.m_count, + num_frames_with_source)) { + result.AppendErrorWithFormat( + "error displaying backtrace for thread: \"0x%4.4x\"\n", + thread->GetIndexID()); + result.SetStatus(eReturnStatusFailed); + return false; + } + if (m_options.m_extended_backtrace) { + DoExtendedBacktrace(thread, result); } - CommandOptions m_options; + return true; + } + + CommandOptions m_options; }; OptionDefinition -CommandObjectThreadBacktrace::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectThreadBacktrace::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "How many frames to display (-1 for all)"}, {LLDB_OPT_SET_1, false, "start", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"}, {LLDB_OPT_SET_1, false, "extended", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Show the extended backtrace, if available"}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; -enum StepScope -{ - eStepScopeSource, - eStepScopeInstruction -}; +enum StepScope { eStepScopeSource, eStepScopeInstruction }; -class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed -{ +class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed { public: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - // Keep default values of all options in one place: OptionParsingStarting () - OptionParsingStarting(nullptr); - } + class CommandOptions : public Options { + public: + CommandOptions() : Options() { + // Keep default values of all options in one place: OptionParsingStarting + // () + OptionParsingStarting(nullptr); + } - ~CommandOptions() override = default; - - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'a': - { - bool success; - bool avoid_no_debug = Args::StringToBoolean (option_arg, true, &success); - if (!success) - error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option); - else - { - m_step_in_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; - } - } - break; - - case 'A': - { - bool success; - bool avoid_no_debug = Args::StringToBoolean (option_arg, true, &success); - if (!success) - error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option); - else - { - m_step_out_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; - } - } - break; - - case 'c': - m_step_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); - if (m_step_count == UINT32_MAX) - error.SetErrorStringWithFormat ("invalid step count '%s'", option_arg); - break; - - case 'C': - m_class_name.clear(); - m_class_name.assign(option_arg); - break; - - case 'm': - { - OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; - m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error); - } - break; - - case 'e': - { - if (strcmp(option_arg, "block") == 0) - { - m_end_line_is_block_end = 1; - break; - } - uint32_t tmp_end_line = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); - if (tmp_end_line == UINT32_MAX) - error.SetErrorStringWithFormat ("invalid end line number '%s'", option_arg); - else - m_end_line = tmp_end_line; - break; - } - break; - - case 'r': - m_avoid_regexp.clear(); - m_avoid_regexp.assign(option_arg); - break; - - case 't': - m_step_in_target.clear(); - m_step_in_target.assign(option_arg); - break; - - default: - error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); - break; - } - return error; - } + ~CommandOptions() override = default; - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_step_in_avoid_no_debug = eLazyBoolCalculate; - m_step_out_avoid_no_debug = eLazyBoolCalculate; - m_run_mode = eOnlyDuringStepping; - - // Check if we are in Non-Stop mode - TargetSP target_sp = - execution_context ? execution_context->GetTargetSP() : - TargetSP(); - if (target_sp && target_sp->GetNonStopModeEnabled()) - m_run_mode = eOnlyThisThread; - - m_avoid_regexp.clear(); - m_step_in_target.clear(); - m_class_name.clear(); - m_step_count = 1; - m_end_line = LLDB_INVALID_LINE_NUMBER; - m_end_line_is_block_end = false; - } + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; + switch (short_option) { + case 'a': { + bool success; + bool avoid_no_debug = Args::StringToBoolean(option_arg, true, &success); + if (!success) + error.SetErrorStringWithFormat( + "invalid boolean value for option '%c'", short_option); + else { + m_step_in_avoid_no_debug = + avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; } + } break; - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - LazyBool m_step_in_avoid_no_debug; - LazyBool m_step_out_avoid_no_debug; - RunMode m_run_mode; - std::string m_avoid_regexp; - std::string m_step_in_target; - std::string m_class_name; - uint32_t m_step_count; - uint32_t m_end_line; - bool m_end_line_is_block_end; - }; - - CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter, - const char *name, - const char *help, - const char *syntax, - StepType step_type, - StepScope step_scope) : - CommandObjectParsed (interpreter, name, help, syntax, - eCommandRequiresProcess | - eCommandRequiresThread | - eCommandTryTargetAPILock | - eCommandProcessMustBeLaunched | - eCommandProcessMustBePaused ), - m_step_type (step_type), - m_step_scope (step_scope), - m_options() - { - CommandArgumentEntry arg; - CommandArgumentData thread_id_arg; - - // Define the first (and only) variant of this arg. - thread_id_arg.arg_type = eArgTypeThreadID; - thread_id_arg.arg_repetition = eArgRepeatOptional; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (thread_id_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); + case 'A': { + bool success; + bool avoid_no_debug = Args::StringToBoolean(option_arg, true, &success); + if (!success) + error.SetErrorStringWithFormat( + "invalid boolean value for option '%c'", short_option); + else { + m_step_out_avoid_no_debug = + avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; + } + } break; + + case 'c': + m_step_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); + if (m_step_count == UINT32_MAX) + error.SetErrorStringWithFormat("invalid step count '%s'", option_arg); + break; + + case 'C': + m_class_name.clear(); + m_class_name.assign(option_arg); + break; + + case 'm': { + OptionEnumValueElement *enum_values = + g_option_table[option_idx].enum_values; + m_run_mode = (lldb::RunMode)Args::StringToOptionEnum( + option_arg, enum_values, eOnlyDuringStepping, error); + } break; + + case 'e': { + if (strcmp(option_arg, "block") == 0) { + m_end_line_is_block_end = 1; + break; + } + uint32_t tmp_end_line = + StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); + if (tmp_end_line == UINT32_MAX) + error.SetErrorStringWithFormat("invalid end line number '%s'", + option_arg); + else + m_end_line = tmp_end_line; + break; + } break; + + case 'r': + m_avoid_regexp.clear(); + m_avoid_regexp.assign(option_arg); + break; + + case 't': + m_step_in_target.clear(); + m_step_in_target.assign(option_arg); + break; + + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", + short_option); + break; + } + return error; } - ~CommandObjectThreadStepWithTypeAndScope() override = default; - - Options * - GetOptions () override - { - return &m_options; + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_step_in_avoid_no_debug = eLazyBoolCalculate; + m_step_out_avoid_no_debug = eLazyBoolCalculate; + m_run_mode = eOnlyDuringStepping; + + // Check if we are in Non-Stop mode + TargetSP target_sp = + execution_context ? execution_context->GetTargetSP() : TargetSP(); + if (target_sp && target_sp->GetNonStopModeEnabled()) + m_run_mode = eOnlyThisThread; + + m_avoid_regexp.clear(); + m_step_in_target.clear(); + m_class_name.clear(); + m_step_count = 1; + m_end_line = LLDB_INVALID_LINE_NUMBER; + m_end_line_is_block_end = false; } -protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Process *process = m_exe_ctx.GetProcessPtr(); - bool synchronous_execution = m_interpreter.GetSynchronous(); - - const uint32_t num_threads = process->GetThreadList().GetSize(); - Thread *thread = nullptr; + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + LazyBool m_step_in_avoid_no_debug; + LazyBool m_step_out_avoid_no_debug; + RunMode m_run_mode; + std::string m_avoid_regexp; + std::string m_step_in_target; + std::string m_class_name; + uint32_t m_step_count; + uint32_t m_end_line; + bool m_end_line_is_block_end; + }; + + CommandObjectThreadStepWithTypeAndScope(CommandInterpreter &interpreter, + const char *name, const char *help, + const char *syntax, + StepType step_type, + StepScope step_scope) + : CommandObjectParsed(interpreter, name, help, syntax, + eCommandRequiresProcess | eCommandRequiresThread | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused), + m_step_type(step_type), m_step_scope(step_scope), m_options() { + CommandArgumentEntry arg; + CommandArgumentData thread_id_arg; + + // Define the first (and only) variant of this arg. + thread_id_arg.arg_type = eArgTypeThreadID; + thread_id_arg.arg_repetition = eArgRepeatOptional; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(thread_id_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectThreadStepWithTypeAndScope() override = default; + + Options *GetOptions() override { return &m_options; } - if (command.GetArgumentCount() == 0) - { - thread = GetDefaultThread(); +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + Process *process = m_exe_ctx.GetProcessPtr(); + bool synchronous_execution = m_interpreter.GetSynchronous(); + + const uint32_t num_threads = process->GetThreadList().GetSize(); + Thread *thread = nullptr; + + if (command.GetArgumentCount() == 0) { + thread = GetDefaultThread(); + + if (thread == nullptr) { + result.AppendError("no selected thread in process"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } 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) { + result.AppendErrorWithFormat("invalid thread index '%s'.\n", + thread_idx_cstr); + result.SetStatus(eReturnStatusFailed); + return false; + } + thread = + process->GetThreadList().FindThreadByIndexID(step_thread_idx).get(); + if (thread == nullptr) { + result.AppendErrorWithFormat( + "Thread index %u is out of range (valid values are 0 - %u).\n", + step_thread_idx, num_threads); + result.SetStatus(eReturnStatusFailed); + return false; + } + } - if (thread == nullptr) - { - result.AppendError ("no selected thread in process"); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - 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) - { - result.AppendErrorWithFormat ("invalid thread index '%s'.\n", thread_idx_cstr); - result.SetStatus (eReturnStatusFailed); - return false; - } - thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get(); - if (thread == nullptr) - { - result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", - step_thread_idx, num_threads); - result.SetStatus (eReturnStatusFailed); - return false; - } - } + if (m_step_type == eStepTypeScripted) { + if (m_options.m_class_name.empty()) { + result.AppendErrorWithFormat("empty class name for scripted step."); + result.SetStatus(eReturnStatusFailed); + return false; + } else if (!m_interpreter.GetScriptInterpreter()->CheckObjectExists( + m_options.m_class_name.c_str())) { + result.AppendErrorWithFormat( + "class for scripted step: \"%s\" does not exist.", + m_options.m_class_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + } - if (m_step_type == eStepTypeScripted) - { - if (m_options.m_class_name.empty()) - { - result.AppendErrorWithFormat ("empty class name for scripted step."); - result.SetStatus(eReturnStatusFailed); - return false; - } - else if (!m_interpreter.GetScriptInterpreter()->CheckObjectExists(m_options.m_class_name.c_str())) - { - result.AppendErrorWithFormat ("class for scripted step: \"%s\" does not exist.", m_options.m_class_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - } + if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER && + m_step_type != eStepTypeInto) { + result.AppendErrorWithFormat( + "end line option is only valid for step into"); + result.SetStatus(eReturnStatusFailed); + return false; + } - if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER - && m_step_type != eStepTypeInto) - { - result.AppendErrorWithFormat("end line option is only valid for step into"); + const bool abort_other_plans = false; + const lldb::RunMode stop_other_threads = m_options.m_run_mode; + + // This is a bit unfortunate, but not all the commands in this command + // object support + // only while stepping, so I use the bool for them. + bool bool_stop_other_threads; + if (m_options.m_run_mode == eAllThreads) + bool_stop_other_threads = false; + else if (m_options.m_run_mode == eOnlyDuringStepping) + bool_stop_other_threads = + (m_step_type != eStepTypeOut && m_step_type != eStepTypeScripted); + else + bool_stop_other_threads = true; + + ThreadPlanSP new_plan_sp; + + if (m_step_type == eStepTypeInto) { + StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); + assert(frame != nullptr); + + if (frame->HasDebugInformation()) { + AddressRange range; + SymbolContext sc = frame->GetSymbolContext(eSymbolContextEverything); + if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER) { + Error error; + if (!sc.GetAddressRangeFromHereToEndLine(m_options.m_end_line, range, + error)) { + result.AppendErrorWithFormat("invalid end-line option: %s.", + error.AsCString()); result.SetStatus(eReturnStatusFailed); return false; - } - - const bool abort_other_plans = false; - const lldb::RunMode stop_other_threads = m_options.m_run_mode; - - // This is a bit unfortunate, but not all the commands in this command object support - // only while stepping, so I use the bool for them. - bool bool_stop_other_threads; - if (m_options.m_run_mode == eAllThreads) - bool_stop_other_threads = false; - else if (m_options.m_run_mode == eOnlyDuringStepping) - bool_stop_other_threads = (m_step_type != eStepTypeOut && m_step_type != eStepTypeScripted); - else - bool_stop_other_threads = true; - - ThreadPlanSP new_plan_sp; - - if (m_step_type == eStepTypeInto) - { - StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); - assert(frame != nullptr); - - if (frame->HasDebugInformation ()) - { - AddressRange range; - SymbolContext sc = frame->GetSymbolContext(eSymbolContextEverything); - if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER) - { - Error error; - if (!sc.GetAddressRangeFromHereToEndLine(m_options.m_end_line, range, error)) - { - result.AppendErrorWithFormat("invalid end-line option: %s.", error.AsCString()); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - else if (m_options.m_end_line_is_block_end) - { - Error error; - Block *block = frame->GetSymbolContext(eSymbolContextBlock).block; - if (!block) - { - result.AppendErrorWithFormat("Could not find the current block."); - result.SetStatus(eReturnStatusFailed); - return false; - } - - AddressRange block_range; - Address pc_address = frame->GetFrameCodeAddress(); - block->GetRangeContainingAddress(pc_address, block_range); - if (!block_range.GetBaseAddress().IsValid()) - { - result.AppendErrorWithFormat("Could not find the current block address."); - result.SetStatus(eReturnStatusFailed); - return false; - } - lldb::addr_t pc_offset_in_block = pc_address.GetFileAddress() - block_range.GetBaseAddress().GetFileAddress(); - lldb::addr_t range_length = block_range.GetByteSize() - pc_offset_in_block; - range = AddressRange(pc_address, range_length); - } - else - { - range = sc.line_entry.range; - } - - new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans, - range, - frame->GetSymbolContext(eSymbolContextEverything), - m_options.m_step_in_target.c_str(), - stop_other_threads, - m_options.m_step_in_avoid_no_debug, - m_options.m_step_out_avoid_no_debug); - - if (new_plan_sp && !m_options.m_avoid_regexp.empty()) - { - ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan_sp.get()); - step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str()); - } - } - else - new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads); - } - else if (m_step_type == eStepTypeOver) - { - StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); - - if (frame->HasDebugInformation()) - new_plan_sp = thread->QueueThreadPlanForStepOverRange (abort_other_plans, - frame->GetSymbolContext(eSymbolContextEverything).line_entry, - frame->GetSymbolContext(eSymbolContextEverything), - stop_other_threads, - m_options.m_step_out_avoid_no_debug); - else - new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true, - abort_other_plans, - bool_stop_other_threads); - } - else if (m_step_type == eStepTypeTrace) - { - new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads); - } - else if (m_step_type == eStepTypeTraceOver) - { - new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads); - } - else if (m_step_type == eStepTypeOut) - { - new_plan_sp = thread->QueueThreadPlanForStepOut(abort_other_plans, - nullptr, - false, - bool_stop_other_threads, - eVoteYes, - eVoteNoOpinion, - thread->GetSelectedFrameIndex(), - m_options.m_step_out_avoid_no_debug); - } - else if (m_step_type == eStepTypeScripted) - { - new_plan_sp = thread->QueueThreadPlanForStepScripted (abort_other_plans, - m_options.m_class_name.c_str(), - bool_stop_other_threads); - } - else - { - result.AppendError ("step type is not supported"); - result.SetStatus (eReturnStatusFailed); + } + } else if (m_options.m_end_line_is_block_end) { + Error error; + Block *block = frame->GetSymbolContext(eSymbolContextBlock).block; + if (!block) { + result.AppendErrorWithFormat("Could not find the current block."); + result.SetStatus(eReturnStatusFailed); return false; - } - - // If we got a new plan, then set it to be a master plan (User level Plans should be master plans - // so that they can be interruptible). Then resume the process. - - if (new_plan_sp) - { - new_plan_sp->SetIsMasterPlan (true); - new_plan_sp->SetOkayToDiscard (false); - - if (m_options.m_step_count > 1) - { - if (new_plan_sp->SetIterationCount(m_options.m_step_count)) - { - result.AppendWarning ("step operation does not support iteration count."); - } - } - - process->GetThreadList().SetSelectedThreadByID (thread->GetID()); - - const uint32_t iohandler_id = process->GetIOHandlerID(); - - StreamString stream; - Error error; - if (synchronous_execution) - error = process->ResumeSynchronous (&stream); - else - error = process->Resume (); - - // There is a race condition where this thread will return up the call stack to the main command handler - // and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has - // a chance to call PushProcessIOHandler(). - process->SyncIOHandler(iohandler_id, 2000); - - if (synchronous_execution) - { - // If any state changed events had anything to say, add that to the result - if (stream.GetData()) - result.AppendMessage(stream.GetData()); + } + + AddressRange block_range; + Address pc_address = frame->GetFrameCodeAddress(); + block->GetRangeContainingAddress(pc_address, block_range); + if (!block_range.GetBaseAddress().IsValid()) { + result.AppendErrorWithFormat( + "Could not find the current block address."); + result.SetStatus(eReturnStatusFailed); + return false; + } + lldb::addr_t pc_offset_in_block = + pc_address.GetFileAddress() - + block_range.GetBaseAddress().GetFileAddress(); + lldb::addr_t range_length = + block_range.GetByteSize() - pc_offset_in_block; + range = AddressRange(pc_address, range_length); + } else { + range = sc.line_entry.range; + } + + new_plan_sp = thread->QueueThreadPlanForStepInRange( + abort_other_plans, range, + frame->GetSymbolContext(eSymbolContextEverything), + m_options.m_step_in_target.c_str(), stop_other_threads, + m_options.m_step_in_avoid_no_debug, + m_options.m_step_out_avoid_no_debug); + + if (new_plan_sp && !m_options.m_avoid_regexp.empty()) { + ThreadPlanStepInRange *step_in_range_plan = + static_cast<ThreadPlanStepInRange *>(new_plan_sp.get()); + step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str()); + } + } else + new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( + false, abort_other_plans, bool_stop_other_threads); + } else if (m_step_type == eStepTypeOver) { + StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); + + if (frame->HasDebugInformation()) + new_plan_sp = thread->QueueThreadPlanForStepOverRange( + abort_other_plans, + frame->GetSymbolContext(eSymbolContextEverything).line_entry, + frame->GetSymbolContext(eSymbolContextEverything), + stop_other_threads, m_options.m_step_out_avoid_no_debug); + else + new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( + true, abort_other_plans, bool_stop_other_threads); + } else if (m_step_type == eStepTypeTrace) { + new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( + false, abort_other_plans, bool_stop_other_threads); + } else if (m_step_type == eStepTypeTraceOver) { + new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( + true, abort_other_plans, bool_stop_other_threads); + } else if (m_step_type == eStepTypeOut) { + new_plan_sp = thread->QueueThreadPlanForStepOut( + abort_other_plans, nullptr, false, bool_stop_other_threads, eVoteYes, + eVoteNoOpinion, thread->GetSelectedFrameIndex(), + m_options.m_step_out_avoid_no_debug); + } else if (m_step_type == eStepTypeScripted) { + new_plan_sp = thread->QueueThreadPlanForStepScripted( + abort_other_plans, m_options.m_class_name.c_str(), + bool_stop_other_threads); + } else { + result.AppendError("step type is not supported"); + result.SetStatus(eReturnStatusFailed); + return false; + } - process->GetThreadList().SetSelectedThreadByID (thread->GetID()); - result.SetDidChangeProcessState (true); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.SetStatus (eReturnStatusSuccessContinuingNoResult); - } - } - else - { - result.AppendError ("Couldn't find thread plan to implement step type."); - result.SetStatus (eReturnStatusFailed); - } - return result.Succeeded(); + // If we got a new plan, then set it to be a master plan (User level Plans + // should be master plans + // so that they can be interruptible). Then resume the process. + + if (new_plan_sp) { + new_plan_sp->SetIsMasterPlan(true); + new_plan_sp->SetOkayToDiscard(false); + + if (m_options.m_step_count > 1) { + if (new_plan_sp->SetIterationCount(m_options.m_step_count)) { + result.AppendWarning( + "step operation does not support iteration count."); + } + } + + process->GetThreadList().SetSelectedThreadByID(thread->GetID()); + + const uint32_t iohandler_id = process->GetIOHandlerID(); + + StreamString stream; + Error error; + if (synchronous_execution) + error = process->ResumeSynchronous(&stream); + else + error = process->Resume(); + + // There is a race condition where this thread will return up the call + // stack to the main command handler + // and show an (lldb) prompt before HandlePrivateEvent (from + // PrivateStateThread) has + // a chance to call PushProcessIOHandler(). + process->SyncIOHandler(iohandler_id, 2000); + + if (synchronous_execution) { + // If any state changed events had anything to say, add that to the + // result + if (stream.GetData()) + result.AppendMessage(stream.GetData()); + + process->GetThreadList().SetSelectedThreadByID(thread->GetID()); + result.SetDidChangeProcessState(true); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.SetStatus(eReturnStatusSuccessContinuingNoResult); + } + } else { + result.AppendError("Couldn't find thread plan to implement step type."); + result.SetStatus(eReturnStatusFailed); } + return result.Succeeded(); + } protected: - StepType m_step_type; - StepScope m_step_scope; - CommandOptions m_options; + StepType m_step_type; + StepScope m_step_scope; + CommandOptions m_options; }; -static OptionEnumValueElement -g_tri_running_mode[] = -{ -{ eOnlyThisThread, "this-thread", "Run only this thread"}, -{ eAllThreads, "all-threads", "Run all threads"}, -{ eOnlyDuringStepping, "while-stepping", "Run only this thread while stepping"}, -{ 0, nullptr, nullptr } -}; - -static OptionEnumValueElement -g_duo_running_mode[] = -{ -{ eOnlyThisThread, "this-thread", "Run only this thread"}, -{ eAllThreads, "all-threads", "Run all threads"}, -{ 0, nullptr, nullptr } -}; - -OptionDefinition -CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] = -{ - // clang-format off +static OptionEnumValueElement g_tri_running_mode[] = { + {eOnlyThisThread, "this-thread", "Run only this thread"}, + {eAllThreads, "all-threads", "Run all threads"}, + {eOnlyDuringStepping, "while-stepping", + "Run only this thread while stepping"}, + {0, nullptr, nullptr}}; + +static OptionEnumValueElement g_duo_running_mode[] = { + {eOnlyThisThread, "this-thread", "Run only this thread"}, + {eAllThreads, "all-threads", "Run all threads"}, + {0, nullptr, nullptr}}; + +OptionDefinition CommandObjectThreadStepWithTypeAndScope::CommandOptions:: + g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "step-in-avoids-no-debug", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "A boolean value that sets whether stepping into functions will step over functions with no debug information."}, {LLDB_OPT_SET_1, false, "step-out-avoids-no-debug", 'A', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "A boolean value, if true stepping out of functions will continue to step out till it hits a function with debug information."}, {LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 1, eArgTypeCount, "How many times to perform the stepping operation - currently only supported for step-inst and next-inst."}, @@ -797,1167 +710,1045 @@ CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] = {LLDB_OPT_SET_1, false, "step-in-target", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into."}, {LLDB_OPT_SET_2, false, "python-class", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "The name of the class that will manage this step - only supported for Scripted Step."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- // CommandObjectThreadContinue //------------------------------------------------------------------------- -class CommandObjectThreadContinue : public CommandObjectParsed -{ +class CommandObjectThreadContinue : public CommandObjectParsed { public: - CommandObjectThreadContinue(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "thread continue", "Continue execution of the current target process. One " - "or more threads may be specified, by default all " - "threads continue.", - nullptr, eCommandRequiresThread | eCommandTryTargetAPILock | - eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) - { - CommandArgumentEntry arg; - CommandArgumentData thread_idx_arg; - - // Define the first (and only) variant of this arg. - thread_idx_arg.arg_type = eArgTypeThreadIndex; - thread_idx_arg.arg_repetition = eArgRepeatPlus; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (thread_idx_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); + CommandObjectThreadContinue(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "thread continue", + "Continue execution of the current target process. One " + "or more threads may be specified, by default all " + "threads continue.", + nullptr, + eCommandRequiresThread | eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) { + CommandArgumentEntry arg; + CommandArgumentData thread_idx_arg; + + // Define the first (and only) variant of this arg. + thread_idx_arg.arg_type = eArgTypeThreadIndex; + thread_idx_arg.arg_repetition = eArgRepeatPlus; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(thread_idx_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectThreadContinue() override = default; + + bool DoExecute(Args &command, CommandReturnObject &result) override { + bool synchronous_execution = m_interpreter.GetSynchronous(); + + if (!m_interpreter.GetDebugger().GetSelectedTarget()) { + result.AppendError("invalid target, create a debug target using the " + "'target create' command"); + result.SetStatus(eReturnStatusFailed); + return false; } - ~CommandObjectThreadContinue() override = default; - - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - bool synchronous_execution = m_interpreter.GetSynchronous (); - - if (!m_interpreter.GetDebugger().GetSelectedTarget()) - { - result.AppendError ("invalid target, create a debug target using the 'target create' command"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - Process *process = m_exe_ctx.GetProcessPtr(); - if (process == nullptr) - { - result.AppendError ("no process exists. Cannot continue"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - StateType state = process->GetState(); - if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended)) - { - const size_t argc = command.GetArgumentCount(); - if (argc > 0) - { - // These two lines appear at the beginning of both blocks in - // this if..else, but that is because we need to release the - // lock before calling process->Resume below. - std::lock_guard<std::recursive_mutex> guard(process->GetThreadList().GetMutex()); - const uint32_t num_threads = process->GetThreadList().GetSize(); - std::vector<Thread *> resume_threads; - for (uint32_t i = 0; i < argc; ++i) - { - bool success; - const int base = 0; - uint32_t thread_idx = StringConvert::ToUInt32 (command.GetArgumentAtIndex(i), LLDB_INVALID_INDEX32, base, &success); - if (success) - { - Thread *thread = process->GetThreadList().FindThreadByIndexID(thread_idx).get(); - - if (thread) - { - resume_threads.push_back(thread); - } - else - { - result.AppendErrorWithFormat("invalid thread index %u.\n", thread_idx); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - else - { - result.AppendErrorWithFormat ("invalid thread index argument: \"%s\".\n", command.GetArgumentAtIndex(i)); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - - if (resume_threads.empty()) - { - result.AppendError ("no valid thread indexes were specified"); - result.SetStatus (eReturnStatusFailed); - return false; - } - else - { - if (resume_threads.size() == 1) - result.AppendMessageWithFormat ("Resuming thread: "); - else - result.AppendMessageWithFormat ("Resuming threads: "); - - for (uint32_t idx = 0; idx < num_threads; ++idx) - { - Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); - std::vector<Thread *>::iterator this_thread_pos = find(resume_threads.begin(), resume_threads.end(), thread); - - if (this_thread_pos != resume_threads.end()) - { - resume_threads.erase(this_thread_pos); - if (!resume_threads.empty()) - result.AppendMessageWithFormat ("%u, ", thread->GetIndexID()); - else - result.AppendMessageWithFormat ("%u ", thread->GetIndexID()); - - const bool override_suspend = true; - thread->SetResumeState (eStateRunning, override_suspend); - } - else - { - thread->SetResumeState (eStateSuspended); - } - } - result.AppendMessageWithFormat ("in process %" PRIu64 "\n", process->GetID()); - } - } - else - { - // These two lines appear at the beginning of both blocks in - // this if..else, but that is because we need to release the - // lock before calling process->Resume below. - std::lock_guard<std::recursive_mutex> guard(process->GetThreadList().GetMutex()); - const uint32_t num_threads = process->GetThreadList().GetSize(); - Thread *current_thread = GetDefaultThread(); - if (current_thread == nullptr) - { - result.AppendError ("the process doesn't have a current thread"); - result.SetStatus (eReturnStatusFailed); - return false; - } - // Set the actions that the threads should each take when resuming - for (uint32_t idx = 0; idx < num_threads; ++idx) - { - Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); - if (thread == current_thread) - { - result.AppendMessageWithFormat ("Resuming thread 0x%4.4" PRIx64 " in process %" PRIu64 "\n", thread->GetID(), process->GetID()); - const bool override_suspend = true; - thread->SetResumeState (eStateRunning, override_suspend); - } - else - { - thread->SetResumeState (eStateSuspended); - } - } - } + Process *process = m_exe_ctx.GetProcessPtr(); + if (process == nullptr) { + result.AppendError("no process exists. Cannot continue"); + result.SetStatus(eReturnStatusFailed); + return false; + } - StreamString stream; - Error error; - if (synchronous_execution) - error = process->ResumeSynchronous (&stream); - else - error = process->Resume (); - - // We should not be holding the thread list lock when we do this. - if (error.Success()) - { - result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID()); - if (synchronous_execution) - { - // If any state changed events had anything to say, add that to the result - if (stream.GetData()) - result.AppendMessage(stream.GetData()); - - result.SetDidChangeProcessState (true); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.SetStatus (eReturnStatusSuccessContinuingNoResult); - } + StateType state = process->GetState(); + if ((state == eStateCrashed) || (state == eStateStopped) || + (state == eStateSuspended)) { + const size_t argc = command.GetArgumentCount(); + if (argc > 0) { + // These two lines appear at the beginning of both blocks in + // this if..else, but that is because we need to release the + // lock before calling process->Resume below. + std::lock_guard<std::recursive_mutex> guard( + process->GetThreadList().GetMutex()); + const uint32_t num_threads = process->GetThreadList().GetSize(); + std::vector<Thread *> resume_threads; + for (uint32_t i = 0; i < argc; ++i) { + bool success; + const int base = 0; + uint32_t thread_idx = + StringConvert::ToUInt32(command.GetArgumentAtIndex(i), + LLDB_INVALID_INDEX32, base, &success); + if (success) { + Thread *thread = + process->GetThreadList().FindThreadByIndexID(thread_idx).get(); + + if (thread) { + resume_threads.push_back(thread); + } else { + result.AppendErrorWithFormat("invalid thread index %u.\n", + thread_idx); + result.SetStatus(eReturnStatusFailed); + return false; } - else - { - result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString()); - result.SetStatus (eReturnStatusFailed); + } else { + result.AppendErrorWithFormat( + "invalid thread index argument: \"%s\".\n", + command.GetArgumentAtIndex(i)); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + + if (resume_threads.empty()) { + result.AppendError("no valid thread indexes were specified"); + result.SetStatus(eReturnStatusFailed); + return false; + } else { + if (resume_threads.size() == 1) + result.AppendMessageWithFormat("Resuming thread: "); + else + result.AppendMessageWithFormat("Resuming threads: "); + + for (uint32_t idx = 0; idx < num_threads; ++idx) { + Thread *thread = + process->GetThreadList().GetThreadAtIndex(idx).get(); + std::vector<Thread *>::iterator this_thread_pos = + find(resume_threads.begin(), resume_threads.end(), thread); + + if (this_thread_pos != resume_threads.end()) { + resume_threads.erase(this_thread_pos); + if (!resume_threads.empty()) + result.AppendMessageWithFormat("%u, ", thread->GetIndexID()); + else + result.AppendMessageWithFormat("%u ", thread->GetIndexID()); + + const bool override_suspend = true; + thread->SetResumeState(eStateRunning, override_suspend); + } else { + thread->SetResumeState(eStateSuspended); } - } - else - { - result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n", - StateAsCString(state)); - result.SetStatus (eReturnStatusFailed); - } - - return result.Succeeded(); + } + result.AppendMessageWithFormat("in process %" PRIu64 "\n", + process->GetID()); + } + } else { + // These two lines appear at the beginning of both blocks in + // this if..else, but that is because we need to release the + // lock before calling process->Resume below. + std::lock_guard<std::recursive_mutex> guard( + process->GetThreadList().GetMutex()); + const uint32_t num_threads = process->GetThreadList().GetSize(); + Thread *current_thread = GetDefaultThread(); + if (current_thread == nullptr) { + result.AppendError("the process doesn't have a current thread"); + result.SetStatus(eReturnStatusFailed); + return false; + } + // Set the actions that the threads should each take when resuming + for (uint32_t idx = 0; idx < num_threads; ++idx) { + Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); + if (thread == current_thread) { + result.AppendMessageWithFormat("Resuming thread 0x%4.4" PRIx64 + " in process %" PRIu64 "\n", + thread->GetID(), process->GetID()); + const bool override_suspend = true; + thread->SetResumeState(eStateRunning, override_suspend); + } else { + thread->SetResumeState(eStateSuspended); + } + } + } + + StreamString stream; + Error error; + if (synchronous_execution) + error = process->ResumeSynchronous(&stream); + else + error = process->Resume(); + + // We should not be holding the thread list lock when we do this. + if (error.Success()) { + result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n", + process->GetID()); + if (synchronous_execution) { + // If any state changed events had anything to say, add that to the + // result + if (stream.GetData()) + result.AppendMessage(stream.GetData()); + + result.SetDidChangeProcessState(true); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.SetStatus(eReturnStatusSuccessContinuingNoResult); + } + } else { + result.AppendErrorWithFormat("Failed to resume process: %s\n", + error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendErrorWithFormat( + "Process cannot be continued from its current state (%s).\n", + StateAsCString(state)); + result.SetStatus(eReturnStatusFailed); } + + return result.Succeeded(); + } }; //------------------------------------------------------------------------- // CommandObjectThreadUntil //------------------------------------------------------------------------- -class CommandObjectThreadUntil : public CommandObjectParsed -{ +class CommandObjectThreadUntil : public CommandObjectParsed { public: - class CommandOptions : public Options - { - public: - uint32_t m_thread_idx; - uint32_t m_frame_idx; - - CommandOptions() : - Options(), - m_thread_idx(LLDB_INVALID_THREAD_ID), - m_frame_idx(LLDB_INVALID_FRAME_ID) - { - // Keep default values of all options in one place: OptionParsingStarting () - OptionParsingStarting(nullptr); - } - - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'a': - { - lldb::addr_t tmp_addr = - Args::StringToAddress(execution_context, option_arg, - LLDB_INVALID_ADDRESS, &error); - if (error.Success()) - m_until_addrs.push_back(tmp_addr); - } - break; - case 't': - m_thread_idx = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_INDEX32); - if (m_thread_idx == LLDB_INVALID_INDEX32) - { - error.SetErrorStringWithFormat ("invalid thread index '%s'", option_arg); - } - break; - case 'f': - m_frame_idx = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_FRAME_ID); - if (m_frame_idx == LLDB_INVALID_FRAME_ID) - { - error.SetErrorStringWithFormat ("invalid frame index '%s'", option_arg); - } - break; - case 'm': - { - OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; - lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error); - - if (error.Success()) - { - if (run_mode == eAllThreads) - m_stop_others = false; - else - m_stop_others = true; - } - } - break; - default: - error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); - break; - } - return error; - } + class CommandOptions : public Options { + public: + uint32_t m_thread_idx; + uint32_t m_frame_idx; + + CommandOptions() + : Options(), m_thread_idx(LLDB_INVALID_THREAD_ID), + m_frame_idx(LLDB_INVALID_FRAME_ID) { + // Keep default values of all options in one place: OptionParsingStarting + // () + OptionParsingStarting(nullptr); + } - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_thread_idx = LLDB_INVALID_THREAD_ID; - m_frame_idx = 0; + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'a': { + lldb::addr_t tmp_addr = Args::StringToAddress( + execution_context, option_arg, LLDB_INVALID_ADDRESS, &error); + if (error.Success()) + m_until_addrs.push_back(tmp_addr); + } break; + case 't': + m_thread_idx = + StringConvert::ToUInt32(option_arg, LLDB_INVALID_INDEX32); + if (m_thread_idx == LLDB_INVALID_INDEX32) { + error.SetErrorStringWithFormat("invalid thread index '%s'", + option_arg); + } + break; + case 'f': + m_frame_idx = + StringConvert::ToUInt32(option_arg, LLDB_INVALID_FRAME_ID); + if (m_frame_idx == LLDB_INVALID_FRAME_ID) { + error.SetErrorStringWithFormat("invalid frame index '%s'", + option_arg); + } + break; + case 'm': { + OptionEnumValueElement *enum_values = + g_option_table[option_idx].enum_values; + lldb::RunMode run_mode = (lldb::RunMode)Args::StringToOptionEnum( + option_arg, enum_values, eOnlyDuringStepping, error); + + if (error.Success()) { + if (run_mode == eAllThreads) m_stop_others = false; - m_until_addrs.clear(); - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - uint32_t m_step_thread_idx; - bool m_stop_others; - std::vector<lldb::addr_t> m_until_addrs; - - // Options table: Required for subclasses of Options. + else + m_stop_others = true; + } + } break; + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", + short_option); + break; + } + return error; + } - static OptionDefinition g_option_table[]; + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_thread_idx = LLDB_INVALID_THREAD_ID; + m_frame_idx = 0; + m_stop_others = false; + m_until_addrs.clear(); + } - // Instance variables to hold the values for command options. - }; + const OptionDefinition *GetDefinitions() override { return g_option_table; } - CommandObjectThreadUntil(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "thread until", "Continue until a line number or address is reached by the " - "current or specified thread. Stops when returning from " - "the current function as a safety measure.", - nullptr, eCommandRequiresThread | eCommandTryTargetAPILock | - eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), - m_options() - { - CommandArgumentEntry arg; - CommandArgumentData line_num_arg; - - // Define the first (and only) variant of this arg. - line_num_arg.arg_type = eArgTypeLineNum; - line_num_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (line_num_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - } + uint32_t m_step_thread_idx; + bool m_stop_others; + std::vector<lldb::addr_t> m_until_addrs; - ~CommandObjectThreadUntil() override = default; + // Options table: Required for subclasses of Options. - Options * - GetOptions () override - { - return &m_options; - } + static OptionDefinition g_option_table[]; -protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - bool synchronous_execution = m_interpreter.GetSynchronous (); + // Instance variables to hold the values for command options. + }; - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) - { - result.AppendError ("invalid target, create a debug target using the 'target create' command"); - result.SetStatus (eReturnStatusFailed); - return false; - } + CommandObjectThreadUntil(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "thread until", + "Continue until a line number or address is reached by the " + "current or specified thread. Stops when returning from " + "the current function as a safety measure.", + nullptr, + eCommandRequiresThread | eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), + m_options() { + CommandArgumentEntry arg; + CommandArgumentData line_num_arg; - Process *process = m_exe_ctx.GetProcessPtr(); - if (process == nullptr) - { - result.AppendError ("need a valid process to step"); - result.SetStatus (eReturnStatusFailed); - } - else - { - Thread *thread = nullptr; - std::vector<uint32_t> line_numbers; - - if (command.GetArgumentCount() >= 1) - { - 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(0), UINT32_MAX); - if (line_number == UINT32_MAX) - { - result.AppendErrorWithFormat ("invalid line number: '%s'.\n", command.GetArgumentAtIndex(0)); - result.SetStatus (eReturnStatusFailed); - return false; - } - else - line_numbers.push_back(line_number); - } - } - else if (m_options.m_until_addrs.empty()) - { - result.AppendErrorWithFormat ("No line number or address provided:\n%s", GetSyntax()); - result.SetStatus (eReturnStatusFailed); - return false; - } + // Define the first (and only) variant of this arg. + line_num_arg.arg_type = eArgTypeLineNum; + line_num_arg.arg_repetition = eArgRepeatPlain; - if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID) - { - thread = GetDefaultThread(); - } - else - { - thread = process->GetThreadList().FindThreadByIndexID(m_options.m_thread_idx).get(); - } + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(line_num_arg); - if (thread == nullptr) - { - const uint32_t num_threads = process->GetThreadList().GetSize(); - result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", - m_options.m_thread_idx, - num_threads); - result.SetStatus (eReturnStatusFailed); - return false; - } + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } - const bool abort_other_plans = false; + ~CommandObjectThreadUntil() override = default; - StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get(); - if (frame == nullptr) - { - result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", - m_options.m_frame_idx, - m_options.m_thread_idx); - result.SetStatus (eReturnStatusFailed); - return false; - } + Options *GetOptions() override { return &m_options; } - ThreadPlanSP new_plan_sp; - - if (frame->HasDebugInformation ()) - { - // Finally we got here... Translate the given line number to a bunch of addresses: - SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit)); - LineTable *line_table = nullptr; - if (sc.comp_unit) - line_table = sc.comp_unit->GetLineTable(); - - if (line_table == nullptr) - { - result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n", - m_options.m_frame_idx, m_options.m_thread_idx); - result.SetStatus (eReturnStatusFailed); - return false; - } - - LineEntry function_start; - uint32_t index_ptr = 0, end_ptr; - std::vector<addr_t> address_list; - - // Find the beginning & end index of the - AddressRange fun_addr_range = sc.function->GetAddressRange(); - Address fun_start_addr = fun_addr_range.GetBaseAddress(); - line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr); - - Address fun_end_addr(fun_start_addr.GetSection(), - fun_start_addr.GetOffset() + fun_addr_range.GetByteSize()); - - bool all_in_function = true; - - line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr); - - for (uint32_t line_number : line_numbers) - { - uint32_t start_idx_ptr = index_ptr; - while (start_idx_ptr <= end_ptr) - { - LineEntry line_entry; - const bool exact = false; - start_idx_ptr = sc.comp_unit->FindLineEntry(start_idx_ptr, line_number, sc.comp_unit, exact, &line_entry); - if (start_idx_ptr == UINT32_MAX) - break; - - addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target); - if (address != LLDB_INVALID_ADDRESS) - { - if (fun_addr_range.ContainsLoadAddress (address, target)) - address_list.push_back (address); - else - all_in_function = false; - } - start_idx_ptr++; - } - } - - for (lldb::addr_t address : m_options.m_until_addrs) - { - if (fun_addr_range.ContainsLoadAddress (address, target)) - address_list.push_back (address); - else - all_in_function = false; - } - - if (address_list.empty()) - { - if (all_in_function) - result.AppendErrorWithFormat ("No line entries matching until target.\n"); - else - result.AppendErrorWithFormat ("Until target outside of the current function.\n"); - - result.SetStatus (eReturnStatusFailed); - return false; - } - - new_plan_sp = thread->QueueThreadPlanForStepUntil (abort_other_plans, - &address_list.front(), - address_list.size(), - m_options.m_stop_others, - m_options.m_frame_idx); - // User level plans should be master plans so they can be interrupted (e.g. by hitting a breakpoint) - // and other plans executed by the user (stepping around the breakpoint) and then a "continue" - // will resume the original plan. - new_plan_sp->SetIsMasterPlan (true); - new_plan_sp->SetOkayToDiscard(false); - } - else - { - result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", - m_options.m_frame_idx, - m_options.m_thread_idx); - result.SetStatus (eReturnStatusFailed); - return false; - } +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + bool synchronous_execution = m_interpreter.GetSynchronous(); + + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (target == nullptr) { + result.AppendError("invalid target, create a debug target using the " + "'target create' command"); + result.SetStatus(eReturnStatusFailed); + return false; + } - process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx); - - StreamString stream; - Error error; - if (synchronous_execution) - error = process->ResumeSynchronous (&stream); - else - error = process->Resume (); - - if (error.Success()) - { - result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID()); - if (synchronous_execution) - { - // If any state changed events had anything to say, add that to the result - if (stream.GetData()) - result.AppendMessage(stream.GetData()); - - result.SetDidChangeProcessState (true); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.SetStatus (eReturnStatusSuccessContinuingNoResult); - } - } - else - { - result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); - result.SetStatus (eReturnStatusFailed); + Process *process = m_exe_ctx.GetProcessPtr(); + if (process == nullptr) { + result.AppendError("need a valid process to step"); + result.SetStatus(eReturnStatusFailed); + } else { + Thread *thread = nullptr; + std::vector<uint32_t> line_numbers; + + if (command.GetArgumentCount() >= 1) { + 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(0), + UINT32_MAX); + if (line_number == UINT32_MAX) { + result.AppendErrorWithFormat("invalid line number: '%s'.\n", + command.GetArgumentAtIndex(0)); + result.SetStatus(eReturnStatusFailed); + return false; + } else + line_numbers.push_back(line_number); + } + } else if (m_options.m_until_addrs.empty()) { + result.AppendErrorWithFormat("No line number or address provided:\n%s", + GetSyntax()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID) { + thread = GetDefaultThread(); + } else { + thread = process->GetThreadList() + .FindThreadByIndexID(m_options.m_thread_idx) + .get(); + } + + if (thread == nullptr) { + const uint32_t num_threads = process->GetThreadList().GetSize(); + result.AppendErrorWithFormat( + "Thread index %u is out of range (valid values are 0 - %u).\n", + m_options.m_thread_idx, num_threads); + result.SetStatus(eReturnStatusFailed); + return false; + } + + const bool abort_other_plans = false; + + StackFrame *frame = + thread->GetStackFrameAtIndex(m_options.m_frame_idx).get(); + if (frame == nullptr) { + result.AppendErrorWithFormat( + "Frame index %u is out of range for thread %u.\n", + m_options.m_frame_idx, m_options.m_thread_idx); + result.SetStatus(eReturnStatusFailed); + return false; + } + + ThreadPlanSP new_plan_sp; + + if (frame->HasDebugInformation()) { + // Finally we got here... Translate the given line number to a bunch of + // addresses: + SymbolContext sc(frame->GetSymbolContext(eSymbolContextCompUnit)); + LineTable *line_table = nullptr; + if (sc.comp_unit) + line_table = sc.comp_unit->GetLineTable(); + + if (line_table == nullptr) { + result.AppendErrorWithFormat("Failed to resolve the line table for " + "frame %u of thread index %u.\n", + m_options.m_frame_idx, + m_options.m_thread_idx); + result.SetStatus(eReturnStatusFailed); + return false; + } + + LineEntry function_start; + uint32_t index_ptr = 0, end_ptr; + std::vector<addr_t> address_list; + + // Find the beginning & end index of the + AddressRange fun_addr_range = sc.function->GetAddressRange(); + Address fun_start_addr = fun_addr_range.GetBaseAddress(); + line_table->FindLineEntryByAddress(fun_start_addr, function_start, + &index_ptr); + + Address fun_end_addr(fun_start_addr.GetSection(), + fun_start_addr.GetOffset() + + fun_addr_range.GetByteSize()); + + bool all_in_function = true; + + line_table->FindLineEntryByAddress(fun_end_addr, function_start, + &end_ptr); + + for (uint32_t line_number : line_numbers) { + uint32_t start_idx_ptr = index_ptr; + while (start_idx_ptr <= end_ptr) { + LineEntry line_entry; + const bool exact = false; + start_idx_ptr = sc.comp_unit->FindLineEntry( + start_idx_ptr, line_number, sc.comp_unit, exact, &line_entry); + if (start_idx_ptr == UINT32_MAX) + break; + + addr_t address = + line_entry.range.GetBaseAddress().GetLoadAddress(target); + if (address != LLDB_INVALID_ADDRESS) { + if (fun_addr_range.ContainsLoadAddress(address, target)) + address_list.push_back(address); + else + all_in_function = false; } - - } - return result.Succeeded(); + start_idx_ptr++; + } + } + + for (lldb::addr_t address : m_options.m_until_addrs) { + if (fun_addr_range.ContainsLoadAddress(address, target)) + address_list.push_back(address); + else + all_in_function = false; + } + + if (address_list.empty()) { + if (all_in_function) + result.AppendErrorWithFormat( + "No line entries matching until target.\n"); + else + result.AppendErrorWithFormat( + "Until target outside of the current function.\n"); + + result.SetStatus(eReturnStatusFailed); + return false; + } + + new_plan_sp = thread->QueueThreadPlanForStepUntil( + abort_other_plans, &address_list.front(), address_list.size(), + m_options.m_stop_others, m_options.m_frame_idx); + // User level plans should be master plans so they can be interrupted + // (e.g. by hitting a breakpoint) + // and other plans executed by the user (stepping around the breakpoint) + // and then a "continue" + // will resume the original plan. + new_plan_sp->SetIsMasterPlan(true); + new_plan_sp->SetOkayToDiscard(false); + } else { + result.AppendErrorWithFormat( + "Frame index %u of thread %u has no debug information.\n", + m_options.m_frame_idx, m_options.m_thread_idx); + result.SetStatus(eReturnStatusFailed); + return false; + } + + process->GetThreadList().SetSelectedThreadByID(m_options.m_thread_idx); + + StreamString stream; + Error error; + if (synchronous_execution) + error = process->ResumeSynchronous(&stream); + else + error = process->Resume(); + + if (error.Success()) { + result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n", + process->GetID()); + if (synchronous_execution) { + // If any state changed events had anything to say, add that to the + // result + if (stream.GetData()) + result.AppendMessage(stream.GetData()); + + result.SetDidChangeProcessState(true); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.SetStatus(eReturnStatusSuccessContinuingNoResult); + } + } else { + result.AppendErrorWithFormat("Failed to resume process: %s.\n", + error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } } + return result.Succeeded(); + } - CommandOptions m_options; + CommandOptions m_options; }; -OptionDefinition -CommandObjectThreadUntil::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectThreadUntil::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "frame", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0"}, {LLDB_OPT_SET_1, false, "thread", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"}, {LLDB_OPT_SET_1, false, "run-mode",'m', OptionParser::eRequiredArgument, nullptr, g_duo_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping this one"}, {LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Run until we reach the specified address, or leave the function - can be specified multiple times."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- // CommandObjectThreadSelect //------------------------------------------------------------------------- -class CommandObjectThreadSelect : public CommandObjectParsed -{ +class CommandObjectThreadSelect : public CommandObjectParsed { public: - CommandObjectThreadSelect(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "thread select", "Change the currently selected thread.", nullptr, - eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | - eCommandProcessMustBePaused) - { - CommandArgumentEntry arg; - CommandArgumentData thread_idx_arg; - - // Define the first (and only) variant of this arg. - thread_idx_arg.arg_type = eArgTypeThreadIndex; - thread_idx_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (thread_idx_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - } + CommandObjectThreadSelect(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "thread select", + "Change the currently selected thread.", nullptr, + eCommandRequiresProcess | eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused) { + CommandArgumentEntry arg; + CommandArgumentData thread_idx_arg; - ~CommandObjectThreadSelect() override = default; + // Define the first (and only) variant of this arg. + thread_idx_arg.arg_type = eArgTypeThreadIndex; + thread_idx_arg.arg_repetition = eArgRepeatPlain; -protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Process *process = m_exe_ctx.GetProcessPtr(); - if (process == nullptr) - { - result.AppendError ("no process"); - result.SetStatus (eReturnStatusFailed); - return false; - } - else if (command.GetArgumentCount() != 1) - { - result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); - result.SetStatus (eReturnStatusFailed); - return false; - } + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(thread_idx_arg); - uint32_t index_id = StringConvert::ToUInt32(command.GetArgumentAtIndex(0), 0, 0); + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } - Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get(); - if (new_thread == nullptr) - { - result.AppendErrorWithFormat ("invalid thread #%s.\n", command.GetArgumentAtIndex(0)); - result.SetStatus (eReturnStatusFailed); - return false; - } + ~CommandObjectThreadSelect() override = default; - process->GetThreadList().SetSelectedThreadByID(new_thread->GetID(), true); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - - return result.Succeeded(); +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + Process *process = m_exe_ctx.GetProcessPtr(); + if (process == nullptr) { + result.AppendError("no process"); + result.SetStatus(eReturnStatusFailed); + return false; + } else if (command.GetArgumentCount() != 1) { + result.AppendErrorWithFormat( + "'%s' takes exactly one thread index argument:\nUsage: %s\n", + m_cmd_name.c_str(), m_cmd_syntax.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; } + + uint32_t index_id = + StringConvert::ToUInt32(command.GetArgumentAtIndex(0), 0, 0); + + Thread *new_thread = + process->GetThreadList().FindThreadByIndexID(index_id).get(); + if (new_thread == nullptr) { + result.AppendErrorWithFormat("invalid thread #%s.\n", + command.GetArgumentAtIndex(0)); + result.SetStatus(eReturnStatusFailed); + return false; + } + + process->GetThreadList().SetSelectedThreadByID(new_thread->GetID(), true); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + + return result.Succeeded(); + } }; //------------------------------------------------------------------------- // CommandObjectThreadList //------------------------------------------------------------------------- -class CommandObjectThreadList : public CommandObjectParsed -{ +class CommandObjectThreadList : public CommandObjectParsed { public: - CommandObjectThreadList(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "thread list", - "Show a summary of each thread in the current target process.", "thread list", - eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | - eCommandProcessMustBePaused) - { - } + CommandObjectThreadList(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "thread list", + "Show a summary of each thread in the current target process.", + "thread list", + eCommandRequiresProcess | eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} - ~CommandObjectThreadList() override = default; + ~CommandObjectThreadList() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Stream &strm = result.GetOutputStream(); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - Process *process = m_exe_ctx.GetProcessPtr(); - const bool only_threads_with_stop_reason = false; - const uint32_t start_frame = 0; - const uint32_t num_frames = 0; - const uint32_t num_frames_with_source = 0; - process->GetStatus(strm); - process->GetThreadStatus (strm, - only_threads_with_stop_reason, - start_frame, - num_frames, - num_frames_with_source); - return result.Succeeded(); - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + Stream &strm = result.GetOutputStream(); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + Process *process = m_exe_ctx.GetProcessPtr(); + const bool only_threads_with_stop_reason = false; + const uint32_t start_frame = 0; + const uint32_t num_frames = 0; + const uint32_t num_frames_with_source = 0; + process->GetStatus(strm); + process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame, + num_frames, num_frames_with_source); + return result.Succeeded(); + } }; //------------------------------------------------------------------------- // CommandObjectThreadInfo //------------------------------------------------------------------------- -class CommandObjectThreadInfo : public CommandObjectIterateOverThreads -{ +class CommandObjectThreadInfo : public CommandObjectIterateOverThreads { public: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - OptionParsingStarting(nullptr); - } - - ~CommandOptions() override = default; + class CommandOptions : public Options { + public: + CommandOptions() : Options() { OptionParsingStarting(nullptr); } - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_json_thread = false; - m_json_stopinfo = false; - } + ~CommandOptions() override = default; - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - const int short_option = m_getopt_table[option_idx].val; - Error error; - - switch (short_option) - { - case 'j': - m_json_thread = true; - break; - - case 's': - m_json_stopinfo = true; - break; - - default: - return Error("invalid short option character '%c'", short_option); - } - return error; - } + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_json_thread = false; + m_json_stopinfo = false; + } - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + const int short_option = m_getopt_table[option_idx].val; + Error error; - bool m_json_thread; - bool m_json_stopinfo; + switch (short_option) { + case 'j': + m_json_thread = true; + break; - static OptionDefinition g_option_table[]; - }; + case 's': + m_json_stopinfo = true; + break; - CommandObjectThreadInfo(CommandInterpreter &interpreter) - : CommandObjectIterateOverThreads( - interpreter, "thread info", - "Show an extended summary of one or more threads. Defaults to the current thread.", "thread info", - eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | - eCommandProcessMustBePaused), - m_options() - { - m_add_return = false; + default: + return Error("invalid short option character '%c'", short_option); + } + return error; } - ~CommandObjectThreadInfo() override = default; - - Options * - GetOptions () override - { - return &m_options; + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + bool m_json_thread; + bool m_json_stopinfo; + + static OptionDefinition g_option_table[]; + }; + + CommandObjectThreadInfo(CommandInterpreter &interpreter) + : CommandObjectIterateOverThreads( + interpreter, "thread info", "Show an extended summary of one or " + "more threads. Defaults to the " + "current thread.", + "thread info", + eCommandRequiresProcess | eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), + m_options() { + m_add_return = false; + } + + ~CommandObjectThreadInfo() override = default; + + Options *GetOptions() override { return &m_options; } + + 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; } - 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; - } - - Thread *thread = thread_sp.get(); + Thread *thread = thread_sp.get(); - Stream &strm = result.GetOutputStream(); - if (!thread->GetDescription (strm, eDescriptionLevelFull, m_options.m_json_thread, m_options.m_json_stopinfo)) - { - result.AppendErrorWithFormat ("error displaying info for thread: \"%d\"\n", thread->GetIndexID()); - result.SetStatus (eReturnStatusFailed); - return false; - } - return true; + Stream &strm = result.GetOutputStream(); + if (!thread->GetDescription(strm, eDescriptionLevelFull, + m_options.m_json_thread, + m_options.m_json_stopinfo)) { + result.AppendErrorWithFormat("error displaying info for thread: \"%d\"\n", + thread->GetIndexID()); + result.SetStatus(eReturnStatusFailed); + return false; } + return true; + } - CommandOptions m_options; + CommandOptions m_options; }; -OptionDefinition -CommandObjectThreadInfo::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectThreadInfo::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_ALL, false, "json", 'j', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the thread info in JSON format."}, {LLDB_OPT_SET_ALL, false, "stop-info", 's', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the extended stop info in JSON format."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- // CommandObjectThreadReturn //------------------------------------------------------------------------- -class CommandObjectThreadReturn : public CommandObjectRaw -{ +class CommandObjectThreadReturn : public CommandObjectRaw { public: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options(), - m_from_expression(false) - { - // Keep default values of all options in one place: OptionParsingStarting () - OptionParsingStarting(nullptr); - } + class CommandOptions : public Options { + public: + CommandOptions() : Options(), m_from_expression(false) { + // Keep default values of all options in one place: OptionParsingStarting + // () + OptionParsingStarting(nullptr); + } - ~CommandOptions() override = default; - - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'x': - { - bool success; - bool tmp_value = Args::StringToBoolean (option_arg, false, &success); - if (success) - m_from_expression = tmp_value; - else - { - error.SetErrorStringWithFormat ("invalid boolean value '%s' for 'x' option", option_arg); - } - } - break; - default: - error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); - break; - } - return error; - } + ~CommandOptions() override = default; - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_from_expression = false; - } + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } + switch (short_option) { + case 'x': { + bool success; + bool tmp_value = Args::StringToBoolean(option_arg, false, &success); + if (success) + m_from_expression = tmp_value; + else { + error.SetErrorStringWithFormat( + "invalid boolean value '%s' for 'x' option", option_arg); + } + } break; + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", + short_option); + break; + } + return error; + } - bool m_from_expression; + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_from_expression = false; + } - // Options table: Required for subclasses of Options. + const OptionDefinition *GetDefinitions() override { return g_option_table; } - static OptionDefinition g_option_table[]; + bool m_from_expression; - // Instance variables to hold the values for command options. - }; + // Options table: Required for subclasses of Options. - CommandObjectThreadReturn(CommandInterpreter &interpreter) - : CommandObjectRaw(interpreter, "thread return", - "Prematurely return from a stack frame, short-circuiting execution of newer frames " - "and optionally yielding a specified value. Defaults to the exiting the current stack " - "frame.", - "thread return", eCommandRequiresFrame | eCommandTryTargetAPILock | - eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), - m_options() - { - CommandArgumentEntry arg; - CommandArgumentData expression_arg; + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + }; + + CommandObjectThreadReturn(CommandInterpreter &interpreter) + : CommandObjectRaw(interpreter, "thread return", + "Prematurely return from a stack frame, " + "short-circuiting execution of newer frames " + "and optionally yielding a specified value. Defaults " + "to the exiting the current stack " + "frame.", + "thread return", + eCommandRequiresFrame | eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused), + m_options() { + CommandArgumentEntry arg; + CommandArgumentData expression_arg; + + // Define the first (and only) variant of this arg. + expression_arg.arg_type = eArgTypeExpression; + expression_arg.arg_repetition = eArgRepeatOptional; - // Define the first (and only) variant of this arg. - expression_arg.arg_type = eArgTypeExpression; - expression_arg.arg_repetition = eArgRepeatOptional; + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(expression_arg); - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (expression_arg); + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); + ~CommandObjectThreadReturn() override = default; + + Options *GetOptions() override { return &m_options; } + +protected: + bool DoExecute(const char *command, CommandReturnObject &result) override { + // I am going to handle this by hand, because I don't want you to have to + // say: + // "thread return -- -5". + if (command[0] == '-' && command[1] == 'x') { + if (command && command[2] != '\0') + result.AppendWarning("Return values ignored when returning from user " + "called expressions"); + + Thread *thread = m_exe_ctx.GetThreadPtr(); + Error error; + error = thread->UnwindInnermostExpression(); + if (!error.Success()) { + result.AppendErrorWithFormat("Unwinding expression failed - %s.", + error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } else { + bool success = + thread->SetSelectedFrameByIndexNoisily(0, result.GetOutputStream()); + if (success) { + m_exe_ctx.SetFrameSP(thread->GetSelectedFrame()); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat( + "Could not select 0th frame after unwinding expression."); + result.SetStatus(eReturnStatusFailed); + } + } + return result.Succeeded(); } - ~CommandObjectThreadReturn() override = default; + ValueObjectSP return_valobj_sp; - Options * - GetOptions() override - { - return &m_options; + StackFrameSP frame_sp = m_exe_ctx.GetFrameSP(); + uint32_t frame_idx = frame_sp->GetFrameIndex(); + + if (frame_sp->IsInlined()) { + result.AppendError("Don't know how to return from inlined frames."); + result.SetStatus(eReturnStatusFailed); + return false; } -protected: - bool - DoExecute (const char *command, CommandReturnObject &result) override - { - // I am going to handle this by hand, because I don't want you to have to say: - // "thread return -- -5". - if (command[0] == '-' && command[1] == 'x') - { - if (command && command[2] != '\0') - result.AppendWarning("Return values ignored when returning from user called expressions"); - - Thread *thread = m_exe_ctx.GetThreadPtr(); - Error error; - error = thread->UnwindInnermostExpression(); - if (!error.Success()) - { - result.AppendErrorWithFormat ("Unwinding expression failed - %s.", error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - else - { - bool success = thread->SetSelectedFrameByIndexNoisily (0, result.GetOutputStream()); - if (success) - { - m_exe_ctx.SetFrameSP(thread->GetSelectedFrame ()); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendErrorWithFormat ("Could not select 0th frame after unwinding expression."); - result.SetStatus (eReturnStatusFailed); - } - } - return result.Succeeded(); - } - - ValueObjectSP return_valobj_sp; - - StackFrameSP frame_sp = m_exe_ctx.GetFrameSP(); - uint32_t frame_idx = frame_sp->GetFrameIndex(); - - if (frame_sp->IsInlined()) - { - result.AppendError("Don't know how to return from inlined frames."); - result.SetStatus (eReturnStatusFailed); - return false; - } - - if (command && command[0] != '\0') - { - Target *target = m_exe_ctx.GetTargetPtr(); - EvaluateExpressionOptions options; - - options.SetUnwindOnError(true); - options.SetUseDynamic(eNoDynamicValues); - - ExpressionResults exe_results = eExpressionSetupError; - exe_results = target->EvaluateExpression (command, - frame_sp.get(), - return_valobj_sp, - options); - if (exe_results != eExpressionCompleted) - { - if (return_valobj_sp) - result.AppendErrorWithFormat("Error evaluating result expression: %s", return_valobj_sp->GetError().AsCString()); - else - result.AppendErrorWithFormat("Unknown error evaluating result expression."); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - - Error error; - ThreadSP thread_sp = m_exe_ctx.GetThreadSP(); - const bool broadcast = true; - error = thread_sp->ReturnFromFrame (frame_sp, return_valobj_sp, broadcast); - if (!error.Success()) - { - result.AppendErrorWithFormat("Error returning from frame %d of thread %d: %s.", frame_idx, thread_sp->GetIndexID(), error.AsCString()); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (command && command[0] != '\0') { + Target *target = m_exe_ctx.GetTargetPtr(); + EvaluateExpressionOptions options; + + options.SetUnwindOnError(true); + options.SetUseDynamic(eNoDynamicValues); + + ExpressionResults exe_results = eExpressionSetupError; + exe_results = target->EvaluateExpression(command, frame_sp.get(), + return_valobj_sp, options); + if (exe_results != eExpressionCompleted) { + if (return_valobj_sp) + result.AppendErrorWithFormat( + "Error evaluating result expression: %s", + return_valobj_sp->GetError().AsCString()); + else + result.AppendErrorWithFormat( + "Unknown error evaluating result expression."); + result.SetStatus(eReturnStatusFailed); + return false; + } + } - result.SetStatus (eReturnStatusSuccessFinishResult); - return true; + Error error; + ThreadSP thread_sp = m_exe_ctx.GetThreadSP(); + const bool broadcast = true; + error = thread_sp->ReturnFromFrame(frame_sp, return_valobj_sp, broadcast); + if (!error.Success()) { + result.AppendErrorWithFormat( + "Error returning from frame %d of thread %d: %s.", frame_idx, + thread_sp->GetIndexID(), error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; } - - CommandOptions m_options; + + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } + + CommandOptions m_options; }; -OptionDefinition -CommandObjectThreadReturn::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectThreadReturn::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_ALL, false, "from-expression", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Return from the innermost expression evaluation."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- // CommandObjectThreadJump //------------------------------------------------------------------------- -class CommandObjectThreadJump : public CommandObjectParsed -{ +class CommandObjectThreadJump : public CommandObjectParsed { public: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - OptionParsingStarting(nullptr); - } - - ~CommandOptions() override = default; - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_filenames.Clear(); - m_line_num = 0; - m_line_offset = 0; - m_load_addr = LLDB_INVALID_ADDRESS; - m_force = false; - } - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - bool success; - const int short_option = m_getopt_table[option_idx].val; - Error error; - - switch (short_option) - { - case 'f': - m_filenames.AppendIfUnique (FileSpec(option_arg, false)); - if (m_filenames.GetSize() > 1) - return Error("only one source file expected."); - break; - case 'l': - m_line_num = StringConvert::ToUInt32 (option_arg, 0, 0, &success); - if (!success || m_line_num == 0) - return Error("invalid line number: '%s'.", option_arg); - break; - case 'b': - m_line_offset = StringConvert::ToSInt32 (option_arg, 0, 0, &success); - if (!success) - return Error("invalid line offset: '%s'.", option_arg); - break; - case 'a': - m_load_addr = Args::StringToAddress(execution_context, - option_arg, - LLDB_INVALID_ADDRESS, - &error); - break; - case 'r': - m_force = true; - break; - default: - return Error("invalid short option character '%c'", short_option); - } - return error; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - FileSpecList m_filenames; - uint32_t m_line_num; - int32_t m_line_offset; - lldb::addr_t m_load_addr; - bool m_force; - - static OptionDefinition g_option_table[]; - }; - - CommandObjectThreadJump (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "thread jump", - "Sets the program counter to a new address.", - "thread jump", - eCommandRequiresFrame | - eCommandTryTargetAPILock | - eCommandProcessMustBeLaunched | - eCommandProcessMustBePaused ), - m_options() - { + class CommandOptions : public Options { + public: + CommandOptions() : Options() { OptionParsingStarting(nullptr); } + + ~CommandOptions() override = default; + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_filenames.Clear(); + m_line_num = 0; + m_line_offset = 0; + m_load_addr = LLDB_INVALID_ADDRESS; + m_force = false; } - ~CommandObjectThreadJump() override = default; - - Options * - GetOptions() override - { - return &m_options; + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + bool success; + const int short_option = m_getopt_table[option_idx].val; + Error error; + + switch (short_option) { + case 'f': + m_filenames.AppendIfUnique(FileSpec(option_arg, false)); + if (m_filenames.GetSize() > 1) + return Error("only one source file expected."); + break; + case 'l': + m_line_num = StringConvert::ToUInt32(option_arg, 0, 0, &success); + if (!success || m_line_num == 0) + return Error("invalid line number: '%s'.", option_arg); + break; + case 'b': + m_line_offset = StringConvert::ToSInt32(option_arg, 0, 0, &success); + if (!success) + return Error("invalid line offset: '%s'.", option_arg); + break; + case 'a': + m_load_addr = Args::StringToAddress(execution_context, option_arg, + LLDB_INVALID_ADDRESS, &error); + break; + case 'r': + m_force = true; + break; + default: + return Error("invalid short option character '%c'", short_option); + } + return error; } -protected: - bool DoExecute (Args& args, CommandReturnObject &result) override - { - RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); - StackFrame *frame = m_exe_ctx.GetFramePtr(); - Thread *thread = m_exe_ctx.GetThreadPtr(); - Target *target = m_exe_ctx.GetTargetPtr(); - const SymbolContext &sym_ctx = frame->GetSymbolContext (eSymbolContextLineEntry); - - if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) - { - // Use this address directly. - Address dest = Address(m_options.m_load_addr); - - lldb::addr_t callAddr = dest.GetCallableLoadAddress (target); - if (callAddr == LLDB_INVALID_ADDRESS) - { - result.AppendErrorWithFormat ("Invalid destination address."); - result.SetStatus (eReturnStatusFailed); - return false; - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } - if (!reg_ctx->SetPC (callAddr)) - { - result.AppendErrorWithFormat ("Error changing PC value for thread %d.", thread->GetIndexID()); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - else - { - // Pick either the absolute line, or work out a relative one. - int32_t line = (int32_t)m_options.m_line_num; - if (line == 0) - line = sym_ctx.line_entry.line + m_options.m_line_offset; - - // Try the current file, but override if asked. - FileSpec file = sym_ctx.line_entry.file; - if (m_options.m_filenames.GetSize() == 1) - file = m_options.m_filenames.GetFileSpecAtIndex(0); - - if (!file) - { - result.AppendErrorWithFormat ("No source file available for the current location."); - result.SetStatus (eReturnStatusFailed); - return false; - } + FileSpecList m_filenames; + uint32_t m_line_num; + int32_t m_line_offset; + lldb::addr_t m_load_addr; + bool m_force; - std::string warnings; - Error err = thread->JumpToLine (file, line, m_options.m_force, &warnings); + static OptionDefinition g_option_table[]; + }; - if (err.Fail()) - { - result.SetError (err); - return false; - } + CommandObjectThreadJump(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "thread jump", + "Sets the program counter to a new address.", "thread jump", + eCommandRequiresFrame | eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), + m_options() {} - if (!warnings.empty()) - result.AppendWarning (warnings.c_str()); - } + ~CommandObjectThreadJump() override = default; - result.SetStatus (eReturnStatusSuccessFinishResult); - return true; + Options *GetOptions() override { return &m_options; } + +protected: + bool DoExecute(Args &args, CommandReturnObject &result) override { + RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); + StackFrame *frame = m_exe_ctx.GetFramePtr(); + Thread *thread = m_exe_ctx.GetThreadPtr(); + Target *target = m_exe_ctx.GetTargetPtr(); + const SymbolContext &sym_ctx = + frame->GetSymbolContext(eSymbolContextLineEntry); + + if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) { + // Use this address directly. + Address dest = Address(m_options.m_load_addr); + + lldb::addr_t callAddr = dest.GetCallableLoadAddress(target); + if (callAddr == LLDB_INVALID_ADDRESS) { + result.AppendErrorWithFormat("Invalid destination address."); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (!reg_ctx->SetPC(callAddr)) { + result.AppendErrorWithFormat("Error changing PC value for thread %d.", + thread->GetIndexID()); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + // Pick either the absolute line, or work out a relative one. + int32_t line = (int32_t)m_options.m_line_num; + if (line == 0) + line = sym_ctx.line_entry.line + m_options.m_line_offset; + + // Try the current file, but override if asked. + FileSpec file = sym_ctx.line_entry.file; + if (m_options.m_filenames.GetSize() == 1) + file = m_options.m_filenames.GetFileSpecAtIndex(0); + + if (!file) { + result.AppendErrorWithFormat( + "No source file available for the current location."); + result.SetStatus(eReturnStatusFailed); + return false; + } + + std::string warnings; + Error err = thread->JumpToLine(file, line, m_options.m_force, &warnings); + + if (err.Fail()) { + result.SetError(err); + return false; + } + + if (!warnings.empty()) + result.AppendWarning(warnings.c_str()); } - CommandOptions m_options; + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } + + CommandOptions m_options; }; -OptionDefinition -CommandObjectThreadJump::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectThreadJump::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file to jump to."}, {LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specifies the line number to jump to."}, {LLDB_OPT_SET_2, true, "by", 'b', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "Jumps by a relative line offset from the current line."}, {LLDB_OPT_SET_3, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Jumps to a specific address."}, {LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "force", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allows the PC to leave the current function."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- @@ -1968,267 +1759,265 @@ CommandObjectThreadJump::CommandOptions::g_option_table[] = // CommandObjectThreadPlanList //------------------------------------------------------------------------- -class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads -{ +class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads { public: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - // Keep default values of all options in one place: OptionParsingStarting () - OptionParsingStarting(nullptr); - } + class CommandOptions : public Options { + public: + CommandOptions() : Options() { + // Keep default values of all options in one place: OptionParsingStarting + // () + OptionParsingStarting(nullptr); + } - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'i': - m_internal = true; - break; - case 'v': - m_verbose = true; - break; - default: - error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); - break; - } - return error; - } + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'i': + m_internal = true; + break; + case 'v': + m_verbose = true; + break; + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", + short_option); + break; + } + return error; + } - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_verbose = false; - m_internal = false; - } + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_verbose = false; + m_internal = false; + } - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } - // Options table: Required for subclasses of Options. + // Options table: Required for subclasses of Options. - static OptionDefinition g_option_table[]; + static OptionDefinition g_option_table[]; - // Instance variables to hold the values for command options. - bool m_verbose; - bool m_internal; - }; + // Instance variables to hold the values for command options. + bool m_verbose; + bool m_internal; + }; - CommandObjectThreadPlanList(CommandInterpreter &interpreter) - : CommandObjectIterateOverThreads( - interpreter, "thread plan list", - "Show thread plans for one or more threads. If no threads are specified, show the " - "current thread. Use the thread-index \"all\" to see all threads.", - nullptr, eCommandRequiresProcess | eCommandRequiresThread | eCommandTryTargetAPILock | - eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), - m_options() - { - } + CommandObjectThreadPlanList(CommandInterpreter &interpreter) + : CommandObjectIterateOverThreads( + interpreter, "thread plan list", + "Show thread plans for one or more threads. If no threads are " + "specified, show the " + "current thread. Use the thread-index \"all\" to see all threads.", + nullptr, + eCommandRequiresProcess | eCommandRequiresThread | + eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused), + m_options() {} - ~CommandObjectThreadPlanList() override = default; + ~CommandObjectThreadPlanList() override = default; - Options * - GetOptions () override - { - return &m_options; - } + Options *GetOptions() override { return &m_options; } 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; - } + 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; + } - Thread *thread = thread_sp.get(); + Thread *thread = thread_sp.get(); - Stream &strm = result.GetOutputStream(); - DescriptionLevel desc_level = eDescriptionLevelFull; - if (m_options.m_verbose) - desc_level = eDescriptionLevelVerbose; + 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); - return true; - } + thread->DumpThreadPlans(&strm, desc_level, m_options.m_internal, true); + return true; + } - CommandOptions m_options; + CommandOptions m_options; }; -OptionDefinition -CommandObjectThreadPlanList::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectThreadPlanList::CommandOptions::g_option_table[] = + { + // clang-format off {LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display more information about the thread plans"}, {LLDB_OPT_SET_1, false, "internal", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display internal as well as user thread plans"}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; -class CommandObjectThreadPlanDiscard : public CommandObjectParsed -{ +class CommandObjectThreadPlanDiscard : public CommandObjectParsed { public: - CommandObjectThreadPlanDiscard(CommandInterpreter &interpreter) - : CommandObjectParsed( - interpreter, "thread plan discard", - "Discards thread plans up to and including the specified index (see 'thread plan list'.) " - "Only user visible plans can be discarded.", - nullptr, eCommandRequiresProcess | eCommandRequiresThread | eCommandTryTargetAPILock | - eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) - { - CommandArgumentEntry arg; - CommandArgumentData plan_index_arg; - - // Define the first (and only) variant of this arg. - plan_index_arg.arg_type = eArgTypeUnsignedInteger; - plan_index_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (plan_index_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); + CommandObjectThreadPlanDiscard(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "thread plan discard", + "Discards thread plans up to and including the " + "specified index (see 'thread plan list'.) " + "Only user visible plans can be discarded.", + nullptr, + eCommandRequiresProcess | eCommandRequiresThread | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused) { + CommandArgumentEntry arg; + CommandArgumentData plan_index_arg; + + // Define the first (and only) variant of this arg. + plan_index_arg.arg_type = eArgTypeUnsignedInteger; + plan_index_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(plan_index_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectThreadPlanDiscard() override = default; + + bool DoExecute(Args &args, CommandReturnObject &result) override { + Thread *thread = m_exe_ctx.GetThreadPtr(); + if (args.GetArgumentCount() != 1) { + result.AppendErrorWithFormat("Too many arguments, expected one - the " + "thread plan index - but got %zu.", + args.GetArgumentCount()); + result.SetStatus(eReturnStatusFailed); + return false; } - ~CommandObjectThreadPlanDiscard() override = default; - - bool - DoExecute (Args& args, CommandReturnObject &result) override - { - Thread *thread = m_exe_ctx.GetThreadPtr(); - if (args.GetArgumentCount() != 1) - { - result.AppendErrorWithFormat("Too many arguments, expected one - the thread plan index - but got %zu.", - args.GetArgumentCount()); - result.SetStatus (eReturnStatusFailed); - return false; - } - - bool success; - uint32_t thread_plan_idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success); - if (!success) - { - result.AppendErrorWithFormat("Invalid thread index: \"%s\" - should be unsigned int.", - args.GetArgumentAtIndex(0)); - result.SetStatus (eReturnStatusFailed); - return false; - } + bool success; + uint32_t thread_plan_idx = + StringConvert::ToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success); + if (!success) { + result.AppendErrorWithFormat( + "Invalid thread index: \"%s\" - should be unsigned int.", + args.GetArgumentAtIndex(0)); + result.SetStatus(eReturnStatusFailed); + return false; + } - if (thread_plan_idx == 0) - { - result.AppendErrorWithFormat("You wouldn't really want me to discard the base thread plan."); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (thread_plan_idx == 0) { + result.AppendErrorWithFormat( + "You wouldn't really want me to discard the base thread plan."); + result.SetStatus(eReturnStatusFailed); + return false; + } - if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx)) - { - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; - } - else - { - result.AppendErrorWithFormat("Could not find User thread plan with index %s.", - args.GetArgumentAtIndex(0)); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx)) { + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return true; + } else { + result.AppendErrorWithFormat( + "Could not find User thread plan with index %s.", + args.GetArgumentAtIndex(0)); + result.SetStatus(eReturnStatusFailed); + return false; } + } }; //------------------------------------------------------------------------- // CommandObjectMultiwordThreadPlan //------------------------------------------------------------------------- -class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword -{ +class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword { public: - CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "plan", "Commands for managing thread plans that control execution.", - "thread plan <subcommand> [<subcommand objects]") - { - LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadPlanList (interpreter))); - LoadSubCommand ("discard", CommandObjectSP (new CommandObjectThreadPlanDiscard (interpreter))); - } + CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "plan", + "Commands for managing thread plans that control execution.", + "thread plan <subcommand> [<subcommand objects]") { + LoadSubCommand( + "list", CommandObjectSP(new CommandObjectThreadPlanList(interpreter))); + LoadSubCommand( + "discard", + CommandObjectSP(new CommandObjectThreadPlanDiscard(interpreter))); + } - ~CommandObjectMultiwordThreadPlan() override = default; + ~CommandObjectMultiwordThreadPlan() override = default; }; //------------------------------------------------------------------------- // CommandObjectMultiwordThread //------------------------------------------------------------------------- -CommandObjectMultiwordThread::CommandObjectMultiwordThread(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "thread", - "Commands for operating on one or more threads in the current process.", - "thread <subcommand> [<subcommand-options>]") -{ - LoadSubCommand ("backtrace", CommandObjectSP (new CommandObjectThreadBacktrace (interpreter))); - LoadSubCommand ("continue", CommandObjectSP (new CommandObjectThreadContinue (interpreter))); - LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadList (interpreter))); - LoadSubCommand ("return", CommandObjectSP (new CommandObjectThreadReturn (interpreter))); - LoadSubCommand ("jump", CommandObjectSP (new CommandObjectThreadJump (interpreter))); - LoadSubCommand ("select", CommandObjectSP (new CommandObjectThreadSelect (interpreter))); - LoadSubCommand ("until", CommandObjectSP (new CommandObjectThreadUntil (interpreter))); - LoadSubCommand ("info", CommandObjectSP (new CommandObjectThreadInfo (interpreter))); - LoadSubCommand("step-in", - CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( - interpreter, "thread step-in", - "Source level single step, stepping into calls. Defaults to current thread unless specified.", - nullptr, eStepTypeInto, eStepScopeSource))); - - LoadSubCommand("step-out", - CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( - interpreter, "thread step-out", "Finish executing the current stack frame and stop after " - "returning. Defaults to current thread unless specified.", - nullptr, eStepTypeOut, eStepScopeSource))); - - LoadSubCommand("step-over", - CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( - interpreter, "thread step-over", - "Source level single step, stepping over calls. Defaults to current thread unless specified.", - nullptr, eStepTypeOver, eStepScopeSource))); - - LoadSubCommand( - "step-inst", - CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( - interpreter, "thread step-inst", - "Instruction level single step, stepping into calls. Defaults to current thread unless specified.", - nullptr, eStepTypeTrace, eStepScopeInstruction))); - - LoadSubCommand( - "step-inst-over", - CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( - interpreter, "thread step-inst-over", - "Instruction level single step, stepping over calls. Defaults to current thread unless specified.", - nullptr, eStepTypeTraceOver, eStepScopeInstruction))); - - LoadSubCommand ("step-scripted", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( - interpreter, - "thread step-scripted", - "Step as instructed by the script class passed in the -C option.", - nullptr, - eStepTypeScripted, - eStepScopeSource))); - - LoadSubCommand ("plan", CommandObjectSP (new CommandObjectMultiwordThreadPlan(interpreter))); +CommandObjectMultiwordThread::CommandObjectMultiwordThread( + CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "thread", "Commands for operating on " + "one or more threads in " + "the current process.", + "thread <subcommand> [<subcommand-options>]") { + LoadSubCommand("backtrace", CommandObjectSP(new CommandObjectThreadBacktrace( + interpreter))); + LoadSubCommand("continue", + CommandObjectSP(new CommandObjectThreadContinue(interpreter))); + LoadSubCommand("list", + CommandObjectSP(new CommandObjectThreadList(interpreter))); + LoadSubCommand("return", + CommandObjectSP(new CommandObjectThreadReturn(interpreter))); + LoadSubCommand("jump", + CommandObjectSP(new CommandObjectThreadJump(interpreter))); + LoadSubCommand("select", + CommandObjectSP(new CommandObjectThreadSelect(interpreter))); + LoadSubCommand("until", + CommandObjectSP(new CommandObjectThreadUntil(interpreter))); + LoadSubCommand("info", + CommandObjectSP(new CommandObjectThreadInfo(interpreter))); + LoadSubCommand("step-in", + CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( + interpreter, "thread step-in", + "Source level single step, stepping into calls. Defaults " + "to current thread unless specified.", + nullptr, eStepTypeInto, eStepScopeSource))); + + LoadSubCommand("step-out", + CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( + interpreter, "thread step-out", + "Finish executing the current stack frame and stop after " + "returning. Defaults to current thread unless specified.", + nullptr, eStepTypeOut, eStepScopeSource))); + + LoadSubCommand("step-over", + CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( + interpreter, "thread step-over", + "Source level single step, stepping over calls. Defaults " + "to current thread unless specified.", + nullptr, eStepTypeOver, eStepScopeSource))); + + LoadSubCommand("step-inst", + CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( + interpreter, "thread step-inst", + "Instruction level single step, stepping into calls. " + "Defaults to current thread unless specified.", + nullptr, eStepTypeTrace, eStepScopeInstruction))); + + LoadSubCommand("step-inst-over", + CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( + interpreter, "thread step-inst-over", + "Instruction level single step, stepping over calls. " + "Defaults to current thread unless specified.", + nullptr, eStepTypeTraceOver, eStepScopeInstruction))); + + LoadSubCommand( + "step-scripted", + CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( + interpreter, "thread step-scripted", + "Step as instructed by the script class passed in the -C option.", + nullptr, eStepTypeScripted, eStepScopeSource))); + + LoadSubCommand("plan", CommandObjectSP(new CommandObjectMultiwordThreadPlan( + interpreter))); } CommandObjectMultiwordThread::~CommandObjectMultiwordThread() = default; diff --git a/lldb/source/Commands/CommandObjectThread.h b/lldb/source/Commands/CommandObjectThread.h index 90f8236..589031e 100644 --- a/lldb/source/Commands/CommandObjectThread.h +++ b/lldb/source/Commands/CommandObjectThread.h @@ -18,13 +18,11 @@ namespace lldb_private { -class CommandObjectMultiwordThread : public CommandObjectMultiword -{ +class CommandObjectMultiwordThread : public CommandObjectMultiword { public: + CommandObjectMultiwordThread(CommandInterpreter &interpreter); - CommandObjectMultiwordThread (CommandInterpreter &interpreter); - - ~CommandObjectMultiwordThread() override; + ~CommandObjectMultiwordThread() override; }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectType.cpp b/lldb/source/Commands/CommandObjectType.cpp index 0ddd65b..60ff00a 100644 --- a/lldb/source/Commands/CommandObjectType.cpp +++ b/lldb/source/Commands/CommandObjectType.cpp @@ -29,11 +29,11 @@ #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandObject.h" #include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/OptionGroupFormat.h" #include "lldb/Interpreter/OptionValueBoolean.h" #include "lldb/Interpreter/OptionValueLanguage.h" #include "lldb/Interpreter/OptionValueString.h" +#include "lldb/Interpreter/Options.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/Language.h" #include "lldb/Target/Process.h" @@ -45,697 +45,558 @@ using namespace lldb; using namespace lldb_private; -class ScriptAddOptions -{ +class ScriptAddOptions { public: - TypeSummaryImpl::Flags m_flags; - StringList m_target_types; - bool m_regex; - ConstString m_name; - std::string m_category; - - ScriptAddOptions(const TypeSummaryImpl::Flags& flags, - bool regx, - const ConstString& name, - std::string catg) : - m_flags(flags), - m_regex(regx), - m_name(name), - m_category(catg) - { - } - - typedef std::shared_ptr<ScriptAddOptions> SharedPointer; + TypeSummaryImpl::Flags m_flags; + StringList m_target_types; + bool m_regex; + ConstString m_name; + std::string m_category; + + ScriptAddOptions(const TypeSummaryImpl::Flags &flags, bool regx, + const ConstString &name, std::string catg) + : m_flags(flags), m_regex(regx), m_name(name), m_category(catg) {} + + typedef std::shared_ptr<ScriptAddOptions> SharedPointer; }; -class SynthAddOptions -{ +class SynthAddOptions { public: - bool m_skip_pointers; - bool m_skip_references; - bool m_cascade; - bool m_regex; - StringList m_target_types; - std::string m_category; - - SynthAddOptions(bool sptr, - bool sref, - bool casc, - bool regx, - std::string catg) : - m_skip_pointers(sptr), - m_skip_references(sref), - m_cascade(casc), - m_regex(regx), - m_target_types(), - m_category(catg) - { - } - - typedef std::shared_ptr<SynthAddOptions> SharedPointer; + bool m_skip_pointers; + bool m_skip_references; + bool m_cascade; + bool m_regex; + StringList m_target_types; + std::string m_category; + + SynthAddOptions(bool sptr, bool sref, bool casc, bool regx, std::string catg) + : m_skip_pointers(sptr), m_skip_references(sref), m_cascade(casc), + m_regex(regx), m_target_types(), m_category(catg) {} + + typedef std::shared_ptr<SynthAddOptions> SharedPointer; }; -static bool -WarnOnPotentialUnquotedUnsignedType (Args& command, CommandReturnObject &result) -{ - for (unsigned idx = 0; idx < command.GetArgumentCount(); idx++) - { - const char* arg = command.GetArgumentAtIndex(idx); - if (idx+1 < command.GetArgumentCount()) - { - if (arg && 0 == strcmp(arg,"unsigned")) - { - const char* next = command.GetArgumentAtIndex(idx+1); - if (next && - (0 == strcmp(next, "int") || - 0 == strcmp(next, "short") || - 0 == strcmp(next, "char") || - 0 == strcmp(next, "long"))) - { - result.AppendWarningWithFormat("%s %s being treated as two types. if you meant the combined type name use quotes, as in \"%s %s\"\n", - arg,next,arg,next); - return true; - } - } - } - } - return false; +static bool WarnOnPotentialUnquotedUnsignedType(Args &command, + CommandReturnObject &result) { + for (unsigned idx = 0; idx < command.GetArgumentCount(); idx++) { + const char *arg = command.GetArgumentAtIndex(idx); + if (idx + 1 < command.GetArgumentCount()) { + if (arg && 0 == strcmp(arg, "unsigned")) { + const char *next = command.GetArgumentAtIndex(idx + 1); + if (next && (0 == strcmp(next, "int") || 0 == strcmp(next, "short") || + 0 == strcmp(next, "char") || 0 == strcmp(next, "long"))) { + result.AppendWarningWithFormat("%s %s being treated as two types. if " + "you meant the combined type name use " + "quotes, as in \"%s %s\"\n", + arg, next, arg, next); + return true; + } + } + } + } + return false; } -class CommandObjectTypeSummaryAdd : - public CommandObjectParsed, - public IOHandlerDelegateMultiline -{ +class CommandObjectTypeSummaryAdd : public CommandObjectParsed, + public IOHandlerDelegateMultiline { private: - class CommandOptions : public Options - { - public: - CommandOptions (CommandInterpreter &interpreter) : - Options() - { - } + class CommandOptions : public Options { + public: + CommandOptions(CommandInterpreter &interpreter) : Options() {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override; + + void OptionParsingStarting(ExecutionContext *execution_context) override; + + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + TypeSummaryImpl::Flags m_flags; + bool m_regex; + std::string m_format_string; + ConstString m_name; + std::string m_python_script; + std::string m_python_function; + bool m_is_add_script; + std::string m_category; + }; + + CommandOptions m_options; + + Options *GetOptions() override { return &m_options; } + + bool Execute_ScriptSummary(Args &command, CommandReturnObject &result); + + bool Execute_StringSummary(Args &command, CommandReturnObject &result); - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override; - - void - OptionParsingStarting(ExecutionContext *execution_context) override; - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - TypeSummaryImpl::Flags m_flags; - bool m_regex; - std::string m_format_string; - ConstString m_name; - std::string m_python_script; - std::string m_python_function; - bool m_is_add_script; - std::string m_category; - }; - - CommandOptions m_options; - - Options * - GetOptions () override - { - return &m_options; - } - - bool - Execute_ScriptSummary (Args& command, CommandReturnObject &result); - - bool - Execute_StringSummary (Args& command, CommandReturnObject &result); - public: - enum SummaryFormatType - { - eRegularSummary, - eRegexSummary, - eNamedSummary - }; - - CommandObjectTypeSummaryAdd (CommandInterpreter &interpreter); + enum SummaryFormatType { eRegularSummary, eRegexSummary, eNamedSummary }; - ~CommandObjectTypeSummaryAdd() override = default; + CommandObjectTypeSummaryAdd(CommandInterpreter &interpreter); - void - IOHandlerActivated (IOHandler &io_handler) override - { - static const char *g_summary_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" + ~CommandObjectTypeSummaryAdd() override = default; + + void IOHandlerActivated(IOHandler &io_handler) override { + static const char *g_summary_addreader_instructions = + "Enter your Python command(s). Type 'DONE' to end.\n" "def function (valobj,internal_dict):\n" - " \"\"\"valobj: an SBValue which you want to provide a summary for\n" + " \"\"\"valobj: an SBValue which you want to provide a summary " + "for\n" " internal_dict: an LLDB support object not to be used\"\"\"\n"; - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); - if (output_sp) - { - output_sp->PutCString(g_summary_addreader_instructions); - output_sp->Flush(); - } + StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + if (output_sp) { + output_sp->PutCString(g_summary_addreader_instructions); + output_sp->Flush(); } + } + + void IOHandlerInputComplete(IOHandler &io_handler, + std::string &data) override { + StreamFileSP error_sp = io_handler.GetErrorStreamFile(); - void - IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override - { - StreamFileSP error_sp = io_handler.GetErrorStreamFile(); - #ifndef LLDB_DISABLE_PYTHON - ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); - if (interpreter) - { - StringList lines; - lines.SplitIntoLines(data); - if (lines.GetSize() > 0) - { - ScriptAddOptions *options_ptr = ((ScriptAddOptions*)io_handler.GetUserData()); - if (options_ptr) - { - ScriptAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope - - ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); - if (interpreter) - { - std::string funct_name_str; - if (interpreter->GenerateTypeScriptFunction (lines, funct_name_str)) - { - if (funct_name_str.empty()) - { - error_sp->Printf ("unable to obtain a valid function name from the script interpreter.\n"); - error_sp->Flush(); - } - else - { - // now I have a valid function name, let's add this as script for every type in the list - - TypeSummaryImplSP script_format; - script_format.reset(new ScriptSummaryFormat(options->m_flags, - funct_name_str.c_str(), - lines.CopyList(" ").c_str())); - - Error error; - - for (size_t i = 0; i < options->m_target_types.GetSize(); i++) - { - const char *type_name = options->m_target_types.GetStringAtIndex(i); - CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name), - script_format, - (options->m_regex ? CommandObjectTypeSummaryAdd::eRegexSummary : CommandObjectTypeSummaryAdd::eRegularSummary), - options->m_category, - &error); - if (error.Fail()) - { - error_sp->Printf ("error: %s", error.AsCString()); - error_sp->Flush(); - } - } - - if (options->m_name) - { - CommandObjectTypeSummaryAdd::AddSummary (options->m_name, - script_format, - CommandObjectTypeSummaryAdd::eNamedSummary, - options->m_category, - &error); - if (error.Fail()) - { - CommandObjectTypeSummaryAdd::AddSummary (options->m_name, - script_format, - CommandObjectTypeSummaryAdd::eNamedSummary, - options->m_category, - &error); - if (error.Fail()) - { - error_sp->Printf ("error: %s", error.AsCString()); - error_sp->Flush(); - } - } - else - { - error_sp->Printf ("error: %s", error.AsCString()); - error_sp->Flush(); - } - } - else - { - if (error.AsCString()) - { - error_sp->Printf ("error: %s", error.AsCString()); - error_sp->Flush(); - } - } - } - } - else - { - error_sp->Printf ("error: unable to generate a function.\n"); - error_sp->Flush(); - } - } - else - { - error_sp->Printf ("error: no script interpreter.\n"); - error_sp->Flush(); - } + ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); + if (interpreter) { + StringList lines; + lines.SplitIntoLines(data); + if (lines.GetSize() > 0) { + ScriptAddOptions *options_ptr = + ((ScriptAddOptions *)io_handler.GetUserData()); + if (options_ptr) { + ScriptAddOptions::SharedPointer options( + options_ptr); // this will ensure that we get rid of the pointer + // when going out of scope + + ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); + if (interpreter) { + std::string funct_name_str; + if (interpreter->GenerateTypeScriptFunction(lines, + funct_name_str)) { + if (funct_name_str.empty()) { + error_sp->Printf("unable to obtain a valid function name from " + "the script interpreter.\n"); + error_sp->Flush(); + } else { + // now I have a valid function name, let's add this as script + // for every type in the list + + TypeSummaryImplSP script_format; + script_format.reset(new ScriptSummaryFormat( + options->m_flags, funct_name_str.c_str(), + lines.CopyList(" ").c_str())); + + Error error; + + for (size_t i = 0; i < options->m_target_types.GetSize(); i++) { + const char *type_name = + options->m_target_types.GetStringAtIndex(i); + CommandObjectTypeSummaryAdd::AddSummary( + ConstString(type_name), script_format, + (options->m_regex + ? CommandObjectTypeSummaryAdd::eRegexSummary + : CommandObjectTypeSummaryAdd::eRegularSummary), + options->m_category, &error); + if (error.Fail()) { + error_sp->Printf("error: %s", error.AsCString()); + error_sp->Flush(); + } } - else - { - error_sp->Printf ("error: internal synchronization information missing or invalid.\n"); + + if (options->m_name) { + CommandObjectTypeSummaryAdd::AddSummary( + options->m_name, script_format, + CommandObjectTypeSummaryAdd::eNamedSummary, + options->m_category, &error); + if (error.Fail()) { + CommandObjectTypeSummaryAdd::AddSummary( + options->m_name, script_format, + CommandObjectTypeSummaryAdd::eNamedSummary, + options->m_category, &error); + if (error.Fail()) { + error_sp->Printf("error: %s", error.AsCString()); + error_sp->Flush(); + } + } else { + error_sp->Printf("error: %s", error.AsCString()); + error_sp->Flush(); + } + } else { + if (error.AsCString()) { + error_sp->Printf("error: %s", error.AsCString()); error_sp->Flush(); + } } + } + } else { + error_sp->Printf("error: unable to generate a function.\n"); + error_sp->Flush(); } - else - { - error_sp->Printf ("error: empty function, didn't add python command.\n"); - error_sp->Flush(); - } - } - else - { - error_sp->Printf ("error: script interpreter missing, didn't add python command.\n"); + } else { + error_sp->Printf("error: no script interpreter.\n"); error_sp->Flush(); - } -#endif // LLDB_DISABLE_PYTHON - io_handler.SetIsDone(true); + } + } else { + error_sp->Printf("error: internal synchronization information " + "missing or invalid.\n"); + error_sp->Flush(); + } + } else { + error_sp->Printf("error: empty function, didn't add python command.\n"); + error_sp->Flush(); + } + } else { + error_sp->Printf( + "error: script interpreter missing, didn't add python command.\n"); + error_sp->Flush(); } - - static bool - AddSummary(ConstString type_name, - lldb::TypeSummaryImplSP entry, - SummaryFormatType type, - std::string category, - Error* error = nullptr); +#endif // LLDB_DISABLE_PYTHON + io_handler.SetIsDone(true); + } + + static bool AddSummary(ConstString type_name, lldb::TypeSummaryImplSP entry, + SummaryFormatType type, std::string category, + Error *error = nullptr); protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override; + bool DoExecute(Args &command, CommandReturnObject &result) override; }; -static const char *g_synth_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" -"You must define a Python class with these methods:\n" -" def __init__(self, valobj, dict):\n" -" def num_children(self):\n" -" def get_child_at_index(self, index):\n" -" def get_child_index(self, name):\n" -" def update(self):\n" -" '''Optional'''\n" -"class synthProvider:\n"; - -class CommandObjectTypeSynthAdd : - public CommandObjectParsed, - public IOHandlerDelegateMultiline -{ +static const char *g_synth_addreader_instructions = + "Enter your Python command(s). Type 'DONE' to end.\n" + "You must define a Python class with these methods:\n" + " def __init__(self, valobj, dict):\n" + " def num_children(self):\n" + " def get_child_at_index(self, index):\n" + " def get_child_index(self, name):\n" + " def update(self):\n" + " '''Optional'''\n" + "class synthProvider:\n"; + +class CommandObjectTypeSynthAdd : public CommandObjectParsed, + public IOHandlerDelegateMultiline { private: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - } + class CommandOptions : public Options { + public: + CommandOptions() : Options() {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + bool success; + + switch (short_option) { + case 'C': + m_cascade = Args::StringToBoolean(option_arg, true, &success); + if (!success) + error.SetErrorStringWithFormat("invalid value for cascade: %s", + option_arg); + break; + case 'P': + handwrite_python = true; + break; + case 'l': + m_class_name = std::string(option_arg); + is_class_based = true; + break; + case 'p': + m_skip_pointers = true; + break; + case 'r': + m_skip_references = true; + break; + case 'w': + m_category = std::string(option_arg); + break; + case 'x': + m_regex = true; + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; + } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_cascade = true; + m_class_name = ""; + m_skip_pointers = false; + m_skip_references = false; + m_category = "default"; + is_class_based = false; + handwrite_python = false; + m_regex = false; + } + + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + bool m_cascade; + bool m_skip_references; + bool m_skip_pointers; + std::string m_class_name; + bool m_input_python; + std::string m_category; + bool is_class_based; + bool handwrite_python; + bool m_regex; + }; + + CommandOptions m_options; + + Options *GetOptions() override { return &m_options; } + + bool Execute_HandwritePython(Args &command, CommandReturnObject &result); + + bool Execute_PythonClass(Args &command, CommandReturnObject &result); - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - bool success; - - switch (short_option) - { - case 'C': - m_cascade = Args::StringToBoolean(option_arg, true, &success); - if (!success) - error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg); - break; - case 'P': - handwrite_python = true; - break; - case 'l': - m_class_name = std::string(option_arg); - is_class_based = true; - break; - case 'p': - m_skip_pointers = true; - break; - case 'r': - m_skip_references = true; - break; - case 'w': - m_category = std::string(option_arg); - break; - case 'x': - m_regex = true; - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_cascade = true; - m_class_name = ""; - m_skip_pointers = false; - m_skip_references = false; - m_category = "default"; - is_class_based = false; - handwrite_python = false; - m_regex = false; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - bool m_cascade; - bool m_skip_references; - bool m_skip_pointers; - std::string m_class_name; - bool m_input_python; - std::string m_category; - bool is_class_based; - bool handwrite_python; - bool m_regex; - }; - - CommandOptions m_options; - - Options * - GetOptions () override - { - return &m_options; - } - - bool - Execute_HandwritePython (Args& command, CommandReturnObject &result); - - bool - Execute_PythonClass (Args& command, CommandReturnObject &result); - protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - WarnOnPotentialUnquotedUnsignedType(command, result); - - if (m_options.handwrite_python) - return Execute_HandwritePython(command, result); - else if (m_options.is_class_based) - return Execute_PythonClass(command, result); - else - { - result.AppendError("must either provide a children list, a Python class name, or use -P and type a Python class line-by-line"); - result.SetStatus(eReturnStatusFailed); - return false; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + WarnOnPotentialUnquotedUnsignedType(command, result); + + if (m_options.handwrite_python) + return Execute_HandwritePython(command, result); + else if (m_options.is_class_based) + return Execute_PythonClass(command, result); + else { + result.AppendError("must either provide a children list, a Python class " + "name, or use -P and type a Python class " + "line-by-line"); + result.SetStatus(eReturnStatusFailed); + return false; } - - void - IOHandlerActivated (IOHandler &io_handler) override - { - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); - if (output_sp) - { - output_sp->PutCString(g_synth_addreader_instructions); - output_sp->Flush(); - } + } + + void IOHandlerActivated(IOHandler &io_handler) override { + StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + if (output_sp) { + output_sp->PutCString(g_synth_addreader_instructions); + output_sp->Flush(); } + } + + void IOHandlerInputComplete(IOHandler &io_handler, + std::string &data) override { + StreamFileSP error_sp = io_handler.GetErrorStreamFile(); - void - IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override - { - StreamFileSP error_sp = io_handler.GetErrorStreamFile(); - #ifndef LLDB_DISABLE_PYTHON - ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); - if (interpreter) - { - StringList lines; - lines.SplitIntoLines(data); - if (lines.GetSize() > 0) - { - SynthAddOptions *options_ptr = ((SynthAddOptions*)io_handler.GetUserData()); - if (options_ptr) - { - SynthAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope - - ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); - if (interpreter) - { - std::string class_name_str; - if (interpreter->GenerateTypeSynthClass (lines, class_name_str)) - { - if (class_name_str.empty()) - { - error_sp->Printf ("error: unable to obtain a proper name for the class.\n"); - error_sp->Flush(); - } - else - { - // everything should be fine now, let's add the synth provider class - - SyntheticChildrenSP synth_provider; - synth_provider.reset(new ScriptedSyntheticChildren(SyntheticChildren::Flags().SetCascades(options->m_cascade). - SetSkipPointers(options->m_skip_pointers). - SetSkipReferences(options->m_skip_references), - class_name_str.c_str())); - - - lldb::TypeCategoryImplSP category; - DataVisualization::Categories::GetCategory(ConstString(options->m_category.c_str()), category); - - Error error; - - for (size_t i = 0; i < options->m_target_types.GetSize(); i++) - { - const char *type_name = options->m_target_types.GetStringAtIndex(i); - ConstString const_type_name(type_name); - if (const_type_name) - { - if (!CommandObjectTypeSynthAdd::AddSynth(const_type_name, - synth_provider, - options->m_regex ? CommandObjectTypeSynthAdd::eRegexSynth : CommandObjectTypeSynthAdd::eRegularSynth, - options->m_category, - &error)) - { - error_sp->Printf("error: %s\n", error.AsCString()); - error_sp->Flush(); - break; - } - } - else - { - error_sp->Printf ("error: invalid type name.\n"); - error_sp->Flush(); - break; - } - } - } - } - else - { - error_sp->Printf ("error: unable to generate a class.\n"); - error_sp->Flush(); - } - } - else - { - error_sp->Printf ("error: no script interpreter.\n"); - error_sp->Flush(); + ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); + if (interpreter) { + StringList lines; + lines.SplitIntoLines(data); + if (lines.GetSize() > 0) { + SynthAddOptions *options_ptr = + ((SynthAddOptions *)io_handler.GetUserData()); + if (options_ptr) { + SynthAddOptions::SharedPointer options( + options_ptr); // this will ensure that we get rid of the pointer + // when going out of scope + + ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); + if (interpreter) { + std::string class_name_str; + if (interpreter->GenerateTypeSynthClass(lines, class_name_str)) { + if (class_name_str.empty()) { + error_sp->Printf( + "error: unable to obtain a proper name for the class.\n"); + error_sp->Flush(); + } else { + // everything should be fine now, let's add the synth provider + // class + + SyntheticChildrenSP synth_provider; + synth_provider.reset(new ScriptedSyntheticChildren( + SyntheticChildren::Flags() + .SetCascades(options->m_cascade) + .SetSkipPointers(options->m_skip_pointers) + .SetSkipReferences(options->m_skip_references), + class_name_str.c_str())); + + lldb::TypeCategoryImplSP category; + DataVisualization::Categories::GetCategory( + ConstString(options->m_category.c_str()), category); + + Error error; + + for (size_t i = 0; i < options->m_target_types.GetSize(); i++) { + const char *type_name = + options->m_target_types.GetStringAtIndex(i); + ConstString const_type_name(type_name); + if (const_type_name) { + if (!CommandObjectTypeSynthAdd::AddSynth( + const_type_name, synth_provider, + options->m_regex + ? CommandObjectTypeSynthAdd::eRegexSynth + : CommandObjectTypeSynthAdd::eRegularSynth, + options->m_category, &error)) { + error_sp->Printf("error: %s\n", error.AsCString()); + error_sp->Flush(); + break; } - } - else - { - error_sp->Printf ("error: internal synchronization data missing.\n"); + } else { + error_sp->Printf("error: invalid type name.\n"); error_sp->Flush(); + break; + } } + } + } else { + error_sp->Printf("error: unable to generate a class.\n"); + error_sp->Flush(); } - else - { - error_sp->Printf ("error: empty function, didn't add python command.\n"); - error_sp->Flush(); - } - } - else - { - error_sp->Printf ("error: script interpreter missing, didn't add python command.\n"); + } else { + error_sp->Printf("error: no script interpreter.\n"); error_sp->Flush(); + } + } else { + error_sp->Printf("error: internal synchronization data missing.\n"); + error_sp->Flush(); } - -#endif // LLDB_DISABLE_PYTHON - io_handler.SetIsDone(true); + } else { + error_sp->Printf("error: empty function, didn't add python command.\n"); + error_sp->Flush(); + } + } else { + error_sp->Printf( + "error: script interpreter missing, didn't add python command.\n"); + error_sp->Flush(); } +#endif // LLDB_DISABLE_PYTHON + io_handler.SetIsDone(true); + } + public: - enum SynthFormatType - { - eRegularSynth, - eRegexSynth - }; - - CommandObjectTypeSynthAdd (CommandInterpreter &interpreter); + enum SynthFormatType { eRegularSynth, eRegexSynth }; + + CommandObjectTypeSynthAdd(CommandInterpreter &interpreter); - ~CommandObjectTypeSynthAdd() override = default; + ~CommandObjectTypeSynthAdd() override = default; - static bool - AddSynth(ConstString type_name, - lldb::SyntheticChildrenSP entry, - SynthFormatType type, - std::string category_name, - Error* error); + static bool AddSynth(ConstString type_name, lldb::SyntheticChildrenSP entry, + SynthFormatType type, std::string category_name, + Error *error); }; //------------------------------------------------------------------------- // CommandObjectTypeFormatAdd //------------------------------------------------------------------------- -class CommandObjectTypeFormatAdd : public CommandObjectParsed -{ +class CommandObjectTypeFormatAdd : public CommandObjectParsed { private: - class CommandOptions : public OptionGroup - { - public: - CommandOptions () : - OptionGroup() - { - } + class CommandOptions : public OptionGroup { + public: + CommandOptions() : OptionGroup() {} + + ~CommandOptions() override = default; + + uint32_t GetNumDefinitions() override; + + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_cascade = true; + m_skip_pointers = false; + m_skip_references = false; + m_regex = false; + m_category.assign("default"); + m_custom_type_name.clear(); + } + + Error SetOptionValue(uint32_t option_idx, const char *option_value, + ExecutionContext *execution_context) override { + Error error; + const int short_option = g_option_table[option_idx].short_option; + bool success; + + switch (short_option) { + case 'C': + m_cascade = Args::StringToBoolean(option_value, true, &success); + if (!success) + error.SetErrorStringWithFormat("invalid value for cascade: %s", + option_value); + break; + case 'p': + m_skip_pointers = true; + break; + case 'w': + m_category.assign(option_value); + break; + case 'r': + m_skip_references = true; + break; + case 'x': + m_regex = true; + break; + case 't': + m_custom_type_name.assign(option_value); + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; + } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + bool m_cascade; + bool m_skip_references; + bool m_skip_pointers; + bool m_regex; + std::string m_category; + std::string m_custom_type_name; + }; - ~CommandOptions() override = default; + OptionGroupOptions m_option_group; + OptionGroupFormat m_format_options; + CommandOptions m_command_options; - uint32_t - GetNumDefinitions () override; - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_cascade = true; - m_skip_pointers = false; - m_skip_references = false; - m_regex = false; - m_category.assign("default"); - m_custom_type_name.clear(); - } + Options *GetOptions() override { return &m_option_group; } - Error - SetOptionValue(uint32_t option_idx, - const char *option_value, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = g_option_table[option_idx].short_option; - bool success; - - switch (short_option) - { - case 'C': - m_cascade = Args::StringToBoolean(option_value, true, &success); - if (!success) - error.SetErrorStringWithFormat("invalid value for cascade: %s", option_value); - break; - case 'p': - m_skip_pointers = true; - break; - case 'w': - m_category.assign(option_value); - break; - case 'r': - m_skip_references = true; - break; - case 'x': - m_regex = true; - break; - case 't': - m_custom_type_name.assign(option_value); - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - bool m_cascade; - bool m_skip_references; - bool m_skip_pointers; - bool m_regex; - std::string m_category; - std::string m_custom_type_name; - }; - - OptionGroupOptions m_option_group; - OptionGroupFormat m_format_options; - CommandOptions m_command_options; - - Options * - GetOptions () override - { - return &m_option_group; - } - public: - CommandObjectTypeFormatAdd (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "type format add", - "Add a new formatting style for a type.", - nullptr), - m_option_group(), - m_format_options(eFormatInvalid), - m_command_options() - { - CommandArgumentEntry type_arg; - CommandArgumentData type_style_arg; - - type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatPlus; - - type_arg.push_back (type_style_arg); - - m_arguments.push_back (type_arg); - - SetHelpLong( -R"( + CommandObjectTypeFormatAdd(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "type format add", + "Add a new formatting style for a type.", nullptr), + m_option_group(), m_format_options(eFormatInvalid), + m_command_options() { + CommandArgumentEntry type_arg; + CommandArgumentData type_style_arg; + + type_style_arg.arg_type = eArgTypeName; + type_style_arg.arg_repetition = eArgRepeatPlus; + + type_arg.push_back(type_style_arg); + + m_arguments.push_back(type_arg); + + SetHelpLong( + R"( The following examples of 'type format add' refer to this code snippet for context: typedef int Aint; @@ -754,8 +615,10 @@ Adding default formatting: (lldb) type format add -f hex AInt (lldb) frame variable iy -)" " Produces hexadecimal display of iy, because no formatter is available for Bint and \ -the one for Aint is used instead." R"( +)" + " Produces hexadecimal display of iy, because no formatter is available for Bint and \ +the one for Aint is used instead." + R"( To prevent this use the cascade option '-C no' to prevent evaluation of typedef chains: @@ -766,99 +629,97 @@ Similar reasoning applies to this: (lldb) type format add -f hex -C no float -p -)" " All float values and float references are now formatted as hexadecimal, but not \ -pointers to floats. Nor will it change the default display for Afloat and Bfloat objects." - ); - - // Add the "--format" to all options groups - m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1); - m_option_group.Append (&m_command_options); - m_option_group.Finalize(); - } +)" + " All float values and float references are now formatted as hexadecimal, but not \ +pointers to floats. Nor will it change the default display for Afloat and Bfloat objects."); + + // Add the "--format" to all options groups + m_option_group.Append(&m_format_options, + OptionGroupFormat::OPTION_GROUP_FORMAT, + LLDB_OPT_SET_1); + m_option_group.Append(&m_command_options); + m_option_group.Finalize(); + } - ~CommandObjectTypeFormatAdd() override = default; + ~CommandObjectTypeFormatAdd() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - const size_t argc = command.GetArgumentCount(); - - if (argc < 1) - { - result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - const Format format = m_format_options.GetFormat(); - if (format == eFormatInvalid && m_command_options.m_custom_type_name.empty()) - { - result.AppendErrorWithFormat ("%s needs a valid format.\n", m_cmd_name.c_str()); + bool DoExecute(Args &command, CommandReturnObject &result) override { + const size_t argc = command.GetArgumentCount(); + + if (argc < 1) { + result.AppendErrorWithFormat("%s takes one or more args.\n", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + const Format format = m_format_options.GetFormat(); + if (format == eFormatInvalid && + m_command_options.m_custom_type_name.empty()) { + result.AppendErrorWithFormat("%s needs a valid format.\n", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + TypeFormatImplSP entry; + + if (m_command_options.m_custom_type_name.empty()) + entry.reset(new TypeFormatImpl_Format( + format, TypeFormatImpl::Flags() + .SetCascades(m_command_options.m_cascade) + .SetSkipPointers(m_command_options.m_skip_pointers) + .SetSkipReferences(m_command_options.m_skip_references))); + else + entry.reset(new TypeFormatImpl_EnumType( + ConstString(m_command_options.m_custom_type_name.c_str()), + TypeFormatImpl::Flags() + .SetCascades(m_command_options.m_cascade) + .SetSkipPointers(m_command_options.m_skip_pointers) + .SetSkipReferences(m_command_options.m_skip_references))); + + // now I have a valid format, let's add it to every type + + TypeCategoryImplSP category_sp; + DataVisualization::Categories::GetCategory( + ConstString(m_command_options.m_category), category_sp); + if (!category_sp) + return false; + + WarnOnPotentialUnquotedUnsignedType(command, result); + + for (size_t i = 0; i < argc; i++) { + const char *typeA = command.GetArgumentAtIndex(i); + ConstString typeCS(typeA); + if (typeCS) { + if (m_command_options.m_regex) { + RegularExpressionSP typeRX(new RegularExpression()); + if (!typeRX->Compile(typeCS.GetCString())) { + result.AppendError( + "regex format error (maybe this is not really a regex?)"); result.SetStatus(eReturnStatusFailed); return false; - } - - TypeFormatImplSP entry; - - if (m_command_options.m_custom_type_name.empty()) - entry.reset(new TypeFormatImpl_Format(format, - TypeFormatImpl::Flags().SetCascades(m_command_options.m_cascade). - SetSkipPointers(m_command_options.m_skip_pointers). - SetSkipReferences(m_command_options.m_skip_references))); - else - entry.reset(new TypeFormatImpl_EnumType(ConstString(m_command_options.m_custom_type_name.c_str()), - TypeFormatImpl::Flags().SetCascades(m_command_options.m_cascade). - SetSkipPointers(m_command_options.m_skip_pointers). - SetSkipReferences(m_command_options.m_skip_references))); - - // now I have a valid format, let's add it to every type - - TypeCategoryImplSP category_sp; - DataVisualization::Categories::GetCategory(ConstString(m_command_options.m_category), category_sp); - if (!category_sp) - return false; - - WarnOnPotentialUnquotedUnsignedType(command, result); - - for (size_t i = 0; i < argc; i++) - { - const char* typeA = command.GetArgumentAtIndex(i); - ConstString typeCS(typeA); - if (typeCS) - { - if (m_command_options.m_regex) - { - RegularExpressionSP typeRX(new RegularExpression()); - if (!typeRX->Compile(typeCS.GetCString())) - { - result.AppendError("regex format error (maybe this is not really a regex?)"); - result.SetStatus(eReturnStatusFailed); - return false; - } - category_sp->GetRegexTypeSummariesContainer()->Delete(typeCS); - category_sp->GetRegexTypeFormatsContainer()->Add(typeRX, entry); - } - else - category_sp->GetTypeFormatsContainer()->Add(typeCS, entry); - } - else - { - result.AppendError("empty typenames not allowed"); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); + } + category_sp->GetRegexTypeSummariesContainer()->Delete(typeCS); + category_sp->GetRegexTypeFormatsContainer()->Add(typeRX, entry); + } else + category_sp->GetTypeFormatsContainer()->Add(typeCS, entry); + } else { + result.AppendError("empty typenames not allowed"); + result.SetStatus(eReturnStatusFailed); + return false; + } } + + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return result.Succeeded(); + } }; -OptionDefinition -CommandObjectTypeFormatAdd::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectTypeFormatAdd::CommandOptions::g_option_table[] = + { + // clang-format off {LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one."}, {LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, {LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, @@ -866,615 +727,506 @@ CommandObjectTypeFormatAdd::CommandOptions::g_option_table[] = {LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions."}, {LLDB_OPT_SET_2, false, "type", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Format variables as if they were of this type."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; -uint32_t -CommandObjectTypeFormatAdd::CommandOptions::GetNumDefinitions () -{ - return sizeof(g_option_table) / sizeof (OptionDefinition); +uint32_t CommandObjectTypeFormatAdd::CommandOptions::GetNumDefinitions() { + return sizeof(g_option_table) / sizeof(OptionDefinition); } -class CommandObjectTypeFormatterDelete : public CommandObjectParsed -{ +class CommandObjectTypeFormatterDelete : public CommandObjectParsed { protected: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - } + class CommandOptions : public Options { + public: + CommandOptions() : Options() {} - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'a': - m_delete_all = true; - break; - case 'w': - m_category = std::string(option_arg); - break; - case 'l': - m_language = Language::GetLanguageTypeFromString(option_arg); - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_delete_all = false; - m_category = "default"; - m_language = lldb::eLanguageTypeUnknown; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - bool m_delete_all; - std::string m_category; - lldb::LanguageType m_language; - }; - - CommandOptions m_options; - uint32_t m_formatter_kind_mask; - - Options * - GetOptions () override - { - return &m_options; + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'a': + m_delete_all = true; + break; + case 'w': + m_category = std::string(option_arg); + break; + case 'l': + m_language = Language::GetLanguageTypeFromString(option_arg); + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; } - -public: - CommandObjectTypeFormatterDelete (CommandInterpreter &interpreter, - uint32_t formatter_kind_mask, - const char* name, - const char* help) : - CommandObjectParsed(interpreter, - name, - help, - nullptr), - m_options(), - m_formatter_kind_mask(formatter_kind_mask) - { - CommandArgumentEntry type_arg; - CommandArgumentData type_style_arg; - - type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatPlain; - - type_arg.push_back (type_style_arg); - - m_arguments.push_back (type_arg); + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_delete_all = false; + m_category = "default"; + m_language = lldb::eLanguageTypeUnknown; } - ~CommandObjectTypeFormatterDelete() override = default; + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + bool m_delete_all; + std::string m_category; + lldb::LanguageType m_language; + }; + + CommandOptions m_options; + uint32_t m_formatter_kind_mask; + + Options *GetOptions() override { return &m_options; } + +public: + CommandObjectTypeFormatterDelete(CommandInterpreter &interpreter, + uint32_t formatter_kind_mask, + const char *name, const char *help) + : CommandObjectParsed(interpreter, name, help, nullptr), m_options(), + m_formatter_kind_mask(formatter_kind_mask) { + CommandArgumentEntry type_arg; + CommandArgumentData type_style_arg; + + type_style_arg.arg_type = eArgTypeName; + type_style_arg.arg_repetition = eArgRepeatPlain; + + type_arg.push_back(type_style_arg); + + m_arguments.push_back(type_arg); + } + + ~CommandObjectTypeFormatterDelete() override = default; protected: - virtual bool - FormatterSpecificDeletion (ConstString typeCS) - { - return false; + virtual bool FormatterSpecificDeletion(ConstString typeCS) { return false; } + + bool DoExecute(Args &command, CommandReturnObject &result) override { + const size_t argc = command.GetArgumentCount(); + + if (argc != 1) { + result.AppendErrorWithFormat("%s takes 1 arg.\n", m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; } - - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - const size_t argc = command.GetArgumentCount(); - - if (argc != 1) - { - result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - const char* typeA = command.GetArgumentAtIndex(0); - ConstString typeCS(typeA); - - if (!typeCS) - { - result.AppendError("empty typenames not allowed"); - result.SetStatus(eReturnStatusFailed); - return false; - } - - if (m_options.m_delete_all) - { - DataVisualization::Categories::ForEach( [this, typeCS] (const lldb::TypeCategoryImplSP& category_sp) -> bool { - category_sp->Delete(typeCS, m_formatter_kind_mask); - return true; - }); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); - } - - bool delete_category = false; - bool extra_deletion = false; - - if (m_options.m_language != lldb::eLanguageTypeUnknown) - { - lldb::TypeCategoryImplSP category; - DataVisualization::Categories::GetCategory(m_options.m_language, category); - if (category) - delete_category = category->Delete(typeCS, m_formatter_kind_mask); - extra_deletion = FormatterSpecificDeletion(typeCS); - } - else - { - lldb::TypeCategoryImplSP category; - DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); - if (category) - delete_category = category->Delete(typeCS, m_formatter_kind_mask); - extra_deletion = FormatterSpecificDeletion(typeCS); - } - - if (delete_category || extra_deletion) - { - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); - } - else - { - result.AppendErrorWithFormat ("no custom formatter for %s.\n", typeA); - result.SetStatus(eReturnStatusFailed); - return false; - } + + const char *typeA = command.GetArgumentAtIndex(0); + ConstString typeCS(typeA); + + if (!typeCS) { + result.AppendError("empty typenames not allowed"); + result.SetStatus(eReturnStatusFailed); + return false; } + + if (m_options.m_delete_all) { + DataVisualization::Categories::ForEach( + [this, typeCS](const lldb::TypeCategoryImplSP &category_sp) -> bool { + category_sp->Delete(typeCS, m_formatter_kind_mask); + return true; + }); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return result.Succeeded(); + } + + bool delete_category = false; + bool extra_deletion = false; + + if (m_options.m_language != lldb::eLanguageTypeUnknown) { + lldb::TypeCategoryImplSP category; + DataVisualization::Categories::GetCategory(m_options.m_language, + category); + if (category) + delete_category = category->Delete(typeCS, m_formatter_kind_mask); + extra_deletion = FormatterSpecificDeletion(typeCS); + } else { + lldb::TypeCategoryImplSP category; + DataVisualization::Categories::GetCategory( + ConstString(m_options.m_category.c_str()), category); + if (category) + delete_category = category->Delete(typeCS, m_formatter_kind_mask); + extra_deletion = FormatterSpecificDeletion(typeCS); + } + + if (delete_category || extra_deletion) { + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return result.Succeeded(); + } else { + result.AppendErrorWithFormat("no custom formatter for %s.\n", typeA); + result.SetStatus(eReturnStatusFailed); + return false; + } + } }; OptionDefinition -CommandObjectTypeFormatterDelete::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectTypeFormatterDelete::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete from every category."}, {LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Delete from given category."}, {LLDB_OPT_SET_3, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Delete from given language's category."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; -class CommandObjectTypeFormatterClear : public CommandObjectParsed -{ +class CommandObjectTypeFormatterClear : public CommandObjectParsed { private: - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - } + class CommandOptions : public Options { + public: + CommandOptions() : Options() {} - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'a': - m_delete_all = true; - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_delete_all = false; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - bool m_delete_all; - }; - - CommandOptions m_options; - uint32_t m_formatter_kind_mask; + ~CommandOptions() override = default; - Options * - GetOptions () override - { - return &m_options; + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'a': + m_delete_all = true; + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; } - -public: - CommandObjectTypeFormatterClear (CommandInterpreter &interpreter, - uint32_t formatter_kind_mask, - const char* name, - const char* help) : - CommandObjectParsed(interpreter, - name, - help, - nullptr), - m_options(), - m_formatter_kind_mask(formatter_kind_mask) - { + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_delete_all = false; } - ~CommandObjectTypeFormatterClear() override = default; + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + bool m_delete_all; + }; + + CommandOptions m_options; + uint32_t m_formatter_kind_mask; + + Options *GetOptions() override { return &m_options; } + +public: + CommandObjectTypeFormatterClear(CommandInterpreter &interpreter, + uint32_t formatter_kind_mask, + const char *name, const char *help) + : CommandObjectParsed(interpreter, name, help, nullptr), m_options(), + m_formatter_kind_mask(formatter_kind_mask) {} + + ~CommandObjectTypeFormatterClear() override = default; protected: - virtual void - FormatterSpecificDeletion () - { - } - - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - if (m_options.m_delete_all) - { - DataVisualization::Categories::ForEach( [this] (const TypeCategoryImplSP& category_sp) -> bool { - category_sp->Clear(m_formatter_kind_mask); - return true; - }); - } - else - { - lldb::TypeCategoryImplSP category; - if (command.GetArgumentCount() > 0) - { - const char* cat_name = command.GetArgumentAtIndex(0); - ConstString cat_nameCS(cat_name); - DataVisualization::Categories::GetCategory(cat_nameCS, category); - } - else - { - DataVisualization::Categories::GetCategory(ConstString(nullptr), category); - } - category->Clear(m_formatter_kind_mask); - } - - FormatterSpecificDeletion(); - - result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); - } + virtual void FormatterSpecificDeletion() {} + + bool DoExecute(Args &command, CommandReturnObject &result) override { + if (m_options.m_delete_all) { + DataVisualization::Categories::ForEach( + [this](const TypeCategoryImplSP &category_sp) -> bool { + category_sp->Clear(m_formatter_kind_mask); + return true; + }); + } else { + lldb::TypeCategoryImplSP category; + if (command.GetArgumentCount() > 0) { + const char *cat_name = command.GetArgumentAtIndex(0); + ConstString cat_nameCS(cat_name); + DataVisualization::Categories::GetCategory(cat_nameCS, category); + } else { + DataVisualization::Categories::GetCategory(ConstString(nullptr), + category); + } + category->Clear(m_formatter_kind_mask); + } + + FormatterSpecificDeletion(); + + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); + } }; OptionDefinition -CommandObjectTypeFormatterClear::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectTypeFormatterClear::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Clear every category."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- // CommandObjectTypeFormatDelete //------------------------------------------------------------------------- -class CommandObjectTypeFormatDelete : public CommandObjectTypeFormatterDelete -{ +class CommandObjectTypeFormatDelete : public CommandObjectTypeFormatterDelete { public: - CommandObjectTypeFormatDelete (CommandInterpreter &interpreter) : - CommandObjectTypeFormatterDelete (interpreter, - eFormatCategoryItemValue | eFormatCategoryItemRegexValue, - "type format delete", - "Delete an existing formatting style for a type.") - { - } - - ~CommandObjectTypeFormatDelete() override = default; + CommandObjectTypeFormatDelete(CommandInterpreter &interpreter) + : CommandObjectTypeFormatterDelete( + interpreter, + eFormatCategoryItemValue | eFormatCategoryItemRegexValue, + "type format delete", + "Delete an existing formatting style for a type.") {} + + ~CommandObjectTypeFormatDelete() override = default; }; //------------------------------------------------------------------------- // CommandObjectTypeFormatClear //------------------------------------------------------------------------- -class CommandObjectTypeFormatClear : public CommandObjectTypeFormatterClear -{ +class CommandObjectTypeFormatClear : public CommandObjectTypeFormatterClear { public: - CommandObjectTypeFormatClear (CommandInterpreter &interpreter) : - CommandObjectTypeFormatterClear (interpreter, - eFormatCategoryItemValue | eFormatCategoryItemRegexValue, - "type format clear", - "Delete all existing format styles.") - { - } + CommandObjectTypeFormatClear(CommandInterpreter &interpreter) + : CommandObjectTypeFormatterClear( + interpreter, + eFormatCategoryItemValue | eFormatCategoryItemRegexValue, + "type format clear", "Delete all existing format styles.") {} }; template <typename FormatterType> -class CommandObjectTypeFormatterList : public CommandObjectParsed -{ - typedef typename FormatterType::SharedPointer FormatterSharedPointer; - - class CommandOptions : public Options - { - public: - CommandOptions() : - Options(), - m_category_regex("",""), - m_category_language(lldb::eLanguageTypeUnknown, lldb::eLanguageTypeUnknown) - { - } - - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'w': - m_category_regex.SetCurrentValue(option_arg); - m_category_regex.SetOptionWasSet(); - break; - case 'l': - error = m_category_language.SetValueFromString(option_arg); - if (error.Success()) - m_category_language.SetOptionWasSet(); - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_category_regex.Clear(); - m_category_language.Clear(); - } - - const OptionDefinition* - GetDefinitions () override - { - static OptionDefinition g_option_table[] = - { - // clang-format off +class CommandObjectTypeFormatterList : public CommandObjectParsed { + typedef typename FormatterType::SharedPointer FormatterSharedPointer; + + class CommandOptions : public Options { + public: + CommandOptions() + : Options(), m_category_regex("", ""), + m_category_language(lldb::eLanguageTypeUnknown, + lldb::eLanguageTypeUnknown) {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'w': + m_category_regex.SetCurrentValue(option_arg); + m_category_regex.SetOptionWasSet(); + break; + case 'l': + error = m_category_language.SetValueFromString(option_arg); + if (error.Success()) + m_category_language.SetOptionWasSet(); + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; + } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_category_regex.Clear(); + m_category_language.Clear(); + } + + const OptionDefinition *GetDefinitions() override { + static OptionDefinition g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "category-regex", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Only show categories matching this filter."}, {LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Only show the category for a specific language."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on - }; + // clang-format on + }; - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - OptionValueString m_category_regex; - OptionValueLanguage m_category_language; - }; - - CommandOptions m_options; - - Options * - GetOptions () override - { - return &m_options; + return g_option_table; } + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + OptionValueString m_category_regex; + OptionValueLanguage m_category_language; + }; + + CommandOptions m_options; + + Options *GetOptions() override { return &m_options; } + public: - CommandObjectTypeFormatterList (CommandInterpreter &interpreter, - const char* name, - const char* help) : - CommandObjectParsed(interpreter, - name, - help, - nullptr), - m_options() - { - CommandArgumentEntry type_arg; - CommandArgumentData type_style_arg; - - type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatOptional; - - type_arg.push_back (type_style_arg); - - m_arguments.push_back (type_arg); - } + CommandObjectTypeFormatterList(CommandInterpreter &interpreter, + const char *name, const char *help) + : CommandObjectParsed(interpreter, name, help, nullptr), m_options() { + CommandArgumentEntry type_arg; + CommandArgumentData type_style_arg; + + type_style_arg.arg_type = eArgTypeName; + type_style_arg.arg_repetition = eArgRepeatOptional; - ~CommandObjectTypeFormatterList() override = default; + type_arg.push_back(type_style_arg); + + m_arguments.push_back(type_arg); + } + + ~CommandObjectTypeFormatterList() override = default; protected: - virtual bool - FormatterSpecificList (CommandReturnObject &result) - { + virtual bool FormatterSpecificList(CommandReturnObject &result) { + return false; + } + + bool DoExecute(Args &command, CommandReturnObject &result) override { + const size_t argc = command.GetArgumentCount(); + + std::unique_ptr<RegularExpression> category_regex; + std::unique_ptr<RegularExpression> formatter_regex; + + if (m_options.m_category_regex.OptionWasSet()) { + category_regex.reset(new RegularExpression()); + if (!category_regex->Compile( + m_options.m_category_regex.GetCurrentValue())) { + result.AppendErrorWithFormat( + "syntax error in category regular expression '%s'", + m_options.m_category_regex.GetCurrentValue()); + result.SetStatus(eReturnStatusFailed); return false; + } } - - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - const size_t argc = command.GetArgumentCount(); - - std::unique_ptr<RegularExpression> category_regex; - std::unique_ptr<RegularExpression> formatter_regex; - - if (m_options.m_category_regex.OptionWasSet()) - { - category_regex.reset(new RegularExpression()); - if (!category_regex->Compile(m_options.m_category_regex.GetCurrentValue())) - { - result.AppendErrorWithFormat("syntax error in category regular expression '%s'", m_options.m_category_regex.GetCurrentValue()); - result.SetStatus(eReturnStatusFailed); - return false; + + if (argc == 1) { + const char *arg = command.GetArgumentAtIndex(0); + formatter_regex.reset(new RegularExpression()); + if (!formatter_regex->Compile(arg)) { + result.AppendErrorWithFormat("syntax error in regular expression '%s'", + arg); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + + bool any_printed = false; + + auto category_closure = [&result, &formatter_regex, &any_printed]( + const lldb::TypeCategoryImplSP &category) -> void { + result.GetOutputStream().Printf( + "-----------------------\nCategory: %s%s\n-----------------------\n", + category->GetName(), category->IsEnabled() ? "" : " (disabled)"); + + TypeCategoryImpl::ForEachCallbacks<FormatterType> foreach; + foreach + .SetExact([&result, &formatter_regex, &any_printed]( + ConstString name, + const FormatterSharedPointer &format_sp) -> bool { + if (formatter_regex) { + bool escape = true; + if (0 == strcmp(name.AsCString(), formatter_regex->GetText())) { + escape = false; + } else if (formatter_regex->Execute(name.AsCString())) { + escape = false; } - } - - if (argc == 1) - { - const char* arg = command.GetArgumentAtIndex(0); - formatter_regex.reset(new RegularExpression()); - if (!formatter_regex->Compile(arg)) - { - result.AppendErrorWithFormat("syntax error in regular expression '%s'", arg); - result.SetStatus(eReturnStatusFailed); - return false; + + if (escape) + return true; + } + + any_printed = true; + result.GetOutputStream().Printf("%s: %s\n", name.AsCString(), + format_sp->GetDescription().c_str()); + return true; + }); + + foreach + .SetWithRegex([&result, &formatter_regex, &any_printed]( + RegularExpressionSP regex_sp, + const FormatterSharedPointer &format_sp) -> bool { + if (formatter_regex) { + bool escape = true; + if (0 == strcmp(regex_sp->GetText(), formatter_regex->GetText())) { + escape = false; + } else if (formatter_regex->Execute(regex_sp->GetText())) { + escape = false; } - } - - bool any_printed = false; - - auto category_closure = [&result, &formatter_regex, &any_printed] (const lldb::TypeCategoryImplSP& category) -> void { - result.GetOutputStream().Printf("-----------------------\nCategory: %s%s\n-----------------------\n", - category->GetName(), - category->IsEnabled() ? "" : " (disabled)"); - - TypeCategoryImpl::ForEachCallbacks<FormatterType> foreach; - foreach.SetExact([&result, &formatter_regex, &any_printed] (ConstString name, const FormatterSharedPointer& format_sp) -> bool { - if (formatter_regex) - { - bool escape = true; - if (0 == strcmp(name.AsCString(), formatter_regex->GetText())) - { - escape = false; - } - else if (formatter_regex->Execute(name.AsCString())) - { - escape = false; - } - - if (escape) - return true; - } - any_printed = true; - result.GetOutputStream().Printf ("%s: %s\n", name.AsCString(), format_sp->GetDescription().c_str()); - return true; - }); - - foreach.SetWithRegex([&result, &formatter_regex, &any_printed] (RegularExpressionSP regex_sp, const FormatterSharedPointer& format_sp) -> bool { - if (formatter_regex) - { - bool escape = true; - if (0 == strcmp(regex_sp->GetText(), formatter_regex->GetText())) - { - escape = false; - } - else if (formatter_regex->Execute(regex_sp->GetText())) - { - escape = false; - } - - if (escape) - return true; - } - - any_printed = true; - result.GetOutputStream().Printf ("%s: %s\n", regex_sp->GetText(), format_sp->GetDescription().c_str()); - return true; - }); - - category->ForEach(foreach); - }; - - if (m_options.m_category_language.OptionWasSet()) - { - lldb::TypeCategoryImplSP category_sp; - DataVisualization::Categories::GetCategory(m_options.m_category_language.GetCurrentValue(), category_sp); - if (category_sp) - category_closure(category_sp); - } - else - { - DataVisualization::Categories::ForEach( [this, &command, &result, &category_regex, &formatter_regex, &category_closure] (const lldb::TypeCategoryImplSP& category) -> bool { - if (category_regex) - { - bool escape = true; - if (0 == strcmp(category->GetName(), category_regex->GetText())) - { - escape = false; - } - else if (category_regex->Execute(category->GetName())) - { - escape = false; - } - - if (escape) - return true; - } - - category_closure(category); - + if (escape) + return true; + } + + any_printed = true; + result.GetOutputStream().Printf("%s: %s\n", regex_sp->GetText(), + format_sp->GetDescription().c_str()); + return true; + }); + + category->ForEach(foreach); + }; + + if (m_options.m_category_language.OptionWasSet()) { + lldb::TypeCategoryImplSP category_sp; + DataVisualization::Categories::GetCategory( + m_options.m_category_language.GetCurrentValue(), category_sp); + if (category_sp) + category_closure(category_sp); + } else { + DataVisualization::Categories::ForEach( + [this, &command, &result, &category_regex, &formatter_regex, + &category_closure]( + const lldb::TypeCategoryImplSP &category) -> bool { + if (category_regex) { + bool escape = true; + if (0 == strcmp(category->GetName(), category_regex->GetText())) { + escape = false; + } else if (category_regex->Execute(category->GetName())) { + escape = false; + } + + if (escape) return true; - }); - - any_printed = FormatterSpecificList(result) | any_printed; - } - - if (any_printed) - result.SetStatus(eReturnStatusSuccessFinishResult); - else - { - result.GetOutputStream().PutCString("no matching results found.\n"); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } - return result.Succeeded(); + } + + category_closure(category); + + return true; + }); + + any_printed = FormatterSpecificList(result) | any_printed; + } + + if (any_printed) + result.SetStatus(eReturnStatusSuccessFinishResult); + else { + result.GetOutputStream().PutCString("no matching results found.\n"); + result.SetStatus(eReturnStatusSuccessFinishNoResult); } + return result.Succeeded(); + } }; //------------------------------------------------------------------------- // CommandObjectTypeFormatList //------------------------------------------------------------------------- -class CommandObjectTypeFormatList : public CommandObjectTypeFormatterList<TypeFormatImpl> -{ +class CommandObjectTypeFormatList + : public CommandObjectTypeFormatterList<TypeFormatImpl> { public: - - CommandObjectTypeFormatList (CommandInterpreter &interpreter) : - CommandObjectTypeFormatterList(interpreter, - "type format list", - "Show a list of current formats.") - { - } + CommandObjectTypeFormatList(CommandInterpreter &interpreter) + : CommandObjectTypeFormatterList(interpreter, "type format list", + "Show a list of current formats.") {} }; #ifndef LLDB_DISABLE_PYTHON @@ -1485,338 +1237,316 @@ public: #endif // LLDB_DISABLE_PYTHON -Error -CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue(uint32_t option_idx, - const char - *option_arg, - ExecutionContext - *execution_context) -{ - Error error; - const int short_option = m_getopt_table[option_idx].val; - bool success; - - switch (short_option) - { - case 'C': - m_flags.SetCascades(Args::StringToBoolean(option_arg, true, &success)); - if (!success) - error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg); - break; - case 'e': - m_flags.SetDontShowChildren(false); - break; - case 'h': - m_flags.SetHideEmptyAggregates(true); - break; - case 'v': - m_flags.SetDontShowValue(true); - break; - case 'c': - m_flags.SetShowMembersOneLiner(true); - break; - case 's': - m_format_string = std::string(option_arg); - break; - case 'p': - m_flags.SetSkipPointers(true); - break; - case 'r': - m_flags.SetSkipReferences(true); - break; - case 'x': - m_regex = true; - break; - case 'n': - m_name.SetCString(option_arg); - break; - case 'o': - m_python_script = std::string(option_arg); - m_is_add_script = true; - break; - case 'F': - m_python_function = std::string(option_arg); - m_is_add_script = true; - break; - case 'P': - m_is_add_script = true; - break; - case 'w': - m_category = std::string(option_arg); - break; - case 'O': - m_flags.SetHideItemNames(true); - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; +Error CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue( + uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) { + Error error; + const int short_option = m_getopt_table[option_idx].val; + bool success; + + switch (short_option) { + case 'C': + m_flags.SetCascades(Args::StringToBoolean(option_arg, true, &success)); + if (!success) + error.SetErrorStringWithFormat("invalid value for cascade: %s", + option_arg); + break; + case 'e': + m_flags.SetDontShowChildren(false); + break; + case 'h': + m_flags.SetHideEmptyAggregates(true); + break; + case 'v': + m_flags.SetDontShowValue(true); + break; + case 'c': + m_flags.SetShowMembersOneLiner(true); + break; + case 's': + m_format_string = std::string(option_arg); + break; + case 'p': + m_flags.SetSkipPointers(true); + break; + case 'r': + m_flags.SetSkipReferences(true); + break; + case 'x': + m_regex = true; + break; + case 'n': + m_name.SetCString(option_arg); + break; + case 'o': + m_python_script = std::string(option_arg); + m_is_add_script = true; + break; + case 'F': + m_python_function = std::string(option_arg); + m_is_add_script = true; + break; + case 'P': + m_is_add_script = true; + break; + case 'w': + m_category = std::string(option_arg); + break; + case 'O': + m_flags.SetHideItemNames(true); + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); + break; + } + + return error; } -void -CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting( - ExecutionContext *execution_context) -{ - m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false); - m_flags.SetShowMembersOneLiner(false).SetSkipPointers(false).SetSkipReferences(false).SetHideItemNames(false); - - m_regex = false; - m_name.Clear(); - m_python_script = ""; - m_python_function = ""; - m_format_string = ""; - m_is_add_script = false; - m_category = "default"; +void CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting( + ExecutionContext *execution_context) { + m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false); + m_flags.SetShowMembersOneLiner(false) + .SetSkipPointers(false) + .SetSkipReferences(false) + .SetHideItemNames(false); + + m_regex = false; + m_name.Clear(); + m_python_script = ""; + m_python_function = ""; + m_format_string = ""; + m_is_add_script = false; + m_category = "default"; } #ifndef LLDB_DISABLE_PYTHON -bool -CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturnObject &result) -{ - const size_t argc = command.GetArgumentCount(); - - if (argc < 1 && !m_options.m_name) - { - result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - TypeSummaryImplSP script_format; - - if (!m_options.m_python_function.empty()) // we have a Python function ready to use - { - const char *funct_name = m_options.m_python_function.c_str(); - if (!funct_name || !funct_name[0]) - { - result.AppendError ("function name empty.\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - std::string code = (" " + m_options.m_python_function + "(valobj,internal_dict)"); - - script_format.reset(new ScriptSummaryFormat(m_options.m_flags, - funct_name, - code.c_str())); - - ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); - - if (interpreter && !interpreter->CheckObjectExists(funct_name)) - result.AppendWarningWithFormat("The provided function \"%s\" does not exist - " - "please define it before attempting to use this summary.\n", - funct_name); - } - else if (!m_options.m_python_script.empty()) // we have a quick 1-line script, just use it - { - ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); - if (!interpreter) - { - result.AppendError ("script interpreter missing - unable to generate function wrapper.\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } - StringList funct_sl; - funct_sl << m_options.m_python_script.c_str(); - std::string funct_name_str; - if (!interpreter->GenerateTypeScriptFunction (funct_sl, - funct_name_str)) - { - result.AppendError ("unable to generate function wrapper.\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } - if (funct_name_str.empty()) - { - result.AppendError ("script interpreter failed to generate a valid function name.\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - std::string code = " " + m_options.m_python_script; - - script_format.reset(new ScriptSummaryFormat(m_options.m_flags, - funct_name_str.c_str(), - code.c_str())); - } - else - { - // Use an IOHandler to grab Python code from the user - ScriptAddOptions *options = new ScriptAddOptions(m_options.m_flags, - m_options.m_regex, - m_options.m_name, - m_options.m_category); - - for (size_t i = 0; i < argc; i++) - { - const char* typeA = command.GetArgumentAtIndex(i); - if (typeA && *typeA) - options->m_target_types << typeA; - else - { - result.AppendError("empty typenames not allowed"); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - - m_interpreter.GetPythonCommandsFromIOHandler (" ", // Prompt - *this, // IOHandlerDelegate - true, // Run IOHandler in async mode - options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions - result.SetStatus(eReturnStatusSuccessFinishNoResult); - - return result.Succeeded(); - } - - // if I am here, script_format must point to something good, so I can add that - // as a script summary to all interested parties - - Error error; - - for (size_t i = 0; i < command.GetArgumentCount(); i++) - { - const char *type_name = command.GetArgumentAtIndex(i); - CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name), - script_format, - (m_options.m_regex ? eRegexSummary : eRegularSummary), - m_options.m_category, - &error); - if (error.Fail()) - { - result.AppendError(error.AsCString()); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - - if (m_options.m_name) - { - AddSummary(m_options.m_name, script_format, eNamedSummary, m_options.m_category, &error); - if (error.Fail()) - { - result.AppendError(error.AsCString()); - result.AppendError("added to types, but not given a name"); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - - return result.Succeeded(); -} +bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary( + Args &command, CommandReturnObject &result) { + const size_t argc = command.GetArgumentCount(); -#endif // LLDB_DISABLE_PYTHON + if (argc < 1 && !m_options.m_name) { + result.AppendErrorWithFormat("%s takes one or more args.\n", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } -bool -CommandObjectTypeSummaryAdd::Execute_StringSummary (Args& command, CommandReturnObject &result) -{ - const size_t argc = command.GetArgumentCount(); - - if (argc < 1 && !m_options.m_name) - { - result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - if (!m_options.m_flags.GetShowMembersOneLiner() && m_options.m_format_string.empty()) - { - result.AppendError("empty summary strings not allowed"); - result.SetStatus(eReturnStatusFailed); - return false; - } - - const char* format_cstr = (m_options.m_flags.GetShowMembersOneLiner() ? "" : m_options.m_format_string.c_str()); - - // ${var%S} is an endless recursion, prevent it - if (strcmp(format_cstr, "${var%S}") == 0) - { - result.AppendError("recursive summary not allowed"); - result.SetStatus(eReturnStatusFailed); - return false; - } - - std::unique_ptr<StringSummaryFormat> string_format(new StringSummaryFormat(m_options.m_flags, format_cstr)); - if (!string_format) - { - result.AppendError("summary creation failed"); - result.SetStatus(eReturnStatusFailed); - return false; + TypeSummaryImplSP script_format; + + if (!m_options.m_python_function + .empty()) // we have a Python function ready to use + { + const char *funct_name = m_options.m_python_function.c_str(); + if (!funct_name || !funct_name[0]) { + result.AppendError("function name empty.\n"); + result.SetStatus(eReturnStatusFailed); + return false; } - if (string_format->m_error.Fail()) - { - result.AppendErrorWithFormat("syntax error: %s", string_format->m_error.AsCString("<unknown>")); + + std::string code = + (" " + m_options.m_python_function + "(valobj,internal_dict)"); + + script_format.reset( + new ScriptSummaryFormat(m_options.m_flags, funct_name, code.c_str())); + + ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); + + if (interpreter && !interpreter->CheckObjectExists(funct_name)) + result.AppendWarningWithFormat( + "The provided function \"%s\" does not exist - " + "please define it before attempting to use this summary.\n", + funct_name); + } else if (!m_options.m_python_script + .empty()) // we have a quick 1-line script, just use it + { + ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); + if (!interpreter) { + result.AppendError("script interpreter missing - unable to generate " + "function wrapper.\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } + StringList funct_sl; + funct_sl << m_options.m_python_script.c_str(); + std::string funct_name_str; + if (!interpreter->GenerateTypeScriptFunction(funct_sl, funct_name_str)) { + result.AppendError("unable to generate function wrapper.\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } + if (funct_name_str.empty()) { + result.AppendError( + "script interpreter failed to generate a valid function name.\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + std::string code = " " + m_options.m_python_script; + + script_format.reset(new ScriptSummaryFormat( + m_options.m_flags, funct_name_str.c_str(), code.c_str())); + } else { + // Use an IOHandler to grab Python code from the user + ScriptAddOptions *options = + new ScriptAddOptions(m_options.m_flags, m_options.m_regex, + m_options.m_name, m_options.m_category); + + for (size_t i = 0; i < argc; i++) { + const char *typeA = command.GetArgumentAtIndex(i); + if (typeA && *typeA) + options->m_target_types << typeA; + else { + result.AppendError("empty typenames not allowed"); result.SetStatus(eReturnStatusFailed); return false; + } } - lldb::TypeSummaryImplSP entry(string_format.release()); - - // now I have a valid format, let's add it to every type - Error error; - for (size_t i = 0; i < argc; i++) - { - const char* typeA = command.GetArgumentAtIndex(i); - if (!typeA || typeA[0] == '\0') - { - result.AppendError("empty typenames not allowed"); - result.SetStatus(eReturnStatusFailed); - return false; - } - ConstString typeCS(typeA); - - AddSummary(typeCS, - entry, - (m_options.m_regex ? eRegexSummary : eRegularSummary), - m_options.m_category, - &error); - - if (error.Fail()) - { - result.AppendError(error.AsCString()); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - - if (m_options.m_name) - { - AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category, &error); - if (error.Fail()) - { - result.AppendError(error.AsCString()); - result.AppendError("added to types, but not given a name"); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - + + m_interpreter.GetPythonCommandsFromIOHandler( + " ", // Prompt + *this, // IOHandlerDelegate + true, // Run IOHandler in async mode + options); // Baton for the "io_handler" that will be passed back into + // our IOHandlerDelegate functions result.SetStatus(eReturnStatusSuccessFinishNoResult); + return result.Succeeded(); + } + + // if I am here, script_format must point to something good, so I can add that + // as a script summary to all interested parties + + Error error; + + for (size_t i = 0; i < command.GetArgumentCount(); i++) { + const char *type_name = command.GetArgumentAtIndex(i); + CommandObjectTypeSummaryAdd::AddSummary( + ConstString(type_name), script_format, + (m_options.m_regex ? eRegexSummary : eRegularSummary), + m_options.m_category, &error); + if (error.Fail()) { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + + if (m_options.m_name) { + AddSummary(m_options.m_name, script_format, eNamedSummary, + m_options.m_category, &error); + if (error.Fail()) { + result.AppendError(error.AsCString()); + result.AppendError("added to types, but not given a name"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + + return result.Succeeded(); } -CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "type summary add", - "Add a new summary style for a type.", - nullptr), - IOHandlerDelegateMultiline ("DONE"), - m_options (interpreter) -{ - CommandArgumentEntry type_arg; - CommandArgumentData type_style_arg; - - type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatPlus; - - type_arg.push_back (type_style_arg); - - m_arguments.push_back (type_arg); - - SetHelpLong( -R"( +#endif // LLDB_DISABLE_PYTHON + +bool CommandObjectTypeSummaryAdd::Execute_StringSummary( + Args &command, CommandReturnObject &result) { + const size_t argc = command.GetArgumentCount(); + + if (argc < 1 && !m_options.m_name) { + result.AppendErrorWithFormat("%s takes one or more args.\n", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (!m_options.m_flags.GetShowMembersOneLiner() && + m_options.m_format_string.empty()) { + result.AppendError("empty summary strings not allowed"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + const char *format_cstr = (m_options.m_flags.GetShowMembersOneLiner() + ? "" + : m_options.m_format_string.c_str()); + + // ${var%S} is an endless recursion, prevent it + if (strcmp(format_cstr, "${var%S}") == 0) { + result.AppendError("recursive summary not allowed"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + std::unique_ptr<StringSummaryFormat> string_format( + new StringSummaryFormat(m_options.m_flags, format_cstr)); + if (!string_format) { + result.AppendError("summary creation failed"); + result.SetStatus(eReturnStatusFailed); + return false; + } + if (string_format->m_error.Fail()) { + result.AppendErrorWithFormat("syntax error: %s", + string_format->m_error.AsCString("<unknown>")); + result.SetStatus(eReturnStatusFailed); + return false; + } + lldb::TypeSummaryImplSP entry(string_format.release()); + + // now I have a valid format, let's add it to every type + Error error; + for (size_t i = 0; i < argc; i++) { + const char *typeA = command.GetArgumentAtIndex(i); + if (!typeA || typeA[0] == '\0') { + result.AppendError("empty typenames not allowed"); + result.SetStatus(eReturnStatusFailed); + return false; + } + ConstString typeCS(typeA); + + AddSummary(typeCS, entry, + (m_options.m_regex ? eRegexSummary : eRegularSummary), + m_options.m_category, &error); + + if (error.Fail()) { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + + if (m_options.m_name) { + AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category, + &error); + if (error.Fail()) { + result.AppendError(error.AsCString()); + result.AppendError("added to types, but not given a name"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return result.Succeeded(); +} + +CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd( + CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "type summary add", + "Add a new summary style for a type.", nullptr), + IOHandlerDelegateMultiline("DONE"), m_options(interpreter) { + CommandArgumentEntry type_arg; + CommandArgumentData type_style_arg; + + type_style_arg.arg_type = eArgTypeName; + type_style_arg.arg_repetition = eArgRepeatPlus; + + type_arg.push_back(type_style_arg); + + m_arguments.push_back(type_arg); + + SetHelpLong( + R"( The following examples of 'type summary add' refer to this code snippet for context: struct JustADemo @@ -1838,51 +1568,65 @@ The following examples of 'type summary add' refer to this code snippet for cont Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14" -)" "Alternatively, you could define formatting for all pointers to integers and \ -rely on that when formatting JustADemo to obtain the same result:" R"( +)" + "Alternatively, you could define formatting for all pointers to integers and \ +rely on that when formatting JustADemo to obtain the same result:" + R"( (lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *" (lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo -)" "Type summaries are automatically applied to derived typedefs, so the examples \ +)" + "Type summaries are automatically applied to derived typedefs, so the examples \ above apply to both JustADemo and NewDemo. The cascade option can be used to \ -suppress this behavior:" R"( +suppress this behavior:" + R"( (lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no The summary will now be used for values of JustADemo but not NewDemo. -)" "By default summaries are shown for pointers and references to values of the \ +)" + "By default summaries are shown for pointers and references to values of the \ specified type. To suppress formatting for pointers use the -p option, or apply \ -the corresponding -r option to suppress formatting for references:" R"( +the corresponding -r option to suppress formatting for references:" + R"( (lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -)" "One-line summaries including all fields in a type can be inferred without supplying an \ -explicit summary string by passing the -c option:" R"( +)" + "One-line summaries including all fields in a type can be inferred without supplying an \ +explicit summary string by passing the -c option:" + R"( (lldb) type summary add -c JustADemo (lldb) frame variable demo_instance (ptr=<address>, value=3.14) -)" "Type summaries normally suppress the nested display of individual fields. To \ -supply a summary to supplement the default structure add the -e option:" R"( +)" + "Type summaries normally suppress the nested display of individual fields. To \ +supply a summary to supplement the default structure add the -e option:" + R"( (lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo -)" "Now when displaying JustADemo values the int* is displayed, followed by the \ -standard LLDB sequence of children, one per line:" R"( +)" + "Now when displaying JustADemo values the int* is displayed, followed by the \ +standard LLDB sequence of children, one per line:" + R"( *ptr = 42 { ptr = <address> value = 3.14 } -)" "You can also add summaries written in Python. These scripts use lldb public API to \ +)" + "You can also add summaries written in Python. These scripts use lldb public API to \ gather information from your variables and produce a meaningful summary. To start a \ multi-line script use the -P option. The function declaration will be displayed along with \ a comment describing the two arguments. End your script with the word 'DONE' on a line by \ -itself:" R"( +itself:" + R"( (lldb) type summary add JustADemo -P def function (valobj,internal_dict): @@ -1894,96 +1638,82 @@ internal_dict: an LLDB support object not to be used""" Alternatively, the -o option can be used when providing a simple one-line Python script: -(lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")" - ); +(lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")"); } -bool -CommandObjectTypeSummaryAdd::DoExecute (Args& command, CommandReturnObject &result) -{ - WarnOnPotentialUnquotedUnsignedType(command, result); +bool CommandObjectTypeSummaryAdd::DoExecute(Args &command, + CommandReturnObject &result) { + WarnOnPotentialUnquotedUnsignedType(command, result); - if (m_options.m_is_add_script) - { + if (m_options.m_is_add_script) { #ifndef LLDB_DISABLE_PYTHON - return Execute_ScriptSummary(command, result); + return Execute_ScriptSummary(command, result); #else - result.AppendError ("python is disabled"); - result.SetStatus(eReturnStatusFailed); - return false; + result.AppendError("python is disabled"); + result.SetStatus(eReturnStatusFailed); + return false; #endif // LLDB_DISABLE_PYTHON - } - - return Execute_StringSummary(command, result); -} + } -static bool -FixArrayTypeNameWithRegex (ConstString &type_name) -{ - llvm::StringRef type_name_ref(type_name.GetStringRef()); - - if (type_name_ref.endswith("[]")) - { - std::string type_name_str(type_name.GetCString()); - type_name_str.resize(type_name_str.length()-2); - if (type_name_str.back() != ' ') - type_name_str.append(" \\[[0-9]+\\]"); - else - type_name_str.append("\\[[0-9]+\\]"); - type_name.SetCString(type_name_str.c_str()); - return true; - } - return false; + return Execute_StringSummary(command, result); } -bool -CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name, - TypeSummaryImplSP entry, - SummaryFormatType type, - std::string category_name, - Error* error) -{ - lldb::TypeCategoryImplSP category; - DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category); - - if (type == eRegularSummary) - { - if (FixArrayTypeNameWithRegex (type_name)) - type = eRegexSummary; - } - - if (type == eRegexSummary) - { - RegularExpressionSP typeRX(new RegularExpression()); - if (!typeRX->Compile(type_name.GetCString())) - { - if (error) - error->SetErrorString("regex format error (maybe this is not really a regex?)"); - return false; - } - - category->GetRegexTypeSummariesContainer()->Delete(type_name); - category->GetRegexTypeSummariesContainer()->Add(typeRX, entry); - - return true; - } - else if (type == eNamedSummary) - { - // system named summaries do not exist (yet?) - DataVisualization::NamedSummaryFormats::Add(type_name,entry); - return true; - } +static bool FixArrayTypeNameWithRegex(ConstString &type_name) { + llvm::StringRef type_name_ref(type_name.GetStringRef()); + + if (type_name_ref.endswith("[]")) { + std::string type_name_str(type_name.GetCString()); + type_name_str.resize(type_name_str.length() - 2); + if (type_name_str.back() != ' ') + type_name_str.append(" \\[[0-9]+\\]"); else - { - category->GetTypeSummariesContainer()->Add(type_name, entry); - return true; - } -} + type_name_str.append("\\[[0-9]+\\]"); + type_name.SetCString(type_name_str.c_str()); + return true; + } + return false; +} -OptionDefinition -CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] = -{ - // clang-format off +bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name, + TypeSummaryImplSP entry, + SummaryFormatType type, + std::string category_name, + Error *error) { + lldb::TypeCategoryImplSP category; + DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), + category); + + if (type == eRegularSummary) { + if (FixArrayTypeNameWithRegex(type_name)) + type = eRegexSummary; + } + + if (type == eRegexSummary) { + RegularExpressionSP typeRX(new RegularExpression()); + if (!typeRX->Compile(type_name.GetCString())) { + if (error) + error->SetErrorString( + "regex format error (maybe this is not really a regex?)"); + return false; + } + + category->GetRegexTypeSummariesContainer()->Delete(type_name); + category->GetRegexTypeSummariesContainer()->Add(typeRX, entry); + + return true; + } else if (type == eNamedSummary) { + // system named summaries do not exist (yet?) + DataVisualization::NamedSummaryFormats::Add(type_name, entry); + return true; + } else { + category->GetTypeSummariesContainer()->Add(type_name, entry); + return true; + } +} + +OptionDefinition CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] = + { + // clang-format off {LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one."}, {LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, {LLDB_OPT_SET_ALL, false, "no-value", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't show the value, just show the summary, for this type."}, @@ -2000,678 +1730,563 @@ CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] = {LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "hide-empty", 'h', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Do not expand aggregate data types with no children."}, {LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "A name for this summary string."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- // CommandObjectTypeSummaryDelete //------------------------------------------------------------------------- -class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete -{ +class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete { public: - CommandObjectTypeSummaryDelete (CommandInterpreter &interpreter) : - CommandObjectTypeFormatterDelete (interpreter, - eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary, - "type summary delete", - "Delete an existing summary for a type.") - { - } + CommandObjectTypeSummaryDelete(CommandInterpreter &interpreter) + : CommandObjectTypeFormatterDelete( + interpreter, + eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary, + "type summary delete", "Delete an existing summary for a type.") {} - ~CommandObjectTypeSummaryDelete() override = default; + ~CommandObjectTypeSummaryDelete() override = default; protected: - bool - FormatterSpecificDeletion (ConstString typeCS) override - { - if (m_options.m_language != lldb::eLanguageTypeUnknown) - return false; - return DataVisualization::NamedSummaryFormats::Delete(typeCS); - } + bool FormatterSpecificDeletion(ConstString typeCS) override { + if (m_options.m_language != lldb::eLanguageTypeUnknown) + return false; + return DataVisualization::NamedSummaryFormats::Delete(typeCS); + } }; -class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear -{ +class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear { public: - CommandObjectTypeSummaryClear (CommandInterpreter &interpreter) : - CommandObjectTypeFormatterClear (interpreter, - eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary, - "type summary clear", - "Delete all existing summaries.") - { - } - + CommandObjectTypeSummaryClear(CommandInterpreter &interpreter) + : CommandObjectTypeFormatterClear( + interpreter, + eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary, + "type summary clear", "Delete all existing summaries.") {} + protected: - void - FormatterSpecificDeletion () override - { - DataVisualization::NamedSummaryFormats::Clear(); - } + void FormatterSpecificDeletion() override { + DataVisualization::NamedSummaryFormats::Clear(); + } }; //------------------------------------------------------------------------- // CommandObjectTypeSummaryList //------------------------------------------------------------------------- -class CommandObjectTypeSummaryList : public CommandObjectTypeFormatterList<TypeSummaryImpl> -{ +class CommandObjectTypeSummaryList + : public CommandObjectTypeFormatterList<TypeSummaryImpl> { public: - CommandObjectTypeSummaryList (CommandInterpreter &interpreter) : - CommandObjectTypeFormatterList(interpreter, - "type summary list", - "Show a list of current summaries.") - { - } - + CommandObjectTypeSummaryList(CommandInterpreter &interpreter) + : CommandObjectTypeFormatterList(interpreter, "type summary list", + "Show a list of current summaries.") {} + protected: - bool - FormatterSpecificList (CommandReturnObject &result) override - { - if (DataVisualization::NamedSummaryFormats::GetCount() > 0) - { - result.GetOutputStream().Printf("Named summaries:\n"); - DataVisualization::NamedSummaryFormats::ForEach( [&result] (ConstString name, const TypeSummaryImplSP& summary_sp) -> bool { - result.GetOutputStream().Printf ("%s: %s\n", name.AsCString(), summary_sp->GetDescription().c_str()); - return true; - }); + bool FormatterSpecificList(CommandReturnObject &result) override { + if (DataVisualization::NamedSummaryFormats::GetCount() > 0) { + result.GetOutputStream().Printf("Named summaries:\n"); + DataVisualization::NamedSummaryFormats::ForEach( + [&result](ConstString name, + const TypeSummaryImplSP &summary_sp) -> bool { + result.GetOutputStream().Printf( + "%s: %s\n", name.AsCString(), + summary_sp->GetDescription().c_str()); return true; - } - return false; + }); + return true; } + return false; + } }; //------------------------------------------------------------------------- // CommandObjectTypeCategoryDefine //------------------------------------------------------------------------- -class CommandObjectTypeCategoryDefine : public CommandObjectParsed -{ - class CommandOptions : public Options - { - public: - CommandOptions() : - Options(), - m_define_enabled(false,false), - m_cate_language(eLanguageTypeUnknown,eLanguageTypeUnknown) - { - } +class CommandObjectTypeCategoryDefine : public CommandObjectParsed { + class CommandOptions : public Options { + public: + CommandOptions() + : Options(), m_define_enabled(false, false), + m_cate_language(eLanguageTypeUnknown, eLanguageTypeUnknown) {} - ~CommandOptions() override = default; - - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'e': - m_define_enabled.SetValueFromString("true"); - break; - case 'l': - error = m_cate_language.SetValueFromString(option_arg); - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_define_enabled.Clear(); - m_cate_language.Clear(); - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - OptionValueBoolean m_define_enabled; - OptionValueLanguage m_cate_language; - }; - - CommandOptions m_options; - - Options * - GetOptions () override - { - return &m_options; + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'e': + m_define_enabled.SetValueFromString("true"); + break; + case 'l': + error = m_cate_language.SetValueFromString(option_arg); + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; + } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_define_enabled.Clear(); + m_cate_language.Clear(); } + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + OptionValueBoolean m_define_enabled; + OptionValueLanguage m_cate_language; + }; + + CommandOptions m_options; + + Options *GetOptions() override { return &m_options; } + public: - CommandObjectTypeCategoryDefine (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "type category define", + CommandObjectTypeCategoryDefine(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "type category define", "Define a new category as a source of formatters.", nullptr), - m_options() - { - CommandArgumentEntry type_arg; - CommandArgumentData type_style_arg; - - type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatPlus; - - type_arg.push_back (type_style_arg); - - m_arguments.push_back (type_arg); - } + m_options() { + CommandArgumentEntry type_arg; + CommandArgumentData type_style_arg; + + type_style_arg.arg_type = eArgTypeName; + type_style_arg.arg_repetition = eArgRepeatPlus; + + type_arg.push_back(type_style_arg); + + m_arguments.push_back(type_arg); + } - ~CommandObjectTypeCategoryDefine() override = default; + ~CommandObjectTypeCategoryDefine() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - const size_t argc = command.GetArgumentCount(); - - if (argc < 1) - { - result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - for (size_t i = 0; i < argc; i++) - { - const char* cateName = command.GetArgumentAtIndex(i); - TypeCategoryImplSP category_sp; - if (DataVisualization::Categories::GetCategory(ConstString(cateName), category_sp) && category_sp) - { - category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue()); - if (m_options.m_define_enabled.GetCurrentValue()) - DataVisualization::Categories::Enable(category_sp, TypeCategoryMap::Default); - } - } - - result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); + bool DoExecute(Args &command, CommandReturnObject &result) override { + const size_t argc = command.GetArgumentCount(); + + if (argc < 1) { + result.AppendErrorWithFormat("%s takes 1 or more args.\n", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; } + + for (size_t i = 0; i < argc; i++) { + const char *cateName = command.GetArgumentAtIndex(i); + TypeCategoryImplSP category_sp; + if (DataVisualization::Categories::GetCategory(ConstString(cateName), + category_sp) && + category_sp) { + category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue()); + if (m_options.m_define_enabled.GetCurrentValue()) + DataVisualization::Categories::Enable(category_sp, + TypeCategoryMap::Default); + } + } + + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); + } }; OptionDefinition -CommandObjectTypeCategoryDefine::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectTypeCategoryDefine::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_ALL, false, "enabled", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "If specified, this category will be created enabled."}, {LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specify the language that this category is supported for."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- // CommandObjectTypeCategoryEnable //------------------------------------------------------------------------- -class CommandObjectTypeCategoryEnable : public CommandObjectParsed -{ - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - } +class CommandObjectTypeCategoryEnable : public CommandObjectParsed { + class CommandOptions : public Options { + public: + CommandOptions() : Options() {} - ~CommandOptions() override = default; - - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'l': - if (option_arg) - { - m_language = Language::GetLanguageTypeFromString(option_arg); - if (m_language == lldb::eLanguageTypeUnknown) - error.SetErrorStringWithFormat ("unrecognized language '%s'", option_arg); - } - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_language = lldb::eLanguageTypeUnknown; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'l': + if (option_arg) { + m_language = Language::GetLanguageTypeFromString(option_arg); + if (m_language == lldb::eLanguageTypeUnknown) + error.SetErrorStringWithFormat("unrecognized language '%s'", + option_arg); } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - lldb::LanguageType m_language; - - }; - - CommandOptions m_options; - - Options * - GetOptions () override - { - return &m_options; + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; + } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_language = lldb::eLanguageTypeUnknown; } - + + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + lldb::LanguageType m_language; + }; + + CommandOptions m_options; + + Options *GetOptions() override { return &m_options; } + public: - CommandObjectTypeCategoryEnable (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "type category enable", + CommandObjectTypeCategoryEnable(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "type category enable", "Enable a category as a source of formatters.", nullptr), - m_options() - { - CommandArgumentEntry type_arg; - CommandArgumentData type_style_arg; - - type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatPlus; - - type_arg.push_back (type_style_arg); - - m_arguments.push_back (type_arg); - - } + m_options() { + CommandArgumentEntry type_arg; + CommandArgumentData type_style_arg; - ~CommandObjectTypeCategoryEnable() override = default; + type_style_arg.arg_type = eArgTypeName; + type_style_arg.arg_repetition = eArgRepeatPlus; + + type_arg.push_back(type_style_arg); + + m_arguments.push_back(type_arg); + } + + ~CommandObjectTypeCategoryEnable() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - const size_t argc = command.GetArgumentCount(); - - if (argc < 1 && - m_options.m_language == lldb::eLanguageTypeUnknown) - { - result.AppendErrorWithFormat ("%s takes arguments and/or a language", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0) - { - DataVisualization::Categories::EnableStar(); + bool DoExecute(Args &command, CommandReturnObject &result) override { + const size_t argc = command.GetArgumentCount(); + + if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) { + result.AppendErrorWithFormat("%s takes arguments and/or a language", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) { + DataVisualization::Categories::EnableStar(); + } else if (argc > 0) { + for (int i = argc - 1; i >= 0; i--) { + const char *typeA = command.GetArgumentAtIndex(i); + ConstString typeCS(typeA); + + if (!typeCS) { + result.AppendError("empty category name not allowed"); + result.SetStatus(eReturnStatusFailed); + return false; } - else if (argc > 0) - { - for (int i = argc - 1; i >= 0; i--) - { - const char* typeA = command.GetArgumentAtIndex(i); - ConstString typeCS(typeA); - - if (!typeCS) - { - result.AppendError("empty category name not allowed"); - result.SetStatus(eReturnStatusFailed); - return false; - } - DataVisualization::Categories::Enable(typeCS); - lldb::TypeCategoryImplSP cate; - if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate) - { - if (cate->GetCount() == 0) - { - result.AppendWarning("empty category enabled (typo?)"); - } - } - } + DataVisualization::Categories::Enable(typeCS); + lldb::TypeCategoryImplSP cate; + if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate) { + if (cate->GetCount() == 0) { + result.AppendWarning("empty category enabled (typo?)"); + } } - - if (m_options.m_language != lldb::eLanguageTypeUnknown) - DataVisualization::Categories::Enable(m_options.m_language); - - result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); + } } + + if (m_options.m_language != lldb::eLanguageTypeUnknown) + DataVisualization::Categories::Enable(m_options.m_language); + + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); + } }; OptionDefinition -CommandObjectTypeCategoryEnable::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectTypeCategoryEnable::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Enable the category for this language."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- // CommandObjectTypeCategoryDelete //------------------------------------------------------------------------- -class CommandObjectTypeCategoryDelete : public CommandObjectParsed -{ +class CommandObjectTypeCategoryDelete : public CommandObjectParsed { public: - CommandObjectTypeCategoryDelete (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "type category delete", + CommandObjectTypeCategoryDelete(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "type category delete", "Delete a category and all associated formatters.", - nullptr) - { - CommandArgumentEntry type_arg; - CommandArgumentData type_style_arg; - - type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatPlus; - - type_arg.push_back (type_style_arg); - - m_arguments.push_back (type_arg); - } + nullptr) { + CommandArgumentEntry type_arg; + CommandArgumentData type_style_arg; + + type_style_arg.arg_type = eArgTypeName; + type_style_arg.arg_repetition = eArgRepeatPlus; + + type_arg.push_back(type_style_arg); + + m_arguments.push_back(type_arg); + } - ~CommandObjectTypeCategoryDelete() override = default; + ~CommandObjectTypeCategoryDelete() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - const size_t argc = command.GetArgumentCount(); - - if (argc < 1) - { - result.AppendErrorWithFormat ("%s takes 1 or more arg.\n", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - bool success = true; - - // the order is not relevant here - for (int i = argc - 1; i >= 0; i--) - { - const char* typeA = command.GetArgumentAtIndex(i); - ConstString typeCS(typeA); - - if (!typeCS) - { - result.AppendError("empty category name not allowed"); - result.SetStatus(eReturnStatusFailed); - return false; - } - if (!DataVisualization::Categories::Delete(typeCS)) - success = false; // keep deleting even if we hit an error - } - if (success) - { - result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); - } - else - { - result.AppendError("cannot delete one or more categories\n"); - result.SetStatus(eReturnStatusFailed); - return false; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + const size_t argc = command.GetArgumentCount(); + + if (argc < 1) { + result.AppendErrorWithFormat("%s takes 1 or more arg.\n", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; } + + bool success = true; + + // the order is not relevant here + for (int i = argc - 1; i >= 0; i--) { + const char *typeA = command.GetArgumentAtIndex(i); + ConstString typeCS(typeA); + + if (!typeCS) { + result.AppendError("empty category name not allowed"); + result.SetStatus(eReturnStatusFailed); + return false; + } + if (!DataVisualization::Categories::Delete(typeCS)) + success = false; // keep deleting even if we hit an error + } + if (success) { + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); + } else { + result.AppendError("cannot delete one or more categories\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } }; //------------------------------------------------------------------------- // CommandObjectTypeCategoryDisable //------------------------------------------------------------------------- -class CommandObjectTypeCategoryDisable : public CommandObjectParsed -{ - class CommandOptions : public Options - { - public: - CommandOptions() : - Options() - { - } +class CommandObjectTypeCategoryDisable : public CommandObjectParsed { + class CommandOptions : public Options { + public: + CommandOptions() : Options() {} - ~CommandOptions() override = default; - - Error - SetOptionValue (uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'l': - if (option_arg) - { - m_language = Language::GetLanguageTypeFromString(option_arg); - if (m_language == lldb::eLanguageTypeUnknown) - error.SetErrorStringWithFormat ("unrecognized language '%s'", option_arg); - } - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_language = lldb::eLanguageTypeUnknown; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'l': + if (option_arg) { + m_language = Language::GetLanguageTypeFromString(option_arg); + if (m_language == lldb::eLanguageTypeUnknown) + error.SetErrorStringWithFormat("unrecognized language '%s'", + option_arg); } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - lldb::LanguageType m_language; - }; - - CommandOptions m_options; - - Options * - GetOptions () override - { - return &m_options; + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; } + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_language = lldb::eLanguageTypeUnknown; + } + + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + lldb::LanguageType m_language; + }; + + CommandOptions m_options; + + Options *GetOptions() override { return &m_options; } + public: - CommandObjectTypeCategoryDisable (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "type category disable", + CommandObjectTypeCategoryDisable(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "type category disable", "Disable a category as a source of formatters.", nullptr), - m_options() - { - CommandArgumentEntry type_arg; - CommandArgumentData type_style_arg; - - type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatPlus; - - type_arg.push_back (type_style_arg); - - m_arguments.push_back (type_arg); - } + m_options() { + CommandArgumentEntry type_arg; + CommandArgumentData type_style_arg; + + type_style_arg.arg_type = eArgTypeName; + type_style_arg.arg_repetition = eArgRepeatPlus; + + type_arg.push_back(type_style_arg); - ~CommandObjectTypeCategoryDisable() override = default; + m_arguments.push_back(type_arg); + } + + ~CommandObjectTypeCategoryDisable() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - const size_t argc = command.GetArgumentCount(); - - if (argc < 1 && - m_options.m_language == lldb::eLanguageTypeUnknown) - { - result.AppendErrorWithFormat ("%s takes arguments and/or a language", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0) - { - DataVisualization::Categories::DisableStar(); - } - else if (argc > 0) - { - // the order is not relevant here - for (int i = argc - 1; i >= 0; i--) - { - const char* typeA = command.GetArgumentAtIndex(i); - ConstString typeCS(typeA); - - if (!typeCS) - { - result.AppendError("empty category name not allowed"); - result.SetStatus(eReturnStatusFailed); - return false; - } - DataVisualization::Categories::Disable(typeCS); - } - } - - if (m_options.m_language != lldb::eLanguageTypeUnknown) - DataVisualization::Categories::Disable(m_options.m_language); + bool DoExecute(Args &command, CommandReturnObject &result) override { + const size_t argc = command.GetArgumentCount(); - result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); + if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) { + result.AppendErrorWithFormat("%s takes arguments and/or a language", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; } + + if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) { + DataVisualization::Categories::DisableStar(); + } else if (argc > 0) { + // the order is not relevant here + for (int i = argc - 1; i >= 0; i--) { + const char *typeA = command.GetArgumentAtIndex(i); + ConstString typeCS(typeA); + + if (!typeCS) { + result.AppendError("empty category name not allowed"); + result.SetStatus(eReturnStatusFailed); + return false; + } + DataVisualization::Categories::Disable(typeCS); + } + } + + if (m_options.m_language != lldb::eLanguageTypeUnknown) + DataVisualization::Categories::Disable(m_options.m_language); + + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); + } }; OptionDefinition -CommandObjectTypeCategoryDisable::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectTypeCategoryDisable::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Enable the category for this language."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- // CommandObjectTypeCategoryList //------------------------------------------------------------------------- -class CommandObjectTypeCategoryList : public CommandObjectParsed -{ +class CommandObjectTypeCategoryList : public CommandObjectParsed { public: - CommandObjectTypeCategoryList (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "type category list", + CommandObjectTypeCategoryList(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "type category list", "Provide a list of all existing categories.", - nullptr) - { - CommandArgumentEntry type_arg; - CommandArgumentData type_style_arg; - - type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatOptional; - - type_arg.push_back (type_style_arg); - - m_arguments.push_back (type_arg); - } + nullptr) { + CommandArgumentEntry type_arg; + CommandArgumentData type_style_arg; - ~CommandObjectTypeCategoryList() override = default; + type_style_arg.arg_type = eArgTypeName; + type_style_arg.arg_repetition = eArgRepeatOptional; + + type_arg.push_back(type_style_arg); + + m_arguments.push_back(type_arg); + } + + ~CommandObjectTypeCategoryList() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - const size_t argc = command.GetArgumentCount(); - - std::unique_ptr<RegularExpression> regex; - - if (argc == 1) - { - regex.reset(new RegularExpression()); - const char* arg = command.GetArgumentAtIndex(0); - if (!regex->Compile(arg)) - { - result.AppendErrorWithFormat("syntax error in category regular expression '%s'", arg); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - else if (argc != 0) - { - result.AppendErrorWithFormat ("%s takes 0 or one arg.\n", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - DataVisualization::Categories::ForEach( [®ex, &result] (const lldb::TypeCategoryImplSP& category_sp) -> bool { - if (regex) - { - bool escape = true; - if (0 == strcmp(category_sp->GetName(), regex->GetText())) - { - escape = false; - } - else if (regex->Execute(category_sp->GetName())) - { - escape = false; - } - - if (escape) - return true; + bool DoExecute(Args &command, CommandReturnObject &result) override { + const size_t argc = command.GetArgumentCount(); + + std::unique_ptr<RegularExpression> regex; + + if (argc == 1) { + regex.reset(new RegularExpression()); + const char *arg = command.GetArgumentAtIndex(0); + if (!regex->Compile(arg)) { + result.AppendErrorWithFormat( + "syntax error in category regular expression '%s'", arg); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else if (argc != 0) { + result.AppendErrorWithFormat("%s takes 0 or one arg.\n", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + DataVisualization::Categories::ForEach( + [®ex, &result](const lldb::TypeCategoryImplSP &category_sp) -> bool { + if (regex) { + bool escape = true; + if (0 == strcmp(category_sp->GetName(), regex->GetText())) { + escape = false; + } else if (regex->Execute(category_sp->GetName())) { + escape = false; } - - result.GetOutputStream().Printf("Category: %s\n", category_sp->GetDescription().c_str()); - - return true; + + if (escape) + return true; + } + + result.GetOutputStream().Printf( + "Category: %s\n", category_sp->GetDescription().c_str()); + + return true; }); - - result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); - } + + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); + } }; //------------------------------------------------------------------------- // CommandObjectTypeFilterList //------------------------------------------------------------------------- -class CommandObjectTypeFilterList : public CommandObjectTypeFormatterList<TypeFilterImpl> -{ +class CommandObjectTypeFilterList + : public CommandObjectTypeFormatterList<TypeFilterImpl> { public: - CommandObjectTypeFilterList (CommandInterpreter &interpreter) : - CommandObjectTypeFormatterList(interpreter, - "type filter list", - "Show a list of current filters.") - { - } + CommandObjectTypeFilterList(CommandInterpreter &interpreter) + : CommandObjectTypeFormatterList(interpreter, "type filter list", + "Show a list of current filters.") {} }; #ifndef LLDB_DISABLE_PYTHON @@ -2680,15 +2295,13 @@ public: // CommandObjectTypeSynthList //------------------------------------------------------------------------- -class CommandObjectTypeSynthList : public CommandObjectTypeFormatterList<SyntheticChildren> -{ +class CommandObjectTypeSynthList + : public CommandObjectTypeFormatterList<SyntheticChildren> { public: - CommandObjectTypeSynthList (CommandInterpreter &interpreter) : - CommandObjectTypeFormatterList(interpreter, - "type synthetic list", - "Show a list of current synthetic providers.") - { - } + CommandObjectTypeSynthList(CommandInterpreter &interpreter) + : CommandObjectTypeFormatterList( + interpreter, "type synthetic list", + "Show a list of current synthetic providers.") {} }; #endif // LLDB_DISABLE_PYTHON @@ -2697,18 +2310,15 @@ public: // CommandObjectTypeFilterDelete //------------------------------------------------------------------------- -class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete -{ +class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete { public: - CommandObjectTypeFilterDelete (CommandInterpreter &interpreter) : - CommandObjectTypeFormatterDelete (interpreter, - eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, - "type filter delete", - "Delete an existing filter for a type.") - { - } + CommandObjectTypeFilterDelete(CommandInterpreter &interpreter) + : CommandObjectTypeFormatterDelete( + interpreter, + eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, + "type filter delete", "Delete an existing filter for a type.") {} - ~CommandObjectTypeFilterDelete() override = default; + ~CommandObjectTypeFilterDelete() override = default; }; #ifndef LLDB_DISABLE_PYTHON @@ -2717,18 +2327,16 @@ public: // CommandObjectTypeSynthDelete //------------------------------------------------------------------------- -class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete -{ +class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete { public: - CommandObjectTypeSynthDelete (CommandInterpreter &interpreter) : - CommandObjectTypeFormatterDelete (interpreter, - eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, - "type synthetic delete", - "Delete an existing synthetic provider for a type.") - { - } - - ~CommandObjectTypeSynthDelete() override = default; + CommandObjectTypeSynthDelete(CommandInterpreter &interpreter) + : CommandObjectTypeFormatterDelete( + interpreter, + eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, + "type synthetic delete", + "Delete an existing synthetic provider for a type.") {} + + ~CommandObjectTypeSynthDelete() override = default; }; #endif // LLDB_DISABLE_PYTHON @@ -2737,16 +2345,13 @@ public: // CommandObjectTypeFilterClear //------------------------------------------------------------------------- -class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear -{ +class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear { public: - CommandObjectTypeFilterClear (CommandInterpreter &interpreter) : - CommandObjectTypeFormatterClear (interpreter, - eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, - "type filter clear", - "Delete all existing filter.") - { - } + CommandObjectTypeFilterClear(CommandInterpreter &interpreter) + : CommandObjectTypeFormatterClear( + interpreter, + eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, + "type filter clear", "Delete all existing filter.") {} }; #ifndef LLDB_DISABLE_PYTHON @@ -2754,190 +2359,173 @@ public: // CommandObjectTypeSynthClear //------------------------------------------------------------------------- -class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear -{ +class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear { public: - CommandObjectTypeSynthClear (CommandInterpreter &interpreter) : - CommandObjectTypeFormatterClear (interpreter, - eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, - "type synthetic clear", - "Delete all existing synthetic providers.") - { - } + CommandObjectTypeSynthClear(CommandInterpreter &interpreter) + : CommandObjectTypeFormatterClear( + interpreter, + eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, + "type synthetic clear", + "Delete all existing synthetic providers.") {} }; -bool -CommandObjectTypeSynthAdd::Execute_HandwritePython (Args& command, CommandReturnObject &result) -{ - SynthAddOptions *options = new SynthAddOptions ( m_options.m_skip_pointers, - m_options.m_skip_references, - m_options.m_cascade, - m_options.m_regex, - m_options.m_category); - - const size_t argc = command.GetArgumentCount(); - - for (size_t i = 0; i < argc; i++) - { - const char* typeA = command.GetArgumentAtIndex(i); - if (typeA && *typeA) - options->m_target_types << typeA; - else - { - result.AppendError("empty typenames not allowed"); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - - m_interpreter.GetPythonCommandsFromIOHandler (" ", // Prompt - *this, // IOHandlerDelegate - true, // Run IOHandler in async mode - options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); +bool CommandObjectTypeSynthAdd::Execute_HandwritePython( + Args &command, CommandReturnObject &result) { + SynthAddOptions *options = new SynthAddOptions( + m_options.m_skip_pointers, m_options.m_skip_references, + m_options.m_cascade, m_options.m_regex, m_options.m_category); + + const size_t argc = command.GetArgumentCount(); + + for (size_t i = 0; i < argc; i++) { + const char *typeA = command.GetArgumentAtIndex(i); + if (typeA && *typeA) + options->m_target_types << typeA; + else { + result.AppendError("empty typenames not allowed"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + + m_interpreter.GetPythonCommandsFromIOHandler( + " ", // Prompt + *this, // IOHandlerDelegate + true, // Run IOHandler in async mode + options); // Baton for the "io_handler" that will be passed back into our + // IOHandlerDelegate functions + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return result.Succeeded(); } -bool -CommandObjectTypeSynthAdd::Execute_PythonClass (Args& command, CommandReturnObject &result) -{ - const size_t argc = command.GetArgumentCount(); - - if (argc < 1) - { - result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - if (m_options.m_class_name.empty() && !m_options.m_input_python) - { - result.AppendErrorWithFormat ("%s needs either a Python class name or -P to directly input Python code.\n", m_cmd_name.c_str()); +bool CommandObjectTypeSynthAdd::Execute_PythonClass( + Args &command, CommandReturnObject &result) { + const size_t argc = command.GetArgumentCount(); + + if (argc < 1) { + result.AppendErrorWithFormat("%s takes one or more args.\n", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (m_options.m_class_name.empty() && !m_options.m_input_python) { + result.AppendErrorWithFormat("%s needs either a Python class name or -P to " + "directly input Python code.\n", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + SyntheticChildrenSP entry; + + ScriptedSyntheticChildren *impl = new ScriptedSyntheticChildren( + SyntheticChildren::Flags() + .SetCascades(m_options.m_cascade) + .SetSkipPointers(m_options.m_skip_pointers) + .SetSkipReferences(m_options.m_skip_references), + m_options.m_class_name.c_str()); + + entry.reset(impl); + + ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); + + if (interpreter && + !interpreter->CheckObjectExists(impl->GetPythonClassName())) + result.AppendWarning("The provided class does not exist - please define it " + "before attempting to use this synthetic provider"); + + // now I have a valid provider, let's add it to every type + + lldb::TypeCategoryImplSP category; + DataVisualization::Categories::GetCategory( + ConstString(m_options.m_category.c_str()), category); + + Error error; + + for (size_t i = 0; i < argc; i++) { + const char *typeA = command.GetArgumentAtIndex(i); + ConstString typeCS(typeA); + if (typeCS) { + if (!AddSynth(typeCS, entry, + m_options.m_regex ? eRegexSynth : eRegularSynth, + m_options.m_category, &error)) { + result.AppendError(error.AsCString()); result.SetStatus(eReturnStatusFailed); return false; + } + } else { + result.AppendError("empty typenames not allowed"); + result.SetStatus(eReturnStatusFailed); + return false; } - - SyntheticChildrenSP entry; - - ScriptedSyntheticChildren* impl = new ScriptedSyntheticChildren(SyntheticChildren::Flags(). - SetCascades(m_options.m_cascade). - SetSkipPointers(m_options.m_skip_pointers). - SetSkipReferences(m_options.m_skip_references), - m_options.m_class_name.c_str()); - - entry.reset(impl); - - ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); - - if (interpreter && !interpreter->CheckObjectExists(impl->GetPythonClassName())) - result.AppendWarning("The provided class does not exist - please define it before attempting to use this synthetic provider"); - - // now I have a valid provider, let's add it to every type - - lldb::TypeCategoryImplSP category; - DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); - - Error error; - - for (size_t i = 0; i < argc; i++) - { - const char* typeA = command.GetArgumentAtIndex(i); - ConstString typeCS(typeA); - if (typeCS) - { - if (!AddSynth(typeCS, - entry, - m_options.m_regex ? eRegexSynth : eRegularSynth, - m_options.m_category, - &error)) - { - result.AppendError(error.AsCString()); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - else - { - result.AppendError("empty typenames not allowed"); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); + } + + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return result.Succeeded(); } - -CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "type synthetic add", - "Add a new synthetic provider for a type.", - nullptr), - IOHandlerDelegateMultiline ("DONE"), - m_options() -{ - CommandArgumentEntry type_arg; - CommandArgumentData type_style_arg; - - type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatPlus; - - type_arg.push_back (type_style_arg); - - m_arguments.push_back (type_arg); + +CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd( + CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "type synthetic add", + "Add a new synthetic provider for a type.", nullptr), + IOHandlerDelegateMultiline("DONE"), m_options() { + CommandArgumentEntry type_arg; + CommandArgumentData type_style_arg; + + type_style_arg.arg_type = eArgTypeName; + type_style_arg.arg_repetition = eArgRepeatPlus; + + type_arg.push_back(type_style_arg); + + m_arguments.push_back(type_arg); } -bool -CommandObjectTypeSynthAdd::AddSynth(ConstString type_name, - SyntheticChildrenSP entry, - SynthFormatType type, - std::string category_name, - Error* error) -{ - lldb::TypeCategoryImplSP category; - DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category); - - if (type == eRegularSynth) - { - if (FixArrayTypeNameWithRegex (type_name)) - type = eRegexSynth; - } - - if (category->AnyMatches(type_name, - eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, - false)) - { - if (error) - error->SetErrorStringWithFormat("cannot add synthetic for type %s when filter is defined in same category!", type_name.AsCString()); - return false; - } - - if (type == eRegexSynth) - { - RegularExpressionSP typeRX(new RegularExpression()); - if (!typeRX->Compile(type_name.GetCString())) - { - if (error) - error->SetErrorString("regex format error (maybe this is not really a regex?)"); - return false; - } - - category->GetRegexTypeSyntheticsContainer()->Delete(type_name); - category->GetRegexTypeSyntheticsContainer()->Add(typeRX, entry); - - return true; - } - else - { - category->GetTypeSyntheticsContainer()->Add(type_name, entry); - return true; +bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name, + SyntheticChildrenSP entry, + SynthFormatType type, + std::string category_name, + Error *error) { + lldb::TypeCategoryImplSP category; + DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), + category); + + if (type == eRegularSynth) { + if (FixArrayTypeNameWithRegex(type_name)) + type = eRegexSynth; + } + + if (category->AnyMatches(type_name, eFormatCategoryItemFilter | + eFormatCategoryItemRegexFilter, + false)) { + if (error) + error->SetErrorStringWithFormat("cannot add synthetic for type %s when " + "filter is defined in same category!", + type_name.AsCString()); + return false; + } + + if (type == eRegexSynth) { + RegularExpressionSP typeRX(new RegularExpression()); + if (!typeRX->Compile(type_name.GetCString())) { + if (error) + error->SetErrorString( + "regex format error (maybe this is not really a regex?)"); + return false; } + + category->GetRegexTypeSyntheticsContainer()->Delete(type_name); + category->GetRegexTypeSyntheticsContainer()->Add(typeRX, entry); + + return true; + } else { + category->GetTypeSyntheticsContainer()->Add(type_name, entry); + return true; + } } -OptionDefinition -CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, {LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, {LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, @@ -2946,182 +2534,154 @@ CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] = {LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type Python code to generate a class that provides synthetic children."}, {LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; #endif // LLDB_DISABLE_PYTHON -class CommandObjectTypeFilterAdd : public CommandObjectParsed -{ +class CommandObjectTypeFilterAdd : public CommandObjectParsed { private: - class CommandOptions : public Options - { - typedef std::vector<std::string> option_vector; + class CommandOptions : public Options { + typedef std::vector<std::string> option_vector; + + public: + CommandOptions() : Options() {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + bool success; + + switch (short_option) { + case 'C': + m_cascade = Args::StringToBoolean(option_arg, true, &success); + if (!success) + error.SetErrorStringWithFormat("invalid value for cascade: %s", + option_arg); + break; + case 'c': + m_expr_paths.push_back(option_arg); + has_child_list = true; + break; + case 'p': + m_skip_pointers = true; + break; + case 'r': + m_skip_references = true; + break; + case 'w': + m_category = std::string(option_arg); + break; + case 'x': + m_regex = true; + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; + } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_cascade = true; + m_skip_pointers = false; + m_skip_references = false; + m_category = "default"; + m_expr_paths.clear(); + has_child_list = false; + m_regex = false; + } + + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. - public: - CommandOptions() : - Options() - { - } + bool m_cascade; + bool m_skip_references; + bool m_skip_pointers; + bool m_input_python; + option_vector m_expr_paths; + std::string m_category; + bool has_child_list; + bool m_regex; - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - bool success; - - switch (short_option) - { - case 'C': - m_cascade = Args::StringToBoolean(option_arg, true, &success); - if (!success) - error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg); - break; - case 'c': - m_expr_paths.push_back(option_arg); - has_child_list = true; - break; - case 'p': - m_skip_pointers = true; - break; - case 'r': - m_skip_references = true; - break; - case 'w': - m_category = std::string(option_arg); - break; - case 'x': - m_regex = true; - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_cascade = true; - m_skip_pointers = false; - m_skip_references = false; - m_category = "default"; - m_expr_paths.clear(); - has_child_list = false; - m_regex = false; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - bool m_cascade; - bool m_skip_references; - bool m_skip_pointers; - bool m_input_python; - option_vector m_expr_paths; - std::string m_category; - bool has_child_list; - bool m_regex; - - typedef option_vector::iterator ExpressionPathsIterator; - }; - - CommandOptions m_options; - - Options * - GetOptions () override - { - return &m_options; + typedef option_vector::iterator ExpressionPathsIterator; + }; + + CommandOptions m_options; + + Options *GetOptions() override { return &m_options; } + + enum FilterFormatType { eRegularFilter, eRegexFilter }; + + bool AddFilter(ConstString type_name, TypeFilterImplSP entry, + FilterFormatType type, std::string category_name, + Error *error) { + lldb::TypeCategoryImplSP category; + DataVisualization::Categories::GetCategory( + ConstString(category_name.c_str()), category); + + if (type == eRegularFilter) { + if (FixArrayTypeNameWithRegex(type_name)) + type = eRegexFilter; } - - enum FilterFormatType - { - eRegularFilter, - eRegexFilter - }; - - bool - AddFilter(ConstString type_name, - TypeFilterImplSP entry, - FilterFormatType type, - std::string category_name, - Error* error) - { - lldb::TypeCategoryImplSP category; - DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category); - - if (type == eRegularFilter) - { - if (FixArrayTypeNameWithRegex (type_name)) - type = eRegexFilter; - } - - if (category->AnyMatches(type_name, - eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, - false)) - { - if (error) - error->SetErrorStringWithFormat("cannot add filter for type %s when synthetic is defined in same category!", type_name.AsCString()); - return false; - } - - if (type == eRegexFilter) - { - RegularExpressionSP typeRX(new RegularExpression()); - if (!typeRX->Compile(type_name.GetCString())) - { - if (error) - error->SetErrorString("regex format error (maybe this is not really a regex?)"); - return false; - } - - category->GetRegexTypeFiltersContainer()->Delete(type_name); - category->GetRegexTypeFiltersContainer()->Add(typeRX, entry); - - return true; - } - else - { - category->GetTypeFiltersContainer()->Add(type_name, entry); - return true; - } + + if (category->AnyMatches(type_name, eFormatCategoryItemSynth | + eFormatCategoryItemRegexSynth, + false)) { + if (error) + error->SetErrorStringWithFormat("cannot add filter for type %s when " + "synthetic is defined in same " + "category!", + type_name.AsCString()); + return false; } + if (type == eRegexFilter) { + RegularExpressionSP typeRX(new RegularExpression()); + if (!typeRX->Compile(type_name.GetCString())) { + if (error) + error->SetErrorString( + "regex format error (maybe this is not really a regex?)"); + return false; + } + + category->GetRegexTypeFiltersContainer()->Delete(type_name); + category->GetRegexTypeFiltersContainer()->Add(typeRX, entry); + + return true; + } else { + category->GetTypeFiltersContainer()->Add(type_name, entry); + return true; + } + } + public: - CommandObjectTypeFilterAdd (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "type filter add", - "Add a new filter for a type.", - nullptr), - m_options() - { - CommandArgumentEntry type_arg; - CommandArgumentData type_style_arg; - - type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatPlus; - - type_arg.push_back (type_style_arg); - - m_arguments.push_back (type_arg); - - SetHelpLong( -R"( + CommandObjectTypeFilterAdd(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "type filter add", + "Add a new filter for a type.", nullptr), + m_options() { + CommandArgumentEntry type_arg; + CommandArgumentData type_style_arg; + + type_style_arg.arg_type = eArgTypeName; + type_style_arg.arg_repetition = eArgRepeatPlus; + + type_arg.push_back(type_style_arg); + + m_arguments.push_back(type_arg); + + SetHelpLong( + R"( The following examples of 'type filter add' refer to this code snippet for context: class Foo { @@ -3142,94 +2702,90 @@ Adding a simple filter: (lldb) type filter add --child a --child g Foo (lldb) frame variable my_foo -)" "Produces output where only a and g are displayed. Other children of my_foo \ -(b, c, d, e, f, h and i) are available by asking for them explicitly:" R"( +)" + "Produces output where only a and g are displayed. Other children of my_foo \ +(b, c, d, e, f, h and i) are available by asking for them explicitly:" + R"( (lldb) frame variable my_foo.b my_foo.c my_foo.i -)" "The formatting option --raw on frame variable bypasses the filter, showing \ -all children of my_foo as if no filter was defined:" R"( +)" + "The formatting option --raw on frame variable bypasses the filter, showing \ +all children of my_foo as if no filter was defined:" + R"( -(lldb) frame variable my_foo --raw)" - ); - } +(lldb) frame variable my_foo --raw)"); + } - ~CommandObjectTypeFilterAdd() override = default; + ~CommandObjectTypeFilterAdd() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - const size_t argc = command.GetArgumentCount(); - - if (argc < 1) - { - result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - if (m_options.m_expr_paths.empty()) - { - result.AppendErrorWithFormat ("%s needs one or more children.\n", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - TypeFilterImplSP entry(new TypeFilterImpl(SyntheticChildren::Flags().SetCascades(m_options.m_cascade). - SetSkipPointers(m_options.m_skip_pointers). - SetSkipReferences(m_options.m_skip_references))); - - // go through the expression paths - CommandOptions::ExpressionPathsIterator begin, end = m_options.m_expr_paths.end(); - - for (begin = m_options.m_expr_paths.begin(); begin != end; begin++) - entry->AddExpressionPath(*begin); - - - // now I have a valid provider, let's add it to every type - - lldb::TypeCategoryImplSP category; - DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); - - Error error; - - WarnOnPotentialUnquotedUnsignedType(command, result); - - for (size_t i = 0; i < argc; i++) - { - const char* typeA = command.GetArgumentAtIndex(i); - ConstString typeCS(typeA); - if (typeCS) - { - if (!AddFilter(typeCS, - entry, - m_options.m_regex ? eRegexFilter : eRegularFilter, - m_options.m_category, - &error)) - { - result.AppendError(error.AsCString()); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - else - { - result.AppendError("empty typenames not allowed"); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); + bool DoExecute(Args &command, CommandReturnObject &result) override { + const size_t argc = command.GetArgumentCount(); + + if (argc < 1) { + result.AppendErrorWithFormat("%s takes one or more args.\n", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (m_options.m_expr_paths.empty()) { + result.AppendErrorWithFormat("%s needs one or more children.\n", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + TypeFilterImplSP entry(new TypeFilterImpl( + SyntheticChildren::Flags() + .SetCascades(m_options.m_cascade) + .SetSkipPointers(m_options.m_skip_pointers) + .SetSkipReferences(m_options.m_skip_references))); + + // go through the expression paths + CommandOptions::ExpressionPathsIterator begin, + end = m_options.m_expr_paths.end(); + + for (begin = m_options.m_expr_paths.begin(); begin != end; begin++) + entry->AddExpressionPath(*begin); + + // now I have a valid provider, let's add it to every type + + lldb::TypeCategoryImplSP category; + DataVisualization::Categories::GetCategory( + ConstString(m_options.m_category.c_str()), category); + + Error error; + + WarnOnPotentialUnquotedUnsignedType(command, result); + + for (size_t i = 0; i < argc; i++) { + const char *typeA = command.GetArgumentAtIndex(i); + ConstString typeCS(typeA); + if (typeCS) { + if (!AddFilter(typeCS, entry, + m_options.m_regex ? eRegexFilter : eRegularFilter, + m_options.m_category, &error)) { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + result.AppendError("empty typenames not allowed"); + result.SetStatus(eReturnStatusFailed); + return false; + } } + + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return result.Succeeded(); + } }; -OptionDefinition -CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] = + { + // clang-format off {LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, {LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, {LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, @@ -3237,484 +2793,466 @@ CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] = {LLDB_OPT_SET_ALL, false, "child", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpressionPath, "Include this expression path in the synthetic view."}, {LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //---------------------------------------------------------------------- // "type lookup" //---------------------------------------------------------------------- -class CommandObjectTypeLookup : public CommandObjectRaw -{ +class CommandObjectTypeLookup : public CommandObjectRaw { protected: - // this function is allowed to do a more aggressive job at guessing languages than the expression parser - // is comfortable with - so leave the original call alone and add one that is specific to type lookup - lldb::LanguageType - GuessLanguage (StackFrame *frame) - { - lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown; - - if (!frame) - return lang_type; - - lang_type = frame->GuessLanguage(); - if (lang_type != lldb::eLanguageTypeUnknown) - return lang_type; - - Symbol *s = frame->GetSymbolContext(eSymbolContextSymbol).symbol; - if (s) - lang_type = s->GetMangled().GuessLanguage(); - - return lang_type; - } - - class CommandOptions : public OptionGroup - { - public: - CommandOptions () : - OptionGroup(), - m_show_help(false), - m_language(eLanguageTypeUnknown) - {} - - ~CommandOptions() override = default; - - uint32_t - GetNumDefinitions () override - { - return 3; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } - - Error - SetOptionValue (uint32_t option_idx, - const char *option_value, - ExecutionContext *execution_context) override - { - Error error; - - const int short_option = g_option_table[option_idx].short_option; - - switch (short_option) - { - case 'h': - m_show_help = true; - break; - - case 'l': - m_language = Language::GetLanguageTypeFromString(option_value); - break; - - default: - error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_show_help = false; - m_language = eLanguageTypeUnknown; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - bool m_show_help; - lldb::LanguageType m_language; - }; - - OptionGroupOptions m_option_group; - CommandOptions m_command_options; - -public: - CommandObjectTypeLookup (CommandInterpreter &interpreter) : - CommandObjectRaw (interpreter, - "type lookup", - "Lookup types and declarations in the current target, following language-specific naming conventions.", - "type lookup <type-specifier>", - eCommandRequiresTarget), - m_option_group(), - m_command_options() - { - m_option_group.Append(&m_command_options); - m_option_group.Finalize(); - } + // this function is allowed to do a more aggressive job at guessing languages + // than the expression parser + // is comfortable with - so leave the original call alone and add one that is + // specific to type lookup + lldb::LanguageType GuessLanguage(StackFrame *frame) { + lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown; - ~CommandObjectTypeLookup() override = default; + if (!frame) + return lang_type; - Options * - GetOptions () override - { - return &m_option_group; + lang_type = frame->GuessLanguage(); + if (lang_type != lldb::eLanguageTypeUnknown) + return lang_type; + + Symbol *s = frame->GetSymbolContext(eSymbolContextSymbol).symbol; + if (s) + lang_type = s->GetMangled().GuessLanguage(); + + return lang_type; + } + + class CommandOptions : public OptionGroup { + public: + CommandOptions() + : OptionGroup(), m_show_help(false), m_language(eLanguageTypeUnknown) {} + + ~CommandOptions() override = default; + + uint32_t GetNumDefinitions() override { return 3; } + + const OptionDefinition *GetDefinitions() override { return g_option_table; } + + Error SetOptionValue(uint32_t option_idx, const char *option_value, + ExecutionContext *execution_context) override { + Error error; + + const int short_option = g_option_table[option_idx].short_option; + + switch (short_option) { + case 'h': + m_show_help = true; + break; + + case 'l': + m_language = Language::GetLanguageTypeFromString(option_value); + break; + + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", + short_option); + break; + } + + return error; } - - const char* - GetHelpLong () override - { - if (m_cmd_help_long.empty()) - { - StreamString stream; - // FIXME: hardcoding languages is not good - lldb::LanguageType languages[] = {eLanguageTypeObjC,eLanguageTypeC_plus_plus}; - - for(const auto lang_type : languages) - { - if (auto language = Language::FindPlugin(lang_type)) - { - if (const char* help = language->GetLanguageSpecificTypeLookupHelp()) - { - stream.Printf("%s\n", help); - } - } - } - - if (stream.GetData()) - m_cmd_help_long.assign(stream.GetString()); - } - return this->CommandObject::GetHelpLong(); + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_show_help = false; + m_language = eLanguageTypeUnknown; } - - bool - DoExecute (const char *raw_command_line, CommandReturnObject &result) override - { - if (!raw_command_line || !raw_command_line[0]) - { - result.SetError("type lookup cannot be invoked without a type name as argument"); - return false; - } - auto exe_ctx = GetCommandInterpreter().GetExecutionContext(); - m_option_group.NotifyOptionParsingStarting(&exe_ctx); - - const char * name_of_type = nullptr; - - if (raw_command_line[0] == '-') - { - // We have some options and these options MUST end with --. - const char *end_options = nullptr; - const char *s = raw_command_line; - while (s && s[0]) - { - end_options = ::strstr (s, "--"); - if (end_options) - { - end_options += 2; // Get past the "--" - if (::isspace (end_options[0])) - { - name_of_type = end_options; - while (::isspace (*name_of_type)) - ++name_of_type; - break; - } - } - s = end_options; - } - - if (end_options) - { - Args args (llvm::StringRef(raw_command_line, end_options - raw_command_line)); - if (!ParseOptions (args, result)) - return false; - - Error error(m_option_group.NotifyOptionParsingFinished( - &exe_ctx)); - if (error.Fail()) - { - result.AppendError (error.AsCString()); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - } - if (nullptr == name_of_type) - name_of_type = raw_command_line; - - // TargetSP target_sp(GetCommandInterpreter().GetDebugger().GetSelectedTarget()); - // const bool fill_all_in = true; - // ExecutionContext exe_ctx(target_sp.get(), fill_all_in); - ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope(); - - bool any_found = false; - - std::vector<Language*> languages; - - bool is_global_search = false; - LanguageType guessed_language = lldb::eLanguageTypeUnknown; - - if ( (is_global_search = (m_command_options.m_language == eLanguageTypeUnknown)) ) - { - // FIXME: hardcoding languages is not good - languages.push_back(Language::FindPlugin(eLanguageTypeObjC)); - languages.push_back(Language::FindPlugin(eLanguageTypeC_plus_plus)); - } - else - { - languages.push_back(Language::FindPlugin(m_command_options.m_language)); - } - - // This is not the most efficient way to do this, but we support very few languages - // so the cost of the sort is going to be dwarfed by the actual lookup anyway - if (StackFrame* frame = m_exe_ctx.GetFramePtr()) - { - guessed_language = GuessLanguage(frame); - if (guessed_language != eLanguageTypeUnknown) - { - std::sort(languages.begin(), - languages.end(), - [guessed_language] (Language* lang1, - Language* lang2) -> bool { - if (!lang1 || !lang2) return false; - LanguageType lt1 = lang1->GetLanguageType(); - LanguageType lt2 = lang2->GetLanguageType(); - if (lt1 == guessed_language) return true; // make the selected frame's language come first - if (lt2 == guessed_language) return false; // make the selected frame's language come first - return (lt1 < lt2); // normal comparison otherwise - }); - } - } - - bool is_first_language = true; - - for (Language* language : languages) - { - if (!language) - continue; - - if (auto scavenger = language->GetTypeScavenger()) - { - Language::TypeScavenger::ResultSet search_results; - if (scavenger->Find(best_scope, name_of_type, search_results) > 0) - { - for (const auto& search_result : search_results) - { - if (search_result && search_result->IsValid()) - { - any_found = true; - search_result->DumpToStream(result.GetOutputStream(), this->m_command_options.m_show_help); - } - } - } - } - // this is "type lookup SomeName" and we did find a match, so get out - if (any_found && is_global_search) - break; - else if (is_first_language && is_global_search && guessed_language != lldb::eLanguageTypeUnknown) - { - is_first_language = false; - result.GetOutputStream().Printf("no type was found in the current language %s matching '%s'; performing a global search across all languages\n", - Language::GetNameForLanguageType(guessed_language), - name_of_type); - } - } - - if (!any_found) - result.AppendMessageWithFormat("no type was found matching '%s'\n", name_of_type); - - result.SetStatus (any_found ? lldb::eReturnStatusSuccessFinishResult : lldb::eReturnStatusSuccessFinishNoResult); - return true; + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + bool m_show_help; + lldb::LanguageType m_language; + }; + + OptionGroupOptions m_option_group; + CommandOptions m_command_options; + +public: + CommandObjectTypeLookup(CommandInterpreter &interpreter) + : CommandObjectRaw(interpreter, "type lookup", + "Lookup types and declarations in the current target, " + "following language-specific naming conventions.", + "type lookup <type-specifier>", + eCommandRequiresTarget), + m_option_group(), m_command_options() { + m_option_group.Append(&m_command_options); + m_option_group.Finalize(); + } + + ~CommandObjectTypeLookup() override = default; + + Options *GetOptions() override { return &m_option_group; } + + const char *GetHelpLong() override { + if (m_cmd_help_long.empty()) { + StreamString stream; + // FIXME: hardcoding languages is not good + lldb::LanguageType languages[] = {eLanguageTypeObjC, + eLanguageTypeC_plus_plus}; + + for (const auto lang_type : languages) { + if (auto language = Language::FindPlugin(lang_type)) { + if (const char *help = + language->GetLanguageSpecificTypeLookupHelp()) { + stream.Printf("%s\n", help); + } + } + } + + if (stream.GetData()) + m_cmd_help_long.assign(stream.GetString()); + } + return this->CommandObject::GetHelpLong(); + } + + bool DoExecute(const char *raw_command_line, + CommandReturnObject &result) override { + if (!raw_command_line || !raw_command_line[0]) { + result.SetError( + "type lookup cannot be invoked without a type name as argument"); + return false; + } + + auto exe_ctx = GetCommandInterpreter().GetExecutionContext(); + m_option_group.NotifyOptionParsingStarting(&exe_ctx); + + const char *name_of_type = nullptr; + + if (raw_command_line[0] == '-') { + // We have some options and these options MUST end with --. + const char *end_options = nullptr; + const char *s = raw_command_line; + while (s && s[0]) { + end_options = ::strstr(s, "--"); + if (end_options) { + end_options += 2; // Get past the "--" + if (::isspace(end_options[0])) { + name_of_type = end_options; + while (::isspace(*name_of_type)) + ++name_of_type; + break; + } + } + s = end_options; + } + + if (end_options) { + Args args( + llvm::StringRef(raw_command_line, end_options - raw_command_line)); + if (!ParseOptions(args, result)) + return false; + + Error error(m_option_group.NotifyOptionParsingFinished(&exe_ctx)); + if (error.Fail()) { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + } + if (nullptr == name_of_type) + name_of_type = raw_command_line; + + // TargetSP + // target_sp(GetCommandInterpreter().GetDebugger().GetSelectedTarget()); + // const bool fill_all_in = true; + // ExecutionContext exe_ctx(target_sp.get(), fill_all_in); + ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope(); + + bool any_found = false; + + std::vector<Language *> languages; + + bool is_global_search = false; + LanguageType guessed_language = lldb::eLanguageTypeUnknown; + + if ((is_global_search = + (m_command_options.m_language == eLanguageTypeUnknown))) { + // FIXME: hardcoding languages is not good + languages.push_back(Language::FindPlugin(eLanguageTypeObjC)); + languages.push_back(Language::FindPlugin(eLanguageTypeC_plus_plus)); + } else { + languages.push_back(Language::FindPlugin(m_command_options.m_language)); + } + + // This is not the most efficient way to do this, but we support very few + // languages + // so the cost of the sort is going to be dwarfed by the actual lookup + // anyway + if (StackFrame *frame = m_exe_ctx.GetFramePtr()) { + guessed_language = GuessLanguage(frame); + if (guessed_language != eLanguageTypeUnknown) { + std::sort( + languages.begin(), languages.end(), + [guessed_language](Language *lang1, Language *lang2) -> bool { + if (!lang1 || !lang2) + return false; + LanguageType lt1 = lang1->GetLanguageType(); + LanguageType lt2 = lang2->GetLanguageType(); + if (lt1 == guessed_language) + return true; // make the selected frame's language come first + if (lt2 == guessed_language) + return false; // make the selected frame's language come first + return (lt1 < lt2); // normal comparison otherwise + }); + } } + + bool is_first_language = true; + + for (Language *language : languages) { + if (!language) + continue; + + if (auto scavenger = language->GetTypeScavenger()) { + Language::TypeScavenger::ResultSet search_results; + if (scavenger->Find(best_scope, name_of_type, search_results) > 0) { + for (const auto &search_result : search_results) { + if (search_result && search_result->IsValid()) { + any_found = true; + search_result->DumpToStream(result.GetOutputStream(), + this->m_command_options.m_show_help); + } + } + } + } + // this is "type lookup SomeName" and we did find a match, so get out + if (any_found && is_global_search) + break; + else if (is_first_language && is_global_search && + guessed_language != lldb::eLanguageTypeUnknown) { + is_first_language = false; + result.GetOutputStream().Printf( + "no type was found in the current language %s matching '%s'; " + "performing a global search across all languages\n", + Language::GetNameForLanguageType(guessed_language), name_of_type); + } + } + + if (!any_found) + result.AppendMessageWithFormat("no type was found matching '%s'\n", + name_of_type); + + result.SetStatus(any_found ? lldb::eReturnStatusSuccessFinishResult + : lldb::eReturnStatusSuccessFinishNoResult); + return true; + } }; -OptionDefinition -CommandObjectTypeLookup::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectTypeLookup::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_ALL, false, "show-help", 'h', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display available help for types"}, {LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Which language's types should the search scope be"}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } - // clang-format on + // clang-format on }; template <typename FormatterType> -class CommandObjectFormatterInfo : public CommandObjectRaw -{ +class CommandObjectFormatterInfo : public CommandObjectRaw { public: - typedef std::function<typename FormatterType::SharedPointer(ValueObject&)> DiscoveryFunction; - CommandObjectFormatterInfo (CommandInterpreter &interpreter, - const char* formatter_name, - DiscoveryFunction discovery_func) : - CommandObjectRaw(interpreter, - nullptr, - nullptr, - nullptr, - eCommandRequiresFrame), - m_formatter_name(formatter_name ? formatter_name : ""), - m_discovery_function(discovery_func) - { - StreamString name; - name.Printf("type %s info", formatter_name); - SetCommandName(name.GetData()); - StreamString help; - help.Printf("This command evaluates the provided expression and shows which %s is applied to the resulting value (if any).", formatter_name); - SetHelp(help.GetData()); - StreamString syntax; - syntax.Printf("type %s info <expr>", formatter_name); - SetSyntax(syntax.GetData()); - } - - ~CommandObjectFormatterInfo() override = default; + typedef std::function<typename FormatterType::SharedPointer(ValueObject &)> + DiscoveryFunction; + CommandObjectFormatterInfo(CommandInterpreter &interpreter, + const char *formatter_name, + DiscoveryFunction discovery_func) + : CommandObjectRaw(interpreter, nullptr, nullptr, nullptr, + eCommandRequiresFrame), + m_formatter_name(formatter_name ? formatter_name : ""), + m_discovery_function(discovery_func) { + StreamString name; + name.Printf("type %s info", formatter_name); + SetCommandName(name.GetData()); + StreamString help; + help.Printf("This command evaluates the provided expression and shows " + "which %s is applied to the resulting value (if any).", + formatter_name); + SetHelp(help.GetData()); + StreamString syntax; + syntax.Printf("type %s info <expr>", formatter_name); + SetSyntax(syntax.GetData()); + } + + ~CommandObjectFormatterInfo() override = default; protected: - bool - DoExecute (const char *command, CommandReturnObject &result) override - { - TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); - Thread *thread = GetDefaultThread(); - if (!thread) - { - result.AppendError("no default thread"); - result.SetStatus(lldb::eReturnStatusFailed); - return false; - } - - StackFrameSP frame_sp = thread->GetSelectedFrame(); - ValueObjectSP result_valobj_sp; - EvaluateExpressionOptions options; - lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(command, frame_sp.get(), result_valobj_sp, options); - if (expr_result == eExpressionCompleted && result_valobj_sp) - { - result_valobj_sp = result_valobj_sp->GetQualifiedRepresentationIfAvailable(target_sp->GetPreferDynamicValue(), target_sp->GetEnableSyntheticValue()); - typename FormatterType::SharedPointer formatter_sp = m_discovery_function(*result_valobj_sp); - if (formatter_sp) - { - std::string description(formatter_sp->GetDescription()); - result.AppendMessageWithFormat("%s applied to (%s) %s is: %s\n", - m_formatter_name.c_str(), - result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"), - command, - description.c_str()); - result.SetStatus(lldb::eReturnStatusSuccessFinishResult); - } - else - { - result.AppendMessageWithFormat("no %s applies to (%s) %s\n", - m_formatter_name.c_str(), - result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"), - command); - result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); - } - return true; - } - else - { - result.AppendError("failed to evaluate expression"); - result.SetStatus(lldb::eReturnStatusFailed); - return false; - } - } + bool DoExecute(const char *command, CommandReturnObject &result) override { + TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); + Thread *thread = GetDefaultThread(); + if (!thread) { + result.AppendError("no default thread"); + result.SetStatus(lldb::eReturnStatusFailed); + return false; + } + + StackFrameSP frame_sp = thread->GetSelectedFrame(); + ValueObjectSP result_valobj_sp; + EvaluateExpressionOptions options; + lldb::ExpressionResults expr_result = target_sp->EvaluateExpression( + command, frame_sp.get(), result_valobj_sp, options); + if (expr_result == eExpressionCompleted && result_valobj_sp) { + result_valobj_sp = + result_valobj_sp->GetQualifiedRepresentationIfAvailable( + target_sp->GetPreferDynamicValue(), + target_sp->GetEnableSyntheticValue()); + typename FormatterType::SharedPointer formatter_sp = + m_discovery_function(*result_valobj_sp); + if (formatter_sp) { + std::string description(formatter_sp->GetDescription()); + result.AppendMessageWithFormat( + "%s applied to (%s) %s is: %s\n", m_formatter_name.c_str(), + result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"), + command, description.c_str()); + result.SetStatus(lldb::eReturnStatusSuccessFinishResult); + } else { + result.AppendMessageWithFormat( + "no %s applies to (%s) %s\n", m_formatter_name.c_str(), + result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"), + command); + result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); + } + return true; + } else { + result.AppendError("failed to evaluate expression"); + result.SetStatus(lldb::eReturnStatusFailed); + return false; + } + } private: - std::string m_formatter_name; - DiscoveryFunction m_discovery_function; + std::string m_formatter_name; + DiscoveryFunction m_discovery_function; }; -class CommandObjectTypeFormat : public CommandObjectMultiword -{ +class CommandObjectTypeFormat : public CommandObjectMultiword { public: - CommandObjectTypeFormat(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "type format", "Commands for customizing value display formats.", - "type format [<sub-command-options>] ") - { - LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeFormatAdd (interpreter))); - LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeFormatClear (interpreter))); - LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFormatDelete (interpreter))); - LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeFormatList (interpreter))); - LoadSubCommand ("info", CommandObjectSP (new CommandObjectFormatterInfo<TypeFormatImpl>(interpreter, - "format", - [](ValueObject& valobj) -> TypeFormatImpl::SharedPointer { - return valobj.GetValueFormat(); - }))); - } - - ~CommandObjectTypeFormat() override = default; + CommandObjectTypeFormat(CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "type format", + "Commands for customizing value display formats.", + "type format [<sub-command-options>] ") { + LoadSubCommand( + "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter))); + LoadSubCommand("clear", CommandObjectSP( + new CommandObjectTypeFormatClear(interpreter))); + LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFormatDelete( + interpreter))); + LoadSubCommand( + "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter))); + LoadSubCommand( + "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeFormatImpl>( + interpreter, "format", + [](ValueObject &valobj) -> TypeFormatImpl::SharedPointer { + return valobj.GetValueFormat(); + }))); + } + + ~CommandObjectTypeFormat() override = default; }; #ifndef LLDB_DISABLE_PYTHON -class CommandObjectTypeSynth : public CommandObjectMultiword -{ +class CommandObjectTypeSynth : public CommandObjectMultiword { public: - CommandObjectTypeSynth(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "type synthetic", - "Commands for operating on synthetic type representations.", - "type synthetic [<sub-command-options>] ") - { - LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSynthAdd (interpreter))); - LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSynthClear (interpreter))); - LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSynthDelete (interpreter))); - LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSynthList (interpreter))); - LoadSubCommand ("info", CommandObjectSP (new CommandObjectFormatterInfo<SyntheticChildren>(interpreter, - "synthetic", - [](ValueObject& valobj) -> SyntheticChildren::SharedPointer { - return valobj.GetSyntheticChildren(); - }))); - } - - ~CommandObjectTypeSynth() override = default; + CommandObjectTypeSynth(CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "type synthetic", + "Commands for operating on synthetic type representations.", + "type synthetic [<sub-command-options>] ") { + LoadSubCommand("add", + CommandObjectSP(new CommandObjectTypeSynthAdd(interpreter))); + LoadSubCommand( + "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter))); + LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSynthDelete( + interpreter))); + LoadSubCommand( + "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter))); + LoadSubCommand( + "info", + CommandObjectSP(new CommandObjectFormatterInfo<SyntheticChildren>( + interpreter, "synthetic", + [](ValueObject &valobj) -> SyntheticChildren::SharedPointer { + return valobj.GetSyntheticChildren(); + }))); + } + + ~CommandObjectTypeSynth() override = default; }; #endif // LLDB_DISABLE_PYTHON -class CommandObjectTypeFilter : public CommandObjectMultiword -{ +class CommandObjectTypeFilter : public CommandObjectMultiword { public: - CommandObjectTypeFilter(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "type filter", "Commands for operating on type filters.", - "type synthetic [<sub-command-options>] ") - { - LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeFilterAdd (interpreter))); - LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeFilterClear (interpreter))); - LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFilterDelete (interpreter))); - LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeFilterList (interpreter))); - } - - ~CommandObjectTypeFilter() override = default; + CommandObjectTypeFilter(CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "type filter", + "Commands for operating on type filters.", + "type synthetic [<sub-command-options>] ") { + LoadSubCommand( + "add", CommandObjectSP(new CommandObjectTypeFilterAdd(interpreter))); + LoadSubCommand("clear", CommandObjectSP( + new CommandObjectTypeFilterClear(interpreter))); + LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFilterDelete( + interpreter))); + LoadSubCommand( + "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter))); + } + + ~CommandObjectTypeFilter() override = default; }; -class CommandObjectTypeCategory : public CommandObjectMultiword -{ +class CommandObjectTypeCategory : public CommandObjectMultiword { public: - CommandObjectTypeCategory(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "type category", "Commands for operating on type categories.", - "type category [<sub-command-options>] ") - { - LoadSubCommand ("define", CommandObjectSP (new CommandObjectTypeCategoryDefine (interpreter))); - LoadSubCommand ("enable", CommandObjectSP (new CommandObjectTypeCategoryEnable (interpreter))); - LoadSubCommand ("disable", CommandObjectSP (new CommandObjectTypeCategoryDisable (interpreter))); - LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeCategoryDelete (interpreter))); - LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeCategoryList (interpreter))); - } - - ~CommandObjectTypeCategory() override = default; + CommandObjectTypeCategory(CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "type category", + "Commands for operating on type categories.", + "type category [<sub-command-options>] ") { + LoadSubCommand( + "define", + CommandObjectSP(new CommandObjectTypeCategoryDefine(interpreter))); + LoadSubCommand( + "enable", + CommandObjectSP(new CommandObjectTypeCategoryEnable(interpreter))); + LoadSubCommand( + "disable", + CommandObjectSP(new CommandObjectTypeCategoryDisable(interpreter))); + LoadSubCommand( + "delete", + CommandObjectSP(new CommandObjectTypeCategoryDelete(interpreter))); + LoadSubCommand("list", CommandObjectSP( + new CommandObjectTypeCategoryList(interpreter))); + } + + ~CommandObjectTypeCategory() override = default; }; -class CommandObjectTypeSummary : public CommandObjectMultiword -{ +class CommandObjectTypeSummary : public CommandObjectMultiword { public: - CommandObjectTypeSummary(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "type summary", "Commands for editing variable summary display options.", - "type summary [<sub-command-options>] ") - { - LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter))); - LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter))); - LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter))); - LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSummaryList (interpreter))); - LoadSubCommand ("info", CommandObjectSP (new CommandObjectFormatterInfo<TypeSummaryImpl>(interpreter, - "summary", - [](ValueObject& valobj) -> TypeSummaryImpl::SharedPointer { - return valobj.GetSummaryFormat(); - }))); - } - - ~CommandObjectTypeSummary() override = default; + CommandObjectTypeSummary(CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "type summary", + "Commands for editing variable summary display options.", + "type summary [<sub-command-options>] ") { + LoadSubCommand( + "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter))); + LoadSubCommand("clear", CommandObjectSP(new CommandObjectTypeSummaryClear( + interpreter))); + LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSummaryDelete( + interpreter))); + LoadSubCommand( + "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter))); + LoadSubCommand( + "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeSummaryImpl>( + interpreter, "summary", + [](ValueObject &valobj) -> TypeSummaryImpl::SharedPointer { + return valobj.GetSummaryFormat(); + }))); + } + + ~CommandObjectTypeSummary() override = default; }; //------------------------------------------------------------------------- @@ -3722,17 +3260,23 @@ public: //------------------------------------------------------------------------- CommandObjectType::CommandObjectType(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "type", "Commands for operating on the type system.", - "type [<sub-command-options>]") -{ - LoadSubCommand ("category", CommandObjectSP (new CommandObjectTypeCategory (interpreter))); - LoadSubCommand ("filter", CommandObjectSP (new CommandObjectTypeFilter (interpreter))); - LoadSubCommand ("format", CommandObjectSP (new CommandObjectTypeFormat (interpreter))); - LoadSubCommand ("summary", CommandObjectSP (new CommandObjectTypeSummary (interpreter))); + : CommandObjectMultiword(interpreter, "type", + "Commands for operating on the type system.", + "type [<sub-command-options>]") { + LoadSubCommand("category", + CommandObjectSP(new CommandObjectTypeCategory(interpreter))); + LoadSubCommand("filter", + CommandObjectSP(new CommandObjectTypeFilter(interpreter))); + LoadSubCommand("format", + CommandObjectSP(new CommandObjectTypeFormat(interpreter))); + LoadSubCommand("summary", + CommandObjectSP(new CommandObjectTypeSummary(interpreter))); #ifndef LLDB_DISABLE_PYTHON - LoadSubCommand ("synthetic", CommandObjectSP (new CommandObjectTypeSynth (interpreter))); + LoadSubCommand("synthetic", + CommandObjectSP(new CommandObjectTypeSynth(interpreter))); #endif // LLDB_DISABLE_PYTHON - LoadSubCommand ("lookup", CommandObjectSP (new CommandObjectTypeLookup (interpreter))); + LoadSubCommand("lookup", + CommandObjectSP(new CommandObjectTypeLookup(interpreter))); } CommandObjectType::~CommandObjectType() = default; diff --git a/lldb/source/Commands/CommandObjectType.h b/lldb/source/Commands/CommandObjectType.h index 54f4a33..f2f9ce7 100644 --- a/lldb/source/Commands/CommandObjectType.h +++ b/lldb/source/Commands/CommandObjectType.h @@ -16,18 +16,17 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-types.h" #include "lldb/Interpreter/CommandObjectMultiword.h" #include "lldb/Interpreter/Options.h" +#include "lldb/lldb-types.h" namespace lldb_private { -class CommandObjectType : public CommandObjectMultiword -{ +class CommandObjectType : public CommandObjectMultiword { public: - CommandObjectType (CommandInterpreter &interpreter); + CommandObjectType(CommandInterpreter &interpreter); - ~CommandObjectType() override; + ~CommandObjectType() override; }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectVersion.cpp b/lldb/source/Commands/CommandObjectVersion.cpp index 06962f86..8b1f25bf 100644 --- a/lldb/source/Commands/CommandObjectVersion.cpp +++ b/lldb/source/Commands/CommandObjectVersion.cpp @@ -13,9 +13,9 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/lldb-private.h" using namespace lldb; using namespace lldb_private; @@ -25,27 +25,18 @@ using namespace lldb_private; //------------------------------------------------------------------------- CommandObjectVersion::CommandObjectVersion(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "version", "Show the LLDB debugger version.", "version") -{ -} - -CommandObjectVersion::~CommandObjectVersion () -{ + : CommandObjectParsed(interpreter, "version", + "Show the LLDB debugger version.", "version") {} + +CommandObjectVersion::~CommandObjectVersion() {} + +bool CommandObjectVersion::DoExecute(Args &args, CommandReturnObject &result) { + if (args.GetArgumentCount() == 0) { + result.AppendMessageWithFormat("%s\n", lldb_private::GetVersion()); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendError("the version command takes no arguments."); + result.SetStatus(eReturnStatusFailed); + } + return true; } - -bool -CommandObjectVersion::DoExecute (Args& args, CommandReturnObject &result) -{ - if (args.GetArgumentCount() == 0) - { - result.AppendMessageWithFormat ("%s\n", lldb_private::GetVersion()); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendError("the version command takes no arguments."); - result.SetStatus (eReturnStatusFailed); - } - return true; -} - diff --git a/lldb/source/Commands/CommandObjectVersion.h b/lldb/source/Commands/CommandObjectVersion.h index 30ba9d1..5f661cc 100644 --- a/lldb/source/Commands/CommandObjectVersion.h +++ b/lldb/source/Commands/CommandObjectVersion.h @@ -22,18 +22,14 @@ namespace lldb_private { // CommandObjectVersion //------------------------------------------------------------------------- -class CommandObjectVersion : public CommandObjectParsed -{ +class CommandObjectVersion : public CommandObjectParsed { public: + CommandObjectVersion(CommandInterpreter &interpreter); - CommandObjectVersion (CommandInterpreter &interpreter); - - ~CommandObjectVersion() override; + ~CommandObjectVersion() override; protected: - bool - DoExecute(Args& args, - CommandReturnObject &result) override; + bool DoExecute(Args &args, CommandReturnObject &result) override; }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectWatchpoint.cpp b/lldb/source/Commands/CommandObjectWatchpoint.cpp index b4c5639..7ff4cce 100644 --- a/lldb/source/Commands/CommandObjectWatchpoint.cpp +++ b/lldb/source/Commands/CommandObjectWatchpoint.cpp @@ -24,9 +24,9 @@ #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectVariable.h" #include "lldb/Host/StringConvert.h" +#include "lldb/Interpreter/CommandCompletions.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Interpreter/CommandCompletions.h" #include "lldb/Symbol/Variable.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/StackFrame.h" @@ -35,126 +35,118 @@ using namespace lldb; using namespace lldb_private; -static void -AddWatchpointDescription(Stream *s, Watchpoint *wp, lldb::DescriptionLevel level) -{ - s->IndentMore(); - wp->GetDescription(s, level); - s->IndentLess(); - s->EOL(); +static void AddWatchpointDescription(Stream *s, Watchpoint *wp, + lldb::DescriptionLevel level) { + s->IndentMore(); + wp->GetDescription(s, level); + s->IndentLess(); + s->EOL(); } -static bool -CheckTargetForWatchpointOperations(Target *target, CommandReturnObject &result) -{ - if (target == nullptr) - { - result.AppendError ("Invalid target. No existing target or watchpoints."); - result.SetStatus (eReturnStatusFailed); - return false; - } - 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.SetStatus (eReturnStatusFailed); - return false; - } - // Target passes our checks, return true. - return true; +static bool CheckTargetForWatchpointOperations(Target *target, + CommandReturnObject &result) { + if (target == nullptr) { + result.AppendError("Invalid target. No existing target or watchpoints."); + result.SetStatus(eReturnStatusFailed); + return false; + } + 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.SetStatus(eReturnStatusFailed); + return false; + } + // Target passes our checks, return true. + return true; } // Equivalent class: {"-", "to", "To", "TO"} of range specifier array. -static const char* RSA[4] = { "-", "to", "To", "TO" }; +static const char *RSA[4] = {"-", "to", "To", "TO"}; // Return the index to RSA if found; otherwise -1 is returned. -static int32_t -WithRSAIndex(llvm::StringRef &Arg) -{ - - uint32_t i; - for (i = 0; i < 4; ++i) - if (Arg.find(RSA[i]) != llvm::StringRef::npos) - return i; - return -1; +static int32_t WithRSAIndex(llvm::StringRef &Arg) { + + uint32_t i; + for (i = 0; i < 4; ++i) + if (Arg.find(RSA[i]) != llvm::StringRef::npos) + return i; + return -1; } // Return true if wp_ids is successfully populated with the watch ids. // False otherwise. -bool -CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(Target *target, Args &args, std::vector<uint32_t> &wp_ids) -{ - // Pre-condition: args.GetArgumentCount() > 0. - if (args.GetArgumentCount() == 0) - { - if (target == nullptr) - return false; - WatchpointSP watch_sp = target->GetLastCreatedWatchpoint(); - if (watch_sp) - { - wp_ids.push_back(watch_sp->GetID()); - return true; - } - else - return false; - } - - llvm::StringRef Minus("-"); - std::vector<llvm::StringRef> StrRefArgs; - std::pair<llvm::StringRef, llvm::StringRef> Pair; - size_t i; - int32_t idx; - // Go through the arguments and make a canonical form of arg list containing - // only numbers with possible "-" in between. - for (i = 0; i < args.GetArgumentCount(); ++i) { - llvm::StringRef Arg(args.GetArgumentAtIndex(i)); - if ((idx = WithRSAIndex(Arg)) == -1) { - StrRefArgs.push_back(Arg); - continue; - } - // The Arg contains the range specifier, split it, then. - Pair = Arg.split(RSA[idx]); - if (!Pair.first.empty()) - StrRefArgs.push_back(Pair.first); - StrRefArgs.push_back(Minus); - if (!Pair.second.empty()) - StrRefArgs.push_back(Pair.second); +bool CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( + Target *target, Args &args, std::vector<uint32_t> &wp_ids) { + // Pre-condition: args.GetArgumentCount() > 0. + if (args.GetArgumentCount() == 0) { + if (target == nullptr) + return false; + WatchpointSP watch_sp = target->GetLastCreatedWatchpoint(); + if (watch_sp) { + wp_ids.push_back(watch_sp->GetID()); + return true; + } else + return false; + } + + llvm::StringRef Minus("-"); + std::vector<llvm::StringRef> StrRefArgs; + std::pair<llvm::StringRef, llvm::StringRef> Pair; + size_t i; + int32_t idx; + // Go through the arguments and make a canonical form of arg list containing + // only numbers with possible "-" in between. + for (i = 0; i < args.GetArgumentCount(); ++i) { + llvm::StringRef Arg(args.GetArgumentAtIndex(i)); + if ((idx = WithRSAIndex(Arg)) == -1) { + StrRefArgs.push_back(Arg); + continue; } - // Now process the canonical list and fill in the vector of uint32_t's. - // If there is any error, return false and the client should ignore wp_ids. - uint32_t beg, end, id; - size_t size = StrRefArgs.size(); - bool in_range = false; - for (i = 0; i < size; ++i) { - llvm::StringRef Arg = StrRefArgs[i]; - if (in_range) { - // Look for the 'end' of the range. Note StringRef::getAsInteger() - // returns true to signify error while parsing. - if (Arg.getAsInteger(0, end)) - return false; - // Found a range! Now append the elements. - for (id = beg; id <= end; ++id) - wp_ids.push_back(id); - in_range = false; - continue; - } - if (i < (size - 1) && StrRefArgs[i+1] == Minus) { - if (Arg.getAsInteger(0, beg)) - return false; - // Turn on the in_range flag, we are looking for end of range next. - ++i; in_range = true; - continue; - } - // Otherwise, we have a simple ID. Just append it. - if (Arg.getAsInteger(0, beg)) - return false; - wp_ids.push_back(beg); + // The Arg contains the range specifier, split it, then. + Pair = Arg.split(RSA[idx]); + if (!Pair.first.empty()) + StrRefArgs.push_back(Pair.first); + StrRefArgs.push_back(Minus); + if (!Pair.second.empty()) + StrRefArgs.push_back(Pair.second); + } + // Now process the canonical list and fill in the vector of uint32_t's. + // If there is any error, return false and the client should ignore wp_ids. + uint32_t beg, end, id; + size_t size = StrRefArgs.size(); + bool in_range = false; + for (i = 0; i < size; ++i) { + llvm::StringRef Arg = StrRefArgs[i]; + if (in_range) { + // Look for the 'end' of the range. Note StringRef::getAsInteger() + // returns true to signify error while parsing. + if (Arg.getAsInteger(0, end)) + return false; + // Found a range! Now append the elements. + for (id = beg; id <= end; ++id) + wp_ids.push_back(id); + in_range = false; + continue; } - // It is an error if after the loop, we're still in_range. - if (in_range) + if (i < (size - 1) && StrRefArgs[i + 1] == Minus) { + if (Arg.getAsInteger(0, beg)) return false; - - return true; // Success! + // Turn on the in_range flag, we are looking for end of range next. + ++i; + in_range = true; + continue; + } + // Otherwise, we have a simple ID. Just append it. + if (Arg.getAsInteger(0, beg)) + return false; + wp_ids.push_back(beg); + } + // It is an error if after the loop, we're still in_range. + if (in_range) + return false; + + return true; // Success! } //------------------------------------------------------------------------- @@ -162,162 +154,140 @@ CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(Target *target, Args &args //------------------------------------------------------------------------- #pragma mark List -class CommandObjectWatchpointList : public CommandObjectParsed -{ +class CommandObjectWatchpointList : public CommandObjectParsed { public: - CommandObjectWatchpointList (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "watchpoint list", - "List all watchpoints at configurable levels of detail.", - nullptr), - m_options() - { - CommandArgumentEntry arg; - CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); - // Add the entry for the first argument for this command to the object's arguments vector. - m_arguments.push_back(arg); + CommandObjectWatchpointList(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "watchpoint list", + "List all watchpoints at configurable levels of detail.", nullptr), + m_options() { + CommandArgumentEntry arg; + CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, + eArgTypeWatchpointIDRange); + // Add the entry for the first argument for this command to the object's + // arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectWatchpointList() override = default; + + Options *GetOptions() override { return &m_options; } + + class CommandOptions : public Options { + public: + CommandOptions() + : Options(), + m_level(lldb::eDescriptionLevelBrief) // Watchpoint List defaults to + // brief descriptions + {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'b': + m_level = lldb::eDescriptionLevelBrief; + break; + case 'f': + m_level = lldb::eDescriptionLevelFull; + break; + case 'v': + m_level = lldb::eDescriptionLevelVerbose; + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; } - ~CommandObjectWatchpointList() override = default; - - Options * - GetOptions () override - { - return &m_options; + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_level = lldb::eDescriptionLevelFull; } - class CommandOptions : public Options - { - public: - CommandOptions() : - Options(), - m_level(lldb::eDescriptionLevelBrief) // Watchpoint List defaults to brief descriptions - { - } - - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'b': - m_level = lldb::eDescriptionLevelBrief; - break; - case 'f': - m_level = lldb::eDescriptionLevelFull; - break; - case 'v': - m_level = lldb::eDescriptionLevelVerbose; - break; - default: - error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_level = lldb::eDescriptionLevelFull; - } - - const OptionDefinition * - GetDefinitions () override - { - return g_option_table; - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } - // Options table: Required for subclasses of Options. + // Options table: Required for subclasses of Options. - static OptionDefinition g_option_table[]; + static OptionDefinition g_option_table[]; - // Instance variables to hold the values for command options. + // Instance variables to hold the values for command options. - lldb::DescriptionLevel m_level; - }; + lldb::DescriptionLevel m_level; + }; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) - { - result.AppendError ("Invalid target. No current target or watchpoints."); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - return true; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (target == nullptr) { + result.AppendError("Invalid target. No current target or watchpoints."); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return true; + } - if (target->GetProcessSP() && target->GetProcessSP()->IsAlive()) - { - uint32_t num_supported_hardware_watchpoints; - Error error = target->GetProcessSP()->GetWatchpointSupportInfo(num_supported_hardware_watchpoints); - if (error.Success()) - result.AppendMessageWithFormat("Number of supported hardware watchpoints: %u\n", - num_supported_hardware_watchpoints); - } + if (target->GetProcessSP() && target->GetProcessSP()->IsAlive()) { + uint32_t num_supported_hardware_watchpoints; + Error error = target->GetProcessSP()->GetWatchpointSupportInfo( + num_supported_hardware_watchpoints); + if (error.Success()) + result.AppendMessageWithFormat( + "Number of supported hardware watchpoints: %u\n", + num_supported_hardware_watchpoints); + } - const WatchpointList &watchpoints = target->GetWatchpointList(); + const WatchpointList &watchpoints = target->GetWatchpointList(); - std::unique_lock<std::recursive_mutex> lock; - target->GetWatchpointList().GetListMutex(lock); + std::unique_lock<std::recursive_mutex> lock; + target->GetWatchpointList().GetListMutex(lock); - size_t num_watchpoints = watchpoints.GetSize(); + size_t num_watchpoints = watchpoints.GetSize(); - if (num_watchpoints == 0) - { - result.AppendMessage("No watchpoints currently set."); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; - } + if (num_watchpoints == 0) { + result.AppendMessage("No watchpoints currently set."); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return true; + } - Stream &output_stream = result.GetOutputStream(); - - if (command.GetArgumentCount() == 0) - { - // No watchpoint selected; show info about all currently set watchpoints. - result.AppendMessage ("Current watchpoints:"); - for (size_t i = 0; i < num_watchpoints; ++i) - { - Watchpoint *wp = watchpoints.GetByIndex(i).get(); - AddWatchpointDescription(&output_stream, wp, m_options.m_level); - } - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } - else - { - // Particular watchpoints selected; enable them. - std::vector<uint32_t> wp_ids; - if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids)) - { - result.AppendError("Invalid watchpoints specification."); - result.SetStatus(eReturnStatusFailed); - return false; - } - - const size_t size = wp_ids.size(); - for (size_t i = 0; i < size; ++i) - { - Watchpoint *wp = watchpoints.FindByID(wp_ids[i]).get(); - if (wp) - AddWatchpointDescription(&output_stream, wp, m_options.m_level); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } - } + Stream &output_stream = result.GetOutputStream(); + + if (command.GetArgumentCount() == 0) { + // No watchpoint selected; show info about all currently set watchpoints. + result.AppendMessage("Current watchpoints:"); + for (size_t i = 0; i < num_watchpoints; ++i) { + Watchpoint *wp = watchpoints.GetByIndex(i).get(); + AddWatchpointDescription(&output_stream, wp, m_options.m_level); + } + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + // Particular watchpoints selected; enable them. + std::vector<uint32_t> wp_ids; + if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( + target, command, wp_ids)) { + result.AppendError("Invalid watchpoints specification."); + result.SetStatus(eReturnStatusFailed); + return false; + } - return result.Succeeded(); + const size_t size = wp_ids.size(); + for (size_t i = 0; i < size; ++i) { + Watchpoint *wp = watchpoints.FindByID(wp_ids[i]).get(); + if (wp) + AddWatchpointDescription(&output_stream, wp, m_options.m_level); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } } + return result.Succeeded(); + } + private: - CommandOptions m_options; + CommandOptions m_options; }; //------------------------------------------------------------------------- @@ -325,15 +295,14 @@ private: //------------------------------------------------------------------------- #pragma mark List::CommandOptions -OptionDefinition -CommandObjectWatchpointList::CommandOptions::g_option_table[] = -{ - // clang-format off +OptionDefinition CommandObjectWatchpointList::CommandOptions::g_option_table[] = + { + // clang-format off {LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a brief description of the watchpoint (no location info)."}, {LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a full description of the watchpoint and its locations."}, {LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Explain everything we know about the watchpoint (for debugging debugger bugs)."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- @@ -341,75 +310,70 @@ CommandObjectWatchpointList::CommandOptions::g_option_table[] = //------------------------------------------------------------------------- #pragma mark Enable -class CommandObjectWatchpointEnable : public CommandObjectParsed -{ +class CommandObjectWatchpointEnable : public CommandObjectParsed { public: - CommandObjectWatchpointEnable (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "enable", - "Enable the specified disabled watchpoint(s). If no watchpoints are specified, enable all of them.", - nullptr) - { - CommandArgumentEntry arg; - CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); - // Add the entry for the first argument for this command to the object's arguments vector. - m_arguments.push_back(arg); - } - - ~CommandObjectWatchpointEnable() override = default; + CommandObjectWatchpointEnable(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "enable", + "Enable the specified disabled watchpoint(s). If " + "no watchpoints are specified, enable all of them.", + nullptr) { + CommandArgumentEntry arg; + CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, + eArgTypeWatchpointIDRange); + // Add the entry for the first argument for this command to the object's + // arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectWatchpointEnable() override = default; protected: - bool - DoExecute (Args& command, - CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (!CheckTargetForWatchpointOperations(target, result)) - return false; + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (!CheckTargetForWatchpointOperations(target, result)) + return false; - std::unique_lock<std::recursive_mutex> lock; - target->GetWatchpointList().GetListMutex(lock); + std::unique_lock<std::recursive_mutex> lock; + target->GetWatchpointList().GetListMutex(lock); - const WatchpointList &watchpoints = target->GetWatchpointList(); + const WatchpointList &watchpoints = target->GetWatchpointList(); - size_t num_watchpoints = watchpoints.GetSize(); + size_t num_watchpoints = watchpoints.GetSize(); - if (num_watchpoints == 0) - { - result.AppendError("No watchpoints exist to be enabled."); - result.SetStatus(eReturnStatusFailed); - return false; - } - - if (command.GetArgumentCount() == 0) - { - // No watchpoint selected; enable all currently set watchpoints. - target->EnableAllWatchpoints(); - result.AppendMessageWithFormat("All watchpoints enabled. (%" PRIu64 " watchpoints)\n", (uint64_t)num_watchpoints); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } - else - { - // Particular watchpoints selected; enable them. - std::vector<uint32_t> wp_ids; - if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids)) - { - result.AppendError("Invalid watchpoints specification."); - result.SetStatus(eReturnStatusFailed); - return false; - } - - int count = 0; - const size_t size = wp_ids.size(); - for (size_t i = 0; i < size; ++i) - if (target->EnableWatchpointByID(wp_ids[i])) - ++count; - result.AppendMessageWithFormat("%d watchpoints enabled.\n", count); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } + if (num_watchpoints == 0) { + result.AppendError("No watchpoints exist to be enabled."); + result.SetStatus(eReturnStatusFailed); + return false; + } - return result.Succeeded(); + if (command.GetArgumentCount() == 0) { + // No watchpoint selected; enable all currently set watchpoints. + target->EnableAllWatchpoints(); + result.AppendMessageWithFormat("All watchpoints enabled. (%" PRIu64 + " watchpoints)\n", + (uint64_t)num_watchpoints); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + // Particular watchpoints selected; enable them. + std::vector<uint32_t> wp_ids; + if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( + target, command, wp_ids)) { + result.AppendError("Invalid watchpoints specification."); + result.SetStatus(eReturnStatusFailed); + return false; + } + + int count = 0; + const size_t size = wp_ids.size(); + for (size_t i = 0; i < size; ++i) + if (target->EnableWatchpointByID(wp_ids[i])) + ++count; + result.AppendMessageWithFormat("%d watchpoints enabled.\n", count); + result.SetStatus(eReturnStatusSuccessFinishNoResult); } + + return result.Succeeded(); + } }; //------------------------------------------------------------------------- @@ -417,80 +381,74 @@ protected: //------------------------------------------------------------------------- #pragma mark Disable -class CommandObjectWatchpointDisable : public CommandObjectParsed -{ +class CommandObjectWatchpointDisable : public CommandObjectParsed { public: - CommandObjectWatchpointDisable (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "watchpoint disable", - "Disable the specified watchpoint(s) without removing it/them. If no watchpoints are specified, disable them all.", - nullptr) - { - CommandArgumentEntry arg; - CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); - // Add the entry for the first argument for this command to the object's arguments vector. - m_arguments.push_back(arg); - } - - ~CommandObjectWatchpointDisable() override = default; + CommandObjectWatchpointDisable(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "watchpoint disable", + "Disable the specified watchpoint(s) without " + "removing it/them. If no watchpoints are " + "specified, disable them all.", + nullptr) { + CommandArgumentEntry arg; + CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, + eArgTypeWatchpointIDRange); + // Add the entry for the first argument for this command to the object's + // arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectWatchpointDisable() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (!CheckTargetForWatchpointOperations(target, result)) - return false; + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (!CheckTargetForWatchpointOperations(target, result)) + return false; - std::unique_lock<std::recursive_mutex> lock; - target->GetWatchpointList().GetListMutex(lock); + std::unique_lock<std::recursive_mutex> lock; + target->GetWatchpointList().GetListMutex(lock); - const WatchpointList &watchpoints = target->GetWatchpointList(); - size_t num_watchpoints = watchpoints.GetSize(); + const WatchpointList &watchpoints = target->GetWatchpointList(); + size_t num_watchpoints = watchpoints.GetSize(); - if (num_watchpoints == 0) - { - result.AppendError("No watchpoints exist to be disabled."); - result.SetStatus(eReturnStatusFailed); - return false; - } - - if (command.GetArgumentCount() == 0) - { - // No watchpoint selected; disable all currently set watchpoints. - if (target->DisableAllWatchpoints()) - { - result.AppendMessageWithFormat("All watchpoints disabled. (%" PRIu64 " watchpoints)\n", (uint64_t)num_watchpoints); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendError("Disable all watchpoints failed\n"); - result.SetStatus(eReturnStatusFailed); - } - } - else - { - // Particular watchpoints selected; disable them. - std::vector<uint32_t> wp_ids; - if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids)) - { - result.AppendError("Invalid watchpoints specification."); - result.SetStatus(eReturnStatusFailed); - return false; - } - - int count = 0; - const size_t size = wp_ids.size(); - for (size_t i = 0; i < size; ++i) - if (target->DisableWatchpointByID(wp_ids[i])) - ++count; - result.AppendMessageWithFormat("%d watchpoints disabled.\n", count); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } + if (num_watchpoints == 0) { + result.AppendError("No watchpoints exist to be disabled."); + result.SetStatus(eReturnStatusFailed); + return false; + } - return result.Succeeded(); + if (command.GetArgumentCount() == 0) { + // No watchpoint selected; disable all currently set watchpoints. + if (target->DisableAllWatchpoints()) { + result.AppendMessageWithFormat("All watchpoints disabled. (%" PRIu64 + " watchpoints)\n", + (uint64_t)num_watchpoints); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + result.AppendError("Disable all watchpoints failed\n"); + result.SetStatus(eReturnStatusFailed); + } + } else { + // Particular watchpoints selected; disable them. + std::vector<uint32_t> wp_ids; + if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( + target, command, wp_ids)) { + result.AppendError("Invalid watchpoints specification."); + result.SetStatus(eReturnStatusFailed); + return false; + } + + int count = 0; + const size_t size = wp_ids.size(); + for (size_t i = 0; i < size; ++i) + if (target->DisableWatchpointByID(wp_ids[i])) + ++count; + result.AppendMessageWithFormat("%d watchpoints disabled.\n", count); + result.SetStatus(eReturnStatusSuccessFinishNoResult); } + + return result.Succeeded(); + } }; //------------------------------------------------------------------------- @@ -498,229 +456,202 @@ protected: //------------------------------------------------------------------------- #pragma mark Delete -class CommandObjectWatchpointDelete : public CommandObjectParsed -{ +class CommandObjectWatchpointDelete : public CommandObjectParsed { public: - CommandObjectWatchpointDelete (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "watchpoint delete", - "Delete the specified watchpoint(s). If no watchpoints are specified, delete them all.", - nullptr) - { - CommandArgumentEntry arg; - CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); - // Add the entry for the first argument for this command to the object's arguments vector. - m_arguments.push_back(arg); - } - - ~CommandObjectWatchpointDelete() override = default; + CommandObjectWatchpointDelete(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "watchpoint delete", + "Delete the specified watchpoint(s). If no " + "watchpoints are specified, delete them all.", + nullptr) { + CommandArgumentEntry arg; + CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, + eArgTypeWatchpointIDRange); + // Add the entry for the first argument for this command to the object's + // arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectWatchpointDelete() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (!CheckTargetForWatchpointOperations(target, result)) - return false; - - std::unique_lock<std::recursive_mutex> lock; - target->GetWatchpointList().GetListMutex(lock); + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (!CheckTargetForWatchpointOperations(target, result)) + return false; - const WatchpointList &watchpoints = target->GetWatchpointList(); + std::unique_lock<std::recursive_mutex> lock; + target->GetWatchpointList().GetListMutex(lock); - size_t num_watchpoints = watchpoints.GetSize(); + const WatchpointList &watchpoints = target->GetWatchpointList(); - if (num_watchpoints == 0) - { - result.AppendError("No watchpoints exist to be deleted."); - result.SetStatus(eReturnStatusFailed); - return false; - } + size_t num_watchpoints = watchpoints.GetSize(); - if (command.GetArgumentCount() == 0) - { - if (!m_interpreter.Confirm("About to delete all watchpoints, do you want to do that?", true)) - { - result.AppendMessage("Operation cancelled..."); - } - else - { - target->RemoveAllWatchpoints(); - result.AppendMessageWithFormat("All watchpoints removed. (%" PRIu64 " watchpoints)\n", (uint64_t)num_watchpoints); - } - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - // Particular watchpoints selected; delete them. - std::vector<uint32_t> wp_ids; - if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids)) - { - result.AppendError("Invalid watchpoints specification."); - result.SetStatus(eReturnStatusFailed); - return false; - } - - int count = 0; - const size_t size = wp_ids.size(); - for (size_t i = 0; i < size; ++i) - if (target->RemoveWatchpointByID(wp_ids[i])) - ++count; - result.AppendMessageWithFormat("%d watchpoints deleted.\n",count); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } + if (num_watchpoints == 0) { + result.AppendError("No watchpoints exist to be deleted."); + result.SetStatus(eReturnStatusFailed); + return false; + } - return result.Succeeded(); + if (command.GetArgumentCount() == 0) { + if (!m_interpreter.Confirm( + "About to delete all watchpoints, do you want to do that?", + true)) { + result.AppendMessage("Operation cancelled..."); + } else { + target->RemoveAllWatchpoints(); + result.AppendMessageWithFormat("All watchpoints removed. (%" PRIu64 + " watchpoints)\n", + (uint64_t)num_watchpoints); + } + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + // Particular watchpoints selected; delete them. + std::vector<uint32_t> wp_ids; + if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( + target, command, wp_ids)) { + result.AppendError("Invalid watchpoints specification."); + result.SetStatus(eReturnStatusFailed); + return false; + } + + int count = 0; + const size_t size = wp_ids.size(); + for (size_t i = 0; i < size; ++i) + if (target->RemoveWatchpointByID(wp_ids[i])) + ++count; + result.AppendMessageWithFormat("%d watchpoints deleted.\n", count); + result.SetStatus(eReturnStatusSuccessFinishNoResult); } + + return result.Succeeded(); + } }; //------------------------------------------------------------------------- // CommandObjectWatchpointIgnore //------------------------------------------------------------------------- -class CommandObjectWatchpointIgnore : public CommandObjectParsed -{ +class CommandObjectWatchpointIgnore : public CommandObjectParsed { public: - CommandObjectWatchpointIgnore (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "watchpoint ignore", - "Set ignore count on the specified watchpoint(s). If no watchpoints are specified, set them all.", + CommandObjectWatchpointIgnore(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "watchpoint ignore", + "Set ignore count on the specified watchpoint(s). " + "If no watchpoints are specified, set them all.", nullptr), - m_options() - { - CommandArgumentEntry arg; - CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); - // Add the entry for the first argument for this command to the object's arguments vector. - m_arguments.push_back(arg); + m_options() { + CommandArgumentEntry arg; + CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, + eArgTypeWatchpointIDRange); + // Add the entry for the first argument for this command to the object's + // arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectWatchpointIgnore() override = default; + + Options *GetOptions() override { return &m_options; } + + class CommandOptions : public Options { + public: + CommandOptions() : Options(), m_ignore_count(0) {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'i': + m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); + if (m_ignore_count == UINT32_MAX) + error.SetErrorStringWithFormat("invalid ignore count '%s'", + option_arg); + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; } - ~CommandObjectWatchpointIgnore() override = default; - - Options * - GetOptions () override - { - return &m_options; + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_ignore_count = 0; } - class CommandOptions : public Options - { - public: - CommandOptions() : - Options(), - m_ignore_count (0) - { - } - - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'i': - m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); - if (m_ignore_count == UINT32_MAX) - error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg); - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_ignore_count = 0; - } - - const OptionDefinition * - GetDefinitions () override - { - return g_option_table; - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } - // Options table: Required for subclasses of Options. + // Options table: Required for subclasses of Options. - static OptionDefinition g_option_table[]; + static OptionDefinition g_option_table[]; - // Instance variables to hold the values for command options. + // Instance variables to hold the values for command options. - uint32_t m_ignore_count; - }; + uint32_t m_ignore_count; + }; protected: - bool - DoExecute (Args& command, - CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (!CheckTargetForWatchpointOperations(target, result)) - return false; - - std::unique_lock<std::recursive_mutex> lock; - target->GetWatchpointList().GetListMutex(lock); + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (!CheckTargetForWatchpointOperations(target, result)) + return false; - const WatchpointList &watchpoints = target->GetWatchpointList(); + std::unique_lock<std::recursive_mutex> lock; + target->GetWatchpointList().GetListMutex(lock); - size_t num_watchpoints = watchpoints.GetSize(); + const WatchpointList &watchpoints = target->GetWatchpointList(); - if (num_watchpoints == 0) - { - result.AppendError("No watchpoints exist to be ignored."); - result.SetStatus(eReturnStatusFailed); - return false; - } + size_t num_watchpoints = watchpoints.GetSize(); - if (command.GetArgumentCount() == 0) - { - target->IgnoreAllWatchpoints(m_options.m_ignore_count); - result.AppendMessageWithFormat("All watchpoints ignored. (%" PRIu64 " watchpoints)\n", (uint64_t)num_watchpoints); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - // Particular watchpoints selected; ignore them. - std::vector<uint32_t> wp_ids; - if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids)) - { - result.AppendError("Invalid watchpoints specification."); - result.SetStatus(eReturnStatusFailed); - return false; - } - - int count = 0; - const size_t size = wp_ids.size(); - for (size_t i = 0; i < size; ++i) - if (target->IgnoreWatchpointByID(wp_ids[i], m_options.m_ignore_count)) - ++count; - result.AppendMessageWithFormat("%d watchpoints ignored.\n",count); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } + if (num_watchpoints == 0) { + result.AppendError("No watchpoints exist to be ignored."); + result.SetStatus(eReturnStatusFailed); + return false; + } - return result.Succeeded(); + if (command.GetArgumentCount() == 0) { + target->IgnoreAllWatchpoints(m_options.m_ignore_count); + result.AppendMessageWithFormat("All watchpoints ignored. (%" PRIu64 + " watchpoints)\n", + (uint64_t)num_watchpoints); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + // Particular watchpoints selected; ignore them. + std::vector<uint32_t> wp_ids; + if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( + target, command, wp_ids)) { + result.AppendError("Invalid watchpoints specification."); + result.SetStatus(eReturnStatusFailed); + return false; + } + + int count = 0; + const size_t size = wp_ids.size(); + for (size_t i = 0; i < size; ++i) + if (target->IgnoreWatchpointByID(wp_ids[i], m_options.m_ignore_count)) + ++count; + result.AppendMessageWithFormat("%d watchpoints ignored.\n", count); + result.SetStatus(eReturnStatusSuccessFinishNoResult); } + return result.Succeeded(); + } + private: - CommandOptions m_options; + CommandOptions m_options; }; #pragma mark Ignore::CommandOptions OptionDefinition -CommandObjectWatchpointIgnore::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectWatchpointIgnore::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_ALL, true, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- @@ -728,161 +659,136 @@ CommandObjectWatchpointIgnore::CommandOptions::g_option_table[] = //------------------------------------------------------------------------- #pragma mark Modify -class CommandObjectWatchpointModify : public CommandObjectParsed -{ +class CommandObjectWatchpointModify : public CommandObjectParsed { public: - CommandObjectWatchpointModify (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "watchpoint modify", - "Modify the options on a watchpoint or set of watchpoints in the executable. " - "If no watchpoint is specified, act on the last created watchpoint. " - "Passing an empty argument clears the modification.", - nullptr), - m_options() - { - CommandArgumentEntry arg; - CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); - // Add the entry for the first argument for this command to the object's arguments vector. - m_arguments.push_back (arg); + CommandObjectWatchpointModify(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "watchpoint modify", + "Modify the options on a watchpoint or set of watchpoints in the " + "executable. " + "If no watchpoint is specified, act on the last created " + "watchpoint. " + "Passing an empty argument clears the modification.", + nullptr), + m_options() { + CommandArgumentEntry arg; + CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, + eArgTypeWatchpointIDRange); + // Add the entry for the first argument for this command to the object's + // arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectWatchpointModify() override = default; + + Options *GetOptions() override { return &m_options; } + + class CommandOptions : public Options { + public: + CommandOptions() : Options(), m_condition(), m_condition_passed(false) {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'c': + if (option_arg != nullptr) + m_condition.assign(option_arg); + else + m_condition.clear(); + m_condition_passed = true; + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", + short_option); + break; + } + + return error; } - ~CommandObjectWatchpointModify() override = default; - - Options * - GetOptions () override - { - return &m_options; + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_condition.clear(); + m_condition_passed = false; } - class CommandOptions : public Options - { - public: - CommandOptions() : - Options(), - m_condition (), - m_condition_passed (false) - { - } - - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'c': - if (option_arg != nullptr) - m_condition.assign (option_arg); - else - m_condition.clear(); - m_condition_passed = true; - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_condition.clear(); - m_condition_passed = false; - } - - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } - // Options table: Required for subclasses of Options. + // Options table: Required for subclasses of Options. - static OptionDefinition g_option_table[]; + static OptionDefinition g_option_table[]; - // Instance variables to hold the values for command options. + // Instance variables to hold the values for command options. - std::string m_condition; - bool m_condition_passed; - }; + std::string m_condition; + bool m_condition_passed; + }; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (!CheckTargetForWatchpointOperations(target, result)) - return false; + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (!CheckTargetForWatchpointOperations(target, result)) + return false; - std::unique_lock<std::recursive_mutex> lock; - target->GetWatchpointList().GetListMutex(lock); + std::unique_lock<std::recursive_mutex> lock; + target->GetWatchpointList().GetListMutex(lock); - const WatchpointList &watchpoints = target->GetWatchpointList(); + const WatchpointList &watchpoints = target->GetWatchpointList(); - size_t num_watchpoints = watchpoints.GetSize(); + size_t num_watchpoints = watchpoints.GetSize(); - if (num_watchpoints == 0) - { - result.AppendError("No watchpoints exist to be modified."); - result.SetStatus(eReturnStatusFailed); - return false; - } + if (num_watchpoints == 0) { + result.AppendError("No watchpoints exist to be modified."); + result.SetStatus(eReturnStatusFailed); + return false; + } - if (command.GetArgumentCount() == 0) - { - WatchpointSP wp_sp = target->GetLastCreatedWatchpoint(); - wp_sp->SetCondition(m_options.m_condition.c_str()); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - // Particular watchpoints selected; set condition on them. - std::vector<uint32_t> wp_ids; - if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids)) - { - result.AppendError("Invalid watchpoints specification."); - result.SetStatus(eReturnStatusFailed); - return false; - } - - int count = 0; - const size_t size = wp_ids.size(); - for (size_t i = 0; i < size; ++i) - { - WatchpointSP wp_sp = watchpoints.FindByID(wp_ids[i]); - if (wp_sp) - { - wp_sp->SetCondition(m_options.m_condition.c_str()); - ++count; - } - } - result.AppendMessageWithFormat("%d watchpoints modified.\n",count); - result.SetStatus (eReturnStatusSuccessFinishNoResult); + if (command.GetArgumentCount() == 0) { + WatchpointSP wp_sp = target->GetLastCreatedWatchpoint(); + wp_sp->SetCondition(m_options.m_condition.c_str()); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + // Particular watchpoints selected; set condition on them. + std::vector<uint32_t> wp_ids; + if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( + target, command, wp_ids)) { + result.AppendError("Invalid watchpoints specification."); + result.SetStatus(eReturnStatusFailed); + return false; + } + + int count = 0; + const size_t size = wp_ids.size(); + for (size_t i = 0; i < size; ++i) { + WatchpointSP wp_sp = watchpoints.FindByID(wp_ids[i]); + if (wp_sp) { + wp_sp->SetCondition(m_options.m_condition.c_str()); + ++count; } - - return result.Succeeded(); + } + result.AppendMessageWithFormat("%d watchpoints modified.\n", count); + result.SetStatus(eReturnStatusSuccessFinishNoResult); } + return result.Succeeded(); + } + private: - CommandOptions m_options; + CommandOptions m_options; }; #pragma mark Modify::CommandOptions OptionDefinition -CommandObjectWatchpointModify::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectWatchpointModify::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The watchpoint stops only if this condition expression evaluates to true."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- @@ -890,208 +796,189 @@ CommandObjectWatchpointModify::CommandOptions::g_option_table[] = //------------------------------------------------------------------------- #pragma mark SetVariable -class CommandObjectWatchpointSetVariable : public CommandObjectParsed -{ +class CommandObjectWatchpointSetVariable : public CommandObjectParsed { public: - CommandObjectWatchpointSetVariable (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "watchpoint set variable", - "Set a watchpoint on a variable. " - "Use the '-w' option to specify the type of watchpoint and " - "the '-s' option to specify the byte size to watch for. " - "If no '-w' option is specified, it defaults to write. " - "If no '-s' option is specified, it defaults to the variable's " - "byte size. " - "Note that there are limited hardware resources for watchpoints. " - "If watchpoint setting fails, consider disable/delete existing ones " - "to free up resources.", - nullptr, - eCommandRequiresFrame | - eCommandTryTargetAPILock | - eCommandProcessMustBeLaunched | - eCommandProcessMustBePaused ), - m_option_group(), - m_option_watchpoint () - { - SetHelpLong( -R"( + CommandObjectWatchpointSetVariable(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "watchpoint set variable", + "Set a watchpoint on a variable. " + "Use the '-w' option to specify the type of watchpoint and " + "the '-s' option to specify the byte size to watch for. " + "If no '-w' option is specified, it defaults to write. " + "If no '-s' option is specified, it defaults to the variable's " + "byte size. " + "Note that there are limited hardware resources for watchpoints. " + "If watchpoint setting fails, consider disable/delete existing " + "ones " + "to free up resources.", + nullptr, + eCommandRequiresFrame | eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), + m_option_group(), m_option_watchpoint() { + SetHelpLong( + R"( Examples: (lldb) watchpoint set variable -w read_write my_global_var -)" " Watches my_global_var for read/write access, with the region to watch \ -corresponding to the byte size of the data type." - ); - - CommandArgumentEntry arg; - CommandArgumentData var_name_arg; - - // Define the only variant of this arg. - var_name_arg.arg_type = eArgTypeVarName; - var_name_arg.arg_repetition = eArgRepeatPlain; - - // Push the variant into the argument entry. - arg.push_back (var_name_arg); - - // Push the data for the only argument into the m_arguments vector. - m_arguments.push_back (arg); - - // Absorb the '-w' and '-s' options into our option group. - m_option_group.Append (&m_option_watchpoint, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Finalize(); - } +)" + " Watches my_global_var for read/write access, with the region to watch \ +corresponding to the byte size of the data type."); - ~CommandObjectWatchpointSetVariable() override = default; + CommandArgumentEntry arg; + CommandArgumentData var_name_arg; - Options * - GetOptions () override - { - return &m_option_group; - } + // Define the only variant of this arg. + var_name_arg.arg_type = eArgTypeVarName; + var_name_arg.arg_repetition = eArgRepeatPlain; + + // Push the variant into the argument entry. + arg.push_back(var_name_arg); + + // Push the data for the only argument into the m_arguments vector. + m_arguments.push_back(arg); + + // Absorb the '-w' and '-s' options into our option group. + m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_ALL, + LLDB_OPT_SET_1); + m_option_group.Finalize(); + } + + ~CommandObjectWatchpointSetVariable() override = default; + + Options *GetOptions() override { return &m_option_group; } protected: - static size_t GetVariableCallback (void *baton, - const char *name, - VariableList &variable_list) - { - Target *target = static_cast<Target *>(baton); - if (target) - { - return target->GetImages().FindGlobalVariables (ConstString(name), - true, - UINT32_MAX, - variable_list); - } - return 0; + static size_t GetVariableCallback(void *baton, const char *name, + VariableList &variable_list) { + Target *target = static_cast<Target *>(baton); + if (target) { + return target->GetImages().FindGlobalVariables(ConstString(name), true, + UINT32_MAX, variable_list); + } + return 0; + } + + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + StackFrame *frame = m_exe_ctx.GetFramePtr(); + + // If no argument is present, issue an error message. There's no way to set + // a watchpoint. + if (command.GetArgumentCount() <= 0) { + result.GetErrorStream().Printf("error: required argument missing; " + "specify your program variable to watch " + "for\n"); + result.SetStatus(eReturnStatusFailed); + return false; } - - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - StackFrame *frame = m_exe_ctx.GetFramePtr(); - - // If no argument is present, issue an error message. There's no way to set a watchpoint. - if (command.GetArgumentCount() <= 0) - { - result.GetErrorStream().Printf("error: required argument missing; specify your program variable to watch for\n"); - result.SetStatus(eReturnStatusFailed); - return false; - } - // If no '-w' is specified, default to '-w write'. - if (!m_option_watchpoint.watch_type_specified) - { - m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite; - } + // If no '-w' is specified, default to '-w write'. + if (!m_option_watchpoint.watch_type_specified) { + m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite; + } - // We passed the sanity check for the command. - // Proceed to set the watchpoint now. - lldb::addr_t addr = 0; - size_t size = 0; - - VariableSP var_sp; - ValueObjectSP valobj_sp; - Stream &output_stream = result.GetOutputStream(); - - // A simple watch variable gesture allows only one argument. - if (command.GetArgumentCount() != 1) - { - result.GetErrorStream().Printf("error: specify exactly one variable to watch for\n"); - result.SetStatus(eReturnStatusFailed); - return false; - } + // We passed the sanity check for the command. + // Proceed to set the watchpoint now. + lldb::addr_t addr = 0; + size_t size = 0; + + VariableSP var_sp; + ValueObjectSP valobj_sp; + Stream &output_stream = result.GetOutputStream(); + + // A simple watch variable gesture allows only one argument. + if (command.GetArgumentCount() != 1) { + result.GetErrorStream().Printf( + "error: specify exactly one variable to watch for\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } - // Things have checked out ok... - Error error; - uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember | - StackFrame::eExpressionPathOptionsAllowDirectIVarAccess; - valobj_sp = frame->GetValueForVariableExpressionPath (command.GetArgumentAtIndex(0), - eNoDynamicValues, - expr_path_options, - var_sp, - error); - - if (!valobj_sp) - { - // Not in the frame; let's check the globals. - - VariableList variable_list; - ValueObjectList valobj_list; - - Error error (Variable::GetValuesForVariableExpressionPath (command.GetArgumentAtIndex(0), - m_exe_ctx.GetBestExecutionContextScope(), - GetVariableCallback, - target, - variable_list, - valobj_list)); - - if (valobj_list.GetSize()) - valobj_sp = valobj_list.GetValueObjectAtIndex(0); - } - - CompilerType compiler_type; - - if (valobj_sp) - { - AddressType addr_type; - addr = valobj_sp->GetAddressOf(false, &addr_type); - if (addr_type == eAddressTypeLoad) - { - // We're in business. - // Find out the size of this variable. - size = m_option_watchpoint.watch_size == 0 ? valobj_sp->GetByteSize() - : m_option_watchpoint.watch_size; - } - compiler_type = valobj_sp->GetCompilerType(); - } - else - { - const char *error_cstr = error.AsCString(nullptr); - if (error_cstr) - result.GetErrorStream().Printf("error: %s\n", error_cstr); - else - result.GetErrorStream().Printf ("error: unable to find any variable expression path that matches '%s'\n", - command.GetArgumentAtIndex(0)); - return false; - } + // Things have checked out ok... + Error error; + uint32_t expr_path_options = + StackFrame::eExpressionPathOptionCheckPtrVsMember | + StackFrame::eExpressionPathOptionsAllowDirectIVarAccess; + valobj_sp = frame->GetValueForVariableExpressionPath( + command.GetArgumentAtIndex(0), eNoDynamicValues, expr_path_options, + var_sp, error); - // Now it's time to create the watchpoint. - uint32_t watch_type = m_option_watchpoint.watch_type; - - error.Clear(); - Watchpoint *wp = target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error).get(); - if (wp) - { - wp->SetWatchSpec(command.GetArgumentAtIndex(0)); - wp->SetWatchVariable(true); - if (var_sp && var_sp->GetDeclaration().GetFile()) - { - StreamString ss; - // True to show fullpath for declaration file. - var_sp->GetDeclaration().DumpStopContext(&ss, true); - wp->SetDeclInfo(ss.GetString()); - } - output_stream.Printf("Watchpoint created: "); - wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); - output_stream.EOL(); - result.SetStatus(eReturnStatusSuccessFinishResult); - } - else - { - result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 ", size=%" PRIu64 ", variable expression='%s').\n", - addr, (uint64_t)size, command.GetArgumentAtIndex(0)); - if (error.AsCString(nullptr)) - result.AppendError(error.AsCString()); - result.SetStatus(eReturnStatusFailed); - } + if (!valobj_sp) { + // Not in the frame; let's check the globals. + + VariableList variable_list; + ValueObjectList valobj_list; - return result.Succeeded(); + Error error(Variable::GetValuesForVariableExpressionPath( + command.GetArgumentAtIndex(0), + m_exe_ctx.GetBestExecutionContextScope(), GetVariableCallback, target, + variable_list, valobj_list)); + + if (valobj_list.GetSize()) + valobj_sp = valobj_list.GetValueObjectAtIndex(0); + } + + CompilerType compiler_type; + + if (valobj_sp) { + AddressType addr_type; + addr = valobj_sp->GetAddressOf(false, &addr_type); + if (addr_type == eAddressTypeLoad) { + // We're in business. + // Find out the size of this variable. + size = m_option_watchpoint.watch_size == 0 + ? valobj_sp->GetByteSize() + : m_option_watchpoint.watch_size; + } + compiler_type = valobj_sp->GetCompilerType(); + } else { + const char *error_cstr = error.AsCString(nullptr); + if (error_cstr) + result.GetErrorStream().Printf("error: %s\n", error_cstr); + else + result.GetErrorStream().Printf("error: unable to find any variable " + "expression path that matches '%s'\n", + command.GetArgumentAtIndex(0)); + return false; } + // Now it's time to create the watchpoint. + uint32_t watch_type = m_option_watchpoint.watch_type; + + error.Clear(); + Watchpoint *wp = + target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error) + .get(); + if (wp) { + wp->SetWatchSpec(command.GetArgumentAtIndex(0)); + wp->SetWatchVariable(true); + if (var_sp && var_sp->GetDeclaration().GetFile()) { + StreamString ss; + // True to show fullpath for declaration file. + var_sp->GetDeclaration().DumpStopContext(&ss, true); + wp->SetDeclInfo(ss.GetString()); + } + output_stream.Printf("Watchpoint created: "); + wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); + output_stream.EOL(); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat( + "Watchpoint creation failed (addr=0x%" PRIx64 ", size=%" PRIu64 + ", variable expression='%s').\n", + addr, (uint64_t)size, command.GetArgumentAtIndex(0)); + if (error.AsCString(nullptr)) + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + + return result.Succeeded(); + } + private: - OptionGroupOptions m_option_group; - OptionGroupWatchpoint m_option_watchpoint; + OptionGroupOptions m_option_group; + OptionGroupWatchpoint m_option_watchpoint; }; //------------------------------------------------------------------------- @@ -1099,210 +986,195 @@ private: //------------------------------------------------------------------------- #pragma mark Set -class CommandObjectWatchpointSetExpression : public CommandObjectRaw -{ +class CommandObjectWatchpointSetExpression : public CommandObjectRaw { public: - CommandObjectWatchpointSetExpression (CommandInterpreter &interpreter) : - CommandObjectRaw(interpreter, - "watchpoint set expression", - "Set a watchpoint on an address by supplying an expression. " - "Use the '-w' option to specify the type of watchpoint and " - "the '-s' option to specify the byte size to watch for. " - "If no '-w' option is specified, it defaults to write. " - "If no '-s' option is specified, it defaults to the target's " - "pointer byte size. " - "Note that there are limited hardware resources for watchpoints. " - "If watchpoint setting fails, consider disable/delete existing ones " - "to free up resources.", - nullptr, - eCommandRequiresFrame | - eCommandTryTargetAPILock | - eCommandProcessMustBeLaunched | - eCommandProcessMustBePaused ), - m_option_group(), - m_option_watchpoint () - { - SetHelpLong( -R"( + CommandObjectWatchpointSetExpression(CommandInterpreter &interpreter) + : CommandObjectRaw( + interpreter, "watchpoint set expression", + "Set a watchpoint on an address by supplying an expression. " + "Use the '-w' option to specify the type of watchpoint and " + "the '-s' option to specify the byte size to watch for. " + "If no '-w' option is specified, it defaults to write. " + "If no '-s' option is specified, it defaults to the target's " + "pointer byte size. " + "Note that there are limited hardware resources for watchpoints. " + "If watchpoint setting fails, consider disable/delete existing " + "ones " + "to free up resources.", + nullptr, + eCommandRequiresFrame | eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), + m_option_group(), m_option_watchpoint() { + SetHelpLong( + R"( Examples: (lldb) watchpoint set expression -w write -s 1 -- foo + 32 - Watches write access for the 1-byte region pointed to by the address 'foo + 32')" - ); - - CommandArgumentEntry arg; - CommandArgumentData expression_arg; - - // Define the only variant of this arg. - expression_arg.arg_type = eArgTypeExpression; - expression_arg.arg_repetition = eArgRepeatPlain; - - // Push the only variant into the argument entry. - arg.push_back (expression_arg); - - // Push the data for the only argument into the m_arguments vector. - m_arguments.push_back (arg); - - // Absorb the '-w' and '-s' options into our option group. - m_option_group.Append (&m_option_watchpoint, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Finalize(); - } + Watches write access for the 1-byte region pointed to by the address 'foo + 32')"); - ~CommandObjectWatchpointSetExpression() override = default; + CommandArgumentEntry arg; + CommandArgumentData expression_arg; - // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString. - bool - WantsCompletion() override { return true; } + // Define the only variant of this arg. + expression_arg.arg_type = eArgTypeExpression; + expression_arg.arg_repetition = eArgRepeatPlain; - Options * - GetOptions () override - { - return &m_option_group; - } + // Push the only variant into the argument entry. + arg.push_back(expression_arg); -protected: - bool - DoExecute (const char *raw_command, CommandReturnObject &result) override - { - auto exe_ctx = GetCommandInterpreter().GetExecutionContext(); - m_option_group.NotifyOptionParsingStarting(&exe_ctx); // This is a raw command, so notify the option group - - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - StackFrame *frame = m_exe_ctx.GetFramePtr(); - - Args command(raw_command); - const char *expr = nullptr; - if (raw_command[0] == '-') - { - // We have some options and these options MUST end with --. - const char *end_options = nullptr; - const char *s = raw_command; - while (s && s[0]) - { - end_options = ::strstr (s, "--"); - if (end_options) - { - end_options += 2; // Get past the "--" - if (::isspace (end_options[0])) - { - expr = end_options; - while (::isspace (*expr)) - ++expr; - break; - } - } - s = end_options; - } - - if (end_options) - { - Args args (llvm::StringRef(raw_command, end_options - raw_command)); - if (!ParseOptions (args, result)) - return false; - - Error error(m_option_group.NotifyOptionParsingFinished( - &exe_ctx)); - if (error.Fail()) - { - result.AppendError (error.AsCString()); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - } + // Push the data for the only argument into the m_arguments vector. + m_arguments.push_back(arg); - if (expr == nullptr) - expr = raw_command; + // Absorb the '-w' and '-s' options into our option group. + m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_ALL, + LLDB_OPT_SET_1); + m_option_group.Finalize(); + } - // If no argument is present, issue an error message. There's no way to set a watchpoint. - if (command.GetArgumentCount() == 0) - { - result.GetErrorStream().Printf("error: required argument missing; specify an expression to evaulate into the address to watch for\n"); - result.SetStatus(eReturnStatusFailed); - return false; - } + ~CommandObjectWatchpointSetExpression() override = default; - // If no '-w' is specified, default to '-w write'. - if (!m_option_watchpoint.watch_type_specified) - { - m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite; - } + // Overrides base class's behavior where WantsCompletion = + // !WantsRawCommandString. + bool WantsCompletion() override { return true; } - // We passed the sanity check for the command. - // Proceed to set the watchpoint now. - lldb::addr_t addr = 0; - size_t size = 0; - - ValueObjectSP valobj_sp; - - // Use expression evaluation to arrive at the address to watch. - EvaluateExpressionOptions options; - options.SetCoerceToId(false); - options.SetUnwindOnError(true); - options.SetKeepInMemory(false); - options.SetTryAllThreads(true); - options.SetTimeoutUsec(0); - - ExpressionResults expr_result = target->EvaluateExpression (expr, - frame, - valobj_sp, - options); - if (expr_result != eExpressionCompleted) - { - result.GetErrorStream().Printf("error: expression evaluation of address to watch failed\n"); - result.GetErrorStream().Printf("expression evaluated: %s\n", expr); - result.SetStatus(eReturnStatusFailed); - return false; - } + Options *GetOptions() override { return &m_option_group; } - // Get the address to watch. - bool success = false; - addr = valobj_sp->GetValueAsUnsigned(0, &success); - if (!success) - { - result.GetErrorStream().Printf("error: expression did not evaluate to an address\n"); - result.SetStatus(eReturnStatusFailed); - return false; - } - - if (m_option_watchpoint.watch_size != 0) - size = m_option_watchpoint.watch_size; - else - size = target->GetArchitecture().GetAddressByteSize(); - - // Now it's time to create the watchpoint. - uint32_t watch_type = m_option_watchpoint.watch_type; - - // Fetch the type from the value object, the type of the watched object is the pointee type - /// of the expression, so convert to that if we found a valid type. - CompilerType compiler_type(valobj_sp->GetCompilerType()); - - Error error; - Watchpoint *wp = target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error).get(); - if (wp) - { - Stream &output_stream = result.GetOutputStream(); - output_stream.Printf("Watchpoint created: "); - wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); - output_stream.EOL(); - result.SetStatus(eReturnStatusSuccessFinishResult); +protected: + bool DoExecute(const char *raw_command, + CommandReturnObject &result) override { + auto exe_ctx = GetCommandInterpreter().GetExecutionContext(); + m_option_group.NotifyOptionParsingStarting( + &exe_ctx); // This is a raw command, so notify the option group + + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + StackFrame *frame = m_exe_ctx.GetFramePtr(); + + Args command(raw_command); + const char *expr = nullptr; + if (raw_command[0] == '-') { + // We have some options and these options MUST end with --. + const char *end_options = nullptr; + const char *s = raw_command; + while (s && s[0]) { + end_options = ::strstr(s, "--"); + if (end_options) { + end_options += 2; // Get past the "--" + if (::isspace(end_options[0])) { + expr = end_options; + while (::isspace(*expr)) + ++expr; + break; + } } - else - { - result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 ", size=%" PRIu64 ").\n", - addr, (uint64_t)size); - if (error.AsCString(nullptr)) - result.AppendError(error.AsCString()); - result.SetStatus(eReturnStatusFailed); + s = end_options; + } + + if (end_options) { + Args args(llvm::StringRef(raw_command, end_options - raw_command)); + if (!ParseOptions(args, result)) + return false; + + Error error(m_option_group.NotifyOptionParsingFinished(&exe_ctx)); + if (error.Fail()) { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; } + } + } - return result.Succeeded(); + if (expr == nullptr) + expr = raw_command; + + // If no argument is present, issue an error message. There's no way to set + // a watchpoint. + if (command.GetArgumentCount() == 0) { + result.GetErrorStream().Printf("error: required argument missing; " + "specify an expression to evaulate into " + "the address to watch for\n"); + result.SetStatus(eReturnStatusFailed); + return false; } + // If no '-w' is specified, default to '-w write'. + if (!m_option_watchpoint.watch_type_specified) { + m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite; + } + + // We passed the sanity check for the command. + // Proceed to set the watchpoint now. + lldb::addr_t addr = 0; + size_t size = 0; + + ValueObjectSP valobj_sp; + + // Use expression evaluation to arrive at the address to watch. + EvaluateExpressionOptions options; + options.SetCoerceToId(false); + options.SetUnwindOnError(true); + options.SetKeepInMemory(false); + options.SetTryAllThreads(true); + options.SetTimeoutUsec(0); + + ExpressionResults expr_result = + target->EvaluateExpression(expr, frame, valobj_sp, options); + if (expr_result != eExpressionCompleted) { + result.GetErrorStream().Printf( + "error: expression evaluation of address to watch failed\n"); + result.GetErrorStream().Printf("expression evaluated: %s\n", expr); + result.SetStatus(eReturnStatusFailed); + return false; + } + + // Get the address to watch. + bool success = false; + addr = valobj_sp->GetValueAsUnsigned(0, &success); + if (!success) { + result.GetErrorStream().Printf( + "error: expression did not evaluate to an address\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (m_option_watchpoint.watch_size != 0) + size = m_option_watchpoint.watch_size; + else + size = target->GetArchitecture().GetAddressByteSize(); + + // Now it's time to create the watchpoint. + uint32_t watch_type = m_option_watchpoint.watch_type; + + // Fetch the type from the value object, the type of the watched object is + // the pointee type + /// of the expression, so convert to that if we found a valid type. + CompilerType compiler_type(valobj_sp->GetCompilerType()); + + Error error; + Watchpoint *wp = + target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error) + .get(); + if (wp) { + Stream &output_stream = result.GetOutputStream(); + output_stream.Printf("Watchpoint created: "); + wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); + output_stream.EOL(); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 + ", size=%" PRIu64 ").\n", + addr, (uint64_t)size); + if (error.AsCString(nullptr)) + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + + return result.Succeeded(); + } + private: - OptionGroupOptions m_option_group; - OptionGroupWatchpoint m_option_watchpoint; + OptionGroupOptions m_option_group; + OptionGroupWatchpoint m_option_watchpoint; }; //------------------------------------------------------------------------- @@ -1310,19 +1182,22 @@ private: //------------------------------------------------------------------------- #pragma mark Set -class CommandObjectWatchpointSet : public CommandObjectMultiword -{ +class CommandObjectWatchpointSet : public CommandObjectMultiword { public: - CommandObjectWatchpointSet(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "watchpoint set", "Commands for setting a watchpoint.", - "watchpoint set <subcommand> [<subcommand-options>]") - { - - LoadSubCommand ("variable", CommandObjectSP (new CommandObjectWatchpointSetVariable (interpreter))); - LoadSubCommand ("expression", CommandObjectSP (new CommandObjectWatchpointSetExpression (interpreter))); - } - - ~CommandObjectWatchpointSet() override = default; + CommandObjectWatchpointSet(CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "watchpoint set", "Commands for setting a watchpoint.", + "watchpoint set <subcommand> [<subcommand-options>]") { + + LoadSubCommand( + "variable", + CommandObjectSP(new CommandObjectWatchpointSetVariable(interpreter))); + LoadSubCommand( + "expression", + CommandObjectSP(new CommandObjectWatchpointSetExpression(interpreter))); + } + + ~CommandObjectWatchpointSet() override = default; }; //------------------------------------------------------------------------- @@ -1330,36 +1205,45 @@ public: //------------------------------------------------------------------------- #pragma mark MultiwordWatchpoint -CommandObjectMultiwordWatchpoint::CommandObjectMultiwordWatchpoint(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "watchpoint", "Commands for operating on watchpoints.", - "watchpoint <subcommand> [<command-options>]") -{ - CommandObjectSP list_command_object (new CommandObjectWatchpointList (interpreter)); - CommandObjectSP enable_command_object (new CommandObjectWatchpointEnable (interpreter)); - CommandObjectSP disable_command_object (new CommandObjectWatchpointDisable (interpreter)); - CommandObjectSP delete_command_object (new CommandObjectWatchpointDelete (interpreter)); - CommandObjectSP ignore_command_object (new CommandObjectWatchpointIgnore (interpreter)); - CommandObjectSP command_command_object (new CommandObjectWatchpointCommand (interpreter)); - CommandObjectSP modify_command_object (new CommandObjectWatchpointModify (interpreter)); - CommandObjectSP set_command_object (new CommandObjectWatchpointSet (interpreter)); - - list_command_object->SetCommandName ("watchpoint list"); - enable_command_object->SetCommandName("watchpoint enable"); - disable_command_object->SetCommandName("watchpoint disable"); - delete_command_object->SetCommandName("watchpoint delete"); - ignore_command_object->SetCommandName("watchpoint ignore"); - command_command_object->SetCommandName ("watchpoint command"); - modify_command_object->SetCommandName("watchpoint modify"); - set_command_object->SetCommandName("watchpoint set"); - - LoadSubCommand ("list", list_command_object); - LoadSubCommand ("enable", enable_command_object); - LoadSubCommand ("disable", disable_command_object); - LoadSubCommand ("delete", delete_command_object); - LoadSubCommand ("ignore", ignore_command_object); - LoadSubCommand ("command", command_command_object); - LoadSubCommand ("modify", modify_command_object); - LoadSubCommand ("set", set_command_object); +CommandObjectMultiwordWatchpoint::CommandObjectMultiwordWatchpoint( + CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "watchpoint", + "Commands for operating on watchpoints.", + "watchpoint <subcommand> [<command-options>]") { + CommandObjectSP list_command_object( + new CommandObjectWatchpointList(interpreter)); + CommandObjectSP enable_command_object( + new CommandObjectWatchpointEnable(interpreter)); + CommandObjectSP disable_command_object( + new CommandObjectWatchpointDisable(interpreter)); + CommandObjectSP delete_command_object( + new CommandObjectWatchpointDelete(interpreter)); + CommandObjectSP ignore_command_object( + new CommandObjectWatchpointIgnore(interpreter)); + CommandObjectSP command_command_object( + new CommandObjectWatchpointCommand(interpreter)); + CommandObjectSP modify_command_object( + new CommandObjectWatchpointModify(interpreter)); + CommandObjectSP set_command_object( + new CommandObjectWatchpointSet(interpreter)); + + list_command_object->SetCommandName("watchpoint list"); + enable_command_object->SetCommandName("watchpoint enable"); + disable_command_object->SetCommandName("watchpoint disable"); + delete_command_object->SetCommandName("watchpoint delete"); + ignore_command_object->SetCommandName("watchpoint ignore"); + command_command_object->SetCommandName("watchpoint command"); + modify_command_object->SetCommandName("watchpoint modify"); + set_command_object->SetCommandName("watchpoint set"); + + LoadSubCommand("list", list_command_object); + LoadSubCommand("enable", enable_command_object); + LoadSubCommand("disable", disable_command_object); + LoadSubCommand("delete", delete_command_object); + LoadSubCommand("ignore", ignore_command_object); + LoadSubCommand("command", command_command_object); + LoadSubCommand("modify", modify_command_object); + LoadSubCommand("set", set_command_object); } CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint() = default; diff --git a/lldb/source/Commands/CommandObjectWatchpoint.h b/lldb/source/Commands/CommandObjectWatchpoint.h index b1926dc..adc0a81 100644 --- a/lldb/source/Commands/CommandObjectWatchpoint.h +++ b/lldb/source/Commands/CommandObjectWatchpoint.h @@ -16,8 +16,8 @@ // Other libraries and framework includes // Project includes #include "lldb/Interpreter/CommandObjectMultiword.h" -#include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/OptionGroupWatchpoint.h" +#include "lldb/Interpreter/Options.h" namespace lldb_private { @@ -25,15 +25,14 @@ namespace lldb_private { // CommandObjectMultiwordWatchpoint //------------------------------------------------------------------------- -class CommandObjectMultiwordWatchpoint : public CommandObjectMultiword -{ +class CommandObjectMultiwordWatchpoint : public CommandObjectMultiword { public: - CommandObjectMultiwordWatchpoint (CommandInterpreter &interpreter); + CommandObjectMultiwordWatchpoint(CommandInterpreter &interpreter); - ~CommandObjectMultiwordWatchpoint() override; + ~CommandObjectMultiwordWatchpoint() override; - static bool - VerifyWatchpointIDs(Target *target, Args &args, std::vector<uint32_t> &wp_ids); + static bool VerifyWatchpointIDs(Target *target, Args &args, + std::vector<uint32_t> &wp_ids); }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectWatchpointCommand.cpp b/lldb/source/Commands/CommandObjectWatchpointCommand.cpp index cc6df75..1cd253b 100644 --- a/lldb/source/Commands/CommandObjectWatchpointCommand.cpp +++ b/lldb/source/Commands/CommandObjectWatchpointCommand.cpp @@ -13,16 +13,16 @@ // Other libraries and framework includes // Project includes -#include "CommandObjectWatchpointCommand.h" #include "CommandObjectWatchpoint.h" +#include "CommandObjectWatchpointCommand.h" +#include "lldb/Breakpoint/StoppointCallbackContext.h" +#include "lldb/Breakpoint/Watchpoint.h" #include "lldb/Core/IOHandler.h" +#include "lldb/Core/State.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" -#include "lldb/Breakpoint/Watchpoint.h" -#include "lldb/Breakpoint/StoppointCallbackContext.h" -#include "lldb/Core/State.h" using namespace lldb; using namespace lldb_private; @@ -31,43 +31,50 @@ using namespace lldb_private; // CommandObjectWatchpointCommandAdd //------------------------------------------------------------------------- -class CommandObjectWatchpointCommandAdd : - public CommandObjectParsed, - public IOHandlerDelegateMultiline -{ +class CommandObjectWatchpointCommandAdd : public CommandObjectParsed, + public IOHandlerDelegateMultiline { public: - CommandObjectWatchpointCommandAdd(CommandInterpreter &interpreter) - : CommandObjectParsed( - interpreter, "add", - "Add a set of LLDB commands to a watchpoint, to be executed whenever the watchpoint is hit.", nullptr), - IOHandlerDelegateMultiline("DONE", IOHandlerDelegate::Completion::LLDBCommand), - m_options() - { - SetHelpLong ( -R"( + CommandObjectWatchpointCommandAdd(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "add", + "Add a set of LLDB commands to a watchpoint, to be " + "executed whenever the watchpoint is hit.", + nullptr), + IOHandlerDelegateMultiline("DONE", + IOHandlerDelegate::Completion::LLDBCommand), + m_options() { + SetHelpLong( + R"( General information about entering watchpoint commands ------------------------------------------------------ -)" "This command will prompt for commands to be executed when the specified \ +)" + "This command will prompt for commands to be executed when the specified \ watchpoint is hit. Each command is typed on its own line following the '> ' \ -prompt until 'DONE' is entered." R"( +prompt until 'DONE' is entered." + R"( -)" "Syntactic errors may not be detected when initially entered, and many \ +)" + "Syntactic errors may not be detected when initially entered, and many \ malformed commands can silently fail when executed. If your watchpoint commands \ -do not appear to be executing, double-check the command syntax." R"( +do not appear to be executing, double-check the command syntax." + R"( -)" "Note: You may enter any debugger command exactly as you would at the debugger \ +)" + "Note: You may enter any debugger command exactly as you would at the debugger \ prompt. There is no limit to the number of commands supplied, but do NOT enter \ -more than one command per line." R"( +more than one command per line." + R"( Special information about PYTHON watchpoint commands ---------------------------------------------------- -)" "You may enter either one or more lines of Python, including function \ +)" + "You may enter either one or more lines of Python, including function \ definitions or calls to functions that will have been imported by the time \ the code executes. Single line watchpoint commands will be interpreted 'as is' \ when the watchpoint is hit. Multiple lines of Python will be wrapped in a \ -generated function, and a call to the function will be attached to the watchpoint." R"( +generated function, and a call to the function will be attached to the watchpoint." + R"( This auto-generated function is passed in three arguments: @@ -75,8 +82,10 @@ This auto-generated function is passed in three arguments: wp: the watchpoint that was hit. -)" "When specifying a python function with the --python-function option, you need \ -to supply the function name prepended by the module name:" R"( +)" + "When specifying a python function with the --python-function option, you need \ +to supply the function name prepended by the module name:" + R"( --python-function myutils.watchpoint_callback @@ -85,16 +94,20 @@ The function itself must have the following prototype: def watchpoint_callback(frame, wp): # Your code goes here -)" "The arguments are the same as the arguments passed to generated functions as \ +)" + "The arguments are the same as the arguments passed to generated functions as \ described above. Note that the global variable 'lldb.frame' will NOT be updated when \ this function is called, so be sure to use the 'frame' argument. The 'frame' argument \ can get you to the thread via frame.GetThread(), the thread can get you to the \ process via thread.GetProcess(), and the process can get you back to the target \ -via process.GetTarget()." R"( +via process.GetTarget()." + R"( -)" "Important Note: As Python code gets collected into functions, access to global \ +)" + "Important Note: As Python code gets collected into functions, access to global \ variables requires explicit scoping using the 'global' keyword. Be sure to use correct \ -Python syntax, including indentation, when entering Python watchpoint commands." R"( +Python syntax, including indentation, when entering Python watchpoint commands." + R"( Example Python one-line watchpoint command: @@ -139,585 +152,540 @@ Enter your Python command(s). Type 'DONE' to end. > print "Hit this watchpoint " + repr(wp_count) + " times!" > DONE -)" "In this case, since there is a reference to a global variable, \ +)" + "In this case, since there is a reference to a global variable, \ 'wp_count', you will also need to make sure 'wp_count' exists and is \ -initialized:" R"( +initialized:" + R"( (lldb) script >>> wp_count = 0 >>> quit() -)" "Final Note: A warning that no watchpoint command was generated when there \ -are no syntax errors may indicate that a function was declared but never called." - ); +)" + "Final Note: A warning that no watchpoint command was generated when there \ +are no syntax errors may indicate that a function was declared but never called."); - CommandArgumentEntry arg; - CommandArgumentData wp_id_arg; + CommandArgumentEntry arg; + CommandArgumentData wp_id_arg; - // Define the first (and only) variant of this arg. - wp_id_arg.arg_type = eArgTypeWatchpointID; - wp_id_arg.arg_repetition = eArgRepeatPlain; + // Define the first (and only) variant of this arg. + wp_id_arg.arg_type = eArgTypeWatchpointID; + wp_id_arg.arg_repetition = eArgRepeatPlain; - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (wp_id_arg); + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(wp_id_arg); - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - } + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } - ~CommandObjectWatchpointCommandAdd() override = default; + ~CommandObjectWatchpointCommandAdd() override = default; - Options * - GetOptions () override - { - return &m_options; - } + Options *GetOptions() override { return &m_options; } - void - IOHandlerActivated (IOHandler &io_handler) override - { - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); - if (output_sp) - { - output_sp->PutCString("Enter your debugger command(s). Type 'DONE' to end.\n"); - output_sp->Flush(); - } + void IOHandlerActivated(IOHandler &io_handler) override { + StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + if (output_sp) { + output_sp->PutCString( + "Enter your debugger command(s). Type 'DONE' to end.\n"); + output_sp->Flush(); } - - void - IOHandlerInputComplete (IOHandler &io_handler, std::string &line) override - { - io_handler.SetIsDone(true); - - // The WatchpointOptions object is owned by the watchpoint or watchpoint location - WatchpointOptions *wp_options = (WatchpointOptions *) io_handler.GetUserData(); - if (wp_options) - { - std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData()); - if (data_ap) - { - data_ap->user_source.SplitIntoLines(line); - BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release())); - wp_options->SetCallback (WatchpointOptionsCallbackFunction, baton_sp); - } - } + } + + void IOHandlerInputComplete(IOHandler &io_handler, + std::string &line) override { + io_handler.SetIsDone(true); + + // The WatchpointOptions object is owned by the watchpoint or watchpoint + // location + WatchpointOptions *wp_options = + (WatchpointOptions *)io_handler.GetUserData(); + if (wp_options) { + std::unique_ptr<WatchpointOptions::CommandData> data_ap( + new WatchpointOptions::CommandData()); + if (data_ap) { + data_ap->user_source.SplitIntoLines(line); + BatonSP baton_sp( + new WatchpointOptions::CommandBaton(data_ap.release())); + wp_options->SetCallback(WatchpointOptionsCallbackFunction, baton_sp); + } } - - void - CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options, - CommandReturnObject &result) - { - m_interpreter.GetLLDBCommandsFromIOHandler ("> ", // Prompt - *this, // IOHandlerDelegate - true, // Run IOHandler in async mode - wp_options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions + } + + void CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options, + CommandReturnObject &result) { + m_interpreter.GetLLDBCommandsFromIOHandler( + "> ", // Prompt + *this, // IOHandlerDelegate + true, // Run IOHandler in async mode + wp_options); // Baton for the "io_handler" that will be passed back into + // our IOHandlerDelegate functions + } + + /// Set a one-liner as the callback for the watchpoint. + void SetWatchpointCommandCallback(WatchpointOptions *wp_options, + const char *oneliner) { + std::unique_ptr<WatchpointOptions::CommandData> data_ap( + new WatchpointOptions::CommandData()); + + // It's necessary to set both user_source and script_source to the oneliner. + // The former is used to generate callback description (as in watchpoint + // command list) + // while the latter is used for Python to interpret during the actual + // callback. + data_ap->user_source.AppendString(oneliner); + data_ap->script_source.assign(oneliner); + data_ap->stop_on_error = m_options.m_stop_on_error; + + BatonSP baton_sp(new WatchpointOptions::CommandBaton(data_ap.release())); + wp_options->SetCallback(WatchpointOptionsCallbackFunction, baton_sp); + } + + static bool + WatchpointOptionsCallbackFunction(void *baton, + StoppointCallbackContext *context, + lldb::user_id_t watch_id) { + bool ret_value = true; + if (baton == nullptr) + return true; + + WatchpointOptions::CommandData *data = + (WatchpointOptions::CommandData *)baton; + StringList &commands = data->user_source; + + if (commands.GetSize() > 0) { + ExecutionContext exe_ctx(context->exe_ctx_ref); + Target *target = exe_ctx.GetTargetPtr(); + if (target) { + CommandReturnObject result; + Debugger &debugger = target->GetDebugger(); + // 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); + result.SetImmediateErrorStream(error_stream); + + CommandInterpreterRunOptions options; + options.SetStopOnContinue(true); + options.SetStopOnError(data->stop_on_error); + options.SetEchoCommands(false); + options.SetPrintResults(true); + options.SetAddToHistory(false); + + debugger.GetCommandInterpreter().HandleCommands(commands, &exe_ctx, + options, result); + result.GetImmediateOutputStream()->Flush(); + result.GetImmediateErrorStream()->Flush(); + } } - - /// Set a one-liner as the callback for the watchpoint. - void - SetWatchpointCommandCallback (WatchpointOptions *wp_options, - const char *oneliner) - { - std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData()); - - // It's necessary to set both user_source and script_source to the oneliner. - // The former is used to generate callback description (as in watchpoint command list) - // while the latter is used for Python to interpret during the actual callback. - data_ap->user_source.AppendString (oneliner); - data_ap->script_source.assign (oneliner); - data_ap->stop_on_error = m_options.m_stop_on_error; - - BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release())); - wp_options->SetCallback (WatchpointOptionsCallbackFunction, baton_sp); + return ret_value; + } + + class CommandOptions : public Options { + public: + CommandOptions() + : Options(), m_use_commands(false), m_use_script_language(false), + m_script_language(eScriptLanguageNone), m_use_one_liner(false), + m_one_liner(), m_function_name() {} + + ~CommandOptions() override = default; + + Error SetOptionValue(uint32_t option_idx, const char *option_arg, + ExecutionContext *execution_context) override { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'o': + m_use_one_liner = true; + m_one_liner = option_arg; + break; + + case 's': + m_script_language = (lldb::ScriptLanguage)Args::StringToOptionEnum( + option_arg, g_option_table[option_idx].enum_values, + eScriptLanguageNone, error); + + m_use_script_language = (m_script_language == eScriptLanguagePython || + m_script_language == eScriptLanguageDefault); + break; + + case 'e': { + bool success = false; + m_stop_on_error = Args::StringToBoolean(option_arg, false, &success); + if (!success) + error.SetErrorStringWithFormat( + "invalid value for stop-on-error: \"%s\"", option_arg); + } break; + + case 'F': + m_use_one_liner = false; + m_use_script_language = true; + m_function_name.assign(option_arg); + break; + + default: + break; + } + return error; } - - static bool - WatchpointOptionsCallbackFunction (void *baton, - StoppointCallbackContext *context, - lldb::user_id_t watch_id) - { - bool ret_value = true; - if (baton == nullptr) - return true; - - WatchpointOptions::CommandData *data = (WatchpointOptions::CommandData *) baton; - StringList &commands = data->user_source; - - if (commands.GetSize() > 0) - { - ExecutionContext exe_ctx (context->exe_ctx_ref); - Target *target = exe_ctx.GetTargetPtr(); - if (target) - { - CommandReturnObject result; - Debugger &debugger = target->GetDebugger(); - // 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); - result.SetImmediateErrorStream (error_stream); - - CommandInterpreterRunOptions options; - options.SetStopOnContinue (true); - options.SetStopOnError (data->stop_on_error); - options.SetEchoCommands (false); - options.SetPrintResults (true); - options.SetAddToHistory (false); - - debugger.GetCommandInterpreter().HandleCommands (commands, - &exe_ctx, - options, - result); - result.GetImmediateOutputStream()->Flush(); - result.GetImmediateErrorStream()->Flush(); - } - } - return ret_value; - } - - class CommandOptions : public Options - { - public: - CommandOptions() : - Options(), - m_use_commands (false), - m_use_script_language (false), - m_script_language (eScriptLanguageNone), - m_use_one_liner (false), - m_one_liner(), - m_function_name() - { - } - ~CommandOptions() override = default; - - Error - SetOptionValue(uint32_t option_idx, const char *option_arg, - ExecutionContext *execution_context) override - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'o': - m_use_one_liner = true; - m_one_liner = option_arg; - break; - - case 's': - m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg, - g_option_table[option_idx].enum_values, - eScriptLanguageNone, - error); - - m_use_script_language = - (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault); - break; - - case 'e': - { - bool success = false; - m_stop_on_error = Args::StringToBoolean(option_arg, false, &success); - if (!success) - error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg); - } - break; - - case 'F': - m_use_one_liner = false; - m_use_script_language = true; - m_function_name.assign(option_arg); - break; - - default: - break; - } - return error; - } + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_use_commands = true; + m_use_script_language = false; + m_script_language = eScriptLanguageNone; - void - OptionParsingStarting(ExecutionContext *execution_context) override - { - m_use_commands = true; - m_use_script_language = false; - m_script_language = eScriptLanguageNone; - - m_use_one_liner = false; - m_stop_on_error = true; - m_one_liner.clear(); - m_function_name.clear(); - } + m_use_one_liner = false; + m_stop_on_error = true; + m_one_liner.clear(); + m_function_name.clear(); + } - const OptionDefinition* - GetDefinitions () override - { - return g_option_table; - } + const OptionDefinition *GetDefinitions() override { return g_option_table; } - // Options table: Required for subclasses of Options. + // Options table: Required for subclasses of Options. - static OptionDefinition g_option_table[]; + static OptionDefinition g_option_table[]; - // Instance variables to hold the values for command options. + // Instance variables to hold the values for command options. - bool m_use_commands; - bool m_use_script_language; - lldb::ScriptLanguage m_script_language; + bool m_use_commands; + bool m_use_script_language; + lldb::ScriptLanguage m_script_language; - // Instance variables to hold the values for one_liner options. - bool m_use_one_liner; - std::string m_one_liner; - bool m_stop_on_error; - std::string m_function_name; - }; + // Instance variables to hold the values for one_liner options. + bool m_use_one_liner; + std::string m_one_liner; + bool m_stop_on_error; + std::string m_function_name; + }; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - - if (target == nullptr) - { - result.AppendError ("There is not a current executable; there are no watchpoints to which to add commands"); - result.SetStatus (eReturnStatusFailed); - return false; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + + if (target == nullptr) { + result.AppendError("There is not a current executable; there are no " + "watchpoints to which to add commands"); + result.SetStatus(eReturnStatusFailed); + return false; + } - const WatchpointList &watchpoints = target->GetWatchpointList(); - size_t num_watchpoints = watchpoints.GetSize(); + const WatchpointList &watchpoints = target->GetWatchpointList(); + size_t num_watchpoints = watchpoints.GetSize(); - if (num_watchpoints == 0) - { - result.AppendError ("No watchpoints exist to have commands added"); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (num_watchpoints == 0) { + result.AppendError("No watchpoints exist to have commands added"); + result.SetStatus(eReturnStatusFailed); + return false; + } - if (!m_options.m_use_script_language && !m_options.m_function_name.empty()) - { - result.AppendError ("need to enable scripting to have a function run as a watchpoint command"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - std::vector<uint32_t> valid_wp_ids; - if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, valid_wp_ids)) - { - result.AppendError("Invalid watchpoints specification."); - result.SetStatus(eReturnStatusFailed); - return false; - } + if (!m_options.m_use_script_language && + !m_options.m_function_name.empty()) { + result.AppendError("need to enable scripting to have a function run as a " + "watchpoint command"); + result.SetStatus(eReturnStatusFailed); + return false; + } - result.SetStatus(eReturnStatusSuccessFinishNoResult); - const size_t count = valid_wp_ids.size(); - for (size_t i = 0; i < count; ++i) - { - uint32_t cur_wp_id = valid_wp_ids.at (i); - if (cur_wp_id != LLDB_INVALID_WATCH_ID) - { - Watchpoint *wp = target->GetWatchpointList().FindByID (cur_wp_id).get(); - // Sanity check wp first. - if (wp == nullptr) continue; - - WatchpointOptions *wp_options = wp->GetOptions(); - // Skip this watchpoint if wp_options is not good. - if (wp_options == nullptr) continue; - - // If we are using script language, get the script interpreter - // in order to set or collect command callback. Otherwise, call - // the methods associated with this object. - if (m_options.m_use_script_language) - { - // Special handling for one-liner specified inline. - if (m_options.m_use_one_liner) - { - m_interpreter.GetScriptInterpreter()->SetWatchpointCommandCallback (wp_options, - m_options.m_one_liner.c_str()); - } - // Special handling for using a Python function by name - // instead of extending the watchpoint callback data structures, we just automatize - // what the user would do manually: make their watchpoint command be a function call - else if (!m_options.m_function_name.empty()) - { - std::string oneliner(m_options.m_function_name); - oneliner += "(frame, wp, internal_dict)"; - m_interpreter.GetScriptInterpreter()->SetWatchpointCommandCallback (wp_options, - oneliner.c_str()); - } - else - { - m_interpreter.GetScriptInterpreter()->CollectDataForWatchpointCommandCallback (wp_options, - result); - } - } - else - { - // Special handling for one-liner specified inline. - if (m_options.m_use_one_liner) - SetWatchpointCommandCallback (wp_options, - m_options.m_one_liner.c_str()); - else - CollectDataForWatchpointCommandCallback (wp_options, - result); - } - } - } + std::vector<uint32_t> valid_wp_ids; + if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, + valid_wp_ids)) { + result.AppendError("Invalid watchpoints specification."); + result.SetStatus(eReturnStatusFailed); + return false; + } - return result.Succeeded(); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + const size_t count = valid_wp_ids.size(); + for (size_t i = 0; i < count; ++i) { + uint32_t cur_wp_id = valid_wp_ids.at(i); + if (cur_wp_id != LLDB_INVALID_WATCH_ID) { + Watchpoint *wp = target->GetWatchpointList().FindByID(cur_wp_id).get(); + // Sanity check wp first. + if (wp == nullptr) + continue; + + WatchpointOptions *wp_options = wp->GetOptions(); + // Skip this watchpoint if wp_options is not good. + if (wp_options == nullptr) + continue; + + // If we are using script language, get the script interpreter + // in order to set or collect command callback. Otherwise, call + // the methods associated with this object. + if (m_options.m_use_script_language) { + // Special handling for one-liner specified inline. + if (m_options.m_use_one_liner) { + m_interpreter.GetScriptInterpreter()->SetWatchpointCommandCallback( + wp_options, m_options.m_one_liner.c_str()); + } + // Special handling for using a Python function by name + // instead of extending the watchpoint callback data structures, we + // just automatize + // what the user would do manually: make their watchpoint command be a + // function call + else if (!m_options.m_function_name.empty()) { + std::string oneliner(m_options.m_function_name); + oneliner += "(frame, wp, internal_dict)"; + m_interpreter.GetScriptInterpreter()->SetWatchpointCommandCallback( + wp_options, oneliner.c_str()); + } else { + m_interpreter.GetScriptInterpreter() + ->CollectDataForWatchpointCommandCallback(wp_options, result); + } + } else { + // Special handling for one-liner specified inline. + if (m_options.m_use_one_liner) + SetWatchpointCommandCallback(wp_options, + m_options.m_one_liner.c_str()); + else + CollectDataForWatchpointCommandCallback(wp_options, result); + } + } } + return result.Succeeded(); + } + private: - CommandOptions m_options; + CommandOptions m_options; }; -// FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting -// language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper. +// FIXME: "script-type" needs to have its contents determined dynamically, so +// somebody can add a new scripting +// language to lldb and have it pickable here without having to change this +// enumeration by hand and rebuild lldb proper. -static OptionEnumValueElement -g_script_option_enumeration[4] = -{ - { eScriptLanguageNone, "command", "Commands are in the lldb command interpreter language"}, - { eScriptLanguagePython, "python", "Commands are in the Python language."}, - { eSortOrderByName, "default-script", "Commands are in the default scripting language."}, - { 0, nullptr, nullptr } -}; +static OptionEnumValueElement g_script_option_enumeration[4] = { + {eScriptLanguageNone, "command", + "Commands are in the lldb command interpreter language"}, + {eScriptLanguagePython, "python", "Commands are in the Python language."}, + {eSortOrderByName, "default-script", + "Commands are in the default scripting language."}, + {0, nullptr, nullptr}}; OptionDefinition -CommandObjectWatchpointCommandAdd::CommandOptions::g_option_table[] = -{ - // clang-format off + CommandObjectWatchpointCommandAdd::CommandOptions::g_option_table[] = { + // clang-format off {LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOneLiner, "Specify a one-line watchpoint command inline. Be sure to surround it with quotes."}, {LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Specify whether watchpoint command execution should terminate on error."}, {LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, nullptr, g_script_option_enumeration, 0, eArgTypeNone, "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."}, {LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Give the name of a Python function to run as command for this watchpoint. Be sure to give a module name if appropriate."}, {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } - // clang-format on + // clang-format on }; //------------------------------------------------------------------------- // CommandObjectWatchpointCommandDelete //------------------------------------------------------------------------- -class CommandObjectWatchpointCommandDelete : public CommandObjectParsed -{ +class CommandObjectWatchpointCommandDelete : public CommandObjectParsed { public: - CommandObjectWatchpointCommandDelete (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "delete", + CommandObjectWatchpointCommandDelete(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "delete", "Delete the set of commands from a watchpoint.", - nullptr) - { - CommandArgumentEntry arg; - CommandArgumentData wp_id_arg; + nullptr) { + CommandArgumentEntry arg; + CommandArgumentData wp_id_arg; - // Define the first (and only) variant of this arg. - wp_id_arg.arg_type = eArgTypeWatchpointID; - wp_id_arg.arg_repetition = eArgRepeatPlain; + // Define the first (and only) variant of this arg. + wp_id_arg.arg_type = eArgTypeWatchpointID; + wp_id_arg.arg_repetition = eArgRepeatPlain; - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (wp_id_arg); + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(wp_id_arg); - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - } + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } - ~CommandObjectWatchpointCommandDelete() override = default; + ~CommandObjectWatchpointCommandDelete() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - - if (target == nullptr) - { - result.AppendError ("There is not a current executable; there are no watchpoints from which to delete commands"); - result.SetStatus (eReturnStatusFailed); - return false; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + + if (target == nullptr) { + result.AppendError("There is not a current executable; there are no " + "watchpoints from which to delete commands"); + result.SetStatus(eReturnStatusFailed); + return false; + } - const WatchpointList &watchpoints = target->GetWatchpointList(); - size_t num_watchpoints = watchpoints.GetSize(); + const WatchpointList &watchpoints = target->GetWatchpointList(); + size_t num_watchpoints = watchpoints.GetSize(); - if (num_watchpoints == 0) - { - result.AppendError ("No watchpoints exist to have commands deleted"); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (num_watchpoints == 0) { + result.AppendError("No watchpoints exist to have commands deleted"); + result.SetStatus(eReturnStatusFailed); + return false; + } - if (command.GetArgumentCount() == 0) - { - result.AppendError ("No watchpoint specified from which to delete the commands"); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (command.GetArgumentCount() == 0) { + result.AppendError( + "No watchpoint specified from which to delete the commands"); + result.SetStatus(eReturnStatusFailed); + return false; + } - std::vector<uint32_t> valid_wp_ids; - if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, valid_wp_ids)) - { - result.AppendError("Invalid watchpoints specification."); - result.SetStatus(eReturnStatusFailed); - return false; - } + std::vector<uint32_t> valid_wp_ids; + if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, + valid_wp_ids)) { + result.AppendError("Invalid watchpoints specification."); + result.SetStatus(eReturnStatusFailed); + return false; + } - result.SetStatus(eReturnStatusSuccessFinishNoResult); - const size_t count = valid_wp_ids.size(); - for (size_t i = 0; i < count; ++i) - { - uint32_t cur_wp_id = valid_wp_ids.at (i); - if (cur_wp_id != LLDB_INVALID_WATCH_ID) - { - Watchpoint *wp = target->GetWatchpointList().FindByID (cur_wp_id).get(); - if (wp) - wp->ClearCallback(); - } - else - { - result.AppendErrorWithFormat("Invalid watchpoint ID: %u.\n", - cur_wp_id); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - return result.Succeeded(); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + const size_t count = valid_wp_ids.size(); + for (size_t i = 0; i < count; ++i) { + uint32_t cur_wp_id = valid_wp_ids.at(i); + if (cur_wp_id != LLDB_INVALID_WATCH_ID) { + Watchpoint *wp = target->GetWatchpointList().FindByID(cur_wp_id).get(); + if (wp) + wp->ClearCallback(); + } else { + result.AppendErrorWithFormat("Invalid watchpoint ID: %u.\n", cur_wp_id); + result.SetStatus(eReturnStatusFailed); + return false; + } } + return result.Succeeded(); + } }; //------------------------------------------------------------------------- // CommandObjectWatchpointCommandList //------------------------------------------------------------------------- -class CommandObjectWatchpointCommandList : public CommandObjectParsed -{ +class CommandObjectWatchpointCommandList : public CommandObjectParsed { public: - CommandObjectWatchpointCommandList (CommandInterpreter &interpreter) : - CommandObjectParsed(interpreter, - "list", - "List the script or set of commands to be executed when the watchpoint is hit.", - nullptr) - { - CommandArgumentEntry arg; - CommandArgumentData wp_id_arg; - - // Define the first (and only) variant of this arg. - wp_id_arg.arg_type = eArgTypeWatchpointID; - wp_id_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (wp_id_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - } + CommandObjectWatchpointCommandList(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "list", "List the script or set of " + "commands to be executed when " + "the watchpoint is hit.", + nullptr) { + CommandArgumentEntry arg; + CommandArgumentData wp_id_arg; + + // Define the first (and only) variant of this arg. + wp_id_arg.arg_type = eArgTypeWatchpointID; + wp_id_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(wp_id_arg); - ~CommandObjectWatchpointCommandList() override = default; + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectWatchpointCommandList() override = default; protected: - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - - if (target == nullptr) - { - result.AppendError ("There is not a current executable; there are no watchpoints for which to list commands"); - result.SetStatus (eReturnStatusFailed); - return false; - } + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + + if (target == nullptr) { + result.AppendError("There is not a current executable; there are no " + "watchpoints for which to list commands"); + result.SetStatus(eReturnStatusFailed); + return false; + } - const WatchpointList &watchpoints = target->GetWatchpointList(); - size_t num_watchpoints = watchpoints.GetSize(); + const WatchpointList &watchpoints = target->GetWatchpointList(); + size_t num_watchpoints = watchpoints.GetSize(); - if (num_watchpoints == 0) - { - result.AppendError ("No watchpoints exist for which to list commands"); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (num_watchpoints == 0) { + result.AppendError("No watchpoints exist for which to list commands"); + result.SetStatus(eReturnStatusFailed); + return false; + } - if (command.GetArgumentCount() == 0) - { - result.AppendError ("No watchpoint specified for which to list the commands"); - result.SetStatus (eReturnStatusFailed); - return false; - } + if (command.GetArgumentCount() == 0) { + result.AppendError( + "No watchpoint specified for which to list the commands"); + result.SetStatus(eReturnStatusFailed); + return false; + } - std::vector<uint32_t> valid_wp_ids; - if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, valid_wp_ids)) - { - result.AppendError("Invalid watchpoints specification."); - result.SetStatus(eReturnStatusFailed); - return false; - } + std::vector<uint32_t> valid_wp_ids; + if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, + valid_wp_ids)) { + result.AppendError("Invalid watchpoints specification."); + result.SetStatus(eReturnStatusFailed); + return false; + } - result.SetStatus(eReturnStatusSuccessFinishNoResult); - const size_t count = valid_wp_ids.size(); - for (size_t i = 0; i < count; ++i) - { - uint32_t cur_wp_id = valid_wp_ids.at (i); - if (cur_wp_id != LLDB_INVALID_WATCH_ID) - { - Watchpoint *wp = target->GetWatchpointList().FindByID (cur_wp_id).get(); - - if (wp) - { - const WatchpointOptions *wp_options = wp->GetOptions(); - if (wp_options) - { - // Get the callback baton associated with the current watchpoint. - const Baton *baton = wp_options->GetBaton(); - if (baton) - { - result.GetOutputStream().Printf ("Watchpoint %u:\n", cur_wp_id); - result.GetOutputStream().IndentMore (); - baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull); - result.GetOutputStream().IndentLess (); - } - else - { - result.AppendMessageWithFormat ("Watchpoint %u does not have an associated command.\n", - cur_wp_id); - } - } - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendErrorWithFormat("Invalid watchpoint ID: %u.\n", cur_wp_id); - result.SetStatus (eReturnStatusFailed); - } + result.SetStatus(eReturnStatusSuccessFinishNoResult); + const size_t count = valid_wp_ids.size(); + for (size_t i = 0; i < count; ++i) { + uint32_t cur_wp_id = valid_wp_ids.at(i); + if (cur_wp_id != LLDB_INVALID_WATCH_ID) { + Watchpoint *wp = target->GetWatchpointList().FindByID(cur_wp_id).get(); + + if (wp) { + const WatchpointOptions *wp_options = wp->GetOptions(); + if (wp_options) { + // Get the callback baton associated with the current watchpoint. + const Baton *baton = wp_options->GetBaton(); + if (baton) { + result.GetOutputStream().Printf("Watchpoint %u:\n", cur_wp_id); + result.GetOutputStream().IndentMore(); + baton->GetDescription(&result.GetOutputStream(), + eDescriptionLevelFull); + result.GetOutputStream().IndentLess(); + } else { + result.AppendMessageWithFormat( + "Watchpoint %u does not have an associated command.\n", + cur_wp_id); } + } + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat("Invalid watchpoint ID: %u.\n", + cur_wp_id); + result.SetStatus(eReturnStatusFailed); } - - return result.Succeeded(); + } } + + return result.Succeeded(); + } }; //------------------------------------------------------------------------- // CommandObjectWatchpointCommand //------------------------------------------------------------------------- -CommandObjectWatchpointCommand::CommandObjectWatchpointCommand(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "command", "Commands for adding, removing and examining LLDB commands " - "executed when the watchpoint is hit (watchpoint 'commmands').", - "command <sub-command> [<sub-command-options>] <watchpoint-id>") -{ - CommandObjectSP add_command_object (new CommandObjectWatchpointCommandAdd (interpreter)); - CommandObjectSP delete_command_object (new CommandObjectWatchpointCommandDelete (interpreter)); - CommandObjectSP list_command_object (new CommandObjectWatchpointCommandList (interpreter)); - - add_command_object->SetCommandName ("watchpoint command add"); - delete_command_object->SetCommandName ("watchpoint command delete"); - list_command_object->SetCommandName ("watchpoint command list"); - - LoadSubCommand ("add", add_command_object); - LoadSubCommand ("delete", delete_command_object); - LoadSubCommand ("list", list_command_object); +CommandObjectWatchpointCommand::CommandObjectWatchpointCommand( + CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "command", + "Commands for adding, removing and examining LLDB commands " + "executed when the watchpoint is hit (watchpoint 'commmands').", + "command <sub-command> [<sub-command-options>] <watchpoint-id>") { + CommandObjectSP add_command_object( + new CommandObjectWatchpointCommandAdd(interpreter)); + CommandObjectSP delete_command_object( + new CommandObjectWatchpointCommandDelete(interpreter)); + CommandObjectSP list_command_object( + new CommandObjectWatchpointCommandList(interpreter)); + + add_command_object->SetCommandName("watchpoint command add"); + delete_command_object->SetCommandName("watchpoint command delete"); + list_command_object->SetCommandName("watchpoint command list"); + + LoadSubCommand("add", add_command_object); + LoadSubCommand("delete", delete_command_object); + LoadSubCommand("list", list_command_object); } CommandObjectWatchpointCommand::~CommandObjectWatchpointCommand() = default; diff --git a/lldb/source/Commands/CommandObjectWatchpointCommand.h b/lldb/source/Commands/CommandObjectWatchpointCommand.h index d77b32a..63152f2 100644 --- a/lldb/source/Commands/CommandObjectWatchpointCommand.h +++ b/lldb/source/Commands/CommandObjectWatchpointCommand.h @@ -16,10 +16,9 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-types.h" -#include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/CommandObjectMultiword.h" - +#include "lldb/Interpreter/Options.h" +#include "lldb/lldb-types.h" namespace lldb_private { @@ -27,12 +26,11 @@ namespace lldb_private { // CommandObjectMultiwordWatchpoint //------------------------------------------------------------------------- -class CommandObjectWatchpointCommand : public CommandObjectMultiword -{ +class CommandObjectWatchpointCommand : public CommandObjectMultiword { public: - CommandObjectWatchpointCommand (CommandInterpreter &interpreter); + CommandObjectWatchpointCommand(CommandInterpreter &interpreter); - ~CommandObjectWatchpointCommand() override; + ~CommandObjectWatchpointCommand() override; }; } // namespace lldb_private |