Skip to content

Commit 7e9bab6

Browse files
committed
Fix debugserver's qProcessInfo reporting of maccatalyst binaries
This patch is similar in spirit to https://reviews.llvm.org/D84480, but does the maccatalyst/macosx disambiguation. I also took the opportunity to factor out the gdb-remote packet log scanning used by several testcases into lldbutil functions. rdar://problem/66059257 Differential Revision: https://reviews.llvm.org/D84576
1 parent 06d4257 commit 7e9bab6

File tree

16 files changed

+252
-122
lines changed

16 files changed

+252
-122
lines changed

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1458,3 +1458,40 @@ def wait_for_file_on_target(testcase, file_path, max_attempts=6):
14581458
(file_path, max_attempts))
14591459

14601460
return read_file_on_target(testcase, file_path)
1461+
1462+
def packetlog_get_process_info(log):
1463+
"""parse a gdb-remote packet log file and extract the response to qProcessInfo"""
1464+
process_info = dict()
1465+
with open(log, "r") as logfile:
1466+
process_info_ostype = None
1467+
expect_process_info_response = False
1468+
for line in logfile:
1469+
if expect_process_info_response:
1470+
for pair in line.split(';'):
1471+
keyval = pair.split(':')
1472+
if len(keyval) == 2:
1473+
process_info[keyval[0]] = keyval[1]
1474+
break
1475+
if 'send packet: $qProcessInfo#' in line:
1476+
expect_process_info_response = True
1477+
return process_info
1478+
1479+
def packetlog_get_dylib_info(log):
1480+
"""parse a gdb-remote packet log file and extract the *last* response to jGetLoadedDynamicLibrariesInfos"""
1481+
import json
1482+
dylib_info = None
1483+
with open(log, "r") as logfile:
1484+
dylib_info = None
1485+
expect_dylib_info_response = False
1486+
for line in logfile:
1487+
if expect_dylib_info_response:
1488+
while line[0] != '$':
1489+
line = line[1:]
1490+
line = line[1:]
1491+
# Unescape '}'.
1492+
dylib_info = json.loads(line.replace('}]','}')[:-4])
1493+
expect_dylib_info_response = False
1494+
if 'send packet: $jGetLoadedDynamicLibrariesInfos:{' in line:
1495+
expect_dylib_info_response = True
1496+
1497+
return dylib_info
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
C_SOURCES := main.c
2+
3+
TRIPLE := $(ARCH)-apple-ios13.0-macabi
4+
CFLAGS_EXTRAS := -target $(TRIPLE)
5+
6+
# FIXME: rdar://problem/54986190
7+
# There is a Clang driver change missing on llvm.org.
8+
override CC=xcrun clang
9+
10+
include Makefile.rules
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import lldb
2+
from lldbsuite.test.lldbtest import *
3+
from lldbsuite.test.decorators import *
4+
import lldbsuite.test.lldbutil as lldbutil
5+
import os
6+
import unittest2
7+
8+
9+
class TestMacCatalyst(TestBase):
10+
11+
mydir = TestBase.compute_mydir(__file__)
12+
13+
@skipIf(macos_version=["<", "10.15"])
14+
@skipUnlessDarwin
15+
@skipIfDarwinEmbedded
16+
@skipIfReproducer # This is hitting https://bugs.python.org/issue22393
17+
def test_macabi(self):
18+
"""Test the x86_64-apple-ios-macabi target linked against a macos dylib"""
19+
self.build()
20+
log = self.getBuildArtifact('packets.log')
21+
self.expect("log enable gdb-remote packets -f "+log)
22+
lldbutil.run_to_source_breakpoint(self, "break here",
23+
lldb.SBFileSpec('main.c'))
24+
self.expect("image list -t -b",
25+
patterns=[self.getArchitecture() +
26+
r'.*-apple-ios.*-macabi a\.out'])
27+
self.expect("fr v s", "Hello macCatalyst")
28+
self.expect("p s", "Hello macCatalyst")
29+
self.check_debugserver(log)
30+
31+
def check_debugserver(self, log):
32+
"""scan the debugserver packet log"""
33+
process_info = lldbutil.packetlog_get_process_info(log)
34+
self.assertTrue('ostype' in process_info)
35+
self.assertEquals(process_info['ostype'], 'maccatalyst')
36+
37+
aout_info = None
38+
dylib_info = lldbutil.packetlog_get_dylib_info(log)
39+
for image in dylib_info['images']:
40+
if image['pathname'].endswith('a.out'):
41+
aout_info = image
42+
self.assertTrue(aout_info)
43+
self.assertEquals(aout_info['min_version_os_name'], 'maccatalyst')
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
int main() {
2+
const char *s = "Hello macCatalyst!";
3+
return 0; // break here
4+
}

lldb/test/API/macosx/macabi/Makefile renamed to lldb/test/API/macosx/macCatalystAppMacOSFramework/Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
C_SOURCES := main.c
22
LD_EXTRAS := -L. -lfoo
33

4-
TRIPLE := x86_64-apple-ios13.0-macabi
4+
TRIPLE := $(ARCH)-apple-ios13.0-macabi
55
CFLAGS_EXTRAS := -target $(TRIPLE)
66

7+
# FIXME: rdar://problem/54986190
8+
override CC=xcrun clang
9+
710
all: libfoo.dylib a.out
811

912
libfoo.dylib: foo.c
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import lldb
2+
from lldbsuite.test.lldbtest import *
3+
from lldbsuite.test.decorators import *
4+
import lldbsuite.test.lldbutil as lldbutil
5+
import os
6+
import unittest2
7+
8+
9+
class TestMacCatalystAppWithMacOSFramework(TestBase):
10+
11+
mydir = TestBase.compute_mydir(__file__)
12+
13+
@skipIf(macos_version=["<", "10.15"])
14+
@skipUnlessDarwin
15+
@skipIfDarwinEmbedded
16+
# There is a Clang driver change missing on llvm.org.
17+
@expectedFailureAll(bugnumber="rdar://problem/54986190>")
18+
@skipIfReproducer # This is hitting https://bugs.python.org/issue22393
19+
def test(self):
20+
"""Test the x86_64-apple-ios-macabi target linked against a macos dylib"""
21+
self.build()
22+
log = self.getBuildArtifact('packets.log')
23+
self.expect("log enable gdb-remote packets -f "+log)
24+
lldbutil.run_to_source_breakpoint(self, "break here",
25+
lldb.SBFileSpec('main.c'))
26+
arch = self.getArchitecture()
27+
self.expect("image list -t -b",
28+
patterns=[arch + r'.*-apple-ios.*-macabi a\.out',
29+
arch + r'.*-apple-macosx.* libfoo.dylib[^(]'])
30+
self.expect("fr v s", "Hello macCatalyst")
31+
self.expect("p s", "Hello macCatalyst")
32+
self.check_debugserver(log)
33+
34+
def check_debugserver(self, log):
35+
"""scan the debugserver packet log"""
36+
process_info = lldbutil.packetlog_get_process_info(log)
37+
self.assertTrue('ostype' in process_info)
38+
self.assertEquals(process_info['ostype'], 'maccatalyst')
39+
40+
aout_info = None
41+
libfoo_info = None
42+
dylib_info = lldbutil.packetlog_get_dylib_info(log)
43+
for image in dylib_info['images']:
44+
if image['pathname'].endswith('a.out'):
45+
aout_info = image
46+
if image['pathname'].endswith('libfoo.dylib'):
47+
libfoo_info = image
48+
self.assertTrue(aout_info)
49+
self.assertTrue(libfoo_info)
50+
self.assertEquals(aout_info['min_version_os_name'], 'maccatalyst')
51+
self.assertEquals(libfoo_info['min_version_os_name'], 'macosx')
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#include "foo.h"
22
int main() {
3-
const char *s = "Hello MacABI!";
3+
const char *s = "Hello macCatalyst!";
44
return foo(); // break here
55
}

lldb/test/API/macosx/macabi/TestMacABImacOSFramework.py

Lines changed: 0 additions & 28 deletions
This file was deleted.

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

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -25,30 +25,10 @@ def check_load_commands(self, expected_load_command):
2525

2626
def check_debugserver(self, log, expected_platform, expected_version):
2727
"""scan the debugserver packet log"""
28-
logfile = open(log, "r")
29-
dylib_info = None
30-
process_info_ostype = None
31-
expect_dylib_info_response = False
32-
expect_process_info_response = False
33-
for line in logfile:
34-
if expect_dylib_info_response:
35-
while line[0] != '$':
36-
line = line[1:]
37-
line = line[1:]
38-
# Unescape '}'.
39-
dylib_info = json.loads(line.replace('}]','}')[:-4])
40-
expect_dylib_info_response = False
41-
if 'send packet: $jGetLoadedDynamicLibrariesInfos:{' in line:
42-
expect_dylib_info_response = True
43-
if expect_process_info_response:
44-
for pair in line.split(';'):
45-
keyval = pair.split(':')
46-
if len(keyval) == 2 and keyval[0] == 'ostype':
47-
process_info_ostype = keyval[1]
48-
if 'send packet: $qProcessInfo#' in line:
49-
expect_process_info_response = True
50-
51-
self.assertEquals(process_info_ostype, expected_platform)
28+
process_info = lldbutil.packetlog_get_process_info(log)
29+
self.assertTrue('ostype' in process_info)
30+
self.assertEquals(process_info['ostype'], expected_platform)
31+
dylib_info = lldbutil.packetlog_get_dylib_info(log)
5232
self.assertTrue(dylib_info)
5333
aout_info = None
5434
for image in dylib_info['images']:

lldb/tools/debugserver/source/DNB.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1418,19 +1418,20 @@ nub_bool_t DNBProcessSharedLibrariesUpdated(nub_process_t pid) {
14181418
return false;
14191419
}
14201420

1421-
const char *DNBGetDeploymentInfo(nub_process_t pid,
1422-
const struct load_command& lc,
1421+
const char *DNBGetDeploymentInfo(nub_process_t pid, bool is_executable,
1422+
const struct load_command &lc,
14231423
uint64_t load_command_address,
1424-
uint32_t& major_version,
1425-
uint32_t& minor_version,
1426-
uint32_t& patch_version) {
1424+
uint32_t &major_version,
1425+
uint32_t &minor_version,
1426+
uint32_t &patch_version) {
14271427
MachProcessSP procSP;
14281428
if (GetProcessSP(pid, procSP)) {
14291429
// FIXME: This doesn't return the correct result when xctest (a
14301430
// macOS binary) is loaded with the macCatalyst dyld platform
14311431
// override. The image info corrects for this, but qProcessInfo
14321432
// will return what is in the binary.
1433-
auto info = procSP->GetDeploymentInfo(lc, load_command_address);
1433+
auto info =
1434+
procSP->GetDeploymentInfo(lc, load_command_address, is_executable);
14341435
major_version = info.major_version;
14351436
minor_version = info.minor_version;
14361437
patch_version = info.patch_version;
@@ -1439,7 +1440,6 @@ const char *DNBGetDeploymentInfo(nub_process_t pid,
14391440
return nullptr;
14401441
}
14411442

1442-
14431443
// Get the current shared library information for a process. Only return
14441444
// the shared libraries that have changed since the last shared library
14451445
// state changed event if only_changed is non-zero.

lldb/tools/debugserver/source/DNB.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,12 @@ nub_bool_t DNBProcessSharedLibrariesUpdated(nub_process_t pid) DNB_EXPORT;
128128
nub_size_t
129129
DNBProcessGetSharedLibraryInfo(nub_process_t pid, nub_bool_t only_changed,
130130
DNBExecutableImageInfo **image_infos) DNB_EXPORT;
131-
const char *DNBGetDeploymentInfo(nub_process_t pid,
132-
const struct load_command& lc,
131+
const char *DNBGetDeploymentInfo(nub_process_t pid, bool is_executable,
132+
const struct load_command &lc,
133133
uint64_t load_command_address,
134-
uint32_t& major_version,
135-
uint32_t& minor_version,
136-
uint32_t& patch_version);
134+
uint32_t &major_version,
135+
uint32_t &minor_version,
136+
uint32_t &patch_version);
137137
nub_bool_t DNBProcessSetNameToAddressCallback(nub_process_t pid,
138138
DNBCallbackNameToAddress callback,
139139
void *baton) DNB_EXPORT;

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,15 +241,24 @@ class MachProcess {
241241
uint32_t patch_version = 0;
242242
};
243243
DeploymentInfo GetDeploymentInfo(const struct load_command &,
244-
uint64_t load_command_address);
244+
uint64_t load_command_address,
245+
bool is_executable);
245246
static const char *GetPlatformString(unsigned char platform);
246247
bool GetMachOInformationFromMemory(uint32_t platform,
247248
nub_addr_t mach_o_header_addr,
248249
int wordsize,
249250
struct mach_o_information &inf);
250251
JSONGenerator::ObjectSP FormatDynamicLibrariesIntoJSON(
251252
const std::vector<struct binary_image_information> &image_infos);
252-
uint32_t GetAllLoadedBinariesViaDYLDSPI(
253+
/// Get the runtime platform from DYLD via SPI.
254+
uint32_t GetProcessPlatformViaDYLDSPI();
255+
/// Use the dyld SPI present in macOS 10.12, iOS 10, tvOS 10,
256+
/// watchOS 3 and newer to get the load address, uuid, and filenames
257+
/// of all the libraries. This only fills in those three fields in
258+
/// the 'struct binary_image_information' - call
259+
/// GetMachOInformationFromMemory to fill in the mach-o header/load
260+
/// command details.
261+
void GetAllLoadedBinariesViaDYLDSPI(
253262
std::vector<struct binary_image_information> &image_infos);
254263
JSONGenerator::ObjectSP GetLoadedDynamicLibrariesInfos(
255264
nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count);

0 commit comments

Comments
 (0)