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