Error TargetList::CreateTarget (Debugger &debugger, const FileSpec& file, const char *triple_cstr, bool get_dependent_files, const OptionGroupPlatform *platform_options, TargetSP &target_sp) { Error error; PlatformSP platform_sp; // This is purposely left empty unless it is specified by triple_cstr. // If not initialized via triple_cstr, then the currently selected platform // will set the architecture correctly. const ArchSpec arch(triple_cstr); if (triple_cstr && triple_cstr[0]) { if (!arch.IsValid()) { error.SetErrorStringWithFormat("invalid triple '%s'", triple_cstr); return error; } } ArchSpec platform_arch(arch); CommandInterpreter &interpreter = debugger.GetCommandInterpreter(); if (platform_options) { if (platform_options->PlatformWasSpecified ()) { const bool select_platform = true; platform_sp = platform_options->CreatePlatformWithOptions (interpreter, arch, select_platform, error, platform_arch); if (!platform_sp) return error; } } if (!platform_sp) { // Get the current platform and make sure it is compatible with the // current architecture if we have a valid architecture. platform_sp = debugger.GetPlatformList().GetSelectedPlatform (); if (arch.IsValid() && !platform_sp->IsCompatibleArchitecture(arch, &platform_arch)) { platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch); } } if (!platform_arch.IsValid()) platform_arch = arch; error = TargetList::CreateTarget (debugger, file, platform_arch, get_dependent_files, platform_sp, target_sp); if (target_sp) { if (file.GetDirectory()) { FileSpec file_dir; file_dir.GetDirectory() = file.GetDirectory(); target_sp->GetExecutableSearchPaths ().Append (file_dir); } } return error; }
Error TargetList::CreateTargetInternal (Debugger &debugger, const char *user_exe_path, const char *triple_cstr, bool get_dependent_files, const OptionGroupPlatform *platform_options, TargetSP &target_sp, bool is_dummy_target) { Error error; PlatformSP platform_sp; // This is purposely left empty unless it is specified by triple_cstr. // If not initialized via triple_cstr, then the currently selected platform // will set the architecture correctly. const ArchSpec arch(triple_cstr); if (triple_cstr && triple_cstr[0]) { if (!arch.IsValid()) { error.SetErrorStringWithFormat("invalid triple '%s'", triple_cstr); return error; } } ArchSpec platform_arch(arch); bool prefer_platform_arch = false; CommandInterpreter &interpreter = debugger.GetCommandInterpreter(); // let's see if there is already an existing plaform before we go creating another... platform_sp = debugger.GetPlatformList().GetSelectedPlatform(); if (platform_options && platform_options->PlatformWasSpecified ()) { // Create a new platform if it doesn't match the selected platform if (!platform_options->PlatformMatches(platform_sp)) { const bool select_platform = true; platform_sp = platform_options->CreatePlatformWithOptions (interpreter, arch, select_platform, error, platform_arch); if (!platform_sp) return error; } } if (user_exe_path && user_exe_path[0]) { ModuleSpecList module_specs; ModuleSpec module_spec; module_spec.GetFileSpec().SetFile(user_exe_path, true); // Resolve the executable in case we are given a path to a application bundle // like a .app bundle on MacOSX Host::ResolveExecutableInBundle (module_spec.GetFileSpec()); lldb::offset_t file_offset = 0; lldb::offset_t file_size = 0; const size_t num_specs = ObjectFile::GetModuleSpecifications (module_spec.GetFileSpec(), file_offset, file_size, module_specs); if (num_specs > 0) { ModuleSpec matching_module_spec; if (num_specs == 1) { if (module_specs.GetModuleSpecAtIndex(0, matching_module_spec)) { if (platform_arch.IsValid()) { if (platform_arch.IsCompatibleMatch(matching_module_spec.GetArchitecture())) { // If the OS or vendor weren't specified, then adopt the module's // architecture so that the platform matching can be more accurate if (!platform_arch.TripleOSWasSpecified() || !platform_arch.TripleVendorWasSpecified()) { prefer_platform_arch = true; platform_arch = matching_module_spec.GetArchitecture(); } } else { StreamString platform_arch_strm; StreamString module_arch_strm; platform_arch.DumpTriple(platform_arch_strm); matching_module_spec.GetArchitecture().DumpTriple(module_arch_strm); error.SetErrorStringWithFormat("the specified architecture '%s' is not compatible with '%s' in '%s'", platform_arch_strm.GetString().c_str(), module_arch_strm.GetString().c_str(), module_spec.GetFileSpec().GetPath().c_str()); return error; } } else { // Only one arch and none was specified prefer_platform_arch = true; platform_arch = matching_module_spec.GetArchitecture(); } } } else { if (arch.IsValid()) { module_spec.GetArchitecture() = arch; if (module_specs.FindMatchingModuleSpec(module_spec, matching_module_spec)) { prefer_platform_arch = true; platform_arch = matching_module_spec.GetArchitecture(); } } else { // No architecture specified, check if there is only one platform for // all of the architectures. typedef std::vector<PlatformSP> PlatformList; PlatformList platforms; PlatformSP host_platform_sp = Platform::GetHostPlatform(); for (size_t i=0; i<num_specs; ++i) { ModuleSpec module_spec; if (module_specs.GetModuleSpecAtIndex(i, module_spec)) { // See if there was a selected platform and check that first // since the user may have specified it. if (platform_sp) { if (platform_sp->IsCompatibleArchitecture(module_spec.GetArchitecture(), false, NULL)) { platforms.push_back(platform_sp); continue; } } // Next check the host platform it if wasn't already checked above if (host_platform_sp && (!platform_sp || host_platform_sp->GetName() != platform_sp->GetName())) { if (host_platform_sp->IsCompatibleArchitecture(module_spec.GetArchitecture(), false, NULL)) { platforms.push_back(host_platform_sp); continue; } } // Just find a platform that matches the architecture in the executable file PlatformSP fallback_platform_sp (Platform::GetPlatformForArchitecture(module_spec.GetArchitecture(), nullptr)); if (fallback_platform_sp) { platforms.push_back(fallback_platform_sp); } } } Platform *platform_ptr = NULL; bool more_than_one_platforms = false; for (const auto &the_platform_sp : platforms) { if (platform_ptr) { if (platform_ptr->GetName() != the_platform_sp->GetName()) { more_than_one_platforms = true; platform_ptr = NULL; break; } } else { platform_ptr = the_platform_sp.get(); } } if (platform_ptr) { // All platforms for all modules in the exectuable match, so we can select this platform platform_sp = platforms.front(); } else if (more_than_one_platforms == false) { // No platforms claim to support this file error.SetErrorString ("No matching platforms found for this file, specify one with the --platform option"); return error; } else { // More than one platform claims to support this file, so the --platform option must be specified StreamString error_strm; std::set<Platform *> platform_set; error_strm.Printf ("more than one platform supports this executable ("); for (const auto &the_platform_sp : platforms) { if (platform_set.find(the_platform_sp.get()) == platform_set.end()) { if (!platform_set.empty()) error_strm.PutCString(", "); error_strm.PutCString(the_platform_sp->GetName().GetCString()); platform_set.insert(the_platform_sp.get()); } } error_strm.Printf("), use the --platform option to specify a platform"); error.SetErrorString(error_strm.GetString().c_str()); return error; } } } } } // If we have a valid architecture, make sure the current platform is // compatible with that architecture if (!prefer_platform_arch && arch.IsValid()) { if (!platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch)) { platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch); if (!is_dummy_target && platform_sp) debugger.GetPlatformList().SetSelectedPlatform(platform_sp); } } else if (platform_arch.IsValid()) { // if "arch" isn't valid, yet "platform_arch" is, it means we have an executable file with // a single architecture which should be used ArchSpec fixed_platform_arch; if (!platform_sp->IsCompatibleArchitecture(platform_arch, false, &fixed_platform_arch)) { platform_sp = Platform::GetPlatformForArchitecture(platform_arch, &fixed_platform_arch); if (!is_dummy_target && platform_sp) debugger.GetPlatformList().SetSelectedPlatform(platform_sp); } } if (!platform_arch.IsValid()) platform_arch = arch; error = TargetList::CreateTargetInternal (debugger, user_exe_path, platform_arch, get_dependent_files, platform_sp, target_sp, is_dummy_target); return error; }
Error TargetList::CreateTarget (Debugger &debugger, const char *user_exe_path, const char *triple_cstr, bool get_dependent_files, const OptionGroupPlatform *platform_options, TargetSP &target_sp) { Error error; PlatformSP platform_sp; // This is purposely left empty unless it is specified by triple_cstr. // If not initialized via triple_cstr, then the currently selected platform // will set the architecture correctly. const ArchSpec arch(triple_cstr); if (triple_cstr && triple_cstr[0]) { if (!arch.IsValid()) { error.SetErrorStringWithFormat("invalid triple '%s'", triple_cstr); return error; } } ArchSpec platform_arch(arch); bool prefer_platform_arch = false; if (user_exe_path && user_exe_path[0]) { ModuleSpecList module_specs; ModuleSpec module_spec; module_spec.GetFileSpec().SetFile(user_exe_path, true); // Resolve the executable in case we are given a path to a application bundle // like a .app bundle on MacOSX Host::ResolveExecutableInBundle (module_spec.GetFileSpec()); lldb::offset_t file_offset = 0; lldb::offset_t file_size = 0; const size_t num_specs = ObjectFile::GetModuleSpecifications (module_spec.GetFileSpec(), file_offset, file_size, module_specs); if (num_specs > 0) { ModuleSpec matching_module_spec; if (num_specs == 1) { if (module_specs.GetModuleSpecAtIndex(0, matching_module_spec)) { if (platform_arch.IsValid()) { if (platform_arch.IsCompatibleMatch(matching_module_spec.GetArchitecture())) { // If the OS or vendor weren't specified, then adopt the module's // architecture so that the platform matching can be more accurate if (!platform_arch.TripleOSWasSpecified() || !platform_arch.TripleVendorWasSpecified()) { prefer_platform_arch = true; platform_arch = matching_module_spec.GetArchitecture(); } } else { error.SetErrorStringWithFormat("the specified architecture '%s' is not compatible with '%s' in '%s'", platform_arch.GetTriple().str().c_str(), matching_module_spec.GetArchitecture().GetTriple().str().c_str(), module_spec.GetFileSpec().GetPath().c_str()); return error; } } else { // Only one arch and none was specified prefer_platform_arch = true; platform_arch = matching_module_spec.GetArchitecture(); } } } else { if (arch.IsValid()) { module_spec.GetArchitecture() = arch; if (module_specs.FindMatchingModuleSpec(module_spec, matching_module_spec)) { prefer_platform_arch = true; platform_arch = matching_module_spec.GetArchitecture(); } } } } } CommandInterpreter &interpreter = debugger.GetCommandInterpreter(); if (platform_options) { if (platform_options->PlatformWasSpecified ()) { const bool select_platform = true; platform_sp = platform_options->CreatePlatformWithOptions (interpreter, arch, select_platform, error, platform_arch); if (!platform_sp) return error; } } if (!platform_sp) { // Get the current platform and make sure it is compatible with the // current architecture if we have a valid architecture. platform_sp = debugger.GetPlatformList().GetSelectedPlatform (); if (!prefer_platform_arch && arch.IsValid()) { if (!platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch)) platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch); } else if (platform_arch.IsValid()) { // if "arch" isn't valid, yet "platform_arch" is, it means we have an executable file with // a single architecture which should be used ArchSpec fixed_platform_arch; if (!platform_sp->IsCompatibleArchitecture(platform_arch, false, &fixed_platform_arch)) platform_sp = Platform::GetPlatformForArchitecture(platform_arch, &fixed_platform_arch); } } if (!platform_arch.IsValid()) platform_arch = arch; error = TargetList::CreateTarget (debugger, user_exe_path, platform_arch, get_dependent_files, platform_sp, target_sp); return error; }