1311128Sdim//===-- NativeThreadListDarwin.cpp ------------------------------------*- C++ 2311128Sdim//-*-===// 3311128Sdim// 4353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5353358Sdim// See https://llvm.org/LICENSE.txt for license information. 6353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7311128Sdim// 8311128Sdim//===----------------------------------------------------------------------===// 9311128Sdim// 10311128Sdim// Created by Greg Clayton on 6/19/07. 11311128Sdim// 12311128Sdim//===----------------------------------------------------------------------===// 13311128Sdim 14311128Sdim#include "NativeThreadListDarwin.h" 15311128Sdim 16311128Sdim// C includes 17311128Sdim#include <inttypes.h> 18311128Sdim#include <mach/vm_map.h> 19311128Sdim#include <sys/sysctl.h> 20311128Sdim 21311128Sdim// LLDB includes 22321369Sdim#include "lldb/Utility/Log.h" 23321369Sdim#include "lldb/Utility/Status.h" 24321369Sdim#include "lldb/Utility/Stream.h" 25311128Sdim#include "lldb/lldb-enumerations.h" 26311128Sdim 27311128Sdim#include "NativeProcessDarwin.h" 28311128Sdim#include "NativeThreadDarwin.h" 29311128Sdim 30311128Sdimusing namespace lldb; 31311128Sdimusing namespace lldb_private; 32311128Sdimusing namespace lldb_private::process_darwin; 33311128Sdim 34311128SdimNativeThreadListDarwin::NativeThreadListDarwin() 35311128Sdim : m_threads(), m_threads_mutex(), m_is_64_bit(false) {} 36311128Sdim 37311128SdimNativeThreadListDarwin::~NativeThreadListDarwin() {} 38311128Sdim 39311128Sdim// These methods will be accessed directly from NativeThreadDarwin 40311128Sdim#if 0 41311128Sdimnub_state_t 42311128SdimNativeThreadListDarwin::GetState(nub_thread_t tid) 43311128Sdim{ 44311128Sdim MachThreadSP thread_sp (GetThreadByID (tid)); 45311128Sdim if (thread_sp) 46311128Sdim return thread_sp->GetState(); 47311128Sdim return eStateInvalid; 48311128Sdim} 49311128Sdim 50311128Sdimconst char * 51311128SdimNativeThreadListDarwin::GetName (nub_thread_t tid) 52311128Sdim{ 53311128Sdim MachThreadSP thread_sp (GetThreadByID (tid)); 54311128Sdim if (thread_sp) 55311128Sdim return thread_sp->GetName(); 56311128Sdim return NULL; 57311128Sdim} 58311128Sdim#endif 59311128Sdim 60311128Sdim// TODO: figure out if we need to add this to NativeThreadDarwin yet. 61311128Sdim#if 0 62311128SdimThreadInfo::QoS 63311128SdimNativeThreadListDarwin::GetRequestedQoS (nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index) 64311128Sdim{ 65311128Sdim MachThreadSP thread_sp (GetThreadByID (tid)); 66311128Sdim if (thread_sp) 67311128Sdim return thread_sp->GetRequestedQoS(tsd, dti_qos_class_index); 68311128Sdim return ThreadInfo::QoS(); 69311128Sdim} 70311128Sdim 71311128Sdimnub_addr_t 72311128SdimNativeThreadListDarwin::GetPThreadT (nub_thread_t tid) 73311128Sdim{ 74311128Sdim MachThreadSP thread_sp (GetThreadByID (tid)); 75311128Sdim if (thread_sp) 76311128Sdim return thread_sp->GetPThreadT(); 77311128Sdim return INVALID_NUB_ADDRESS; 78311128Sdim} 79311128Sdim 80311128Sdimnub_addr_t 81311128SdimNativeThreadListDarwin::GetDispatchQueueT (nub_thread_t tid) 82311128Sdim{ 83311128Sdim MachThreadSP thread_sp (GetThreadByID (tid)); 84311128Sdim if (thread_sp) 85311128Sdim return thread_sp->GetDispatchQueueT(); 86311128Sdim return INVALID_NUB_ADDRESS; 87311128Sdim} 88311128Sdim 89311128Sdimnub_addr_t 90311128SdimNativeThreadListDarwin::GetTSDAddressForThread (nub_thread_t tid, uint64_t plo_pthread_tsd_base_address_offset, uint64_t plo_pthread_tsd_base_offset, uint64_t plo_pthread_tsd_entry_size) 91311128Sdim{ 92311128Sdim MachThreadSP thread_sp (GetThreadByID (tid)); 93311128Sdim if (thread_sp) 94311128Sdim return thread_sp->GetTSDAddressForThread(plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size); 95311128Sdim return INVALID_NUB_ADDRESS; 96311128Sdim} 97311128Sdim#endif 98311128Sdim 99311128Sdim// TODO implement these 100311128Sdim#if 0 101311128Sdimnub_thread_t 102311128SdimNativeThreadListDarwin::SetCurrentThread(nub_thread_t tid) 103311128Sdim{ 104311128Sdim MachThreadSP thread_sp (GetThreadByID (tid)); 105311128Sdim if (thread_sp) 106311128Sdim { 107311128Sdim m_current_thread = thread_sp; 108311128Sdim return tid; 109311128Sdim } 110311128Sdim return INVALID_NUB_THREAD; 111311128Sdim} 112311128Sdim 113311128Sdim 114311128Sdimbool 115311128SdimNativeThreadListDarwin::GetThreadStoppedReason(nub_thread_t tid, struct DNBThreadStopInfo *stop_info) const 116311128Sdim{ 117311128Sdim MachThreadSP thread_sp (GetThreadByID (tid)); 118311128Sdim if (thread_sp) 119311128Sdim return thread_sp->GetStopException().GetStopInfo(stop_info); 120311128Sdim return false; 121311128Sdim} 122311128Sdim 123311128Sdimbool 124311128SdimNativeThreadListDarwin::GetIdentifierInfo (nub_thread_t tid, thread_identifier_info_data_t *ident_info) 125311128Sdim{ 126311128Sdim thread_t mach_port_number = GetMachPortNumberByThreadID (tid); 127311128Sdim 128311128Sdim mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; 129311128Sdim return ::thread_info (mach_port_number, THREAD_IDENTIFIER_INFO, (thread_info_t)ident_info, &count) == KERN_SUCCESS; 130311128Sdim} 131311128Sdim 132311128Sdimvoid 133311128SdimNativeThreadListDarwin::DumpThreadStoppedReason (nub_thread_t tid) const 134311128Sdim{ 135311128Sdim MachThreadSP thread_sp (GetThreadByID (tid)); 136311128Sdim if (thread_sp) 137311128Sdim thread_sp->GetStopException().DumpStopReason(); 138311128Sdim} 139311128Sdim 140311128Sdimconst char * 141311128SdimNativeThreadListDarwin::GetThreadInfo (nub_thread_t tid) const 142311128Sdim{ 143311128Sdim MachThreadSP thread_sp (GetThreadByID (tid)); 144311128Sdim if (thread_sp) 145311128Sdim return thread_sp->GetBasicInfoAsString(); 146311128Sdim return NULL; 147311128Sdim} 148311128Sdim 149311128Sdim#endif 150311128Sdim 151311128SdimNativeThreadDarwinSP 152311128SdimNativeThreadListDarwin::GetThreadByID(lldb::tid_t tid) const { 153311128Sdim std::lock_guard<std::recursive_mutex> locker(m_threads_mutex); 154311128Sdim for (auto thread_sp : m_threads) { 155311128Sdim if (thread_sp && (thread_sp->GetID() == tid)) 156311128Sdim return thread_sp; 157311128Sdim } 158311128Sdim return NativeThreadDarwinSP(); 159311128Sdim} 160311128Sdim 161311128SdimNativeThreadDarwinSP NativeThreadListDarwin::GetThreadByMachPortNumber( 162311128Sdim ::thread_t mach_port_number) const { 163311128Sdim std::lock_guard<std::recursive_mutex> locker(m_threads_mutex); 164311128Sdim for (auto thread_sp : m_threads) { 165311128Sdim if (thread_sp && (thread_sp->GetMachPortNumber() == mach_port_number)) 166311128Sdim return thread_sp; 167311128Sdim } 168311128Sdim return NativeThreadDarwinSP(); 169311128Sdim} 170311128Sdim 171311128Sdimlldb::tid_t NativeThreadListDarwin::GetThreadIDByMachPortNumber( 172311128Sdim ::thread_t mach_port_number) const { 173311128Sdim std::lock_guard<std::recursive_mutex> locker(m_threads_mutex); 174311128Sdim for (auto thread_sp : m_threads) { 175311128Sdim if (thread_sp && (thread_sp->GetMachPortNumber() == mach_port_number)) 176311128Sdim return thread_sp->GetID(); 177311128Sdim } 178311128Sdim return LLDB_INVALID_THREAD_ID; 179311128Sdim} 180311128Sdim 181311128Sdim// TODO implement 182311128Sdim#if 0 183311128Sdimthread_t 184311128SdimNativeThreadListDarwin::GetMachPortNumberByThreadID (nub_thread_t globally_unique_id) const 185311128Sdim{ 186311128Sdim PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); 187311128Sdim MachThreadSP thread_sp; 188311128Sdim const size_t num_threads = m_threads.size(); 189311128Sdim for (size_t idx = 0; idx < num_threads; ++idx) 190311128Sdim { 191311128Sdim if (m_threads[idx]->ThreadID() == globally_unique_id) 192311128Sdim { 193311128Sdim return m_threads[idx]->MachPortNumber(); 194311128Sdim } 195311128Sdim } 196311128Sdim return 0; 197311128Sdim} 198311128Sdim 199311128Sdimbool 200311128SdimNativeThreadListDarwin::GetRegisterValue (nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *reg_value ) const 201311128Sdim{ 202311128Sdim MachThreadSP thread_sp (GetThreadByID (tid)); 203311128Sdim if (thread_sp) 204311128Sdim return thread_sp->GetRegisterValue(set, reg, reg_value); 205311128Sdim 206311128Sdim return false; 207311128Sdim} 208311128Sdim 209311128Sdimbool 210311128SdimNativeThreadListDarwin::SetRegisterValue (nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *reg_value ) const 211311128Sdim{ 212311128Sdim MachThreadSP thread_sp (GetThreadByID (tid)); 213311128Sdim if (thread_sp) 214311128Sdim return thread_sp->SetRegisterValue(set, reg, reg_value); 215311128Sdim 216311128Sdim return false; 217311128Sdim} 218311128Sdim 219311128Sdimnub_size_t 220311128SdimNativeThreadListDarwin::GetRegisterContext (nub_thread_t tid, void *buf, size_t buf_len) 221311128Sdim{ 222311128Sdim MachThreadSP thread_sp (GetThreadByID (tid)); 223311128Sdim if (thread_sp) 224311128Sdim return thread_sp->GetRegisterContext (buf, buf_len); 225311128Sdim return 0; 226311128Sdim} 227311128Sdim 228311128Sdimnub_size_t 229311128SdimNativeThreadListDarwin::SetRegisterContext (nub_thread_t tid, const void *buf, size_t buf_len) 230311128Sdim{ 231311128Sdim MachThreadSP thread_sp (GetThreadByID (tid)); 232311128Sdim if (thread_sp) 233311128Sdim return thread_sp->SetRegisterContext (buf, buf_len); 234311128Sdim return 0; 235311128Sdim} 236311128Sdim 237311128Sdimuint32_t 238311128SdimNativeThreadListDarwin::SaveRegisterState (nub_thread_t tid) 239311128Sdim{ 240311128Sdim MachThreadSP thread_sp (GetThreadByID (tid)); 241311128Sdim if (thread_sp) 242311128Sdim return thread_sp->SaveRegisterState (); 243311128Sdim return 0; 244311128Sdim} 245311128Sdim 246311128Sdimbool 247311128SdimNativeThreadListDarwin::RestoreRegisterState (nub_thread_t tid, uint32_t save_id) 248311128Sdim{ 249311128Sdim MachThreadSP thread_sp (GetThreadByID (tid)); 250311128Sdim if (thread_sp) 251311128Sdim return thread_sp->RestoreRegisterState (save_id); 252311128Sdim return 0; 253311128Sdim} 254311128Sdim#endif 255311128Sdim 256311128Sdimsize_t NativeThreadListDarwin::GetNumberOfThreads() const { 257311128Sdim std::lock_guard<std::recursive_mutex> locker(m_threads_mutex); 258311128Sdim return static_cast<size_t>(m_threads.size()); 259311128Sdim} 260311128Sdim 261311128Sdim// TODO implement 262311128Sdim#if 0 263311128Sdimnub_thread_t 264311128SdimNativeThreadListDarwin::ThreadIDAtIndex (nub_size_t idx) const 265311128Sdim{ 266311128Sdim PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); 267311128Sdim if (idx < m_threads.size()) 268311128Sdim return m_threads[idx]->ThreadID(); 269311128Sdim return INVALID_NUB_THREAD; 270311128Sdim} 271311128Sdim 272311128Sdimnub_thread_t 273311128SdimNativeThreadListDarwin::CurrentThreadID ( ) 274311128Sdim{ 275311128Sdim MachThreadSP thread_sp; 276311128Sdim CurrentThread(thread_sp); 277311128Sdim if (thread_sp.get()) 278311128Sdim return thread_sp->ThreadID(); 279311128Sdim return INVALID_NUB_THREAD; 280311128Sdim} 281311128Sdim 282311128Sdim#endif 283311128Sdim 284311128Sdimbool NativeThreadListDarwin::NotifyException(MachException::Data &exc) { 285311128Sdim auto thread_sp = GetThreadByMachPortNumber(exc.thread_port); 286311128Sdim if (thread_sp) { 287311128Sdim thread_sp->NotifyException(exc); 288311128Sdim return true; 289311128Sdim } 290311128Sdim return false; 291311128Sdim} 292311128Sdim 293311128Sdimvoid NativeThreadListDarwin::Clear() { 294311128Sdim std::lock_guard<std::recursive_mutex> locker(m_threads_mutex); 295311128Sdim m_threads.clear(); 296311128Sdim} 297311128Sdim 298311128Sdimuint32_t NativeThreadListDarwin::UpdateThreadList(NativeProcessDarwin &process, 299311128Sdim bool update, 300311128Sdim collection *new_threads) { 301311128Sdim Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 302311128Sdim 303311128Sdim std::lock_guard<std::recursive_mutex> locker(m_threads_mutex); 304360784Sdim LLDB_LOGF(log, 305360784Sdim "NativeThreadListDarwin::%s() (pid = %" PRIu64 ", update = " 306360784Sdim "%u) process stop count = %u", 307360784Sdim __FUNCTION__, process.GetID(), update, process.GetStopID()); 308311128Sdim 309311128Sdim if (process.GetStopID() == 0) { 310341825Sdim // On our first stop, we'll record details like 32/64 bitness and select 311341825Sdim // the proper architecture implementation. 312311128Sdim // 313311128Sdim int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)process.GetID()}; 314311128Sdim 315311128Sdim struct kinfo_proc processInfo; 316311128Sdim size_t bufsize = sizeof(processInfo); 317311128Sdim if ((sysctl(mib, (unsigned)(sizeof(mib) / sizeof(int)), &processInfo, 318311128Sdim &bufsize, NULL, 0) == 0) && 319311128Sdim (bufsize > 0)) { 320311128Sdim if (processInfo.kp_proc.p_flag & P_LP64) 321311128Sdim m_is_64_bit = true; 322311128Sdim } 323311128Sdim 324311128Sdim// TODO implement architecture selection and abstraction. 325311128Sdim#if 0 326311128Sdim#if defined(__i386__) || defined(__x86_64__) 327311128Sdim if (m_is_64_bit) 328311128Sdim DNBArchProtocol::SetArchitecture(CPU_TYPE_X86_64); 329311128Sdim else 330311128Sdim DNBArchProtocol::SetArchitecture(CPU_TYPE_I386); 331311128Sdim#elif defined(__arm__) || defined(__arm64__) || defined(__aarch64__) 332311128Sdim if (m_is_64_bit) 333311128Sdim DNBArchProtocol::SetArchitecture(CPU_TYPE_ARM64); 334311128Sdim else 335311128Sdim DNBArchProtocol::SetArchitecture(CPU_TYPE_ARM); 336311128Sdim#endif 337311128Sdim#endif 338311128Sdim } 339311128Sdim 340311128Sdim if (m_threads.empty() || update) { 341311128Sdim thread_array_t thread_list = nullptr; 342311128Sdim mach_msg_type_number_t thread_list_count = 0; 343311128Sdim task_t task = process.GetTask(); 344311128Sdim 345321369Sdim Status error; 346311128Sdim auto mach_err = ::task_threads(task, &thread_list, &thread_list_count); 347311128Sdim error.SetError(mach_err, eErrorTypeMachKernel); 348311128Sdim if (error.Fail()) { 349360784Sdim LLDB_LOGF(log, 350360784Sdim "::task_threads(task = 0x%4.4x, thread_list => %p, " 351360784Sdim "thread_list_count => %u) failed: %u (%s)", 352360784Sdim task, thread_list, thread_list_count, error.GetError(), 353360784Sdim error.AsCString()); 354311128Sdim return 0; 355311128Sdim } 356311128Sdim 357311128Sdim if (thread_list_count > 0) { 358311128Sdim collection currThreads; 359311128Sdim size_t idx; 360341825Sdim // Iterator through the current thread list and see which threads we 361341825Sdim // already have in our list (keep them), which ones we don't (add them), 362341825Sdim // and which ones are not around anymore (remove them). 363311128Sdim for (idx = 0; idx < thread_list_count; ++idx) { 364311128Sdim // Get the Mach thread port. 365311128Sdim const ::thread_t mach_port_num = thread_list[idx]; 366311128Sdim 367311128Sdim // Get the unique thread id for the mach port number. 368311128Sdim uint64_t unique_thread_id = 369311128Sdim NativeThreadDarwin::GetGloballyUniqueThreadIDForMachPortID( 370311128Sdim mach_port_num); 371311128Sdim 372311128Sdim // Retrieve the thread if it exists. 373311128Sdim auto thread_sp = GetThreadByID(unique_thread_id); 374311128Sdim if (thread_sp) { 375341825Sdim // We are already tracking it. Keep the existing native thread 376341825Sdim // instance. 377311128Sdim currThreads.push_back(thread_sp); 378311128Sdim } else { 379341825Sdim // We don't have a native thread instance for this thread. Create it 380341825Sdim // now. 381311128Sdim thread_sp.reset(new NativeThreadDarwin( 382311128Sdim &process, m_is_64_bit, unique_thread_id, mach_port_num)); 383311128Sdim 384341825Sdim // Add the new thread regardless of its is user ready state. Make 385341825Sdim // sure the thread is ready to be displayed and shown to users before 386341825Sdim // we add this thread to our list... 387311128Sdim if (thread_sp->IsUserReady()) { 388311128Sdim if (new_threads) 389311128Sdim new_threads->push_back(thread_sp); 390311128Sdim 391311128Sdim currThreads.push_back(thread_sp); 392311128Sdim } 393311128Sdim } 394311128Sdim } 395311128Sdim 396311128Sdim m_threads.swap(currThreads); 397311128Sdim m_current_thread.reset(); 398311128Sdim 399311128Sdim // Free the vm memory given to us by ::task_threads() 400311128Sdim vm_size_t thread_list_size = 401311128Sdim (vm_size_t)(thread_list_count * sizeof(::thread_t)); 402311128Sdim ::vm_deallocate(::mach_task_self(), (vm_address_t)thread_list, 403311128Sdim thread_list_size); 404311128Sdim } 405311128Sdim } 406311128Sdim return static_cast<uint32_t>(m_threads.size()); 407311128Sdim} 408311128Sdim 409311128Sdim// TODO implement 410311128Sdim#if 0 411311128Sdim 412311128Sdimvoid 413311128SdimNativeThreadListDarwin::CurrentThread (MachThreadSP& thread_sp) 414311128Sdim{ 415311128Sdim // locker will keep a mutex locked until it goes out of scope 416311128Sdim PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); 417311128Sdim if (m_current_thread.get() == NULL) 418311128Sdim { 419341825Sdim // Figure out which thread is going to be our current thread. This is 420341825Sdim // currently done by finding the first thread in the list that has a 421341825Sdim // valid exception. 422311128Sdim const size_t num_threads = m_threads.size(); 423311128Sdim for (uint32_t idx = 0; idx < num_threads; ++idx) 424311128Sdim { 425311128Sdim if (m_threads[idx]->GetStopException().IsValid()) 426311128Sdim { 427311128Sdim m_current_thread = m_threads[idx]; 428311128Sdim break; 429311128Sdim } 430311128Sdim } 431311128Sdim } 432311128Sdim thread_sp = m_current_thread; 433311128Sdim} 434311128Sdim 435311128Sdim#endif 436311128Sdim 437311128Sdimvoid NativeThreadListDarwin::Dump(Stream &stream) const { 438311128Sdim bool first = true; 439311128Sdim 440311128Sdim std::lock_guard<std::recursive_mutex> locker(m_threads_mutex); 441311128Sdim for (auto thread_sp : m_threads) { 442311128Sdim if (thread_sp) { 443311128Sdim // Handle newlines between thread entries. 444311128Sdim if (first) 445311128Sdim first = false; 446311128Sdim else 447311128Sdim stream.PutChar('\n'); 448311128Sdim thread_sp->Dump(stream); 449311128Sdim } 450311128Sdim } 451311128Sdim} 452311128Sdim 453311128Sdimvoid NativeThreadListDarwin::ProcessWillResume( 454311128Sdim NativeProcessDarwin &process, const ResumeActionList &thread_actions) { 455311128Sdim std::lock_guard<std::recursive_mutex> locker(m_threads_mutex); 456311128Sdim 457341825Sdim // Update our thread list, because sometimes libdispatch or the kernel will 458341825Sdim // spawn threads while a task is suspended. 459311128Sdim NativeThreadListDarwin::collection new_threads; 460311128Sdim 461311128Sdim// TODO implement this. 462311128Sdim#if 0 463311128Sdim // First figure out if we were planning on running only one thread, and if 464311128Sdim // so, force that thread to resume. 465311128Sdim bool run_one_thread; 466311128Sdim thread_t solo_thread = THREAD_NULL; 467311128Sdim if ((thread_actions.GetSize() > 0) && 468311128Sdim (thread_actions.NumActionsWithState(eStateStepping) + 469311128Sdim thread_actions.NumActionsWithState (eStateRunning) == 1)) 470311128Sdim { 471311128Sdim run_one_thread = true; 472311128Sdim const DNBThreadResumeAction *action_ptr = thread_actions.GetFirst(); 473311128Sdim size_t num_actions = thread_actions.GetSize(); 474311128Sdim for (size_t i = 0; i < num_actions; i++, action_ptr++) 475311128Sdim { 476311128Sdim if (action_ptr->state == eStateStepping || action_ptr->state == eStateRunning) 477311128Sdim { 478311128Sdim solo_thread = action_ptr->tid; 479311128Sdim break; 480311128Sdim } 481311128Sdim } 482311128Sdim } 483311128Sdim else 484311128Sdim run_one_thread = false; 485311128Sdim#endif 486311128Sdim 487311128Sdim UpdateThreadList(process, true, &new_threads); 488311128Sdim 489311128Sdim#if 0 490311128Sdim DNBThreadResumeAction resume_new_threads = { -1U, eStateRunning, 0, INVALID_NUB_ADDRESS }; 491341825Sdim // If we are planning to run only one thread, any new threads should be 492341825Sdim // suspended. 493311128Sdim if (run_one_thread) 494311128Sdim resume_new_threads.state = eStateSuspended; 495311128Sdim 496311128Sdim const size_t num_new_threads = new_threads.size(); 497311128Sdim const size_t num_threads = m_threads.size(); 498311128Sdim for (uint32_t idx = 0; idx < num_threads; ++idx) 499311128Sdim { 500311128Sdim MachThread *thread = m_threads[idx].get(); 501311128Sdim bool handled = false; 502311128Sdim for (uint32_t new_idx = 0; new_idx < num_new_threads; ++new_idx) 503311128Sdim { 504311128Sdim if (thread == new_threads[new_idx].get()) 505311128Sdim { 506311128Sdim thread->ThreadWillResume(&resume_new_threads); 507311128Sdim handled = true; 508311128Sdim break; 509311128Sdim } 510311128Sdim } 511311128Sdim 512311128Sdim if (!handled) 513311128Sdim { 514311128Sdim const DNBThreadResumeAction *thread_action = thread_actions.GetActionForThread (thread->ThreadID(), true); 515311128Sdim // There must always be a thread action for every thread. 516311128Sdim assert (thread_action); 517311128Sdim bool others_stopped = false; 518311128Sdim if (solo_thread == thread->ThreadID()) 519311128Sdim others_stopped = true; 520311128Sdim thread->ThreadWillResume (thread_action, others_stopped); 521311128Sdim } 522311128Sdim } 523311128Sdim 524311128Sdim if (new_threads.size()) 525311128Sdim { 526311128Sdim for (uint32_t idx = 0; idx < num_new_threads; ++idx) 527311128Sdim { 528311128Sdim DNBLogThreadedIf (LOG_THREAD, "NativeThreadListDarwin::ProcessWillResume (pid = %4.4x) stop-id=%u, resuming newly discovered thread: 0x%8.8" PRIx64 ", thread-is-user-ready=%i)", 529311128Sdim process->ProcessID(), 530311128Sdim process->StopCount(), 531311128Sdim new_threads[idx]->ThreadID(), 532311128Sdim new_threads[idx]->IsUserReady()); 533311128Sdim } 534311128Sdim } 535311128Sdim#endif 536311128Sdim} 537311128Sdim 538311128Sdimuint32_t NativeThreadListDarwin::ProcessDidStop(NativeProcessDarwin &process) { 539311128Sdim std::lock_guard<std::recursive_mutex> locker(m_threads_mutex); 540311128Sdim 541311128Sdim // Update our thread list. 542311128Sdim UpdateThreadList(process, true); 543311128Sdim 544311128Sdim for (auto thread_sp : m_threads) { 545311128Sdim if (thread_sp) 546311128Sdim thread_sp->ThreadDidStop(); 547311128Sdim } 548311128Sdim return (uint32_t)m_threads.size(); 549311128Sdim} 550311128Sdim 551341825Sdim// Check each thread in our thread list to see if we should notify our client 552341825Sdim// of the current halt in execution. 553311128Sdim// 554341825Sdim// Breakpoints can have callback functions associated with them than can return 555341825Sdim// true to stop, or false to continue executing the inferior. 556311128Sdim// 557311128Sdim// RETURNS 558311128Sdim// true if we should stop and notify our clients 559311128Sdim// false if we should resume our child process and skip notification 560311128Sdimbool NativeThreadListDarwin::ShouldStop(bool &step_more) { 561311128Sdim std::lock_guard<std::recursive_mutex> locker(m_threads_mutex); 562311128Sdim for (auto thread_sp : m_threads) { 563311128Sdim if (thread_sp && thread_sp->ShouldStop(step_more)) 564311128Sdim return true; 565311128Sdim } 566311128Sdim return false; 567311128Sdim} 568311128Sdim 569311128Sdim// Implement. 570311128Sdim#if 0 571311128Sdim 572311128Sdimvoid 573311128SdimNativeThreadListDarwin::NotifyBreakpointChanged (const DNBBreakpoint *bp) 574311128Sdim{ 575311128Sdim PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); 576311128Sdim const size_t num_threads = m_threads.size(); 577311128Sdim for (uint32_t idx = 0; idx < num_threads; ++idx) 578311128Sdim { 579311128Sdim m_threads[idx]->NotifyBreakpointChanged(bp); 580311128Sdim } 581311128Sdim} 582311128Sdim 583311128Sdim 584311128Sdimuint32_t 585311128SdimNativeThreadListDarwin::EnableHardwareBreakpoint (const DNBBreakpoint* bp) const 586311128Sdim{ 587311128Sdim if (bp != NULL) 588311128Sdim { 589311128Sdim const size_t num_threads = m_threads.size(); 590311128Sdim for (uint32_t idx = 0; idx < num_threads; ++idx) 591311128Sdim m_threads[idx]->EnableHardwareBreakpoint(bp); 592311128Sdim } 593311128Sdim return INVALID_NUB_HW_INDEX; 594311128Sdim} 595311128Sdim 596311128Sdimbool 597311128SdimNativeThreadListDarwin::DisableHardwareBreakpoint (const DNBBreakpoint* bp) const 598311128Sdim{ 599311128Sdim if (bp != NULL) 600311128Sdim { 601311128Sdim const size_t num_threads = m_threads.size(); 602311128Sdim for (uint32_t idx = 0; idx < num_threads; ++idx) 603311128Sdim m_threads[idx]->DisableHardwareBreakpoint(bp); 604311128Sdim } 605311128Sdim return false; 606311128Sdim} 607311128Sdim 608341825Sdim// DNBWatchpointSet() -> MachProcess::CreateWatchpoint() -> 609341825Sdim// MachProcess::EnableWatchpoint() -> 610341825Sdim// NativeThreadListDarwin::EnableHardwareWatchpoint(). 611311128Sdimuint32_t 612311128SdimNativeThreadListDarwin::EnableHardwareWatchpoint (const DNBBreakpoint* wp) const 613311128Sdim{ 614311128Sdim uint32_t hw_index = INVALID_NUB_HW_INDEX; 615311128Sdim if (wp != NULL) 616311128Sdim { 617311128Sdim PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); 618311128Sdim const size_t num_threads = m_threads.size(); 619341825Sdim // On Mac OS X we have to prime the control registers for new threads. 620341825Sdim // We do this using the control register data for the first thread, for 621341825Sdim // lack of a better way of choosing. 622311128Sdim bool also_set_on_task = true; 623311128Sdim for (uint32_t idx = 0; idx < num_threads; ++idx) 624311128Sdim { 625311128Sdim if ((hw_index = m_threads[idx]->EnableHardwareWatchpoint(wp, also_set_on_task)) == INVALID_NUB_HW_INDEX) 626311128Sdim { 627341825Sdim // We know that idx failed for some reason. Let's rollback the 628341825Sdim // transaction for [0, idx). 629311128Sdim for (uint32_t i = 0; i < idx; ++i) 630311128Sdim m_threads[i]->RollbackTransForHWP(); 631311128Sdim return INVALID_NUB_HW_INDEX; 632311128Sdim } 633311128Sdim also_set_on_task = false; 634311128Sdim } 635311128Sdim // Notify each thread to commit the pending transaction. 636311128Sdim for (uint32_t idx = 0; idx < num_threads; ++idx) 637311128Sdim m_threads[idx]->FinishTransForHWP(); 638311128Sdim 639311128Sdim } 640311128Sdim return hw_index; 641311128Sdim} 642311128Sdim 643311128Sdimbool 644311128SdimNativeThreadListDarwin::DisableHardwareWatchpoint (const DNBBreakpoint* wp) const 645311128Sdim{ 646311128Sdim if (wp != NULL) 647311128Sdim { 648311128Sdim PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); 649311128Sdim const size_t num_threads = m_threads.size(); 650311128Sdim 651341825Sdim // On Mac OS X we have to prime the control registers for new threads. 652341825Sdim // We do this using the control register data for the first thread, for 653341825Sdim // lack of a better way of choosing. 654311128Sdim bool also_set_on_task = true; 655311128Sdim for (uint32_t idx = 0; idx < num_threads; ++idx) 656311128Sdim { 657311128Sdim if (!m_threads[idx]->DisableHardwareWatchpoint(wp, also_set_on_task)) 658311128Sdim { 659341825Sdim // We know that idx failed for some reason. Let's rollback the 660341825Sdim // transaction for [0, idx). 661311128Sdim for (uint32_t i = 0; i < idx; ++i) 662311128Sdim m_threads[i]->RollbackTransForHWP(); 663311128Sdim return false; 664311128Sdim } 665311128Sdim also_set_on_task = false; 666311128Sdim } 667311128Sdim // Notify each thread to commit the pending transaction. 668311128Sdim for (uint32_t idx = 0; idx < num_threads; ++idx) 669311128Sdim m_threads[idx]->FinishTransForHWP(); 670311128Sdim 671311128Sdim return true; 672311128Sdim } 673311128Sdim return false; 674311128Sdim} 675311128Sdim 676311128Sdimuint32_t 677311128SdimNativeThreadListDarwin::NumSupportedHardwareWatchpoints () const 678311128Sdim{ 679311128Sdim PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); 680311128Sdim const size_t num_threads = m_threads.size(); 681341825Sdim // Use an arbitrary thread to retrieve the number of supported hardware 682341825Sdim // watchpoints. 683311128Sdim if (num_threads) 684311128Sdim return m_threads[0]->NumSupportedHardwareWatchpoints(); 685311128Sdim return 0; 686311128Sdim} 687311128Sdim 688311128Sdimuint32_t 689311128SdimNativeThreadListDarwin::GetThreadIndexForThreadStoppedWithSignal (const int signo) const 690311128Sdim{ 691311128Sdim PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); 692311128Sdim uint32_t should_stop = false; 693311128Sdim const size_t num_threads = m_threads.size(); 694311128Sdim for (uint32_t idx = 0; !should_stop && idx < num_threads; ++idx) 695311128Sdim { 696311128Sdim if (m_threads[idx]->GetStopException().SoftSignal () == signo) 697311128Sdim return idx; 698311128Sdim } 699311128Sdim return UINT32_MAX; 700311128Sdim} 701311128Sdim 702311128Sdim#endif 703