1 //===-- TargetList.cpp ------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // C Includes 11 // C++ Includes 12 // Other libraries and framework includes 13 // Project includes 14 #include "lldb/Core/Broadcaster.h" 15 #include "lldb/Core/Event.h" 16 #include "lldb/Core/State.h" 17 #include "lldb/Core/Timer.h" 18 #include "lldb/Host/Host.h" 19 #include "lldb/Target/Process.h" 20 #include "lldb/Target/TargetList.h" 21 22 using namespace lldb; 23 using namespace lldb_private; 24 25 26 //---------------------------------------------------------------------- 27 // TargetList constructor 28 //---------------------------------------------------------------------- 29 TargetList::TargetList() : 30 Broadcaster("TargetList"), 31 m_target_list(), 32 m_target_list_mutex (Mutex::eMutexTypeRecursive), 33 m_current_target_idx (0) 34 { 35 } 36 37 //---------------------------------------------------------------------- 38 // Destructor 39 //---------------------------------------------------------------------- 40 TargetList::~TargetList() 41 { 42 Mutex::Locker locker(m_target_list_mutex); 43 m_target_list.clear(); 44 } 45 46 Error 47 TargetList::CreateTarget 48 ( 49 const FileSpec& file, 50 const ArchSpec& arch, 51 const UUID *uuid_ptr, 52 bool get_dependent_files, 53 TargetSP &target_sp 54 ) 55 { 56 Timer scoped_timer (__PRETTY_FUNCTION__, 57 "TargetList::CreateTarget (file = '%s/%s', arch = '%s', uuid = %p)", 58 file.GetDirectory().AsCString(), 59 file.GetFilename().AsCString(), 60 arch.AsCString(), 61 uuid_ptr); 62 ModuleSP exe_module_sp; 63 FileSpec resolved_file(file); 64 if (!Host::ResolveExecutableInBundle (&resolved_file)) 65 resolved_file = file; 66 67 Error error = ModuleList::GetSharedModule(resolved_file, 68 arch, 69 uuid_ptr, 70 NULL, 71 0, 72 exe_module_sp, 73 NULL, 74 NULL); 75 if (exe_module_sp) 76 { 77 target_sp.reset(new Target); 78 target_sp->SetExecutableModule (exe_module_sp, get_dependent_files); 79 80 if (target_sp.get()) 81 { 82 Mutex::Locker locker(m_target_list_mutex); 83 m_current_target_idx = m_target_list.size(); 84 m_target_list.push_back(target_sp); 85 } 86 87 // target_sp.reset(new Target); 88 // // Let the target resolve any funky bundle paths before we try and get 89 // // the object file... 90 // target_sp->SetExecutableModule (exe_module_sp, get_dependent_files); 91 // if (exe_module_sp->GetObjectFile() == NULL) 92 // { 93 // error.SetErrorStringWithFormat("%s%s%s: doesn't contain architecture %s", 94 // file.GetDirectory().AsCString(), 95 // file.GetDirectory() ? "/" : "", 96 // file.GetFilename().AsCString(), 97 // arch.AsCString()); 98 // } 99 // else 100 // { 101 // if (target_sp.get()) 102 // { 103 // error.Clear(); 104 // Mutex::Locker locker(m_target_list_mutex); 105 // m_current_target_idx = m_target_list.size(); 106 // m_target_list.push_back(target_sp); 107 // } 108 // } 109 } 110 else 111 { 112 target_sp.reset(); 113 } 114 115 return error; 116 } 117 118 bool 119 TargetList::DeleteTarget (TargetSP &target_sp) 120 { 121 Mutex::Locker locker(m_target_list_mutex); 122 collection::iterator pos, end = m_target_list.end(); 123 124 for (pos = m_target_list.begin(); pos != end; ++pos) 125 { 126 if (pos->get() == target_sp.get()) 127 { 128 m_target_list.erase(pos); 129 return true; 130 } 131 } 132 return false; 133 } 134 135 136 TargetSP 137 TargetList::FindTargetWithExecutableAndArchitecture 138 ( 139 const FileSpec &exe_file_spec, 140 const ArchSpec *exe_arch_ptr 141 ) const 142 { 143 Mutex::Locker locker (m_target_list_mutex); 144 TargetSP target_sp; 145 bool full_match = exe_file_spec.GetDirectory(); 146 147 collection::const_iterator pos, end = m_target_list.end(); 148 for (pos = m_target_list.begin(); pos != end; ++pos) 149 { 150 ModuleSP module_sp ((*pos)->GetExecutableModule()); 151 152 if (module_sp) 153 { 154 if (FileSpec::Equal (exe_file_spec, module_sp->GetFileSpec(), full_match)) 155 { 156 if (exe_arch_ptr) 157 { 158 if (*exe_arch_ptr != module_sp->GetArchitecture()) 159 continue; 160 } 161 target_sp = *pos; 162 break; 163 } 164 } 165 } 166 return target_sp; 167 } 168 169 TargetSP 170 TargetList::FindTargetWithProcessID (lldb::pid_t pid) const 171 { 172 Mutex::Locker locker(m_target_list_mutex); 173 TargetSP target_sp; 174 collection::const_iterator pos, end = m_target_list.end(); 175 for (pos = m_target_list.begin(); pos != end; ++pos) 176 { 177 Process* process = (*pos)->GetProcessSP().get(); 178 if (process && process->GetID() == pid) 179 { 180 target_sp = *pos; 181 break; 182 } 183 } 184 return target_sp; 185 } 186 187 188 TargetSP 189 TargetList::FindTargetWithProcess (Process *process) const 190 { 191 TargetSP target_sp; 192 if (process) 193 { 194 Mutex::Locker locker(m_target_list_mutex); 195 collection::const_iterator pos, end = m_target_list.end(); 196 for (pos = m_target_list.begin(); pos != end; ++pos) 197 { 198 if (process == (*pos)->GetProcessSP().get()) 199 { 200 target_sp = *pos; 201 break; 202 } 203 } 204 } 205 return target_sp; 206 } 207 208 TargetSP 209 TargetList::GetTargetSP (Target *target) const 210 { 211 TargetSP target_sp; 212 if (target) 213 { 214 Mutex::Locker locker(m_target_list_mutex); 215 collection::const_iterator pos, end = m_target_list.end(); 216 for (pos = m_target_list.begin(); pos != end; ++pos) 217 { 218 if (target == (*pos).get()) 219 { 220 target_sp = *pos; 221 break; 222 } 223 } 224 } 225 return target_sp; 226 } 227 228 uint32_t 229 TargetList::SendAsyncInterrupt (lldb::pid_t pid) 230 { 231 uint32_t num_async_interrupts_sent = 0; 232 233 if (pid != LLDB_INVALID_PROCESS_ID) 234 { 235 TargetSP target_sp(FindTargetWithProcessID (pid)); 236 if (target_sp.get()) 237 { 238 Process* process = target_sp->GetProcessSP().get(); 239 if (process) 240 { 241 process->BroadcastEvent (Process::eBroadcastBitInterrupt, NULL); 242 ++num_async_interrupts_sent; 243 } 244 } 245 } 246 else 247 { 248 // We don't have a valid pid to broadcast to, so broadcast to the target 249 // list's async broadcaster... 250 BroadcastEvent (Process::eBroadcastBitInterrupt, NULL); 251 } 252 253 return num_async_interrupts_sent; 254 } 255 256 uint32_t 257 TargetList::SignalIfRunning (lldb::pid_t pid, int signo) 258 { 259 uint32_t num_signals_sent = 0; 260 Process *process = NULL; 261 if (pid == LLDB_INVALID_PROCESS_ID) 262 { 263 // Signal all processes with signal 264 Mutex::Locker locker(m_target_list_mutex); 265 collection::iterator pos, end = m_target_list.end(); 266 for (pos = m_target_list.begin(); pos != end; ++pos) 267 { 268 process = (*pos)->GetProcessSP().get(); 269 if (process) 270 { 271 if (process->IsAlive()) 272 { 273 ++num_signals_sent; 274 process->Signal (signo); 275 } 276 } 277 } 278 } 279 else 280 { 281 // Signal a specific process with signal 282 TargetSP target_sp(FindTargetWithProcessID (pid)); 283 if (target_sp.get()) 284 { 285 process = target_sp->GetProcessSP().get(); 286 if (process) 287 { 288 if (process->IsAlive()) 289 { 290 ++num_signals_sent; 291 process->Signal (signo); 292 } 293 } 294 } 295 } 296 return num_signals_sent; 297 } 298 299 int 300 TargetList::GetNumTargets () const 301 { 302 Mutex::Locker locker (m_target_list_mutex); 303 return m_target_list.size(); 304 } 305 306 lldb::TargetSP 307 TargetList::GetTargetAtIndex (uint32_t idx) const 308 { 309 TargetSP target_sp; 310 Mutex::Locker locker (m_target_list_mutex); 311 if (idx < m_target_list.size()) 312 target_sp = m_target_list[idx]; 313 return target_sp; 314 } 315 316 uint32_t 317 TargetList::SetCurrentTarget (Target* target) 318 { 319 Mutex::Locker locker (m_target_list_mutex); 320 collection::const_iterator pos, 321 begin = m_target_list.begin(), 322 end = m_target_list.end(); 323 for (pos = begin; pos != end; ++pos) 324 { 325 if (pos->get() == target) 326 { 327 m_current_target_idx = std::distance (begin, pos); 328 return m_current_target_idx; 329 } 330 } 331 m_current_target_idx = 0; 332 return m_current_target_idx; 333 } 334 335 lldb::TargetSP 336 TargetList::GetCurrentTarget () 337 { 338 Mutex::Locker locker (m_target_list_mutex); 339 if (m_current_target_idx >= m_target_list.size()) 340 m_current_target_idx = 0; 341 return GetTargetAtIndex (m_current_target_idx); 342 } 343