Skip to content

Commit 10f3e50

Browse files
committed
Improve the detection of iOS/tvOS/watchOS simulator binaries in
debugserver and lldb This patch improves the heuristics for correctly identifying simulator binaries on Darwin and adds support for simulators running on Apple Silicon. rdar://problem/64046344 Differential Revision: https://reviews.llvm.org/D82616 (cherry picked from commit 0da0437)
1 parent 4ebea46 commit 10f3e50

File tree

5 files changed

+296
-98
lines changed

5 files changed

+296
-98
lines changed

lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -680,11 +680,16 @@ bool DynamicLoaderDarwin::AddModulesUsingImageInfos(
680680
loaded_module_list.AppendIfNeeded(image_module_sp);
681681
}
682682

683-
// macCataylst support:
684-
// Update the module's platform with the DYLD info.
683+
// To support macCatalyst and legacy iOS simulator,
684+
// update the module's platform with the DYLD info.
685685
ArchSpec dyld_spec = image_infos[idx].GetArchitecture();
686-
if (dyld_spec.GetTriple().getOS() == llvm::Triple::IOS &&
687-
dyld_spec.GetTriple().getEnvironment() == llvm::Triple::MacABI)
686+
auto &dyld_triple = dyld_spec.GetTriple();
687+
if ((dyld_triple.getEnvironment() == llvm::Triple::MacABI &&
688+
dyld_triple.getOS() == llvm::Triple::IOS) ||
689+
(dyld_triple.getEnvironment() == llvm::Triple::Simulator &&
690+
(dyld_triple.getOS() == llvm::Triple::IOS ||
691+
dyld_triple.getOS() == llvm::Triple::TvOS ||
692+
dyld_triple.getOS() == llvm::Triple::WatchOS)))
688693
image_module_sp->MergeArchitecture(dyld_spec);
689694
}
690695
}
@@ -747,13 +752,23 @@ lldb_private::ArchSpec DynamicLoaderDarwin::ImageInfo::GetArchitecture() const {
747752
// Update the module's platform with the DYLD info.
748753
lldb_private::ArchSpec arch_spec(lldb_private::eArchTypeMachO, header.cputype,
749754
header.cpusubtype);
750-
if (os_type == llvm::Triple::IOS && os_env == llvm::Triple::MacABI) {
751-
llvm::Triple triple(llvm::Twine("x86_64-apple-ios") + min_version_os_sdk +
752-
"-macabi");
755+
if (os_env == llvm::Triple::MacABI && os_type == llvm::Triple::IOS) {
756+
llvm::Triple triple(llvm::Twine(arch_spec.GetArchitectureName()) +
757+
"-apple-ios" + min_version_os_sdk + "-macabi");
753758
ArchSpec maccatalyst_spec(triple);
754759
if (arch_spec.IsCompatibleMatch(maccatalyst_spec))
755760
arch_spec.MergeFrom(maccatalyst_spec);
756761
}
762+
if (os_env == llvm::Triple::Simulator &&
763+
(os_type == llvm::Triple::IOS || os_type == llvm::Triple::TvOS ||
764+
os_type == llvm::Triple::WatchOS)) {
765+
llvm::Triple triple(llvm::Twine(arch_spec.GetArchitectureName()) +
766+
"-apple-" + llvm::Triple::getOSTypeName(os_type) +
767+
min_version_os_sdk + "-simulator");
768+
ArchSpec sim_spec(triple);
769+
if (arch_spec.IsCompatibleMatch(sim_spec))
770+
arch_spec.MergeFrom(sim_spec);
771+
}
757772
return arch_spec;
758773
}
759774

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import lldb
2+
from lldbsuite.test.lldbtest import *
3+
from lldbsuite.test.decorators import *
4+
import lldbsuite.test.lldbutil as lldbutil
5+
import json
6+
import unittest2
7+
8+
9+
@skipIfDarwin # rdar://problem/64552748
10+
class TestSimulatorPlatformLaunching(TestBase):
11+
12+
mydir = TestBase.compute_mydir(__file__)
13+
NO_DEBUG_INFO_TESTCASE = True
14+
15+
def check_load_commands(self, expected_load_command):
16+
"""sanity check the built binary for the expected number of load commands"""
17+
load_cmds = subprocess.check_output(
18+
['otool', '-l', self.getBuildArtifact()]
19+
).decode("utf-8")
20+
found = 0
21+
for line in load_cmds.split('\n'):
22+
if expected_load_command in line:
23+
found += 1
24+
self.assertEquals(found, 1, "wrong load command")
25+
26+
27+
def run_with(self, arch, os, env, expected_load_command):
28+
self.build(dictionary={'TRIPLE': arch+'-apple-'+os+'-'+env})
29+
lldbutil.run_to_source_breakpoint(self, "break here",
30+
lldb.SBFileSpec("hello.c"))
31+
self.check_load_commands(expected_load_command)
32+
self.expect('image list -b -t',
33+
patterns=['a\.out '+arch+'-apple-'+os+'.*-'+env])
34+
35+
@skipUnlessDarwin
36+
@skipIfDarwinEmbedded
37+
@apple_simulator_test('iphone')
38+
def test_ios(self):
39+
"""Test running an iOS simulator binary"""
40+
self.run_with(arch=self.getArchitecture(),
41+
os='ios', env='simulator',
42+
expected_load_command='LC_BUILD_VERSION')
43+
44+
@skipUnlessDarwin
45+
@skipIfDarwinEmbedded
46+
@apple_simulator_test('appletv')
47+
def test_tvos(self):
48+
"""Test running an tvOS simulator binary"""
49+
self.run_with(arch=self.getArchitecture(),
50+
os='tvos', env='simulator',
51+
expected_load_command='LC_BUILD_VERSION')
52+
53+
@skipUnlessDarwin
54+
@skipIfDarwinEmbedded
55+
@apple_simulator_test('watch')
56+
@skipIfDarwin # rdar://problem/64552748
57+
@skipIf(archs=['arm64','arm64e'])
58+
def test_watchos_i386(self):
59+
"""Test running a 32-bit watchOS simulator binary"""
60+
self.run_with(arch='i386',
61+
os='watchos', env='simulator',
62+
expected_load_command='LC_BUILD_VERSION')
63+
64+
@skipUnlessDarwin
65+
@skipIfDarwinEmbedded
66+
@apple_simulator_test('watch')
67+
@skipIfDarwin # rdar://problem/64552748
68+
@skipIf(archs=['i386','x86_64'])
69+
def test_watchos_armv7k(self):
70+
"""Test running a 32-bit watchOS simulator binary"""
71+
self.run_with(arch='armv7k',
72+
os='watchos', env='simulator',
73+
expected_load_command='LC_BUILD_VERSION')
74+
75+
76+
#
77+
# Back-deployment tests.
78+
#
79+
# Older Mach-O versions used less expressive load commands, such
80+
# as LC_VERSION_MIN_IPHONEOS that wouldn't distinguish between ios
81+
# and ios-simulator. When targeting a simulator on Apple Silicon
82+
# macOS, however, these legacy load commands are never generated.
83+
#
84+
85+
@skipUnlessDarwin
86+
@skipIfDarwinEmbedded
87+
@apple_simulator_test('iphone')
88+
@skipIf(archs=['arm64','arm64e'])
89+
def test_lc_version_min_iphoneos(self):
90+
"""Test running a back-deploying iOS simulator binary
91+
with a legacy iOS load command"""
92+
self.run_with(arch=self.getArchitecture(),
93+
os='ios11.0', env='simulator',
94+
expected_load_command='LC_VERSION_MIN_IPHONEOS')
95+
96+
@skipUnlessDarwin
97+
@skipIfDarwinEmbedded
98+
@apple_simulator_test('iphone')
99+
@skipIf(archs=['i386','x86_64'])
100+
def test_ios_backdeploy_apple_silicon(self):
101+
"""Test running a back-deploying iOS simulator binary"""
102+
self.run_with(arch=self.getArchitecture(),
103+
os='ios11.0', env='simulator',
104+
expected_load_command='LC_BUILD_VERSION')
105+
106+
@skipUnlessDarwin
107+
@skipIfDarwinEmbedded
108+
@apple_simulator_test('appletv')
109+
@skipIf(archs=['arm64','arm64e'])
110+
def test_lc_version_min_tvos(self):
111+
"""Test running a back-deploying tvOS simulator binary
112+
with a legacy tvOS load command"""
113+
self.run_with(arch=self.getArchitecture(),
114+
os='tvos11.0', env='simulator',
115+
expected_load_command='LC_VERSION_MIN_TVOS')
116+
117+
@skipUnlessDarwin
118+
@skipIfDarwinEmbedded
119+
@apple_simulator_test('appletv')
120+
@skipIf(archs=['i386','x86_64'])
121+
def test_tvos_backdeploy_apple_silicon(self):
122+
"""Test running a back-deploying tvOS simulator binary"""
123+
self.run_with(arch=self.getArchitecture(),
124+
os='tvos11.0', env='simulator',
125+
expected_load_command='LC_BUILD_VERSION')
126+
127+
@skipUnlessDarwin
128+
@skipIfDarwinEmbedded
129+
@apple_simulator_test('watch')
130+
@skipIf(archs=['arm64','arm64e'])
131+
@skipIfDarwin # rdar://problem/64552748
132+
def test_lc_version_min_watchos(self):
133+
"""Test running a back-deploying watchOS simulator binary
134+
with a legacy watchOS load command"""
135+
self.run_with(arch='i386',
136+
os='watchos4.0', env='simulator',
137+
expected_load_command='LC_VERSION_MIN_WATCHOS')
138+
139+
@skipUnlessDarwin
140+
@skipIfDarwinEmbedded
141+
@apple_simulator_test('watch')
142+
@skipIf(archs=['arm64','arm64e'])
143+
@skipIfDarwin # rdar://problem/64552748
144+
def test_watchos_backdeploy_apple_silicon(self):
145+
"""Test running a back-deploying watchOS simulator binary"""
146+
self.run_with(arch='armv7k',
147+
os='watchos4.0', env='simulator',
148+
expected_load_command='LC_BUILD_VERSION')

lldb/tools/debugserver/source/DNB.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,10 +1391,14 @@ const char *DNBGetDeploymentInfo(nub_process_t pid,
13911391
uint32_t& minor_version,
13921392
uint32_t& patch_version) {
13931393
MachProcessSP procSP;
1394-
if (GetProcessSP(pid, procSP))
1395-
return procSP->GetDeploymentInfo(lc, load_command_address,
1396-
major_version, minor_version,
1397-
patch_version);
1394+
if (GetProcessSP(pid, procSP)) {
1395+
// FIXME: This doesn't correct for older ios simulator and macCatalyst.
1396+
auto info = procSP->GetDeploymentInfo(lc, load_command_address);
1397+
major_version = info.major_version;
1398+
minor_version = info.minor_version;
1399+
patch_version = info.patch_version;
1400+
return procSP->GetPlatformString(info.platform);
1401+
}
13981402
return nullptr;
13991403
}
14001404

lldb/tools/debugserver/source/MacOSX/MachProcess.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -230,10 +230,22 @@ class MachProcess {
230230
uint64_t plo_pthread_tsd_base_address_offset,
231231
uint64_t plo_pthread_tsd_base_offset,
232232
uint64_t plo_pthread_tsd_entry_size);
233-
const char *
234-
GetDeploymentInfo(const struct load_command&, uint64_t load_command_address,
235-
uint32_t& major_version, uint32_t& minor_version,
236-
uint32_t& patch_version);
233+
234+
struct DeploymentInfo {
235+
DeploymentInfo() = default;
236+
operator bool() { return platform > 0; }
237+
/// The Mach-O platform type;
238+
unsigned char platform = 0;
239+
/// Pre-LC_BUILD_VERSION files don't disambiguate between ios and ios
240+
/// simulator.
241+
bool maybe_simulator = false;
242+
uint32_t major_version = 0;
243+
uint32_t minor_version = 0;
244+
uint32_t patch_version = 0;
245+
};
246+
DeploymentInfo GetDeploymentInfo(const struct load_command &,
247+
uint64_t load_command_address);
248+
static const char *GetPlatformString(unsigned char platform);
237249
bool GetMachOInformationFromMemory(uint32_t platform,
238250
nub_addr_t mach_o_header_addr,
239251
int wordsize,

0 commit comments

Comments
 (0)