Metadata-Version: 2.4
Name: dwarffi
Version: 0.0.3
Summary: Basic Python project scaffold for dwarffi.
Requires-Python: >=3.10
Provides-Extra: dev
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: ruff>=0.4.0; extra == 'dev'
Description-Content-Type: text/markdown

# dwarffi

An authentic, **DWARF-powered type interface for Python**.

`dwarffi` allows you to interact with memory layouts using
**Intermediate Symbol Files (ISF)** generated from DWARF debug
information. It provides a CFFI-like experience without requiring header
files---instead, it uses the actual compiled structures from your
binaries.

**Intermediate Symbol Files (ISF)** are JSON representations of DWARF type
information. They capture the exact memory layout, including padding and
alignment, as defined in the original C code and compiled into the binary. You 
can generate ISF files using the `dwarf2json` tool, which extracts DWARF info 
from ELF binaries.

Read more about `dwarf2json` and ISF in the [dwarf2json README](https://github.com/volatilityfoundation/dwarf2json).


------------------------------------------------------------------------

## 🚀 Features

-   **DWARF-Native**: No need to rewrite C headers. Just point to a
    `.json` or `.json.xz` ISF file (generated by `dwarf2json`).
-   **Architecture Agnostic**: Handles Big Endian (PowerPC/MIPS) and
    Little Endian (ARM/x86) transparently.
-   **Dynamic `cdef`**: Compile C code on the fly to generate types,
    with automatic debug-type retention to prevent compilers from
    stripping unused definitions.
-   **Recursive Typedef Handling**: Automatic resolution and decay of
    typedef chains.
-   **C-Style Magic**:
    -   Pointer arithmetic (`ptr + 5`)
    -   Pointer subtraction (`ptr2 - ptr1`)
    -   Array slicing (`arr[1:5]`)
    -   Deep struct initialization via nested dictionaries
-   **Safety Semantics**:
    -   Automatic bit-masking
    -   Sign extension
    -   C-style integer overflow/underflow behavior
-   **Anonymous Struct/Union Flattening**: Access anonymous union
    members directly (ideal for register maps).
-   **ISF Export Support**: Save dynamically generated ISFs to `.json`
    or `.json.xz`.

------------------------------------------------------------------------

## 📦 Installation
```bash
pip install dwarffi
```

### Requirements for `cdef()`

To use dynamic compilation:

-   A C compiler (`gcc`, `clang`, or cross-compiler)
-   `dwarf2json` available in your PATH

NOTE: For some compilers you may need to disable options for optimizing away unused debug types. For example, with `gcc` you can use
`-fno-eliminate-unused-debug-types`.

------------------------------------------------------------------------

# 🛠️ Quick Start

## 1️⃣ CFFI-style `cdef`

``` python
from dwarffi import DFFI

ffi = DFFI()
ffi.cdef("""
    struct sensor_data {
        uint32_t timestamp;
        int16_t  readings[3];
        uint8_t  status;
    };
""")
```

Create an instance:

``` python
sensor = ffi.new("struct sensor_data", {
    "timestamp": 1234567,
    "readings": [10, -5, 20],
    "status": 0x01
})

print(f"Bytes: {sensor.to_bytes().hex()}")
print(f"Reading[1]: {sensor.readings[1]}")  # -5
```

------------------------------------------------------------------------

## 2️⃣ Embedded Architecture Analysis

``` python
ffi = DFFI("mips_be_target.json")

raw_data = bytearray(b'\x00\x00\x12\x34\xff\xff\xff\xfb')
cpu_ctx = ffi.from_buffer("struct cpu_context", raw_data)

print(hex(cpu_ctx.pc))      # 0x1234
print(cpu_ctx.status)       # -5 (Sign-extended)
```

------------------------------------------------------------------------

# 🧩 Advanced Usage

## Anonymous Unions

``` python
ffi.cdef("""
struct reg_map {
    union {
        uint32_t ALL;
        struct {
            uint16_t LOW;
            uint16_t HIGH;
        };
    };
};
""")

reg = ffi.new("struct reg_map")
reg.ALL = 0x12345678
print(hex(reg.HIGH))  # 0x1234
```

------------------------------------------------------------------------

## Pointer Arithmetic

``` python
ptr = ffi.cast("int *", 0x4000)
next_ptr = ptr + 1
print(hex(next_ptr.address))
```

------------------------------------------------------------------------

# ⚙️ How It Works

`dwarffi` operates in three phases:

### 1. Parsing

Reads ISF JSON files that represent the DWARF type tree.

### 2. Type Synthesis

Builds Python representations of:

-   Base types
-   Structs
-   Unions
-   Enums
-   Typedef chains
-   Arrays
-   Pointers

### 3. Memory Mapping

Uses Python's `struct.pack` and `struct.unpack` under the hood to:

-   Convert Python integers into architecture-accurate byte layouts
-   Apply endianness rules
-   Respect alignment and padding

Instances are bound views into bytearrays. Field access directly
reads/writes into the underlying buffer.

------------------------------------------------------------------------

# 📚 Core API Reference

### `DFFI()`

Create an empty instance or load an ISF file.

### `cdef(source, compiler="gcc", save_isf_to=None)`

Compile C source → DWARF → ISF → load into current FFI.

### `new(ctype, init=None)`

Allocate a new instance of a C type.

### `from_buffer(ctype, buffer)`

Bind a type to existing memory.

### `sizeof(ctype)`

Return size in bytes.

### `offsetof(ctype, field)`

Return byte offset of a field.

### `cast(ctype, value)`

Reinterpret memory or create pointer instances.

### `addressof(instance)`

Return pointer to instance.


------------------------------------------------------------------------

# 🤝 Contributing

Contributions are welcome!

``` bash
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest
```
