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
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,23 @@ analyzeHeadless /tmp/ghidra-project DffiExport \
The exporter writes `base_types`, `user_types`, `enums`, `typedefs`, `symbols`,
and `functions` in the same ISF shape consumed by `DFFI`.

Inside PyGhidra, you can snapshot the currently open program directly without
writing an intermediate JSON file:

```python
from dwarffi import DFFI

ffi = DFFI.from_ghidra(currentProgram)
print(ffi.sizeof("Packet"))
print(ffi.get_symbol("global_counter"))
```

If `currentProgram` is in the caller's PyGhidra or GhidraScript scope, the
argument can be omitted. The snapshot captures types, symbols, and functions at
call time; call `DFFI.from_ghidra(...)` again after editing Ghidra data types.
Use `types_only=True`, `include_symbols=False`, or `include_functions=False` to
limit exported sections. PyGhidra is not an install dependency for `dwarffi`.

Import an ISF into the active Ghidra program:

```bash
Expand Down
34 changes: 33 additions & 1 deletion src/dwarffi/dffi.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,38 @@ def __init__(
self.load_isf(item)
else:
self.load_isf(isf_input)

@classmethod
def from_ghidra(
cls,
program: Any = None,
*,
include_symbols: bool = True,
include_functions: bool = True,
types_only: bool = False,
source_name: Optional[str] = None,
) -> "DFFI":
"""
Create a snapshot-backed DFFI instance from a PyGhidra/Ghidra Program.

If ``program`` is omitted, this looks for ``currentProgram`` in the
caller's PyGhidra or GhidraScript context. Type, symbol, and function
data are captured at call time; later Ghidra edits require calling this
method again.
"""
from .ghidra import current_program_from_context, program_to_isf

if program is None:
program = current_program_from_context()
return cls(
program_to_isf(
program,
include_symbols=include_symbols,
include_functions=include_functions,
types_only=types_only,
source_name=source_name,
)
)

def _add_vtypejson(self, source: str, vtype_obj: VtypeJson) -> None:
"""Internal helper to add a VtypeJson instance to the engine."""
Expand Down Expand Up @@ -1456,4 +1488,4 @@ def load_elf_bytes(
)
finally:
if os.path.exists(tmp_elf_path):
os.remove(tmp_elf_path)
os.remove(tmp_elf_path)
Loading
Loading