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 #include "lldb/lldb-python.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Core/Broadcaster.h" 17 #include "lldb/Core/Debugger.h" 18 #include "lldb/Core/Event.h" 19 #include "lldb/Core/Module.h" 20 #include "lldb/Core/ModuleSpec.h" 21 #include "lldb/Core/State.h" 22 #include "lldb/Core/Timer.h" 23 #include "lldb/Host/Host.h" 24 #include "lldb/Interpreter/CommandInterpreter.h" 25 #include "lldb/Interpreter/OptionGroupPlatform.h" 26 #include "lldb/Symbol/ObjectFile.h" 27 #include "lldb/Target/Platform.h" 28 #include "lldb/Target/Process.h" 29 #include "lldb/Target/TargetList.h" 30 31 using namespace lldb; 32 using namespace lldb_private; 33 34 ConstString & 35 TargetList::GetStaticBroadcasterClass () 36 { 37 static ConstString class_name ("lldb.targetList"); 38 return class_name; 39 } 40 41 //---------------------------------------------------------------------- 42 // TargetList constructor 43 //---------------------------------------------------------------------- 44 TargetList::TargetList(Debugger &debugger) : 45 Broadcaster(&debugger, TargetList::GetStaticBroadcasterClass().AsCString()), 46 m_target_list(), 47 m_target_list_mutex (Mutex::eMutexTypeRecursive), 48 m_selected_target_idx (0) 49 { 50 CheckInWithManager(); 51 } 52 53 //---------------------------------------------------------------------- 54 // Destructor 55 //---------------------------------------------------------------------- 56 TargetList::~TargetList() 57 { 58 Mutex::Locker locker(m_target_list_mutex); 59 m_target_list.clear(); 60 } 61 62 Error 63 TargetList::CreateTarget (Debugger &debugger, 64 const char *user_exe_path, 65 const char *triple_cstr, 66 bool get_dependent_files, 67 const OptionGroupPlatform *platform_options, 68 TargetSP &target_sp) 69 { 70 Error error; 71 PlatformSP platform_sp; 72 73 // This is purposely left empty unless it is specified by triple_cstr. 74 // If not initialized via triple_cstr, then the currently selected platform 75 // will set the architecture correctly. 76 const ArchSpec arch(triple_cstr); 77 if (triple_cstr && triple_cstr[0]) 78 { 79 if (!arch.IsValid()) 80 { 81 error.SetErrorStringWithFormat("invalid triple '%s'", triple_cstr); 82 return error; 83 } 84 } 85 86 ArchSpec platform_arch(arch); 87 88 89 if (user_exe_path && user_exe_path[0]) 90 { 91 ModuleSpecList module_specs; 92 ModuleSpec module_spec; 93 module_spec.GetFileSpec().SetFile(user_exe_path, true); 94 lldb::offset_t file_offset = 0; 95 const size_t num_specs = ObjectFile::GetModuleSpecifications (module_spec.GetFileSpec(), file_offset, module_specs); 96 if (num_specs > 0) 97 { 98 ModuleSpec matching_module_spec; 99 100 if (num_specs == 1) 101 { 102 if (module_specs.GetModuleSpecAtIndex(0, matching_module_spec)) 103 { 104 if (platform_arch.IsValid()) 105 { 106 if (!platform_arch.IsCompatibleMatch(matching_module_spec.GetArchitecture())) 107 { 108 error.SetErrorStringWithFormat("the specified architecture '%s' is not compatible with '%s' in '%s'", 109 platform_arch.GetTriple().str().c_str(), 110 matching_module_spec.GetArchitecture().GetTriple().str().c_str(), 111 module_spec.GetFileSpec().GetPath().c_str()); 112 return error; 113 } 114 } 115 else 116 { 117 // Only one arch and none was specified 118 platform_arch = matching_module_spec.GetArchitecture(); 119 } 120 } 121 } 122 else 123 { 124 if (arch.IsValid()) 125 { 126 module_spec.GetArchitecture() = arch; 127 if (module_specs.FindMatchingModuleSpec(module_spec, matching_module_spec)) 128 { 129 platform_arch = matching_module_spec.GetArchitecture(); 130 } 131 } 132 else 133 { 134 // No arch specified, select the first arch 135 if (module_specs.GetModuleSpecAtIndex(0, matching_module_spec)) 136 { 137 platform_arch = matching_module_spec.GetArchitecture(); 138 } 139 } 140 } 141 } 142 } 143 144 CommandInterpreter &interpreter = debugger.GetCommandInterpreter(); 145 if (platform_options) 146 { 147 if (platform_options->PlatformWasSpecified ()) 148 { 149 const bool select_platform = true; 150 platform_sp = platform_options->CreatePlatformWithOptions (interpreter, 151 arch, 152 select_platform, 153 error, 154 platform_arch); 155 if (!platform_sp) 156 return error; 157 } 158 } 159 160 if (!platform_sp) 161 { 162 // Get the current platform and make sure it is compatible with the 163 // current architecture if we have a valid architecture. 164 platform_sp = debugger.GetPlatformList().GetSelectedPlatform (); 165 166 if (arch.IsValid() && !platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch)) 167 { 168 platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch); 169 } 170 } 171 172 if (!platform_arch.IsValid()) 173 platform_arch = arch; 174 175 error = TargetList::CreateTarget (debugger, 176 user_exe_path, 177 platform_arch, 178 get_dependent_files, 179 platform_sp, 180 target_sp); 181 return error; 182 } 183 184 Error 185 TargetList::CreateTarget (Debugger &debugger, 186 const char *user_exe_path, 187 const ArchSpec& specified_arch, 188 bool get_dependent_files, 189 PlatformSP &platform_sp, 190 TargetSP &target_sp) 191 { 192 Timer scoped_timer (__PRETTY_FUNCTION__, 193 "TargetList::CreateTarget (file = '%s', arch = '%s')", 194 user_exe_path, 195 specified_arch.GetArchitectureName()); 196 Error error; 197 198 ArchSpec arch(specified_arch); 199 200 if (platform_sp) 201 { 202 if (arch.IsValid()) 203 { 204 if (!platform_sp->IsCompatibleArchitecture(arch, false, NULL)) 205 platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch); 206 } 207 } 208 else if (arch.IsValid()) 209 { 210 platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch); 211 } 212 213 if (!platform_sp) 214 platform_sp = debugger.GetPlatformList().GetSelectedPlatform(); 215 216 if (!arch.IsValid()) 217 arch = specified_arch; 218 219 FileSpec file (user_exe_path, false); 220 if (!file.Exists() && user_exe_path && user_exe_path[0] == '~') 221 { 222 file = FileSpec(user_exe_path, true); 223 } 224 bool user_exe_path_is_bundle = false; 225 char resolved_bundle_exe_path[PATH_MAX]; 226 resolved_bundle_exe_path[0] = '\0'; 227 if (file) 228 { 229 if (file.GetFileType() == FileSpec::eFileTypeDirectory) 230 user_exe_path_is_bundle = true; 231 232 if (file.IsRelativeToCurrentWorkingDirectory()) 233 { 234 // Ignore paths that start with "./" and "../" 235 if (!((user_exe_path[0] == '.' && user_exe_path[1] == '/') || 236 (user_exe_path[0] == '.' && user_exe_path[1] == '.' && user_exe_path[2] == '/'))) 237 { 238 char cwd[PATH_MAX]; 239 if (getcwd (cwd, sizeof(cwd))) 240 { 241 std::string cwd_user_exe_path (cwd); 242 cwd_user_exe_path += '/'; 243 cwd_user_exe_path += user_exe_path; 244 FileSpec cwd_file (cwd_user_exe_path.c_str(), false); 245 if (cwd_file.Exists()) 246 file = cwd_file; 247 } 248 } 249 } 250 251 ModuleSP exe_module_sp; 252 if (platform_sp) 253 { 254 FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths()); 255 error = platform_sp->ResolveExecutable (file, 256 arch, 257 exe_module_sp, 258 executable_search_paths.GetSize() ? &executable_search_paths : NULL); 259 } 260 261 if (error.Success() && exe_module_sp) 262 { 263 if (exe_module_sp->GetObjectFile() == NULL) 264 { 265 if (arch.IsValid()) 266 { 267 error.SetErrorStringWithFormat("\"%s\" doesn't contain architecture %s", 268 file.GetPath().c_str(), 269 arch.GetArchitectureName()); 270 } 271 else 272 { 273 error.SetErrorStringWithFormat("unsupported file type \"%s\"", 274 file.GetPath().c_str()); 275 } 276 return error; 277 } 278 target_sp.reset(new Target(debugger, arch, platform_sp)); 279 target_sp->SetExecutableModule (exe_module_sp, get_dependent_files); 280 if (user_exe_path_is_bundle) 281 exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path, sizeof(resolved_bundle_exe_path)); 282 } 283 } 284 else 285 { 286 // No file was specified, just create an empty target with any arch 287 // if a valid arch was specified 288 target_sp.reset(new Target(debugger, arch, platform_sp)); 289 } 290 291 if (target_sp) 292 { 293 // Set argv0 with what the user typed, unless the user specified a 294 // directory. If the user specified a directory, then it is probably a 295 // bundle that was resolved and we need to use the resolved bundle path 296 if (user_exe_path) 297 { 298 // Use exactly what the user typed as the first argument when we exec or posix_spawn 299 if (user_exe_path_is_bundle && resolved_bundle_exe_path[0]) 300 { 301 target_sp->SetArg0 (resolved_bundle_exe_path); 302 } 303 else 304 { 305 // Just use what the user typed 306 target_sp->SetArg0 (user_exe_path); 307 } 308 } 309 if (file.GetDirectory()) 310 { 311 FileSpec file_dir; 312 file_dir.GetDirectory() = file.GetDirectory(); 313 target_sp->GetExecutableSearchPaths ().Append (file_dir); 314 } 315 Mutex::Locker locker(m_target_list_mutex); 316 m_selected_target_idx = m_target_list.size(); 317 m_target_list.push_back(target_sp); 318 319 320 } 321 322 return error; 323 } 324 325 bool 326 TargetList::DeleteTarget (TargetSP &target_sp) 327 { 328 Mutex::Locker locker(m_target_list_mutex); 329 collection::iterator pos, end = m_target_list.end(); 330 331 for (pos = m_target_list.begin(); pos != end; ++pos) 332 { 333 if (pos->get() == target_sp.get()) 334 { 335 m_target_list.erase(pos); 336 return true; 337 } 338 } 339 return false; 340 } 341 342 343 TargetSP 344 TargetList::FindTargetWithExecutableAndArchitecture 345 ( 346 const FileSpec &exe_file_spec, 347 const ArchSpec *exe_arch_ptr 348 ) const 349 { 350 Mutex::Locker locker (m_target_list_mutex); 351 TargetSP target_sp; 352 bool full_match = exe_file_spec.GetDirectory(); 353 354 collection::const_iterator pos, end = m_target_list.end(); 355 for (pos = m_target_list.begin(); pos != end; ++pos) 356 { 357 Module *exe_module = (*pos)->GetExecutableModulePointer(); 358 359 if (exe_module) 360 { 361 if (FileSpec::Equal (exe_file_spec, exe_module->GetFileSpec(), full_match)) 362 { 363 if (exe_arch_ptr) 364 { 365 if (!exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture())) 366 continue; 367 } 368 target_sp = *pos; 369 break; 370 } 371 } 372 } 373 return target_sp; 374 } 375 376 TargetSP 377 TargetList::FindTargetWithProcessID (lldb::pid_t pid) const 378 { 379 Mutex::Locker locker(m_target_list_mutex); 380 TargetSP target_sp; 381 collection::const_iterator pos, end = m_target_list.end(); 382 for (pos = m_target_list.begin(); pos != end; ++pos) 383 { 384 Process* process = (*pos)->GetProcessSP().get(); 385 if (process && process->GetID() == pid) 386 { 387 target_sp = *pos; 388 break; 389 } 390 } 391 return target_sp; 392 } 393 394 395 TargetSP 396 TargetList::FindTargetWithProcess (Process *process) const 397 { 398 TargetSP target_sp; 399 if (process) 400 { 401 Mutex::Locker locker(m_target_list_mutex); 402 collection::const_iterator pos, end = m_target_list.end(); 403 for (pos = m_target_list.begin(); pos != end; ++pos) 404 { 405 if (process == (*pos)->GetProcessSP().get()) 406 { 407 target_sp = *pos; 408 break; 409 } 410 } 411 } 412 return target_sp; 413 } 414 415 TargetSP 416 TargetList::GetTargetSP (Target *target) const 417 { 418 TargetSP target_sp; 419 if (target) 420 { 421 Mutex::Locker locker(m_target_list_mutex); 422 collection::const_iterator pos, end = m_target_list.end(); 423 for (pos = m_target_list.begin(); pos != end; ++pos) 424 { 425 if (target == (*pos).get()) 426 { 427 target_sp = *pos; 428 break; 429 } 430 } 431 } 432 return target_sp; 433 } 434 435 uint32_t 436 TargetList::SendAsyncInterrupt (lldb::pid_t pid) 437 { 438 uint32_t num_async_interrupts_sent = 0; 439 440 if (pid != LLDB_INVALID_PROCESS_ID) 441 { 442 TargetSP target_sp(FindTargetWithProcessID (pid)); 443 if (target_sp.get()) 444 { 445 Process* process = target_sp->GetProcessSP().get(); 446 if (process) 447 { 448 process->SendAsyncInterrupt(); 449 ++num_async_interrupts_sent; 450 } 451 } 452 } 453 else 454 { 455 // We don't have a valid pid to broadcast to, so broadcast to the target 456 // list's async broadcaster... 457 BroadcastEvent (Process::eBroadcastBitInterrupt, NULL); 458 } 459 460 return num_async_interrupts_sent; 461 } 462 463 uint32_t 464 TargetList::SignalIfRunning (lldb::pid_t pid, int signo) 465 { 466 uint32_t num_signals_sent = 0; 467 Process *process = NULL; 468 if (pid == LLDB_INVALID_PROCESS_ID) 469 { 470 // Signal all processes with signal 471 Mutex::Locker locker(m_target_list_mutex); 472 collection::iterator pos, end = m_target_list.end(); 473 for (pos = m_target_list.begin(); pos != end; ++pos) 474 { 475 process = (*pos)->GetProcessSP().get(); 476 if (process) 477 { 478 if (process->IsAlive()) 479 { 480 ++num_signals_sent; 481 process->Signal (signo); 482 } 483 } 484 } 485 } 486 else 487 { 488 // Signal a specific process with signal 489 TargetSP target_sp(FindTargetWithProcessID (pid)); 490 if (target_sp.get()) 491 { 492 process = target_sp->GetProcessSP().get(); 493 if (process) 494 { 495 if (process->IsAlive()) 496 { 497 ++num_signals_sent; 498 process->Signal (signo); 499 } 500 } 501 } 502 } 503 return num_signals_sent; 504 } 505 506 int 507 TargetList::GetNumTargets () const 508 { 509 Mutex::Locker locker (m_target_list_mutex); 510 return m_target_list.size(); 511 } 512 513 lldb::TargetSP 514 TargetList::GetTargetAtIndex (uint32_t idx) const 515 { 516 TargetSP target_sp; 517 Mutex::Locker locker (m_target_list_mutex); 518 if (idx < m_target_list.size()) 519 target_sp = m_target_list[idx]; 520 return target_sp; 521 } 522 523 uint32_t 524 TargetList::GetIndexOfTarget (lldb::TargetSP target_sp) const 525 { 526 Mutex::Locker locker (m_target_list_mutex); 527 size_t num_targets = m_target_list.size(); 528 for (size_t idx = 0; idx < num_targets; idx++) 529 { 530 if (target_sp == m_target_list[idx]) 531 return idx; 532 } 533 return UINT32_MAX; 534 } 535 536 uint32_t 537 TargetList::SetSelectedTarget (Target* target) 538 { 539 Mutex::Locker locker (m_target_list_mutex); 540 collection::const_iterator pos, 541 begin = m_target_list.begin(), 542 end = m_target_list.end(); 543 for (pos = begin; pos != end; ++pos) 544 { 545 if (pos->get() == target) 546 { 547 m_selected_target_idx = std::distance (begin, pos); 548 return m_selected_target_idx; 549 } 550 } 551 m_selected_target_idx = 0; 552 return m_selected_target_idx; 553 } 554 555 lldb::TargetSP 556 TargetList::GetSelectedTarget () 557 { 558 Mutex::Locker locker (m_target_list_mutex); 559 if (m_selected_target_idx >= m_target_list.size()) 560 m_selected_target_idx = 0; 561 return GetTargetAtIndex (m_selected_target_idx); 562 } 563