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 // Project includes 11fb1a0a0dSZachary Turner #include "lldb/Target/TargetList.h" 1230fdc8d8SChris Lattner #include "lldb/Core/Broadcaster.h" 13ded470d3SGreg Clayton #include "lldb/Core/Debugger.h" 1430fdc8d8SChris Lattner #include "lldb/Core/Event.h" 151f746071SGreg Clayton #include "lldb/Core/Module.h" 16f4d6de6aSGreg Clayton #include "lldb/Core/ModuleSpec.h" 1730fdc8d8SChris Lattner #include "lldb/Core/State.h" 1830fdc8d8SChris Lattner #include "lldb/Host/Host.h" 19893c932aSJim Ingham #include "lldb/Host/HostInfo.h" 20b3a40ba8SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 21cac9c5f9SGreg Clayton #include "lldb/Interpreter/OptionGroupPlatform.h" 22f4d6de6aSGreg Clayton #include "lldb/Symbol/ObjectFile.h" 23e996fd30SGreg Clayton #include "lldb/Target/Platform.h" 2430fdc8d8SChris Lattner #include "lldb/Target/Process.h" 258d48cd60SZachary Turner #include "lldb/Utility/TildeExpressionResolver.h" 2638d0632eSPavel Labath #include "lldb/Utility/Timer.h" 2730fdc8d8SChris Lattner 281d5855b1SPavel Labath // Other libraries and framework includes 291d5855b1SPavel Labath #include "llvm/ADT/SmallString.h" 301d5855b1SPavel Labath #include "llvm/Support/FileSystem.h" 311d5855b1SPavel Labath 3230fdc8d8SChris Lattner using namespace lldb; 3330fdc8d8SChris Lattner using namespace lldb_private; 3430fdc8d8SChris Lattner 35b9c1b51eSKate Stone ConstString &TargetList::GetStaticBroadcasterClass() { 364bddaeb5SJim Ingham static ConstString class_name("lldb.targetList"); 374bddaeb5SJim Ingham return class_name; 384bddaeb5SJim Ingham } 3930fdc8d8SChris Lattner 4030fdc8d8SChris Lattner //---------------------------------------------------------------------- 4130fdc8d8SChris Lattner // TargetList constructor 4230fdc8d8SChris Lattner //---------------------------------------------------------------------- 4316ff8604SSaleem Abdulrasool TargetList::TargetList(Debugger &debugger) 44b9c1b51eSKate Stone : Broadcaster(debugger.GetBroadcasterManager(), 45b9c1b51eSKate Stone TargetList::GetStaticBroadcasterClass().AsCString()), 46b9c1b51eSKate Stone m_target_list(), m_target_list_mutex(), m_selected_target_idx(0) { 474bddaeb5SJim Ingham CheckInWithManager(); 4830fdc8d8SChris Lattner } 4930fdc8d8SChris Lattner 5030fdc8d8SChris Lattner //---------------------------------------------------------------------- 5130fdc8d8SChris Lattner // Destructor 5230fdc8d8SChris Lattner //---------------------------------------------------------------------- 53b9c1b51eSKate Stone TargetList::~TargetList() { 5416ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 5530fdc8d8SChris Lattner m_target_list.clear(); 5630fdc8d8SChris Lattner } 5730fdc8d8SChris Lattner 5897206d57SZachary Turner Status TargetList::CreateTarget(Debugger &debugger, 59a47464b2SZachary Turner llvm::StringRef user_exe_path, 60a47464b2SZachary Turner llvm::StringRef triple_str, 61cac9c5f9SGreg Clayton bool get_dependent_files, 62cac9c5f9SGreg Clayton const OptionGroupPlatform *platform_options, 63b9c1b51eSKate Stone TargetSP &target_sp) { 64a47464b2SZachary Turner return CreateTargetInternal(debugger, user_exe_path, triple_str, 65b9c1b51eSKate Stone get_dependent_files, platform_options, target_sp, 66893c932aSJim Ingham false); 67893c932aSJim Ingham } 68893c932aSJim Ingham 6997206d57SZachary Turner Status TargetList::CreateTarget(Debugger &debugger, 70a47464b2SZachary Turner llvm::StringRef user_exe_path, 71893c932aSJim Ingham const ArchSpec &specified_arch, 72893c932aSJim Ingham bool get_dependent_files, 73b9c1b51eSKate Stone PlatformSP &platform_sp, TargetSP &target_sp) { 74b9c1b51eSKate Stone return CreateTargetInternal(debugger, user_exe_path, specified_arch, 75b9c1b51eSKate Stone get_dependent_files, platform_sp, target_sp, 76893c932aSJim Ingham false); 77893c932aSJim Ingham } 78893c932aSJim Ingham 7997206d57SZachary Turner Status TargetList::CreateTargetInternal( 80a47464b2SZachary Turner Debugger &debugger, llvm::StringRef user_exe_path, 81a47464b2SZachary Turner llvm::StringRef triple_str, bool get_dependent_files, 82a47464b2SZachary Turner const OptionGroupPlatform *platform_options, TargetSP &target_sp, 83a47464b2SZachary Turner bool is_dummy_target) { 8497206d57SZachary Turner Status error; 85cac9c5f9SGreg Clayton PlatformSP platform_sp; 86cac9c5f9SGreg Clayton 8705097246SAdrian Prantl // This is purposely left empty unless it is specified by triple_cstr. If not 8805097246SAdrian Prantl // initialized via triple_cstr, then the currently selected platform will set 8905097246SAdrian Prantl // the architecture correctly. 90a47464b2SZachary Turner const ArchSpec arch(triple_str); 91a47464b2SZachary Turner if (!triple_str.empty()) { 92b9c1b51eSKate Stone if (!arch.IsValid()) { 93a47464b2SZachary Turner error.SetErrorStringWithFormat("invalid triple '%s'", 94a47464b2SZachary Turner triple_str.str().c_str()); 95cac9c5f9SGreg Clayton return error; 96cac9c5f9SGreg Clayton } 97cac9c5f9SGreg Clayton } 98b3a40ba8SGreg Clayton 9970512317SGreg Clayton ArchSpec platform_arch(arch); 100f4d6de6aSGreg Clayton 1013f19ada8SGreg Clayton bool prefer_platform_arch = false; 102f4d6de6aSGreg Clayton 103b0cc53cfSGreg Clayton CommandInterpreter &interpreter = debugger.GetCommandInterpreter(); 1041b5a74eeSVince Harron 1054ebdee0aSBruce Mitchener // let's see if there is already an existing platform before we go creating 106b9c1b51eSKate Stone // another... 1071b5a74eeSVince Harron platform_sp = debugger.GetPlatformList().GetSelectedPlatform(); 1081b5a74eeSVince Harron 109b9c1b51eSKate Stone if (platform_options && platform_options->PlatformWasSpecified()) { 110ccd2a6d9SGreg Clayton // Create a new platform if it doesn't match the selected platform 111b9c1b51eSKate Stone if (!platform_options->PlatformMatches(platform_sp)) { 112b0cc53cfSGreg Clayton const bool select_platform = true; 113b9c1b51eSKate Stone platform_sp = platform_options->CreatePlatformWithOptions( 114b9c1b51eSKate Stone interpreter, arch, select_platform, error, platform_arch); 115b0cc53cfSGreg Clayton if (!platform_sp) 116b0cc53cfSGreg Clayton return error; 117b0cc53cfSGreg Clayton } 118ccd2a6d9SGreg Clayton } 119b0cc53cfSGreg Clayton 120a47464b2SZachary Turner if (!user_exe_path.empty()) { 121f4d6de6aSGreg Clayton ModuleSpecList module_specs; 122f4d6de6aSGreg Clayton ModuleSpec module_spec; 123*937348cdSJonas Devlieghere module_spec.GetFileSpec().SetFile(user_exe_path, true, 124*937348cdSJonas Devlieghere FileSpec::Style::native); 125c76fa8a3SGreg Clayton 126b9c1b51eSKate Stone // Resolve the executable in case we are given a path to a application 12705097246SAdrian Prantl // bundle like a .app bundle on MacOSX 128c76fa8a3SGreg Clayton Host::ResolveExecutableInBundle(module_spec.GetFileSpec()); 129c76fa8a3SGreg Clayton 130f4d6de6aSGreg Clayton lldb::offset_t file_offset = 0; 1312540a8a7SGreg Clayton lldb::offset_t file_size = 0; 132b9c1b51eSKate Stone const size_t num_specs = ObjectFile::GetModuleSpecifications( 133b9c1b51eSKate Stone module_spec.GetFileSpec(), file_offset, file_size, module_specs); 134b9c1b51eSKate Stone if (num_specs > 0) { 135f4d6de6aSGreg Clayton ModuleSpec matching_module_spec; 136f4d6de6aSGreg Clayton 137b9c1b51eSKate Stone if (num_specs == 1) { 138b9c1b51eSKate Stone if (module_specs.GetModuleSpecAtIndex(0, matching_module_spec)) { 139b9c1b51eSKate Stone if (platform_arch.IsValid()) { 140b9c1b51eSKate Stone if (platform_arch.IsCompatibleMatch( 141b9c1b51eSKate Stone matching_module_spec.GetArchitecture())) { 1423f19ada8SGreg Clayton // If the OS or vendor weren't specified, then adopt the module's 14305097246SAdrian Prantl // architecture so that the platform matching can be more 14405097246SAdrian Prantl // accurate 145b9c1b51eSKate Stone if (!platform_arch.TripleOSWasSpecified() || 146b9c1b51eSKate Stone !platform_arch.TripleVendorWasSpecified()) { 1473f19ada8SGreg Clayton prefer_platform_arch = true; 1483f19ada8SGreg Clayton platform_arch = matching_module_spec.GetArchitecture(); 1493f19ada8SGreg Clayton } 150b9c1b51eSKate Stone } else { 1517df337f8STodd Fiala StreamString platform_arch_strm; 1527df337f8STodd Fiala StreamString module_arch_strm; 1537df337f8STodd Fiala 1547df337f8STodd Fiala platform_arch.DumpTriple(platform_arch_strm); 155b9c1b51eSKate Stone matching_module_spec.GetArchitecture().DumpTriple( 156b9c1b51eSKate Stone module_arch_strm); 157b9c1b51eSKate Stone error.SetErrorStringWithFormat( 158b9c1b51eSKate Stone "the specified architecture '%s' is not compatible with '%s' " 159b9c1b51eSKate Stone "in '%s'", 160c156427dSZachary Turner platform_arch_strm.GetData(), module_arch_strm.GetData(), 161b5ad4ec7SGreg Clayton module_spec.GetFileSpec().GetPath().c_str()); 162f4d6de6aSGreg Clayton return error; 163f4d6de6aSGreg Clayton } 164b9c1b51eSKate Stone } else { 165f4d6de6aSGreg Clayton // Only one arch and none was specified 1663f19ada8SGreg Clayton prefer_platform_arch = true; 167f4d6de6aSGreg Clayton platform_arch = matching_module_spec.GetArchitecture(); 168f4d6de6aSGreg Clayton } 169f4d6de6aSGreg Clayton } 170b9c1b51eSKate Stone } else { 171b9c1b51eSKate Stone if (arch.IsValid()) { 172f4d6de6aSGreg Clayton module_spec.GetArchitecture() = arch; 173b9c1b51eSKate Stone if (module_specs.FindMatchingModuleSpec(module_spec, 174b9c1b51eSKate Stone matching_module_spec)) { 1753f19ada8SGreg Clayton prefer_platform_arch = true; 176f4d6de6aSGreg Clayton platform_arch = matching_module_spec.GetArchitecture(); 177f4d6de6aSGreg Clayton } 178b9c1b51eSKate Stone } else { 179b0cc53cfSGreg Clayton // No architecture specified, check if there is only one platform for 180b0cc53cfSGreg Clayton // all of the architectures. 181b0cc53cfSGreg Clayton 182b0cc53cfSGreg Clayton typedef std::vector<PlatformSP> PlatformList; 183b0cc53cfSGreg Clayton PlatformList platforms; 184615eb7e6SGreg Clayton PlatformSP host_platform_sp = Platform::GetHostPlatform(); 185b9c1b51eSKate Stone for (size_t i = 0; i < num_specs; ++i) { 186b0cc53cfSGreg Clayton ModuleSpec module_spec; 187b9c1b51eSKate Stone if (module_specs.GetModuleSpecAtIndex(i, module_spec)) { 188b0cc53cfSGreg Clayton // See if there was a selected platform and check that first 189b0cc53cfSGreg Clayton // since the user may have specified it. 190b9c1b51eSKate Stone if (platform_sp) { 191b9c1b51eSKate Stone if (platform_sp->IsCompatibleArchitecture( 192b9c1b51eSKate Stone module_spec.GetArchitecture(), false, nullptr)) { 193b0cc53cfSGreg Clayton platforms.push_back(platform_sp); 194b0cc53cfSGreg Clayton continue; 195f4d6de6aSGreg Clayton } 196f4d6de6aSGreg Clayton } 197f4d6de6aSGreg Clayton 19805097246SAdrian Prantl // Next check the host platform it if wasn't already checked 19905097246SAdrian Prantl // above 200b9c1b51eSKate Stone if (host_platform_sp && 201b9c1b51eSKate Stone (!platform_sp || 202b9c1b51eSKate Stone host_platform_sp->GetName() != platform_sp->GetName())) { 203b9c1b51eSKate Stone if (host_platform_sp->IsCompatibleArchitecture( 204b9c1b51eSKate Stone module_spec.GetArchitecture(), false, nullptr)) { 205b0cc53cfSGreg Clayton platforms.push_back(host_platform_sp); 206b0cc53cfSGreg Clayton continue; 207b0cc53cfSGreg Clayton } 208b0cc53cfSGreg Clayton } 209b0cc53cfSGreg Clayton 210b9c1b51eSKate Stone // Just find a platform that matches the architecture in the 211b9c1b51eSKate Stone // executable file 212b9c1b51eSKate Stone PlatformSP fallback_platform_sp( 213b9c1b51eSKate Stone Platform::GetPlatformForArchitecture( 214b9c1b51eSKate Stone module_spec.GetArchitecture(), nullptr)); 215b9c1b51eSKate Stone if (fallback_platform_sp) { 216e92a74ceSJason Molenda platforms.push_back(fallback_platform_sp); 217e92a74ceSJason Molenda } 218b0cc53cfSGreg Clayton } 219b0cc53cfSGreg Clayton } 220b0cc53cfSGreg Clayton 221e65b2cf2SEugene Zelenko Platform *platform_ptr = nullptr; 2229d58c728SJason Molenda bool more_than_one_platforms = false; 223b9c1b51eSKate Stone for (const auto &the_platform_sp : platforms) { 224b9c1b51eSKate Stone if (platform_ptr) { 225b9c1b51eSKate Stone if (platform_ptr->GetName() != the_platform_sp->GetName()) { 2269d58c728SJason Molenda more_than_one_platforms = true; 227e65b2cf2SEugene Zelenko platform_ptr = nullptr; 228b0cc53cfSGreg Clayton break; 229b0cc53cfSGreg Clayton } 230b9c1b51eSKate Stone } else { 231b0cc53cfSGreg Clayton platform_ptr = the_platform_sp.get(); 232b0cc53cfSGreg Clayton } 233b0cc53cfSGreg Clayton } 234b0cc53cfSGreg Clayton 235b9c1b51eSKate Stone if (platform_ptr) { 2364ebdee0aSBruce Mitchener // All platforms for all modules in the executable match, so we can 237b9c1b51eSKate Stone // select this platform 238b0cc53cfSGreg Clayton platform_sp = platforms.front(); 239b9c1b51eSKate Stone } else if (more_than_one_platforms == false) { 2409d58c728SJason Molenda // No platforms claim to support this file 241b9c1b51eSKate Stone error.SetErrorString("No matching platforms found for this file, " 242b9c1b51eSKate Stone "specify one with the --platform option"); 2439d58c728SJason Molenda return error; 244b9c1b51eSKate Stone } else { 245b9c1b51eSKate Stone // More than one platform claims to support this file, so the 246b9c1b51eSKate Stone // --platform option must be specified 247b0cc53cfSGreg Clayton StreamString error_strm; 248b0cc53cfSGreg Clayton std::set<Platform *> platform_set; 249b9c1b51eSKate Stone error_strm.Printf( 250b9c1b51eSKate Stone "more than one platform supports this executable ("); 251b9c1b51eSKate Stone for (const auto &the_platform_sp : platforms) { 252b9c1b51eSKate Stone if (platform_set.find(the_platform_sp.get()) == 253b9c1b51eSKate Stone platform_set.end()) { 254b0cc53cfSGreg Clayton if (!platform_set.empty()) 255b0cc53cfSGreg Clayton error_strm.PutCString(", "); 256b0cc53cfSGreg Clayton error_strm.PutCString(the_platform_sp->GetName().GetCString()); 257b0cc53cfSGreg Clayton platform_set.insert(the_platform_sp.get()); 258b0cc53cfSGreg Clayton } 259b0cc53cfSGreg Clayton } 260b9c1b51eSKate Stone error_strm.Printf( 261b9c1b51eSKate Stone "), use the --platform option to specify a platform"); 262c156427dSZachary Turner error.SetErrorString(error_strm.GetString()); 263b3a40ba8SGreg Clayton return error; 264b3a40ba8SGreg Clayton } 265b3a40ba8SGreg Clayton } 266b0cc53cfSGreg Clayton } 267b0cc53cfSGreg Clayton } 268b0cc53cfSGreg Clayton } 269b3a40ba8SGreg Clayton 270869e0c1cSTed Woodward // If we have a valid architecture, make sure the current platform is 271869e0c1cSTed Woodward // compatible with that architecture 272b9c1b51eSKate Stone if (!prefer_platform_arch && arch.IsValid()) { 273b9c1b51eSKate Stone if (!platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch)) { 27470512317SGreg Clayton platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch); 2758ec55a53SRobert Flack if (!is_dummy_target && platform_sp) 27695bbdf64SGreg Clayton debugger.GetPlatformList().SetSelectedPlatform(platform_sp); 27795bbdf64SGreg Clayton } 278b9c1b51eSKate Stone } else if (platform_arch.IsValid()) { 279b9c1b51eSKate Stone // if "arch" isn't valid, yet "platform_arch" is, it means we have an 28005097246SAdrian Prantl // executable file with a single architecture which should be used 2813f19ada8SGreg Clayton ArchSpec fixed_platform_arch; 282b9c1b51eSKate Stone if (!platform_sp->IsCompatibleArchitecture(platform_arch, false, 283b9c1b51eSKate Stone &fixed_platform_arch)) { 284b9c1b51eSKate Stone platform_sp = Platform::GetPlatformForArchitecture(platform_arch, 285b9c1b51eSKate Stone &fixed_platform_arch); 2868ec55a53SRobert Flack if (!is_dummy_target && platform_sp) 28795bbdf64SGreg Clayton debugger.GetPlatformList().SetSelectedPlatform(platform_sp); 28895bbdf64SGreg Clayton } 2893f19ada8SGreg Clayton } 290b3a40ba8SGreg Clayton 29170512317SGreg Clayton if (!platform_arch.IsValid()) 29270512317SGreg Clayton platform_arch = arch; 29370512317SGreg Clayton 294b9c1b51eSKate Stone error = TargetList::CreateTargetInternal( 295b9c1b51eSKate Stone debugger, user_exe_path, platform_arch, get_dependent_files, platform_sp, 296b9c1b51eSKate Stone target_sp, is_dummy_target); 297cac9c5f9SGreg Clayton return error; 298cac9c5f9SGreg Clayton } 299cac9c5f9SGreg Clayton 300b9c1b51eSKate Stone lldb::TargetSP TargetList::GetDummyTarget(lldb_private::Debugger &debugger) { 301893c932aSJim Ingham // FIXME: Maybe the dummy target should be per-Debugger 302b9c1b51eSKate Stone if (!m_dummy_target_sp || !m_dummy_target_sp->IsValid()) { 303893c932aSJim Ingham ArchSpec arch(Target::GetDefaultArchitecture()); 304893c932aSJim Ingham if (!arch.IsValid()) 305893c932aSJim Ingham arch = HostInfo::GetArchitecture(); 30697206d57SZachary Turner Status err = CreateDummyTarget( 307b9c1b51eSKate Stone debugger, arch.GetTriple().getTriple().c_str(), m_dummy_target_sp); 308893c932aSJim Ingham } 309893c932aSJim Ingham 310893c932aSJim Ingham return m_dummy_target_sp; 311893c932aSJim Ingham } 312893c932aSJim Ingham 31397206d57SZachary Turner Status TargetList::CreateDummyTarget(Debugger &debugger, 314a47464b2SZachary Turner llvm::StringRef specified_arch_name, 315b9c1b51eSKate Stone lldb::TargetSP &target_sp) { 316893c932aSJim Ingham PlatformSP host_platform_sp(Platform::GetHostPlatform()); 317b9c1b51eSKate Stone return CreateTargetInternal( 318b9c1b51eSKate Stone debugger, (const char *)nullptr, specified_arch_name, false, 319b9c1b51eSKate Stone (const OptionGroupPlatform *)nullptr, target_sp, true); 320893c932aSJim Ingham } 321893c932aSJim Ingham 32297206d57SZachary Turner Status TargetList::CreateTargetInternal(Debugger &debugger, 323a47464b2SZachary Turner llvm::StringRef user_exe_path, 32470512317SGreg Clayton const ArchSpec &specified_arch, 32530fdc8d8SChris Lattner bool get_dependent_files, 326893c932aSJim Ingham lldb::PlatformSP &platform_sp, 327893c932aSJim Ingham lldb::TargetSP &target_sp, 328b9c1b51eSKate Stone bool is_dummy_target) { 329f9d16476SPavel Labath static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 330f9d16476SPavel Labath Timer scoped_timer( 331f9d16476SPavel Labath func_cat, "TargetList::CreateTarget (file = '%s', arch = '%s')", 332f9d16476SPavel Labath user_exe_path.str().c_str(), specified_arch.GetArchitectureName()); 33397206d57SZachary Turner Status error; 3345aee162fSJim Ingham 33570512317SGreg Clayton ArchSpec arch(specified_arch); 33670512317SGreg Clayton 337b9c1b51eSKate Stone if (arch.IsValid()) { 338b9c1b51eSKate Stone if (!platform_sp || 339b9c1b51eSKate Stone !platform_sp->IsCompatibleArchitecture(arch, false, nullptr)) 34070512317SGreg Clayton platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch); 34170512317SGreg Clayton } 34270512317SGreg Clayton 34370512317SGreg Clayton if (!platform_sp) 34470512317SGreg Clayton platform_sp = debugger.GetPlatformList().GetSelectedPlatform(); 345ded470d3SGreg Clayton 3468ae50eb4SGreg Clayton if (!arch.IsValid()) 3478ae50eb4SGreg Clayton arch = specified_arch; 3488ae50eb4SGreg Clayton 349d26206b5SJason Molenda FileSpec file(user_exe_path, false); 350a47464b2SZachary Turner if (!file.Exists() && user_exe_path.startswith("~")) { 351b9c1b51eSKate Stone // we want to expand the tilde but we don't want to resolve any symbolic 3528d48cd60SZachary Turner // links so we can't use the FileSpec constructor's resolve flag 3538d48cd60SZachary Turner llvm::SmallString<64> unglobbed_path; 3548d48cd60SZachary Turner StandardTildeExpressionResolver Resolver; 3558d48cd60SZachary Turner Resolver.ResolveFullPath(user_exe_path, unglobbed_path); 3569f822cd1SMichael Sartain 3573f559740SZachary Turner if (unglobbed_path.empty()) 3583f559740SZachary Turner file = FileSpec(user_exe_path, false); 3593f559740SZachary Turner else 3603f559740SZachary Turner file = FileSpec(unglobbed_path.c_str(), false); 361d26206b5SJason Molenda } 3629f822cd1SMichael Sartain 36382d79295SGreg Clayton bool user_exe_path_is_bundle = false; 36482d79295SGreg Clayton char resolved_bundle_exe_path[PATH_MAX]; 36582d79295SGreg Clayton resolved_bundle_exe_path[0] = '\0'; 366b9c1b51eSKate Stone if (file) { 3677d86ee5aSZachary Turner if (llvm::sys::fs::is_directory(file.GetPath())) 36882d79295SGreg Clayton user_exe_path_is_bundle = true; 36982d79295SGreg Clayton 370a47464b2SZachary Turner if (file.IsRelative() && !user_exe_path.empty()) { 3711d5855b1SPavel Labath llvm::SmallString<64> cwd; 3721d5855b1SPavel Labath if (! llvm::sys::fs::current_path(cwd)) { 373d68dbd5aSGreg Clayton FileSpec cwd_file(cwd.c_str(), false); 374d68dbd5aSGreg Clayton cwd_file.AppendPathComponent(file); 3759ff5aae5SGreg Clayton if (cwd_file.Exists()) 3769ff5aae5SGreg Clayton file = cwd_file; 377a0ca6601SGreg Clayton } 378a0ca6601SGreg Clayton } 379a0ca6601SGreg Clayton 38030fdc8d8SChris Lattner ModuleSP exe_module_sp; 381b9c1b51eSKate Stone if (platform_sp) { 382b9c1b51eSKate Stone FileSpecList executable_search_paths( 383b9c1b51eSKate Stone Target::GetDefaultExecutableSearchPaths()); 3848012cadbSGreg Clayton ModuleSpec module_spec(file, arch); 385b9c1b51eSKate Stone error = platform_sp->ResolveExecutable(module_spec, exe_module_sp, 386b9c1b51eSKate Stone executable_search_paths.GetSize() 387b9c1b51eSKate Stone ? &executable_search_paths 388b9c1b51eSKate Stone : nullptr); 389c859e2d5SGreg Clayton } 390428a9a58SCaroline Tice 391b9c1b51eSKate Stone if (error.Success() && exe_module_sp) { 392b9c1b51eSKate Stone if (exe_module_sp->GetObjectFile() == nullptr) { 393b9c1b51eSKate Stone if (arch.IsValid()) { 394b9c1b51eSKate Stone error.SetErrorStringWithFormat( 395b9c1b51eSKate Stone "\"%s\" doesn't contain architecture %s", file.GetPath().c_str(), 39664195a2cSGreg Clayton arch.GetArchitectureName()); 397b9c1b51eSKate Stone } else { 398b5ad4ec7SGreg Clayton error.SetErrorStringWithFormat("unsupported file type \"%s\"", 399b5ad4ec7SGreg Clayton file.GetPath().c_str()); 400bc5cad6cSGreg Clayton } 4015aee162fSJim Ingham return error; 4025aee162fSJim Ingham } 403893c932aSJim Ingham target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target)); 40430fdc8d8SChris Lattner target_sp->SetExecutableModule(exe_module_sp, get_dependent_files); 40582d79295SGreg Clayton if (user_exe_path_is_bundle) 406b9c1b51eSKate Stone exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path, 407b9c1b51eSKate Stone sizeof(resolved_bundle_exe_path)); 4085aee162fSJim Ingham } 409b9c1b51eSKate Stone } else { 41005097246SAdrian Prantl // No file was specified, just create an empty target with any arch if a 41105097246SAdrian Prantl // valid arch was specified 412893c932aSJim Ingham target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target)); 413e996fd30SGreg Clayton } 4141559a46bSCaroline Tice 415b9c1b51eSKate Stone if (target_sp) { 41682d79295SGreg Clayton // Set argv0 with what the user typed, unless the user specified a 41782d79295SGreg Clayton // directory. If the user specified a directory, then it is probably a 41882d79295SGreg Clayton // bundle that was resolved and we need to use the resolved bundle path 419a47464b2SZachary Turner if (!user_exe_path.empty()) { 420b9c1b51eSKate Stone // Use exactly what the user typed as the first argument when we exec or 421b9c1b51eSKate Stone // posix_spawn 422b9c1b51eSKate Stone if (user_exe_path_is_bundle && resolved_bundle_exe_path[0]) { 42382d79295SGreg Clayton target_sp->SetArg0(resolved_bundle_exe_path); 424b9c1b51eSKate Stone } else { 4259f822cd1SMichael Sartain // Use resolved path 4269f822cd1SMichael Sartain target_sp->SetArg0(file.GetPath().c_str()); 427a0ca6601SGreg Clayton } 42882d79295SGreg Clayton } 429b9c1b51eSKate Stone if (file.GetDirectory()) { 430a0ca6601SGreg Clayton FileSpec file_dir; 431a0ca6601SGreg Clayton file_dir.GetDirectory() = file.GetDirectory(); 432a0ca6601SGreg Clayton target_sp->GetExecutableSearchPaths().Append(file_dir); 433a0ca6601SGreg Clayton } 434893c932aSJim Ingham 435893c932aSJim Ingham // Don't put the dummy target in the target list, it's held separately. 436b9c1b51eSKate Stone if (!is_dummy_target) { 43716ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 4382976d00aSJim Ingham m_selected_target_idx = m_target_list.size(); 43930fdc8d8SChris Lattner m_target_list.push_back(target_sp); 44033df7cd3SJim Ingham // Now prime this from the dummy target: 44133df7cd3SJim Ingham target_sp->PrimeFromDummyTarget(debugger.GetDummyTarget()); 442b9c1b51eSKate Stone } else { 443893c932aSJim Ingham m_dummy_target_sp = target_sp; 444893c932aSJim Ingham } 44530fdc8d8SChris Lattner } 44630fdc8d8SChris Lattner 44730fdc8d8SChris Lattner return error; 44830fdc8d8SChris Lattner } 44930fdc8d8SChris Lattner 450b9c1b51eSKate Stone bool TargetList::DeleteTarget(TargetSP &target_sp) { 45116ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 45230fdc8d8SChris Lattner collection::iterator pos, end = m_target_list.end(); 45330fdc8d8SChris Lattner 454b9c1b51eSKate Stone for (pos = m_target_list.begin(); pos != end; ++pos) { 455b9c1b51eSKate Stone if (pos->get() == target_sp.get()) { 45630fdc8d8SChris Lattner m_target_list.erase(pos); 45730fdc8d8SChris Lattner return true; 45830fdc8d8SChris Lattner } 45930fdc8d8SChris Lattner } 46030fdc8d8SChris Lattner return false; 46130fdc8d8SChris Lattner } 46230fdc8d8SChris Lattner 463b9c1b51eSKate Stone TargetSP TargetList::FindTargetWithExecutableAndArchitecture( 464b9c1b51eSKate Stone const FileSpec &exe_file_spec, const ArchSpec *exe_arch_ptr) const { 46516ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 46630fdc8d8SChris Lattner TargetSP target_sp; 467ddd7a2a6SSean Callanan bool full_match = (bool)exe_file_spec.GetDirectory(); 46830fdc8d8SChris Lattner 46930fdc8d8SChris Lattner collection::const_iterator pos, end = m_target_list.end(); 470b9c1b51eSKate Stone for (pos = m_target_list.begin(); pos != end; ++pos) { 471aa149cbdSGreg Clayton Module *exe_module = (*pos)->GetExecutableModulePointer(); 47230fdc8d8SChris Lattner 473b9c1b51eSKate Stone if (exe_module) { 474b9c1b51eSKate Stone if (FileSpec::Equal(exe_file_spec, exe_module->GetFileSpec(), 475b9c1b51eSKate Stone full_match)) { 476b9c1b51eSKate Stone if (exe_arch_ptr) { 477bf4b7be6SSean Callanan if (!exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture())) 47830fdc8d8SChris Lattner continue; 47930fdc8d8SChris Lattner } 48030fdc8d8SChris Lattner target_sp = *pos; 48130fdc8d8SChris Lattner break; 48230fdc8d8SChris Lattner } 48330fdc8d8SChris Lattner } 48430fdc8d8SChris Lattner } 48530fdc8d8SChris Lattner return target_sp; 48630fdc8d8SChris Lattner } 48730fdc8d8SChris Lattner 488b9c1b51eSKate Stone TargetSP TargetList::FindTargetWithProcessID(lldb::pid_t pid) const { 48916ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 49030fdc8d8SChris Lattner TargetSP target_sp; 49130fdc8d8SChris Lattner collection::const_iterator pos, end = m_target_list.end(); 492b9c1b51eSKate Stone for (pos = m_target_list.begin(); pos != end; ++pos) { 49330fdc8d8SChris Lattner Process *process = (*pos)->GetProcessSP().get(); 494b9c1b51eSKate Stone if (process && process->GetID() == pid) { 49530fdc8d8SChris Lattner target_sp = *pos; 49630fdc8d8SChris Lattner break; 49730fdc8d8SChris Lattner } 49830fdc8d8SChris Lattner } 49930fdc8d8SChris Lattner return target_sp; 50030fdc8d8SChris Lattner } 50130fdc8d8SChris Lattner 502b9c1b51eSKate Stone TargetSP TargetList::FindTargetWithProcess(Process *process) const { 50330fdc8d8SChris Lattner TargetSP target_sp; 504b9c1b51eSKate Stone if (process) { 50516ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 50630fdc8d8SChris Lattner collection::const_iterator pos, end = m_target_list.end(); 507b9c1b51eSKate Stone for (pos = m_target_list.begin(); pos != end; ++pos) { 508b9c1b51eSKate Stone if (process == (*pos)->GetProcessSP().get()) { 50930fdc8d8SChris Lattner target_sp = *pos; 51030fdc8d8SChris Lattner break; 51130fdc8d8SChris Lattner } 51230fdc8d8SChris Lattner } 51330fdc8d8SChris Lattner } 51430fdc8d8SChris Lattner return target_sp; 51530fdc8d8SChris Lattner } 51630fdc8d8SChris Lattner 517b9c1b51eSKate Stone TargetSP TargetList::GetTargetSP(Target *target) const { 51830fdc8d8SChris Lattner TargetSP target_sp; 519b9c1b51eSKate Stone if (target) { 52016ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 52130fdc8d8SChris Lattner collection::const_iterator pos, end = m_target_list.end(); 522b9c1b51eSKate Stone for (pos = m_target_list.begin(); pos != end; ++pos) { 523b9c1b51eSKate Stone if (target == (*pos).get()) { 52430fdc8d8SChris Lattner target_sp = *pos; 52530fdc8d8SChris Lattner break; 52630fdc8d8SChris Lattner } 52730fdc8d8SChris Lattner } 52830fdc8d8SChris Lattner } 52930fdc8d8SChris Lattner return target_sp; 53030fdc8d8SChris Lattner } 53130fdc8d8SChris Lattner 532b9c1b51eSKate Stone uint32_t TargetList::SendAsyncInterrupt(lldb::pid_t pid) { 53330fdc8d8SChris Lattner uint32_t num_async_interrupts_sent = 0; 53430fdc8d8SChris Lattner 535b9c1b51eSKate Stone if (pid != LLDB_INVALID_PROCESS_ID) { 53630fdc8d8SChris Lattner TargetSP target_sp(FindTargetWithProcessID(pid)); 537b9c1b51eSKate Stone if (target_sp) { 53830fdc8d8SChris Lattner Process *process = target_sp->GetProcessSP().get(); 539b9c1b51eSKate Stone if (process) { 540cfc0935eSJim Ingham process->SendAsyncInterrupt(); 54130fdc8d8SChris Lattner ++num_async_interrupts_sent; 54230fdc8d8SChris Lattner } 54330fdc8d8SChris Lattner } 544b9c1b51eSKate Stone } else { 54530fdc8d8SChris Lattner // We don't have a valid pid to broadcast to, so broadcast to the target 54630fdc8d8SChris Lattner // list's async broadcaster... 547e65b2cf2SEugene Zelenko BroadcastEvent(Process::eBroadcastBitInterrupt, nullptr); 54830fdc8d8SChris Lattner } 54930fdc8d8SChris Lattner 55030fdc8d8SChris Lattner return num_async_interrupts_sent; 55130fdc8d8SChris Lattner } 55230fdc8d8SChris Lattner 553b9c1b51eSKate Stone uint32_t TargetList::SignalIfRunning(lldb::pid_t pid, int signo) { 55430fdc8d8SChris Lattner uint32_t num_signals_sent = 0; 555e65b2cf2SEugene Zelenko Process *process = nullptr; 556b9c1b51eSKate Stone if (pid == LLDB_INVALID_PROCESS_ID) { 55730fdc8d8SChris Lattner // Signal all processes with signal 55816ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 55930fdc8d8SChris Lattner collection::iterator pos, end = m_target_list.end(); 560b9c1b51eSKate Stone for (pos = m_target_list.begin(); pos != end; ++pos) { 56130fdc8d8SChris Lattner process = (*pos)->GetProcessSP().get(); 562b9c1b51eSKate Stone if (process) { 563b9c1b51eSKate Stone if (process->IsAlive()) { 56430fdc8d8SChris Lattner ++num_signals_sent; 56530fdc8d8SChris Lattner process->Signal(signo); 56630fdc8d8SChris Lattner } 56730fdc8d8SChris Lattner } 56830fdc8d8SChris Lattner } 569b9c1b51eSKate Stone } else { 57030fdc8d8SChris Lattner // Signal a specific process with signal 57130fdc8d8SChris Lattner TargetSP target_sp(FindTargetWithProcessID(pid)); 572b9c1b51eSKate Stone if (target_sp) { 57330fdc8d8SChris Lattner process = target_sp->GetProcessSP().get(); 574b9c1b51eSKate Stone if (process) { 575b9c1b51eSKate Stone if (process->IsAlive()) { 57630fdc8d8SChris Lattner ++num_signals_sent; 57730fdc8d8SChris Lattner process->Signal(signo); 57830fdc8d8SChris Lattner } 57930fdc8d8SChris Lattner } 58030fdc8d8SChris Lattner } 58130fdc8d8SChris Lattner } 58230fdc8d8SChris Lattner return num_signals_sent; 58330fdc8d8SChris Lattner } 58430fdc8d8SChris Lattner 585b9c1b51eSKate Stone int TargetList::GetNumTargets() const { 58616ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 58730fdc8d8SChris Lattner return m_target_list.size(); 58830fdc8d8SChris Lattner } 58930fdc8d8SChris Lattner 590b9c1b51eSKate Stone lldb::TargetSP TargetList::GetTargetAtIndex(uint32_t idx) const { 59130fdc8d8SChris Lattner TargetSP target_sp; 59216ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 59330fdc8d8SChris Lattner if (idx < m_target_list.size()) 59430fdc8d8SChris Lattner target_sp = m_target_list[idx]; 59530fdc8d8SChris Lattner return target_sp; 59630fdc8d8SChris Lattner } 59730fdc8d8SChris Lattner 598b9c1b51eSKate Stone uint32_t TargetList::GetIndexOfTarget(lldb::TargetSP target_sp) const { 59916ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 6008499e1a4SJim Ingham size_t num_targets = m_target_list.size(); 601b9c1b51eSKate Stone for (size_t idx = 0; idx < num_targets; idx++) { 6028499e1a4SJim Ingham if (target_sp == m_target_list[idx]) 6038499e1a4SJim Ingham return idx; 6048499e1a4SJim Ingham } 6058499e1a4SJim Ingham return UINT32_MAX; 6068499e1a4SJim Ingham } 6078499e1a4SJim Ingham 608b9c1b51eSKate Stone uint32_t TargetList::SetSelectedTarget(Target *target) { 60916ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 610b9c1b51eSKate Stone collection::const_iterator pos, begin = m_target_list.begin(), 61130fdc8d8SChris Lattner end = m_target_list.end(); 612b9c1b51eSKate Stone for (pos = begin; pos != end; ++pos) { 613b9c1b51eSKate Stone if (pos->get() == target) { 6142976d00aSJim Ingham m_selected_target_idx = std::distance(begin, pos); 6152976d00aSJim Ingham return m_selected_target_idx; 61630fdc8d8SChris Lattner } 61730fdc8d8SChris Lattner } 6182976d00aSJim Ingham m_selected_target_idx = 0; 6192976d00aSJim Ingham return m_selected_target_idx; 62030fdc8d8SChris Lattner } 62130fdc8d8SChris Lattner 622b9c1b51eSKate Stone lldb::TargetSP TargetList::GetSelectedTarget() { 62316ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 6242976d00aSJim Ingham if (m_selected_target_idx >= m_target_list.size()) 6252976d00aSJim Ingham m_selected_target_idx = 0; 6262976d00aSJim Ingham return GetTargetAtIndex(m_selected_target_idx); 62730fdc8d8SChris Lattner } 628