Metadata-Version: 2.4
Name: stkfmt
Version: 0.1.0
Summary: Generate terminal diagrams for hand-authored memory layouts
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"

# stkfmt

Generate clean terminal diagrams of hand-authored memory layouts for reverse-engineering notes, educational material, and write-ups.

```bash
pip install stkfmt
stkfmt memory.json --unicode
stkfmt ghidra function.txt --unicode
stkfmt ghidra function.txt --abi windows-x64 --unicode
```

```json
{
  "title": "main()",
  "regions": [
    {
      "name": "Stack",
      "direction": "down",
      "blocks": [
        {
          "id": "name-ptr",
          "address": "0x7fffffffe1a8",
          "size": 8,
          "value": "0x404050",
          "label": "name",
          "type": "char *",
          "points_to": "heap-name"
        }
      ]
    },
    {
      "name": "Heap",
      "blocks": [
        {
          "id": "heap-name",
          "address": "0x404050",
          "size": 4,
          "value": "41 64 61 00",
          "label": "name",
          "type": "char[4]",
          "note": "\"Ada\""
        }
      ]
    }
  ]
}
```

## Usage

```text
stkfmt <input> [options]
stkfmt ghidra <listing.txt> [options]

  input                 JSON file path, or - to read JSON from stdin
  -s, --style STYLE     ascii or unicode (default: ascii)
  -u, --unicode         shortcut for --style unicode
  -o, --output FILE     write output to FILE instead of stdout
      --no-addresses    hide address gutters and pointer-target addresses
      --abi ABI         apply an ABI profile to a Ghidra listing (windows-x64)
  -v, --version         show version
```

Each block requires `size` (bytes) and `label`. `value` is optional: omitted values render as `<unknown>`, which is useful for static Ghidra layouts. A region uses one coordinate system: either absolute `address` values, or signed `offset` values with a region `base` such as `rsp`.

An addressed block displays its inclusive byte range. An offset block displays a base-relative range, e.g. `RSP-0x148..RSP-0x39`. `stkfmt` sorts coordinate-bearing blocks into physical memory order (high-to-low for `direction: "down"`), renders unknown gaps as `unmapped`, rejects overlapping blocks, and validates an optional power-of-two `align` requirement. A gap is not assumed to be ABI padding; label an explicit block `padding` only when you know that is what it is.

## Ghidra listings

Copy or export a Ghidra function listing to a text file, then import its `Stack[...]` rows directly:

```bash
stkfmt ghidra examples/ghidra_function_listing.txt --unicode
```

The importer reads Ghidra stack offsets, storage sizes, type names, and variable names. It intentionally ignores register rows, xrefs, decompiler output, and instruction listings. Static layout imports render values as `<unknown>`.

For a Windows x64 function, add its return-address stack slot explicitly:

```bash
stkfmt ghidra examples/ghidra_function_listing.txt --abi windows-x64 --unicode
```

This labels the return address at `Stack[+0x0..+0x7]`.
