Skip to content

Commit 7cac42a

Browse files
committed
Run a.out in simulator and find it
1 parent 771febc commit 7cac42a

File tree

6 files changed

+160
-73
lines changed

6 files changed

+160
-73
lines changed

lldb/packages/Python/lldbsuite/test/lldbutil.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
# System modules
88
import errno
99
import io
10+
import json
1011
import os
1112
import re
1213
import sys
@@ -1704,3 +1705,89 @@ def packetlog_get_dylib_info(log):
17041705
expect_dylib_info_response = True
17051706

17061707
return dylib_info
1708+
1709+
1710+
# ========================
1711+
# Utilities for simulators
1712+
# ========================
1713+
1714+
1715+
def get_latest_apple_simulator(platform_name, log=None):
1716+
# Run simctl to list all simulators
1717+
cmd = ["xcrun", "simctl", "list", "-j", "devices"]
1718+
cmd_str = " ".join(cmd)
1719+
if log:
1720+
log(cmd_str)
1721+
sim_devices_str = subprocess.check_output(cmd).decode("utf-8")
1722+
sim_devices = json.loads(sim_devices_str)["devices"]
1723+
1724+
# Find an available simulator for the requested platform
1725+
device_uuid = None
1726+
device_runtime = None
1727+
for simulator in sim_devices:
1728+
if isinstance(simulator, dict):
1729+
runtime = simulator["name"]
1730+
devices = simulator["devices"]
1731+
else:
1732+
runtime = simulator
1733+
devices = sim_devices[simulator]
1734+
if not platform_name in runtime.lower():
1735+
continue
1736+
for device in devices:
1737+
if "availability" in device and device["availability"] != "(available)":
1738+
continue
1739+
if "isAvailable" in device and not device["isAvailable"]:
1740+
continue
1741+
if device_runtime and runtime < device_runtime:
1742+
continue
1743+
device_uuid = device["udid"]
1744+
device_runtime = runtime
1745+
# Stop searching in this runtime
1746+
break
1747+
1748+
return device_uuid
1749+
1750+
1751+
def launch_exe_in_apple_simulator(
1752+
device_uuid,
1753+
exe_path,
1754+
exe_args=[],
1755+
stderr_lines_to_read=0,
1756+
stderr_patterns=[],
1757+
log=None,
1758+
):
1759+
exe_path = os.path.realpath(exe_path)
1760+
cmd = [
1761+
"xcrun",
1762+
"simctl",
1763+
"spawn",
1764+
"-s",
1765+
device_uuid,
1766+
exe_path,
1767+
] + exe_args
1768+
if log:
1769+
log(" ".join(cmd))
1770+
sim_launcher = subprocess.Popen(cmd, stderr=subprocess.PIPE)
1771+
1772+
# Read stderr to try to find matches.
1773+
# Each pattern will return the value of group[1] of the first match in the stderr.
1774+
# Will read at most stderr_lines_to_read lines.
1775+
# Will early terminate when all matches have been found.
1776+
total_patterns = len(stderr_patterns)
1777+
matches_found = 0
1778+
matched_strings = [None] * total_patterns
1779+
for _ in range(0, stderr_lines_to_read):
1780+
stderr = sim_launcher.stderr.readline().decode("utf-8")
1781+
if not stderr:
1782+
continue
1783+
for i, pattern in enumerate(stderr_patterns):
1784+
if matched_strings[i] is not None:
1785+
continue
1786+
match = re.match(pattern, stderr)
1787+
if match:
1788+
matched_strings[i] = str(match.group(1))
1789+
matches_found += 1
1790+
if matches_found == total_patterns:
1791+
break
1792+
1793+
return exe_path, matched_strings
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1-
C_SOURCES := hello.c
1+
CFLAGS_EXTRAS := -D__STDC_LIMIT_MACROS -D__STDC_FORMAT_MACROS
2+
ENABLE_THREADS := YES
3+
CXX_SOURCES := hello.cpp
4+
MAKE_DSYM := NO
25

36
include Makefile.rules

lldb/test/API/macosx/simulator/TestSimulatorPlatform.py

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,26 +74,46 @@ def run_with(
7474
log = self.getBuildArtifact("packets.log")
7575
self.expect("log enable gdb-remote packets -f " + log)
7676
lldbutil.run_to_source_breakpoint(
77-
self, "break here", lldb.SBFileSpec("hello.c")
77+
self, "break here", lldb.SBFileSpec("hello.cpp")
7878
)
7979
triple_re = "-".join([arch, "apple", os + vers + ".*"] + env_list)
8080
self.expect("image list -b -t", patterns=[r"a\.out " + triple_re])
81+
self.check_debugserver(log, os + env, vers)
82+
8183
if expected_platform is not None:
8284
# Verify the platform name.
83-
self.expect("platform status", patterns=[r"Platform: " + expected_platform])
85+
self.expect(
86+
"platform status",
87+
patterns=[r"Platform: " + expected_platform + "-simulator"],
88+
)
89+
90+
# Launch exe in simulator and verify that `platform process list` can find the process.
91+
# This separate launch is needed because the command ignores processes which are being debugged.
92+
device_udid = lldbutil.get_latest_apple_simulator(
93+
expected_platform, self.trace
94+
)
95+
_, matched_strings = lldbutil.launch_exe_in_apple_simulator(
96+
device_udid,
97+
self.getBuildArtifact("a.out"),
98+
exe_args=[],
99+
stderr_lines_to_read=1, # in hello.cpp, the pid is printed first
100+
stderr_patterns=[r"PID: (.*)"],
101+
log=self.trace,
102+
)
103+
104+
# Make sure we found the PID.
105+
self.assertIsNotNone(matched_strings[0])
106+
pid = int(matched_strings[0])
107+
84108
# Verify that processes on the platform can be listed.
85-
#
86-
# Note: The `Host::FindProcessesImpl()` of some of the Hosts filters out processes which are being debugged.
87-
# (e.g. code for iOS simulator linked below). So we cannot verify that `a.out` is in the process list
88-
# (because its already being debugged by this test).
89-
# https://github.com/llvm/llvm-project/blob/b5dbf8210a57b986b9802304745f4c5c108cf37b/lldb/source/Host/macosx/objcxx/Host.mm#L724
90109
self.expect(
91110
"platform process list",
92111
patterns=[
93-
r"\d+ matching processes were found on \"%s\"" % expected_platform
112+
r"\d+ matching processes were found on \"%s-simulator\""
113+
% expected_platform,
114+
r"%d .+ a.out" % pid,
94115
],
95116
)
96-
self.check_debugserver(log, os + env, vers)
97117

98118
@skipIfAsan
99119
@skipUnlessDarwin
@@ -107,7 +127,7 @@ def test_ios(self):
107127
vers="",
108128
env="simulator",
109129
expected_load_command="LC_BUILD_VERSION",
110-
expected_platform="ios-simulator",
130+
expected_platform="ios",
111131
)
112132

113133
@skipIfAsan

lldb/test/API/macosx/simulator/hello.c

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include <stdio.h>
2+
#include <thread>
3+
#if !defined(_WIN32)
4+
#include <unistd.h>
5+
#endif
6+
7+
static void print_pid() {
8+
#if defined(_WIN32)
9+
fprintf(stderr, "PID: %d\n", ::GetCurrentProcessId());
10+
#else
11+
fprintf(stderr, "PID: %d\n", getpid());
12+
#endif
13+
}
14+
15+
static void sleep() {
16+
std::this_thread::sleep_for(std::chrono::seconds(10));
17+
}
18+
19+
int main(int argc, char **argv) {
20+
print_pid();
21+
puts("break here\n");
22+
sleep();
23+
return 0;
24+
}

lldb/test/API/tools/lldb-server/TestAppleSimulatorOSType.py

Lines changed: 15 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -14,40 +14,12 @@ class TestAppleSimulatorOSType(gdbremote_testcase.GdbRemoteTestCaseBase):
1414
READ_LINES = 10
1515

1616
def check_simulator_ostype(self, sdk, platform_name, arch=platform.machine()):
17-
cmd = ["xcrun", "simctl", "list", "-j", "devices"]
18-
cmd_str = " ".join(cmd)
19-
self.trace(cmd_str)
20-
sim_devices_str = subprocess.check_output(cmd).decode("utf-8")
17+
# Get simulator
18+
deviceUDID = None
2119
try:
22-
sim_devices = json.loads(sim_devices_str)["devices"]
20+
deviceUDID = lldbutil.get_latest_apple_simulator(platform_name, self.trace)
2321
except json.decoder.JSONDecodeError:
24-
self.fail(
25-
"Could not parse '{}' output. Authorization denied?".format(cmd_str)
26-
)
27-
# Find an available simulator for the requested platform
28-
deviceUDID = None
29-
deviceRuntime = None
30-
for simulator in sim_devices:
31-
if isinstance(simulator, dict):
32-
runtime = simulator["name"]
33-
devices = simulator["devices"]
34-
else:
35-
runtime = simulator
36-
devices = sim_devices[simulator]
37-
if not platform_name in runtime.lower():
38-
continue
39-
for device in devices:
40-
if "availability" in device and device["availability"] != "(available)":
41-
continue
42-
if "isAvailable" in device and not device["isAvailable"]:
43-
continue
44-
if deviceRuntime and runtime < deviceRuntime:
45-
continue
46-
deviceUDID = device["udid"]
47-
deviceRuntime = runtime
48-
# Stop searching in this runtime
49-
break
50-
22+
self.fail("Could not parse output. Authorization denied?")
5123
if not deviceUDID:
5224
self.skipTest(
5325
"Could not find a simulator for {} ({})".format(platform_name, arch)
@@ -78,34 +50,20 @@ def check_simulator_ostype(self, sdk, platform_name, arch=platform.machine()):
7850
},
7951
compiler=clang,
8052
)
81-
exe_path = os.path.realpath(self.getBuildArtifact(exe_name))
82-
cmd = [
83-
"xcrun",
84-
"simctl",
85-
"spawn",
86-
"-s",
53+
54+
# Launch the executable in the simulator
55+
exe_path, matched_groups = lldbutil.launch_exe_in_apple_simulator(
8756
deviceUDID,
88-
exe_path,
89-
"print-pid",
90-
"sleep:10",
91-
]
92-
self.trace(" ".join(cmd))
93-
sim_launcher = subprocess.Popen(cmd, stderr=subprocess.PIPE)
94-
# Get the PID from the process output
95-
pid = None
96-
97-
# Read the first READ_LINES to try to find the PID.
98-
for _ in range(0, self.READ_LINES):
99-
stderr = sim_launcher.stderr.readline().decode("utf-8")
100-
if not stderr:
101-
continue
102-
match = re.match(r"PID: (.*)", stderr)
103-
if match:
104-
pid = int(match.group(1))
105-
break
57+
self.getBuildArtifact(exe_name),
58+
["print-pid", "sleep:10"],
59+
self.READ_LINES,
60+
[r"PID: (.*)"],
61+
self.trace,
62+
)
10663

10764
# Make sure we found the PID.
108-
self.assertIsNotNone(pid)
65+
self.assertIsNotNone(matched_groups[0])
66+
pid = int(matched_groups[0])
10967

11068
# Launch debug monitor attaching to the simulated process
11169
server = self.connect_to_debug_monitor(attach_pid=pid)

0 commit comments

Comments
 (0)