#!/usr/bin/env python3 from flask import Flask, request, jsonify, send_from_directory import subprocess import re import os app = Flask(__name__) TYPE_TO_GDB_FMT = { "int8": "db", "uint8": "dub", "int16": "dh", "uint16": "duh", "int32": "dw", "uint32": "duw", "float": "f", "double": "g", } def run_gdb_once(gdb_path, target, addr, length, data_type): if data_type not in TYPE_TO_GDB_FMT: raise ValueError(f"Unsupported type '{data_type}'") fmt = TYPE_TO_GDB_FMT[data_type] # Build gdb command: # gdb -q --nx -ex "target remote ..." -ex "x/ " -ex "quit" examine_cmd = f"x/{length}{fmt} {addr}" result = subprocess.run( [ gdb_path, "--quiet", "--nx", "-ex", f"target remote {target}", "-ex", examine_cmd, "-ex", "quit", ], capture_output=True, text=True, ) if result.returncode != 0: raise RuntimeError( f"GDB exited with code {result.returncode}:\n{result.stderr or result.stdout}" ) return result.stdout.splitlines() def parse_values(lines, data_type): values = [] line_re = re.compile(r"^0x[0-9a-fA-F]+:\s*(.*)$") for line in lines: line = line.strip() m = line_re.match(line) if not m: continue rest = m.group(1) tokens = rest.split() for t in tokens: try: if data_type in ("float", "double"): v = float(t) else: v = int(t, 10) values.append(v) except ValueError: pass return values @app.route("/") def index(): return send_from_directory(os.path.dirname(__file__), "index.html") @app.route("/api/read_memory", methods=["POST"]) def read_memory(): data = request.get_json(force=True) gdb_path = data.get("gdb_path", "arm-none-eabi-gdb") target = data.get("target", "localhost:3333") addr = data.get("addr") length = data.get("length") data_type = data.get("type") if addr is None or length is None or data_type is None: return jsonify({"error": "addr, length, and type are required"}), 400 try: length = int(length) except ValueError: return jsonify({"error": "length must be an integer"}), 400 try: lines = run_gdb_once(gdb_path, target, addr, length, data_type) values = parse_values(lines, data_type) if len(values) > length: values = values[:length] return jsonify({ "addr": addr, "length": length, "type": data_type, "values": values, }) except Exception as e: return jsonify({"error": str(e)}), 500 if __name__ == "__main__": # For dev only — behind firewall, not on the open internet. app.run(host="127.0.0.1", port=5000, debug=True)