diff --git a/lldb/examples/python/scripted_process/scripted_process.py b/lldb/examples/python/scripted_process/scripted_process.py --- a/lldb/examples/python/scripted_process/scripted_process.py +++ b/lldb/examples/python/scripted_process/scripted_process.py @@ -76,6 +76,15 @@ """ pass + def get_selected_thread_index(self): + """ Get the index of the selected scripted process thread. + + Returns: + Int: The thread index that should be selected by lldb. + (default: 0) + """ + return 0 + @abstractmethod def get_registers_for_thread(self, tid): """ Get the register context dictionary for a certain thread of diff --git a/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h b/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h --- a/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h +++ b/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h @@ -48,6 +48,8 @@ return nullptr; } + virtual uint32_t GetSelectedThreadIndex() { return LLDB_INVALID_INDEX32; } + virtual StructuredData::DictionarySP GetRegistersForThread(lldb::tid_t tid) { return nullptr; } diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp --- a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp +++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp @@ -359,6 +359,11 @@ void ScriptedProcess::RefreshStateAfterStop() { // Let all threads recover from stopping and do any clean up based on the // previous thread state (if any). + const uint32_t selected_thread_idx = GetInterface().GetSelectedThreadIndex(); + + if (selected_thread_idx != LLDB_INVALID_INDEX32 && + selected_thread_idx <= m_thread_list.GetSize()) + m_thread_list.SetSelectedThreadByIndexID(selected_thread_idx); } bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) { diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h @@ -44,6 +44,8 @@ StructuredData::DictionarySP GetThreadWithID(lldb::tid_t tid) override; + uint32_t GetSelectedThreadIndex() override; + StructuredData::DictionarySP GetRegistersForThread(lldb::tid_t tid) override; lldb::DataExtractorSP ReadMemoryAtAddress(lldb::addr_t address, size_t size, diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp @@ -113,6 +113,21 @@ return dict; } +uint32_t ScriptedProcessPythonInterface::GetSelectedThreadIndex() { + Status error; + StructuredData::ObjectSP obj = Dispatch("get_selected_thread_index", error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) + return LLDB_INVALID_INDEX32; + + const uint64_t val = obj->GetIntegerValue(LLDB_INVALID_INDEX32); + + if (!val || std::numeric_limits::max() <= val) + return LLDB_INVALID_INDEX32; + + return static_cast(val); +} + StructuredData::DictionarySP ScriptedProcessPythonInterface::GetRegistersForThread(lldb::tid_t tid) { // TODO: Implement diff --git a/lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py b/lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py --- a/lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py +++ b/lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py @@ -57,6 +57,9 @@ return data + def get_selected_thread_index(self): + return 3 + def get_loaded_images(self): # TODO: Iterate over corefile_target modules and build a data structure # from it.