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