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 // Don't just select the first architecture, we want to let the platform select 133 // the best architecture first when there are multiple archs. 134 // else 135 // { 136 // // No arch specified, select the first arch 137 // if (module_specs.GetModuleSpecAtIndex(0, matching_module_spec)) 138 // { 139 // platform_arch = matching_module_spec.GetArchitecture(); 140 // } 141 // } 142 } 143 } 144 } 145 146 CommandInterpreter &interpreter = debugger.GetCommandInterpreter(); 147 if (platform_options) 148 { 149 if (platform_options->PlatformWasSpecified ()) 150 { 151 const bool select_platform = true; 152 platform_sp = platform_options->CreatePlatformWithOptions (interpreter, 153 arch, 154 select_platform, 155 error, 156 platform_arch); 157 if (!platform_sp) 158 return error; 159 } 160 } 161 162 if (!platform_sp) 163 { 164 // Get the current platform and make sure it is compatible with the 165 // current architecture if we have a valid architecture. 166 platform_sp = debugger.GetPlatformList().GetSelectedPlatform (); 167 168 if (arch.IsValid() && !platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch)) 169 { 170 platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch); 171 } 172 } 173 174 if (!platform_arch.IsValid()) 175 platform_arch = arch; 176 177 error = TargetList::CreateTarget (debugger, 178 user_exe_path, 179 platform_arch, 180 get_dependent_files, 181 platform_sp, 182 target_sp); 183 return error; 184 } 185 186 Error 187 TargetList::CreateTarget (Debugger &debugger, 188 const char *user_exe_path, 189 const ArchSpec& specified_arch, 190 bool get_dependent_files, 191 PlatformSP &platform_sp, 192 TargetSP &target_sp) 193 { 194 Timer scoped_timer (__PRETTY_FUNCTION__, 195 "TargetList::CreateTarget (file = '%s', arch = '%s')", 196 user_exe_path, 197 specified_arch.GetArchitectureName()); 198 Error error; 199 200 ArchSpec arch(specified_arch); 201 202 if (platform_sp) 203 { 204 if (arch.IsValid()) 205 { 206 if (!platform_sp->IsCompatibleArchitecture(arch, false, NULL)) 207 platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch); 208 } 209 } 210 else if (arch.IsValid()) 211 { 212 platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch); 213 } 214 215 if (!platform_sp) 216 platform_sp = debugger.GetPlatformList().GetSelectedPlatform(); 217 218 if (!arch.IsValid()) 219 arch = specified_arch; 220 221 FileSpec file (user_exe_path, false); 222 if (!file.Exists() && user_exe_path && user_exe_path[0] == '~') 223 { 224 file = FileSpec(user_exe_path, true); 225 } 226 bool user_exe_path_is_bundle = false; 227 char resolved_bundle_exe_path[PATH_MAX]; 228 resolved_bundle_exe_path[0] = '\0'; 229 if (file) 230 { 231 if (file.GetFileType() == FileSpec::eFileTypeDirectory) 232 user_exe_path_is_bundle = true; 233 234 if (file.IsRelativeToCurrentWorkingDirectory()) 235 { 236 // Ignore paths that start with "./" and "../" 237 if (!((user_exe_path[0] == '.' && user_exe_path[1] == '/') || 238 (user_exe_path[0] == '.' && user_exe_path[1] == '.' && user_exe_path[2] == '/'))) 239 { 240 char cwd[PATH_MAX]; 241 if (getcwd (cwd, sizeof(cwd))) 242 { 243 std::string cwd_user_exe_path (cwd); 244 cwd_user_exe_path += '/'; 245 cwd_user_exe_path += user_exe_path; 246 FileSpec cwd_file (cwd_user_exe_path.c_str(), false); 247 if (cwd_file.Exists()) 248 file = cwd_file; 249 } 250 } 251 } 252 253 ModuleSP exe_module_sp; 254 if (platform_sp) 255 { 256 FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths()); 257 error = platform_sp->ResolveExecutable (file, 258 arch, 259 exe_module_sp, 260 executable_search_paths.GetSize() ? &executable_search_paths : NULL); 261 } 262 263 if (error.Success() && exe_module_sp) 264 { 265 if (exe_module_sp->GetObjectFile() == NULL) 266 { 267 if (arch.IsValid()) 268 { 269 error.SetErrorStringWithFormat("\"%s\" doesn't contain architecture %s", 270 file.GetPath().c_str(), 271 arch.GetArchitectureName()); 272 } 273 else 274 { 275 error.SetErrorStringWithFormat("unsupported file type \"%s\"", 276 file.GetPath().c_str()); 277 } 278 return error; 279 } 280 target_sp.reset(new Target(debugger, arch, platform_sp)); 281 target_sp->SetExecutableModule (exe_module_sp, get_dependent_files); 282 if (user_exe_path_is_bundle) 283 exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path, sizeof(resolved_bundle_exe_path)); 284 } 285 } 286 else 287 { 288 // No file was specified, just create an empty target with any arch 289 // if a valid arch was specified 290 target_sp.reset(new Target(debugger, arch, platform_sp)); 291 } 292 293 if (target_sp) 294 { 295 // Set argv0 with what the user typed, unless the user specified a 296 // directory. If the user specified a directory, then it is probably a 297 // bundle that was resolved and we need to use the resolved bundle path 298 if (user_exe_path) 299 { 300 // Use exactly what the user typed as the first argument when we exec or posix_spawn 301 if (user_exe_path_is_bundle && resolved_bundle_exe_path[0]) 302 { 303 target_sp->SetArg0 (resolved_bundle_exe_path); 304 } 305 else 306 { 307 // Just use what the user typed 308 target_sp->SetArg0 (user_exe_path); 309 } 310 } 311 if (file.GetDirectory()) 312 { 313 FileSpec file_dir; 314 file_dir.GetDirectory() = file.GetDirectory(); 315 target_sp->GetExecutableSearchPaths ().Append (file_dir); 316 } 317 Mutex::Locker locker(m_target_list_mutex); 318 m_selected_target_idx = m_target_list.size(); 319 m_target_list.push_back(target_sp); 320 321 322 } 323 324 return error; 325 } 326 327 bool 328 TargetList::DeleteTarget (TargetSP &target_sp) 329 { 330 Mutex::Locker locker(m_target_list_mutex); 331 collection::iterator pos, end = m_target_list.end(); 332 333 for (pos = m_target_list.begin(); pos != end; ++pos) 334 { 335 if (pos->get() == target_sp.get()) 336 { 337 m_target_list.erase(pos); 338 return true; 339 } 340 } 341 return false; 342 } 343 344 345 TargetSP 346 TargetList::FindTargetWithExecutableAndArchitecture 347 ( 348 const FileSpec &exe_file_spec, 349 const ArchSpec *exe_arch_ptr 350 ) const 351 { 352 Mutex::Locker locker (m_target_list_mutex); 353 TargetSP target_sp; 354 bool full_match = exe_file_spec.GetDirectory(); 355 356 collection::const_iterator pos, end = m_target_list.end(); 357 for (pos = m_target_list.begin(); pos != end; ++pos) 358 { 359 Module *exe_module = (*pos)->GetExecutableModulePointer(); 360 361 if (exe_module) 362 { 363 if (FileSpec::Equal (exe_file_spec, exe_module->GetFileSpec(), full_match)) 364 { 365 if (exe_arch_ptr) 366 { 367 if (!exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture())) 368 continue; 369 } 370 target_sp = *pos; 371 break; 372 } 373 } 374 } 375 return target_sp; 376 } 377 378 TargetSP 379 TargetList::FindTargetWithProcessID (lldb::pid_t pid) const 380 { 381 Mutex::Locker locker(m_target_list_mutex); 382 TargetSP target_sp; 383 collection::const_iterator pos, end = m_target_list.end(); 384 for (pos = m_target_list.begin(); pos != end; ++pos) 385 { 386 Process* process = (*pos)->GetProcessSP().get(); 387 if (process && process->GetID() == pid) 388 { 389 target_sp = *pos; 390 break; 391 } 392 } 393 return target_sp; 394 } 395 396 397 TargetSP 398 TargetList::FindTargetWithProcess (Process *process) const 399 { 400 TargetSP target_sp; 401 if (process) 402 { 403 Mutex::Locker locker(m_target_list_mutex); 404 collection::const_iterator pos, end = m_target_list.end(); 405 for (pos = m_target_list.begin(); pos != end; ++pos) 406 { 407 if (process == (*pos)->GetProcessSP().get()) 408 { 409 target_sp = *pos; 410 break; 411 } 412 } 413 } 414 return target_sp; 415 } 416 417 TargetSP 418 TargetList::GetTargetSP (Target *target) const 419 { 420 TargetSP target_sp; 421 if (target) 422 { 423 Mutex::Locker locker(m_target_list_mutex); 424 collection::const_iterator pos, end = m_target_list.end(); 425 for (pos = m_target_list.begin(); pos != end; ++pos) 426 { 427 if (target == (*pos).get()) 428 { 429 target_sp = *pos; 430 break; 431 } 432 } 433 } 434 return target_sp; 435 } 436 437 uint32_t 438 TargetList::SendAsyncInterrupt (lldb::pid_t pid) 439 { 440 uint32_t num_async_interrupts_sent = 0; 441 442 if (pid != LLDB_INVALID_PROCESS_ID) 443 { 444 TargetSP target_sp(FindTargetWithProcessID (pid)); 445 if (target_sp.get()) 446 { 447 Process* process = target_sp->GetProcessSP().get(); 448 if (process) 449 { 450 process->SendAsyncInterrupt(); 451 ++num_async_interrupts_sent; 452 } 453 } 454 } 455 else 456 { 457 // We don't have a valid pid to broadcast to, so broadcast to the target 458 // list's async broadcaster... 459 BroadcastEvent (Process::eBroadcastBitInterrupt, NULL); 460 } 461 462 return num_async_interrupts_sent; 463 } 464 465 uint32_t 466 TargetList::SignalIfRunning (lldb::pid_t pid, int signo) 467 { 468 uint32_t num_signals_sent = 0; 469 Process *process = NULL; 470 if (pid == LLDB_INVALID_PROCESS_ID) 471 { 472 // Signal all processes with signal 473 Mutex::Locker locker(m_target_list_mutex); 474 collection::iterator pos, end = m_target_list.end(); 475 for (pos = m_target_list.begin(); pos != end; ++pos) 476 { 477 process = (*pos)->GetProcessSP().get(); 478 if (process) 479 { 480 if (process->IsAlive()) 481 { 482 ++num_signals_sent; 483 process->Signal (signo); 484 } 485 } 486 } 487 } 488 else 489 { 490 // Signal a specific process with signal 491 TargetSP target_sp(FindTargetWithProcessID (pid)); 492 if (target_sp.get()) 493 { 494 process = target_sp->GetProcessSP().get(); 495 if (process) 496 { 497 if (process->IsAlive()) 498 { 499 ++num_signals_sent; 500 process->Signal (signo); 501 } 502 } 503 } 504 } 505 return num_signals_sent; 506 } 507 508 int 509 TargetList::GetNumTargets () const 510 { 511 Mutex::Locker locker (m_target_list_mutex); 512 return m_target_list.size(); 513 } 514 515 lldb::TargetSP 516 TargetList::GetTargetAtIndex (uint32_t idx) const 517 { 518 TargetSP target_sp; 519 Mutex::Locker locker (m_target_list_mutex); 520 if (idx < m_target_list.size()) 521 target_sp = m_target_list[idx]; 522 return target_sp; 523 } 524 525 uint32_t 526 TargetList::GetIndexOfTarget (lldb::TargetSP target_sp) const 527 { 528 Mutex::Locker locker (m_target_list_mutex); 529 size_t num_targets = m_target_list.size(); 530 for (size_t idx = 0; idx < num_targets; idx++) 531 { 532 if (target_sp == m_target_list[idx]) 533 return idx; 534 } 535 return UINT32_MAX; 536 } 537 538 uint32_t 539 TargetList::SetSelectedTarget (Target* target) 540 { 541 Mutex::Locker locker (m_target_list_mutex); 542 collection::const_iterator pos, 543 begin = m_target_list.begin(), 544 end = m_target_list.end(); 545 for (pos = begin; pos != end; ++pos) 546 { 547 if (pos->get() == target) 548 { 549 m_selected_target_idx = std::distance (begin, pos); 550 return m_selected_target_idx; 551 } 552 } 553 m_selected_target_idx = 0; 554 return m_selected_target_idx; 555 } 556 557 lldb::TargetSP 558 TargetList::GetSelectedTarget () 559 { 560 Mutex::Locker locker (m_target_list_mutex); 561 if (m_selected_target_idx >= m_target_list.size()) 562 m_selected_target_idx = 0; 563 return GetTargetAtIndex (m_selected_target_idx); 564 } 565