For compiler authors
You're building a compiler or toolchain that produces EVM bytecode. Here's how to emit ethdebug/format data so debuggers can provide rich debugging experiences for your users.
What you need to emit
ethdebug/format defines several kinds of debug information:
- Type information — Describe the structure of data in your language (integers, structs, arrays, mappings)
- Pointer information — Describe where variables are stored at runtime, including dynamic locations computed from other values
- Program information — Describe what's in scope at each bytecode instruction, mapping bytecode back to source code
- Info schema — Bundle everything together with source files and compilation metadata
Quick example: describing a type
Here's how to describe a simple uint256:
A uint256 typeSchema:ethdebug/format/type/elementary/uint
{
"kind": "uint",
"bits": 256
}
A storage mapping from addresses to balances:
An address → uint256 mappingSchema:ethdebug/format/type/complex/mapping
{
"kind": "mapping",
"contains": {
"key": { "type": { "kind": "address" } },
"value": { "type": { "kind": "uint", "bits": 256 } }
}
}
Quick example: describing a storage variable
A pointer tells debuggers where to find a variable's value. For a uint256
at storage slot 0:
A simple storage pointerSchema:ethdebug/format/pointer/region/storage
{
"location": "storage",
"slot": "0x0",
"length": 32
}
For a dynamic array where the length is at slot 2 and elements start at
keccak256(2):
A dynamic array pointerSchema:ethdebug/format/pointer/collection
{
"group": [
{ "name": "array-length", "location": "storage", "slot": "0x2" },
{
"list": {
"count": { "$read": "array-length" },
"each": "i",
"is": {
"location": "storage",
"slot": {
"$sum": [{ "$keccak256": [{ "$wordsized": "0x2" }] }, "i"]
}
}
}
}
]
}
Integration approach
Most compilers can add ethdebug/format support incrementally:
- Start with types — Emit type definitions for your language's data structures. This can be a straightforward starting point.
- Add storage pointers — Describe where storage variables live. Many variables have static locations.
- Add memory/stack pointers — Describe temporary values. These often require tracking allocation during code generation.
- Add program information — Emit source mappings and scope information. This typically requires the most compiler changes.
Go deeper
Compiler implementation guide
Detailed guidance on emitting ethdebug/format from your compiler.
Specification
Formal schema definitions for all ethdebug/format structures.
Explore by topic
- Types — Full documentation on type definitions
- Pointers — Full documentation on pointer definitions
- Programs — Full documentation on program annotations
- Info schema — Full documentation on bundling debug data
- BUG Playground — See a working compiler that emits ethdebug/format