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