llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Michael Christensen (mdko) <details> <summary>Changes</summary> We'd like a way to select the current thread by its thread ID (rather than its internal LLDB thread index). This PR adds a `-t` option (`--thread_id` long option) that tells the `thread select` command to interpret the `<thread-index>` argument as a thread ID. Here's an example of it working: ``` michristensen@<!-- -->devbig356 llvm/llvm-project (thread-select-tid) ยป ../Debug/bin/lldb ~/scratch/cpp/threading/a.out (lldb) target create "/home/michristensen/scratch/cpp/threading/a.out" Current executable set to '/home/michristensen/scratch/cpp/threading/a.out' (x86_64). (lldb) b 18 Breakpoint 1: where = a.out`main + 80 at main.cpp:18:12, address = 0x0000000000000850 (lldb) run Process 215715 launched: '/home/michristensen/scratch/cpp/threading/a.out' (x86_64) This is a thread, i=1 This is a thread, i=2 This is a thread, i=3 This is a thread, i=4 This is a thread, i=5 Process 215715 stopped * thread #<!-- -->1, name = 'a.out', stop reason = breakpoint 1.1 frame #<!-- -->0: 0x0000555555400850 a.out`main at main.cpp:18:12 15 for (int i = 0; i < 5; i++) { 16 pthread_create(&thread_ids[i], NULL, foo, NULL); 17 } -> 18 for (int i = 0; i < 5; i++) { 19 pthread_join(thread_ids[i], NULL); 20 } 21 return 0; (lldb) thread select 2 * thread #<!-- -->2, name = 'a.out' frame #<!-- -->0: 0x00007ffff68f9918 libc.so.6`__nanosleep + 72 libc.so.6`__nanosleep: -> 0x7ffff68f9918 <+72>: cmpq $-0x1000, %rax ; imm = 0xF000 0x7ffff68f991e <+78>: ja 0x7ffff68f9952 ; <+130> 0x7ffff68f9920 <+80>: movl %edx, %edi 0x7ffff68f9922 <+82>: movl %eax, 0xc(%rsp) (lldb) thread info thread #<!-- -->2: tid = 216047, 0x00007ffff68f9918 libc.so.6`__nanosleep + 72, name = 'a.out' (lldb) thread list Process 215715 stopped thread #<!-- -->1: tid = 215715, 0x0000555555400850 a.out`main at main.cpp:18:12, name = 'a.out', stop reason = breakpoint 1.1 * thread #<!-- -->2: tid = 216047, 0x00007ffff68f9918 libc.so.6`__nanosleep + 72, name = 'a.out' thread #<!-- -->3: tid = 216048, 0x00007ffff68f9918 libc.so.6`__nanosleep + 72, name = 'a.out' thread #<!-- -->4: tid = 216049, 0x00007ffff68f9918 libc.so.6`__nanosleep + 72, name = 'a.out' thread #<!-- -->5: tid = 216050, 0x00007ffff68f9918 libc.so.6`__nanosleep + 72, name = 'a.out' thread #<!-- -->6: tid = 216051, 0x00007ffff68f9918 libc.so.6`__nanosleep + 72, name = 'a.out' (lldb) thread select 215715 error: invalid thread #<!-- -->215715. (lldb) thread select -t 215715 * thread #<!-- -->1, name = 'a.out', stop reason = breakpoint 1.1 frame #<!-- -->0: 0x0000555555400850 a.out`main at main.cpp:18:12 15 for (int i = 0; i < 5; i++) { 16 pthread_create(&thread_ids[i], NULL, foo, NULL); 17 } -> 18 for (int i = 0; i < 5; i++) { 19 pthread_join(thread_ids[i], NULL); 20 } 21 return 0; (lldb) thread select -t 216051 * thread #<!-- -->6, name = 'a.out' frame #<!-- -->0: 0x00007ffff68f9918 libc.so.6`__nanosleep + 72 libc.so.6`__nanosleep: -> 0x7ffff68f9918 <+72>: cmpq $-0x1000, %rax ; imm = 0xF000 0x7ffff68f991e <+78>: ja 0x7ffff68f9952 ; <+130> 0x7ffff68f9920 <+80>: movl %edx, %edi 0x7ffff68f9922 <+82>: movl %eax, 0xc(%rsp) (lldb) thread select 3 * thread #<!-- -->3, name = 'a.out' frame #<!-- -->0: 0x00007ffff68f9918 libc.so.6`__nanosleep + 72 libc.so.6`__nanosleep: -> 0x7ffff68f9918 <+72>: cmpq $-0x1000, %rax ; imm = 0xF000 0x7ffff68f991e <+78>: ja 0x7ffff68f9952 ; <+130> 0x7ffff68f9920 <+80>: movl %edx, %edi 0x7ffff68f9922 <+82>: movl %eax, 0xc(%rsp) (lldb) thread select -t 216048 * thread #<!-- -->3, name = 'a.out' frame #<!-- -->0: 0x00007ffff68f9918 libc.so.6`__nanosleep + 72 libc.so.6`__nanosleep: -> 0x7ffff68f9918 <+72>: cmpq $-0x1000, %rax ; imm = 0xF000 0x7ffff68f991e <+78>: ja 0x7ffff68f9952 ; <+130> 0x7ffff68f9920 <+80>: movl %edx, %edi 0x7ffff68f9922 <+82>: movl %eax, 0xc(%rsp) (lldb) thread select --thread_id 216048 * thread #<!-- -->3, name = 'a.out' frame #<!-- -->0: 0x00007ffff68f9918 libc.so.6`__nanosleep + 72 libc.so.6`__nanosleep: -> 0x7ffff68f9918 <+72>: cmpq $-0x1000, %rax ; imm = 0xF000 0x7ffff68f991e <+78>: ja 0x7ffff68f9952 ; <+130> 0x7ffff68f9920 <+80>: movl %edx, %edi 0x7ffff68f9922 <+82>: movl %eax, 0xc(%rsp) (lldb) help thread select Change the currently selected thread. Syntax: thread select <cmd-options> <thread-index> Command Options Usage: thread select [-t] <thread-index> -t ( --thread_id ) Provide a thread ID instead of a thread index. This command takes options and free-form arguments. If your arguments resemble option specifiers (i.e., they start with a - or --), you must use ' -- ' between the end of the command options and the beginning of the arguments. (lldb) c Process 215715 resuming Process 215715 exited with status = 0 (0x00000000) ``` --- Full diff: https://github.com/llvm/llvm-project/pull/73596.diff 3 Files Affected: - (modified) lldb/source/Commands/CommandObjectThread.cpp (+53-6) - (modified) lldb/source/Commands/Options.td (+5) - (modified) lldb/test/API/commands/thread/select/TestThreadSelect.py (+20-3) ``````````diff diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index a9f5a4f8a4fbd71c..9384df319cc221dd 100644 --- a/lldb/source/Commands/CommandObjectThread.cpp +++ b/lldb/source/Commands/CommandObjectThread.cpp @@ -1129,8 +1129,44 @@ class CommandObjectThreadUntil : public CommandObjectParsed { // CommandObjectThreadSelect +#define LLDB_OPTIONS_thread_select +#include "CommandOptions.inc" + class CommandObjectThreadSelect : public CommandObjectParsed { public: + class CommandOptions : public Options { + public: + CommandOptions() { OptionParsingStarting(nullptr); } + + ~CommandOptions() override = default; + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_thread_id = false; + } + + Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, + ExecutionContext *execution_context) override { + const int short_option = m_getopt_table[option_idx].val; + switch (short_option) { + case 't': { + m_thread_id = true; + break; + } + + default: + llvm_unreachable("Unimplemented option"); + } + + return {}; + } + + llvm::ArrayRef<OptionDefinition> GetDefinitions() override { + return llvm::ArrayRef(g_thread_select_options); + } + + bool m_thread_id; + }; + CommandObjectThreadSelect(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "thread select", "Change the currently selected thread.", nullptr, @@ -1165,6 +1201,8 @@ class CommandObjectThreadSelect : public CommandObjectParsed { nullptr); } + Options *GetOptions() override { return &m_options; } + protected: void DoExecute(Args &command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); @@ -1173,22 +1211,29 @@ class CommandObjectThreadSelect : public CommandObjectParsed { return; } 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()); + "'%s' takes exactly one thread %s argument:\nUsage: %s\n", + m_cmd_name.c_str(), m_options.m_thread_id ? "ID" : "index", + m_cmd_syntax.c_str()); return; } uint32_t index_id; if (!llvm::to_integer(command.GetArgumentAtIndex(0), index_id)) { - result.AppendErrorWithFormat("Invalid thread index '%s'", + result.AppendErrorWithFormat("Invalid thread %s '%s'", + m_options.m_thread_id ? "ID" : "index", command.GetArgumentAtIndex(0)); return; } - Thread *new_thread = - process->GetThreadList().FindThreadByIndexID(index_id).get(); + Thread *new_thread = nullptr; + if (m_options.m_thread_id) { + new_thread = process->GetThreadList().FindThreadByID(index_id).get(); + } else { + new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get(); + } if (new_thread == nullptr) { - result.AppendErrorWithFormat("invalid thread #%s.\n", + result.AppendErrorWithFormat("invalid thread %s%s.\n", + m_options.m_thread_id ? "ID " : "#", command.GetArgumentAtIndex(0)); return; } @@ -1196,6 +1241,8 @@ class CommandObjectThreadSelect : public CommandObjectParsed { process->GetThreadList().SetSelectedThreadByID(new_thread->GetID(), true); result.SetStatus(eReturnStatusSuccessFinishNoResult); } + + CommandOptions m_options; }; // CommandObjectThreadList diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td index 542c78be5a12dada..23886046df8f673e 100644 --- a/lldb/source/Commands/Options.td +++ b/lldb/source/Commands/Options.td @@ -1117,6 +1117,11 @@ let Command = "thread plan list" in { Desc<"Display thread plans for unreported threads">; } +let Command = "thread select" in { + def thread_thread_id : Option<"thread_id", "t">, + Desc<"Provide a thread ID instead of a thread index.">; +} + let Command = "thread trace dump function calls" in { def thread_trace_dump_function_calls_file : Option<"file", "F">, Group<1>, Arg<"Filename">, diff --git a/lldb/test/API/commands/thread/select/TestThreadSelect.py b/lldb/test/API/commands/thread/select/TestThreadSelect.py index 91f8909471bf2bbe..4d01b82d9d947e5b 100644 --- a/lldb/test/API/commands/thread/select/TestThreadSelect.py +++ b/lldb/test/API/commands/thread/select/TestThreadSelect.py @@ -12,17 +12,34 @@ def test_invalid_arg(self): self, "// break here", lldb.SBFileSpec("main.cpp") ) - self.expect( - "thread select -1", error=True, startstr="error: Invalid thread index '-1'" - ) self.expect( "thread select 0x1ffffffff", error=True, startstr="error: Invalid thread index '0x1ffffffff'", ) + self.expect( + "thread select -t 0x1ffffffff", + error=True, + startstr="error: Invalid thread ID '0x1ffffffff'", + ) # Parses but not a valid thread id. self.expect( "thread select 0xffffffff", error=True, startstr="error: invalid thread #0xffffffff.", ) + self.expect( + "thread select -t 0xffffffff", + error=True, + startstr="error: invalid thread ID 0xffffffff.", + ) + + def test_thread_select_tid(self): + self.build() + + lldbutil.run_to_source_breakpoint( + self, "// break here", lldb.SBFileSpec("main.cpp") + ) + self.runCmd( + "thread select -t %d" % self.thread().GetThreadID(), + ) `````````` </details> https://github.com/llvm/llvm-project/pull/73596 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits