Index: lldb/include/lldb/Target/Process.h =================================================================== --- lldb/include/lldb/Target/Process.h +++ lldb/include/lldb/Target/Process.h @@ -732,6 +732,12 @@ void SetShouldDetach(bool b) { m_should_detach = b; } + /// Get the image vector for the current process. + /// + /// \return + /// The constant reference to the member m_image_tokens. + const std::vector& GetImageTokens() { return m_image_tokens; } + /// Get the image information address for the current process. /// /// Some runtimes have system functions that can help dynamic loaders locate Index: lldb/source/Commands/CommandObjectProcess.cpp =================================================================== --- lldb/source/Commands/CommandObjectProcess.cpp +++ lldb/source/Commands/CommandObjectProcess.cpp @@ -912,6 +912,15 @@ ~CommandObjectProcessLoad() override = default; + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { + + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, + request, nullptr); + } + Options *GetOptions() override { return &m_options; } protected: @@ -977,6 +986,24 @@ ~CommandObjectProcessUnload() override = default; + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { + + if (request.GetCursorIndex() != 0) + return; + + Process *process = m_exe_ctx.GetProcessPtr(); + + const std::vector &tokens = process->GetImageTokens(); + const size_t token_num = tokens.size(); + for(size_t token = 0; token < token_num; ++ token) { + if (tokens[token] == LLDB_INVALID_IMAGE_TOKEN) + continue; + request.TryCompleteCurrentArg(std::to_string(token)); + } + } + protected: bool DoExecute(Args &command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); Index: lldb/test/API/functionalities/completion/Makefile =================================================================== --- lldb/test/API/functionalities/completion/Makefile +++ lldb/test/API/functionalities/completion/Makefile @@ -1,3 +1,10 @@ CXX_SOURCES := main.cpp +USE_LIBDL := 1 + +a.out: lib_shared + +lib_shared: + $(MAKE) -f $(MAKEFILE_RULES) \ + DYLIB_ONLY=YES DYLIB_CXX_SOURCES=shared.cpp DYLIB_NAME=shared include Makefile.rules Index: lldb/test/API/functionalities/completion/TestCompletion.py =================================================================== --- lldb/test/API/functionalities/completion/TestCompletion.py +++ lldb/test/API/functionalities/completion/TestCompletion.py @@ -85,6 +85,26 @@ ['mips', 'arm64']) + @skipUnlessPlatform(["linux"]) + def test_process_unload(self): + """Test the completion for "process unload " """ + # This tab completion should not work without a running process. + self.complete_from_to('process unload ', + 'process unload ') + + self.build() + lldbutil.run_to_source_breakpoint(self, '// Break here', lldb.SBFileSpec("main.cpp")) + err = lldb.SBError() + self.process().LoadImage(lldb.SBFileSpec(self.getBuildArtifact("libshared.so")), err) + self.assertTrue(err.Success(), str(err) + str(self.getBuildArtifact("libshared.so"))) + + self.complete_from_to('process unload ', + 'process unload 0') + + self.process().UnloadImage(0) + self.complete_from_to('process unload ', + 'process unload ') + def test_process_signal(self): # The tab completion for "process signal" won't work without a running process. self.complete_from_to('process signal ', Index: lldb/test/API/functionalities/completion/shared.cpp =================================================================== --- /dev/null +++ lldb/test/API/functionalities/completion/shared.cpp @@ -0,0 +1,3 @@ +int foo() { + return 123; +}