-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[lldb] Add type hints to gdbclientutils.py #162172
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
dsandersllvm
wants to merge
1
commit into
llvm:main
Choose a base branch
from
dsandersllvm:gdbremote-type-hints
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+43
−27
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,12 @@ | ||
from abc import ABC, abstractmethod | ||
import ctypes | ||
import errno | ||
import io | ||
import threading | ||
import socket | ||
import traceback | ||
from lldbsuite.support import seven | ||
from typing import Optional | ||
|
||
|
||
def checksum(message): | ||
|
@@ -86,8 +88,8 @@ class MockGDBServerResponder: | |
handles any packet not recognized in the common packet handling code. | ||
""" | ||
|
||
registerCount = 40 | ||
packetLog = None | ||
registerCount: int = 40 | ||
packetLog: Optional[list[str]] = None | ||
|
||
class RESPONSE_DISCONNECT: | ||
pass | ||
|
@@ -103,6 +105,7 @@ def respond(self, packet): | |
Return the unframed packet data that the server should issue in response | ||
to the given packet received from the client. | ||
""" | ||
assert self.packetLog is not None | ||
self.packetLog.append(packet) | ||
if packet is MockGDBServer.PACKET_INTERRUPT: | ||
return self.interrupt() | ||
|
@@ -242,7 +245,7 @@ def qProcessInfo(self): | |
def qHostInfo(self): | ||
return "ptrsize:8;endian:little;" | ||
|
||
def qEcho(self): | ||
def qEcho(self, _: int): | ||
return "E04" | ||
|
||
def qQueryGDBServer(self): | ||
|
@@ -263,10 +266,10 @@ def A(self, packet): | |
def D(self, packet): | ||
return "OK" | ||
|
||
def readRegisters(self): | ||
def readRegisters(self) -> str: | ||
return "00000000" * self.registerCount | ||
|
||
def readRegister(self, register): | ||
def readRegister(self, register: int) -> str: | ||
return "00000000" | ||
|
||
def writeRegisters(self, registers_hex): | ||
|
@@ -306,7 +309,8 @@ def haltReason(self): | |
# SIGINT is 2, return type is 2 digit hex string | ||
return "S02" | ||
|
||
def qXferRead(self, obj, annex, offset, length): | ||
def qXferRead(self, obj: str, annex: str, offset: int, | ||
length: int) -> tuple[str | None, bool]: | ||
return None, False | ||
|
||
def _qXferResponse(self, data, has_more): | ||
|
@@ -374,15 +378,17 @@ class UnexpectedPacketException(Exception): | |
pass | ||
|
||
|
||
class ServerChannel: | ||
class ServerChannel(ABC): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not "adding type hints". "Change the title to "Add type hints and use abstract base class in" |
||
""" | ||
A wrapper class for TCP or pty-based server. | ||
""" | ||
|
||
def get_connect_address(self): | ||
@abstractmethod | ||
def get_connect_address(self) -> str: | ||
"""Get address for the client to connect to.""" | ||
|
||
def get_connect_url(self): | ||
@abstractmethod | ||
def get_connect_url(self) -> str: | ||
"""Get URL suitable for process connect command.""" | ||
|
||
def close_server(self): | ||
|
@@ -394,10 +400,12 @@ def accept(self): | |
def close_connection(self): | ||
"""Close all resources used by the accepted connection.""" | ||
|
||
def recv(self): | ||
@abstractmethod | ||
def recv(self) -> bytes: | ||
"""Receive a data packet from the connected client.""" | ||
|
||
def sendall(self, data): | ||
@abstractmethod | ||
def sendall(self, data: bytes) -> None: | ||
"""Send the data to the connected client.""" | ||
|
||
|
||
|
@@ -428,11 +436,11 @@ def close_connection(self): | |
self._connection.close() | ||
self._connection = None | ||
|
||
def recv(self): | ||
def recv(self) -> bytes: | ||
assert self._connection is not None | ||
return self._connection.recv(4096) | ||
|
||
def sendall(self, data): | ||
def sendall(self, data: bytes) -> None: | ||
assert self._connection is not None | ||
return self._connection.sendall(data) | ||
|
||
|
@@ -444,21 +452,21 @@ def __init__(self): | |
)[0] | ||
super().__init__(family, type, proto, addr) | ||
|
||
def get_connect_address(self): | ||
def get_connect_address(self) -> str: | ||
return "[{}]:{}".format(*self._server_socket.getsockname()) | ||
|
||
def get_connect_url(self): | ||
def get_connect_url(self) -> str: | ||
return "connect://" + self.get_connect_address() | ||
|
||
|
||
class UnixServerSocket(ServerSocket): | ||
def __init__(self, addr): | ||
super().__init__(socket.AF_UNIX, socket.SOCK_STREAM, 0, addr) | ||
|
||
def get_connect_address(self): | ||
def get_connect_address(self) -> str: | ||
return self._server_socket.getsockname() | ||
|
||
def get_connect_url(self): | ||
def get_connect_url(self) -> str: | ||
return "unix-connect://" + self.get_connect_address() | ||
|
||
|
||
|
@@ -472,7 +480,7 @@ def __init__(self): | |
self._primary = io.FileIO(primary, "r+b") | ||
self._secondary = io.FileIO(secondary, "r+b") | ||
|
||
def get_connect_address(self): | ||
def get_connect_address(self) -> str: | ||
libc = ctypes.CDLL(None) | ||
libc.ptsname.argtypes = (ctypes.c_int,) | ||
libc.ptsname.restype = ctypes.c_char_p | ||
|
@@ -485,7 +493,7 @@ def close_server(self): | |
self._secondary.close() | ||
self._primary.close() | ||
|
||
def recv(self): | ||
def recv(self) -> bytes: | ||
try: | ||
return self._primary.read(4096) | ||
except OSError as e: | ||
|
@@ -494,8 +502,8 @@ def recv(self): | |
return b"" | ||
raise | ||
|
||
def sendall(self, data): | ||
return self._primary.write(data) | ||
def sendall(self, data: bytes) -> None: | ||
self._primary.write(data) | ||
|
||
|
||
class MockGDBServer: | ||
|
@@ -528,18 +536,21 @@ def stop(self): | |
self._thread.join() | ||
self._thread = None | ||
|
||
def get_connect_address(self): | ||
def get_connect_address(self) -> str: | ||
assert self._socket is not None | ||
return self._socket.get_connect_address() | ||
|
||
def get_connect_url(self): | ||
def get_connect_url(self) -> str: | ||
assert self._socket is not None | ||
return self._socket.get_connect_url() | ||
|
||
def run(self): | ||
assert self._socket is not None | ||
# For testing purposes, we only need to worry about one client | ||
# connecting just one time. | ||
try: | ||
self._socket.accept() | ||
except: | ||
except Exception: | ||
traceback.print_exc() | ||
return | ||
self._shouldSendAck = True | ||
|
@@ -554,7 +565,7 @@ def run(self): | |
self._receive(data) | ||
except self.TerminateConnectionException: | ||
pass | ||
except Exception as e: | ||
except Exception: | ||
print( | ||
"An exception happened when receiving the response from the gdb server. Closing the client..." | ||
) | ||
|
@@ -587,7 +598,9 @@ def _parsePacket(self): | |
Once a complete packet is found at the front of self._receivedData, | ||
its data is removed form self._receivedData. | ||
""" | ||
assert self._receivedData is not None | ||
data = self._receivedData | ||
assert self._receivedDataOffset is not None | ||
i = self._receivedDataOffset | ||
data_len = len(data) | ||
if data_len == 0: | ||
|
@@ -640,10 +653,13 @@ def _parsePacket(self): | |
self._receivedDataOffset = 0 | ||
return packet | ||
|
||
def _sendPacket(self, packet): | ||
self._socket.sendall(seven.bitcast_to_bytes(frame_packet(packet))) | ||
def _sendPacket(self, packet: str): | ||
assert self._socket is not None | ||
framed_packet = seven.bitcast_to_bytes(frame_packet(packet)) | ||
self._socket.sendall(framed_packet) | ||
|
||
def _handlePacket(self, packet): | ||
assert self._socket is not None | ||
if packet is self.PACKET_ACK: | ||
# Ignore ACKs from the client. For the future, we can consider | ||
# adding validation code to make sure the client only sends ACKs | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know what this means. Does someone call this with an extra parameter?