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