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 (!arch.IsValid()) 169 arch = specified_arch; 170 171 172 if (file) 173 { 174 ModuleSP exe_module_sp; 175 FileSpec resolved_file(file); 176 if (platform_sp) 177 { 178 FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths()); 179 error = platform_sp->ResolveExecutable (file, 180 arch, 181 exe_module_sp, 182 executable_search_paths.GetSize() ? &executable_search_paths : NULL); 183 } 184 185 if (error.Success() && exe_module_sp) 186 { 187 if (exe_module_sp->GetObjectFile() == NULL) 188 { 189 if (arch.IsValid()) 190 { 191 error.SetErrorStringWithFormat("\"%s%s%s\" doesn't contain architecture %s", 192 file.GetDirectory().AsCString(), 193 file.GetDirectory() ? "/" : "", 194 file.GetFilename().AsCString(), 195 arch.GetArchitectureName()); 196 } 197 else 198 { 199 error.SetErrorStringWithFormat("unsupported file type \"%s%s%s\"", 200 file.GetDirectory().AsCString(), 201 file.GetDirectory() ? "/" : "", 202 file.GetFilename().AsCString()); 203 } 204 return error; 205 } 206 target_sp.reset(new Target(debugger, arch, platform_sp)); 207 target_sp->SetExecutableModule (exe_module_sp, get_dependent_files); 208 } 209 } 210 else 211 { 212 // No file was specified, just create an empty target with any arch 213 // if a valid arch was specified 214 target_sp.reset(new Target(debugger, arch, platform_sp)); 215 } 216 217 if (target_sp) 218 { 219 target_sp->UpdateInstanceName(); 220 221 Mutex::Locker locker(m_target_list_mutex); 222 m_selected_target_idx = m_target_list.size(); 223 m_target_list.push_back(target_sp); 224 } 225 226 return error; 227 } 228 229 bool 230 TargetList::DeleteTarget (TargetSP &target_sp) 231 { 232 Mutex::Locker locker(m_target_list_mutex); 233 collection::iterator pos, end = m_target_list.end(); 234 235 for (pos = m_target_list.begin(); pos != end; ++pos) 236 { 237 if (pos->get() == target_sp.get()) 238 { 239 m_target_list.erase(pos); 240 return true; 241 } 242 } 243 return false; 244 } 245 246 247 TargetSP 248 TargetList::FindTargetWithExecutableAndArchitecture 249 ( 250 const FileSpec &exe_file_spec, 251 const ArchSpec *exe_arch_ptr 252 ) const 253 { 254 Mutex::Locker locker (m_target_list_mutex); 255 TargetSP target_sp; 256 bool full_match = exe_file_spec.GetDirectory(); 257 258 collection::const_iterator pos, end = m_target_list.end(); 259 for (pos = m_target_list.begin(); pos != end; ++pos) 260 { 261 Module *exe_module = (*pos)->GetExecutableModulePointer(); 262 263 if (exe_module) 264 { 265 if (FileSpec::Equal (exe_file_spec, exe_module->GetFileSpec(), full_match)) 266 { 267 if (exe_arch_ptr) 268 { 269 if (*exe_arch_ptr != exe_module->GetArchitecture()) 270 continue; 271 } 272 target_sp = *pos; 273 break; 274 } 275 } 276 } 277 return target_sp; 278 } 279 280 TargetSP 281 TargetList::FindTargetWithProcessID (lldb::pid_t pid) const 282 { 283 Mutex::Locker locker(m_target_list_mutex); 284 TargetSP target_sp; 285 collection::const_iterator pos, end = m_target_list.end(); 286 for (pos = m_target_list.begin(); pos != end; ++pos) 287 { 288 Process* process = (*pos)->GetProcessSP().get(); 289 if (process && process->GetID() == pid) 290 { 291 target_sp = *pos; 292 break; 293 } 294 } 295 return target_sp; 296 } 297 298 299 TargetSP 300 TargetList::FindTargetWithProcess (Process *process) const 301 { 302 TargetSP target_sp; 303 if (process) 304 { 305 Mutex::Locker locker(m_target_list_mutex); 306 collection::const_iterator pos, end = m_target_list.end(); 307 for (pos = m_target_list.begin(); pos != end; ++pos) 308 { 309 if (process == (*pos)->GetProcessSP().get()) 310 { 311 target_sp = *pos; 312 break; 313 } 314 } 315 } 316 return target_sp; 317 } 318 319 TargetSP 320 TargetList::GetTargetSP (Target *target) const 321 { 322 TargetSP target_sp; 323 if (target) 324 { 325 Mutex::Locker locker(m_target_list_mutex); 326 collection::const_iterator pos, end = m_target_list.end(); 327 for (pos = m_target_list.begin(); pos != end; ++pos) 328 { 329 if (target == (*pos).get()) 330 { 331 target_sp = *pos; 332 break; 333 } 334 } 335 } 336 return target_sp; 337 } 338 339 uint32_t 340 TargetList::SendAsyncInterrupt (lldb::pid_t pid) 341 { 342 uint32_t num_async_interrupts_sent = 0; 343 344 if (pid != LLDB_INVALID_PROCESS_ID) 345 { 346 TargetSP target_sp(FindTargetWithProcessID (pid)); 347 if (target_sp.get()) 348 { 349 Process* process = target_sp->GetProcessSP().get(); 350 if (process) 351 { 352 process->SendAsyncInterrupt(); 353 ++num_async_interrupts_sent; 354 } 355 } 356 } 357 else 358 { 359 // We don't have a valid pid to broadcast to, so broadcast to the target 360 // list's async broadcaster... 361 BroadcastEvent (Process::eBroadcastBitInterrupt, NULL); 362 } 363 364 return num_async_interrupts_sent; 365 } 366 367 uint32_t 368 TargetList::SignalIfRunning (lldb::pid_t pid, int signo) 369 { 370 uint32_t num_signals_sent = 0; 371 Process *process = NULL; 372 if (pid == LLDB_INVALID_PROCESS_ID) 373 { 374 // Signal all processes with signal 375 Mutex::Locker locker(m_target_list_mutex); 376 collection::iterator pos, end = m_target_list.end(); 377 for (pos = m_target_list.begin(); pos != end; ++pos) 378 { 379 process = (*pos)->GetProcessSP().get(); 380 if (process) 381 { 382 if (process->IsAlive()) 383 { 384 ++num_signals_sent; 385 process->Signal (signo); 386 } 387 } 388 } 389 } 390 else 391 { 392 // Signal a specific process with signal 393 TargetSP target_sp(FindTargetWithProcessID (pid)); 394 if (target_sp.get()) 395 { 396 process = target_sp->GetProcessSP().get(); 397 if (process) 398 { 399 if (process->IsAlive()) 400 { 401 ++num_signals_sent; 402 process->Signal (signo); 403 } 404 } 405 } 406 } 407 return num_signals_sent; 408 } 409 410 int 411 TargetList::GetNumTargets () const 412 { 413 Mutex::Locker locker (m_target_list_mutex); 414 return m_target_list.size(); 415 } 416 417 lldb::TargetSP 418 TargetList::GetTargetAtIndex (uint32_t idx) const 419 { 420 TargetSP target_sp; 421 Mutex::Locker locker (m_target_list_mutex); 422 if (idx < m_target_list.size()) 423 target_sp = m_target_list[idx]; 424 return target_sp; 425 } 426 427 uint32_t 428 TargetList::GetIndexOfTarget (lldb::TargetSP target_sp) const 429 { 430 Mutex::Locker locker (m_target_list_mutex); 431 size_t num_targets = m_target_list.size(); 432 for (size_t idx = 0; idx < num_targets; idx++) 433 { 434 if (target_sp == m_target_list[idx]) 435 return idx; 436 } 437 return UINT32_MAX; 438 } 439 440 uint32_t 441 TargetList::SetSelectedTarget (Target* target) 442 { 443 Mutex::Locker locker (m_target_list_mutex); 444 collection::const_iterator pos, 445 begin = m_target_list.begin(), 446 end = m_target_list.end(); 447 for (pos = begin; pos != end; ++pos) 448 { 449 if (pos->get() == target) 450 { 451 m_selected_target_idx = std::distance (begin, pos); 452 return m_selected_target_idx; 453 } 454 } 455 m_selected_target_idx = 0; 456 return m_selected_target_idx; 457 } 458 459 lldb::TargetSP 460 TargetList::GetSelectedTarget () 461 { 462 Mutex::Locker locker (m_target_list_mutex); 463 if (m_selected_target_idx >= m_target_list.size()) 464 m_selected_target_idx = 0; 465 return GetTargetAtIndex (m_selected_target_idx); 466 } 467