1import lldb
2from lldbsuite.test.lldbtest import *
3from lldbsuite.test.decorators import *
4from gdbclientutils import *
5
6
7class TestNoLocalFile(GDBRemoteTestBase):
8    """ Test the case where there is NO local copy of the file
9        being debugged.  We shouldn't immediately error out, but
10        rather lldb should ask debugserver if it knows about the file. """
11
12
13    @skipIfXmlSupportMissing
14    def test(self):
15        self.absent_file = '/nosuch_dir/nosuch_subdir/nosuch_executable'
16        self.a_packet_file = None
17        class MyResponder(MockGDBServerResponder):
18            def __init__(self, testcase):
19                MockGDBServerResponder.__init__(self)
20                self.after_launch = False
21                self.testcase = testcase
22                self.current_thread = 0
23
24            def A(self, packet):
25                # This is the main test, we want to see that lldb DID send the
26                # A packet to get debugserver to load the file.
27                # Skip the length and second length:
28                a_arr = packet.split(",")
29                self.testcase.a_packet_file = bytearray.fromhex(a_arr[2]).decode()
30                return "OK"
31
32            def qXferRead(self, obj, annex, offset, length):
33                if annex == "target.xml":
34                    return """<?xml version="1.0"?>
35                        <target version="1.0">
36                          <architecture>i386:x86-64</architecture>
37                          <feature name="org.gnu.gdb.i386.core">
38                            <reg name="rip" bitsize="64" regnum="0" type="code_ptr" group="general"/>
39                          </feature>
40                        </target>""", False
41                else:
42                    return None, False
43
44            def qC(self):
45                if not self.after_launch:
46                    return "QC0"
47                return "0"
48
49            def qfThreadInfo(self):
50                if not self.after_launch:
51                    return "OK"
52                return "m0"
53
54            def qsThreadInfo(self):
55                if not self.after_launch:
56                    return "OK"
57                return "l"
58
59            def qLaunchSuccess(self):
60                return "OK"
61
62            def qProcessInfo(self):
63                return "$pid:10b70;parent-pid:10b20;real-uid:1f6;real-gid:14;effective-uid:1f6;effective-gid:14;cputype:1000007;cpusubtype:8;ptrsize:8;ostype:macosx;vendor:apple;endian:little;"
64
65
66        error = lldb.SBError()
67        self.server.responder = MyResponder(self)
68        target = self.dbg.CreateTarget(None, "x86_64-apple-macosx", "remote-macosx", False, error)
69        self.assertSuccess(error, "Made a valid target")
70        launch_info = target.GetLaunchInfo()
71        launch_info.SetExecutableFile(lldb.SBFileSpec(self.absent_file), True)
72        flags = launch_info.GetLaunchFlags()
73        flags |= lldb.eLaunchFlagStopAtEntry
74        launch_info.SetLaunchFlags(flags)
75
76        process = self.connect(target)
77        self.assertTrue(process.IsValid(), "Process is valid")
78
79        # We need to fetch the connected event:
80        lldbutil.expect_state_changes(self, self.dbg.GetListener(), process, [lldb.eStateConnected])
81
82        self.server.responder.after_launch = True
83
84        process = target.Launch(launch_info, error)
85        self.assertSuccess(error, "Successfully launched.")
86        self.assertEqual(process.GetState(), lldb.eStateStopped, "Should be stopped at entry")
87        self.assertIsNotNone(self.a_packet_file, "A packet was sent")
88        self.assertEqual(self.absent_file, self.a_packet_file, "The A packet file was correct")
89