summaryrefslogtreecommitdiffstats
path: root/debug/risc-v-gsp-rm-vm/greeneye/gdbridge.py
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-02 11:44:31 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-02 11:44:31 -0400
commit1c99bfbeffff04529f6f669601fdf835a73778da (patch)
tree5867bab46e5848541df36c703f6fd8d6d0256e54 /debug/risc-v-gsp-rm-vm/greeneye/gdbridge.py
parent2fd653044127a665e4677a2cdfb58120d7b3e16b (diff)
downloadopen-iov-1c99bfbeffff04529f6f669601fdf835a73778da.tar.gz
open-iov-1c99bfbeffff04529f6f669601fdf835a73778da.zip
rename (cosmetic): green-eye -> risc-v-gsp-rm-debugger in user-facing names, docs, CLI, launcher and CI workflow; internal greeneye package/module identifiers unchanged (includes in-flight greeneye module edits present in the tree)
Diffstat (limited to 'debug/risc-v-gsp-rm-vm/greeneye/gdbridge.py')
-rw-r--r--debug/risc-v-gsp-rm-vm/greeneye/gdbridge.py22
1 files changed, 18 insertions, 4 deletions
diff --git a/debug/risc-v-gsp-rm-vm/greeneye/gdbridge.py b/debug/risc-v-gsp-rm-vm/greeneye/gdbridge.py
index cc06e43..eafac39 100644
--- a/debug/risc-v-gsp-rm-vm/greeneye/gdbridge.py
+++ b/debug/risc-v-gsp-rm-vm/greeneye/gdbridge.py
@@ -1,4 +1,4 @@
-"""Ghidra control bridge: let GhidraScripts drive a green-eye session.
+"""Ghidra control bridge: let GhidraScripts drive a risc-v-gsp-rm-debugger session.
A tiny JSON-lines server over localhost. Each request is one line::
@@ -20,6 +20,9 @@ import threading
from .errors import GreenEyeError
+#: The bridge is unauthenticated and write-capable; it must never be exposed.
+LOOPBACK_HOSTS = ("127.0.0.1", "localhost", "::1")
+
class GhidraBridge:
def __init__(self, session, host: str = "127.0.0.1", port: int = 0):
@@ -34,6 +37,8 @@ class GhidraBridge:
# -- lifecycle ---------------------------------------------------------
def start(self) -> int:
+ if self.host not in LOOPBACK_HOSTS:
+ raise ValueError(f"refusing non-loopback bind {self.host!r}; the Ghidra bridge is local-only")
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((self.host, self.port))
@@ -46,12 +51,21 @@ class GhidraBridge:
def stop(self) -> None:
self._stop.set()
- if self._server is not None:
+ server = self._server
+ self._server = None
+ if server is not None:
+ # shutdown() wakes a thread blocked in accept(); close() alone does
+ # not, which left the listener up after a <close> command.
+ try:
+ server.shutdown(socket.SHUT_RDWR)
+ except OSError:
+ pass
try:
- self._server.close()
+ server.close()
except OSError:
pass
- self._server = None
+ if self._thread is not None and self._thread.is_alive() and threading.current_thread() is not self._thread:
+ self._thread.join(timeout=2.0)
def serve_forever(self) -> None:
if self._thread is None: