[Lldb-commits] [lldb] Add option to pass thread ID to thread select command (PR #73596)
https://github.com/mdko created https://github.com/llvm/llvm-project/pull/73596 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 `` 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 = 0x0850 (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: 0x55400850 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: 0x768f9918 libc.so.6`__nanosleep + 72 libc.so.6`__nanosleep: -> 0x768f9918 <+72>: cmpq $-0x1000, %rax ; imm = 0xF000 0x768f991e <+78>: ja 0x768f9952 ; <+130> 0x768f9920 <+80>: movl %edx, %edi 0x768f9922 <+82>: movl %eax, 0xc(%rsp) (lldb) thread info thread #2: tid = 216047, 0x768f9918 libc.so.6`__nanosleep + 72, name = 'a.out' (lldb) thread list Process 215715 stopped thread #1: tid = 215715, 0x55400850 a.out`main at main.cpp:18:12, name = 'a.out', stop reason = breakpoint 1.1 * thread #2: tid = 216047, 0x768f9918 libc.so.6`__nanosleep + 72, name = 'a.out' thread #3: tid = 216048, 0x768f9918 libc.so.6`__nanosleep + 72, name = 'a.out' thread #4: tid = 216049, 0x768f9918 libc.so.6`__nanosleep + 72, name = 'a.out' thread #5: tid = 216050, 0x768f9918 libc.so.6`__nanosleep + 72, name = 'a.out' thread #6: tid = 216051, 0x768f9918 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: 0x55400850 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: 0x768f9918 libc.so.6`__nanosleep + 72 libc.so.6`__nanosleep: -> 0x768f9918 <+72>: cmpq $-0x1000, %rax ; imm = 0xF000 0x768f991e <+78>: ja 0x768f9952 ; <+130> 0x768f9920 <+80>: movl %edx, %edi 0x768f9922 <+82>: movl %eax, 0xc(%rsp) (lldb) thread select 3 * thread #3, name = 'a.out' frame #0: 0x768f9918 libc.so.6`__nanosleep + 72 libc.so.6`__nanosleep: -> 0x768f9918 <+72>: cmpq $-0x1000, %rax ; imm = 0xF000 0x768f991e <+78>: ja 0x768f9952 ; <+130> 0x768f9920 <+80>: movl %edx, %edi 0x768f9922 <+82>: movl %eax, 0xc(%rsp) (lldb) thread select -t 216048 * thread #3, name = 'a.out' frame #0: 0x768f9918 libc.so.6`__nanosleep + 72 libc.so.6`__nanosleep: -> 0x768f9918 <+72>: cmpq $-0x1000, %rax ; imm = 0xF000 0x768f991e <+78>: ja 0x768f9952 ; <+130> 0x768f9920 <+80>: movl %edx, %edi 0x768f9922 <+82>: movl %eax, 0xc(%rsp) (lldb) thread select --thread_id 216048 * thread #3, name = 'a.out' frame #0: 0x768f9918 libc.so.6`__nanosleep + 72 libc.so.6`__nanosleep: -> 0x768f9918 <+72>: cmpq $-0x1000, %rax ; imm = 0xF000 0x768f991e <+78>: ja 0x768f9952 ; <+130> 0x768f9920 <+80>: movl %edx, %edi 0x768f9922 <+82>: movl %eax, 0xc(%rsp) (lldb) help thread select Change the currently selected thread. Syntax: thread select Command Options Usage: thread select [-t] -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 (0x) ``` >From 97a6e23c85457a14c91c5800fa03bb872e6f1fa6 Mon Sep 17 00:00:00 2001 From: Michael Christensen Date: Mon, 27 Nov 2023 12:49:24 -0800 Subject: [PATCH] Add option to pass thread ID to t
[Lldb-commits] [lldb] Add option to pass thread ID to thread select command (PR #73596)
mdko wrote: CC @jeffreytan81 @clayborg 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
[Lldb-commits] [lldb] Add option to pass thread ID to thread select command (PR #73596)
mdko wrote: @jimingham So it seems that when `-t ` is supplied, the user shouldn't be able to specify a thread index as well, e.g. the following is disallowed: ``` thread select -t 216051 1 ``` Would it make sense then for `thread select` to take two possible mutually exclusive options (`-t `) and (`-i `), with the `-i` option being the default (i.e. doesn't need to be specified)? e.g. ``` thread select -t 216051 ``` and ``` thread select -i 1 thread select 1 ``` (where the `-i` doesn't need to be supplied by default)? > It makes the completer much easier to hook up since the option value can > complete against the native thread ID's Sounds good, I'll work on adding the complete for the native thread ID option with the above change. 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
[Lldb-commits] [lldb] Add option to pass thread ID to thread select command (PR #73596)
https://github.com/mdko updated https://github.com/llvm/llvm-project/pull/73596 >From 97a6e23c85457a14c91c5800fa03bb872e6f1fa6 Mon Sep 17 00:00:00 2001 From: Michael Christensen Date: Mon, 27 Nov 2023 12:49:24 -0800 Subject: [PATCH 1/2] Add option to pass thread ID to thread select command --- lldb/source/Commands/CommandObjectThread.cpp | 59 +-- lldb/source/Commands/Options.td | 5 ++ .../thread/select/TestThreadSelect.py | 23 +++- 3 files changed, 78 insertions(+), 9 deletions(-) diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index a9f5a4f8a4fbd71..9384df319cc221d 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 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 542c78be5a12dad..23886046df8f673 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/AP
[Lldb-commits] [lldb] Add option to pass thread ID to thread select command (PR #73596)
https://github.com/mdko updated https://github.com/llvm/llvm-project/pull/73596 >From 97a6e23c85457a14c91c5800fa03bb872e6f1fa6 Mon Sep 17 00:00:00 2001 From: Michael Christensen Date: Mon, 27 Nov 2023 12:49:24 -0800 Subject: [PATCH 1/3] Add option to pass thread ID to thread select command --- lldb/source/Commands/CommandObjectThread.cpp | 59 +-- lldb/source/Commands/Options.td | 5 ++ .../thread/select/TestThreadSelect.py | 23 +++- 3 files changed, 78 insertions(+), 9 deletions(-) diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index a9f5a4f8a4fbd71..9384df319cc221d 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 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 542c78be5a12dad..23886046df8f673 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/AP
[Lldb-commits] [lldb] Add option to pass thread ID to thread select command (PR #73596)
mdko wrote: [Latest changes](https://github.com/llvm/llvm-project/pull/73596/commits/34045b9b2e04e01fed142ad2d7f4503e69646c9f) implement reviewer suggestions: * `thread_id` option is now `thread-id` * This option takes a value rather than causing original argument to be interpreted differently * This option is now in a separate grouping, so we can show the two separate ways of calling this command: `thread select ` and ` thread select [-t ]`. This is similar to what shows up with `memory write ...` Example usage: ``` michristensen@devbig356 llvm/Debug » ./bin/lldb ~/scratch/cpp/virtual/a.out error: module importing failed: This script interpreter does not support importing modules. NAME PASS STOP NOTIFY === === === === SIGPIPE true falsefalse (lldb) target create "/home/michristensen/scratch/cpp/virtual/a.out" Current executable set to '/home/michristensen/scratch/cpp/virtual/a.out' (x86_64). (lldb) b 18 Breakpoint 1: where = a.out`main + 13 at t2.cpp:20:14, address = 0x0c2d (lldb) ^D michristensen@devbig356 llvm/Debug » michristensen@devbig356 llvm/Debug » ./bin/lldb ~/scratch/cpp/threading/a.out error: module importing failed: This script interpreter does not support importing modules. NAME PASS STOP NOTIFY === === === === SIGPIPE true falsefalse (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 = 0x0850 (lldb) run Process 3517265 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 3517265 stopped * thread #1, name = 'a.out', stop reason = breakpoint 1.1 frame #0: 0x55400850 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: 0x768f9918 libc.so.6`__nanosleep + 72 libc.so.6`__nanosleep: -> 0x768f9918 <+72>: cmpq $-0x1000, %rax ; imm = 0xF000 0x768f991e <+78>: ja 0x768f9952 ; <+130> 0x768f9920 <+80>: movl %edx, %edi 0x768f9922 <+82>: movl %eax, 0xc(%rsp) (lldb) thread info thread #2: tid = 3517533, 0x768f9918 libc.so.6`__nanosleep + 72, name = 'a.out' (lldb) thread list Process 3517265 stopped thread #1: tid = 3517265, 0x55400850 a.out`main at main.cpp:18:12, name = 'a.out', stop reason = breakpoint 1.1 * thread #2: tid = 3517533, 0x768f9918 libc.so.6`__nanosleep + 72, name = 'a.out' thread #3: tid = 3517534, 0x768f9918 libc.so.6`__nanosleep + 72, name = 'a.out' thread #4: tid = 3517535, 0x768f9918 libc.so.6`__nanosleep + 72, name = 'a.out' thread #5: tid = 3517536, 0x768f9918 libc.so.6`__nanosleep + 72, name = 'a.out' thread #6: tid = 3517537, 0x768f9918 libc.so.6`__nanosleep + 72, name = 'a.out' (lldb) thread select 3517265 error: Invalid thread #3517265. (lldb) thread select -t 3517265 * thread #1, name = 'a.out', stop reason = breakpoint 1.1 frame #0: 0x55400850 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 3517534 * thread #3, name = 'a.out' frame #0: 0x768f9918 libc.so.6`__nanosleep + 72 libc.so.6`__nanosleep: -> 0x768f9918 <+72>: cmpq $-0x1000, %rax ; imm = 0xF000 0x768f991e <+78>: ja 0x768f9952 ; <+130> 0x768f9920 <+80>: movl %edx, %edi 0x768f9922 <+82>: movl %eax, 0xc(%rsp) (lldb) thread select 6 * thread #6, name = 'a.out' frame #0: 0x768f9918 libc.so.6`__nanosleep + 72 libc.so.6`__nanosleep: -> 0x768f9918 <+72>: cmpq $-0x1000, %rax ; imm = 0xF000 0x768f991e <+78>: ja 0x768f9952 ; <+130> 0x768f9920 <+80>: movl %edx, %edi 0x768f9922 <+82>: movl %eax, 0xc(%rsp) (lldb) thread info thread #6: tid = 3517537, 0x768f9918 libc.so.6`__nanosleep + 72, name = 'a.out' (lldb) thread select -t 3517536 * thread #5, name = 'a.out' frame #0: 0x768f9918 libc.so.6`__nanosleep + 72 libc.so.6`__nanosleep: -> 0x768f9918 <+72>: cmpq $-0x1000, %rax ; imm = 0xF000 0x768f991e <+78>: ja 0x768f9952 ; <+130> 0x768f9920 <+80>: movl %edx, %edi 0x768f9922 <+82>: movl %eax, 0xc(%rsp) (lldb) thread info thread #5: tid = 3517536, 0x768f9918 libc.s
[Lldb-commits] [lldb] Add option to pass thread ID to thread select command (PR #73596)
@@ -1117,6 +1117,11 @@ let Command = "thread plan list" in { Desc<"Display thread plans for unreported threads">; } +let Command = "thread select" in { + def thread_select_thread_id : Option<"thread-id", "t">, Group<2>, +Arg<"ThreadID">, Desc<"Provide a thread ID instead of a thread index.">; mdko wrote: Yes it's a uint64_t: https://github.com/llvm/llvm-project/blob/35db35b7cfb80139ab6f23c7f10c47df5d1d7462/lldb/include/lldb/lldb-types.h#L82 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
[Lldb-commits] [lldb] Add option to pass thread ID to thread select command (PR #73596)
https://github.com/mdko edited 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
[Lldb-commits] [lldb] Add option to pass thread ID to thread select command (PR #73596)
@@ -1165,37 +1208,59 @@ class CommandObjectThreadSelect : public CommandObjectParsed { nullptr); } + Options *GetOptions() override { return &m_option_group; } + protected: void DoExecute(Args &command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); if (process == nullptr) { result.AppendError("no process"); return; -} else if (command.GetArgumentCount() != 1) { +} else if (m_options.m_thread_id == LLDB_INVALID_THREAD_ID && + command.GetArgumentCount() != 1) { result.AppendErrorWithFormat( - "'%s' takes exactly one thread index argument:\nUsage: %s\n", + "'%s' takes exactly one thread index argument, or a thread ID " + "option:\nUsage: %s\n", m_cmd_name.c_str(), 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'", - command.GetArgumentAtIndex(0)); +} else if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID && + command.GetArgumentCount() != 0) { + result.AppendErrorWithFormat("'%s' cannot take both a thread ID option " + "and a thread index argument:\nUsage: %s\n", + m_cmd_name.c_str(), m_cmd_syntax.c_str()); return; } -Thread *new_thread = -process->GetThreadList().FindThreadByIndexID(index_id).get(); -if (new_thread == nullptr) { - result.AppendErrorWithFormat("invalid thread #%s.\n", - command.GetArgumentAtIndex(0)); - return; +Thread *new_thread = nullptr; +if (command.GetArgumentCount() == 1) { + uint32_t index_id; + if (!llvm::to_integer(command.GetArgumentAtIndex(0), index_id)) { +result.AppendErrorWithFormat("Invalid thread index '%s'", + command.GetArgumentAtIndex(0)); +return; + } + new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get(); + if (new_thread == nullptr) { +result.AppendErrorWithFormat("Invalid thread #%s.\n", + command.GetArgumentAtIndex(0)); +return; + } +} else { + new_thread = + process->GetThreadList().FindThreadByID(m_options.m_thread_id).get(); + if (new_thread == nullptr) { +result.AppendErrorWithFormat("Invalid thread ID %lu.\n", mdko wrote: Thread IDs are shown as unsigned decimal, e.g.: ``` (lldb) thread list Process 2291372 stopped thread #1: tid = 2291372, 0x55400850 a.out`main at main.cpp:18:12, name = 'a.out', stop reason = breakpoint 1.1 * thread #2: tid = 2291686, 0x768f9918 libc.so.6`__nanosleep + 72, name = 'a.out' thread #3: tid = 2291688, 0x768f9918 libc.so.6`__nanosleep + 72, name = 'a.out' thread #4: tid = 2291690, 0x768f9918 libc.so.6`__nanosleep + 72, name = 'a.out' thread #5: tid = 2291691, 0x768f9918 libc.so.6`__nanosleep + 72, name = 'a.out' thread #6: tid = 2291692, 0x768f9918 libc.so.6`__nanosleep + 72, name = 'a.out' ``` 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
[Lldb-commits] [lldb] Add option to pass thread ID to thread select command (PR #73596)
https://github.com/mdko updated https://github.com/llvm/llvm-project/pull/73596 >From 97a6e23c85457a14c91c5800fa03bb872e6f1fa6 Mon Sep 17 00:00:00 2001 From: Michael Christensen Date: Mon, 27 Nov 2023 12:49:24 -0800 Subject: [PATCH 1/4] Add option to pass thread ID to thread select command --- lldb/source/Commands/CommandObjectThread.cpp | 59 +-- lldb/source/Commands/Options.td | 5 ++ .../thread/select/TestThreadSelect.py | 23 +++- 3 files changed, 78 insertions(+), 9 deletions(-) diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index a9f5a4f8a4fbd71..9384df319cc221d 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 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 542c78be5a12dad..23886046df8f673 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/AP
[Lldb-commits] [lldb] Add option to pass thread ID to thread select command (PR #73596)
https://github.com/mdko updated https://github.com/llvm/llvm-project/pull/73596 >From 97a6e23c85457a14c91c5800fa03bb872e6f1fa6 Mon Sep 17 00:00:00 2001 From: Michael Christensen Date: Mon, 27 Nov 2023 12:49:24 -0800 Subject: [PATCH 1/5] Add option to pass thread ID to thread select command --- lldb/source/Commands/CommandObjectThread.cpp | 59 +-- lldb/source/Commands/Options.td | 5 ++ .../thread/select/TestThreadSelect.py | 23 +++- 3 files changed, 78 insertions(+), 9 deletions(-) diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index a9f5a4f8a4fbd71..9384df319cc221d 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 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 542c78be5a12dad..23886046df8f673 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/AP
[Lldb-commits] [lldb] Add option to pass thread ID to thread select command (PR #73596)
mdko wrote: [Latest changes]() update help and usage text, format specifier, add a general thread ID completion mechanism, and use this thread ID completion in the `thread select -t` argument. (If the thread ID completer is satisfactory, I can add it to other ThreadID args in [Options.td](https://github.com/mdko/llvm-project/blob/main/lldb/source/Commands/Options.td) in a later PR.) Example: ``` michristensen@devbig356 llvm/Debug » ./bin/lldb ~/scratch/cpp/threading/a.out NAME PASS STOP NOTIFY === === === === SIGPIPE true falsefalse (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 = 0x0850 (lldb) run Process 2749371 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 2749371 stopped * thread #1, name = 'a.out', stop reason = breakpoint 1.1 frame #0: 0x55400850 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 list Process 2749371 stopped * thread #1: tid = 2749371, 0x55400850 a.out`main at main.cpp:18:12, name = 'a.out', stop reason = breakpoint 1.1 thread #2: tid = 2749646, 0x768f9918 libc.so.6`__nanosleep + 72, name = 'a.out' thread #3: tid = 2749647, 0x768f9918 libc.so.6`__nanosleep + 72, name = 'a.out' thread #4: tid = 2749648, 0x768f9918 libc.so.6`__nanosleep + 72, name = 'a.out' thread #5: tid = 2749649, 0x768f9918 libc.so.6`__nanosleep + 72, name = 'a.out' thread #6: tid = 2749650, 0x768f9918 libc.so.6`__nanosleep + 72, name = 'a.out' (lldb) thread select -t 2749 Available completions: 2749371 -- * thread #1, name = 'a.out', stop reason = breakpoint 1.1 frame #0: 0x55400850 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; 2749646 -- thread #2, name = 'a.out' frame #0: 0x768f9918 libc.so.6`__nanosleep + 72 libc.so.6`__nanosleep: -> 0x768f9918 <+72>: cmpq $-0x1000, %rax ; imm = 0xF000 0x768f991e <+78>: ja 0x768f9952 ; <+130> 0x768f9920 <+80>: movl %edx, %edi 0x768f9922 <+82>: movl %eax, 0xc(%rsp) 2749647 -- thread #3, name = 'a.out' frame #0: 0x768f9918 libc.so.6`__nanosleep + 72 libc.so.6`__nanosleep: -> 0x768f9918 <+72>: cmpq $-0x1000, %rax ; imm = 0xF000 0x768f991e <+78>: ja 0x768f9952 ; <+130> 0x768f9920 <+80>: movl %edx, %edi 0x768f9922 <+82>: movl %eax, 0xc(%rsp) 2749648 -- thread #4, name = 'a.out' frame #0: 0x768f9918 libc.so.6`__nanosleep + 72 libc.so.6`__nanosleep: -> 0x768f9918 <+72>: cmpq $-0x1000, %rax ; imm = 0xF000 0x768f991e <+78>: ja 0x768f9952 ; <+130> 0x768f9920 <+80>: movl %edx, %edi 0x768f9922 <+82>: movl %eax, 0xc(%rsp) 2749649 -- thread #5, name = 'a.out' frame #0: 0x768f9918 libc.so.6`__nanosleep + 72 libc.so.6`__nanosleep: -> 0x768f9918 <+72>: cmpq $-0x1000, %rax ; imm = 0xF000 0x768f991e <+78>: ja 0x768f9952 ; <+130> 0x768f9920 <+80>: movl %edx, %edi 0x768f9922 <+82>: movl %eax, 0xc(%rsp) 2749650 -- thread #6, name = 'a.out' frame #0: 0x768f9918 libc.so.6`__nanosleep + 72 libc.so.6`__nanosleep: -> 0x768f9918 <+72>: cmpq $-0x1000, %rax ; imm = 0xF000 0x768f991e <+78>: ja 0x768f9952 ; <+130> 0x768f9920 <+80>: movl %edx, %edi 0x768f9922 <+82>: movl %eax, 0xc(%rsp) (lldb) thread select -t 2749371 * thread #1, name = 'a.out', stop reason = breakpoint 1.1 frame #0: 0x55400850 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 Available completions: 1 -- * thread #1, name = 'a.out', stop reason = breakpoint 1.1 frame #0: 0x55400850 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-commits] [lldb] Add option to pass thread ID to thread select command (PR #73596)
@@ -807,6 +808,23 @@ void CommandCompletions::TypeCategoryNames(CommandInterpreter &interpreter, }); } +void CommandCompletions::ThreadIDs(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { + const ExecutionContext &exe_ctx = interpreter.GetExecutionContext(); + if (!exe_ctx.HasProcessScope()) +return; + + ThreadList &threads = exe_ctx.GetProcessPtr()->GetThreadList(); + lldb::ThreadSP thread_sp; + for (uint32_t idx = 0; (thread_sp = threads.GetThreadAtIndex(idx)); ++idx) { mdko wrote: It's to avoid this warning: ``` /home/michristensen/llvm/llvm-project/lldb/source/Commands/CommandCompletions.cpp:820:36: warning: using the result of an assignment as a condition without parentheses [-Wparentheses] for (uint32_t idx = 0; thread_sp = threads.GetThreadAtIndex(idx); ++idx) { ~~^~~ /home/michristensen/llvm/llvm-project/lldb/source/Commands/CommandCompletions.cpp:820:36: note: place parentheses around the assignment to silence this warning for (uint32_t idx = 0; thread_sp = threads.GetThreadAtIndex(idx); ++idx) { ``` It's also consistent to how it was done in the ThreadIndex completer code: https://github.com/llvm/llvm-project/blob/e109a2ea37b20141aad8c4db4d39ff56e8a6dc4e/lldb/source/Commands/CommandCompletions.cpp#L776 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
[Lldb-commits] [lldb] Add option to pass thread ID to thread select command (PR #73596)
@@ -1296,10 +1296,11 @@ enum CompletionType { eRemoteDiskFileCompletion = (1u << 22), eRemoteDiskDirectoryCompletion = (1u << 23), eTypeCategoryNameCompletion = (1u << 24), + eThreadIDCompletion = (1u << 25), mdko wrote: @clayborg Is there anything special about `eCustomCompletion` being last? The comment in 1300-1302 seems to allude to this, but I don't see anything in the code base requiring this nor any other custom completions. 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
[Lldb-commits] [lldb] Add option to pass thread ID to thread select command (PR #73596)
@@ -1296,10 +1296,11 @@ enum CompletionType { eRemoteDiskFileCompletion = (1u << 22), eRemoteDiskDirectoryCompletion = (1u << 23), eTypeCategoryNameCompletion = (1u << 24), + eThreadIDCompletion = (1u << 25), mdko wrote: @jimingham What are your thoughts on putting eThreadIDCompletion before eCustomCompletion? (See @clayborg 's comments above) 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
[Lldb-commits] [lldb] Add option to pass thread ID to thread select command (PR #73596)
https://github.com/mdko updated https://github.com/llvm/llvm-project/pull/73596 >From 97a6e23c85457a14c91c5800fa03bb872e6f1fa6 Mon Sep 17 00:00:00 2001 From: Michael Christensen Date: Mon, 27 Nov 2023 12:49:24 -0800 Subject: [PATCH 1/6] Add option to pass thread ID to thread select command --- lldb/source/Commands/CommandObjectThread.cpp | 59 +-- lldb/source/Commands/Options.td | 5 ++ .../thread/select/TestThreadSelect.py | 23 +++- 3 files changed, 78 insertions(+), 9 deletions(-) diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index a9f5a4f8a4fbd..9384df319cc22 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 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 542c78be5a12d..23886046df8f6 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/comman
[Lldb-commits] [lldb] Add option to pass thread ID to thread select command (PR #73596)
mdko wrote: Latest change: * Reverts `eCustomCompletion` to original value * Moves `eThreadIDCompletion` after `eCustomCompletion` * Adds `eTerminatorCompletion` as last value in enum * Sets all values to 64 bit to future-proof it 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
[Lldb-commits] [lldb] Add option to pass thread ID to thread select command (PR #73596)
https://github.com/mdko updated https://github.com/llvm/llvm-project/pull/73596 >From 97a6e23c85457a14c91c5800fa03bb872e6f1fa6 Mon Sep 17 00:00:00 2001 From: Michael Christensen Date: Mon, 27 Nov 2023 12:49:24 -0800 Subject: [PATCH 1/7] Add option to pass thread ID to thread select command --- lldb/source/Commands/CommandObjectThread.cpp | 59 +-- lldb/source/Commands/Options.td | 5 ++ .../thread/select/TestThreadSelect.py | 23 +++- 3 files changed, 78 insertions(+), 9 deletions(-) diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index a9f5a4f8a4fbd..9384df319cc22 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 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 542c78be5a12d..23886046df8f6 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/comman
[Lldb-commits] [lldb] Add option to pass thread ID to thread select command (PR #73596)
@@ -1270,36 +1270,37 @@ enum WatchpointValueKind { }; enum CompletionType { - eNoCompletion = 0u, - eSourceFileCompletion = (1u << 0), - eDiskFileCompletion = (1u << 1), - eDiskDirectoryCompletion = (1u << 2), - eSymbolCompletion = (1u << 3), - eModuleCompletion = (1u << 4), - eSettingsNameCompletion = (1u << 5), - ePlatformPluginCompletion = (1u << 6), - eArchitectureCompletion = (1u << 7), - eVariablePathCompletion = (1u << 8), - eRegisterCompletion = (1u << 9), - eBreakpointCompletion = (1u << 10), - eProcessPluginCompletion = (1u << 11), - eDisassemblyFlavorCompletion = (1u << 12), - eTypeLanguageCompletion = (1u << 13), - eFrameIndexCompletion = (1u << 14), - eModuleUUIDCompletion = (1u << 15), - eStopHookIDCompletion = (1u << 16), - eThreadIndexCompletion = (1u << 17), - eWatchpointIDCompletion = (1u << 18), - eBreakpointNameCompletion = (1u << 19), - eProcessIDCompletion = (1u << 20), - eProcessNameCompletion = (1u << 21), - eRemoteDiskFileCompletion = (1u << 22), - eRemoteDiskDirectoryCompletion = (1u << 23), - eTypeCategoryNameCompletion = (1u << 24), - // This item serves two purposes. It is the last element in the enum, so - // you can add custom enums starting from here in your Option class. Also - // if you & in this bit the base code will not process the option. - eCustomCompletion = (1u << 25) + eNoCompletion = 0ul, + eSourceFileCompletion = (1ul << 0), + eDiskFileCompletion = (1ul << 1), + eDiskDirectoryCompletion = (1ul << 2), + eSymbolCompletion = (1ul << 3), + eModuleCompletion = (1ul << 4), + eSettingsNameCompletion = (1ul << 5), + ePlatformPluginCompletion = (1ul << 6), + eArchitectureCompletion = (1ul << 7), + eVariablePathCompletion = (1ul << 8), + eRegisterCompletion = (1ul << 9), + eBreakpointCompletion = (1ul << 10), + eProcessPluginCompletion = (1ul << 11), + eDisassemblyFlavorCompletion = (1ul << 12), + eTypeLanguageCompletion = (1ul << 13), + eFrameIndexCompletion = (1ul << 14), + eModuleUUIDCompletion = (1ul << 15), + eStopHookIDCompletion = (1ul << 16), + eThreadIndexCompletion = (1ul << 17), + eWatchpointIDCompletion = (1ul << 18), + eBreakpointNameCompletion = (1ul << 19), + eProcessIDCompletion = (1ul << 20), + eProcessNameCompletion = (1ul << 21), + eRemoteDiskFileCompletion = (1ul << 22), + eRemoteDiskDirectoryCompletion = (1ul << 23), + eTypeCategoryNameCompletion = (1ul << 24), + eCustomCompletion = (1ul << 25), + eThreadIDCompletion = (1ul << 26), + // This last enum element is just for input validation. + // Add new completions before this element. + eTerminatorCompletion = (1ul << 63) mdko wrote: @jimingham Thanks for the quick feedback, makes sense. Latest changes update `eTerminatorCompletion` value based on your comments. 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
[Lldb-commits] [lldb] Add option to pass thread ID to thread select command (PR #73596)
mdko wrote: @jimingham @clayborg IIUC I don't have merge permissions, otherwise I'd squash and merge this myself. Please let me know if there's anything I should do at this point. Thanks! 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
[Lldb-commits] [lldb] [easy] Fix spacing in help message of 'process save-core' command (PR #89445)
https://github.com/mdko created https://github.com/llvm/llvm-project/pull/89445 Very minor change to help message on `process save-core`. Adds space between two sentences explaining the `-p` option: "Specify a plugin name to create the core file.This allows core files to be saved in different formats." --> "Specify a plugin name to create the core file. This allows core files to be saved in different formats." Before: ``` (lldb) help process save-core Save the current process as a core file using an appropriate file type. Syntax: process save-core [-s corefile-style -p plugin-name] FILE Command Options Usage: process save-core [-p[]] [-s ] -p[] ( --plugin-name=[] ) Specify a plugin name to create the core file.This allows core files to be saved in different formats. -s ( --style ) Request a specific style of corefile to be saved. Values: full | modified-memory | stack 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. ``` After: ``` michristensen@devbig356 build/Debug » $HOME/llvm-sand/build/Debug/bin/lldb -x (lldb) help process save-core Save the current process as a core file using an appropriate file type. Syntax: process save-core [-s corefile-style -p plugin-name] FILE Command Options Usage: process save-core [-p[]] [-s ] -p[] ( --plugin-name=[] ) Specify a plugin name to create the core file. This allows core files to be saved in different formats. -s ( --style ) Request a specific style of corefile to be saved. Values: full | modified-memory | stack 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. ``` >From 38f81bc7c9581b2e5f8972b465c6b2461499437c Mon Sep 17 00:00:00 2001 From: Michael Christensen Date: Fri, 19 Apr 2024 11:54:45 -0700 Subject: [PATCH] fix spacing in help message of 'process save-core' command --- lldb/source/Commands/Options.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td index 62bbfdc117834f..00238d67d73215 100644 --- a/lldb/source/Commands/Options.td +++ b/lldb/source/Commands/Options.td @@ -784,7 +784,7 @@ let Command = "process save_core" in { EnumArg<"SaveCoreStyle">, Desc<"Request a specific style " "of corefile to be saved.">; def process_save_core_plugin_name : Option<"plugin-name", "p">, -OptionalArg<"Plugin">, Desc<"Specify a plugin name to create the core file." +OptionalArg<"Plugin">, Desc<"Specify a plugin name to create the core file. " "This allows core files to be saved in different formats.">; } ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits