xref: /llvm-project/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py (revision ceeb08b9e0a51a4d2e0804baeb579fe8a6485885)
101263c6cSJonas Devlieghere#!/usr/bin/env python
201263c6cSJonas Devlieghere
301263c6cSJonas Devlieghereimport binascii
401263c6cSJonas Devlieghereimport json
501263c6cSJonas Devlieghereimport optparse
601263c6cSJonas Devlieghereimport os
701263c6cSJonas Devlieghereimport pprint
801263c6cSJonas Devlieghereimport socket
901263c6cSJonas Devlieghereimport string
1001263c6cSJonas Devlieghereimport subprocess
1101263c6cSJonas Devlieghereimport sys
1201263c6cSJonas Devlieghereimport threading
1301263c6cSJonas Devlieghereimport time
1401263c6cSJonas Devlieghere
1501263c6cSJonas Devlieghere
1601263c6cSJonas Devliegheredef dump_memory(base_addr, data, num_per_line, outfile):
1701263c6cSJonas Devlieghere    data_len = len(data)
1801263c6cSJonas Devlieghere    hex_string = binascii.hexlify(data)
1901263c6cSJonas Devlieghere    addr = base_addr
2001263c6cSJonas Devlieghere    ascii_str = ""
2101263c6cSJonas Devlieghere    i = 0
2201263c6cSJonas Devlieghere    while i < data_len:
2301263c6cSJonas Devlieghere        outfile.write("0x%8.8x: " % (addr + i))
2401263c6cSJonas Devlieghere        bytes_left = data_len - i
2501263c6cSJonas Devlieghere        if bytes_left >= num_per_line:
2601263c6cSJonas Devlieghere            curr_data_len = num_per_line
2701263c6cSJonas Devlieghere        else:
2801263c6cSJonas Devlieghere            curr_data_len = bytes_left
2901263c6cSJonas Devlieghere        hex_start_idx = i * 2
3001263c6cSJonas Devlieghere        hex_end_idx = hex_start_idx + curr_data_len * 2
3101263c6cSJonas Devlieghere        curr_hex_str = hex_string[hex_start_idx:hex_end_idx]
3201263c6cSJonas Devlieghere        # 'curr_hex_str' now contains the hex byte string for the
3301263c6cSJonas Devlieghere        # current line with no spaces between bytes
3401263c6cSJonas Devlieghere        t = iter(curr_hex_str)
3501263c6cSJonas Devlieghere        # Print hex bytes separated by space
3601263c6cSJonas Devlieghere        outfile.write(" ".join(a + b for a, b in zip(t, t)))
3701263c6cSJonas Devlieghere        # Print two spaces
3801263c6cSJonas Devlieghere        outfile.write("  ")
3901263c6cSJonas Devlieghere        # Calculate ASCII string for bytes into 'ascii_str'
4001263c6cSJonas Devlieghere        ascii_str = ""
4101263c6cSJonas Devlieghere        for j in range(i, i + curr_data_len):
4201263c6cSJonas Devlieghere            ch = data[j]
4301263c6cSJonas Devlieghere            if ch in string.printable and ch not in string.whitespace:
4401263c6cSJonas Devlieghere                ascii_str += "%c" % (ch)
4501263c6cSJonas Devlieghere            else:
4601263c6cSJonas Devlieghere                ascii_str += "."
4701263c6cSJonas Devlieghere        # Print ASCII representation and newline
4801263c6cSJonas Devlieghere        outfile.write(ascii_str)
4901263c6cSJonas Devlieghere        i = i + curr_data_len
5001263c6cSJonas Devlieghere        outfile.write("\n")
5101263c6cSJonas Devlieghere
5201263c6cSJonas Devlieghere
5301263c6cSJonas Devliegheredef read_packet(f, verbose=False, trace_file=None):
5401263c6cSJonas Devlieghere    """Decode a JSON packet that starts with the content length and is
5501263c6cSJonas Devlieghere    followed by the JSON bytes from a file 'f'. Returns None on EOF.
5601263c6cSJonas Devlieghere    """
5701263c6cSJonas Devlieghere    line = f.readline().decode("utf-8")
5801263c6cSJonas Devlieghere    if len(line) == 0:
5901263c6cSJonas Devlieghere        return None  # EOF.
6001263c6cSJonas Devlieghere
6101263c6cSJonas Devlieghere    # Watch for line that starts with the prefix
6201263c6cSJonas Devlieghere    prefix = "Content-Length: "
6301263c6cSJonas Devlieghere    if line.startswith(prefix):
6401263c6cSJonas Devlieghere        # Decode length of JSON bytes
6501263c6cSJonas Devlieghere        if verbose:
6601263c6cSJonas Devlieghere            print('content: "%s"' % (line))
6701263c6cSJonas Devlieghere        length = int(line[len(prefix) :])
6801263c6cSJonas Devlieghere        if verbose:
6901263c6cSJonas Devlieghere            print('length: "%u"' % (length))
7001263c6cSJonas Devlieghere        # Skip empty line
7101263c6cSJonas Devlieghere        line = f.readline()
7201263c6cSJonas Devlieghere        if verbose:
7301263c6cSJonas Devlieghere            print('empty: "%s"' % (line))
7401263c6cSJonas Devlieghere        # Read JSON bytes
7501263c6cSJonas Devlieghere        json_str = f.read(length)
7601263c6cSJonas Devlieghere        if verbose:
7701263c6cSJonas Devlieghere            print('json: "%s"' % (json_str))
7801263c6cSJonas Devlieghere        if trace_file:
7901263c6cSJonas Devlieghere            trace_file.write("from adaptor:\n%s\n" % (json_str))
8001263c6cSJonas Devlieghere        # Decode the JSON bytes into a python dictionary
8101263c6cSJonas Devlieghere        return json.loads(json_str)
8201263c6cSJonas Devlieghere
832a32afddSDavid Spickett    raise Exception("unexpected malformed message from lldb-dap: " + line)
8401263c6cSJonas Devlieghere
8501263c6cSJonas Devlieghere
8601263c6cSJonas Devliegheredef packet_type_is(packet, packet_type):
8701263c6cSJonas Devlieghere    return "type" in packet and packet["type"] == packet_type
8801263c6cSJonas Devlieghere
8901263c6cSJonas Devlieghere
9001263c6cSJonas Devliegheredef dump_dap_log(log_file):
9101263c6cSJonas Devlieghere    print("========= DEBUG ADAPTER PROTOCOL LOGS =========")
9201263c6cSJonas Devlieghere    if log_file is None:
9301263c6cSJonas Devlieghere        print("no log file available")
9401263c6cSJonas Devlieghere    else:
9501263c6cSJonas Devlieghere        with open(log_file, "r") as file:
9601263c6cSJonas Devlieghere            print(file.read())
9701263c6cSJonas Devlieghere    print("========= END =========")
9801263c6cSJonas Devlieghere
9901263c6cSJonas Devlieghere
10001263c6cSJonas Devliegheredef read_packet_thread(vs_comm, log_file):
10101263c6cSJonas Devlieghere    done = False
10201263c6cSJonas Devlieghere    try:
10301263c6cSJonas Devlieghere        while not done:
10401263c6cSJonas Devlieghere            packet = read_packet(vs_comm.recv, trace_file=vs_comm.trace_file)
10501263c6cSJonas Devlieghere            # `packet` will be `None` on EOF. We want to pass it down to
10601263c6cSJonas Devlieghere            # handle_recv_packet anyway so the main thread can handle unexpected
1072a32afddSDavid Spickett            # termination of lldb-dap and stop waiting for new packets.
10801263c6cSJonas Devlieghere            done = not vs_comm.handle_recv_packet(packet)
10901263c6cSJonas Devlieghere    finally:
11001263c6cSJonas Devlieghere        dump_dap_log(log_file)
11101263c6cSJonas Devlieghere
11201263c6cSJonas Devlieghere
11301263c6cSJonas Devlieghereclass DebugCommunication(object):
11401263c6cSJonas Devlieghere    def __init__(self, recv, send, init_commands, log_file=None):
11501263c6cSJonas Devlieghere        self.trace_file = None
11601263c6cSJonas Devlieghere        self.send = send
11701263c6cSJonas Devlieghere        self.recv = recv
11801263c6cSJonas Devlieghere        self.recv_packets = []
11901263c6cSJonas Devlieghere        self.recv_condition = threading.Condition()
12001263c6cSJonas Devlieghere        self.recv_thread = threading.Thread(
12101263c6cSJonas Devlieghere            target=read_packet_thread, args=(self, log_file)
12201263c6cSJonas Devlieghere        )
12301263c6cSJonas Devlieghere        self.process_event_body = None
12401263c6cSJonas Devlieghere        self.exit_status = None
12501263c6cSJonas Devlieghere        self.initialize_body = None
12601263c6cSJonas Devlieghere        self.thread_stop_reasons = {}
12701263c6cSJonas Devlieghere        self.breakpoint_events = []
12801263c6cSJonas Devlieghere        self.progress_events = []
12901263c6cSJonas Devlieghere        self.reverse_requests = []
13001263c6cSJonas Devlieghere        self.sequence = 1
13101263c6cSJonas Devlieghere        self.threads = None
13201263c6cSJonas Devlieghere        self.recv_thread.start()
13301263c6cSJonas Devlieghere        self.output_condition = threading.Condition()
13401263c6cSJonas Devlieghere        self.output = {}
13501263c6cSJonas Devlieghere        self.configuration_done_sent = False
13601263c6cSJonas Devlieghere        self.frame_scopes = {}
13701263c6cSJonas Devlieghere        self.init_commands = init_commands
13801263c6cSJonas Devlieghere        self.disassembled_instructions = {}
13901263c6cSJonas Devlieghere
14001263c6cSJonas Devlieghere    @classmethod
14101263c6cSJonas Devlieghere    def encode_content(cls, s):
14201263c6cSJonas Devlieghere        return ("Content-Length: %u\r\n\r\n%s" % (len(s), s)).encode("utf-8")
14301263c6cSJonas Devlieghere
14401263c6cSJonas Devlieghere    @classmethod
14501263c6cSJonas Devlieghere    def validate_response(cls, command, response):
14601263c6cSJonas Devlieghere        if command["command"] != response["command"]:
14701263c6cSJonas Devlieghere            raise ValueError("command mismatch in response")
14801263c6cSJonas Devlieghere        if command["seq"] != response["request_seq"]:
14901263c6cSJonas Devlieghere            raise ValueError("seq mismatch in response")
15001263c6cSJonas Devlieghere
15101263c6cSJonas Devlieghere    def get_modules(self):
15201263c6cSJonas Devlieghere        module_list = self.request_modules()["body"]["modules"]
15301263c6cSJonas Devlieghere        modules = {}
15401263c6cSJonas Devlieghere        for module in module_list:
15501263c6cSJonas Devlieghere            modules[module["name"]] = module
15601263c6cSJonas Devlieghere        return modules
15701263c6cSJonas Devlieghere
15801263c6cSJonas Devlieghere    def get_output(self, category, timeout=0.0, clear=True):
15901263c6cSJonas Devlieghere        self.output_condition.acquire()
16001263c6cSJonas Devlieghere        output = None
16101263c6cSJonas Devlieghere        if category in self.output:
16201263c6cSJonas Devlieghere            output = self.output[category]
16301263c6cSJonas Devlieghere            if clear:
16401263c6cSJonas Devlieghere                del self.output[category]
16501263c6cSJonas Devlieghere        elif timeout != 0.0:
16601263c6cSJonas Devlieghere            self.output_condition.wait(timeout)
16701263c6cSJonas Devlieghere            if category in self.output:
16801263c6cSJonas Devlieghere                output = self.output[category]
16901263c6cSJonas Devlieghere                if clear:
17001263c6cSJonas Devlieghere                    del self.output[category]
17101263c6cSJonas Devlieghere        self.output_condition.release()
17201263c6cSJonas Devlieghere        return output
17301263c6cSJonas Devlieghere
17411a4d43fSMiro Bucko    def collect_output(self, category, timeout_secs, pattern, clear=True):
17511a4d43fSMiro Bucko        end_time = time.time() + timeout_secs
17601263c6cSJonas Devlieghere        collected_output = ""
17701263c6cSJonas Devlieghere        while end_time > time.time():
17801263c6cSJonas Devlieghere            output = self.get_output(category, timeout=0.25, clear=clear)
17901263c6cSJonas Devlieghere            if output:
18001263c6cSJonas Devlieghere                collected_output += output
18111a4d43fSMiro Bucko                if pattern is not None and pattern in output:
18211a4d43fSMiro Bucko                    break
18301263c6cSJonas Devlieghere        return collected_output if collected_output else None
18401263c6cSJonas Devlieghere
18501263c6cSJonas Devlieghere    def enqueue_recv_packet(self, packet):
18601263c6cSJonas Devlieghere        self.recv_condition.acquire()
18701263c6cSJonas Devlieghere        self.recv_packets.append(packet)
18801263c6cSJonas Devlieghere        self.recv_condition.notify()
18901263c6cSJonas Devlieghere        self.recv_condition.release()
19001263c6cSJonas Devlieghere
19101263c6cSJonas Devlieghere    def handle_recv_packet(self, packet):
19201263c6cSJonas Devlieghere        """Called by the read thread that is waiting for all incoming packets
19301263c6cSJonas Devlieghere        to store the incoming packet in "self.recv_packets" in a thread safe
19401263c6cSJonas Devlieghere        way. This function will then signal the "self.recv_condition" to
19501263c6cSJonas Devlieghere        indicate a new packet is available. Returns True if the caller
19601263c6cSJonas Devlieghere        should keep calling this function for more packets.
19701263c6cSJonas Devlieghere        """
19801263c6cSJonas Devlieghere        # If EOF, notify the read thread by enqueuing a None.
19901263c6cSJonas Devlieghere        if not packet:
20001263c6cSJonas Devlieghere            self.enqueue_recv_packet(None)
20101263c6cSJonas Devlieghere            return False
20201263c6cSJonas Devlieghere
20301263c6cSJonas Devlieghere        # Check the packet to see if is an event packet
20401263c6cSJonas Devlieghere        keepGoing = True
20501263c6cSJonas Devlieghere        packet_type = packet["type"]
20601263c6cSJonas Devlieghere        if packet_type == "event":
20701263c6cSJonas Devlieghere            event = packet["event"]
20801263c6cSJonas Devlieghere            body = None
20901263c6cSJonas Devlieghere            if "body" in packet:
21001263c6cSJonas Devlieghere                body = packet["body"]
21101263c6cSJonas Devlieghere            # Handle the event packet and cache information from these packets
21201263c6cSJonas Devlieghere            # as they come in
21301263c6cSJonas Devlieghere            if event == "output":
21401263c6cSJonas Devlieghere                # Store any output we receive so clients can retrieve it later.
21501263c6cSJonas Devlieghere                category = body["category"]
21601263c6cSJonas Devlieghere                output = body["output"]
21701263c6cSJonas Devlieghere                self.output_condition.acquire()
21801263c6cSJonas Devlieghere                if category in self.output:
21901263c6cSJonas Devlieghere                    self.output[category] += output
22001263c6cSJonas Devlieghere                else:
22101263c6cSJonas Devlieghere                    self.output[category] = output
22201263c6cSJonas Devlieghere                self.output_condition.notify()
22301263c6cSJonas Devlieghere                self.output_condition.release()
22401263c6cSJonas Devlieghere                # no need to add 'output' event packets to our packets list
22501263c6cSJonas Devlieghere                return keepGoing
22601263c6cSJonas Devlieghere            elif event == "process":
22701263c6cSJonas Devlieghere                # When a new process is attached or launched, remember the
22801263c6cSJonas Devlieghere                # details that are available in the body of the event
22901263c6cSJonas Devlieghere                self.process_event_body = body
23001263c6cSJonas Devlieghere            elif event == "stopped":
23101263c6cSJonas Devlieghere                # Each thread that stops with a reason will send a
23201263c6cSJonas Devlieghere                # 'stopped' event. We need to remember the thread stop
23301263c6cSJonas Devlieghere                # reasons since the 'threads' command doesn't return
23401263c6cSJonas Devlieghere                # that information.
23501263c6cSJonas Devlieghere                self._process_stopped()
23601263c6cSJonas Devlieghere                tid = body["threadId"]
23701263c6cSJonas Devlieghere                self.thread_stop_reasons[tid] = body
23801263c6cSJonas Devlieghere            elif event == "breakpoint":
23901263c6cSJonas Devlieghere                # Breakpoint events come in when a breakpoint has locations
24001263c6cSJonas Devlieghere                # added or removed. Keep track of them so we can look for them
24101263c6cSJonas Devlieghere                # in tests.
24201263c6cSJonas Devlieghere                self.breakpoint_events.append(packet)
24301263c6cSJonas Devlieghere                # no need to add 'breakpoint' event packets to our packets list
24401263c6cSJonas Devlieghere                return keepGoing
24501263c6cSJonas Devlieghere            elif event.startswith("progress"):
24601263c6cSJonas Devlieghere                # Progress events come in as 'progressStart', 'progressUpdate',
24701263c6cSJonas Devlieghere                # and 'progressEnd' events. Keep these around in case test
24801263c6cSJonas Devlieghere                # cases want to verify them.
24901263c6cSJonas Devlieghere                self.progress_events.append(packet)
25001263c6cSJonas Devlieghere                # No need to add 'progress' event packets to our packets list.
25101263c6cSJonas Devlieghere                return keepGoing
25201263c6cSJonas Devlieghere
25301263c6cSJonas Devlieghere        elif packet_type == "response":
25401263c6cSJonas Devlieghere            if packet["command"] == "disconnect":
25501263c6cSJonas Devlieghere                keepGoing = False
25601263c6cSJonas Devlieghere        self.enqueue_recv_packet(packet)
25701263c6cSJonas Devlieghere        return keepGoing
25801263c6cSJonas Devlieghere
25901263c6cSJonas Devlieghere    def send_packet(self, command_dict, set_sequence=True):
26001263c6cSJonas Devlieghere        """Take the "command_dict" python dictionary and encode it as a JSON
26101263c6cSJonas Devlieghere        string and send the contents as a packet to the VSCode debug
26201263c6cSJonas Devlieghere        adaptor"""
26301263c6cSJonas Devlieghere        # Set the sequence ID for this command automatically
26401263c6cSJonas Devlieghere        if set_sequence:
26501263c6cSJonas Devlieghere            command_dict["seq"] = self.sequence
26601263c6cSJonas Devlieghere            self.sequence += 1
26701263c6cSJonas Devlieghere        # Encode our command dictionary as a JSON string
26801263c6cSJonas Devlieghere        json_str = json.dumps(command_dict, separators=(",", ":"))
26901263c6cSJonas Devlieghere        if self.trace_file:
27001263c6cSJonas Devlieghere            self.trace_file.write("to adaptor:\n%s\n" % (json_str))
27101263c6cSJonas Devlieghere        length = len(json_str)
27201263c6cSJonas Devlieghere        if length > 0:
27301263c6cSJonas Devlieghere            # Send the encoded JSON packet and flush the 'send' file
27401263c6cSJonas Devlieghere            self.send.write(self.encode_content(json_str))
27501263c6cSJonas Devlieghere            self.send.flush()
27601263c6cSJonas Devlieghere
27701263c6cSJonas Devlieghere    def recv_packet(self, filter_type=None, filter_event=None, timeout=None):
27801263c6cSJonas Devlieghere        """Get a JSON packet from the VSCode debug adaptor. This function
27901263c6cSJonas Devlieghere        assumes a thread that reads packets is running and will deliver
28001263c6cSJonas Devlieghere        any received packets by calling handle_recv_packet(...). This
28101263c6cSJonas Devlieghere        function will wait for the packet to arrive and return it when
28201263c6cSJonas Devlieghere        it does."""
28301263c6cSJonas Devlieghere        while True:
28401263c6cSJonas Devlieghere            try:
28501263c6cSJonas Devlieghere                self.recv_condition.acquire()
28601263c6cSJonas Devlieghere                packet = None
28701263c6cSJonas Devlieghere                while True:
28801263c6cSJonas Devlieghere                    for i, curr_packet in enumerate(self.recv_packets):
28901263c6cSJonas Devlieghere                        if not curr_packet:
29001263c6cSJonas Devlieghere                            raise EOFError
29101263c6cSJonas Devlieghere                        packet_type = curr_packet["type"]
29201263c6cSJonas Devlieghere                        if filter_type is None or packet_type in filter_type:
29301263c6cSJonas Devlieghere                            if filter_event is None or (
29401263c6cSJonas Devlieghere                                packet_type == "event"
29501263c6cSJonas Devlieghere                                and curr_packet["event"] in filter_event
29601263c6cSJonas Devlieghere                            ):
29701263c6cSJonas Devlieghere                                packet = self.recv_packets.pop(i)
29801263c6cSJonas Devlieghere                                break
29901263c6cSJonas Devlieghere                    if packet:
30001263c6cSJonas Devlieghere                        break
30101263c6cSJonas Devlieghere                    # Sleep until packet is received
30201263c6cSJonas Devlieghere                    len_before = len(self.recv_packets)
30301263c6cSJonas Devlieghere                    self.recv_condition.wait(timeout)
30401263c6cSJonas Devlieghere                    len_after = len(self.recv_packets)
30501263c6cSJonas Devlieghere                    if len_before == len_after:
30601263c6cSJonas Devlieghere                        return None  # Timed out
30701263c6cSJonas Devlieghere                return packet
30801263c6cSJonas Devlieghere            except EOFError:
30901263c6cSJonas Devlieghere                return None
31001263c6cSJonas Devlieghere            finally:
31101263c6cSJonas Devlieghere                self.recv_condition.release()
31201263c6cSJonas Devlieghere
31301263c6cSJonas Devlieghere        return None
31401263c6cSJonas Devlieghere
31501263c6cSJonas Devlieghere    def send_recv(self, command):
31601263c6cSJonas Devlieghere        """Send a command python dictionary as JSON and receive the JSON
31701263c6cSJonas Devlieghere        response. Validates that the response is the correct sequence and
31801263c6cSJonas Devlieghere        command in the reply. Any events that are received are added to the
31901263c6cSJonas Devlieghere        events list in this object"""
32001263c6cSJonas Devlieghere        self.send_packet(command)
32101263c6cSJonas Devlieghere        done = False
32201263c6cSJonas Devlieghere        while not done:
32301263c6cSJonas Devlieghere            response_or_request = self.recv_packet(filter_type=["response", "request"])
32401263c6cSJonas Devlieghere            if response_or_request is None:
32501263c6cSJonas Devlieghere                desc = 'no response for "%s"' % (command["command"])
32601263c6cSJonas Devlieghere                raise ValueError(desc)
32701263c6cSJonas Devlieghere            if response_or_request["type"] == "response":
32801263c6cSJonas Devlieghere                self.validate_response(command, response_or_request)
32901263c6cSJonas Devlieghere                return response_or_request
33001263c6cSJonas Devlieghere            else:
33101263c6cSJonas Devlieghere                self.reverse_requests.append(response_or_request)
33201263c6cSJonas Devlieghere                if response_or_request["command"] == "runInTerminal":
33301263c6cSJonas Devlieghere                    subprocess.Popen(
33401263c6cSJonas Devlieghere                        response_or_request["arguments"]["args"],
33501263c6cSJonas Devlieghere                        env=response_or_request["arguments"]["env"],
33601263c6cSJonas Devlieghere                    )
33701263c6cSJonas Devlieghere                    self.send_packet(
33801263c6cSJonas Devlieghere                        {
33901263c6cSJonas Devlieghere                            "type": "response",
34001263c6cSJonas Devlieghere                            "seq": -1,
34101263c6cSJonas Devlieghere                            "request_seq": response_or_request["seq"],
34201263c6cSJonas Devlieghere                            "success": True,
34301263c6cSJonas Devlieghere                            "command": "runInTerminal",
34401263c6cSJonas Devlieghere                            "body": {},
34501263c6cSJonas Devlieghere                        },
34601263c6cSJonas Devlieghere                        set_sequence=False,
34701263c6cSJonas Devlieghere                    )
34801263c6cSJonas Devlieghere                elif response_or_request["command"] == "startDebugging":
34901263c6cSJonas Devlieghere                    self.send_packet(
35001263c6cSJonas Devlieghere                        {
35101263c6cSJonas Devlieghere                            "type": "response",
35201263c6cSJonas Devlieghere                            "seq": -1,
35301263c6cSJonas Devlieghere                            "request_seq": response_or_request["seq"],
35401263c6cSJonas Devlieghere                            "success": True,
35501263c6cSJonas Devlieghere                            "command": "startDebugging",
35601263c6cSJonas Devlieghere                            "body": {},
35701263c6cSJonas Devlieghere                        },
35801263c6cSJonas Devlieghere                        set_sequence=False,
35901263c6cSJonas Devlieghere                    )
36001263c6cSJonas Devlieghere                else:
36101263c6cSJonas Devlieghere                    desc = 'unknown reverse request "%s"' % (
36201263c6cSJonas Devlieghere                        response_or_request["command"]
36301263c6cSJonas Devlieghere                    )
36401263c6cSJonas Devlieghere                    raise ValueError(desc)
36501263c6cSJonas Devlieghere
36601263c6cSJonas Devlieghere        return None
36701263c6cSJonas Devlieghere
36801263c6cSJonas Devlieghere    def wait_for_event(self, filter=None, timeout=None):
36901263c6cSJonas Devlieghere        while True:
37001263c6cSJonas Devlieghere            return self.recv_packet(
37101263c6cSJonas Devlieghere                filter_type="event", filter_event=filter, timeout=timeout
37201263c6cSJonas Devlieghere            )
37301263c6cSJonas Devlieghere        return None
37401263c6cSJonas Devlieghere
37501263c6cSJonas Devlieghere    def wait_for_stopped(self, timeout=None):
37601263c6cSJonas Devlieghere        stopped_events = []
37701263c6cSJonas Devlieghere        stopped_event = self.wait_for_event(
37801263c6cSJonas Devlieghere            filter=["stopped", "exited"], timeout=timeout
37901263c6cSJonas Devlieghere        )
38001263c6cSJonas Devlieghere        exited = False
38101263c6cSJonas Devlieghere        while stopped_event:
38201263c6cSJonas Devlieghere            stopped_events.append(stopped_event)
38301263c6cSJonas Devlieghere            # If we exited, then we are done
38401263c6cSJonas Devlieghere            if stopped_event["event"] == "exited":
38501263c6cSJonas Devlieghere                self.exit_status = stopped_event["body"]["exitCode"]
38601263c6cSJonas Devlieghere                exited = True
38701263c6cSJonas Devlieghere                break
38801263c6cSJonas Devlieghere            # Otherwise we stopped and there might be one or more 'stopped'
38901263c6cSJonas Devlieghere            # events for each thread that stopped with a reason, so keep
39001263c6cSJonas Devlieghere            # checking for more 'stopped' events and return all of them
39101263c6cSJonas Devlieghere            stopped_event = self.wait_for_event(filter="stopped", timeout=0.25)
39201263c6cSJonas Devlieghere        if exited:
39301263c6cSJonas Devlieghere            self.threads = []
39401263c6cSJonas Devlieghere        return stopped_events
39501263c6cSJonas Devlieghere
39601263c6cSJonas Devlieghere    def wait_for_exited(self):
39701263c6cSJonas Devlieghere        event_dict = self.wait_for_event("exited")
39801263c6cSJonas Devlieghere        if event_dict is None:
39901263c6cSJonas Devlieghere            raise ValueError("didn't get exited event")
40001263c6cSJonas Devlieghere        return event_dict
40101263c6cSJonas Devlieghere
40201263c6cSJonas Devlieghere    def wait_for_terminated(self):
40301263c6cSJonas Devlieghere        event_dict = self.wait_for_event("terminated")
40401263c6cSJonas Devlieghere        if event_dict is None:
40501263c6cSJonas Devlieghere            raise ValueError("didn't get terminated event")
40601263c6cSJonas Devlieghere        return event_dict
40701263c6cSJonas Devlieghere
40801263c6cSJonas Devlieghere    def get_initialize_value(self, key):
40901263c6cSJonas Devlieghere        """Get a value for the given key if it there is a key/value pair in
41001263c6cSJonas Devlieghere        the "initialize" request response body.
41101263c6cSJonas Devlieghere        """
41201263c6cSJonas Devlieghere        if self.initialize_body and key in self.initialize_body:
41301263c6cSJonas Devlieghere            return self.initialize_body[key]
41401263c6cSJonas Devlieghere        return None
41501263c6cSJonas Devlieghere
41601263c6cSJonas Devlieghere    def get_threads(self):
41701263c6cSJonas Devlieghere        if self.threads is None:
41801263c6cSJonas Devlieghere            self.request_threads()
41901263c6cSJonas Devlieghere        return self.threads
42001263c6cSJonas Devlieghere
42101263c6cSJonas Devlieghere    def get_thread_id(self, threadIndex=0):
42201263c6cSJonas Devlieghere        """Utility function to get the first thread ID in the thread list.
42301263c6cSJonas Devlieghere        If the thread list is empty, then fetch the threads.
42401263c6cSJonas Devlieghere        """
42501263c6cSJonas Devlieghere        if self.threads is None:
42601263c6cSJonas Devlieghere            self.request_threads()
42701263c6cSJonas Devlieghere        if self.threads and threadIndex < len(self.threads):
42801263c6cSJonas Devlieghere            return self.threads[threadIndex]["id"]
42901263c6cSJonas Devlieghere        return None
43001263c6cSJonas Devlieghere
43101263c6cSJonas Devlieghere    def get_stackFrame(self, frameIndex=0, threadId=None):
43201263c6cSJonas Devlieghere        """Get a single "StackFrame" object from a "stackTrace" request and
43301263c6cSJonas Devlieghere        return the "StackFrame" as a python dictionary, or None on failure
43401263c6cSJonas Devlieghere        """
43501263c6cSJonas Devlieghere        if threadId is None:
43601263c6cSJonas Devlieghere            threadId = self.get_thread_id()
43701263c6cSJonas Devlieghere        if threadId is None:
43801263c6cSJonas Devlieghere            print("invalid threadId")
43901263c6cSJonas Devlieghere            return None
44001263c6cSJonas Devlieghere        response = self.request_stackTrace(threadId, startFrame=frameIndex, levels=1)
44101263c6cSJonas Devlieghere        if response:
44201263c6cSJonas Devlieghere            return response["body"]["stackFrames"][0]
44301263c6cSJonas Devlieghere        print("invalid response")
44401263c6cSJonas Devlieghere        return None
44501263c6cSJonas Devlieghere
44601263c6cSJonas Devlieghere    def get_completions(self, text, frameId=None):
44701263c6cSJonas Devlieghere        if frameId is None:
44801263c6cSJonas Devlieghere            stackFrame = self.get_stackFrame()
44901263c6cSJonas Devlieghere            frameId = stackFrame["id"]
45001263c6cSJonas Devlieghere        response = self.request_completions(text, frameId)
45101263c6cSJonas Devlieghere        return response["body"]["targets"]
45201263c6cSJonas Devlieghere
453b8d38bb5Sjeffreytan81    def get_scope_variables(self, scope_name, frameIndex=0, threadId=None, is_hex=None):
45401263c6cSJonas Devlieghere        stackFrame = self.get_stackFrame(frameIndex=frameIndex, threadId=threadId)
45501263c6cSJonas Devlieghere        if stackFrame is None:
45601263c6cSJonas Devlieghere            return []
45701263c6cSJonas Devlieghere        frameId = stackFrame["id"]
45801263c6cSJonas Devlieghere        if frameId in self.frame_scopes:
45901263c6cSJonas Devlieghere            frame_scopes = self.frame_scopes[frameId]
46001263c6cSJonas Devlieghere        else:
46101263c6cSJonas Devlieghere            scopes_response = self.request_scopes(frameId)
46201263c6cSJonas Devlieghere            frame_scopes = scopes_response["body"]["scopes"]
46301263c6cSJonas Devlieghere            self.frame_scopes[frameId] = frame_scopes
46401263c6cSJonas Devlieghere        for scope in frame_scopes:
46501263c6cSJonas Devlieghere            if scope["name"] == scope_name:
46601263c6cSJonas Devlieghere                varRef = scope["variablesReference"]
467b8d38bb5Sjeffreytan81                variables_response = self.request_variables(varRef, is_hex=is_hex)
46801263c6cSJonas Devlieghere                if variables_response:
46901263c6cSJonas Devlieghere                    if "body" in variables_response:
47001263c6cSJonas Devlieghere                        body = variables_response["body"]
47101263c6cSJonas Devlieghere                        if "variables" in body:
47201263c6cSJonas Devlieghere                            vars = body["variables"]
47301263c6cSJonas Devlieghere                            return vars
47401263c6cSJonas Devlieghere        return []
47501263c6cSJonas Devlieghere
47601263c6cSJonas Devlieghere    def get_global_variables(self, frameIndex=0, threadId=None):
47701263c6cSJonas Devlieghere        return self.get_scope_variables(
47801263c6cSJonas Devlieghere            "Globals", frameIndex=frameIndex, threadId=threadId
47901263c6cSJonas Devlieghere        )
48001263c6cSJonas Devlieghere
481b8d38bb5Sjeffreytan81    def get_local_variables(self, frameIndex=0, threadId=None, is_hex=None):
48201263c6cSJonas Devlieghere        return self.get_scope_variables(
483b8d38bb5Sjeffreytan81            "Locals", frameIndex=frameIndex, threadId=threadId, is_hex=is_hex
48401263c6cSJonas Devlieghere        )
48501263c6cSJonas Devlieghere
48601263c6cSJonas Devlieghere    def get_registers(self, frameIndex=0, threadId=None):
48701263c6cSJonas Devlieghere        return self.get_scope_variables(
48801263c6cSJonas Devlieghere            "Registers", frameIndex=frameIndex, threadId=threadId
48901263c6cSJonas Devlieghere        )
49001263c6cSJonas Devlieghere
491b8d38bb5Sjeffreytan81    def get_local_variable(self, name, frameIndex=0, threadId=None, is_hex=None):
492b8d38bb5Sjeffreytan81        locals = self.get_local_variables(
493b8d38bb5Sjeffreytan81            frameIndex=frameIndex, threadId=threadId, is_hex=is_hex
494b8d38bb5Sjeffreytan81        )
49501263c6cSJonas Devlieghere        for local in locals:
49601263c6cSJonas Devlieghere            if "name" in local and local["name"] == name:
49701263c6cSJonas Devlieghere                return local
49801263c6cSJonas Devlieghere        return None
49901263c6cSJonas Devlieghere
500b8d38bb5Sjeffreytan81    def get_local_variable_value(self, name, frameIndex=0, threadId=None, is_hex=None):
50101263c6cSJonas Devlieghere        variable = self.get_local_variable(
502b8d38bb5Sjeffreytan81            name, frameIndex=frameIndex, threadId=threadId, is_hex=is_hex
50301263c6cSJonas Devlieghere        )
50401263c6cSJonas Devlieghere        if variable and "value" in variable:
50501263c6cSJonas Devlieghere            return variable["value"]
50601263c6cSJonas Devlieghere        return None
50701263c6cSJonas Devlieghere
508b8d38bb5Sjeffreytan81    def get_local_variable_child(
509b8d38bb5Sjeffreytan81        self, name, child_name, frameIndex=0, threadId=None, is_hex=None
510b8d38bb5Sjeffreytan81    ):
511df6f756aSZequan Wu        local = self.get_local_variable(name, frameIndex, threadId)
512df6f756aSZequan Wu        if local["variablesReference"] == 0:
513df6f756aSZequan Wu            return None
514b8d38bb5Sjeffreytan81        children = self.request_variables(local["variablesReference"], is_hex=is_hex)[
515b8d38bb5Sjeffreytan81            "body"
516b8d38bb5Sjeffreytan81        ]["variables"]
517df6f756aSZequan Wu        for child in children:
518df6f756aSZequan Wu            if child["name"] == child_name:
519df6f756aSZequan Wu                return child
520df6f756aSZequan Wu        return None
521df6f756aSZequan Wu
52201263c6cSJonas Devlieghere    def replay_packets(self, replay_file_path):
52301263c6cSJonas Devlieghere        f = open(replay_file_path, "r")
52401263c6cSJonas Devlieghere        mode = "invalid"
52501263c6cSJonas Devlieghere        set_sequence = False
52601263c6cSJonas Devlieghere        command_dict = None
52701263c6cSJonas Devlieghere        while mode != "eof":
52801263c6cSJonas Devlieghere            if mode == "invalid":
52901263c6cSJonas Devlieghere                line = f.readline()
53001263c6cSJonas Devlieghere                if line.startswith("to adapter:"):
53101263c6cSJonas Devlieghere                    mode = "send"
53201263c6cSJonas Devlieghere                elif line.startswith("from adapter:"):
53301263c6cSJonas Devlieghere                    mode = "recv"
53401263c6cSJonas Devlieghere            elif mode == "send":
53501263c6cSJonas Devlieghere                command_dict = read_packet(f)
53601263c6cSJonas Devlieghere                # Skip the end of line that follows the JSON
53701263c6cSJonas Devlieghere                f.readline()
53801263c6cSJonas Devlieghere                if command_dict is None:
53901263c6cSJonas Devlieghere                    raise ValueError("decode packet failed from replay file")
54001263c6cSJonas Devlieghere                print("Sending:")
54101263c6cSJonas Devlieghere                pprint.PrettyPrinter(indent=2).pprint(command_dict)
54201263c6cSJonas Devlieghere                # raw_input('Press ENTER to send:')
54301263c6cSJonas Devlieghere                self.send_packet(command_dict, set_sequence)
54401263c6cSJonas Devlieghere                mode = "invalid"
54501263c6cSJonas Devlieghere            elif mode == "recv":
54601263c6cSJonas Devlieghere                print("Replay response:")
54701263c6cSJonas Devlieghere                replay_response = read_packet(f)
54801263c6cSJonas Devlieghere                # Skip the end of line that follows the JSON
54901263c6cSJonas Devlieghere                f.readline()
55001263c6cSJonas Devlieghere                pprint.PrettyPrinter(indent=2).pprint(replay_response)
55101263c6cSJonas Devlieghere                actual_response = self.recv_packet()
55201263c6cSJonas Devlieghere                if actual_response:
55301263c6cSJonas Devlieghere                    type = actual_response["type"]
55401263c6cSJonas Devlieghere                    print("Actual response:")
55501263c6cSJonas Devlieghere                    if type == "response":
55601263c6cSJonas Devlieghere                        self.validate_response(command_dict, actual_response)
55701263c6cSJonas Devlieghere                    pprint.PrettyPrinter(indent=2).pprint(actual_response)
55801263c6cSJonas Devlieghere                else:
55901263c6cSJonas Devlieghere                    print("error: didn't get a valid response")
56001263c6cSJonas Devlieghere                mode = "invalid"
56101263c6cSJonas Devlieghere
56201263c6cSJonas Devlieghere    def request_attach(
56301263c6cSJonas Devlieghere        self,
56401263c6cSJonas Devlieghere        program=None,
56501263c6cSJonas Devlieghere        pid=None,
56601263c6cSJonas Devlieghere        waitFor=None,
56701263c6cSJonas Devlieghere        trace=None,
56801263c6cSJonas Devlieghere        initCommands=None,
56901263c6cSJonas Devlieghere        preRunCommands=None,
57001263c6cSJonas Devlieghere        stopCommands=None,
57101263c6cSJonas Devlieghere        exitCommands=None,
57201263c6cSJonas Devlieghere        attachCommands=None,
57301263c6cSJonas Devlieghere        terminateCommands=None,
57401263c6cSJonas Devlieghere        coreFile=None,
57501263c6cSJonas Devlieghere        postRunCommands=None,
57601263c6cSJonas Devlieghere        sourceMap=None,
577a52be0ccSSanthosh Kumar Ellendula        gdbRemotePort=None,
578a52be0ccSSanthosh Kumar Ellendula        gdbRemoteHostname=None,
57901263c6cSJonas Devlieghere    ):
58001263c6cSJonas Devlieghere        args_dict = {}
58101263c6cSJonas Devlieghere        if pid is not None:
58201263c6cSJonas Devlieghere            args_dict["pid"] = pid
58301263c6cSJonas Devlieghere        if program is not None:
58401263c6cSJonas Devlieghere            args_dict["program"] = program
58501263c6cSJonas Devlieghere        if waitFor is not None:
58601263c6cSJonas Devlieghere            args_dict["waitFor"] = waitFor
58701263c6cSJonas Devlieghere        if trace:
58801263c6cSJonas Devlieghere            args_dict["trace"] = trace
58901263c6cSJonas Devlieghere        args_dict["initCommands"] = self.init_commands
59001263c6cSJonas Devlieghere        if initCommands:
59101263c6cSJonas Devlieghere            args_dict["initCommands"].extend(initCommands)
59201263c6cSJonas Devlieghere        if preRunCommands:
59301263c6cSJonas Devlieghere            args_dict["preRunCommands"] = preRunCommands
59401263c6cSJonas Devlieghere        if stopCommands:
59501263c6cSJonas Devlieghere            args_dict["stopCommands"] = stopCommands
59601263c6cSJonas Devlieghere        if exitCommands:
59701263c6cSJonas Devlieghere            args_dict["exitCommands"] = exitCommands
59801263c6cSJonas Devlieghere        if terminateCommands:
59901263c6cSJonas Devlieghere            args_dict["terminateCommands"] = terminateCommands
60001263c6cSJonas Devlieghere        if attachCommands:
60101263c6cSJonas Devlieghere            args_dict["attachCommands"] = attachCommands
60201263c6cSJonas Devlieghere        if coreFile:
60301263c6cSJonas Devlieghere            args_dict["coreFile"] = coreFile
60401263c6cSJonas Devlieghere        if postRunCommands:
60501263c6cSJonas Devlieghere            args_dict["postRunCommands"] = postRunCommands
60601263c6cSJonas Devlieghere        if sourceMap:
60701263c6cSJonas Devlieghere            args_dict["sourceMap"] = sourceMap
608a52be0ccSSanthosh Kumar Ellendula        if gdbRemotePort is not None:
609a52be0ccSSanthosh Kumar Ellendula            args_dict["gdb-remote-port"] = gdbRemotePort
610a52be0ccSSanthosh Kumar Ellendula        if gdbRemoteHostname is not None:
611a52be0ccSSanthosh Kumar Ellendula            args_dict["gdb-remote-hostname"] = gdbRemoteHostname
61201263c6cSJonas Devlieghere        command_dict = {"command": "attach", "type": "request", "arguments": args_dict}
61301263c6cSJonas Devlieghere        return self.send_recv(command_dict)
61401263c6cSJonas Devlieghere
61501263c6cSJonas Devlieghere    def request_configurationDone(self):
61601263c6cSJonas Devlieghere        command_dict = {
61701263c6cSJonas Devlieghere            "command": "configurationDone",
61801263c6cSJonas Devlieghere            "type": "request",
61901263c6cSJonas Devlieghere            "arguments": {},
62001263c6cSJonas Devlieghere        }
62101263c6cSJonas Devlieghere        response = self.send_recv(command_dict)
62201263c6cSJonas Devlieghere        if response:
62301263c6cSJonas Devlieghere            self.configuration_done_sent = True
62401263c6cSJonas Devlieghere        return response
62501263c6cSJonas Devlieghere
62601263c6cSJonas Devlieghere    def _process_stopped(self):
62701263c6cSJonas Devlieghere        self.threads = None
62801263c6cSJonas Devlieghere        self.frame_scopes = {}
62901263c6cSJonas Devlieghere
63001263c6cSJonas Devlieghere    def request_continue(self, threadId=None):
63101263c6cSJonas Devlieghere        if self.exit_status is not None:
63201263c6cSJonas Devlieghere            raise ValueError("request_continue called after process exited")
63301263c6cSJonas Devlieghere        # If we have launched or attached, then the first continue is done by
63401263c6cSJonas Devlieghere        # sending the 'configurationDone' request
63501263c6cSJonas Devlieghere        if not self.configuration_done_sent:
63601263c6cSJonas Devlieghere            return self.request_configurationDone()
63701263c6cSJonas Devlieghere        args_dict = {}
63801263c6cSJonas Devlieghere        if threadId is None:
63901263c6cSJonas Devlieghere            threadId = self.get_thread_id()
64001263c6cSJonas Devlieghere        args_dict["threadId"] = threadId
64101263c6cSJonas Devlieghere        command_dict = {
64201263c6cSJonas Devlieghere            "command": "continue",
64301263c6cSJonas Devlieghere            "type": "request",
64401263c6cSJonas Devlieghere            "arguments": args_dict,
64501263c6cSJonas Devlieghere        }
64601263c6cSJonas Devlieghere        response = self.send_recv(command_dict)
64701263c6cSJonas Devlieghere        # Caller must still call wait_for_stopped.
64801263c6cSJonas Devlieghere        return response
64901263c6cSJonas Devlieghere
65001263c6cSJonas Devlieghere    def request_restart(self, restartArguments=None):
65101263c6cSJonas Devlieghere        command_dict = {
65201263c6cSJonas Devlieghere            "command": "restart",
65301263c6cSJonas Devlieghere            "type": "request",
65401263c6cSJonas Devlieghere        }
65501263c6cSJonas Devlieghere        if restartArguments:
65601263c6cSJonas Devlieghere            command_dict["arguments"] = restartArguments
65701263c6cSJonas Devlieghere
65801263c6cSJonas Devlieghere        response = self.send_recv(command_dict)
65901263c6cSJonas Devlieghere        # Caller must still call wait_for_stopped.
66001263c6cSJonas Devlieghere        return response
66101263c6cSJonas Devlieghere
66201263c6cSJonas Devlieghere    def request_disconnect(self, terminateDebuggee=None):
66301263c6cSJonas Devlieghere        args_dict = {}
66401263c6cSJonas Devlieghere        if terminateDebuggee is not None:
66501263c6cSJonas Devlieghere            if terminateDebuggee:
66601263c6cSJonas Devlieghere                args_dict["terminateDebuggee"] = True
66701263c6cSJonas Devlieghere            else:
66801263c6cSJonas Devlieghere                args_dict["terminateDebuggee"] = False
66901263c6cSJonas Devlieghere        command_dict = {
67001263c6cSJonas Devlieghere            "command": "disconnect",
67101263c6cSJonas Devlieghere            "type": "request",
67201263c6cSJonas Devlieghere            "arguments": args_dict,
67301263c6cSJonas Devlieghere        }
67401263c6cSJonas Devlieghere        return self.send_recv(command_dict)
67501263c6cSJonas Devlieghere
67601263c6cSJonas Devlieghere    def request_disassemble(
67701263c6cSJonas Devlieghere        self, memoryReference, offset=-50, instructionCount=200, resolveSymbols=True
67801263c6cSJonas Devlieghere    ):
67901263c6cSJonas Devlieghere        args_dict = {
68001263c6cSJonas Devlieghere            "memoryReference": memoryReference,
68101263c6cSJonas Devlieghere            "offset": offset,
68201263c6cSJonas Devlieghere            "instructionCount": instructionCount,
68301263c6cSJonas Devlieghere            "resolveSymbols": resolveSymbols,
68401263c6cSJonas Devlieghere        }
68501263c6cSJonas Devlieghere        command_dict = {
68601263c6cSJonas Devlieghere            "command": "disassemble",
68701263c6cSJonas Devlieghere            "type": "request",
68801263c6cSJonas Devlieghere            "arguments": args_dict,
68901263c6cSJonas Devlieghere        }
69001263c6cSJonas Devlieghere        instructions = self.send_recv(command_dict)["body"]["instructions"]
69101263c6cSJonas Devlieghere        for inst in instructions:
69201263c6cSJonas Devlieghere            self.disassembled_instructions[inst["address"]] = inst
69301263c6cSJonas Devlieghere
6943acb1eacSAdrian Vogelsgesang    def request_readMemory(self, memoryReference, offset, count):
6953acb1eacSAdrian Vogelsgesang        args_dict = {
6963acb1eacSAdrian Vogelsgesang            "memoryReference": memoryReference,
6973acb1eacSAdrian Vogelsgesang            "offset": offset,
6983acb1eacSAdrian Vogelsgesang            "count": count,
6993acb1eacSAdrian Vogelsgesang        }
7003acb1eacSAdrian Vogelsgesang        command_dict = {
7013acb1eacSAdrian Vogelsgesang            "command": "readMemory",
7023acb1eacSAdrian Vogelsgesang            "type": "request",
7033acb1eacSAdrian Vogelsgesang            "arguments": args_dict,
7043acb1eacSAdrian Vogelsgesang        }
7053acb1eacSAdrian Vogelsgesang        return self.send_recv(command_dict)
7063acb1eacSAdrian Vogelsgesang
70701263c6cSJonas Devlieghere    def request_evaluate(self, expression, frameIndex=0, threadId=None, context=None):
70801263c6cSJonas Devlieghere        stackFrame = self.get_stackFrame(frameIndex=frameIndex, threadId=threadId)
70901263c6cSJonas Devlieghere        if stackFrame is None:
71001263c6cSJonas Devlieghere            return []
71101263c6cSJonas Devlieghere        args_dict = {
71201263c6cSJonas Devlieghere            "expression": expression,
71301263c6cSJonas Devlieghere            "context": context,
71401263c6cSJonas Devlieghere            "frameId": stackFrame["id"],
71501263c6cSJonas Devlieghere        }
71601263c6cSJonas Devlieghere        command_dict = {
71701263c6cSJonas Devlieghere            "command": "evaluate",
71801263c6cSJonas Devlieghere            "type": "request",
71901263c6cSJonas Devlieghere            "arguments": args_dict,
72001263c6cSJonas Devlieghere        }
72101263c6cSJonas Devlieghere        return self.send_recv(command_dict)
72201263c6cSJonas Devlieghere
7235b4100ccSJohn Harrison    def request_exceptionInfo(self, threadId=None):
7245b4100ccSJohn Harrison        if threadId is None:
7255b4100ccSJohn Harrison            threadId = self.get_thread_id()
7265b4100ccSJohn Harrison        args_dict = {"threadId": threadId}
7275b4100ccSJohn Harrison        command_dict = {
7285b4100ccSJohn Harrison            "command": "exceptionInfo",
7295b4100ccSJohn Harrison            "type": "request",
7305b4100ccSJohn Harrison            "arguments": args_dict,
7315b4100ccSJohn Harrison        }
7325b4100ccSJohn Harrison        return self.send_recv(command_dict)
7335b4100ccSJohn Harrison
73401263c6cSJonas Devlieghere    def request_initialize(self, sourceInitFile):
73501263c6cSJonas Devlieghere        command_dict = {
73601263c6cSJonas Devlieghere            "command": "initialize",
73701263c6cSJonas Devlieghere            "type": "request",
73801263c6cSJonas Devlieghere            "arguments": {
73901263c6cSJonas Devlieghere                "adapterID": "lldb-native",
74001263c6cSJonas Devlieghere                "clientID": "vscode",
74101263c6cSJonas Devlieghere                "columnsStartAt1": True,
74201263c6cSJonas Devlieghere                "linesStartAt1": True,
74301263c6cSJonas Devlieghere                "locale": "en-us",
74401263c6cSJonas Devlieghere                "pathFormat": "path",
74501263c6cSJonas Devlieghere                "supportsRunInTerminalRequest": True,
74601263c6cSJonas Devlieghere                "supportsVariablePaging": True,
74701263c6cSJonas Devlieghere                "supportsVariableType": True,
74801263c6cSJonas Devlieghere                "supportsStartDebuggingRequest": True,
74901263c6cSJonas Devlieghere                "sourceInitFile": sourceInitFile,
75001263c6cSJonas Devlieghere            },
75101263c6cSJonas Devlieghere        }
75201263c6cSJonas Devlieghere        response = self.send_recv(command_dict)
75301263c6cSJonas Devlieghere        if response:
75401263c6cSJonas Devlieghere            if "body" in response:
75501263c6cSJonas Devlieghere                self.initialize_body = response["body"]
75601263c6cSJonas Devlieghere        return response
75701263c6cSJonas Devlieghere
75801263c6cSJonas Devlieghere    def request_launch(
75901263c6cSJonas Devlieghere        self,
76001263c6cSJonas Devlieghere        program,
76101263c6cSJonas Devlieghere        args=None,
76201263c6cSJonas Devlieghere        cwd=None,
76301263c6cSJonas Devlieghere        env=None,
76401263c6cSJonas Devlieghere        stopOnEntry=False,
76501263c6cSJonas Devlieghere        disableASLR=True,
76601263c6cSJonas Devlieghere        disableSTDIO=False,
76701263c6cSJonas Devlieghere        shellExpandArguments=False,
76801263c6cSJonas Devlieghere        trace=False,
76901263c6cSJonas Devlieghere        initCommands=None,
77001263c6cSJonas Devlieghere        preRunCommands=None,
77101263c6cSJonas Devlieghere        stopCommands=None,
77201263c6cSJonas Devlieghere        exitCommands=None,
77301263c6cSJonas Devlieghere        terminateCommands=None,
77401263c6cSJonas Devlieghere        sourcePath=None,
77501263c6cSJonas Devlieghere        debuggerRoot=None,
77601263c6cSJonas Devlieghere        launchCommands=None,
77701263c6cSJonas Devlieghere        sourceMap=None,
77801263c6cSJonas Devlieghere        runInTerminal=False,
77901263c6cSJonas Devlieghere        postRunCommands=None,
78001263c6cSJonas Devlieghere        enableAutoVariableSummaries=False,
78119ecdedcSAdrian Vogelsgesang        displayExtendedBacktrace=False,
78201263c6cSJonas Devlieghere        enableSyntheticChildDebugging=False,
78385ee3fc7Sjeffreytan81        commandEscapePrefix=None,
784d9ec4b24SWalter Erquinigo        customFrameFormat=None,
7851654d7dcSWalter Erquinigo        customThreadFormat=None,
78601263c6cSJonas Devlieghere    ):
78701263c6cSJonas Devlieghere        args_dict = {"program": program}
78801263c6cSJonas Devlieghere        if args:
78901263c6cSJonas Devlieghere            args_dict["args"] = args
79001263c6cSJonas Devlieghere        if cwd:
79101263c6cSJonas Devlieghere            args_dict["cwd"] = cwd
79201263c6cSJonas Devlieghere        if env:
79301263c6cSJonas Devlieghere            args_dict["env"] = env
79401263c6cSJonas Devlieghere        if stopOnEntry:
79501263c6cSJonas Devlieghere            args_dict["stopOnEntry"] = stopOnEntry
79601263c6cSJonas Devlieghere        if disableSTDIO:
79701263c6cSJonas Devlieghere            args_dict["disableSTDIO"] = disableSTDIO
79801263c6cSJonas Devlieghere        if shellExpandArguments:
79901263c6cSJonas Devlieghere            args_dict["shellExpandArguments"] = shellExpandArguments
80001263c6cSJonas Devlieghere        if trace:
80101263c6cSJonas Devlieghere            args_dict["trace"] = trace
80201263c6cSJonas Devlieghere        args_dict["initCommands"] = self.init_commands
80301263c6cSJonas Devlieghere        if initCommands:
80401263c6cSJonas Devlieghere            args_dict["initCommands"].extend(initCommands)
80501263c6cSJonas Devlieghere        if preRunCommands:
80601263c6cSJonas Devlieghere            args_dict["preRunCommands"] = preRunCommands
80701263c6cSJonas Devlieghere        if stopCommands:
80801263c6cSJonas Devlieghere            args_dict["stopCommands"] = stopCommands
80901263c6cSJonas Devlieghere        if exitCommands:
81001263c6cSJonas Devlieghere            args_dict["exitCommands"] = exitCommands
81101263c6cSJonas Devlieghere        if terminateCommands:
81201263c6cSJonas Devlieghere            args_dict["terminateCommands"] = terminateCommands
81301263c6cSJonas Devlieghere        if sourcePath:
81401263c6cSJonas Devlieghere            args_dict["sourcePath"] = sourcePath
81501263c6cSJonas Devlieghere        if debuggerRoot:
81601263c6cSJonas Devlieghere            args_dict["debuggerRoot"] = debuggerRoot
81701263c6cSJonas Devlieghere        if launchCommands:
81801263c6cSJonas Devlieghere            args_dict["launchCommands"] = launchCommands
81901263c6cSJonas Devlieghere        if sourceMap:
82001263c6cSJonas Devlieghere            args_dict["sourceMap"] = sourceMap
82101263c6cSJonas Devlieghere        if runInTerminal:
82201263c6cSJonas Devlieghere            args_dict["runInTerminal"] = runInTerminal
82301263c6cSJonas Devlieghere        if postRunCommands:
82401263c6cSJonas Devlieghere            args_dict["postRunCommands"] = postRunCommands
825d9ec4b24SWalter Erquinigo        if customFrameFormat:
826d9ec4b24SWalter Erquinigo            args_dict["customFrameFormat"] = customFrameFormat
8271654d7dcSWalter Erquinigo        if customThreadFormat:
8281654d7dcSWalter Erquinigo            args_dict["customThreadFormat"] = customThreadFormat
829d9ec4b24SWalter Erquinigo
830b4e1af00SMichael Buch        args_dict["disableASLR"] = disableASLR
83101263c6cSJonas Devlieghere        args_dict["enableAutoVariableSummaries"] = enableAutoVariableSummaries
83201263c6cSJonas Devlieghere        args_dict["enableSyntheticChildDebugging"] = enableSyntheticChildDebugging
83319ecdedcSAdrian Vogelsgesang        args_dict["displayExtendedBacktrace"] = displayExtendedBacktrace
83410664813SWalter Erquinigo        args_dict["commandEscapePrefix"] = commandEscapePrefix
83501263c6cSJonas Devlieghere        command_dict = {"command": "launch", "type": "request", "arguments": args_dict}
83601263c6cSJonas Devlieghere        response = self.send_recv(command_dict)
83701263c6cSJonas Devlieghere
83801263c6cSJonas Devlieghere        if response["success"]:
83901263c6cSJonas Devlieghere            # Wait for a 'process' and 'initialized' event in any order
84001263c6cSJonas Devlieghere            self.wait_for_event(filter=["process", "initialized"])
84101263c6cSJonas Devlieghere            self.wait_for_event(filter=["process", "initialized"])
84201263c6cSJonas Devlieghere        return response
84301263c6cSJonas Devlieghere
8446257a98bSAdrian Vogelsgesang    def request_next(self, threadId, granularity="statement"):
84501263c6cSJonas Devlieghere        if self.exit_status is not None:
84601263c6cSJonas Devlieghere            raise ValueError("request_continue called after process exited")
8476257a98bSAdrian Vogelsgesang        args_dict = {"threadId": threadId, "granularity": granularity}
84801263c6cSJonas Devlieghere        command_dict = {"command": "next", "type": "request", "arguments": args_dict}
84901263c6cSJonas Devlieghere        return self.send_recv(command_dict)
85001263c6cSJonas Devlieghere
8516257a98bSAdrian Vogelsgesang    def request_stepIn(self, threadId, targetId, granularity="statement"):
85201263c6cSJonas Devlieghere        if self.exit_status is not None:
8532f2e31c3Sjeffreytan81            raise ValueError("request_stepIn called after process exited")
8546257a98bSAdrian Vogelsgesang        args_dict = {
8556257a98bSAdrian Vogelsgesang            "threadId": threadId,
8566257a98bSAdrian Vogelsgesang            "targetId": targetId,
8576257a98bSAdrian Vogelsgesang            "granularity": granularity,
8586257a98bSAdrian Vogelsgesang        }
85901263c6cSJonas Devlieghere        command_dict = {"command": "stepIn", "type": "request", "arguments": args_dict}
86001263c6cSJonas Devlieghere        return self.send_recv(command_dict)
86101263c6cSJonas Devlieghere
8622f2e31c3Sjeffreytan81    def request_stepInTargets(self, frameId):
8632f2e31c3Sjeffreytan81        if self.exit_status is not None:
8642f2e31c3Sjeffreytan81            raise ValueError("request_stepInTargets called after process exited")
8652f2e31c3Sjeffreytan81        args_dict = {"frameId": frameId}
8662f2e31c3Sjeffreytan81        command_dict = {
8672f2e31c3Sjeffreytan81            "command": "stepInTargets",
8682f2e31c3Sjeffreytan81            "type": "request",
8692f2e31c3Sjeffreytan81            "arguments": args_dict,
8702f2e31c3Sjeffreytan81        }
8712f2e31c3Sjeffreytan81        return self.send_recv(command_dict)
8722f2e31c3Sjeffreytan81
87301263c6cSJonas Devlieghere    def request_stepOut(self, threadId):
87401263c6cSJonas Devlieghere        if self.exit_status is not None:
8752f2e31c3Sjeffreytan81            raise ValueError("request_stepOut called after process exited")
87601263c6cSJonas Devlieghere        args_dict = {"threadId": threadId}
87701263c6cSJonas Devlieghere        command_dict = {"command": "stepOut", "type": "request", "arguments": args_dict}
87801263c6cSJonas Devlieghere        return self.send_recv(command_dict)
87901263c6cSJonas Devlieghere
88001263c6cSJonas Devlieghere    def request_pause(self, threadId=None):
88101263c6cSJonas Devlieghere        if self.exit_status is not None:
8822f2e31c3Sjeffreytan81            raise ValueError("request_pause called after process exited")
88301263c6cSJonas Devlieghere        if threadId is None:
88401263c6cSJonas Devlieghere            threadId = self.get_thread_id()
88501263c6cSJonas Devlieghere        args_dict = {"threadId": threadId}
88601263c6cSJonas Devlieghere        command_dict = {"command": "pause", "type": "request", "arguments": args_dict}
88701263c6cSJonas Devlieghere        return self.send_recv(command_dict)
88801263c6cSJonas Devlieghere
88901263c6cSJonas Devlieghere    def request_scopes(self, frameId):
89001263c6cSJonas Devlieghere        args_dict = {"frameId": frameId}
89101263c6cSJonas Devlieghere        command_dict = {"command": "scopes", "type": "request", "arguments": args_dict}
89201263c6cSJonas Devlieghere        return self.send_recv(command_dict)
89301263c6cSJonas Devlieghere
89401263c6cSJonas Devlieghere    def request_setBreakpoints(self, file_path, line_array, data=None):
89501263c6cSJonas Devlieghere        """data is array of parameters for breakpoints in line_array.
89601263c6cSJonas Devlieghere        Each parameter object is 1:1 mapping with entries in line_entry.
89701263c6cSJonas Devlieghere        It contains optional location/hitCondition/logMessage parameters.
89801263c6cSJonas Devlieghere        """
89901263c6cSJonas Devlieghere        (dir, base) = os.path.split(file_path)
90001263c6cSJonas Devlieghere        source_dict = {"name": base, "path": file_path}
90101263c6cSJonas Devlieghere        args_dict = {
90201263c6cSJonas Devlieghere            "source": source_dict,
90301263c6cSJonas Devlieghere            "sourceModified": False,
90401263c6cSJonas Devlieghere        }
90501263c6cSJonas Devlieghere        if line_array is not None:
90601263c6cSJonas Devlieghere            args_dict["lines"] = "%s" % line_array
90701263c6cSJonas Devlieghere            breakpoints = []
90801263c6cSJonas Devlieghere            for i, line in enumerate(line_array):
90901263c6cSJonas Devlieghere                breakpoint_data = None
91001263c6cSJonas Devlieghere                if data is not None and i < len(data):
91101263c6cSJonas Devlieghere                    breakpoint_data = data[i]
91201263c6cSJonas Devlieghere                bp = {"line": line}
91301263c6cSJonas Devlieghere                if breakpoint_data is not None:
914*ceeb08b9SMichael Buch                    if "condition" in breakpoint_data and breakpoint_data["condition"]:
91501263c6cSJonas Devlieghere                        bp["condition"] = breakpoint_data["condition"]
916*ceeb08b9SMichael Buch                    if (
917*ceeb08b9SMichael Buch                        "hitCondition" in breakpoint_data
918*ceeb08b9SMichael Buch                        and breakpoint_data["hitCondition"]
919*ceeb08b9SMichael Buch                    ):
92001263c6cSJonas Devlieghere                        bp["hitCondition"] = breakpoint_data["hitCondition"]
921*ceeb08b9SMichael Buch                    if (
922*ceeb08b9SMichael Buch                        "logMessage" in breakpoint_data
923*ceeb08b9SMichael Buch                        and breakpoint_data["logMessage"]
924*ceeb08b9SMichael Buch                    ):
92501263c6cSJonas Devlieghere                        bp["logMessage"] = breakpoint_data["logMessage"]
92601263c6cSJonas Devlieghere                breakpoints.append(bp)
92701263c6cSJonas Devlieghere            args_dict["breakpoints"] = breakpoints
92801263c6cSJonas Devlieghere
92901263c6cSJonas Devlieghere        command_dict = {
93001263c6cSJonas Devlieghere            "command": "setBreakpoints",
93101263c6cSJonas Devlieghere            "type": "request",
93201263c6cSJonas Devlieghere            "arguments": args_dict,
93301263c6cSJonas Devlieghere        }
93401263c6cSJonas Devlieghere        return self.send_recv(command_dict)
93501263c6cSJonas Devlieghere
93601263c6cSJonas Devlieghere    def request_setExceptionBreakpoints(self, filters):
93701263c6cSJonas Devlieghere        args_dict = {"filters": filters}
93801263c6cSJonas Devlieghere        command_dict = {
93901263c6cSJonas Devlieghere            "command": "setExceptionBreakpoints",
94001263c6cSJonas Devlieghere            "type": "request",
94101263c6cSJonas Devlieghere            "arguments": args_dict,
94201263c6cSJonas Devlieghere        }
94301263c6cSJonas Devlieghere        return self.send_recv(command_dict)
94401263c6cSJonas Devlieghere
94501263c6cSJonas Devlieghere    def request_setFunctionBreakpoints(self, names, condition=None, hitCondition=None):
94601263c6cSJonas Devlieghere        breakpoints = []
94701263c6cSJonas Devlieghere        for name in names:
94801263c6cSJonas Devlieghere            bp = {"name": name}
94901263c6cSJonas Devlieghere            if condition is not None:
95001263c6cSJonas Devlieghere                bp["condition"] = condition
95101263c6cSJonas Devlieghere            if hitCondition is not None:
95201263c6cSJonas Devlieghere                bp["hitCondition"] = hitCondition
95301263c6cSJonas Devlieghere            breakpoints.append(bp)
95401263c6cSJonas Devlieghere        args_dict = {"breakpoints": breakpoints}
95501263c6cSJonas Devlieghere        command_dict = {
95601263c6cSJonas Devlieghere            "command": "setFunctionBreakpoints",
95701263c6cSJonas Devlieghere            "type": "request",
95801263c6cSJonas Devlieghere            "arguments": args_dict,
95901263c6cSJonas Devlieghere        }
96001263c6cSJonas Devlieghere        return self.send_recv(command_dict)
96101263c6cSJonas Devlieghere
962df6f756aSZequan Wu    def request_dataBreakpointInfo(
963df6f756aSZequan Wu        self, variablesReference, name, frameIndex=0, threadId=None
964df6f756aSZequan Wu    ):
965df6f756aSZequan Wu        stackFrame = self.get_stackFrame(frameIndex=frameIndex, threadId=threadId)
966df6f756aSZequan Wu        if stackFrame is None:
967df6f756aSZequan Wu            return []
968df6f756aSZequan Wu        args_dict = {
969df6f756aSZequan Wu            "variablesReference": variablesReference,
970df6f756aSZequan Wu            "name": name,
971df6f756aSZequan Wu            "frameId": stackFrame["id"],
972df6f756aSZequan Wu        }
973df6f756aSZequan Wu        command_dict = {
974df6f756aSZequan Wu            "command": "dataBreakpointInfo",
975df6f756aSZequan Wu            "type": "request",
976df6f756aSZequan Wu            "arguments": args_dict,
977df6f756aSZequan Wu        }
978df6f756aSZequan Wu        return self.send_recv(command_dict)
979df6f756aSZequan Wu
980df6f756aSZequan Wu    def request_setDataBreakpoint(self, dataBreakpoints):
981df6f756aSZequan Wu        """dataBreakpoints is a list of dictionary with following fields:
982df6f756aSZequan Wu        {
983df6f756aSZequan Wu            dataId: (address in hex)/(size in bytes)
984df6f756aSZequan Wu            accessType: read/write/readWrite
985df6f756aSZequan Wu            [condition]: string
986df6f756aSZequan Wu            [hitCondition]: string
987df6f756aSZequan Wu        }
988df6f756aSZequan Wu        """
989df6f756aSZequan Wu        args_dict = {"breakpoints": dataBreakpoints}
990df6f756aSZequan Wu        command_dict = {
991df6f756aSZequan Wu            "command": "setDataBreakpoints",
992df6f756aSZequan Wu            "type": "request",
993df6f756aSZequan Wu            "arguments": args_dict,
994df6f756aSZequan Wu        }
995df6f756aSZequan Wu        return self.send_recv(command_dict)
996df6f756aSZequan Wu
99701263c6cSJonas Devlieghere    def request_compileUnits(self, moduleId):
99801263c6cSJonas Devlieghere        args_dict = {"moduleId": moduleId}
99901263c6cSJonas Devlieghere        command_dict = {
100001263c6cSJonas Devlieghere            "command": "compileUnits",
100101263c6cSJonas Devlieghere            "type": "request",
100201263c6cSJonas Devlieghere            "arguments": args_dict,
100301263c6cSJonas Devlieghere        }
100401263c6cSJonas Devlieghere        response = self.send_recv(command_dict)
100501263c6cSJonas Devlieghere        return response
100601263c6cSJonas Devlieghere
100701263c6cSJonas Devlieghere    def request_completions(self, text, frameId=None):
1008a5876befSAdrian Vogelsgesang        args_dict = {"text": text, "column": len(text) + 1}
100901263c6cSJonas Devlieghere        if frameId:
101001263c6cSJonas Devlieghere            args_dict["frameId"] = frameId
101101263c6cSJonas Devlieghere        command_dict = {
101201263c6cSJonas Devlieghere            "command": "completions",
101301263c6cSJonas Devlieghere            "type": "request",
101401263c6cSJonas Devlieghere            "arguments": args_dict,
101501263c6cSJonas Devlieghere        }
101601263c6cSJonas Devlieghere        return self.send_recv(command_dict)
101701263c6cSJonas Devlieghere
101801263c6cSJonas Devlieghere    def request_modules(self):
101901263c6cSJonas Devlieghere        return self.send_recv({"command": "modules", "type": "request"})
102001263c6cSJonas Devlieghere
102101263c6cSJonas Devlieghere    def request_stackTrace(
102201263c6cSJonas Devlieghere        self, threadId=None, startFrame=None, levels=None, dump=False
102301263c6cSJonas Devlieghere    ):
102401263c6cSJonas Devlieghere        if threadId is None:
102501263c6cSJonas Devlieghere            threadId = self.get_thread_id()
102601263c6cSJonas Devlieghere        args_dict = {"threadId": threadId}
102701263c6cSJonas Devlieghere        if startFrame is not None:
102801263c6cSJonas Devlieghere            args_dict["startFrame"] = startFrame
102901263c6cSJonas Devlieghere        if levels is not None:
103001263c6cSJonas Devlieghere            args_dict["levels"] = levels
103101263c6cSJonas Devlieghere        command_dict = {
103201263c6cSJonas Devlieghere            "command": "stackTrace",
103301263c6cSJonas Devlieghere            "type": "request",
103401263c6cSJonas Devlieghere            "arguments": args_dict,
103501263c6cSJonas Devlieghere        }
103601263c6cSJonas Devlieghere        response = self.send_recv(command_dict)
103701263c6cSJonas Devlieghere        if dump:
103801263c6cSJonas Devlieghere            for idx, frame in enumerate(response["body"]["stackFrames"]):
103901263c6cSJonas Devlieghere                name = frame["name"]
104001263c6cSJonas Devlieghere                if "line" in frame and "source" in frame:
104101263c6cSJonas Devlieghere                    source = frame["source"]
104201263c6cSJonas Devlieghere                    if "sourceReference" not in source:
104301263c6cSJonas Devlieghere                        if "name" in source:
104401263c6cSJonas Devlieghere                            source_name = source["name"]
104501263c6cSJonas Devlieghere                            line = frame["line"]
104601263c6cSJonas Devlieghere                            print("[%3u] %s @ %s:%u" % (idx, name, source_name, line))
104701263c6cSJonas Devlieghere                            continue
104801263c6cSJonas Devlieghere                print("[%3u] %s" % (idx, name))
104901263c6cSJonas Devlieghere        return response
105001263c6cSJonas Devlieghere
105101263c6cSJonas Devlieghere    def request_threads(self):
105201263c6cSJonas Devlieghere        """Request a list of all threads and combine any information from any
105301263c6cSJonas Devlieghere        "stopped" events since those contain more information about why a
105401263c6cSJonas Devlieghere        thread actually stopped. Returns an array of thread dictionaries
105501263c6cSJonas Devlieghere        with information about all threads"""
105601263c6cSJonas Devlieghere        command_dict = {"command": "threads", "type": "request", "arguments": {}}
105701263c6cSJonas Devlieghere        response = self.send_recv(command_dict)
105801263c6cSJonas Devlieghere        body = response["body"]
105901263c6cSJonas Devlieghere        # Fill in "self.threads" correctly so that clients that call
106001263c6cSJonas Devlieghere        # self.get_threads() or self.get_thread_id(...) can get information
106101263c6cSJonas Devlieghere        # on threads when the process is stopped.
106201263c6cSJonas Devlieghere        if "threads" in body:
106301263c6cSJonas Devlieghere            self.threads = body["threads"]
106401263c6cSJonas Devlieghere            for thread in self.threads:
106501263c6cSJonas Devlieghere                # Copy the thread dictionary so we can add key/value pairs to
106601263c6cSJonas Devlieghere                # it without affecting the original info from the "threads"
106701263c6cSJonas Devlieghere                # command.
106801263c6cSJonas Devlieghere                tid = thread["id"]
106901263c6cSJonas Devlieghere                if tid in self.thread_stop_reasons:
107001263c6cSJonas Devlieghere                    thread_stop_info = self.thread_stop_reasons[tid]
107101263c6cSJonas Devlieghere                    copy_keys = ["reason", "description", "text"]
107201263c6cSJonas Devlieghere                    for key in copy_keys:
107301263c6cSJonas Devlieghere                        if key in thread_stop_info:
107401263c6cSJonas Devlieghere                            thread[key] = thread_stop_info[key]
107501263c6cSJonas Devlieghere        else:
107601263c6cSJonas Devlieghere            self.threads = None
107701263c6cSJonas Devlieghere        return response
107801263c6cSJonas Devlieghere
1079b8d38bb5Sjeffreytan81    def request_variables(
1080b8d38bb5Sjeffreytan81        self, variablesReference, start=None, count=None, is_hex=None
1081b8d38bb5Sjeffreytan81    ):
108201263c6cSJonas Devlieghere        args_dict = {"variablesReference": variablesReference}
108301263c6cSJonas Devlieghere        if start is not None:
108401263c6cSJonas Devlieghere            args_dict["start"] = start
108501263c6cSJonas Devlieghere        if count is not None:
108601263c6cSJonas Devlieghere            args_dict["count"] = count
1087b8d38bb5Sjeffreytan81        if is_hex is not None:
1088b8d38bb5Sjeffreytan81            args_dict["format"] = {"hex": is_hex}
108901263c6cSJonas Devlieghere        command_dict = {
109001263c6cSJonas Devlieghere            "command": "variables",
109101263c6cSJonas Devlieghere            "type": "request",
109201263c6cSJonas Devlieghere            "arguments": args_dict,
109301263c6cSJonas Devlieghere        }
109401263c6cSJonas Devlieghere        return self.send_recv(command_dict)
109501263c6cSJonas Devlieghere
109601263c6cSJonas Devlieghere    def request_setVariable(self, containingVarRef, name, value, id=None):
109701263c6cSJonas Devlieghere        args_dict = {
109801263c6cSJonas Devlieghere            "variablesReference": containingVarRef,
109901263c6cSJonas Devlieghere            "name": name,
110001263c6cSJonas Devlieghere            "value": str(value),
110101263c6cSJonas Devlieghere        }
110201263c6cSJonas Devlieghere        if id is not None:
110301263c6cSJonas Devlieghere            args_dict["id"] = id
110401263c6cSJonas Devlieghere        command_dict = {
110501263c6cSJonas Devlieghere            "command": "setVariable",
110601263c6cSJonas Devlieghere            "type": "request",
110701263c6cSJonas Devlieghere            "arguments": args_dict,
110801263c6cSJonas Devlieghere        }
110901263c6cSJonas Devlieghere        return self.send_recv(command_dict)
111001263c6cSJonas Devlieghere
11110cc2cd78SAdrian Vogelsgesang    def request_locations(self, locationReference):
11120cc2cd78SAdrian Vogelsgesang        args_dict = {
11130cc2cd78SAdrian Vogelsgesang            "locationReference": locationReference,
11140cc2cd78SAdrian Vogelsgesang        }
11150cc2cd78SAdrian Vogelsgesang        command_dict = {
11160cc2cd78SAdrian Vogelsgesang            "command": "locations",
11170cc2cd78SAdrian Vogelsgesang            "type": "request",
11180cc2cd78SAdrian Vogelsgesang            "arguments": args_dict,
11190cc2cd78SAdrian Vogelsgesang        }
11200cc2cd78SAdrian Vogelsgesang        return self.send_recv(command_dict)
11210cc2cd78SAdrian Vogelsgesang
112201263c6cSJonas Devlieghere    def request_testGetTargetBreakpoints(self):
112301263c6cSJonas Devlieghere        """A request packet used in the LLDB test suite to get all currently
112401263c6cSJonas Devlieghere        set breakpoint infos for all breakpoints currently set in the
112501263c6cSJonas Devlieghere        target.
112601263c6cSJonas Devlieghere        """
112701263c6cSJonas Devlieghere        command_dict = {
112801263c6cSJonas Devlieghere            "command": "_testGetTargetBreakpoints",
112901263c6cSJonas Devlieghere            "type": "request",
113001263c6cSJonas Devlieghere            "arguments": {},
113101263c6cSJonas Devlieghere        }
113201263c6cSJonas Devlieghere        return self.send_recv(command_dict)
113301263c6cSJonas Devlieghere
113401263c6cSJonas Devlieghere    def terminate(self):
113501263c6cSJonas Devlieghere        self.send.close()
113601263c6cSJonas Devlieghere        # self.recv.close()
113701263c6cSJonas Devlieghere
113889c27d6bSSanthosh Kumar Ellendula    def request_setInstructionBreakpoints(self, memory_reference=[]):
113989c27d6bSSanthosh Kumar Ellendula        breakpoints = []
114089c27d6bSSanthosh Kumar Ellendula        for i in memory_reference:
114189c27d6bSSanthosh Kumar Ellendula            args_dict = {
114289c27d6bSSanthosh Kumar Ellendula                "instructionReference": i,
114389c27d6bSSanthosh Kumar Ellendula            }
114489c27d6bSSanthosh Kumar Ellendula            breakpoints.append(args_dict)
114589c27d6bSSanthosh Kumar Ellendula        args_dict = {"breakpoints": breakpoints}
114689c27d6bSSanthosh Kumar Ellendula        command_dict = {
114789c27d6bSSanthosh Kumar Ellendula            "command": "setInstructionBreakpoints",
114889c27d6bSSanthosh Kumar Ellendula            "type": "request",
114989c27d6bSSanthosh Kumar Ellendula            "arguments": args_dict,
115089c27d6bSSanthosh Kumar Ellendula        }
115189c27d6bSSanthosh Kumar Ellendula        return self.send_recv(command_dict)
115201263c6cSJonas Devlieghere
115301263c6cSJonas Devlieghereclass DebugAdaptorServer(DebugCommunication):
115401263c6cSJonas Devlieghere    def __init__(
115510664813SWalter Erquinigo        self,
115610664813SWalter Erquinigo        executable=None,
115710664813SWalter Erquinigo        port=None,
115810664813SWalter Erquinigo        init_commands=[],
115910664813SWalter Erquinigo        log_file=None,
116010664813SWalter Erquinigo        env=None,
116101263c6cSJonas Devlieghere    ):
116201263c6cSJonas Devlieghere        self.process = None
116301263c6cSJonas Devlieghere        if executable is not None:
116401263c6cSJonas Devlieghere            adaptor_env = os.environ.copy()
116501263c6cSJonas Devlieghere            if env is not None:
116601263c6cSJonas Devlieghere                adaptor_env.update(env)
116701263c6cSJonas Devlieghere
116801263c6cSJonas Devlieghere            if log_file:
116901263c6cSJonas Devlieghere                adaptor_env["LLDBDAP_LOG"] = log_file
117001263c6cSJonas Devlieghere            self.process = subprocess.Popen(
117101263c6cSJonas Devlieghere                [executable],
117201263c6cSJonas Devlieghere                stdin=subprocess.PIPE,
117301263c6cSJonas Devlieghere                stdout=subprocess.PIPE,
117401263c6cSJonas Devlieghere                stderr=subprocess.PIPE,
117501263c6cSJonas Devlieghere                env=adaptor_env,
117601263c6cSJonas Devlieghere            )
117701263c6cSJonas Devlieghere            DebugCommunication.__init__(
117801263c6cSJonas Devlieghere                self, self.process.stdout, self.process.stdin, init_commands, log_file
117901263c6cSJonas Devlieghere            )
118001263c6cSJonas Devlieghere        elif port is not None:
118101263c6cSJonas Devlieghere            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
118201263c6cSJonas Devlieghere            s.connect(("127.0.0.1", port))
118301263c6cSJonas Devlieghere            DebugCommunication.__init__(
118401263c6cSJonas Devlieghere                self, s.makefile("r"), s.makefile("w"), init_commands
118501263c6cSJonas Devlieghere            )
118601263c6cSJonas Devlieghere
118701263c6cSJonas Devlieghere    def get_pid(self):
118801263c6cSJonas Devlieghere        if self.process:
118901263c6cSJonas Devlieghere            return self.process.pid
119001263c6cSJonas Devlieghere        return -1
119101263c6cSJonas Devlieghere
119201263c6cSJonas Devlieghere    def terminate(self):
119301263c6cSJonas Devlieghere        super(DebugAdaptorServer, self).terminate()
119401263c6cSJonas Devlieghere        if self.process is not None:
119501263c6cSJonas Devlieghere            self.process.terminate()
119601263c6cSJonas Devlieghere            self.process.wait()
119701263c6cSJonas Devlieghere            self.process = None
119801263c6cSJonas Devlieghere
119901263c6cSJonas Devlieghere
120001263c6cSJonas Devliegheredef attach_options_specified(options):
120101263c6cSJonas Devlieghere    if options.pid is not None:
120201263c6cSJonas Devlieghere        return True
120301263c6cSJonas Devlieghere    if options.waitFor:
120401263c6cSJonas Devlieghere        return True
120501263c6cSJonas Devlieghere    if options.attach:
120601263c6cSJonas Devlieghere        return True
120701263c6cSJonas Devlieghere    if options.attachCmds:
120801263c6cSJonas Devlieghere        return True
120901263c6cSJonas Devlieghere    return False
121001263c6cSJonas Devlieghere
121101263c6cSJonas Devlieghere
121201263c6cSJonas Devliegheredef run_vscode(dbg, args, options):
121301263c6cSJonas Devlieghere    dbg.request_initialize(options.sourceInitFile)
121401263c6cSJonas Devlieghere    if attach_options_specified(options):
121501263c6cSJonas Devlieghere        response = dbg.request_attach(
121601263c6cSJonas Devlieghere            program=options.program,
121701263c6cSJonas Devlieghere            pid=options.pid,
121801263c6cSJonas Devlieghere            waitFor=options.waitFor,
121901263c6cSJonas Devlieghere            attachCommands=options.attachCmds,
122001263c6cSJonas Devlieghere            initCommands=options.initCmds,
122101263c6cSJonas Devlieghere            preRunCommands=options.preRunCmds,
122201263c6cSJonas Devlieghere            stopCommands=options.stopCmds,
122301263c6cSJonas Devlieghere            exitCommands=options.exitCmds,
122401263c6cSJonas Devlieghere            terminateCommands=options.terminateCmds,
122501263c6cSJonas Devlieghere        )
122601263c6cSJonas Devlieghere    else:
122701263c6cSJonas Devlieghere        response = dbg.request_launch(
122801263c6cSJonas Devlieghere            options.program,
122901263c6cSJonas Devlieghere            args=args,
123001263c6cSJonas Devlieghere            env=options.envs,
123101263c6cSJonas Devlieghere            cwd=options.workingDir,
123201263c6cSJonas Devlieghere            debuggerRoot=options.debuggerRoot,
123301263c6cSJonas Devlieghere            sourcePath=options.sourcePath,
123401263c6cSJonas Devlieghere            initCommands=options.initCmds,
123501263c6cSJonas Devlieghere            preRunCommands=options.preRunCmds,
123601263c6cSJonas Devlieghere            stopCommands=options.stopCmds,
123701263c6cSJonas Devlieghere            exitCommands=options.exitCmds,
123801263c6cSJonas Devlieghere            terminateCommands=options.terminateCmds,
123901263c6cSJonas Devlieghere        )
124001263c6cSJonas Devlieghere
124101263c6cSJonas Devlieghere    if response["success"]:
124201263c6cSJonas Devlieghere        if options.sourceBreakpoints:
124301263c6cSJonas Devlieghere            source_to_lines = {}
124401263c6cSJonas Devlieghere            for file_line in options.sourceBreakpoints:
124501263c6cSJonas Devlieghere                (path, line) = file_line.split(":")
124601263c6cSJonas Devlieghere                if len(path) == 0 or len(line) == 0:
124701263c6cSJonas Devlieghere                    print('error: invalid source with line "%s"' % (file_line))
124801263c6cSJonas Devlieghere
124901263c6cSJonas Devlieghere                else:
125001263c6cSJonas Devlieghere                    if path in source_to_lines:
125101263c6cSJonas Devlieghere                        source_to_lines[path].append(int(line))
125201263c6cSJonas Devlieghere                    else:
125301263c6cSJonas Devlieghere                        source_to_lines[path] = [int(line)]
125401263c6cSJonas Devlieghere            for source in source_to_lines:
125501263c6cSJonas Devlieghere                dbg.request_setBreakpoints(source, source_to_lines[source])
125601263c6cSJonas Devlieghere        if options.funcBreakpoints:
125701263c6cSJonas Devlieghere            dbg.request_setFunctionBreakpoints(options.funcBreakpoints)
125801263c6cSJonas Devlieghere        dbg.request_configurationDone()
125901263c6cSJonas Devlieghere        dbg.wait_for_stopped()
126001263c6cSJonas Devlieghere    else:
126101263c6cSJonas Devlieghere        if "message" in response:
126201263c6cSJonas Devlieghere            print(response["message"])
126301263c6cSJonas Devlieghere    dbg.request_disconnect(terminateDebuggee=True)
126401263c6cSJonas Devlieghere
126501263c6cSJonas Devlieghere
126601263c6cSJonas Devliegheredef main():
126701263c6cSJonas Devlieghere    parser = optparse.OptionParser(
126801263c6cSJonas Devlieghere        description=(
1269c5c11f34SJohn Harrison            "A testing framework for the Visual Studio Code Debug Adaptor protocol"
127001263c6cSJonas Devlieghere        )
127101263c6cSJonas Devlieghere    )
127201263c6cSJonas Devlieghere
127301263c6cSJonas Devlieghere    parser.add_option(
127401263c6cSJonas Devlieghere        "--vscode",
127501263c6cSJonas Devlieghere        type="string",
127601263c6cSJonas Devlieghere        dest="vscode_path",
127701263c6cSJonas Devlieghere        help=(
127801263c6cSJonas Devlieghere            "The path to the command line program that implements the "
127901263c6cSJonas Devlieghere            "Visual Studio Code Debug Adaptor protocol."
128001263c6cSJonas Devlieghere        ),
128101263c6cSJonas Devlieghere        default=None,
128201263c6cSJonas Devlieghere    )
128301263c6cSJonas Devlieghere
128401263c6cSJonas Devlieghere    parser.add_option(
128501263c6cSJonas Devlieghere        "--program",
128601263c6cSJonas Devlieghere        type="string",
128701263c6cSJonas Devlieghere        dest="program",
128801263c6cSJonas Devlieghere        help="The path to the program to debug.",
128901263c6cSJonas Devlieghere        default=None,
129001263c6cSJonas Devlieghere    )
129101263c6cSJonas Devlieghere
129201263c6cSJonas Devlieghere    parser.add_option(
129301263c6cSJonas Devlieghere        "--workingDir",
129401263c6cSJonas Devlieghere        type="string",
129501263c6cSJonas Devlieghere        dest="workingDir",
129601263c6cSJonas Devlieghere        default=None,
129701263c6cSJonas Devlieghere        help="Set the working directory for the process we launch.",
129801263c6cSJonas Devlieghere    )
129901263c6cSJonas Devlieghere
130001263c6cSJonas Devlieghere    parser.add_option(
130101263c6cSJonas Devlieghere        "--sourcePath",
130201263c6cSJonas Devlieghere        type="string",
130301263c6cSJonas Devlieghere        dest="sourcePath",
130401263c6cSJonas Devlieghere        default=None,
130501263c6cSJonas Devlieghere        help=(
130601263c6cSJonas Devlieghere            "Set the relative source root for any debug info that has "
130701263c6cSJonas Devlieghere            "relative paths in it."
130801263c6cSJonas Devlieghere        ),
130901263c6cSJonas Devlieghere    )
131001263c6cSJonas Devlieghere
131101263c6cSJonas Devlieghere    parser.add_option(
131201263c6cSJonas Devlieghere        "--debuggerRoot",
131301263c6cSJonas Devlieghere        type="string",
131401263c6cSJonas Devlieghere        dest="debuggerRoot",
131501263c6cSJonas Devlieghere        default=None,
131601263c6cSJonas Devlieghere        help=(
13172a32afddSDavid Spickett            "Set the working directory for lldb-dap for any object files "
131801263c6cSJonas Devlieghere            "with relative paths in the Mach-o debug map."
131901263c6cSJonas Devlieghere        ),
132001263c6cSJonas Devlieghere    )
132101263c6cSJonas Devlieghere
132201263c6cSJonas Devlieghere    parser.add_option(
132301263c6cSJonas Devlieghere        "-r",
132401263c6cSJonas Devlieghere        "--replay",
132501263c6cSJonas Devlieghere        type="string",
132601263c6cSJonas Devlieghere        dest="replay",
132701263c6cSJonas Devlieghere        help=(
132801263c6cSJonas Devlieghere            "Specify a file containing a packet log to replay with the "
132901263c6cSJonas Devlieghere            "current Visual Studio Code Debug Adaptor executable."
133001263c6cSJonas Devlieghere        ),
133101263c6cSJonas Devlieghere        default=None,
133201263c6cSJonas Devlieghere    )
133301263c6cSJonas Devlieghere
133401263c6cSJonas Devlieghere    parser.add_option(
133501263c6cSJonas Devlieghere        "-g",
133601263c6cSJonas Devlieghere        "--debug",
133701263c6cSJonas Devlieghere        action="store_true",
133801263c6cSJonas Devlieghere        dest="debug",
133901263c6cSJonas Devlieghere        default=False,
134001263c6cSJonas Devlieghere        help="Pause waiting for a debugger to attach to the debug adaptor",
134101263c6cSJonas Devlieghere    )
134201263c6cSJonas Devlieghere
134301263c6cSJonas Devlieghere    parser.add_option(
134401263c6cSJonas Devlieghere        "--sourceInitFile",
134501263c6cSJonas Devlieghere        action="store_true",
134601263c6cSJonas Devlieghere        dest="sourceInitFile",
134701263c6cSJonas Devlieghere        default=False,
13482a32afddSDavid Spickett        help="Whether lldb-dap should source .lldbinit file or not",
134901263c6cSJonas Devlieghere    )
135001263c6cSJonas Devlieghere
135101263c6cSJonas Devlieghere    parser.add_option(
135201263c6cSJonas Devlieghere        "--port",
135301263c6cSJonas Devlieghere        type="int",
135401263c6cSJonas Devlieghere        dest="port",
135501263c6cSJonas Devlieghere        help="Attach a socket to a port instead of using STDIN for VSCode",
135601263c6cSJonas Devlieghere        default=None,
135701263c6cSJonas Devlieghere    )
135801263c6cSJonas Devlieghere
135901263c6cSJonas Devlieghere    parser.add_option(
136001263c6cSJonas Devlieghere        "--pid",
136101263c6cSJonas Devlieghere        type="int",
136201263c6cSJonas Devlieghere        dest="pid",
136301263c6cSJonas Devlieghere        help="The process ID to attach to",
136401263c6cSJonas Devlieghere        default=None,
136501263c6cSJonas Devlieghere    )
136601263c6cSJonas Devlieghere
136701263c6cSJonas Devlieghere    parser.add_option(
136801263c6cSJonas Devlieghere        "--attach",
136901263c6cSJonas Devlieghere        action="store_true",
137001263c6cSJonas Devlieghere        dest="attach",
137101263c6cSJonas Devlieghere        default=False,
137201263c6cSJonas Devlieghere        help=(
137301263c6cSJonas Devlieghere            "Specify this option to attach to a process by name. The "
137401263c6cSJonas Devlieghere            "process name is the basename of the executable specified with "
137501263c6cSJonas Devlieghere            "the --program option."
137601263c6cSJonas Devlieghere        ),
137701263c6cSJonas Devlieghere    )
137801263c6cSJonas Devlieghere
137901263c6cSJonas Devlieghere    parser.add_option(
138001263c6cSJonas Devlieghere        "-f",
138101263c6cSJonas Devlieghere        "--function-bp",
138201263c6cSJonas Devlieghere        type="string",
138301263c6cSJonas Devlieghere        action="append",
138401263c6cSJonas Devlieghere        dest="funcBreakpoints",
138501263c6cSJonas Devlieghere        help=(
138601263c6cSJonas Devlieghere            "Specify the name of a function to break at. "
138701263c6cSJonas Devlieghere            "Can be specified more than once."
138801263c6cSJonas Devlieghere        ),
138901263c6cSJonas Devlieghere        default=[],
139001263c6cSJonas Devlieghere    )
139101263c6cSJonas Devlieghere
139201263c6cSJonas Devlieghere    parser.add_option(
139301263c6cSJonas Devlieghere        "-s",
139401263c6cSJonas Devlieghere        "--source-bp",
139501263c6cSJonas Devlieghere        type="string",
139601263c6cSJonas Devlieghere        action="append",
139701263c6cSJonas Devlieghere        dest="sourceBreakpoints",
139801263c6cSJonas Devlieghere        default=[],
139901263c6cSJonas Devlieghere        help=(
140001263c6cSJonas Devlieghere            "Specify source breakpoints to set in the format of "
140101263c6cSJonas Devlieghere            "<source>:<line>. "
140201263c6cSJonas Devlieghere            "Can be specified more than once."
140301263c6cSJonas Devlieghere        ),
140401263c6cSJonas Devlieghere    )
140501263c6cSJonas Devlieghere
140601263c6cSJonas Devlieghere    parser.add_option(
140701263c6cSJonas Devlieghere        "--attachCommand",
140801263c6cSJonas Devlieghere        type="string",
140901263c6cSJonas Devlieghere        action="append",
141001263c6cSJonas Devlieghere        dest="attachCmds",
141101263c6cSJonas Devlieghere        default=[],
141201263c6cSJonas Devlieghere        help=(
141301263c6cSJonas Devlieghere            "Specify a LLDB command that will attach to a process. "
141401263c6cSJonas Devlieghere            "Can be specified more than once."
141501263c6cSJonas Devlieghere        ),
141601263c6cSJonas Devlieghere    )
141701263c6cSJonas Devlieghere
141801263c6cSJonas Devlieghere    parser.add_option(
141901263c6cSJonas Devlieghere        "--initCommand",
142001263c6cSJonas Devlieghere        type="string",
142101263c6cSJonas Devlieghere        action="append",
142201263c6cSJonas Devlieghere        dest="initCmds",
142301263c6cSJonas Devlieghere        default=[],
142401263c6cSJonas Devlieghere        help=(
142501263c6cSJonas Devlieghere            "Specify a LLDB command that will be executed before the target "
142601263c6cSJonas Devlieghere            "is created. Can be specified more than once."
142701263c6cSJonas Devlieghere        ),
142801263c6cSJonas Devlieghere    )
142901263c6cSJonas Devlieghere
143001263c6cSJonas Devlieghere    parser.add_option(
143101263c6cSJonas Devlieghere        "--preRunCommand",
143201263c6cSJonas Devlieghere        type="string",
143301263c6cSJonas Devlieghere        action="append",
143401263c6cSJonas Devlieghere        dest="preRunCmds",
143501263c6cSJonas Devlieghere        default=[],
143601263c6cSJonas Devlieghere        help=(
143701263c6cSJonas Devlieghere            "Specify a LLDB command that will be executed after the target "
143801263c6cSJonas Devlieghere            "has been created. Can be specified more than once."
143901263c6cSJonas Devlieghere        ),
144001263c6cSJonas Devlieghere    )
144101263c6cSJonas Devlieghere
144201263c6cSJonas Devlieghere    parser.add_option(
144301263c6cSJonas Devlieghere        "--stopCommand",
144401263c6cSJonas Devlieghere        type="string",
144501263c6cSJonas Devlieghere        action="append",
144601263c6cSJonas Devlieghere        dest="stopCmds",
144701263c6cSJonas Devlieghere        default=[],
144801263c6cSJonas Devlieghere        help=(
144901263c6cSJonas Devlieghere            "Specify a LLDB command that will be executed each time the"
145001263c6cSJonas Devlieghere            "process stops. Can be specified more than once."
145101263c6cSJonas Devlieghere        ),
145201263c6cSJonas Devlieghere    )
145301263c6cSJonas Devlieghere
145401263c6cSJonas Devlieghere    parser.add_option(
145501263c6cSJonas Devlieghere        "--exitCommand",
145601263c6cSJonas Devlieghere        type="string",
145701263c6cSJonas Devlieghere        action="append",
145801263c6cSJonas Devlieghere        dest="exitCmds",
145901263c6cSJonas Devlieghere        default=[],
146001263c6cSJonas Devlieghere        help=(
146101263c6cSJonas Devlieghere            "Specify a LLDB command that will be executed when the process "
146201263c6cSJonas Devlieghere            "exits. Can be specified more than once."
146301263c6cSJonas Devlieghere        ),
146401263c6cSJonas Devlieghere    )
146501263c6cSJonas Devlieghere
146601263c6cSJonas Devlieghere    parser.add_option(
146701263c6cSJonas Devlieghere        "--terminateCommand",
146801263c6cSJonas Devlieghere        type="string",
146901263c6cSJonas Devlieghere        action="append",
147001263c6cSJonas Devlieghere        dest="terminateCmds",
147101263c6cSJonas Devlieghere        default=[],
147201263c6cSJonas Devlieghere        help=(
147301263c6cSJonas Devlieghere            "Specify a LLDB command that will be executed when the debugging "
147401263c6cSJonas Devlieghere            "session is terminated. Can be specified more than once."
147501263c6cSJonas Devlieghere        ),
147601263c6cSJonas Devlieghere    )
147701263c6cSJonas Devlieghere
147801263c6cSJonas Devlieghere    parser.add_option(
147901263c6cSJonas Devlieghere        "--env",
148001263c6cSJonas Devlieghere        type="string",
148101263c6cSJonas Devlieghere        action="append",
148201263c6cSJonas Devlieghere        dest="envs",
148301263c6cSJonas Devlieghere        default=[],
148401263c6cSJonas Devlieghere        help=("Specify environment variables to pass to the launched " "process."),
148501263c6cSJonas Devlieghere    )
148601263c6cSJonas Devlieghere
148701263c6cSJonas Devlieghere    parser.add_option(
148801263c6cSJonas Devlieghere        "--waitFor",
148901263c6cSJonas Devlieghere        action="store_true",
149001263c6cSJonas Devlieghere        dest="waitFor",
149101263c6cSJonas Devlieghere        default=False,
149201263c6cSJonas Devlieghere        help=(
149301263c6cSJonas Devlieghere            "Wait for the next process to be launched whose name matches "
149401263c6cSJonas Devlieghere            "the basename of the program specified with the --program "
149501263c6cSJonas Devlieghere            "option"
149601263c6cSJonas Devlieghere        ),
149701263c6cSJonas Devlieghere    )
149801263c6cSJonas Devlieghere
149901263c6cSJonas Devlieghere    (options, args) = parser.parse_args(sys.argv[1:])
150001263c6cSJonas Devlieghere
150101263c6cSJonas Devlieghere    if options.vscode_path is None and options.port is None:
150201263c6cSJonas Devlieghere        print(
150301263c6cSJonas Devlieghere            "error: must either specify a path to a Visual Studio Code "
150401263c6cSJonas Devlieghere            "Debug Adaptor vscode executable path using the --vscode "
15052a32afddSDavid Spickett            "option, or a port to attach to for an existing lldb-dap "
150601263c6cSJonas Devlieghere            "using the --port option"
150701263c6cSJonas Devlieghere        )
150801263c6cSJonas Devlieghere        return
150901263c6cSJonas Devlieghere    dbg = DebugAdaptorServer(executable=options.vscode_path, port=options.port)
151001263c6cSJonas Devlieghere    if options.debug:
151101263c6cSJonas Devlieghere        raw_input('Waiting for debugger to attach pid "%i"' % (dbg.get_pid()))
151201263c6cSJonas Devlieghere    if options.replay:
151301263c6cSJonas Devlieghere        dbg.replay_packets(options.replay)
151401263c6cSJonas Devlieghere    else:
151501263c6cSJonas Devlieghere        run_vscode(dbg, args, options)
151601263c6cSJonas Devlieghere    dbg.terminate()
151701263c6cSJonas Devlieghere
151801263c6cSJonas Devlieghere
151901263c6cSJonas Devlieghereif __name__ == "__main__":
152001263c6cSJonas Devlieghere    main()
1521