Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions src/re_agent/cli/cmd_reverse.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions src/re_agent/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
8 changes: 6 additions & 2 deletions tests/test_cli/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down