Index: lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp =================================================================== --- lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp +++ lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp @@ -304,33 +304,53 @@ StructuredData::DictionarySP thread_info_sp = GetInterface().GetThreadsInfo(); - // FIXME: Need to sort the dictionary otherwise the thread ids won't match the - // thread indices. - if (!thread_info_sp) return ScriptedInterface::ErrorWithMessage( LLVM_PRETTY_FUNCTION, "Couldn't fetch thread list from Scripted Process.", error); - auto create_scripted_thread = - [this, &old_thread_list, &error, - &new_thread_list](ConstString key, StructuredData::Object *val) -> bool { + // Because `StructuredData::Dictionary` uses a `std::map` for storage, each item is sorted based on the key alphabetical + // order. Since `GetThreadsInfo` provides thread indices as the key element, + // thread info comes ordered alphabetically, instead of numerically, so we + // need to sort the thread indices before creating thread. + + StructuredData::ArraySP keys = thread_info_sp->GetKeys(); + + std::vector sorted_keys(keys->GetSize()); + auto sort_keys = [&sorted_keys](StructuredData::Object *item) -> bool { + if (!item) + return false; + + llvm::StringRef value = item->GetStringValue(); + size_t idx = 0; + + // Make sure the provided index is actually an integer + if (!llvm::to_integer(value, idx)) + return false; + + sorted_keys[idx] = value; + return true; + }; + + size_t thread_count = thread_info_sp->GetSize(); + + if (!keys->ForEach(sort_keys) || sorted_keys.size() != thread_count) + // Might be worth showing the unsorted thread list instead of return early. + return ScriptedInterface::ErrorWithMessage( + LLVM_PRETTY_FUNCTION, "Couldn't sort thread list.", error); + + for (size_t idx = 0; idx < thread_count; idx++) { + llvm::StringRef key = sorted_keys[idx]; + StructuredData::ObjectSP val = thread_info_sp->GetValueForKey(key); if (!val) return ScriptedInterface::ErrorWithMessage( LLVM_PRETTY_FUNCTION, "Invalid thread info object", error); - lldb::tid_t tid = LLDB_INVALID_THREAD_ID; - if (!llvm::to_integer(key.AsCString(), tid)) + uint32_t thread_idx = UINT32_MAX; + if (!llvm::to_integer(key, thread_idx)) return ScriptedInterface::ErrorWithMessage( - LLVM_PRETTY_FUNCTION, "Invalid thread id", error); - - if (ThreadSP thread_sp = - old_thread_list.FindThreadByID(tid, false /*=can_update*/)) { - // If the thread was already in the old_thread_list, - // just add it back to the new_thread_list. - new_thread_list.AddThread(thread_sp); - return true; - } + LLVM_PRETTY_FUNCTION, "Invalid thread index", error); auto thread_or_error = ScriptedThread::Create(*this, val->GetAsGeneric()); @@ -346,16 +366,12 @@ return ScriptedInterface::ErrorWithMessage( LLVM_PRETTY_FUNCTION, llvm::Twine("Invalid Register Context for thread " + - llvm::Twine(key.AsCString())) + llvm::Twine(key.data())) .str(), error); new_thread_list.AddThread(thread_sp); - - return true; - }; - - thread_info_sp->ForEach(create_scripted_thread); + } return new_thread_list.GetSize(false) > 0; }