From 455642a908f37502635d99f1a9556135faf9f933 Mon Sep 17 00:00:00 2001 From: Leonard Date: Sat, 15 Aug 2026 20:44:49 +0200 Subject: [PATCH] Add function name option for address reversal --- src/re_agent/cli/cmd_reverse.py | 14 ++++++++++---- src/re_agent/cli/main.py | 1 + tests/test_cli/test_main.py | 8 ++++++-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/re_agent/cli/cmd_reverse.py b/src/re_agent/cli/cmd_reverse.py index 0711bc7..71f279e 100644 --- a/src/re_agent/cli/cmd_reverse.py +++ b/src/re_agent/cli/cmd_reverse.py @@ -35,15 +35,19 @@ def cmd_reverse(args: argparse.Namespace) -> int: from re_agent.orchestrator.single import reverse_single class_name = args.class_name or "" - function_name = "" + function_name = args.function_name or "" # Try to resolve function metadata from the backend - if not class_name: + if not class_name or not function_name: try: dec = backend.decompile(args.address) if dec.name and "::" in dec.name: - class_name, _, function_name = dec.name.rpartition("::") - elif dec.name: + detected_class, _, detected_function = dec.name.rpartition("::") + if not class_name: + class_name = detected_class + if not function_name: + function_name = detected_function + elif dec.name and not function_name: function_name = dec.name except Exception: pass # Best-effort; proceed with empty metadata @@ -96,6 +100,8 @@ def _dry_run(args: argparse.Namespace, config: object) -> int: print(f"Would reverse: {args.address}") if args.class_name: print(f" Class: {args.class_name}") + if args.function_name: + print(f" Function: {args.function_name}") return 0 if args.class_name: diff --git a/src/re_agent/cli/main.py b/src/re_agent/cli/main.py index c225817..d7365c2 100644 --- a/src/re_agent/cli/main.py +++ b/src/re_agent/cli/main.py @@ -22,6 +22,7 @@ def build_parser() -> argparse.ArgumentParser: rev_p = sub.add_parser("reverse", help="Reverse engineer functions") rev_p.add_argument("--address", help="Single function address to reverse") rev_p.add_argument("--class", dest="class_name", help="Class name for class-level reversal") + rev_p.add_argument("--function", dest="function_name", help="Function name for single-address reversal") rev_p.add_argument("--max-functions", type=int, default=None, help="Max functions per class") rev_p.add_argument("--max-rounds", type=int, default=None, help="Max review rounds per function") rev_p.add_argument("--dry-run", action="store_true", help="Show plan without executing") diff --git a/tests/test_cli/test_main.py b/tests/test_cli/test_main.py index 9ccdcc7..cc925c9 100644 --- a/tests/test_cli/test_main.py +++ b/tests/test_cli/test_main.py @@ -56,11 +56,15 @@ def test_status_no_session(tmp_path: Path) -> None: assert result == 0 -def test_reverse_dry_run(tmp_path: Path) -> None: +def test_reverse_dry_run(tmp_path: Path, capsys) -> None: config_path = tmp_path / "re-agent.yaml" config_path.write_text("llm:\n provider: claude\n") - result = main(["--config", str(config_path), "reverse", "--address", "0x6F86A0", "--dry-run"]) + result = main(["--config", str(config_path), "reverse", "--address", "0x6F86A0", "--class", "CVehicleModelInfo", "--function", "SetupCommonData", "--dry-run"]) + captured = capsys.readouterr() assert result == 0 + assert "Would reverse: 0x6F86A0" in captured.out + assert "Class: CVehicleModelInfo" in captured.out + assert "Function: SetupCommonData" in captured.out def test_reverse_no_target(tmp_path: Path) -> None: