summaryrefslogtreecommitdiffstats
path: root/debug/risc-v-gsp-rm-vm/harness/version_diff.py
diff options
context:
space:
mode:
Diffstat (limited to 'debug/risc-v-gsp-rm-vm/harness/version_diff.py')
-rw-r--r--debug/risc-v-gsp-rm-vm/harness/version_diff.py48
1 files changed, 42 insertions, 6 deletions
diff --git a/debug/risc-v-gsp-rm-vm/harness/version_diff.py b/debug/risc-v-gsp-rm-vm/harness/version_diff.py
index a95f244..ccc6a15 100644
--- a/debug/risc-v-gsp-rm-vm/harness/version_diff.py
+++ b/debug/risc-v-gsp-rm-vm/harness/version_diff.py
@@ -8,7 +8,7 @@ of aborting the report:
1. image/shape -- entry, PT_LOAD layout, ELF section sizes, hashes, span;
2. symbol inventory -- ELF ``.symtab`` plus Ghidra names/index/exports TSVs
(including the 3-column ``ExportForGreenEye`` form) and
- green-eye JSON DBs; added/removed/moved/resized with
+ risc-v-gsp-rm-debugger JSON DBs; added/removed/moved/resized with
the anonymous-shift matching discipline of
``userspace/cuda/tools/diff_corpus.py``;
3. decompiled hints -- a corpus diff over two ``decompiled_index.tsv`` files,
@@ -27,11 +27,15 @@ Everything is local and stdlib-only: nothing is downloaded. The RM 610 gate
Run from the tool root:
python3 harness/version_diff.py --old old.elf --new new.elf --out dumps/vdiff
+
+``--dry-run`` prints the plan (and enforces the RM 610 gate) without opening
+any target or creating ``--out``.
"""
from __future__ import annotations
import argparse
import contextlib
+import json
import os
import re
import shutil
@@ -102,6 +106,7 @@ from greeneye.symbols import Symbol # noqa: E402
from greeneye.target import QemuTarget # noqa: E402
FORMAT = "greeneye-version-diff/1"
+PLAN_FORMAT = "greeneye-version-diff-plan/1"
RM610_DOC = "docs/23-RM610-READINESS.md"
RM610_TOKEN = "RM610-APPROVED"
RM610_ENV = "GREENEYE_RM610_APPROVED"
@@ -1218,7 +1223,7 @@ def _hex(value) -> str:
def render_markdown(report: dict, options: VersionDiffOptions) -> str:
old, new = report["old"], report["new"]
lines = [
- "# green-eye version diff",
+ "# risc-v-gsp-rm-debugger version diff",
"",
"> **# TOOL IN DEVELOPMENT - NOT READY YET!** Generated by `harness/version_diff.py`.",
"",
@@ -1413,7 +1418,7 @@ def _short_json(value, limit: int = 72) -> str:
def _add_side_symbols(parser: argparse.ArgumentParser, side: str) -> None:
- parser.add_argument(f"--{side}-symbols", help="green-eye symbol DB JSON for the %s target" % side)
+ parser.add_argument(f"--{side}-symbols", help="risc-v-gsp-rm-debugger symbol DB JSON for the %s target" % side)
parser.add_argument(f"--{side}-ghidra-names", help="Ghidra names.tsv for the %s target" % side)
parser.add_argument(f"--{side}-ghidra-index", help="Ghidra decompiled_index.tsv for the %s target" % side)
parser.add_argument(
@@ -1428,7 +1433,8 @@ def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(prog="version_diff", description=__doc__.splitlines()[0])
parser.add_argument("--old", required=True, help="old target (RISC-V ELF or raw .fwimage)")
parser.add_argument("--new", required=True, help="new target (RISC-V ELF or raw .fwimage)")
- parser.add_argument("--out", required=True, help="output directory for the report, sessions and DBs")
+ parser.add_argument("--out", help="output directory for the report, sessions and DBs (required unless --dry-run)")
+ parser.add_argument("--dry-run", action="store_true", help="print the plan and exit without opening targets or creating --out")
parser.add_argument("--old-label", help="report label for the old target (default: file stem)")
parser.add_argument("--new-label", help="report label for the new target (default: file stem)")
parser.add_argument("--release", help="release label; an rm610 release is gated by docs/23")
@@ -1438,7 +1444,7 @@ def build_parser() -> argparse.ArgumentParser:
parser.add_argument("--corpus-diff", nargs=2, metavar=("OLD_TSV", "NEW_TSV"),
help="diff two decompiled_index.tsv corpus exports")
parser.add_argument("--corpus-report", help="attach a previously produced corpus diff report")
- parser.add_argument("--stimulus", help="green-eye script replacing the builtin demo scenario")
+ parser.add_argument("--stimulus", help="risc-v-gsp-rm-debugger script replacing the builtin demo scenario")
parser.add_argument("--probe-instructions", type=int, default=2000,
help="probe step budget (0 = wall-clock --probe-duration)")
parser.add_argument("--probe-duration", type=float, default=0.5,
@@ -1456,7 +1462,7 @@ def options_from_args(args: argparse.Namespace) -> VersionDiffOptions:
return VersionDiffOptions(
old=args.old,
new=args.new,
- out=os.path.abspath(args.out),
+ out=os.path.abspath(args.out) if args.out else "",
old_label=args.old_label,
new_label=args.new_label,
release=args.release,
@@ -1483,9 +1489,39 @@ def options_from_args(args: argparse.Namespace) -> VersionDiffOptions:
)
+def build_plan(options: VersionDiffOptions) -> dict:
+ """Dry-run plan: gate + targets + output layout, nothing opened."""
+ check_rm610_gate(options.labels(), approval_token=options.approval_token)
+ return {
+ "format": PLAN_FORMAT,
+ "tool": "harness/version_diff.py",
+ "dry_run": True,
+ "status": "planned",
+ "rm610_gate": {"status": "passed", "labels": sorted(set(options.labels()))},
+ "old": {"label": options.label_for("old"), "path": options.old},
+ "new": {"label": options.label_for("new"), "path": options.new},
+ "out": os.path.abspath(options.out) if options.out else "<out>",
+ "sections": ["image", "symbols", "corpus", "probe", "behavior"],
+ "corpus_diff": list(options.corpus_diff) if options.corpus_diff else None,
+ "reports": {"json": "version-diff.json", "markdown": "version-diff.md"},
+ }
+
+
def main(argv: list[str] | None = None) -> int:
parser = build_parser()
args = parser.parse_args(argv)
+ if args.dry_run:
+ options = options_from_args(args)
+ try:
+ plan = build_plan(options)
+ except Rm610GateError as exc:
+ print(f"[version-diff] RM610 gate refused: {exc}", file=sys.stderr)
+ return 3
+ print(json.dumps(plan, indent=2, sort_keys=True))
+ print("[version-diff] dry-run: no target opened, nothing written")
+ return 0
+ if not args.out:
+ parser.error("--out is required unless --dry-run is used")
options = options_from_args(args)
try:
report = run_version_diff(options)