130fdc8d8SChris Lattner //===-- TargetList.cpp ------------------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1030fdc8d8SChris Lattner // C Includes 1130fdc8d8SChris Lattner // C++ Includes 1230fdc8d8SChris Lattner // Other libraries and framework includes 1330fdc8d8SChris Lattner // Project includes 1430fdc8d8SChris Lattner #include "lldb/Core/Broadcaster.h" 15ded470d3SGreg Clayton #include "lldb/Core/Debugger.h" 1630fdc8d8SChris Lattner #include "lldb/Core/Event.h" 171f746071SGreg Clayton #include "lldb/Core/Module.h" 18f4d6de6aSGreg Clayton #include "lldb/Core/ModuleSpec.h" 1930fdc8d8SChris Lattner #include "lldb/Core/State.h" 2030fdc8d8SChris Lattner #include "lldb/Core/Timer.h" 2130fdc8d8SChris Lattner #include "lldb/Host/Host.h" 22893c932aSJim Ingham #include "lldb/Host/HostInfo.h" 23b3a40ba8SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 24cac9c5f9SGreg Clayton #include "lldb/Interpreter/OptionGroupPlatform.h" 25f4d6de6aSGreg Clayton #include "lldb/Symbol/ObjectFile.h" 26e996fd30SGreg Clayton #include "lldb/Target/Platform.h" 2730fdc8d8SChris Lattner #include "lldb/Target/Process.h" 2830fdc8d8SChris Lattner #include "lldb/Target/TargetList.h" 2930fdc8d8SChris Lattner 303f559740SZachary Turner #include "llvm/ADT/SmallString.h" 313f559740SZachary Turner 3230fdc8d8SChris Lattner using namespace lldb; 3330fdc8d8SChris Lattner using namespace lldb_private; 3430fdc8d8SChris Lattner 354bddaeb5SJim Ingham ConstString & 364bddaeb5SJim Ingham TargetList::GetStaticBroadcasterClass () 374bddaeb5SJim Ingham { 384bddaeb5SJim Ingham static ConstString class_name ("lldb.targetList"); 394bddaeb5SJim Ingham return class_name; 404bddaeb5SJim Ingham } 4130fdc8d8SChris Lattner 4230fdc8d8SChris Lattner //---------------------------------------------------------------------- 4330fdc8d8SChris Lattner // TargetList constructor 4430fdc8d8SChris Lattner //---------------------------------------------------------------------- 454bddaeb5SJim Ingham TargetList::TargetList(Debugger &debugger) : 464f465cffSJim Ingham Broadcaster(&debugger, TargetList::GetStaticBroadcasterClass().AsCString()), 4730fdc8d8SChris Lattner m_target_list(), 4830fdc8d8SChris Lattner m_target_list_mutex (Mutex::eMutexTypeRecursive), 492976d00aSJim Ingham m_selected_target_idx (0) 5030fdc8d8SChris Lattner { 514bddaeb5SJim Ingham CheckInWithManager(); 5230fdc8d8SChris Lattner } 5330fdc8d8SChris Lattner 5430fdc8d8SChris Lattner //---------------------------------------------------------------------- 5530fdc8d8SChris Lattner // Destructor 5630fdc8d8SChris Lattner //---------------------------------------------------------------------- 5730fdc8d8SChris Lattner TargetList::~TargetList() 5830fdc8d8SChris Lattner { 5930fdc8d8SChris Lattner Mutex::Locker locker(m_target_list_mutex); 6030fdc8d8SChris Lattner m_target_list.clear(); 6130fdc8d8SChris Lattner } 6230fdc8d8SChris Lattner 6330fdc8d8SChris Lattner Error 64cac9c5f9SGreg Clayton TargetList::CreateTarget (Debugger &debugger, 65a0ca6601SGreg Clayton const char *user_exe_path, 66cac9c5f9SGreg Clayton const char *triple_cstr, 67cac9c5f9SGreg Clayton bool get_dependent_files, 68cac9c5f9SGreg Clayton const OptionGroupPlatform *platform_options, 69cac9c5f9SGreg Clayton TargetSP &target_sp) 70cac9c5f9SGreg Clayton { 71893c932aSJim Ingham return CreateTargetInternal (debugger, 72893c932aSJim Ingham user_exe_path, 73893c932aSJim Ingham triple_cstr, 74893c932aSJim Ingham get_dependent_files, 75893c932aSJim Ingham platform_options, 76893c932aSJim Ingham target_sp, 77893c932aSJim Ingham false); 78893c932aSJim Ingham } 79893c932aSJim Ingham 80893c932aSJim Ingham Error 81893c932aSJim Ingham TargetList::CreateTarget (Debugger &debugger, 82893c932aSJim Ingham const char *user_exe_path, 83893c932aSJim Ingham const ArchSpec& specified_arch, 84893c932aSJim Ingham bool get_dependent_files, 85893c932aSJim Ingham PlatformSP &platform_sp, 86893c932aSJim Ingham TargetSP &target_sp) 87893c932aSJim Ingham { 88893c932aSJim Ingham return CreateTargetInternal (debugger, 89893c932aSJim Ingham user_exe_path, 90893c932aSJim Ingham specified_arch, 91893c932aSJim Ingham get_dependent_files, 92893c932aSJim Ingham platform_sp, 93893c932aSJim Ingham target_sp, 94893c932aSJim Ingham false); 95893c932aSJim Ingham } 96893c932aSJim Ingham 97893c932aSJim Ingham Error 98893c932aSJim Ingham TargetList::CreateTargetInternal (Debugger &debugger, 99893c932aSJim Ingham const char *user_exe_path, 100893c932aSJim Ingham const char *triple_cstr, 101893c932aSJim Ingham bool get_dependent_files, 102893c932aSJim Ingham const OptionGroupPlatform *platform_options, 103893c932aSJim Ingham TargetSP &target_sp, 104893c932aSJim Ingham bool is_dummy_target) 105893c932aSJim Ingham { 106cac9c5f9SGreg Clayton Error error; 107cac9c5f9SGreg Clayton PlatformSP platform_sp; 108cac9c5f9SGreg Clayton 109cdc21d4cSJohnny Chen // This is purposely left empty unless it is specified by triple_cstr. 110cdc21d4cSJohnny Chen // If not initialized via triple_cstr, then the currently selected platform 111cdc21d4cSJohnny Chen // will set the architecture correctly. 11270512317SGreg Clayton const ArchSpec arch(triple_cstr); 11370512317SGreg Clayton if (triple_cstr && triple_cstr[0]) 114cac9c5f9SGreg Clayton { 115cac9c5f9SGreg Clayton if (!arch.IsValid()) 116cac9c5f9SGreg Clayton { 11786edbf41SGreg Clayton error.SetErrorStringWithFormat("invalid triple '%s'", triple_cstr); 118cac9c5f9SGreg Clayton return error; 119cac9c5f9SGreg Clayton } 120cac9c5f9SGreg Clayton } 121b3a40ba8SGreg Clayton 12270512317SGreg Clayton ArchSpec platform_arch(arch); 123f4d6de6aSGreg Clayton 1243f19ada8SGreg Clayton bool prefer_platform_arch = false; 125f4d6de6aSGreg Clayton 126b0cc53cfSGreg Clayton CommandInterpreter &interpreter = debugger.GetCommandInterpreter(); 1271b5a74eeSVince Harron 1281b5a74eeSVince Harron // let's see if there is already an existing plaform before we go creating another... 1291b5a74eeSVince Harron platform_sp = debugger.GetPlatformList().GetSelectedPlatform(); 1301b5a74eeSVince Harron 131ccd2a6d9SGreg Clayton if (platform_options && platform_options->PlatformWasSpecified ()) 132ccd2a6d9SGreg Clayton { 133ccd2a6d9SGreg Clayton // Create a new platform if it doesn't match the selected platform 134ccd2a6d9SGreg Clayton if (!platform_options->PlatformMatches(platform_sp)) 135b0cc53cfSGreg Clayton { 136b0cc53cfSGreg Clayton const bool select_platform = true; 137b0cc53cfSGreg Clayton platform_sp = platform_options->CreatePlatformWithOptions (interpreter, 138b0cc53cfSGreg Clayton arch, 139b0cc53cfSGreg Clayton select_platform, 140b0cc53cfSGreg Clayton error, 141b0cc53cfSGreg Clayton platform_arch); 142b0cc53cfSGreg Clayton if (!platform_sp) 143b0cc53cfSGreg Clayton return error; 144b0cc53cfSGreg Clayton } 145ccd2a6d9SGreg Clayton } 146b0cc53cfSGreg Clayton 147f4d6de6aSGreg Clayton if (user_exe_path && user_exe_path[0]) 148f4d6de6aSGreg Clayton { 149f4d6de6aSGreg Clayton ModuleSpecList module_specs; 150f4d6de6aSGreg Clayton ModuleSpec module_spec; 151f4d6de6aSGreg Clayton module_spec.GetFileSpec().SetFile(user_exe_path, true); 152c76fa8a3SGreg Clayton 153c76fa8a3SGreg Clayton // Resolve the executable in case we are given a path to a application bundle 154c76fa8a3SGreg Clayton // like a .app bundle on MacOSX 155c76fa8a3SGreg Clayton Host::ResolveExecutableInBundle (module_spec.GetFileSpec()); 156c76fa8a3SGreg Clayton 157f4d6de6aSGreg Clayton lldb::offset_t file_offset = 0; 1582540a8a7SGreg Clayton lldb::offset_t file_size = 0; 1592540a8a7SGreg Clayton const size_t num_specs = ObjectFile::GetModuleSpecifications (module_spec.GetFileSpec(), file_offset, file_size, module_specs); 160f4d6de6aSGreg Clayton if (num_specs > 0) 161f4d6de6aSGreg Clayton { 162f4d6de6aSGreg Clayton ModuleSpec matching_module_spec; 163f4d6de6aSGreg Clayton 164f4d6de6aSGreg Clayton if (num_specs == 1) 165f4d6de6aSGreg Clayton { 166f4d6de6aSGreg Clayton if (module_specs.GetModuleSpecAtIndex(0, matching_module_spec)) 167f4d6de6aSGreg Clayton { 168f4d6de6aSGreg Clayton if (platform_arch.IsValid()) 169f4d6de6aSGreg Clayton { 1703f19ada8SGreg Clayton if (platform_arch.IsCompatibleMatch(matching_module_spec.GetArchitecture())) 1713f19ada8SGreg Clayton { 1723f19ada8SGreg Clayton // If the OS or vendor weren't specified, then adopt the module's 1733f19ada8SGreg Clayton // architecture so that the platform matching can be more accurate 1743f19ada8SGreg Clayton if (!platform_arch.TripleOSWasSpecified() || !platform_arch.TripleVendorWasSpecified()) 1753f19ada8SGreg Clayton { 1763f19ada8SGreg Clayton prefer_platform_arch = true; 1773f19ada8SGreg Clayton platform_arch = matching_module_spec.GetArchitecture(); 1783f19ada8SGreg Clayton } 1793f19ada8SGreg Clayton } 1803f19ada8SGreg Clayton else 181f4d6de6aSGreg Clayton { 1827df337f8STodd Fiala StreamString platform_arch_strm; 1837df337f8STodd Fiala StreamString module_arch_strm; 1847df337f8STodd Fiala 1857df337f8STodd Fiala platform_arch.DumpTriple(platform_arch_strm); 1867df337f8STodd Fiala matching_module_spec.GetArchitecture().DumpTriple(module_arch_strm); 187b5ad4ec7SGreg Clayton error.SetErrorStringWithFormat("the specified architecture '%s' is not compatible with '%s' in '%s'", 1887df337f8STodd Fiala platform_arch_strm.GetString().c_str(), 1897df337f8STodd Fiala module_arch_strm.GetString().c_str(), 190b5ad4ec7SGreg Clayton module_spec.GetFileSpec().GetPath().c_str()); 191f4d6de6aSGreg Clayton return error; 192f4d6de6aSGreg Clayton } 193f4d6de6aSGreg Clayton } 194f4d6de6aSGreg Clayton else 195f4d6de6aSGreg Clayton { 196f4d6de6aSGreg Clayton // Only one arch and none was specified 1973f19ada8SGreg Clayton prefer_platform_arch = true; 198f4d6de6aSGreg Clayton platform_arch = matching_module_spec.GetArchitecture(); 199f4d6de6aSGreg Clayton } 200f4d6de6aSGreg Clayton } 201f4d6de6aSGreg Clayton } 202f4d6de6aSGreg Clayton else 203f4d6de6aSGreg Clayton { 204f4d6de6aSGreg Clayton if (arch.IsValid()) 205f4d6de6aSGreg Clayton { 206f4d6de6aSGreg Clayton module_spec.GetArchitecture() = arch; 207f4d6de6aSGreg Clayton if (module_specs.FindMatchingModuleSpec(module_spec, matching_module_spec)) 208f4d6de6aSGreg Clayton { 2093f19ada8SGreg Clayton prefer_platform_arch = true; 210f4d6de6aSGreg Clayton platform_arch = matching_module_spec.GetArchitecture(); 211f4d6de6aSGreg Clayton } 212f4d6de6aSGreg Clayton } 213b0cc53cfSGreg Clayton else 214b0cc53cfSGreg Clayton { 215b0cc53cfSGreg Clayton // No architecture specified, check if there is only one platform for 216b0cc53cfSGreg Clayton // all of the architectures. 217b0cc53cfSGreg Clayton 218b0cc53cfSGreg Clayton typedef std::vector<PlatformSP> PlatformList; 219b0cc53cfSGreg Clayton PlatformList platforms; 220615eb7e6SGreg Clayton PlatformSP host_platform_sp = Platform::GetHostPlatform(); 221b0cc53cfSGreg Clayton for (size_t i=0; i<num_specs; ++i) 222b0cc53cfSGreg Clayton { 223b0cc53cfSGreg Clayton ModuleSpec module_spec; 224b0cc53cfSGreg Clayton if (module_specs.GetModuleSpecAtIndex(i, module_spec)) 225b0cc53cfSGreg Clayton { 226b0cc53cfSGreg Clayton // See if there was a selected platform and check that first 227b0cc53cfSGreg Clayton // since the user may have specified it. 228b0cc53cfSGreg Clayton if (platform_sp) 229b0cc53cfSGreg Clayton { 230b0cc53cfSGreg Clayton if (platform_sp->IsCompatibleArchitecture(module_spec.GetArchitecture(), false, NULL)) 231b0cc53cfSGreg Clayton { 232b0cc53cfSGreg Clayton platforms.push_back(platform_sp); 233b0cc53cfSGreg Clayton continue; 234f4d6de6aSGreg Clayton } 235f4d6de6aSGreg Clayton } 236f4d6de6aSGreg Clayton 237b0cc53cfSGreg Clayton // Next check the host platform it if wasn't already checked above 238b0cc53cfSGreg Clayton if (host_platform_sp && (!platform_sp || host_platform_sp->GetName() != platform_sp->GetName())) 239b3a40ba8SGreg Clayton { 240b0cc53cfSGreg Clayton if (host_platform_sp->IsCompatibleArchitecture(module_spec.GetArchitecture(), false, NULL)) 241b3a40ba8SGreg Clayton { 242b0cc53cfSGreg Clayton platforms.push_back(host_platform_sp); 243b0cc53cfSGreg Clayton continue; 244b0cc53cfSGreg Clayton } 245b0cc53cfSGreg Clayton } 246b0cc53cfSGreg Clayton 247b0cc53cfSGreg Clayton // Just find a platform that matches the architecture in the executable file 248*e92a74ceSJason Molenda PlatformSP fallback_platform_sp (Platform::GetPlatformForArchitecture(module_spec.GetArchitecture(), nullptr)); 249*e92a74ceSJason Molenda if (fallback_platform_sp) 250*e92a74ceSJason Molenda { 251*e92a74ceSJason Molenda platforms.push_back(fallback_platform_sp); 252*e92a74ceSJason Molenda } 253b0cc53cfSGreg Clayton } 254b0cc53cfSGreg Clayton } 255b0cc53cfSGreg Clayton 256b0cc53cfSGreg Clayton Platform *platform_ptr = NULL; 2579d58c728SJason Molenda bool more_than_one_platforms = false; 258b0cc53cfSGreg Clayton for (const auto &the_platform_sp : platforms) 259b0cc53cfSGreg Clayton { 260b0cc53cfSGreg Clayton if (platform_ptr) 261b0cc53cfSGreg Clayton { 262b0cc53cfSGreg Clayton if (platform_ptr->GetName() != the_platform_sp->GetName()) 263b0cc53cfSGreg Clayton { 2649d58c728SJason Molenda more_than_one_platforms = true; 265b0cc53cfSGreg Clayton platform_ptr = NULL; 266b0cc53cfSGreg Clayton break; 267b0cc53cfSGreg Clayton } 268b0cc53cfSGreg Clayton } 269b0cc53cfSGreg Clayton else 270b0cc53cfSGreg Clayton { 271b0cc53cfSGreg Clayton platform_ptr = the_platform_sp.get(); 272b0cc53cfSGreg Clayton } 273b0cc53cfSGreg Clayton } 274b0cc53cfSGreg Clayton 275b0cc53cfSGreg Clayton if (platform_ptr) 276b0cc53cfSGreg Clayton { 277b0cc53cfSGreg Clayton // All platforms for all modules in the exectuable match, so we can select this platform 278b0cc53cfSGreg Clayton platform_sp = platforms.front(); 279b0cc53cfSGreg Clayton } 2809d58c728SJason Molenda else if (more_than_one_platforms == false) 2819d58c728SJason Molenda { 2829d58c728SJason Molenda // No platforms claim to support this file 2839d58c728SJason Molenda error.SetErrorString ("No matching platforms found for this file, specify one with the --platform option"); 2849d58c728SJason Molenda return error; 2859d58c728SJason Molenda } 286b0cc53cfSGreg Clayton else 287b0cc53cfSGreg Clayton { 288b0cc53cfSGreg Clayton // More than one platform claims to support this file, so the --platform option must be specified 289b0cc53cfSGreg Clayton StreamString error_strm; 290b0cc53cfSGreg Clayton std::set<Platform *> platform_set; 291b0cc53cfSGreg Clayton error_strm.Printf ("more than one platform supports this executable ("); 292b0cc53cfSGreg Clayton for (const auto &the_platform_sp : platforms) 293b0cc53cfSGreg Clayton { 294b0cc53cfSGreg Clayton if (platform_set.find(the_platform_sp.get()) == platform_set.end()) 295b0cc53cfSGreg Clayton { 296b0cc53cfSGreg Clayton if (!platform_set.empty()) 297b0cc53cfSGreg Clayton error_strm.PutCString(", "); 298b0cc53cfSGreg Clayton error_strm.PutCString(the_platform_sp->GetName().GetCString()); 299b0cc53cfSGreg Clayton platform_set.insert(the_platform_sp.get()); 300b0cc53cfSGreg Clayton } 301b0cc53cfSGreg Clayton } 302b0cc53cfSGreg Clayton error_strm.Printf("), use the --platform option to specify a platform"); 303b0cc53cfSGreg Clayton error.SetErrorString(error_strm.GetString().c_str()); 304b3a40ba8SGreg Clayton return error; 305b3a40ba8SGreg Clayton } 306b3a40ba8SGreg Clayton } 307b0cc53cfSGreg Clayton } 308b0cc53cfSGreg Clayton } 309b0cc53cfSGreg Clayton } 310b3a40ba8SGreg Clayton 311869e0c1cSTed Woodward // If we have a valid architecture, make sure the current platform is 312869e0c1cSTed Woodward // compatible with that architecture 3133f19ada8SGreg Clayton if (!prefer_platform_arch && arch.IsValid()) 314b3a40ba8SGreg Clayton { 3153f19ada8SGreg Clayton if (!platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch)) 31695bbdf64SGreg Clayton { 31770512317SGreg Clayton platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch); 3188ec55a53SRobert Flack if (!is_dummy_target && platform_sp) 31995bbdf64SGreg Clayton debugger.GetPlatformList().SetSelectedPlatform(platform_sp); 32095bbdf64SGreg Clayton } 321b3a40ba8SGreg Clayton } 3223f19ada8SGreg Clayton else if (platform_arch.IsValid()) 3233f19ada8SGreg Clayton { 3243f19ada8SGreg Clayton // if "arch" isn't valid, yet "platform_arch" is, it means we have an executable file with 3253f19ada8SGreg Clayton // a single architecture which should be used 3263f19ada8SGreg Clayton ArchSpec fixed_platform_arch; 3273f19ada8SGreg Clayton if (!platform_sp->IsCompatibleArchitecture(platform_arch, false, &fixed_platform_arch)) 32895bbdf64SGreg Clayton { 3293f19ada8SGreg Clayton platform_sp = Platform::GetPlatformForArchitecture(platform_arch, &fixed_platform_arch); 3308ec55a53SRobert Flack if (!is_dummy_target && platform_sp) 33195bbdf64SGreg Clayton debugger.GetPlatformList().SetSelectedPlatform(platform_sp); 33295bbdf64SGreg Clayton } 3333f19ada8SGreg Clayton } 334b3a40ba8SGreg Clayton 33570512317SGreg Clayton if (!platform_arch.IsValid()) 33670512317SGreg Clayton platform_arch = arch; 33770512317SGreg Clayton 338893c932aSJim Ingham error = TargetList::CreateTargetInternal (debugger, 339a0ca6601SGreg Clayton user_exe_path, 34070512317SGreg Clayton platform_arch, 341cac9c5f9SGreg Clayton get_dependent_files, 342cac9c5f9SGreg Clayton platform_sp, 343893c932aSJim Ingham target_sp, 344893c932aSJim Ingham is_dummy_target); 345cac9c5f9SGreg Clayton return error; 346cac9c5f9SGreg Clayton } 347cac9c5f9SGreg Clayton 348893c932aSJim Ingham lldb::TargetSP 349893c932aSJim Ingham TargetList::GetDummyTarget (lldb_private::Debugger &debugger) 350893c932aSJim Ingham { 351893c932aSJim Ingham // FIXME: Maybe the dummy target should be per-Debugger 352893c932aSJim Ingham if (!m_dummy_target_sp || !m_dummy_target_sp->IsValid()) 353893c932aSJim Ingham { 354893c932aSJim Ingham ArchSpec arch(Target::GetDefaultArchitecture()); 355893c932aSJim Ingham if (!arch.IsValid()) 356893c932aSJim Ingham arch = HostInfo::GetArchitecture(); 357893c932aSJim Ingham Error err = CreateDummyTarget(debugger, 358893c932aSJim Ingham arch.GetTriple().getTriple().c_str(), 359893c932aSJim Ingham m_dummy_target_sp); 360893c932aSJim Ingham } 361893c932aSJim Ingham 362893c932aSJim Ingham return m_dummy_target_sp; 363893c932aSJim Ingham } 364893c932aSJim Ingham 365cac9c5f9SGreg Clayton Error 366893c932aSJim Ingham TargetList::CreateDummyTarget (Debugger &debugger, 367893c932aSJim Ingham const char *specified_arch_name, 368893c932aSJim Ingham lldb::TargetSP &target_sp) 369893c932aSJim Ingham { 370893c932aSJim Ingham PlatformSP host_platform_sp(Platform::GetHostPlatform()); 371893c932aSJim Ingham return CreateTargetInternal (debugger, 372893c932aSJim Ingham (const char *) nullptr, 373893c932aSJim Ingham specified_arch_name, 374893c932aSJim Ingham false, 375893c932aSJim Ingham (const OptionGroupPlatform *) nullptr, 376893c932aSJim Ingham target_sp, 377893c932aSJim Ingham true); 378893c932aSJim Ingham } 379893c932aSJim Ingham 380893c932aSJim Ingham Error 381893c932aSJim Ingham TargetList::CreateTargetInternal (Debugger &debugger, 382a0ca6601SGreg Clayton const char *user_exe_path, 38370512317SGreg Clayton const ArchSpec& specified_arch, 38430fdc8d8SChris Lattner bool get_dependent_files, 385893c932aSJim Ingham lldb::PlatformSP &platform_sp, 386893c932aSJim Ingham lldb::TargetSP &target_sp, 387893c932aSJim Ingham bool is_dummy_target) 38830fdc8d8SChris Lattner { 389893c932aSJim Ingham 39030fdc8d8SChris Lattner Timer scoped_timer (__PRETTY_FUNCTION__, 391a0ca6601SGreg Clayton "TargetList::CreateTarget (file = '%s', arch = '%s')", 392a0ca6601SGreg Clayton user_exe_path, 39370512317SGreg Clayton specified_arch.GetArchitectureName()); 3945aee162fSJim Ingham Error error; 3955aee162fSJim Ingham 39670512317SGreg Clayton ArchSpec arch(specified_arch); 39770512317SGreg Clayton 39870512317SGreg Clayton if (arch.IsValid()) 39970512317SGreg Clayton { 400b0cc53cfSGreg Clayton if (!platform_sp || !platform_sp->IsCompatibleArchitecture(arch, false, NULL)) 40170512317SGreg Clayton platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch); 40270512317SGreg Clayton } 40370512317SGreg Clayton 40470512317SGreg Clayton if (!platform_sp) 40570512317SGreg Clayton platform_sp = debugger.GetPlatformList().GetSelectedPlatform(); 406ded470d3SGreg Clayton 4078ae50eb4SGreg Clayton if (!arch.IsValid()) 4088ae50eb4SGreg Clayton arch = specified_arch; 4098ae50eb4SGreg Clayton 410d26206b5SJason Molenda FileSpec file (user_exe_path, false); 411d26206b5SJason Molenda if (!file.Exists() && user_exe_path && user_exe_path[0] == '~') 412d26206b5SJason Molenda { 4139f822cd1SMichael Sartain // we want to expand the tilde but we don't want to resolve any symbolic links 4149f822cd1SMichael Sartain // so we can't use the FileSpec constructor's resolve flag 4153f559740SZachary Turner llvm::SmallString<64> unglobbed_path(user_exe_path); 4163f559740SZachary Turner FileSpec::ResolveUsername(unglobbed_path); 4179f822cd1SMichael Sartain 4183f559740SZachary Turner if (unglobbed_path.empty()) 4193f559740SZachary Turner file = FileSpec(user_exe_path, false); 4203f559740SZachary Turner else 4213f559740SZachary Turner file = FileSpec(unglobbed_path.c_str(), false); 422d26206b5SJason Molenda } 4239f822cd1SMichael Sartain 42482d79295SGreg Clayton bool user_exe_path_is_bundle = false; 42582d79295SGreg Clayton char resolved_bundle_exe_path[PATH_MAX]; 42682d79295SGreg Clayton resolved_bundle_exe_path[0] = '\0'; 427e996fd30SGreg Clayton if (file) 4285aee162fSJim Ingham { 42982d79295SGreg Clayton if (file.GetFileType() == FileSpec::eFileTypeDirectory) 43082d79295SGreg Clayton user_exe_path_is_bundle = true; 43182d79295SGreg Clayton 432372e9067SChaoren Lin if (file.IsRelative() && user_exe_path) 433a0ca6601SGreg Clayton { 434a0ca6601SGreg Clayton // Ignore paths that start with "./" and "../" 435a0ca6601SGreg Clayton if (!((user_exe_path[0] == '.' && user_exe_path[1] == '/') || 436a0ca6601SGreg Clayton (user_exe_path[0] == '.' && user_exe_path[1] == '.' && user_exe_path[2] == '/'))) 437a0ca6601SGreg Clayton { 438a0ca6601SGreg Clayton char cwd[PATH_MAX]; 439a0ca6601SGreg Clayton if (getcwd (cwd, sizeof(cwd))) 440a0ca6601SGreg Clayton { 441a0ca6601SGreg Clayton std::string cwd_user_exe_path (cwd); 442a0ca6601SGreg Clayton cwd_user_exe_path += '/'; 443a0ca6601SGreg Clayton cwd_user_exe_path += user_exe_path; 4449ff5aae5SGreg Clayton FileSpec cwd_file (cwd_user_exe_path.c_str(), false); 4459ff5aae5SGreg Clayton if (cwd_file.Exists()) 4469ff5aae5SGreg Clayton file = cwd_file; 447a0ca6601SGreg Clayton } 448a0ca6601SGreg Clayton } 449a0ca6601SGreg Clayton } 450a0ca6601SGreg Clayton 45130fdc8d8SChris Lattner ModuleSP exe_module_sp; 452e996fd30SGreg Clayton if (platform_sp) 453c859e2d5SGreg Clayton { 454c859e2d5SGreg Clayton FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths()); 4558012cadbSGreg Clayton ModuleSpec module_spec(file, arch); 4568012cadbSGreg Clayton error = platform_sp->ResolveExecutable (module_spec, 457c859e2d5SGreg Clayton exe_module_sp, 458c859e2d5SGreg Clayton executable_search_paths.GetSize() ? &executable_search_paths : NULL); 459c859e2d5SGreg Clayton } 460428a9a58SCaroline Tice 461e996fd30SGreg Clayton if (error.Success() && exe_module_sp) 46230fdc8d8SChris Lattner { 4635aee162fSJim Ingham if (exe_module_sp->GetObjectFile() == NULL) 4645aee162fSJim Ingham { 465bc5cad6cSGreg Clayton if (arch.IsValid()) 466bc5cad6cSGreg Clayton { 467b5ad4ec7SGreg Clayton error.SetErrorStringWithFormat("\"%s\" doesn't contain architecture %s", 468b5ad4ec7SGreg Clayton file.GetPath().c_str(), 46964195a2cSGreg Clayton arch.GetArchitectureName()); 470bc5cad6cSGreg Clayton } 471bc5cad6cSGreg Clayton else 472bc5cad6cSGreg Clayton { 473b5ad4ec7SGreg Clayton error.SetErrorStringWithFormat("unsupported file type \"%s\"", 474b5ad4ec7SGreg Clayton file.GetPath().c_str()); 475bc5cad6cSGreg Clayton } 4765aee162fSJim Ingham return error; 4775aee162fSJim Ingham } 478893c932aSJim Ingham target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target)); 47930fdc8d8SChris Lattner target_sp->SetExecutableModule (exe_module_sp, get_dependent_files); 48082d79295SGreg Clayton if (user_exe_path_is_bundle) 48182d79295SGreg Clayton exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path, sizeof(resolved_bundle_exe_path)); 4825aee162fSJim Ingham } 4835aee162fSJim Ingham } 484e996fd30SGreg Clayton else 485e996fd30SGreg Clayton { 486e996fd30SGreg Clayton // No file was specified, just create an empty target with any arch 487e996fd30SGreg Clayton // if a valid arch was specified 488893c932aSJim Ingham target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target)); 489e996fd30SGreg Clayton } 4901559a46bSCaroline Tice 491e996fd30SGreg Clayton if (target_sp) 492e996fd30SGreg Clayton { 49382d79295SGreg Clayton // Set argv0 with what the user typed, unless the user specified a 49482d79295SGreg Clayton // directory. If the user specified a directory, then it is probably a 49582d79295SGreg Clayton // bundle that was resolved and we need to use the resolved bundle path 496a0ca6601SGreg Clayton if (user_exe_path) 497a0ca6601SGreg Clayton { 498a0ca6601SGreg Clayton // Use exactly what the user typed as the first argument when we exec or posix_spawn 49982d79295SGreg Clayton if (user_exe_path_is_bundle && resolved_bundle_exe_path[0]) 50082d79295SGreg Clayton { 50182d79295SGreg Clayton target_sp->SetArg0 (resolved_bundle_exe_path); 50282d79295SGreg Clayton } 50382d79295SGreg Clayton else 50482d79295SGreg Clayton { 5059f822cd1SMichael Sartain // Use resolved path 5069f822cd1SMichael Sartain target_sp->SetArg0 (file.GetPath().c_str()); 507a0ca6601SGreg Clayton } 50882d79295SGreg Clayton } 509a0ca6601SGreg Clayton if (file.GetDirectory()) 510a0ca6601SGreg Clayton { 511a0ca6601SGreg Clayton FileSpec file_dir; 512a0ca6601SGreg Clayton file_dir.GetDirectory() = file.GetDirectory(); 513a0ca6601SGreg Clayton target_sp->GetExecutableSearchPaths ().Append (file_dir); 514a0ca6601SGreg Clayton } 515893c932aSJim Ingham 516893c932aSJim Ingham // Don't put the dummy target in the target list, it's held separately. 517893c932aSJim Ingham if (!is_dummy_target) 518893c932aSJim Ingham { 51930fdc8d8SChris Lattner Mutex::Locker locker(m_target_list_mutex); 5202976d00aSJim Ingham m_selected_target_idx = m_target_list.size(); 52130fdc8d8SChris Lattner m_target_list.push_back(target_sp); 52233df7cd3SJim Ingham // Now prime this from the dummy target: 52333df7cd3SJim Ingham target_sp->PrimeFromDummyTarget(debugger.GetDummyTarget()); 524893c932aSJim Ingham } 525893c932aSJim Ingham else 526893c932aSJim Ingham { 527893c932aSJim Ingham m_dummy_target_sp = target_sp; 528893c932aSJim Ingham } 52930fdc8d8SChris Lattner } 53030fdc8d8SChris Lattner 53130fdc8d8SChris Lattner return error; 53230fdc8d8SChris Lattner } 53330fdc8d8SChris Lattner 53430fdc8d8SChris Lattner bool 53530fdc8d8SChris Lattner TargetList::DeleteTarget (TargetSP &target_sp) 53630fdc8d8SChris Lattner { 53730fdc8d8SChris Lattner Mutex::Locker locker(m_target_list_mutex); 53830fdc8d8SChris Lattner collection::iterator pos, end = m_target_list.end(); 53930fdc8d8SChris Lattner 54030fdc8d8SChris Lattner for (pos = m_target_list.begin(); pos != end; ++pos) 54130fdc8d8SChris Lattner { 54230fdc8d8SChris Lattner if (pos->get() == target_sp.get()) 54330fdc8d8SChris Lattner { 54430fdc8d8SChris Lattner m_target_list.erase(pos); 54530fdc8d8SChris Lattner return true; 54630fdc8d8SChris Lattner } 54730fdc8d8SChris Lattner } 54830fdc8d8SChris Lattner return false; 54930fdc8d8SChris Lattner } 55030fdc8d8SChris Lattner 55130fdc8d8SChris Lattner 55230fdc8d8SChris Lattner TargetSP 55330fdc8d8SChris Lattner TargetList::FindTargetWithExecutableAndArchitecture 55430fdc8d8SChris Lattner ( 55530fdc8d8SChris Lattner const FileSpec &exe_file_spec, 55630fdc8d8SChris Lattner const ArchSpec *exe_arch_ptr 55730fdc8d8SChris Lattner ) const 55830fdc8d8SChris Lattner { 55930fdc8d8SChris Lattner Mutex::Locker locker (m_target_list_mutex); 56030fdc8d8SChris Lattner TargetSP target_sp; 561ddd7a2a6SSean Callanan bool full_match = (bool)exe_file_spec.GetDirectory(); 56230fdc8d8SChris Lattner 56330fdc8d8SChris Lattner collection::const_iterator pos, end = m_target_list.end(); 56430fdc8d8SChris Lattner for (pos = m_target_list.begin(); pos != end; ++pos) 56530fdc8d8SChris Lattner { 566aa149cbdSGreg Clayton Module *exe_module = (*pos)->GetExecutableModulePointer(); 56730fdc8d8SChris Lattner 568aa149cbdSGreg Clayton if (exe_module) 56930fdc8d8SChris Lattner { 570aa149cbdSGreg Clayton if (FileSpec::Equal (exe_file_spec, exe_module->GetFileSpec(), full_match)) 57130fdc8d8SChris Lattner { 57230fdc8d8SChris Lattner if (exe_arch_ptr) 57330fdc8d8SChris Lattner { 574bf4b7be6SSean Callanan if (!exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture())) 57530fdc8d8SChris Lattner continue; 57630fdc8d8SChris Lattner } 57730fdc8d8SChris Lattner target_sp = *pos; 57830fdc8d8SChris Lattner break; 57930fdc8d8SChris Lattner } 58030fdc8d8SChris Lattner } 58130fdc8d8SChris Lattner } 58230fdc8d8SChris Lattner return target_sp; 58330fdc8d8SChris Lattner } 58430fdc8d8SChris Lattner 58530fdc8d8SChris Lattner TargetSP 58630fdc8d8SChris Lattner TargetList::FindTargetWithProcessID (lldb::pid_t pid) const 58730fdc8d8SChris Lattner { 58830fdc8d8SChris Lattner Mutex::Locker locker(m_target_list_mutex); 58930fdc8d8SChris Lattner TargetSP target_sp; 59030fdc8d8SChris Lattner collection::const_iterator pos, end = m_target_list.end(); 59130fdc8d8SChris Lattner for (pos = m_target_list.begin(); pos != end; ++pos) 59230fdc8d8SChris Lattner { 59330fdc8d8SChris Lattner Process* process = (*pos)->GetProcessSP().get(); 59430fdc8d8SChris Lattner if (process && process->GetID() == pid) 59530fdc8d8SChris Lattner { 59630fdc8d8SChris Lattner target_sp = *pos; 59730fdc8d8SChris Lattner break; 59830fdc8d8SChris Lattner } 59930fdc8d8SChris Lattner } 60030fdc8d8SChris Lattner return target_sp; 60130fdc8d8SChris Lattner } 60230fdc8d8SChris Lattner 60330fdc8d8SChris Lattner 60430fdc8d8SChris Lattner TargetSP 60530fdc8d8SChris Lattner TargetList::FindTargetWithProcess (Process *process) const 60630fdc8d8SChris Lattner { 60730fdc8d8SChris Lattner TargetSP target_sp; 60830fdc8d8SChris Lattner if (process) 60930fdc8d8SChris Lattner { 61030fdc8d8SChris Lattner Mutex::Locker locker(m_target_list_mutex); 61130fdc8d8SChris Lattner collection::const_iterator pos, end = m_target_list.end(); 61230fdc8d8SChris Lattner for (pos = m_target_list.begin(); pos != end; ++pos) 61330fdc8d8SChris Lattner { 61430fdc8d8SChris Lattner if (process == (*pos)->GetProcessSP().get()) 61530fdc8d8SChris Lattner { 61630fdc8d8SChris Lattner target_sp = *pos; 61730fdc8d8SChris Lattner break; 61830fdc8d8SChris Lattner } 61930fdc8d8SChris Lattner } 62030fdc8d8SChris Lattner } 62130fdc8d8SChris Lattner return target_sp; 62230fdc8d8SChris Lattner } 62330fdc8d8SChris Lattner 62430fdc8d8SChris Lattner TargetSP 62530fdc8d8SChris Lattner TargetList::GetTargetSP (Target *target) const 62630fdc8d8SChris Lattner { 62730fdc8d8SChris Lattner TargetSP target_sp; 62830fdc8d8SChris Lattner if (target) 62930fdc8d8SChris Lattner { 63030fdc8d8SChris Lattner Mutex::Locker locker(m_target_list_mutex); 63130fdc8d8SChris Lattner collection::const_iterator pos, end = m_target_list.end(); 63230fdc8d8SChris Lattner for (pos = m_target_list.begin(); pos != end; ++pos) 63330fdc8d8SChris Lattner { 63430fdc8d8SChris Lattner if (target == (*pos).get()) 63530fdc8d8SChris Lattner { 63630fdc8d8SChris Lattner target_sp = *pos; 63730fdc8d8SChris Lattner break; 63830fdc8d8SChris Lattner } 63930fdc8d8SChris Lattner } 64030fdc8d8SChris Lattner } 64130fdc8d8SChris Lattner return target_sp; 64230fdc8d8SChris Lattner } 64330fdc8d8SChris Lattner 64430fdc8d8SChris Lattner uint32_t 64530fdc8d8SChris Lattner TargetList::SendAsyncInterrupt (lldb::pid_t pid) 64630fdc8d8SChris Lattner { 64730fdc8d8SChris Lattner uint32_t num_async_interrupts_sent = 0; 64830fdc8d8SChris Lattner 64930fdc8d8SChris Lattner if (pid != LLDB_INVALID_PROCESS_ID) 65030fdc8d8SChris Lattner { 65130fdc8d8SChris Lattner TargetSP target_sp(FindTargetWithProcessID (pid)); 65230fdc8d8SChris Lattner if (target_sp.get()) 65330fdc8d8SChris Lattner { 65430fdc8d8SChris Lattner Process* process = target_sp->GetProcessSP().get(); 65530fdc8d8SChris Lattner if (process) 65630fdc8d8SChris Lattner { 657cfc0935eSJim Ingham process->SendAsyncInterrupt(); 65830fdc8d8SChris Lattner ++num_async_interrupts_sent; 65930fdc8d8SChris Lattner } 66030fdc8d8SChris Lattner } 66130fdc8d8SChris Lattner } 66230fdc8d8SChris Lattner else 66330fdc8d8SChris Lattner { 66430fdc8d8SChris Lattner // We don't have a valid pid to broadcast to, so broadcast to the target 66530fdc8d8SChris Lattner // list's async broadcaster... 66630fdc8d8SChris Lattner BroadcastEvent (Process::eBroadcastBitInterrupt, NULL); 66730fdc8d8SChris Lattner } 66830fdc8d8SChris Lattner 66930fdc8d8SChris Lattner return num_async_interrupts_sent; 67030fdc8d8SChris Lattner } 67130fdc8d8SChris Lattner 67230fdc8d8SChris Lattner uint32_t 67330fdc8d8SChris Lattner TargetList::SignalIfRunning (lldb::pid_t pid, int signo) 67430fdc8d8SChris Lattner { 67530fdc8d8SChris Lattner uint32_t num_signals_sent = 0; 67630fdc8d8SChris Lattner Process *process = NULL; 67730fdc8d8SChris Lattner if (pid == LLDB_INVALID_PROCESS_ID) 67830fdc8d8SChris Lattner { 67930fdc8d8SChris Lattner // Signal all processes with signal 68030fdc8d8SChris Lattner Mutex::Locker locker(m_target_list_mutex); 68130fdc8d8SChris Lattner collection::iterator pos, end = m_target_list.end(); 68230fdc8d8SChris Lattner for (pos = m_target_list.begin(); pos != end; ++pos) 68330fdc8d8SChris Lattner { 68430fdc8d8SChris Lattner process = (*pos)->GetProcessSP().get(); 68530fdc8d8SChris Lattner if (process) 68630fdc8d8SChris Lattner { 68730fdc8d8SChris Lattner if (process->IsAlive()) 68830fdc8d8SChris Lattner { 68930fdc8d8SChris Lattner ++num_signals_sent; 69030fdc8d8SChris Lattner process->Signal (signo); 69130fdc8d8SChris Lattner } 69230fdc8d8SChris Lattner } 69330fdc8d8SChris Lattner } 69430fdc8d8SChris Lattner } 69530fdc8d8SChris Lattner else 69630fdc8d8SChris Lattner { 69730fdc8d8SChris Lattner // Signal a specific process with signal 69830fdc8d8SChris Lattner TargetSP target_sp(FindTargetWithProcessID (pid)); 69930fdc8d8SChris Lattner if (target_sp.get()) 70030fdc8d8SChris Lattner { 70130fdc8d8SChris Lattner process = target_sp->GetProcessSP().get(); 70230fdc8d8SChris Lattner if (process) 70330fdc8d8SChris Lattner { 70430fdc8d8SChris Lattner if (process->IsAlive()) 70530fdc8d8SChris Lattner { 70630fdc8d8SChris Lattner ++num_signals_sent; 70730fdc8d8SChris Lattner process->Signal (signo); 70830fdc8d8SChris Lattner } 70930fdc8d8SChris Lattner } 71030fdc8d8SChris Lattner } 71130fdc8d8SChris Lattner } 71230fdc8d8SChris Lattner return num_signals_sent; 71330fdc8d8SChris Lattner } 71430fdc8d8SChris Lattner 71530fdc8d8SChris Lattner int 71630fdc8d8SChris Lattner TargetList::GetNumTargets () const 71730fdc8d8SChris Lattner { 71830fdc8d8SChris Lattner Mutex::Locker locker (m_target_list_mutex); 71930fdc8d8SChris Lattner return m_target_list.size(); 72030fdc8d8SChris Lattner } 72130fdc8d8SChris Lattner 72230fdc8d8SChris Lattner lldb::TargetSP 72330fdc8d8SChris Lattner TargetList::GetTargetAtIndex (uint32_t idx) const 72430fdc8d8SChris Lattner { 72530fdc8d8SChris Lattner TargetSP target_sp; 72630fdc8d8SChris Lattner Mutex::Locker locker (m_target_list_mutex); 72730fdc8d8SChris Lattner if (idx < m_target_list.size()) 72830fdc8d8SChris Lattner target_sp = m_target_list[idx]; 72930fdc8d8SChris Lattner return target_sp; 73030fdc8d8SChris Lattner } 73130fdc8d8SChris Lattner 73230fdc8d8SChris Lattner uint32_t 7338499e1a4SJim Ingham TargetList::GetIndexOfTarget (lldb::TargetSP target_sp) const 7348499e1a4SJim Ingham { 7358499e1a4SJim Ingham Mutex::Locker locker (m_target_list_mutex); 7368499e1a4SJim Ingham size_t num_targets = m_target_list.size(); 7378499e1a4SJim Ingham for (size_t idx = 0; idx < num_targets; idx++) 7388499e1a4SJim Ingham { 7398499e1a4SJim Ingham if (target_sp == m_target_list[idx]) 7408499e1a4SJim Ingham return idx; 7418499e1a4SJim Ingham } 7428499e1a4SJim Ingham return UINT32_MAX; 7438499e1a4SJim Ingham } 7448499e1a4SJim Ingham 7458499e1a4SJim Ingham uint32_t 7462976d00aSJim Ingham TargetList::SetSelectedTarget (Target* target) 74730fdc8d8SChris Lattner { 74830fdc8d8SChris Lattner Mutex::Locker locker (m_target_list_mutex); 74930fdc8d8SChris Lattner collection::const_iterator pos, 75030fdc8d8SChris Lattner begin = m_target_list.begin(), 75130fdc8d8SChris Lattner end = m_target_list.end(); 75230fdc8d8SChris Lattner for (pos = begin; pos != end; ++pos) 75330fdc8d8SChris Lattner { 75430fdc8d8SChris Lattner if (pos->get() == target) 75530fdc8d8SChris Lattner { 7562976d00aSJim Ingham m_selected_target_idx = std::distance (begin, pos); 7572976d00aSJim Ingham return m_selected_target_idx; 75830fdc8d8SChris Lattner } 75930fdc8d8SChris Lattner } 7602976d00aSJim Ingham m_selected_target_idx = 0; 7612976d00aSJim Ingham return m_selected_target_idx; 76230fdc8d8SChris Lattner } 76330fdc8d8SChris Lattner 76430fdc8d8SChris Lattner lldb::TargetSP 7652976d00aSJim Ingham TargetList::GetSelectedTarget () 76630fdc8d8SChris Lattner { 76730fdc8d8SChris Lattner Mutex::Locker locker (m_target_list_mutex); 7682976d00aSJim Ingham if (m_selected_target_idx >= m_target_list.size()) 7692976d00aSJim Ingham m_selected_target_idx = 0; 7702976d00aSJim Ingham return GetTargetAtIndex (m_selected_target_idx); 77130fdc8d8SChris Lattner } 772