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