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