From: Jason Molenda Date: Sun, 4 Nov 2012 03:20:05 +0000 (+0000) Subject: Add new ArchSpec methods, IsCompatibleMatch() and IsExactMatch(). X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ba813dc03c7a4d6ea68f00ef91c31c20e6540534;p=platform%2Fupstream%2Fllvm.git Add new ArchSpec methods, IsCompatibleMatch() and IsExactMatch(). The operator== method is a synonym for IsExactMatch(). The essential difference between these two is that IsCompatibleMatch() will say that armv7 and armv7s are compatible and return true. IsExactMatch() will say that armv7 and armv7s are not a match. An armv7s cpu can run either generic armv7 binaries or armv7s binaries (the latter being tuned for it). When we're picking the slice of a universal Mach-O file to load in an armv7s Target, we need to be able to first look for an exact cpu subtype match (armv7s == armv7s) and failing that, looking for a slice with a compatible architecture. Update ObjectContainerUniversalMachO::GetObjectFile to prefer an exact match of the cpu type, falling back to a compatible match if necessary. llvm-svn: 167365 --- diff --git a/lldb/include/lldb/Core/ArchSpec.h b/lldb/include/lldb/Core/ArchSpec.h index 917ef74..d60fdbd 100644 --- a/lldb/include/lldb/Core/ArchSpec.h +++ b/lldb/include/lldb/Core/ArchSpec.h @@ -367,7 +367,30 @@ public: lldb::ByteOrder GetDefaultEndian () const; + //------------------------------------------------------------------ + /// Compare an ArchSpec to another ArchSpec, requiring an exact cpu + /// type match between them. + /// e.g. armv7s is not an exact match with armv7 - this would return false + /// + /// @return true if the two ArchSpecs match. + //------------------------------------------------------------------ + bool + IsExactMatch (const ArchSpec& rhs) const; + + //------------------------------------------------------------------ + /// Compare an ArchSpec to another ArchSpec, requiring a compatible + /// cpu type match between them. + /// e.g. armv7s is compatible with armv7 - this method would return true + /// + /// @return true if the two ArchSpecs are compatible + //------------------------------------------------------------------ + bool + IsCompatibleMatch (const ArchSpec& rhs) const; + protected: + bool + Compare (const ArchSpec& rhs, bool exact_match) const; + llvm::Triple m_triple; Core m_core; lldb::ByteOrder m_byte_order; @@ -388,6 +411,8 @@ protected: /// @param[in] lhs The Left Hand Side ArchSpec object to compare. /// @param[in] rhs The Left Hand Side ArchSpec object to compare. /// +/// Uses the IsExactMatch() method for comparing the cpu types. +/// /// @return true if \a lhs is equal to \a rhs //------------------------------------------------------------------ bool operator==(const ArchSpec& lhs, const ArchSpec& rhs); diff --git a/lldb/source/Core/ArchSpec.cpp b/lldb/source/Core/ArchSpec.cpp index 28f2778..30b057b 100644 --- a/lldb/source/Core/ArchSpec.cpp +++ b/lldb/source/Core/ArchSpec.cpp @@ -27,6 +27,9 @@ using namespace lldb_private; #define ARCH_SPEC_SEPARATOR_CHAR '-' + +static bool cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_inverse, bool enforce_exact_match); + namespace lldb_private { struct CoreDefinition @@ -711,6 +714,82 @@ ArchSpec::GetMaximumOpcodeByteSize() const return 0; } +bool +ArchSpec::IsExactMatch (const ArchSpec& rhs) const +{ + return Compare (rhs, true); +} + +bool +ArchSpec::IsCompatibleMatch (const ArchSpec& rhs) const +{ + return Compare (rhs, false); +} + +bool +ArchSpec::Compare (const ArchSpec& rhs, bool exact_match) const +{ + if (GetByteOrder() != rhs.GetByteOrder()) + return false; + + const ArchSpec::Core lhs_core = GetCore (); + const ArchSpec::Core rhs_core = rhs.GetCore (); + + const bool core_match = cores_match (lhs_core, rhs_core, true, exact_match); + + if (core_match) + { + const llvm::Triple &lhs_triple = GetTriple(); + const llvm::Triple &rhs_triple = rhs.GetTriple(); + + const llvm::Triple::VendorType lhs_triple_vendor = lhs_triple.getVendor(); + const llvm::Triple::VendorType rhs_triple_vendor = rhs_triple.getVendor(); + if (lhs_triple_vendor != rhs_triple_vendor) + { + const bool rhs_vendor_specified = rhs.TripleVendorWasSpecified(); + const bool lhs_vendor_specified = TripleVendorWasSpecified(); + // Both architectures had the vendor specified, so if they aren't + // equal then we return false + if (rhs_vendor_specified && lhs_vendor_specified) + return false; + + // Only fail if both vendor types are not unknown + if (lhs_triple_vendor != llvm::Triple::UnknownVendor && + rhs_triple_vendor != llvm::Triple::UnknownVendor) + return false; + } + + const llvm::Triple::OSType lhs_triple_os = lhs_triple.getOS(); + const llvm::Triple::OSType rhs_triple_os = rhs_triple.getOS(); + if (lhs_triple_os != rhs_triple_os) + { + const bool rhs_os_specified = rhs.TripleOSWasSpecified(); + const bool lhs_os_specified = TripleOSWasSpecified(); + // Both architectures had the OS specified, so if they aren't + // equal then we return false + if (rhs_os_specified && lhs_os_specified) + return false; + // Only fail if both os types are not unknown + if (lhs_triple_os != llvm::Triple::UnknownOS && + rhs_triple_os != llvm::Triple::UnknownOS) + return false; + } + + const llvm::Triple::EnvironmentType lhs_triple_env = lhs_triple.getEnvironment(); + const llvm::Triple::EnvironmentType rhs_triple_env = rhs_triple.getEnvironment(); + + if (lhs_triple_env != rhs_triple_env) + { + // Only fail if both environment types are not unknown + if (lhs_triple_env != llvm::Triple::UnknownEnvironment && + rhs_triple_env != llvm::Triple::UnknownEnvironment) + return false; + } + return true; + } + return false; +} + //===----------------------------------------------------------------------===// // Helper methods. @@ -736,119 +815,13 @@ ArchSpec::CoreUpdated (bool update_triple) // Operators. static bool -cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_inverse) +cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_inverse, bool enforce_exact_match) { + if (core1 == core2) + return true; + switch (core1) { -// case ArchSpec::eCore_arm_armv4: -// try_inverse = false; -// if (core2 == ArchSpec::eCore_thumb) -// return true; -// break; -// -// case ArchSpec::eCore_arm_armv4t: -// try_inverse = false; -// if (core2 == ArchSpec::eCore_thumbv4t) -// return true; -// break; -// -// case ArchSpec::eCore_arm_armv5: -// try_inverse = false; -// if (core2 == ArchSpec::eCore_thumbv5) -// return true; -// break; -// -// case ArchSpec::eCore_arm_armv5t: -// case ArchSpec::eCore_arm_armv5e: -// try_inverse = false; -// if (core2 == ArchSpec::eCore_thumbv5e) -// return true; -// break; -// -// case ArchSpec::eCore_arm_armv6: -// try_inverse = false; -// if (core2 == ArchSpec::eCore_thumbv6) -// return true; -// break; -// -// case ArchSpec::eCore_arm_armv7: -// try_inverse = false; -// if (core2 == ArchSpec::eCore_thumbv7) -// return true; -// break; -// -// case ArchSpec::eCore_arm_armv7f: -// try_inverse = false; -// if (core2 == ArchSpec::eCore_thumbv7f) -// return true; -// break; -// -// case ArchSpec::eCore_arm_armv7k: -// try_inverse = false; -// if (core2 == ArchSpec::eCore_thumbv7k) -// return true; -// break; -// -// case ArchSpec::eCore_arm_armv7s: -// try_inverse = false; -// if (core2 == ArchSpec::eCore_thumbv7s) -// return true; -// break; -// -// case ArchSpec::eCore_thumb: -// try_inverse = false; -// if (core2 == ArchSpec::eCore_arm_armv4) -// return true; -// break; -// -// case ArchSpec::eCore_thumbv4t: -// try_inverse = false; -// if (core2 == ArchSpec::eCore_arm_armv4t) -// return true; -// break; -// -// case ArchSpec::eCore_thumbv5: -// try_inverse = false; -// if (core2 == ArchSpec::eCore_arm_armv5) -// return true; -// break; -// -// case ArchSpec::eCore_thumbv5e: -// try_inverse = false; -// if (core2 == ArchSpec::eCore_arm_armv5t || core2 == ArchSpec::eCore_arm_armv5e) -// return true; -// break; -// -// case ArchSpec::eCore_thumbv6: -// try_inverse = false; -// if (core2 == ArchSpec::eCore_arm_armv6) -// return true; -// break; -// -// case ArchSpec::eCore_thumbv7: -// try_inverse = false; -// if (core2 == ArchSpec::eCore_arm_armv7) -// return true; -// break; -// -// case ArchSpec::eCore_thumbv7f: -// try_inverse = false; -// if (core2 == ArchSpec::eCore_arm_armv7f) -// return true; -// break; -// -// case ArchSpec::eCore_thumbv7k: -// try_inverse = false; -// if (core2 == ArchSpec::eCore_arm_armv7k) -// return true; -// break; -// -// case ArchSpec::eCore_thumbv7s: -// try_inverse = false; -// if (core2 == ArchSpec::eCore_arm_armv7s) -// return true; -// break; - case ArchSpec::kCore_any: return true; @@ -876,87 +849,29 @@ cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_in return true; break; - case ArchSpec::eCore_arm_armv7: case ArchSpec::eCore_arm_armv7f: case ArchSpec::eCore_arm_armv7k: case ArchSpec::eCore_arm_armv7s: - try_inverse = false; - if (core2 == ArchSpec::eCore_arm_armv7) - return true; + if (!enforce_exact_match) + { + try_inverse = false; + if (core2 == ArchSpec::eCore_arm_armv7) + return true; + } break; default: break; } if (try_inverse) - return cores_match (core2, core1, false); + return cores_match (core2, core1, false, enforce_exact_match); return false; } bool lldb_private::operator== (const ArchSpec& lhs, const ArchSpec& rhs) { - if (lhs.GetByteOrder() != rhs.GetByteOrder()) - return false; - - const ArchSpec::Core lhs_core = lhs.GetCore (); - const ArchSpec::Core rhs_core = rhs.GetCore (); - - // Check if the cores match, or check a little closer watching for wildcard - // and equivalent cores - const bool core_match = (lhs_core == rhs_core) || cores_match (lhs_core, rhs_core, true); - - if (core_match) - { - const llvm::Triple &lhs_triple = lhs.GetTriple(); - const llvm::Triple &rhs_triple = rhs.GetTriple(); - - const llvm::Triple::VendorType lhs_triple_vendor = lhs_triple.getVendor(); - const llvm::Triple::VendorType rhs_triple_vendor = rhs_triple.getVendor(); - if (lhs_triple_vendor != rhs_triple_vendor) - { - const bool rhs_vendor_specified = rhs.TripleVendorWasSpecified(); - const bool lhs_vendor_specified = lhs.TripleVendorWasSpecified(); - // Both architectures had the vendor specified, so if they aren't - // equal then we return false - if (rhs_vendor_specified && lhs_vendor_specified) - return false; - - // Only fail if both vendor types are not unknown - if (lhs_triple_vendor != llvm::Triple::UnknownVendor && - rhs_triple_vendor != llvm::Triple::UnknownVendor) - return false; - } - - const llvm::Triple::OSType lhs_triple_os = lhs_triple.getOS(); - const llvm::Triple::OSType rhs_triple_os = rhs_triple.getOS(); - if (lhs_triple_os != rhs_triple_os) - { - const bool rhs_os_specified = rhs.TripleOSWasSpecified(); - const bool lhs_os_specified = lhs.TripleOSWasSpecified(); - // Both architectures had the OS specified, so if they aren't - // equal then we return false - if (rhs_os_specified && lhs_os_specified) - return false; - // Only fail if both os types are not unknown - if (lhs_triple_os != llvm::Triple::UnknownOS && - rhs_triple_os != llvm::Triple::UnknownOS) - return false; - } - - const llvm::Triple::EnvironmentType lhs_triple_env = lhs_triple.getEnvironment(); - const llvm::Triple::EnvironmentType rhs_triple_env = rhs_triple.getEnvironment(); - - if (lhs_triple_env != rhs_triple_env) - { - // Only fail if both environment types are not unknown - if (lhs_triple_env != llvm::Triple::UnknownEnvironment && - rhs_triple_env != llvm::Triple::UnknownEnvironment) - return false; - } - return true; - } - return false; + return lhs.IsExactMatch (rhs); } bool diff --git a/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp b/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp index c2d97bc..2241bc7 100644 --- a/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp +++ b/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp @@ -203,11 +203,12 @@ ObjectContainerUniversalMachO::GetObjectFile (const FileSpec *file) 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)) { - if (arch == curr_arch) + if (arch.IsExactMatch(curr_arch)) { return ObjectFile::FindPlugin (module_sp, file, @@ -217,6 +218,23 @@ ObjectContainerUniversalMachO::GetObjectFile (const FileSpec *file) } } } + + // Failing an exact match, try to find a compatible Arch of the Target. + for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx) + { + if (GetArchitectureAtIndex (arch_idx, curr_arch)) + { + if (arch.IsCompatibleMatch(curr_arch)) + { + return ObjectFile::FindPlugin (module_sp, + file, + m_offset + m_fat_archs[arch_idx].offset, + m_fat_archs[arch_idx].size, + m_data.GetSharedDataBuffer()); + } + } + } + } return ObjectFileSP(); }