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