Skip to content

Commit e77fce0

Browse files
committedSep 4, 2016
[NFC] Darwin llgs support from Week of Code
This code represents the Week of Code work I did on bringing up lldb-server LLGS support for Darwin. It does not include the Xcode project changes needed, as we don't want to throw that switch until more support is implemented (i.e. this change is inert, no build systems use it yet. I've verified on Ubuntu 16.04, macOS Xcode and macOS cmake builds). This change does some minimal refactoring of code that is shared with the Linux LLGS portion, moving it from NativeProcessLinux into NativeProcessProtocol. That code is also used by NativeProcessDarwin. Current state on Darwin: * Process launching is implemented. (Attach is not). Launching on devices has not yet been tested (FBS/BKS might need a bit of work). * Inferior waitpid monitoring and communication of exit status via MainLoop callback is implemented. * Memory read/write, breakpoints, thread register context, etc. are not yet implemented. This impacts process stop/resume, as the initial launch suspended immediately starts the process up and running because it doesn't know it is supposed to remain stopped. * I implemented the equivalent of MachThreadList as NativeThreadListDarwin, in anticipation that we might want to factor out common parts into NativeThreadList{Protocol} and share some code here. After writing it, though, the fallout from merging Mach Task/Process into a single concept plus some other minor changes makes the whole NativeThreadListDarwin concept nothing more than dead weight. I am likely going to get rid of this class and just manage it directly in NativeProcessDarwin, much like I did for NativeProcessLinux. * There is a stub-out call for starting a STDIO thread. That will go away and adopt the MainLoop pselect-based IOObject reading. I am developing the fully-integrated changes in the following repo, which contains the necessary Xcode bits and the glue that enables lldb-debugserver on a macOS system: https://github.com/tfiala/lldb/tree/llgs-darwin This change also breaks out a few of the lldb-server tests into their own directory, and adds some $qHostInfo tests (not sure why I didn't write those tests back when I initially implemented that on the Linux side). llvm-svn: 280604
1 parent a57d2ca commit e77fce0

35 files changed

+6319
-128
lines changed
 

‎lldb/include/lldb/Host/Debug.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ namespace lldb_private {
201201
{
202202
uint64_t type;
203203
uint32_t data_count;
204-
lldb::addr_t data[2];
204+
lldb::addr_t data[8];
205205
} exception;
206206
} details;
207207
};

‎lldb/include/lldb/Host/common/NativeProcessProtocol.h

+12-6
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,6 @@ namespace lldb_private
3737

3838
public:
3939

40-
// lldb_private::Host calls should be used to launch a process for debugging, and
41-
// then the process should be attached to. When attaching to a process
42-
// lldb_private::Host calls should be used to locate the process to attach to,
43-
// and then this function should be called.
44-
NativeProcessProtocol (lldb::pid_t pid);
45-
4640
virtual ~NativeProcessProtocol ()
4741
{
4842
}
@@ -379,6 +373,12 @@ namespace lldb_private
379373
int m_terminal_fd;
380374
uint32_t m_stop_id;
381375

376+
// lldb_private::Host calls should be used to launch a process for debugging, and
377+
// then the process should be attached to. When attaching to a process
378+
// lldb_private::Host calls should be used to locate the process to attach to,
379+
// and then this function should be called.
380+
NativeProcessProtocol (lldb::pid_t pid);
381+
382382
// -----------------------------------------------------------
383383
// Internal interface for state handling
384384
// -----------------------------------------------------------
@@ -415,6 +415,12 @@ namespace lldb_private
415415
NativeThreadProtocolSP
416416
GetThreadByIDUnlocked (lldb::tid_t tid);
417417

418+
// -----------------------------------------------------------
419+
// Static helper methods for derived classes.
420+
// -----------------------------------------------------------
421+
static Error
422+
ResolveProcessArchitecture(lldb::pid_t pid, ArchSpec &arch);
423+
418424
private:
419425

420426
void

‎lldb/include/lldb/lldb-private-forward.h

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ namespace lldb_private
2424
class NativeProcessProtocol;
2525
class NativeRegisterContext;
2626
class NativeThreadProtocol;
27+
class ResumeActionList;
2728
class UnixSignals;
2829

2930
// ---------------------------------------------------------------

‎lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteProcessInfo.py

+17
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,13 @@ def test_qProcessInfo_contains_cputype_cpusubtype_debugserver_darwin(self):
155155
self.build()
156156
self.qProcessInfo_contains_keys(set(['cputype', 'cpusubtype']))
157157

158+
@skipUnlessDarwin
159+
@llgs_test
160+
def test_qProcessInfo_contains_cputype_cpusubtype_llgs_darwin(self):
161+
self.init_llgs_test()
162+
self.build()
163+
self.qProcessInfo_contains_keys(set(['cputype', 'cpusubtype']))
164+
158165
@skipUnlessPlatform(["linux"])
159166
@llgs_test
160167
def test_qProcessInfo_contains_triple_llgs_linux(self):
@@ -172,6 +179,16 @@ def test_qProcessInfo_does_not_contain_triple_debugserver_darwin(self):
172179
# for the remote Host and Process.
173180
self.qProcessInfo_does_not_contain_keys(set(['triple']))
174181

182+
@skipUnlessDarwin
183+
@llgs_test
184+
def test_qProcessInfo_does_not_contain_triple_llgs_darwin(self):
185+
self.init_llgs_test()
186+
self.build()
187+
# We don't expect to see triple on darwin. If we do, we'll prefer triple
188+
# to cputype/cpusubtype and skip some darwin-based ProcessGDBRemote ArchSpec setup
189+
# for the remote Host and Process.
190+
self.qProcessInfo_does_not_contain_keys(set(['triple']))
191+
175192
@skipUnlessPlatform(["linux"])
176193
@llgs_test
177194
def test_qProcessInfo_does_not_contain_cputype_cpusubtype_llgs_linux(self):

‎lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py

-95
Original file line numberDiff line numberDiff line change
@@ -97,101 +97,6 @@ def test_list_threads_in_stop_reply_supported_llgs(self):
9797
self.init_llgs_test()
9898
self.list_threads_in_stop_reply_supported()
9999

100-
def install_and_create_launch_args(self):
101-
exe_path = os.path.abspath('a.out')
102-
if not lldb.remote_platform:
103-
return [exe_path]
104-
remote_path = lldbutil.append_to_process_working_directory(os.path.basename(exe_path))
105-
remote_file_spec = lldb.SBFileSpec(remote_path, False)
106-
err = lldb.remote_platform.Install(lldb.SBFileSpec(exe_path, True), remote_file_spec)
107-
if err.Fail():
108-
raise Exception("remote_platform.Install('%s', '%s') failed: %s" % (exe_path, remote_path, err))
109-
return [remote_path]
110-
111-
def start_inferior(self):
112-
launch_args = self.install_and_create_launch_args()
113-
114-
server = self.connect_to_debug_monitor()
115-
self.assertIsNotNone(server)
116-
117-
self.add_no_ack_remote_stream()
118-
self.test_sequence.add_log_lines(
119-
["read packet: %s" % lldbgdbserverutils.build_gdbremote_A_packet(launch_args),
120-
"send packet: $OK#9a"],
121-
True)
122-
self.expect_gdbremote_sequence()
123-
124-
@debugserver_test
125-
def test_start_inferior_debugserver(self):
126-
self.init_debugserver_test()
127-
self.build()
128-
self.start_inferior()
129-
130-
@llgs_test
131-
def test_start_inferior_llgs(self):
132-
self.init_llgs_test()
133-
self.build()
134-
self.start_inferior()
135-
136-
def inferior_exit_0(self):
137-
launch_args = self.install_and_create_launch_args()
138-
139-
server = self.connect_to_debug_monitor()
140-
self.assertIsNotNone(server)
141-
142-
self.add_no_ack_remote_stream()
143-
self.add_verified_launch_packets(launch_args)
144-
self.test_sequence.add_log_lines(
145-
["read packet: $vCont;c#a8",
146-
"send packet: $W00#00"],
147-
True)
148-
149-
self.expect_gdbremote_sequence()
150-
151-
@debugserver_test
152-
def test_inferior_exit_0_debugserver(self):
153-
self.init_debugserver_test()
154-
self.build()
155-
self.inferior_exit_0()
156-
157-
@llgs_test
158-
def test_inferior_exit_0_llgs(self):
159-
self.init_llgs_test()
160-
self.build()
161-
self.inferior_exit_0()
162-
163-
def inferior_exit_42(self):
164-
launch_args = self.install_and_create_launch_args()
165-
166-
server = self.connect_to_debug_monitor()
167-
self.assertIsNotNone(server)
168-
169-
RETVAL = 42
170-
171-
# build launch args
172-
launch_args += ["retval:%d" % RETVAL]
173-
174-
self.add_no_ack_remote_stream()
175-
self.add_verified_launch_packets(launch_args)
176-
self.test_sequence.add_log_lines(
177-
["read packet: $vCont;c#a8",
178-
"send packet: $W{0:02x}#00".format(RETVAL)],
179-
True)
180-
181-
self.expect_gdbremote_sequence()
182-
183-
@debugserver_test
184-
def test_inferior_exit_42_debugserver(self):
185-
self.init_debugserver_test()
186-
self.build()
187-
self.inferior_exit_42()
188-
189-
@llgs_test
190-
def test_inferior_exit_42_llgs(self):
191-
self.init_llgs_test()
192-
self.build()
193-
self.inferior_exit_42()
194-
195100
def c_packet_works(self):
196101
launch_args = self.install_and_create_launch_args()
197102

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
LEVEL = ../../../make
2+
3+
VPATH = ..
4+
5+
override CFLAGS_EXTRAS += -D__STDC_LIMIT_MACROS -D__STDC_FORMAT_MACROS
6+
ENABLE_THREADS := YES
7+
CXX_SOURCES := main.cpp
8+
MAKE_DSYM :=NO
9+
10+
include $(LEVEL)/Makefile.rules
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
from __future__ import print_function
2+
3+
# lldb test suite imports
4+
from lldbsuite.test.decorators import *
5+
from lldbsuite.test.lldbtest import TestBase
6+
7+
# gdb-remote-specific imports
8+
import lldbgdbserverutils
9+
from gdbremote_testcase import GdbRemoteTestCaseBase
10+
11+
12+
class TestGdbRemoteExitCode(GdbRemoteTestCaseBase):
13+
14+
mydir = TestBase.compute_mydir(__file__)
15+
16+
FAILED_LAUNCH_CODE = "E08"
17+
18+
def get_launch_fail_reason(self):
19+
self.reset_test_sequence()
20+
self.test_sequence.add_log_lines(
21+
["read packet: $qLaunchSuccess#00"],
22+
True)
23+
self.test_sequence.add_log_lines(
24+
[{"direction": "send", "regex": r"^\$(.+)#[0-9a-fA-F]{2}$",
25+
"capture": {1: "launch_result"}}],
26+
True)
27+
context = self.expect_gdbremote_sequence()
28+
self.assertIsNotNone(context)
29+
return context.get("launch_result")[1:]
30+
31+
def start_inferior(self):
32+
launch_args = self.install_and_create_launch_args()
33+
34+
server = self.connect_to_debug_monitor()
35+
self.assertIsNotNone(server)
36+
37+
self.add_no_ack_remote_stream()
38+
self.test_sequence.add_log_lines(
39+
["read packet: %s" % lldbgdbserverutils.build_gdbremote_A_packet(
40+
launch_args)],
41+
True)
42+
self.test_sequence.add_log_lines(
43+
[{"direction": "send", "regex": r"^\$(.+)#[0-9a-fA-F]{2}$",
44+
"capture": {1: "A_result"}}],
45+
True)
46+
context = self.expect_gdbremote_sequence()
47+
self.assertIsNotNone(context)
48+
49+
launch_result = context.get("A_result")
50+
self.assertIsNotNone(launch_result)
51+
if launch_result == self.FAILED_LAUNCH_CODE:
52+
fail_reason = self.get_launch_fail_reason()
53+
self.fail("failed to launch inferior: " + fail_reason)
54+
55+
@debugserver_test
56+
def test_start_inferior_debugserver(self):
57+
self.init_debugserver_test()
58+
self.build()
59+
self.start_inferior()
60+
61+
@llgs_test
62+
def test_start_inferior_llgs(self):
63+
self.init_llgs_test()
64+
self.build()
65+
self.start_inferior()
66+
67+
def inferior_exit_0(self):
68+
launch_args = self.install_and_create_launch_args()
69+
70+
server = self.connect_to_debug_monitor()
71+
self.assertIsNotNone(server)
72+
73+
self.add_no_ack_remote_stream()
74+
self.add_verified_launch_packets(launch_args)
75+
self.test_sequence.add_log_lines(
76+
["read packet: $vCont;c#a8",
77+
"send packet: $W00#00"],
78+
True)
79+
80+
self.expect_gdbremote_sequence()
81+
82+
@debugserver_test
83+
def test_inferior_exit_0_debugserver(self):
84+
self.init_debugserver_test()
85+
self.build()
86+
self.inferior_exit_0()
87+
88+
@llgs_test
89+
def test_inferior_exit_0_llgs(self):
90+
self.init_llgs_test()
91+
self.build()
92+
self.inferior_exit_0()
93+
94+
def inferior_exit_42(self):
95+
launch_args = self.install_and_create_launch_args()
96+
97+
server = self.connect_to_debug_monitor()
98+
self.assertIsNotNone(server)
99+
100+
RETVAL = 42
101+
102+
# build launch args
103+
launch_args += ["retval:%d" % RETVAL]
104+
105+
self.add_no_ack_remote_stream()
106+
self.add_verified_launch_packets(launch_args)
107+
self.test_sequence.add_log_lines(
108+
["read packet: $vCont;c#a8",
109+
"send packet: $W{0:02x}#00".format(RETVAL)],
110+
True)
111+
112+
self.expect_gdbremote_sequence()
113+
114+
@debugserver_test
115+
def test_inferior_exit_42_debugserver(self):
116+
self.init_debugserver_test()
117+
self.build()
118+
self.inferior_exit_42()
119+
120+
@llgs_test
121+
def test_inferior_exit_42_llgs(self):
122+
self.init_llgs_test()
123+
self.build()
124+
self.inferior_exit_42()

‎lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py

+14-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def setUpServerLogging(self, is_llgs):
133133
self.debug_monitor_extra_args.append("--log-file=" + log_file)
134134
self.debug_monitor_extra_args.append("--log-channels={}".format(":".join(lldbtest_config.channels)))
135135
else:
136-
self.debug_monitor_extra_args = ["--log-file=" + self.log_file, "--log-flags=0x800000"]
136+
self.debug_monitor_extra_args = ["--log-file=" + log_file, "--log-flags=0x800000"]
137137

138138
def get_next_port(self):
139139
return 12000 + random.randint(0,3999)
@@ -1370,3 +1370,16 @@ def single_step_only_steps_one_instruction(self, use_Hc_packet=True, step_instru
13701370
def maybe_strict_output_regex(self, regex):
13711371
return '.*'+regex+'.*' if lldbplatformutil.hasChattyStderr(self) else '^'+regex+'$'
13721372

1373+
def install_and_create_launch_args(self):
1374+
exe_path = os.path.abspath('a.out')
1375+
if not lldb.remote_platform:
1376+
return [exe_path]
1377+
remote_path = lldbutil.append_to_process_working_directory(
1378+
os.path.basename(exe_path))
1379+
remote_file_spec = lldb.SBFileSpec(remote_path, False)
1380+
err = lldb.remote_platform.Install(lldb.SBFileSpec(exe_path, True),
1381+
remote_file_spec)
1382+
if err.Fail():
1383+
raise Exception("remote_platform.Install('%s', '%s') failed: %s" %
1384+
(exe_path, remote_path, err))
1385+
return [remote_path]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
LEVEL = ../../../make
2+
3+
VPATH = ..
4+
5+
override CFLAGS_EXTRAS += -D__STDC_LIMIT_MACROS -D__STDC_FORMAT_MACROS
6+
ENABLE_THREADS := YES
7+
CXX_SOURCES := main.cpp
8+
MAKE_DSYM :=NO
9+
10+
include $(LEVEL)/Makefile.rules

0 commit comments

Comments
 (0)
Please sign in to comment.