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 166 return error; 167 } 168 169 bool 170 TargetList::DeleteTarget (TargetSP &target_sp) 171 { 172 Mutex::Locker locker(m_target_list_mutex); 173 collection::iterator pos, end = m_target_list.end(); 174 175 for (pos = m_target_list.begin(); pos != end; ++pos) 176 { 177 if (pos->get() == target_sp.get()) 178 { 179 m_target_list.erase(pos); 180 return true; 181 } 182 } 183 return false; 184 } 185 186 187 TargetSP 188 TargetList::FindTargetWithExecutableAndArchitecture 189 ( 190 const FileSpec &exe_file_spec, 191 const ArchSpec *exe_arch_ptr 192 ) const 193 { 194 Mutex::Locker locker (m_target_list_mutex); 195 TargetSP target_sp; 196 bool full_match = exe_file_spec.GetDirectory(); 197 198 collection::const_iterator pos, end = m_target_list.end(); 199 for (pos = m_target_list.begin(); pos != end; ++pos) 200 { 201 Module *exe_module = (*pos)->GetExecutableModulePointer(); 202 203 if (exe_module) 204 { 205 if (FileSpec::Equal (exe_file_spec, exe_module->GetFileSpec(), full_match)) 206 { 207 if (exe_arch_ptr) 208 { 209 if (*exe_arch_ptr != exe_module->GetArchitecture()) 210 continue; 211 } 212 target_sp = *pos; 213 break; 214 } 215 } 216 } 217 return target_sp; 218 } 219 220 TargetSP 221 TargetList::FindTargetWithProcessID (lldb::pid_t pid) const 222 { 223 Mutex::Locker locker(m_target_list_mutex); 224 TargetSP target_sp; 225 collection::const_iterator pos, end = m_target_list.end(); 226 for (pos = m_target_list.begin(); pos != end; ++pos) 227 { 228 Process* process = (*pos)->GetProcessSP().get(); 229 if (process && process->GetID() == pid) 230 { 231 target_sp = *pos; 232 break; 233 } 234 } 235 return target_sp; 236 } 237 238 239 TargetSP 240 TargetList::FindTargetWithProcess (Process *process) const 241 { 242 TargetSP target_sp; 243 if (process) 244 { 245 Mutex::Locker locker(m_target_list_mutex); 246 collection::const_iterator pos, end = m_target_list.end(); 247 for (pos = m_target_list.begin(); pos != end; ++pos) 248 { 249 if (process == (*pos)->GetProcessSP().get()) 250 { 251 target_sp = *pos; 252 break; 253 } 254 } 255 } 256 return target_sp; 257 } 258 259 TargetSP 260 TargetList::GetTargetSP (Target *target) const 261 { 262 TargetSP target_sp; 263 if (target) 264 { 265 Mutex::Locker locker(m_target_list_mutex); 266 collection::const_iterator pos, end = m_target_list.end(); 267 for (pos = m_target_list.begin(); pos != end; ++pos) 268 { 269 if (target == (*pos).get()) 270 { 271 target_sp = *pos; 272 break; 273 } 274 } 275 } 276 return target_sp; 277 } 278 279 uint32_t 280 TargetList::SendAsyncInterrupt (lldb::pid_t pid) 281 { 282 uint32_t num_async_interrupts_sent = 0; 283 284 if (pid != LLDB_INVALID_PROCESS_ID) 285 { 286 TargetSP target_sp(FindTargetWithProcessID (pid)); 287 if (target_sp.get()) 288 { 289 Process* process = target_sp->GetProcessSP().get(); 290 if (process) 291 { 292 process->BroadcastEvent (Process::eBroadcastBitInterrupt, NULL); 293 ++num_async_interrupts_sent; 294 } 295 } 296 } 297 else 298 { 299 // We don't have a valid pid to broadcast to, so broadcast to the target 300 // list's async broadcaster... 301 BroadcastEvent (Process::eBroadcastBitInterrupt, NULL); 302 } 303 304 return num_async_interrupts_sent; 305 } 306 307 uint32_t 308 TargetList::SignalIfRunning (lldb::pid_t pid, int signo) 309 { 310 uint32_t num_signals_sent = 0; 311 Process *process = NULL; 312 if (pid == LLDB_INVALID_PROCESS_ID) 313 { 314 // Signal all processes with signal 315 Mutex::Locker locker(m_target_list_mutex); 316 collection::iterator pos, end = m_target_list.end(); 317 for (pos = m_target_list.begin(); pos != end; ++pos) 318 { 319 process = (*pos)->GetProcessSP().get(); 320 if (process) 321 { 322 if (process->IsAlive()) 323 { 324 ++num_signals_sent; 325 process->Signal (signo); 326 } 327 } 328 } 329 } 330 else 331 { 332 // Signal a specific process with signal 333 TargetSP target_sp(FindTargetWithProcessID (pid)); 334 if (target_sp.get()) 335 { 336 process = target_sp->GetProcessSP().get(); 337 if (process) 338 { 339 if (process->IsAlive()) 340 { 341 ++num_signals_sent; 342 process->Signal (signo); 343 } 344 } 345 } 346 } 347 return num_signals_sent; 348 } 349 350 int 351 TargetList::GetNumTargets () const 352 { 353 Mutex::Locker locker (m_target_list_mutex); 354 return m_target_list.size(); 355 } 356 357 lldb::TargetSP 358 TargetList::GetTargetAtIndex (uint32_t idx) const 359 { 360 TargetSP target_sp; 361 Mutex::Locker locker (m_target_list_mutex); 362 if (idx < m_target_list.size()) 363 target_sp = m_target_list[idx]; 364 return target_sp; 365 } 366 367 uint32_t 368 TargetList::SetSelectedTarget (Target* target) 369 { 370 Mutex::Locker locker (m_target_list_mutex); 371 collection::const_iterator pos, 372 begin = m_target_list.begin(), 373 end = m_target_list.end(); 374 for (pos = begin; pos != end; ++pos) 375 { 376 if (pos->get() == target) 377 { 378 m_selected_target_idx = std::distance (begin, pos); 379 return m_selected_target_idx; 380 } 381 } 382 m_selected_target_idx = 0; 383 return m_selected_target_idx; 384 } 385 386 lldb::TargetSP 387 TargetList::GetSelectedTarget () 388 { 389 Mutex::Locker locker (m_target_list_mutex); 390 if (m_selected_target_idx >= m_target_list.size()) 391 m_selected_target_idx = 0; 392 return GetTargetAtIndex (m_selected_target_idx); 393 } 394