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 Mutex::Locker locker(m_target_list_mutex); 220 m_selected_target_idx = m_target_list.size(); 221 m_target_list.push_back(target_sp); 222 } 223 224 return error; 225 } 226 227 bool 228 TargetList::DeleteTarget (TargetSP &target_sp) 229 { 230 Mutex::Locker locker(m_target_list_mutex); 231 collection::iterator pos, end = m_target_list.end(); 232 233 for (pos = m_target_list.begin(); pos != end; ++pos) 234 { 235 if (pos->get() == target_sp.get()) 236 { 237 m_target_list.erase(pos); 238 return true; 239 } 240 } 241 return false; 242 } 243 244 245 TargetSP 246 TargetList::FindTargetWithExecutableAndArchitecture 247 ( 248 const FileSpec &exe_file_spec, 249 const ArchSpec *exe_arch_ptr 250 ) const 251 { 252 Mutex::Locker locker (m_target_list_mutex); 253 TargetSP target_sp; 254 bool full_match = exe_file_spec.GetDirectory(); 255 256 collection::const_iterator pos, end = m_target_list.end(); 257 for (pos = m_target_list.begin(); pos != end; ++pos) 258 { 259 Module *exe_module = (*pos)->GetExecutableModulePointer(); 260 261 if (exe_module) 262 { 263 if (FileSpec::Equal (exe_file_spec, exe_module->GetFileSpec(), full_match)) 264 { 265 if (exe_arch_ptr) 266 { 267 if (*exe_arch_ptr != exe_module->GetArchitecture()) 268 continue; 269 } 270 target_sp = *pos; 271 break; 272 } 273 } 274 } 275 return target_sp; 276 } 277 278 TargetSP 279 TargetList::FindTargetWithProcessID (lldb::pid_t pid) const 280 { 281 Mutex::Locker locker(m_target_list_mutex); 282 TargetSP target_sp; 283 collection::const_iterator pos, end = m_target_list.end(); 284 for (pos = m_target_list.begin(); pos != end; ++pos) 285 { 286 Process* process = (*pos)->GetProcessSP().get(); 287 if (process && process->GetID() == pid) 288 { 289 target_sp = *pos; 290 break; 291 } 292 } 293 return target_sp; 294 } 295 296 297 TargetSP 298 TargetList::FindTargetWithProcess (Process *process) const 299 { 300 TargetSP target_sp; 301 if (process) 302 { 303 Mutex::Locker locker(m_target_list_mutex); 304 collection::const_iterator pos, end = m_target_list.end(); 305 for (pos = m_target_list.begin(); pos != end; ++pos) 306 { 307 if (process == (*pos)->GetProcessSP().get()) 308 { 309 target_sp = *pos; 310 break; 311 } 312 } 313 } 314 return target_sp; 315 } 316 317 TargetSP 318 TargetList::GetTargetSP (Target *target) const 319 { 320 TargetSP target_sp; 321 if (target) 322 { 323 Mutex::Locker locker(m_target_list_mutex); 324 collection::const_iterator pos, end = m_target_list.end(); 325 for (pos = m_target_list.begin(); pos != end; ++pos) 326 { 327 if (target == (*pos).get()) 328 { 329 target_sp = *pos; 330 break; 331 } 332 } 333 } 334 return target_sp; 335 } 336 337 uint32_t 338 TargetList::SendAsyncInterrupt (lldb::pid_t pid) 339 { 340 uint32_t num_async_interrupts_sent = 0; 341 342 if (pid != LLDB_INVALID_PROCESS_ID) 343 { 344 TargetSP target_sp(FindTargetWithProcessID (pid)); 345 if (target_sp.get()) 346 { 347 Process* process = target_sp->GetProcessSP().get(); 348 if (process) 349 { 350 process->SendAsyncInterrupt(); 351 ++num_async_interrupts_sent; 352 } 353 } 354 } 355 else 356 { 357 // We don't have a valid pid to broadcast to, so broadcast to the target 358 // list's async broadcaster... 359 BroadcastEvent (Process::eBroadcastBitInterrupt, NULL); 360 } 361 362 return num_async_interrupts_sent; 363 } 364 365 uint32_t 366 TargetList::SignalIfRunning (lldb::pid_t pid, int signo) 367 { 368 uint32_t num_signals_sent = 0; 369 Process *process = NULL; 370 if (pid == LLDB_INVALID_PROCESS_ID) 371 { 372 // Signal all processes with signal 373 Mutex::Locker locker(m_target_list_mutex); 374 collection::iterator pos, end = m_target_list.end(); 375 for (pos = m_target_list.begin(); pos != end; ++pos) 376 { 377 process = (*pos)->GetProcessSP().get(); 378 if (process) 379 { 380 if (process->IsAlive()) 381 { 382 ++num_signals_sent; 383 process->Signal (signo); 384 } 385 } 386 } 387 } 388 else 389 { 390 // Signal a specific process with signal 391 TargetSP target_sp(FindTargetWithProcessID (pid)); 392 if (target_sp.get()) 393 { 394 process = target_sp->GetProcessSP().get(); 395 if (process) 396 { 397 if (process->IsAlive()) 398 { 399 ++num_signals_sent; 400 process->Signal (signo); 401 } 402 } 403 } 404 } 405 return num_signals_sent; 406 } 407 408 int 409 TargetList::GetNumTargets () const 410 { 411 Mutex::Locker locker (m_target_list_mutex); 412 return m_target_list.size(); 413 } 414 415 lldb::TargetSP 416 TargetList::GetTargetAtIndex (uint32_t idx) const 417 { 418 TargetSP target_sp; 419 Mutex::Locker locker (m_target_list_mutex); 420 if (idx < m_target_list.size()) 421 target_sp = m_target_list[idx]; 422 return target_sp; 423 } 424 425 uint32_t 426 TargetList::GetIndexOfTarget (lldb::TargetSP target_sp) const 427 { 428 Mutex::Locker locker (m_target_list_mutex); 429 size_t num_targets = m_target_list.size(); 430 for (size_t idx = 0; idx < num_targets; idx++) 431 { 432 if (target_sp == m_target_list[idx]) 433 return idx; 434 } 435 return UINT32_MAX; 436 } 437 438 uint32_t 439 TargetList::SetSelectedTarget (Target* target) 440 { 441 Mutex::Locker locker (m_target_list_mutex); 442 collection::const_iterator pos, 443 begin = m_target_list.begin(), 444 end = m_target_list.end(); 445 for (pos = begin; pos != end; ++pos) 446 { 447 if (pos->get() == target) 448 { 449 m_selected_target_idx = std::distance (begin, pos); 450 return m_selected_target_idx; 451 } 452 } 453 m_selected_target_idx = 0; 454 return m_selected_target_idx; 455 } 456 457 lldb::TargetSP 458 TargetList::GetSelectedTarget () 459 { 460 Mutex::Locker locker (m_target_list_mutex); 461 if (m_selected_target_idx >= m_target_list.size()) 462 m_selected_target_idx = 0; 463 return GetTargetAtIndex (m_selected_target_idx); 464 } 465