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