---
title: "DWARF as a Shared Reverse Engineering Format"
description: "Create DWARF debug information with the LIEF Extended DWARF editor and share reverse-engineered types and functions between Binary Ninja and Ghidra plugins."
canonical_url: "https://lief.re/blog/2025-05-27-dwarf-editor/"
markdown_url: "https://lief.re/blog/2025-05-27-dwarf-editor/index.md"
authors: ["Romain Thomas"]
date_published: "2025-05-27T00:00:00Z"
date_modified: "2025-05-27T00:00:00Z"
language: "en-US"
section: "blog"
tags: ["DWARF","LIEF Extended","reverse-engineering","Binary Ninja","Ghidra"]
categories: []
---

# DWARF as a Shared Reverse Engineering Format

> Create DWARF debug information with the LIEF Extended DWARF editor and share reverse-engineered types and functions between Binary Ninja and Ghidra plugins.

![Featuring Image](https://lief.re/blog/2025-05-27-dwarf-editor/featured.webp)





## Introduction

When reverse engineering binaries, we could want, at some point, to share the reverse-engineered
information with others. The DWARF format, originally designed to hold debug
information associated with the original source code, is also well-suited for
storing reverse-engineered information such as structures and function names.

This blog post introduces a new API in *LIEF extended* to create DWARF files.
It also introduces two plugins for Ghidra and BinaryNinja to export binary analysis
into DWARF.

## Creating DWARF with LIEF (extended)

[LIEF extended](https://lief.re/doc/latest/extended/intro.html) now provides a
comprehensive API to create DWARF files.

This API is available in Python, Rust, and C++ and it looks like this:

```python
import lief

elf = lief.ELF.parse("./libd5A7BCF0524B8.so")

editor: lief.dwarf.Editor = lief.dwarf.Editor.from_binary(elf)
unit: lief.dwarf.editor.CompilationUnit = editor.create_compilation_unit()
unit.set_producer("Generated by LIEF (LLVM backend)")

func: lief.dwarf.editor.Function = unit.create_function("vm_set_register")
func.set_address(0x1400023)

editor.write("libd5A7BCF0524B8.dwarf")
```

Under the hood, LIEF uses the LLVM's DWARF backend to create and generate the final DWARF.
In contrast to LLVM's low-level API, LIEF provides an abstraction that simplifies
the implementation details of the DWARF format.

For instance, if we want to create a DWARF for a function
that contains a **stack variable** at the offset (on the stack) `8`,
we can use the following API:

```python
func: lief.dwarf.editor.Function = unit.create_function("vm_set_register")

var: lief.dwarf.editor.Variable = func.create_stack_variable("my_stack_variable")
var.set_stack_offset(8)
```

This code generates the following DWARF:

```text
0x0000000c: DW_TAG_compile_unit
              DW_AT_producer    ("Generated by LIEF (LLVM backend)")

0x00000011:   DW_TAG_subprogram
                DW_AT_name      ("vm_set_register")
                DW_AT_entry_pc  (0x0000000001400023)

0x0000001e:     DW_TAG_variable
                  DW_AT_name    ("my_stack_variable")
                  DW_AT_location        (DW_OP_fbreg -8)
```

Defining the `DW_AT_location` for a stack variable is not as simple as it sounds.
It requires defining some kind of DWARF expression and if you are curious about
the actual implementation, you can check this [GitHub Gist](https://gist.github.com/romainthomas/1f7ba555c4439d9b4b457e293834ec5a).


**Summary**

LIEF exposes a high-level API to create DWARF based on the LLVM's low-level API


## DWARF and Reverse Engineering

Reverse engineering tools typically use their own format to store information about
analyzed binaries such as `*.idb` and `*.bndb`. Most of these tools are not compatible
with each other, except Binary Ninja which has a support for loading IDB ([*Migrating from IDA*](https://docs.binary.ninja/guide/migration/migrationguideida.html)).
For Ghidra, importing IDA database is a non-goal (c.f. [issue #2921](https://github.com/NationalSecurityAgency/ghidra/issues/2921))

One alternative is to export binary information using [BinExport](https://github.com/google/binexport)
or [quokka](https://github.com/quarkslab/quokka),
but many tools lack support for **importing** the exported data.

In contrast, Binary Ninja, Ghidra, and IDA all have built-in support for loading
DWARF files and external DWARF files.
The DWARF format is primarily designed to hold information about the original
source code, and the purpose of reverse engineering is to recover the semantic
of the source code information from the binary.

Therefore, we could use the DWARF as a reverse-engineering shared format to
export types, functions, and variables from reverse-engineered binaries.

![LIEF plugins export Binary Ninja and Ghidra analysis to DWARF for use across reverse-engineering tools](https://lief.re/blog/2025-05-27-dwarf-editor/tool2dw.webp)

DWARF is compatible with PE binaries, even though it is not the default format
for storing debug information on Windows.


**PE / DWARF**

If you compile a Windows executable with `clang[-cl]` and with the flags `-g -gdwarf-5`,
the final PE will contains DWARF information along with an external `.pdb`.


Currently, Binary Ninja is the only tool with a built-in plugin that can generate
a DWARF file from a `BinaryView` representation. However, it lacks the ability to
export stack-based variables, which can be crucial information.

The next section introduces two plugins for Ghidra and BinaryNinja to generate DWARF
from these tools.

## BinaryNinja & Ghidra Plugins

![Binary Ninja and Ghidra plugin logos](https://lief.re/blog/2025-05-27-dwarf-editor/plugins.webp)

To provide some background on this feature, I initially developed the BinaryNinja's DWARF exporter plugin
for my own needs before Vector35 team released an official plugin in BinaryNinja 3.5.
I use this plugin in my reverse engineering workflow to
symbolize [QBDI](https://github.com/QBDI/QBDI) traces from DWARF information:

1. I statically reverse-engineer the binary
2. I generate a DWARF file
3. I trace the binary with QBDI that uses the DWARF file to symbolize:
    - Stack accesses (hence the need to stack variables in the DWARF)
    - Function calls and their parameters
    - Static variables accesses
4. goto 1.

For instance, I used this process to reverse engineer the [DroidGuard VM](https://www.romainthomas.fr/publication/22-sstic-blackhat-droidguard-safetynet/)
a few years ago.
I'll take this blog post as an opportunity to share the DWARF associated with
my reverse engineering of the VM `libd5A7BCF0524B8.so`:

- **Original Binary:** [libd5A7BCF0524B8.so](https://lief.re/blog/2025-05-27-dwarf-editor/libd5A7BCF0524B8.so)
- **Binary with generated DWARF:** [libd5A7BCF0524B8.so.debug](https://lief.re/blog/2025-05-27-dwarf-editor/libd5A7BCF0524B8.so.debug)

As mentioned earlier, this functionality is integrated into BinaryNinja since version 3.5,
so I'll focus more on the Ghidra plugin. For more information about the Binary Ninja
integration, visit [LIEF - Binary Ninja](https://lief.re/doc/latest/plugins/binaryninja/index.html).

The Ghidra plugin allows us to export Ghidra's Program information into a DWARF file.
This can be done from the Project Manager interface by selecting the `DWARF` format
in the export section:

![Ghidra Project Manager export dialog with DWARF selected as the output format](https://lief.re/blog/2025-05-27-dwarf-editor/project-dwarf-export.webp)

You can also use this plugin from the `CodeBrowser` tool, by left-clicking on
the LIEF menu and selecting `Export as DWARF`:

![Ghidra CodeBrowser LIEF menu with the Export as DWARF command](https://lief.re/blog/2025-05-27-dwarf-editor/codebrowser-export-dwarf.webp)

The plugin is primarily written in Java (using the JNI) and you can also generate a
DWARF file from a headless Java script:

```java
import lief.ghidra.core.dwarf.export.Manager;
import lief.ghidra.core.NativeBridge;

public class LiefDwarfExportScript extends GhidraScript {
  @Override
  protected void run() throws Exception {
    NativeBridge.init();
    Manager manager = new Manager(currentProgram);
    File output = new File("/home/romain/output.dwarf");
    manager.export(output);
  }
}
```


**IDA Support**

I do not plan to support IDA for this functionality. However, if there is strong
demand for it, feel free to reach out to me. You can also create your own IDA
script using the Python or C++ API.


## Last Word

This DWARF export functionality is still in early development, so I cannot
guarantee it is free of bugs. The current version also does not export
comments, but I plan to support this feature in the future.

The source code for the plugins is here:

- [plugins/binaryninja](https://github.com/lief-project/LIEF/tree/main/plugins/binaryninja)
- [plugins/ghidra](https://github.com/lief-project/LIEF/tree/main/plugins/ghidra)


Thank you for using LIEF.

Romain.


[^bn-dwarf-plugin]: https://github.com/Vector35/binaryninja-api/tree/f3c7443839a69bdb49b8313e6eef7a3834feb85f/plugins/dwarf/dwarf_export
