Correctly detect legacy iOS simulator Mach-O objectfiles

The code in ObjectFileMachO didn't disambiguate between ios and
ios-simulator object files for Mach-O objects using the legacy
ambiguous LC_VERSION_MIN load commands. This used to not matter before
taught ArchSpec that ios and ios-simulator are no longer compatible.

rdar://problem/66545307

Differential Revision: https://reviews.llvm.org/D85358
This commit is contained in:
Adrian Prantl 2020-08-05 13:57:14 -07:00
parent 128bf458ab
commit 05df9cc703
4 changed files with 58 additions and 20 deletions

View File

@ -5007,8 +5007,8 @@ void ObjectFileMachO::GetAllArchSpecs(const llvm::MachO::mach_header &header,
struct version_min_command version_min;
switch (load_cmd.cmd) {
case llvm::MachO::LC_VERSION_MIN_IPHONEOS:
case llvm::MachO::LC_VERSION_MIN_MACOSX:
case llvm::MachO::LC_VERSION_MIN_IPHONEOS:
case llvm::MachO::LC_VERSION_MIN_TVOS:
case llvm::MachO::LC_VERSION_MIN_WATCHOS: {
if (load_cmd.cmdsize != sizeof(version_min))
@ -5024,7 +5024,19 @@ void ObjectFileMachO::GetAllArchSpecs(const llvm::MachO::mach_header &header,
auto triple = base_triple;
triple.setOSName(os.str());
os_name.clear();
// Disambiguate legacy simulator platforms.
if (load_cmd.cmd != llvm::MachO::LC_VERSION_MIN_MACOSX &&
(base_triple.getArch() == llvm::Triple::x86_64 ||
base_triple.getArch() == llvm::Triple::x86)) {
// The combination of legacy LC_VERSION_MIN load command and
// x86 architecture always indicates a simulator environment.
// The combination of LC_VERSION_MIN and arm architecture only
// appears for native binaries. Back-deploying simulator
// binaries on Apple Silicon Macs use the modern unambigous
// LC_BUILD_VERSION load commands; no special handling required.
triple.setEnvironment(llvm::Triple::Simulator);
}
add_triple(triple);
break;
}

View File

@ -1057,20 +1057,6 @@ bool ArchSpec::IsEqualTo(const ArchSpec &rhs, bool exact_match) const {
return true;
}
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;
}
// x86_64-apple-ios-macabi and x86_64-apple-ios are not compatible.
if (lhs_triple_os == llvm::Triple::IOS &&
rhs_triple_os == llvm::Triple::IOS &&
@ -1079,6 +1065,19 @@ bool ArchSpec::IsEqualTo(const ArchSpec &rhs, bool exact_match) const {
lhs_triple_env != rhs_triple_env)
return false;
if (lhs_triple_os != rhs_triple_os) {
const bool lhs_os_specified = TripleOSWasSpecified();
const bool rhs_os_specified = rhs.TripleOSWasSpecified();
// If both OS types are specified and different, fail.
if (lhs_os_specified && rhs_os_specified)
return false;
// If the pair of os+env is both unspecified, match any other os+env combo.
if (!exact_match && ((!lhs_os_specified && !lhs_triple.hasEnvironment()) ||
(!rhs_os_specified && !rhs_triple.hasEnvironment())))
return true;
}
return IsCompatibleEnvironment(lhs_triple_env, rhs_triple_env);
}

View File

@ -6,7 +6,6 @@ import json
import unittest2
@skipIfDarwin # rdar://problem/64552748
class TestSimulatorPlatformLaunching(TestBase):
mydir = TestBase.compute_mydir(__file__)
@ -41,14 +40,16 @@ class TestSimulatorPlatformLaunching(TestBase):
def run_with(self, arch, os, vers, env, expected_load_command):
self.build(dictionary={'TRIPLE': arch+'-apple-'+os+vers+'-'+env})
env_list = [env] if env else []
triple = '-'.join([arch, 'apple', os + vers] + env_list)
self.build(dictionary={'TRIPLE': triple})
self.check_load_commands(expected_load_command)
log = self.getBuildArtifact('packets.log')
self.expect("log enable gdb-remote packets -f "+log)
lldbutil.run_to_source_breakpoint(self, "break here",
lldb.SBFileSpec("hello.c"))
self.expect('image list -b -t',
patterns=['a\.out '+arch+'-apple-'+os+vers+'.*-'+env])
triple_re = '-'.join([arch, 'apple', os + vers+'.*'] + env_list)
self.expect('image list -b -t', patterns=['a\.out '+triple_re])
self.check_debugserver(log, os+env, vers)
@skipUnlessDarwin
@ -101,6 +102,13 @@ class TestSimulatorPlatformLaunching(TestBase):
# macOS, however, these legacy load commands are never generated.
#
@skipUnlessDarwin
@skipIfDarwinEmbedded
def test_lc_version_min_macosx(self):
"""Test running a back-deploying non-simulator MacOS X binary"""
self.run_with(arch=self.getArchitecture(),
os='macosx', vers='10.9', env='',
expected_load_command='LC_VERSION_MIN_MACOSX')
@skipUnlessDarwin
@skipIfDarwinEmbedded
@apple_simulator_test('iphone')

View File

@ -305,6 +305,25 @@ TEST(ArchSpecTest, Compatibility) {
ArchSpec B("x86_64-apple-ios-simulator");
ASSERT_FALSE(A.IsExactMatch(B));
ASSERT_FALSE(A.IsCompatibleMatch(B));
ASSERT_FALSE(B.IsExactMatch(A));
ASSERT_FALSE(B.IsCompatibleMatch(A));
}
{
ArchSpec A("x86_64-apple-ios");
ArchSpec B("x86_64-apple-ios-simulator");
ASSERT_FALSE(A.IsExactMatch(B));
ASSERT_FALSE(A.IsCompatibleMatch(B));
ASSERT_FALSE(B.IsExactMatch(A));
ASSERT_FALSE(B.IsCompatibleMatch(A));
}
{
// FIXME: This is surprisingly not equivalent to "x86_64-*-*".
ArchSpec A("x86_64");
ArchSpec B("x86_64-apple-ios-simulator");
ASSERT_FALSE(A.IsExactMatch(B));
ASSERT_TRUE(A.IsCompatibleMatch(B));
ASSERT_FALSE(B.IsExactMatch(A));
ASSERT_TRUE(B.IsCompatibleMatch(A));
}
{
ArchSpec A("arm64-apple-ios");