bool PlatformWindows::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) { // From macosx;s plugin code. For FreeBSD we may want to support more archs. if (idx == 0) { arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture); return arch.IsValid(); } else if (idx == 1) { ArchSpec platform_arch (Host::GetArchitecture (Host::eSystemDefaultArchitecture)); ArchSpec platform_arch64 (Host::GetArchitecture (Host::eSystemDefaultArchitecture64)); if (platform_arch.IsExactMatch(platform_arch64)) { // This freebsd platform supports both 32 and 64 bit. Since we already // returned the 64 bit arch for idx == 0, return the 32 bit arch // for idx == 1 arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture32); return arch.IsValid(); } } return false; }
bool PlatformAppleWatchSimulator::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) { static const ArchSpec platform_arch(HostInfo::GetArchitecture(HostInfo::eArchKind64)); if (idx == 0) { arch = platform_arch; if (arch.IsValid()) { arch.GetTriple().setOS (llvm::Triple::WatchOS); return true; } } return false; }
bool PlatformOpenBSD::GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) { if (IsHost()) { ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); if (hostArch.GetTriple().isOSOpenBSD()) { if (idx == 0) { arch = hostArch; return arch.IsValid(); } } } else { if (m_remote_platform_sp) return m_remote_platform_sp->GetSupportedArchitectureAtIndex(idx, arch); llvm::Triple triple; // Set the OS to OpenBSD triple.setOS(llvm::Triple::OpenBSD); // Set the architecture switch (idx) { case 0: triple.setArchName("x86_64"); break; case 1: triple.setArchName("i386"); break; case 2: triple.setArchName("aarch64"); break; case 3: triple.setArchName("arm"); break; default: return false; } // Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the // vendor by calling triple.SetVendorName("unknown") so that it is a // "unspecified unknown". This means when someone calls // triple.GetVendorName() it will return an empty string which indicates // that the vendor can be set when two architectures are merged // Now set the triple into "arch" and return true arch.SetTriple(triple); return true; } return false; }
void Platform::GetStatus (Stream &strm) { uint32_t major = UINT32_MAX; uint32_t minor = UINT32_MAX; uint32_t update = UINT32_MAX; std::string s; strm.Printf (" Platform: %s\n", GetShortPluginName()); ArchSpec arch (GetSystemArchitecture()); if (arch.IsValid()) { if (!arch.GetTriple().str().empty()) strm.Printf(" Triple: %s\n", arch.GetTriple().str().c_str()); } if (GetOSVersion(major, minor, update)) { strm.Printf("OS Version: %u", major); if (minor != UINT32_MAX) strm.Printf(".%u", minor); if (update != UINT32_MAX) strm.Printf(".%u", update); if (GetOSBuildString (s)) strm.Printf(" (%s)", s.c_str()); strm.EOL(); } if (GetOSKernelDescription (s)) strm.Printf(" Kernel: %s\n", s.c_str()); if (IsHost()) { strm.Printf(" Hostname: %s\n", GetHostname()); } else { const bool is_connected = IsConnected(); if (is_connected) strm.Printf(" Hostname: %s\n", GetHostname()); strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no"); } }
ObjectFileSP ObjectContainerUniversalMachO::GetObjectFile(const FileSpec *file) { uint32_t arch_idx = 0; ArchSpec arch; // If the module hasn't specified an architecture yet, set it to the default // architecture: ModuleSP module_sp(GetModule()); if (module_sp) { if (!module_sp->GetArchitecture().IsValid()) { arch = Target::GetDefaultArchitecture(); if (!arch.IsValid()) arch.SetTriple(LLDB_ARCH_DEFAULT); } else arch = module_sp->GetArchitecture(); ArchSpec curr_arch; // First, try to find an exact match for the Arch of the Target. for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx) { if (GetArchitectureAtIndex(arch_idx, curr_arch) && arch.IsExactMatch(curr_arch)) break; } // Failing an exact match, try to find a compatible Arch of the Target. if (arch_idx >= m_header.nfat_arch) { for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx) { if (GetArchitectureAtIndex(arch_idx, curr_arch) && arch.IsCompatibleMatch(curr_arch)) break; } } if (arch_idx < m_header.nfat_arch) { DataBufferSP data_sp; lldb::offset_t data_offset = 0; return ObjectFile::FindPlugin( module_sp, file, m_offset + m_fat_archs[arch_idx].offset, m_fat_archs[arch_idx].size, data_sp, data_offset); } } return ObjectFileSP(); }
Error NativeProcessProtocol::ResolveProcessArchitecture(lldb::pid_t pid, ArchSpec &arch) { // Grab process info for the running process. ProcessInstanceInfo process_info; if (!Host::GetProcessInfo(pid, process_info)) return Error("failed to get process info"); // Resolve the executable module. ModuleSpecList module_specs; if (!ObjectFile::GetModuleSpecifications(process_info.GetExecutableFile(), 0, 0, module_specs)) return Error("failed to get module specifications"); lldbassert(module_specs.GetSize() == 1); arch = module_specs.GetModuleSpecRefAtIndex(0).GetArchitecture(); if (arch.IsValid()) return Error(); else return Error("failed to retrieve a valid architecture from the exe module"); }
ObjectContainerBSDArchive::Archive::shared_ptr ObjectContainerBSDArchive::Archive::FindCachedArchive (const FileSpec &file, const ArchSpec &arch, const TimeValue &time, lldb::offset_t file_offset) { Mutex::Locker locker(Archive::GetArchiveCacheMutex ()); shared_ptr archive_sp; Archive::Map &archive_map = Archive::GetArchiveCache (); Archive::Map::iterator pos = archive_map.find (file); // Don't cache a value for "archive_map.end()" below since we might // delete an archive entry... while (pos != archive_map.end() && pos->first == file) { bool match = true; if (arch.IsValid() && pos->second->GetArchitecture().IsCompatibleMatch(arch) == false) match = false; else if (file_offset != LLDB_INVALID_OFFSET && pos->second->GetFileOffset() != file_offset) match = false; if (match) { if (pos->second->GetModificationTime() == time) { return pos->second; } else { // We have a file at the same path with the same architecture // whose modification time doesn't match. It doesn't make sense // for us to continue to use this BSD archive since we cache only // the object info which consists of file time info and also the // file offset and file size of any contianed objects. Since // this information is now out of date, we won't get the correct // information if we go and extract the file data, so we should // remove the old and outdated entry. archive_map.erase (pos); pos = archive_map.find (file); continue; // Continue to next iteration so we don't increment pos below... } } ++pos; } return archive_sp; }
PlatformSP Platform::Create (const ArchSpec &arch, ArchSpec *platform_arch_ptr, Error &error) { lldb::PlatformSP platform_sp; if (arch.IsValid()) { uint32_t idx; PlatformCreateInstance create_callback; // First try exact arch matches across all platform plug-ins bool exact = true; for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx) { if (create_callback) { platform_sp.reset(create_callback(false, &arch)); if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, exact, platform_arch_ptr)) return platform_sp; } } // Next try compatible arch matches across all platform plug-ins exact = false; for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx) { if (create_callback) { platform_sp.reset(create_callback(false, &arch)); if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, exact, platform_arch_ptr)) return platform_sp; } } } else error.SetErrorString ("invalid platform name"); if (platform_arch_ptr) platform_arch_ptr->Clear(); platform_sp.reset(); return platform_sp; }
//------------------------------------------------------------------ /// Lets a platform answer if it is compatible with a given /// architecture and the target triple contained within. //------------------------------------------------------------------ bool Platform::IsCompatibleArchitecture (const ArchSpec &arch, bool exact_arch_match, ArchSpec *compatible_arch_ptr) { // If the architecture is invalid, we must answer true... if (arch.IsValid()) { ArchSpec platform_arch; // Try for an exact architecture match first. if (exact_arch_match) { for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx) { if (arch.IsExactMatch(platform_arch)) { if (compatible_arch_ptr) *compatible_arch_ptr = platform_arch; return true; } } } else { for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx) { if (arch.IsCompatibleMatch(platform_arch)) { if (compatible_arch_ptr) *compatible_arch_ptr = platform_arch; return true; } } } } if (compatible_arch_ptr) compatible_arch_ptr->Clear(); return false; }
Error PlatformKalimba::ResolveExecutable (const FileSpec &exe_file, const ArchSpec &exe_arch, lldb::ModuleSP &exe_module_sp, const FileSpecList *module_search_paths_ptr) { Error error; char exe_path[PATH_MAX]; FileSpec resolved_exe_file (exe_file); if (!resolved_exe_file.Exists()) { exe_file.GetPath(exe_path, sizeof(exe_path)); error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path); } if (error.Success()) { ModuleSpec module_spec (resolved_exe_file, exe_arch); if (exe_arch.IsValid()) { error = ModuleList::GetSharedModule (module_spec, exe_module_sp, NULL, NULL, NULL); if (error.Fail()) { // If we failed, it may be because the vendor and os aren't known. If that is the // case, try setting them to the host architecture and give it another try. llvm::Triple &module_triple = module_spec.GetArchitecture().GetTriple(); bool is_vendor_specified = (module_triple.getVendor() != llvm::Triple::UnknownVendor); bool is_os_specified = (module_triple.getOS() != llvm::Triple::UnknownOS); if (!is_vendor_specified || !is_os_specified) { const llvm::Triple &host_triple = Host::GetArchitecture (Host::eSystemDefaultArchitecture).GetTriple(); if (!is_vendor_specified) module_triple.setVendorName (host_triple.getVendorName()); if (!is_os_specified) module_triple.setOSName (host_triple.getOSName()); error = ModuleList::GetSharedModule (module_spec, exe_module_sp, NULL, NULL, NULL); } } // TODO find out why exe_module_sp might be NULL if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL) { exe_module_sp.reset(); error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s", exe_file.GetPath().c_str(), exe_arch.GetArchitectureName()); } } else { // No valid architecture was specified, ask the platform for // the architectures that we should be using (in the correct order) // and see if we can find a match that way StreamString arch_names; for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, module_spec.GetArchitecture()); ++idx) { error = ModuleList::GetSharedModule (module_spec, exe_module_sp, NULL, NULL, NULL); // Did we find an executable using one of the if (error.Success()) { if (exe_module_sp && exe_module_sp->GetObjectFile()) break; else error.SetErrorToGenericError(); } if (idx > 0) arch_names.PutCString (", "); arch_names.PutCString (module_spec.GetArchitecture().GetArchitectureName()); } if (error.Fail() || !exe_module_sp) { error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s", exe_file.GetPath().c_str(), GetPluginName().GetCString(), arch_names.GetString().c_str()); } } } return error; }
//---------------------------------------------------------------------- // Process Control //---------------------------------------------------------------------- Error ProcessMachCore::DoLoadCore () { Error error; if (!m_core_module_sp) { error.SetErrorString ("invalid core module"); return error; } ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); if (core_objfile == NULL) { error.SetErrorString ("invalid core object file"); return error; } if (core_objfile->GetNumThreadContexts() == 0) { error.SetErrorString ("core file doesn't contain any LC_THREAD load commands, or the LC_THREAD architecture is not supported in this lldb"); return error; } SectionList *section_list = core_objfile->GetSectionList(); if (section_list == NULL) { error.SetErrorString ("core file has no sections"); return error; } const uint32_t num_sections = section_list->GetNumSections(0); if (num_sections == 0) { error.SetErrorString ("core file has no sections"); return error; } SetCanJIT(false); llvm::MachO::mach_header header; DataExtractor data (&header, sizeof(header), m_core_module_sp->GetArchitecture().GetByteOrder(), m_core_module_sp->GetArchitecture().GetAddressByteSize()); bool ranges_are_sorted = true; addr_t vm_addr = 0; for (uint32_t i=0; i<num_sections; ++i) { Section *section = section_list->GetSectionAtIndex (i).get(); if (section) { lldb::addr_t section_vm_addr = section->GetFileAddress(); FileRange file_range (section->GetFileOffset(), section->GetFileSize()); VMRangeToFileOffset::Entry range_entry (section_vm_addr, section->GetByteSize(), file_range); if (vm_addr > section_vm_addr) ranges_are_sorted = false; vm_addr = section->GetFileAddress(); VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back(); // printf ("LC_SEGMENT[%u] arange=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), frange=[0x%8.8x - 0x%8.8x)\n", // i, // range_entry.GetRangeBase(), // range_entry.GetRangeEnd(), // range_entry.data.GetRangeBase(), // range_entry.data.GetRangeEnd()); if (last_entry && last_entry->GetRangeEnd() == range_entry.GetRangeBase() && last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase()) { last_entry->SetRangeEnd (range_entry.GetRangeEnd()); last_entry->data.SetRangeEnd (range_entry.data.GetRangeEnd()); //puts("combine"); } else { m_core_aranges.Append(range_entry); } } } if (!ranges_are_sorted) { m_core_aranges.Sort(); } if (m_dyld_addr == LLDB_INVALID_ADDRESS || m_mach_kernel_addr == LLDB_INVALID_ADDRESS) { // We need to locate the main executable in the memory ranges // we have in the core file. We need to search for both a user-process dyld binary // and a kernel binary in memory; we must look at all the pages in the binary so // we don't miss one or the other. If we find a user-process dyld binary, stop // searching -- that's the one we'll prefer over the mach kernel. const size_t num_core_aranges = m_core_aranges.GetSize(); for (size_t i=0; i<num_core_aranges && m_dyld_addr == LLDB_INVALID_ADDRESS; ++i) { const VMRangeToFileOffset::Entry *entry = m_core_aranges.GetEntryAtIndex(i); lldb::addr_t section_vm_addr_start = entry->GetRangeBase(); lldb::addr_t section_vm_addr_end = entry->GetRangeEnd(); for (lldb::addr_t section_vm_addr = section_vm_addr_start; section_vm_addr < section_vm_addr_end; section_vm_addr += 0x1000) { GetDynamicLoaderAddress (section_vm_addr); } } } // If we found both a user-process dyld and a kernel binary, we need to decide // which to prefer. if (GetCorefilePreference() == eKernelCorefile) { if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) { m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic(); } else if (m_dyld_addr != LLDB_INVALID_ADDRESS) { m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic(); } } else { if (m_dyld_addr != LLDB_INVALID_ADDRESS) { m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic(); } else if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) { m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic(); } } // Even if the architecture is set in the target, we need to override // it to match the core file which is always single arch. ArchSpec arch (m_core_module_sp->GetArchitecture()); if (arch.GetCore() == ArchSpec::eCore_x86_32_i486) { arch.SetTriple ("i386", m_target.GetPlatform().get()); } if (arch.IsValid()) m_target.SetArchitecture(arch); return error; }
Error ModuleList::GetSharedModule ( const FileSpec& in_file_spec, const ArchSpec& arch, const lldb_private::UUID *uuid_ptr, const ConstString *object_name_ptr, off_t object_offset, ModuleSP &module_sp, ModuleSP *old_module_sp_ptr, bool *did_create_ptr, bool always_create ) { ModuleList &shared_module_list = GetSharedModuleList (); Mutex::Locker locker(shared_module_list.m_modules_mutex); char path[PATH_MAX]; char uuid_cstr[64]; Error error; module_sp.reset(); if (did_create_ptr) *did_create_ptr = false; if (old_module_sp_ptr) old_module_sp_ptr->reset(); // First just try and get the file where it purports to be (path in // in_file_spec), then check and uuid. if (in_file_spec) { // Make sure no one else can try and get or create a module while this // function is actively working on it by doing an extra lock on the // global mutex list. if (always_create == false) { ModuleList matching_module_list; const size_t num_matching_modules = shared_module_list.FindModules (&in_file_spec, &arch, NULL, object_name_ptr, matching_module_list); if (num_matching_modules > 0) { for (uint32_t module_idx = 0; module_idx < num_matching_modules; ++module_idx) { module_sp = matching_module_list.GetModuleAtIndex(module_idx); if (uuid_ptr && uuid_ptr->IsValid()) { // We found the module we were looking for. if (module_sp->GetUUID() == *uuid_ptr) return error; } else { // If we didn't have a UUID in mind when looking for the object file, // then we should make sure the modification time hasn't changed! TimeValue file_spec_mod_time(in_file_spec.GetModificationTime()); if (file_spec_mod_time.IsValid()) { if (file_spec_mod_time == module_sp->GetModificationTime()) return error; } } if (old_module_sp_ptr && !old_module_sp_ptr->get()) *old_module_sp_ptr = module_sp; shared_module_list.Remove (module_sp); module_sp.reset(); } } } if (module_sp) return error; else { #if defined ENABLE_MODULE_SP_LOGGING ModuleSP logging_module_sp (new Module (in_file_spec, arch, object_name_ptr, object_offset), ModuleSharedPtrLogger, (void *)ConstString("a.out").GetCString()); module_sp = logging_module_sp; #else module_sp.reset (new Module (in_file_spec, arch, object_name_ptr, object_offset)); #endif // Make sure there are a module and an object file since we can specify // a valid file path with an architecture that might not be in that file. // By getting the object file we can guarantee that the architecture matches if (module_sp && module_sp->GetObjectFile()) { // If we get in here we got the correct arch, now we just need // to verify the UUID if one was given if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) module_sp.reset(); else { if (did_create_ptr) *did_create_ptr = true; shared_module_list.Append(module_sp); return error; } } } } // Either the file didn't exist where at the path, or no path was given, so // we now have to use more extreme measures to try and find the appropriate // module. // Fixup the incoming path in case the path points to a valid file, yet // the arch or UUID (if one was passed in) don't match. FileSpec file_spec = Symbols::LocateExecutableObjectFile (in_file_spec ? &in_file_spec : NULL, arch.IsValid() ? &arch : NULL, uuid_ptr); // Don't look for the file if it appears to be the same one we already // checked for above... if (file_spec != in_file_spec) { if (!file_spec.Exists()) { file_spec.GetPath(path, sizeof(path)); if (file_spec.Exists()) { if (uuid_ptr && uuid_ptr->IsValid()) uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr)); else uuid_cstr[0] = '\0'; if (arch.IsValid()) { if (uuid_cstr[0]) error.SetErrorStringWithFormat("'%s' does not contain the %s architecture and UUID %s", path, arch.GetArchitectureName(), uuid_cstr); else error.SetErrorStringWithFormat("'%s' does not contain the %s architecture.", path, arch.GetArchitectureName()); } } else { error.SetErrorStringWithFormat("'%s' does not exist", path); } return error; } // Make sure no one else can try and get or create a module while this // function is actively working on it by doing an extra lock on the // global mutex list. ModuleList matching_module_list; if (shared_module_list.FindModules (&file_spec, &arch, uuid_ptr, object_name_ptr, matching_module_list) > 0) { module_sp = matching_module_list.GetModuleAtIndex(0); // If we didn't have a UUID in mind when looking for the object file, // then we should make sure the modification time hasn't changed! if (uuid_ptr == NULL) { TimeValue file_spec_mod_time(file_spec.GetModificationTime()); if (file_spec_mod_time.IsValid()) { if (file_spec_mod_time != module_sp->GetModificationTime()) { if (old_module_sp_ptr) *old_module_sp_ptr = module_sp; shared_module_list.Remove (module_sp); module_sp.reset(); } } } } if (module_sp.get() == NULL) { #if defined ENABLE_MODULE_SP_LOGGING ModuleSP logging_module_sp (new Module (file_spec, arch, object_name_ptr, object_offset), ModuleSharedPtrLogger, 0); module_sp = logging_module_sp; #else module_sp.reset (new Module (file_spec, arch, object_name_ptr, object_offset)); #endif // Make sure there are a module and an object file since we can specify // a valid file path with an architecture that might not be in that file. // By getting the object file we can guarantee that the architecture matches if (module_sp && module_sp->GetObjectFile()) { if (did_create_ptr) *did_create_ptr = true; shared_module_list.Append(module_sp); } else { file_spec.GetPath(path, sizeof(path)); if (file_spec) { if (arch.IsValid()) error.SetErrorStringWithFormat("unable to open %s architecture in '%s'", arch.GetArchitectureName(), path); else error.SetErrorStringWithFormat("unable to open '%s'", path); } else { if (uuid_ptr && uuid_ptr->IsValid()) uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr)); else uuid_cstr[0] = '\0'; if (uuid_cstr[0]) error.SetErrorStringWithFormat("cannot locate a module for UUID '%s'", uuid_cstr); else error.SetErrorStringWithFormat("cannot locate a module"); } } } } return error; }
bool CommandObjectFile::Execute ( CommandInterpreter &interpreter, Args& command, CommandReturnObject &result ) { const char *file_path = command.GetArgumentAtIndex(0); Timer scoped_timer(__PRETTY_FUNCTION__, "(dbg) file '%s'", file_path); const int argc = command.GetArgumentCount(); if (argc == 1) { FileSpec file_spec (file_path); if (! file_spec.Exists()) { result.AppendErrorWithFormat ("File '%s' does not exist.\n", file_path); result.SetStatus (eReturnStatusFailed); return result.Succeeded(); } TargetSP target_sp; ArchSpec arch; if (m_options.m_arch.IsValid()) arch = m_options.m_arch; else { arch = lldb_private::GetDefaultArchitecture (); if (!arch.IsValid()) arch = LLDB_ARCH_DEFAULT; } Debugger &debugger = interpreter.GetDebugger(); Error error = debugger.GetTargetList().CreateTarget (debugger, file_spec, arch, NULL, true, target_sp); if (error.Fail() && !m_options.m_arch.IsValid()) { if (arch == LLDB_ARCH_DEFAULT_32BIT) arch = LLDB_ARCH_DEFAULT_64BIT; else arch = LLDB_ARCH_DEFAULT_32BIT; error = debugger.GetTargetList().CreateTarget (debugger, file_spec, arch, NULL, true, target_sp); } if (target_sp) { debugger.GetTargetList().SetCurrentTarget(target_sp.get()); result.AppendMessageWithFormat ("Current executable set to '%s' (%s).\n", file_path, arch.AsCString()); result.SetStatus (eReturnStatusSuccessFinishNoResult); } else { result.AppendError(error.AsCString()); result.SetStatus (eReturnStatusFailed); } } else { result.AppendErrorWithFormat("'%s' takes exactly one executable path argument.\n", m_cmd_name.c_str()); result.SetStatus (eReturnStatusFailed); } return result.Succeeded(); }
//---------------------------------------------------------------------- // Process Control //---------------------------------------------------------------------- Error ProcessElfCore::DoLoadCore () { Error error; if (!m_core_module_sp) { error.SetErrorString ("invalid core module"); return error; } ObjectFileELF *core = (ObjectFileELF *)(m_core_module_sp->GetObjectFile()); if (core == NULL) { error.SetErrorString ("invalid core object file"); return error; } const uint32_t num_segments = core->GetProgramHeaderCount(); if (num_segments == 0) { error.SetErrorString ("core file has no sections"); return error; } SetCanJIT(false); m_thread_data_valid = true; bool ranges_are_sorted = true; lldb::addr_t vm_addr = 0; /// Walk through segments and Thread and Address Map information. /// PT_NOTE - Contains Thread and Register information /// PT_LOAD - Contains a contiguous range of Process Address Space for(uint32_t i = 1; i <= num_segments; i++) { const elf::ELFProgramHeader *header = core->GetProgramHeaderByIndex(i); assert(header != NULL); DataExtractor data = core->GetSegmentDataByIndex(i); // Parse thread contexts and auxv structure if (header->p_type == llvm::ELF::PT_NOTE) ParseThreadContextsFromNoteSegment(header, data); // PT_LOAD segments contains address map if (header->p_type == llvm::ELF::PT_LOAD) { lldb::addr_t last_addr = AddAddressRangeFromLoadSegment(header); if (vm_addr > last_addr) ranges_are_sorted = false; vm_addr = last_addr; } } if (!ranges_are_sorted) m_core_aranges.Sort(); // Even if the architecture is set in the target, we need to override // it to match the core file which is always single arch. ArchSpec arch (m_core_module_sp->GetArchitecture()); if (arch.IsValid()) m_target.SetArchitecture(arch); return error; }
Error PlatformLinux::ResolveExecutable (const FileSpec &exe_file, const ArchSpec &exe_arch, lldb::ModuleSP &exe_module_sp, const FileSpecList *module_search_paths_ptr) { Error error; // Nothing special to do here, just use the actual file and architecture char exe_path[PATH_MAX]; FileSpec resolved_exe_file (exe_file); if (IsHost()) { // If we have "ls" as the exe_file, resolve the executable location based on // the current path variables if (!resolved_exe_file.Exists()) { exe_file.GetPath(exe_path, sizeof(exe_path)); resolved_exe_file.SetFile(exe_path, true); } if (!resolved_exe_file.Exists()) resolved_exe_file.ResolveExecutableLocation (); if (resolved_exe_file.Exists()) error.Clear(); else { exe_file.GetPath(exe_path, sizeof(exe_path)); error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path); } } else { if (m_remote_platform_sp) { error = m_remote_platform_sp->ResolveExecutable (exe_file, exe_arch, exe_module_sp, NULL); } else { // We may connect to a process and use the provided executable (Don't use local $PATH). if (resolved_exe_file.Exists()) error.Clear(); else error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path); } } if (error.Success()) { ModuleSpec module_spec (resolved_exe_file, exe_arch); if (exe_arch.IsValid()) { error = ModuleList::GetSharedModule (module_spec, exe_module_sp, NULL, NULL, NULL); // TODO find out why exe_module_sp might be NULL if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL) { exe_module_sp.reset(); error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain the architecture %s", exe_file.GetDirectory().AsCString(""), exe_file.GetDirectory() ? "/" : "", exe_file.GetFilename().AsCString(""), exe_arch.GetArchitectureName()); } } else { // No valid architecture was specified, ask the platform for // the architectures that we should be using (in the correct order) // and see if we can find a match that way StreamString arch_names; for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, module_spec.GetArchitecture()); ++idx) { error = ModuleList::GetSharedModule (module_spec, exe_module_sp, NULL, NULL, NULL); // Did we find an executable using one of the if (error.Success()) { if (exe_module_sp && exe_module_sp->GetObjectFile()) break; else error.SetErrorToGenericError(); } if (idx > 0) arch_names.PutCString (", "); arch_names.PutCString (module_spec.GetArchitecture().GetArchitectureName()); } if (error.Fail() || !exe_module_sp) { error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain any '%s' platform architectures: %s", exe_file.GetDirectory().AsCString(""), exe_file.GetDirectory() ? "/" : "", exe_file.GetFilename().AsCString(""), GetShortPluginName(), arch_names.GetString().c_str()); } } } return error; }
//---------------------------------------------------------------------- // Process Control //---------------------------------------------------------------------- Error ProcessElfCore::DoLoadCore () { Error error; if (!m_core_module_sp) { error.SetErrorString ("invalid core module"); return error; } ObjectFileELF *core = (ObjectFileELF *)(m_core_module_sp->GetObjectFile()); if (core == NULL) { error.SetErrorString ("invalid core object file"); return error; } const uint32_t num_segments = core->GetProgramHeaderCount(); if (num_segments == 0) { error.SetErrorString ("core file has no segments"); return error; } SetCanJIT(false); m_thread_data_valid = true; bool ranges_are_sorted = true; lldb::addr_t vm_addr = 0; /// Walk through segments and Thread and Address Map information. /// PT_NOTE - Contains Thread and Register information /// PT_LOAD - Contains a contiguous range of Process Address Space for(uint32_t i = 1; i <= num_segments; i++) { const elf::ELFProgramHeader *header = core->GetProgramHeaderByIndex(i); assert(header != NULL); DataExtractor data = core->GetSegmentDataByIndex(i); // Parse thread contexts and auxv structure if (header->p_type == llvm::ELF::PT_NOTE) ParseThreadContextsFromNoteSegment(header, data); // PT_LOAD segments contains address map if (header->p_type == llvm::ELF::PT_LOAD) { lldb::addr_t last_addr = AddAddressRangeFromLoadSegment(header); if (vm_addr > last_addr) ranges_are_sorted = false; vm_addr = last_addr; } } if (!ranges_are_sorted) { m_core_aranges.Sort(); m_core_range_infos.Sort(); } // Even if the architecture is set in the target, we need to override // it to match the core file which is always single arch. ArchSpec arch (m_core_module_sp->GetArchitecture()); if (arch.IsValid()) GetTarget().SetArchitecture(arch); SetUnixSignals(UnixSignals::Create(GetArchitecture())); // Core files are useless without the main executable. See if we can locate the main // executable using data we found in the core file notes. lldb::ModuleSP exe_module_sp = GetTarget().GetExecutableModule(); if (!exe_module_sp) { // The first entry in the NT_FILE might be our executable if (!m_nt_file_entries.empty()) { ModuleSpec exe_module_spec; exe_module_spec.GetArchitecture() = arch; exe_module_spec.GetFileSpec().SetFile(m_nt_file_entries[0].path.GetCString(), false); if (exe_module_spec.GetFileSpec()) { exe_module_sp = GetTarget().GetSharedModule(exe_module_spec); if (exe_module_sp) GetTarget().SetExecutableModule(exe_module_sp, false); } } } return error; }
//---------------------------------------------------------------------- // Process Control //---------------------------------------------------------------------- Error ProcessMachCore::DoLoadCore () { Error error; if (!m_core_module_sp) { error.SetErrorString ("invalid core module"); return error; } ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); if (core_objfile == NULL) { error.SetErrorString ("invalid core object file"); return error; } if (core_objfile->GetNumThreadContexts() == 0) { error.SetErrorString ("core file doesn't contain any LC_THREAD load commands, or the LC_THREAD architecture is not supported in this lldb"); return error; } SectionList *section_list = core_objfile->GetSectionList(); if (section_list == NULL) { error.SetErrorString ("core file has no sections"); return error; } const uint32_t num_sections = section_list->GetNumSections(0); if (num_sections == 0) { error.SetErrorString ("core file has no sections"); return error; } SetCanJIT(false); llvm::MachO::mach_header header; DataExtractor data (&header, sizeof(header), m_core_module_sp->GetArchitecture().GetByteOrder(), m_core_module_sp->GetArchitecture().GetAddressByteSize()); bool ranges_are_sorted = true; addr_t vm_addr = 0; for (uint32_t i=0; i<num_sections; ++i) { Section *section = section_list->GetSectionAtIndex (i).get(); if (section) { lldb::addr_t section_vm_addr = section->GetFileAddress(); FileRange file_range (section->GetFileOffset(), section->GetFileSize()); VMRangeToFileOffset::Entry range_entry (section_vm_addr, section->GetByteSize(), file_range); if (vm_addr > section_vm_addr) ranges_are_sorted = false; vm_addr = section->GetFileAddress(); VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back(); // printf ("LC_SEGMENT[%u] arange=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), frange=[0x%8.8x - 0x%8.8x)\n", // i, // range_entry.GetRangeBase(), // range_entry.GetRangeEnd(), // range_entry.data.GetRangeBase(), // range_entry.data.GetRangeEnd()); if (last_entry && last_entry->GetRangeEnd() == range_entry.GetRangeBase() && last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase()) { last_entry->SetRangeEnd (range_entry.GetRangeEnd()); last_entry->data.SetRangeEnd (range_entry.data.GetRangeEnd()); //puts("combine"); } else { m_core_aranges.Append(range_entry); } // After we have added this section to our m_core_aranges map, // we can check the start of the section to see if it might // contain dyld for user space apps, or the mach kernel file // for kernel cores. if (m_dyld_addr == LLDB_INVALID_ADDRESS) GetDynamicLoaderAddress (section_vm_addr); } } if (!ranges_are_sorted) { m_core_aranges.Sort(); } // Even if the architecture is set in the target, we need to override // it to match the core file which is always single arch. ArchSpec arch (m_core_module_sp->GetArchitecture()); if (arch.GetCore() == ArchSpec::eCore_x86_32_i486) { arch.SetTriple ("i386", m_target.GetPlatform().get()); } if (arch.IsValid()) m_target.SetArchitecture(arch); if (m_dyld_addr == LLDB_INVALID_ADDRESS) { // We need to locate the main executable in the memory ranges // we have in the core file. We already checked the first address // in each memory zone above, so we just need to check each page // except the first page in each range and stop once we have found // our main executable const size_t num_core_aranges = m_core_aranges.GetSize(); for (size_t i=0; i<num_core_aranges && m_dyld_addr == LLDB_INVALID_ADDRESS; ++i) { const VMRangeToFileOffset::Entry *entry = m_core_aranges.GetEntryAtIndex(i); lldb::addr_t section_vm_addr_start = entry->GetRangeBase(); lldb::addr_t section_vm_addr_end = entry->GetRangeEnd(); for (lldb::addr_t section_vm_addr = section_vm_addr_start + 0x1000; section_vm_addr < section_vm_addr_end; section_vm_addr += 0x1000) { if (GetDynamicLoaderAddress (section_vm_addr)) { break; } } } } return error; }
Error PlatformRemoteiOS::ResolveExecutable (const FileSpec &exe_file, const ArchSpec &exe_arch, lldb::ModuleSP &exe_module_sp, const FileSpecList *module_search_paths_ptr) { Error error; // Nothing special to do here, just use the actual file and architecture FileSpec resolved_exe_file (exe_file); // If we have "ls" as the exe_file, resolve the executable loation based on // the current path variables // TODO: resolve bare executables in the Platform SDK // if (!resolved_exe_file.Exists()) // resolved_exe_file.ResolveExecutableLocation (); // Resolve any executable within a bundle on MacOSX // TODO: verify that this handles shallow bundles, if not then implement one ourselves Host::ResolveExecutableInBundle (resolved_exe_file); if (resolved_exe_file.Exists()) { if (exe_arch.IsValid()) { ModuleSpec module_spec (resolved_exe_file, exe_arch); error = ModuleList::GetSharedModule (module_spec, exe_module_sp, NULL, NULL, NULL); if (exe_module_sp && exe_module_sp->GetObjectFile()) return error; exe_module_sp.reset(); } // No valid architecture was specified or the exact ARM slice wasn't // found so ask the platform for the architectures that we should be // using (in the correct order) and see if we can find a match that way StreamString arch_names; ArchSpec platform_arch; for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx) { ModuleSpec module_spec (resolved_exe_file, platform_arch); error = ModuleList::GetSharedModule (module_spec, exe_module_sp, NULL, NULL, NULL); // Did we find an executable using one of the if (error.Success()) { if (exe_module_sp && exe_module_sp->GetObjectFile()) break; else error.SetErrorToGenericError(); } if (idx > 0) arch_names.PutCString (", "); arch_names.PutCString (platform_arch.GetArchitectureName()); } if (error.Fail() || !exe_module_sp) { error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s", exe_file.GetPath().c_str(), GetPluginName().GetCString(), arch_names.GetString().c_str()); } } else { error.SetErrorStringWithFormat ("'%s' does not exist", exe_file.GetPath().c_str()); } return error; }
//---------------------------------------------------------------------- // Process Control //---------------------------------------------------------------------- Error ProcessMachCore::DoLoadCore () { Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_PROCESS)); Error error; if (!m_core_module_sp) { error.SetErrorString ("invalid core module"); return error; } ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); if (core_objfile == NULL) { error.SetErrorString ("invalid core object file"); return error; } if (core_objfile->GetNumThreadContexts() == 0) { error.SetErrorString ("core file doesn't contain any LC_THREAD load commands, or the LC_THREAD architecture is not supported in this lldb"); return error; } SectionList *section_list = core_objfile->GetSectionList(); if (section_list == NULL) { error.SetErrorString ("core file has no sections"); return error; } const uint32_t num_sections = section_list->GetNumSections(0); if (num_sections == 0) { error.SetErrorString ("core file has no sections"); return error; } SetCanJIT(false); llvm::MachO::mach_header header; DataExtractor data (&header, sizeof(header), m_core_module_sp->GetArchitecture().GetByteOrder(), m_core_module_sp->GetArchitecture().GetAddressByteSize()); bool ranges_are_sorted = true; addr_t vm_addr = 0; for (uint32_t i=0; i<num_sections; ++i) { Section *section = section_list->GetSectionAtIndex (i).get(); if (section) { lldb::addr_t section_vm_addr = section->GetFileAddress(); FileRange file_range (section->GetFileOffset(), section->GetFileSize()); VMRangeToFileOffset::Entry range_entry (section_vm_addr, section->GetByteSize(), file_range); if (vm_addr > section_vm_addr) ranges_are_sorted = false; vm_addr = section->GetFileAddress(); VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back(); // printf ("LC_SEGMENT[%u] arange=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), frange=[0x%8.8x - 0x%8.8x)\n", // i, // range_entry.GetRangeBase(), // range_entry.GetRangeEnd(), // range_entry.data.GetRangeBase(), // range_entry.data.GetRangeEnd()); if (last_entry && last_entry->GetRangeEnd() == range_entry.GetRangeBase() && last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase()) { last_entry->SetRangeEnd (range_entry.GetRangeEnd()); last_entry->data.SetRangeEnd (range_entry.data.GetRangeEnd()); //puts("combine"); } else { m_core_aranges.Append(range_entry); } // Some core files don't fill in the permissions correctly. If that is the case // assume read + execute so clients don't think the memory is not readable, // or executable. The memory isn't writable since this plug-in doesn't implement // DoWriteMemory. uint32_t permissions = section->GetPermissions(); if (permissions == 0) permissions = lldb::ePermissionsReadable | lldb::ePermissionsExecutable; m_core_range_infos.Append( VMRangeToPermissions::Entry(section_vm_addr, section->GetByteSize(), permissions)); } } if (!ranges_are_sorted) { m_core_aranges.Sort(); m_core_range_infos.Sort(); } if (m_dyld_addr == LLDB_INVALID_ADDRESS || m_mach_kernel_addr == LLDB_INVALID_ADDRESS) { // We need to locate the main executable in the memory ranges // we have in the core file. We need to search for both a user-process dyld binary // and a kernel binary in memory; we must look at all the pages in the binary so // we don't miss one or the other. Step through all memory segments searching for // a kernel binary and for a user process dyld -- we'll decide which to prefer // later if both are present. const size_t num_core_aranges = m_core_aranges.GetSize(); for (size_t i = 0; i < num_core_aranges; ++i) { const VMRangeToFileOffset::Entry *entry = m_core_aranges.GetEntryAtIndex(i); lldb::addr_t section_vm_addr_start = entry->GetRangeBase(); lldb::addr_t section_vm_addr_end = entry->GetRangeEnd(); for (lldb::addr_t section_vm_addr = section_vm_addr_start; section_vm_addr < section_vm_addr_end; section_vm_addr += 0x1000) { GetDynamicLoaderAddress (section_vm_addr); } } } if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) { // In the case of multiple kernel images found in the core file via exhaustive // search, we may not pick the correct one. See if the DynamicLoaderDarwinKernel's // search heuristics might identify the correct one. // Most of the time, I expect the address from SearchForDarwinKernel() will be the // same as the address we found via exhaustive search. if (GetTarget().GetArchitecture().IsValid() == false && m_core_module_sp.get()) { GetTarget().SetArchitecture (m_core_module_sp->GetArchitecture()); } // SearchForDarwinKernel will end up calling back into this this class in the GetImageInfoAddress // method which will give it the m_mach_kernel_addr/m_dyld_addr it already has. Save that aside // and set m_mach_kernel_addr/m_dyld_addr to an invalid address temporarily so // DynamicLoaderDarwinKernel does a real search for the kernel using its own heuristics. addr_t saved_mach_kernel_addr = m_mach_kernel_addr; addr_t saved_user_dyld_addr = m_dyld_addr; m_mach_kernel_addr = LLDB_INVALID_ADDRESS; m_dyld_addr = LLDB_INVALID_ADDRESS; addr_t better_kernel_address = DynamicLoaderDarwinKernel::SearchForDarwinKernel (this); m_mach_kernel_addr = saved_mach_kernel_addr; m_dyld_addr = saved_user_dyld_addr; if (better_kernel_address != LLDB_INVALID_ADDRESS) { if (log) log->Printf ("ProcessMachCore::DoLoadCore: Using the kernel address from DynamicLoaderDarwinKernel"); m_mach_kernel_addr = better_kernel_address; } } // If we found both a user-process dyld and a kernel binary, we need to decide // which to prefer. if (GetCorefilePreference() == eKernelCorefile) { if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) { if (log) log->Printf ("ProcessMachCore::DoLoadCore: Using kernel corefile image at 0x%" PRIx64, m_mach_kernel_addr); m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic(); } else if (m_dyld_addr != LLDB_INVALID_ADDRESS) { if (log) log->Printf ("ProcessMachCore::DoLoadCore: Using user process dyld image at 0x%" PRIx64, m_dyld_addr); m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic(); } } else { if (m_dyld_addr != LLDB_INVALID_ADDRESS) { if (log) log->Printf ("ProcessMachCore::DoLoadCore: Using user process dyld image at 0x%" PRIx64, m_dyld_addr); m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic(); } else if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) { if (log) log->Printf ("ProcessMachCore::DoLoadCore: Using kernel corefile image at 0x%" PRIx64, m_mach_kernel_addr); m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic(); } } if (m_dyld_plugin_name != DynamicLoaderMacOSXDYLD::GetPluginNameStatic()) { // For non-user process core files, the permissions on the core file segments are usually // meaningless, they may be just "read", because we're dealing with kernel coredumps or // early startup coredumps and the dumper is grabbing pages of memory without knowing // what they are. If they aren't marked as "exeuctable", that can break the unwinder // which will check a pc value to see if it is in an executable segment and stop the // backtrace early if it is not ("executable" and "unknown" would both be fine, but // "not executable" will break the unwinder). size_t core_range_infos_size = m_core_range_infos.GetSize(); for (size_t i = 0; i < core_range_infos_size; i++) { VMRangeToPermissions::Entry *ent = m_core_range_infos.GetMutableEntryAtIndex (i); ent->data = lldb::ePermissionsReadable | lldb::ePermissionsExecutable; } } // Even if the architecture is set in the target, we need to override // it to match the core file which is always single arch. ArchSpec arch (m_core_module_sp->GetArchitecture()); if (arch.GetCore() == ArchSpec::eCore_x86_32_i486) { arch.SetTriple ("i386", GetTarget().GetPlatform().get()); } if (arch.IsValid()) GetTarget().SetArchitecture(arch); return error; }
bool PlatformFreeBSD::GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) { if (IsHost()) { ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); if (hostArch.GetTriple().isOSFreeBSD()) { if (idx == 0) { arch = hostArch; return arch.IsValid(); } else if (idx == 1) { // If the default host architecture is 64-bit, look for a 32-bit variant if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) { arch = HostInfo::GetArchitecture(HostInfo::eArchKind32); return arch.IsValid(); } } } } else { if (m_remote_platform_sp) return m_remote_platform_sp->GetSupportedArchitectureAtIndex(idx, arch); llvm::Triple triple; // Set the OS to FreeBSD triple.setOS(llvm::Triple::FreeBSD); // Set the architecture switch (idx) { case 0: triple.setArchName("x86_64"); break; case 1: triple.setArchName("i386"); break; case 2: triple.setArchName("aarch64"); break; case 3: triple.setArchName("arm"); break; case 4: triple.setArchName("mips64"); break; case 5: triple.setArchName("mips"); break; case 6: triple.setArchName("ppc64"); break; case 7: triple.setArchName("ppc"); break; default: return false; } // Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the // vendor by // calling triple.SetVendorName("unknown") so that it is a "unspecified // unknown". // This means when someone calls triple.GetVendorName() it will return an // empty string // which indicates that the vendor can be set when two architectures are // merged // Now set the triple into "arch" and return true arch.SetTriple(triple); return true; } return false; }
const ArchSpec & Host::GetArchitecture (SystemDefaultArchitecture arch_kind) { static bool g_supports_32 = false; static bool g_supports_64 = false; static ArchSpec g_host_arch_32; static ArchSpec g_host_arch_64; #if defined (__APPLE__) // Apple is different in that it can support both 32 and 64 bit executables // in the same operating system running concurrently. Here we detect the // correct host architectures for both 32 and 64 bit including if 64 bit // executables are supported on the system. if (g_supports_32 == false && g_supports_64 == false) { // All apple systems support 32 bit execution. g_supports_32 = true; uint32_t cputype, cpusubtype; uint32_t is_64_bit_capable = false; size_t len = sizeof(cputype); ArchSpec host_arch; // These will tell us about the kernel architecture, which even on a 64 // bit machine can be 32 bit... if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0) { len = sizeof (cpusubtype); if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) != 0) cpusubtype = CPU_TYPE_ANY; len = sizeof (is_64_bit_capable); if (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0) { if (is_64_bit_capable) g_supports_64 = true; } if (is_64_bit_capable) { #if defined (__i386__) || defined (__x86_64__) if (cpusubtype == CPU_SUBTYPE_486) cpusubtype = CPU_SUBTYPE_I386_ALL; #endif if (cputype & CPU_ARCH_ABI64) { // We have a 64 bit kernel on a 64 bit system g_host_arch_32.SetArchitecture (eArchTypeMachO, ~(CPU_ARCH_MASK) & cputype, cpusubtype); g_host_arch_64.SetArchitecture (eArchTypeMachO, cputype, cpusubtype); } else { // We have a 32 bit kernel on a 64 bit system g_host_arch_32.SetArchitecture (eArchTypeMachO, cputype, cpusubtype); cputype |= CPU_ARCH_ABI64; g_host_arch_64.SetArchitecture (eArchTypeMachO, cputype, cpusubtype); } } else { g_host_arch_32.SetArchitecture (eArchTypeMachO, cputype, cpusubtype); g_host_arch_64.Clear(); } } } #else // #if defined (__APPLE__) if (g_supports_32 == false && g_supports_64 == false) { llvm::Triple triple(llvm::sys::getDefaultTargetTriple()); g_host_arch_32.Clear(); g_host_arch_64.Clear(); switch (triple.getArch()) { default: g_host_arch_32.SetTriple(triple); g_supports_32 = true; break; case llvm::Triple::x86_64: case llvm::Triple::sparcv9: case llvm::Triple::ppc64: case llvm::Triple::cellspu: g_host_arch_64.SetTriple(triple); g_supports_64 = true; break; } g_supports_32 = g_host_arch_32.IsValid(); g_supports_64 = g_host_arch_64.IsValid(); } #endif // #else for #if defined (__APPLE__) if (arch_kind == eSystemDefaultArchitecture32) return g_host_arch_32; else if (arch_kind == eSystemDefaultArchitecture64) return g_host_arch_64; if (g_supports_64) return g_host_arch_64; return g_host_arch_32; }