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