|
2 | 2 |
|
3 | 3 | import json |
4 | 4 | import os |
| 5 | +import subprocess |
5 | 6 | import sys |
6 | 7 | import time |
7 | 8 | from functools import wraps |
|
14 | 15 | from click.types import BoolParamType, IntRange |
15 | 16 |
|
16 | 17 | import bdx |
17 | | -from bdx import debug, error, info, log, make_progress_bar |
| 18 | +from bdx import debug, error, info, log, make_progress_bar, trace |
18 | 19 | # fmt: off |
19 | 20 | from bdx.binary import BinaryDirectory, find_compilation_database |
20 | 21 | from bdx.index import (IndexingOptions, SymbolIndex, index_binary_directory, |
@@ -311,7 +312,10 @@ def convert(self, value, param, ctx): |
311 | 312 | @click.option( |
312 | 313 | "-f", |
313 | 314 | "--format", |
314 | | - help="Output format (json, sexp, or Python string format)", |
| 315 | + help=( |
| 316 | + "Output format (json, sexp, or Python string format). " |
| 317 | + "'{}'-placeholders are replaced with symbol fields." |
| 318 | + ), |
315 | 319 | type=SearchOutputFormatParamType(), |
316 | 320 | nargs=1, |
317 | 321 | default=None, |
@@ -357,6 +361,69 @@ def search(_directory, index_path, query, num, format): |
357 | 361 | exit(1) |
358 | 362 |
|
359 | 363 |
|
| 364 | +@cli.command() |
| 365 | +@_common_options(index_must_exist=True) |
| 366 | +@click.argument( |
| 367 | + "query", |
| 368 | + nargs=-1, |
| 369 | +) |
| 370 | +@click.option( |
| 371 | + "-n", |
| 372 | + "--num", |
| 373 | + help="Limit the number of results", |
| 374 | + type=click.IntRange(1), |
| 375 | + metavar="LIMIT", |
| 376 | + default=None, |
| 377 | +) |
| 378 | +@click.option( |
| 379 | + "-D", |
| 380 | + "--disassembler", |
| 381 | + help=( |
| 382 | + "The command to run to disassemble a symbol. " |
| 383 | + "'{}'-placeholders are replaced with search keys." |
| 384 | + ), |
| 385 | + nargs=1, |
| 386 | + default=( |
| 387 | + "objdump -dC " |
| 388 | + "'{path}' " |
| 389 | + "--section '{section}' " |
| 390 | + "--start-address 0x{address:x} --stop-address 0x{endaddress:x}" |
| 391 | + ), |
| 392 | +) |
| 393 | +def disass(_directory, index_path, query, num, disassembler): |
| 394 | + """Search binary directory for symbols.""" |
| 395 | + results = search_index( |
| 396 | + index_path=index_path, query=" ".join(query), limit=num |
| 397 | + ) |
| 398 | + |
| 399 | + while True: |
| 400 | + try: |
| 401 | + res = next(results) |
| 402 | + except QueryParser.Error as e: |
| 403 | + error(f"Invalid query: {str(e)}") |
| 404 | + exit(1) |
| 405 | + except StopIteration: |
| 406 | + break |
| 407 | + |
| 408 | + data = res.asdict() |
| 409 | + data.update(res.dynamic_fields()) |
| 410 | + |
| 411 | + try: |
| 412 | + cmd = disassembler.format(**data) |
| 413 | + except (KeyError, ValueError, TypeError) as e: |
| 414 | + error( |
| 415 | + "Invalid format: {} in '{}'\nAvailable keys: {}", |
| 416 | + str(e), |
| 417 | + disassembler, |
| 418 | + list(data.keys()), |
| 419 | + ) |
| 420 | + exit(1) |
| 421 | + |
| 422 | + trace("Symbol: {}", res) |
| 423 | + debug("Running command: {}", cmd) |
| 424 | + subprocess.check_call(cmd, shell=True) |
| 425 | + |
| 426 | + |
360 | 427 | @cli.command() |
361 | 428 | @_common_options(index_must_exist=True) |
362 | 429 | def files(_directory, index_path): |
|
0 commit comments