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