Skip to content

Commit 1811ea0

Browse files
DarkaMaulclaude
andcommitted
Unify apply-back path into disassembler_path
Merge commit()/regenerate()'s ida_path and ghidra_path into a single disassembler_path, dispatched via the Disassembler backend recorded in the .quokka file. Rename the quokka-apply --ghidra-path option to --disassembler-path accordingly. Addresses PR #120 review feedback. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 685cb2a commit 1811ea0

4 files changed

Lines changed: 24 additions & 22 deletions

File tree

bindings/python/quokka/__main__.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -389,10 +389,11 @@ def main(
389389
help="IDA .i64 database or Ghidra .gpr/project directory to modify",
390390
)
391391
@click.option(
392-
"--ghidra-path",
392+
"--disassembler-path",
393393
type=click.Path(exists=True),
394394
default=None,
395-
help="Ghidra installation directory (overrides GHIDRA_INSTALL_DIR)",
395+
help="Disassembler installation path (IDA install dir or Ghidra "
396+
"install dir, depending on the backend recorded in the .quokka file)",
396397
)
397398
@click.option("--overwrite", is_flag=True, default=False, help="Allow overwriting an existing disassembler database")
398399
@click.option("-v", "--verbose", count=True, help="Increase logging verbosity")
@@ -401,7 +402,7 @@ def main(
401402
def apply_changes(
402403
action: str,
403404
database_file: str | None,
404-
ghidra_path: str | None,
405+
disassembler_path: str | None,
405406
overwrite: bool,
406407
verbose: int,
407408
quokka_file: str,
@@ -429,7 +430,7 @@ def apply_changes(
429430
try:
430431
errors = program.commit(
431432
database_file=database_file,
432-
ghidra_path=ghidra_path,
433+
disassembler_path=disassembler_path,
433434
overwrite=overwrite,
434435
)
435436
except FileExistsError as e:
@@ -444,7 +445,7 @@ def apply_changes(
444445
try:
445446
new_program = program.regenerate(
446447
database_file=database_file,
447-
ghidra_path=ghidra_path,
448+
disassembler_path=disassembler_path,
448449
overwrite=overwrite,
449450
)
450451
logging.info(f"Regenerated: {new_program.export_file}")

bindings/python/quokka/program.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,19 +1353,23 @@ def _commit_edits_ghidra(
13531353
def commit(
13541354
self,
13551355
database_file: "Path|str|None" = None,
1356-
ida_path: "Path|str|None" = None,
1357-
ghidra_path: "Path|str|None" = None,
1356+
disassembler_path: "Path|str|None" = None,
13581357
overwrite: bool = True,
13591358
timeout: int = 600,
13601359
) -> int:
13611360
"""Write the .quokka and apply edits to the disassembler database.
13621361
1362+
The target disassembler is determined by the backend recorded in the
1363+
``.quokka`` file (``self.disassembler``): edits are always applied with
1364+
the same disassembler that produced the export.
1365+
13631366
Arguments:
13641367
database_file: Path to the disassembler database. For IDA this is
13651368
an ``.i64`` database. For Ghidra this is either a ``.gpr`` file
13661369
or a directory that contains/should contain a Ghidra project.
1367-
ida_path: Optional IDA installation path (IDA only).
1368-
ghidra_path: Optional Ghidra installation path (Ghidra only).
1370+
disassembler_path: Optional installation path for the disassembler
1371+
selected by ``self.disassembler`` (the IDA install dir for an
1372+
IDA export, the Ghidra install dir for a Ghidra export).
13691373
overwrite: Allow modifying an existing database.
13701374
timeout: Disassembler timeout in seconds.
13711375
@@ -1383,14 +1387,14 @@ def commit(
13831387
database_file = str(self.executable.exec_file) + ".i64"
13841388
return self._commit_edits_ida(
13851389
database_file,
1386-
ida_path=ida_path,
1390+
ida_path=disassembler_path,
13871391
overwrite=overwrite,
13881392
timeout=timeout,
13891393
)
13901394
case Disassembler.GHIDRA:
13911395
return self._commit_edits_ghidra(
13921396
database_file,
1393-
ghidra_path=ghidra_path,
1397+
ghidra_path=disassembler_path,
13941398
overwrite=overwrite,
13951399
timeout=timeout,
13961400
)
@@ -1403,8 +1407,7 @@ def commit(
14031407
def regenerate(
14041408
self,
14051409
database_file: "Path|str|None" = None,
1406-
ida_path: "Path|str|None" = None,
1407-
ghidra_path: "Path|str|None" = None,
1410+
disassembler_path: "Path|str|None" = None,
14081411
overwrite: bool = True,
14091412
timeout: int = 600,
14101413
) -> 'Program':
@@ -1415,8 +1418,8 @@ def regenerate(
14151418
14161419
Arguments:
14171420
database_file: Path to the disassembler database/project.
1418-
ida_path: Optional IDA installation path.
1419-
ghidra_path: Optional Ghidra installation path.
1421+
disassembler_path: Optional installation path for the disassembler
1422+
selected by ``self.disassembler``.
14201423
overwrite: Allow modifying an existing database.
14211424
timeout: IDA timeout in seconds.
14221425
@@ -1428,8 +1431,7 @@ def regenerate(
14281431
"""
14291432
errors = self.commit(
14301433
database_file=database_file,
1431-
ida_path=ida_path,
1432-
ghidra_path=ghidra_path,
1434+
disassembler_path=disassembler_path,
14331435
overwrite=overwrite,
14341436
timeout=timeout,
14351437
)

docs/write_feature.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,7 @@ errors = prog.commit(database_file="binary_ghidra/binary.gpr", overwrite=True)
9292
| Parameter | Type | Default | Description |
9393
|-----------|------|---------|-------------|
9494
| `database_file` | `Path\|str\|None` | backend default | IDA `.i64` database, Ghidra `.gpr` file, or Ghidra project directory |
95-
| `ida_path` | `Path\|str\|None` | `None` | IDA installation directory (auto-detected if omitted) |
96-
| `ghidra_path` | `Path\|str\|None` | `None` | Ghidra installation directory (or `GHIDRA_INSTALL_DIR`) |
95+
| `disassembler_path` | `Path\|str\|None` | `None` | Installation directory of the disassembler recorded in the `.quokka` file (IDA install dir, or Ghidra install dir / `GHIDRA_INSTALL_DIR`) |
9796
| `overwrite` | `bool` | `True` | Allow modifying an existing database/project. Raises `FileExistsError` when `False` and it exists. Logs a warning when `True`. |
9897
| `timeout` | `int` | `600` | Maximum seconds to wait for the disassembler |
9998

@@ -144,15 +143,15 @@ disassembler database/project without writing Python code:
144143
```commandline
145144
$ quokka-apply binary.quokka binary --overwrite
146145
$ quokka-apply binary.quokka binary --regenerate --overwrite
147-
$ quokka-apply binary.quokka binary --database-file binary_ghidra/binary.gpr --ghidra-path "$GHIDRA_INSTALL_DIR" --overwrite
146+
$ quokka-apply binary.quokka binary --database-file binary_ghidra/binary.gpr --disassembler-path "$GHIDRA_INSTALL_DIR" --overwrite
148147
```
149148

150149
| Option | Description |
151150
|--------|-------------|
152151
| `--commit` | Write `.quokka` and apply edits to the disassembler (default) |
153152
| `--regenerate` | Commit then re-export a fresh `.quokka` from the disassembler |
154153
| `--database-file` | IDA `.i64` database or Ghidra `.gpr`/project directory |
155-
| `--ghidra-path` | Ghidra installation directory |
154+
| `--disassembler-path` | Disassembler installation directory (IDA or Ghidra, per the backend recorded in the `.quokka`) |
156155
| `--overwrite` | Allow overwriting an existing disassembler database |
157156
| `-v`, `--verbose` | Increase logging verbosity |
158157

tests/python/tests/offline/test_commit_regenerate.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ def test_commit_ghidra_calls_apply_back(self):
190190

191191
assert prog.commit(
192192
database_file="/tmp/proj.gpr",
193-
ghidra_path="/opt/ghidra",
193+
disassembler_path="/opt/ghidra",
194194
overwrite=True,
195195
timeout=42,
196196
) == 0

0 commit comments

Comments
 (0)