-
Notifications
You must be signed in to change notification settings - Fork 618
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
Bus: Expose shared memory on Unix systems #3219
Conversation
Sorry, I'm fundamentally against this.
This is why I implemented PINE, which executes in the context of the CPU thread, and safely invalidates the rec as needed. (I know Windows has this "functionality", but I'm planning on removing that as well, since it has the same safety problems, once consumers have a chance to switch over to PINE) |
On Windows, the shared memory handle is closed on Destroy() and therefore is accessible at runtime. On Unixes the shared memory was unlinked right after its creation, effectively making the shared memory unavailable from the outside world. This commit brings feature parity to Unix systems. Allows the shared memory to be accessed at runtime from an external process for RAM inspection.
I was not aware of PINE's existence. If you tell me it can achieve the same things without these limitations then that sounds pretty good. Thank you. Do you have any example code available somewhere to use PINE ? |
It's fairly straightforward, you just send over a 4-byte packet length, 1-byte command type, and variable args over a unix domain socket in So e.g. to write 0x12345678 to address 0x80001000, you would send:
and get back:
You don't need to handle the replies, can just ignore them, but you should read them out, otherwise your socket receive buffer will eventually fill, and the DS side will stop processing commands. Full command list: duckstation/src/core/pine_server.cpp Lines 51 to 70 in f1465dd
duckstation/src/core/pine_server.cpp Lines 261 to 526 in f1465dd
This is the test script I used when writing the implementation: import socket
import binascii
import platform
import os
def get_socket():
if (platform.system() == "Windows"):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1", 28011))
else:
sdir = os.getenv("XDG_RUNTIME_DIR")
if sdir is None:
sdir = os.getenv("TEMPDIR", "/tmp")
sfilename = f"{sdir}/duckstation.sock"
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect(sfilename)
return s
def print_hex_ascii(data):
def to_printable_ascii(byte):
return chr(byte) if 32 <= byte <= 126 else '.'
for i in range(0, len(data), 8):
chunk = data[i:i+8]
hex_part = ' '.join(f'{byte:02x}' for byte in chunk)
ascii_part = ''.join(to_printable_ascii(byte) for byte in chunk)
print(f"{hex_part:<23} {ascii_part}")
def test_query(data):
s = None
try:
s = get_socket()
for i in range(4):
s.sendall(data)
print(f"Sent data: {binascii.hexlify(data).decode('utf-8')}")
response = s.recv(4096)
print("Response:")
print_hex_ascii(response)
except Exception as e:
print(f"An error occurred: {e}")
finally:
if s is not None:
s.close()
if __name__ == "__main__":
data = b"\x05\x00\x00\x00\x08" * 1
#data = b"\x09\x00\x00\x00\x02\x00\x00\x00\x00" * 4
test_query(data) |
1c8d966
to
6021e43
Compare
dd53df7
to
e0509eb
Compare
3b1521a
to
fae6b7a
Compare
I've implemented this in 02fbfae, but with a number of changes:
Please note that as I've stated above, this is not safe for use when manipulating MIPS code externally. There is no page protection on the external mapping, so it will not invalidate JIT blocks, and you'll likely be executing stale code. It is only safe for manipulating/writing data. |
On Windows, the shared memory handle is closed on Destroy() and therefore is accessible at runtime. On Unixes the shared memory was unlinked right after its creation, effectively making the shared memory unavailable from the outside world.
This commit brings feature parity to Unix systems. Allows the shared memory to be accessed at runtime from an external process for RAM inspection.