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/Debugger.h" 16 #include "lldb/Core/Event.h" 17 #include "lldb/Core/State.h" 18 #include "lldb/Core/Timer.h" 19 #include "lldb/Host/Host.h" 20 #include "lldb/Interpreter/CommandInterpreter.h" 21 #include "lldb/Interpreter/OptionGroupPlatform.h" 22 #include "lldb/Target/Platform.h" 23 #include "lldb/Target/Process.h" 24 #include "lldb/Target/TargetList.h" 25 26 using namespace lldb; 27 using namespace lldb_private; 28 29 ConstString & 30 TargetList::GetStaticBroadcasterClass () 31 { 32 static ConstString class_name ("lldb.targetList"); 33 return class_name; 34 } 35 36 //---------------------------------------------------------------------- 37 // TargetList constructor 38 //---------------------------------------------------------------------- 39 TargetList::TargetList(Debugger &debugger) : 40 Broadcaster(&debugger, "TargetList"), 41 m_target_list(), 42 m_target_list_mutex (Mutex::eMutexTypeRecursive), 43 m_selected_target_idx (0) 44 { 45 CheckInWithManager(); 46 } 47 48 //---------------------------------------------------------------------- 49 // Destructor 50 //---------------------------------------------------------------------- 51 TargetList::~TargetList() 52 { 53 Mutex::Locker locker(m_target_list_mutex); 54 m_target_list.clear(); 55 } 56 57 Error 58 TargetList::CreateTarget (Debugger &debugger, 59 const FileSpec& file, 60 const char *triple_cstr, 61 bool get_dependent_files, 62 const OptionGroupPlatform *platform_options, 63 TargetSP &target_sp) 64 { 65 Error error; 66 PlatformSP platform_sp; 67 68 // This is purposely left empty unless it is specified by triple_cstr. 69 // If not initialized via triple_cstr, then the currently selected platform 70 // will set the architecture correctly. 71 const ArchSpec arch(triple_cstr); 72 if (triple_cstr && triple_cstr[0]) 73 { 74 if (!arch.IsValid()) 75 { 76 error.SetErrorStringWithFormat("invalid triple '%s'", triple_cstr); 77 return error; 78 } 79 } 80 81 ArchSpec platform_arch(arch); 82 CommandInterpreter &interpreter = debugger.GetCommandInterpreter(); 83 if (platform_options) 84 { 85 if (platform_options->PlatformWasSpecified ()) 86 { 87 const bool select_platform = true; 88 platform_sp = platform_options->CreatePlatformWithOptions (interpreter, 89 arch, 90 select_platform, 91 error, 92 platform_arch); 93 if (!platform_sp) 94 return error; 95 } 96 } 97 98 if (!platform_sp) 99 { 100 // Get the current platform and make sure it is compatible with the 101 // current architecture if we have a valid architecture. 102 platform_sp = debugger.GetPlatformList().GetSelectedPlatform (); 103 104 if (arch.IsValid() && !platform_sp->IsCompatibleArchitecture(arch, &platform_arch)) 105 { 106 platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch); 107 } 108 } 109 110 if (!platform_arch.IsValid()) 111 platform_arch = arch; 112 113 error = TargetList::CreateTarget (debugger, 114 file, 115 platform_arch, 116 get_dependent_files, 117 platform_sp, 118 target_sp); 119 120 if (target_sp) 121 { 122 if (file.GetDirectory()) 123 { 124 FileSpec file_dir; 125 file_dir.GetDirectory() = file.GetDirectory(); 126 target_sp->GetExecutableSearchPaths ().Append (file_dir); 127 } 128 } 129 return error; 130 } 131 132 Error 133 TargetList::CreateTarget 134 ( 135 Debugger &debugger, 136 const FileSpec& file, 137 const ArchSpec& specified_arch, 138 bool get_dependent_files, 139 PlatformSP &platform_sp, 140 TargetSP &target_sp 141 ) 142 { 143 Timer scoped_timer (__PRETTY_FUNCTION__, 144 "TargetList::CreateTarget (file = '%s/%s', arch = '%s')", 145 file.GetDirectory().AsCString(), 146 file.GetFilename().AsCString(), 147 specified_arch.GetArchitectureName()); 148 Error error; 149 150 ArchSpec arch(specified_arch); 151 152 if (platform_sp) 153 { 154 if (arch.IsValid()) 155 { 156 if (!platform_sp->IsCompatibleArchitecture(arch)) 157 platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch); 158 } 159 } 160 else if (arch.IsValid()) 161 { 162 platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch); 163 } 164 165 if (!platform_sp) 166 platform_sp = debugger.GetPlatformList().GetSelectedPlatform(); 167 168 if (file) 169 { 170 ModuleSP exe_module_sp; 171 FileSpec resolved_file(file); 172 if (platform_sp) 173 { 174 FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths()); 175 error = platform_sp->ResolveExecutable (file, 176 arch, 177 exe_module_sp, 178 executable_search_paths.GetSize() ? &executable_search_paths : NULL); 179 } 180 181 if (error.Success() && exe_module_sp) 182 { 183 if (exe_module_sp->GetObjectFile() == NULL) 184 { 185 if (arch.IsValid()) 186 { 187 error.SetErrorStringWithFormat("\"%s%s%s\" doesn't contain architecture %s", 188 file.GetDirectory().AsCString(), 189 file.GetDirectory() ? "/" : "", 190 file.GetFilename().AsCString(), 191 arch.GetArchitectureName()); 192 } 193 else 194 { 195 error.SetErrorStringWithFormat("unsupported file type \"%s%s%s\"", 196 file.GetDirectory().AsCString(), 197 file.GetDirectory() ? "/" : "", 198 file.GetFilename().AsCString()); 199 } 200 return error; 201 } 202 target_sp.reset(new Target(debugger, arch, platform_sp)); 203 target_sp->SetExecutableModule (exe_module_sp, get_dependent_files); 204 } 205 } 206 else 207 { 208 // No file was specified, just create an empty target with any arch 209 // if a valid arch was specified 210 target_sp.reset(new Target(debugger, arch, platform_sp)); 211 } 212 213 if (target_sp) 214 { 215 target_sp->UpdateInstanceName(); 216 217 Mutex::Locker locker(m_target_list_mutex); 218 m_selected_target_idx = m_target_list.size(); 219 m_target_list.push_back(target_sp); 220 } 221 222 return error; 223 } 224 225 bool 226 TargetList::DeleteTarget (TargetSP &target_sp) 227 { 228 Mutex::Locker locker(m_target_list_mutex); 229 collection::iterator pos, end = m_target_list.end(); 230 231 for (pos = m_target_list.begin(); pos != end; ++pos) 232 { 233 if (pos->get() == target_sp.get()) 234 { 235 m_target_list.erase(pos); 236 return true; 237 } 238 } 239 return false; 240 } 241 242 243 TargetSP 244 TargetList::FindTargetWithExecutableAndArchitecture 245 ( 246 const FileSpec &exe_file_spec, 247 const ArchSpec *exe_arch_ptr 248 ) const 249 { 250 Mutex::Locker locker (m_target_list_mutex); 251 TargetSP target_sp; 252 bool full_match = exe_file_spec.GetDirectory(); 253 254 collection::const_iterator pos, end = m_target_list.end(); 255 for (pos = m_target_list.begin(); pos != end; ++pos) 256 { 257 Module *exe_module = (*pos)->GetExecutableModulePointer(); 258 259 if (exe_module) 260 { 261 if (FileSpec::Equal (exe_file_spec, exe_module->GetFileSpec(), full_match)) 262 { 263 if (exe_arch_ptr) 264 { 265 if (*exe_arch_ptr != exe_module->GetArchitecture()) 266 continue; 267 } 268 target_sp = *pos; 269 break; 270 } 271 } 272 } 273 return target_sp; 274 } 275 276 TargetSP 277 TargetList::FindTargetWithProcessID (lldb::pid_t pid) const 278 { 279 Mutex::Locker locker(m_target_list_mutex); 280 TargetSP target_sp; 281 collection::const_iterator pos, end = m_target_list.end(); 282 for (pos = m_target_list.begin(); pos != end; ++pos) 283 { 284 Process* process = (*pos)->GetProcessSP().get(); 285 if (process && process->GetID() == pid) 286 { 287 target_sp = *pos; 288 break; 289 } 290 } 291 return target_sp; 292 } 293 294 295 TargetSP 296 TargetList::FindTargetWithProcess (Process *process) const 297 { 298 TargetSP target_sp; 299 if (process) 300 { 301 Mutex::Locker locker(m_target_list_mutex); 302 collection::const_iterator pos, end = m_target_list.end(); 303 for (pos = m_target_list.begin(); pos != end; ++pos) 304 { 305 if (process == (*pos)->GetProcessSP().get()) 306 { 307 target_sp = *pos; 308 break; 309 } 310 } 311 } 312 return target_sp; 313 } 314 315 TargetSP 316 TargetList::GetTargetSP (Target *target) const 317 { 318 TargetSP target_sp; 319 if (target) 320 { 321 Mutex::Locker locker(m_target_list_mutex); 322 collection::const_iterator pos, end = m_target_list.end(); 323 for (pos = m_target_list.begin(); pos != end; ++pos) 324 { 325 if (target == (*pos).get()) 326 { 327 target_sp = *pos; 328 break; 329 } 330 } 331 } 332 return target_sp; 333 } 334 335 uint32_t 336 TargetList::SendAsyncInterrupt (lldb::pid_t pid) 337 { 338 uint32_t num_async_interrupts_sent = 0; 339 340 if (pid != LLDB_INVALID_PROCESS_ID) 341 { 342 TargetSP target_sp(FindTargetWithProcessID (pid)); 343 if (target_sp.get()) 344 { 345 Process* process = target_sp->GetProcessSP().get(); 346 if (process) 347 { 348 process->BroadcastEvent (Process::eBroadcastBitInterrupt, NULL); 349 ++num_async_interrupts_sent; 350 } 351 } 352 } 353 else 354 { 355 // We don't have a valid pid to broadcast to, so broadcast to the target 356 // list's async broadcaster... 357 BroadcastEvent (Process::eBroadcastBitInterrupt, NULL); 358 } 359 360 return num_async_interrupts_sent; 361 } 362 363 uint32_t 364 TargetList::SignalIfRunning (lldb::pid_t pid, int signo) 365 { 366 uint32_t num_signals_sent = 0; 367 Process *process = NULL; 368 if (pid == LLDB_INVALID_PROCESS_ID) 369 { 370 // Signal all processes with signal 371 Mutex::Locker locker(m_target_list_mutex); 372 collection::iterator pos, end = m_target_list.end(); 373 for (pos = m_target_list.begin(); pos != end; ++pos) 374 { 375 process = (*pos)->GetProcessSP().get(); 376 if (process) 377 { 378 if (process->IsAlive()) 379 { 380 ++num_signals_sent; 381 process->Signal (signo); 382 } 383 } 384 } 385 } 386 else 387 { 388 // Signal a specific process with signal 389 TargetSP target_sp(FindTargetWithProcessID (pid)); 390 if (target_sp.get()) 391 { 392 process = target_sp->GetProcessSP().get(); 393 if (process) 394 { 395 if (process->IsAlive()) 396 { 397 ++num_signals_sent; 398 process->Signal (signo); 399 } 400 } 401 } 402 } 403 return num_signals_sent; 404 } 405 406 int 407 TargetList::GetNumTargets () const 408 { 409 Mutex::Locker locker (m_target_list_mutex); 410 return m_target_list.size(); 411 } 412 413 lldb::TargetSP 414 TargetList::GetTargetAtIndex (uint32_t idx) const 415 { 416 TargetSP target_sp; 417 Mutex::Locker locker (m_target_list_mutex); 418 if (idx < m_target_list.size()) 419 target_sp = m_target_list[idx]; 420 return target_sp; 421 } 422 423 uint32_t 424 TargetList::GetIndexOfTarget (lldb::TargetSP target_sp) const 425 { 426 Mutex::Locker locker (m_target_list_mutex); 427 size_t num_targets = m_target_list.size(); 428 for (size_t idx = 0; idx < num_targets; idx++) 429 { 430 if (target_sp == m_target_list[idx]) 431 return idx; 432 } 433 return UINT32_MAX; 434 } 435 436 uint32_t 437 TargetList::SetSelectedTarget (Target* target) 438 { 439 Mutex::Locker locker (m_target_list_mutex); 440 collection::const_iterator pos, 441 begin = m_target_list.begin(), 442 end = m_target_list.end(); 443 for (pos = begin; pos != end; ++pos) 444 { 445 if (pos->get() == target) 446 { 447 m_selected_target_idx = std::distance (begin, pos); 448 return m_selected_target_idx; 449 } 450 } 451 m_selected_target_idx = 0; 452 return m_selected_target_idx; 453 } 454 455 lldb::TargetSP 456 TargetList::GetSelectedTarget () 457 { 458 Mutex::Locker locker (m_target_list_mutex); 459 if (m_selected_target_idx >= m_target_list.size()) 460 m_selected_target_idx = 0; 461 return GetTargetAtIndex (m_selected_target_idx); 462 } 463