# magic-trace Debug Info and Symbol Table Requirements: A Complete Guide

> Understand magic-trace debug info and symbol table needs. Learn how to configure your build for full source code tracing and symbol resolution to avoid raw addresses.

- Repository: [Jane Street/magic-trace](https://github.com/janestreet/magic-trace)
- Tags: how-to-guide
- Published: 2026-05-24

---

**magic-trace requires an unstripped ELF symbol table (`.symtab` or `.dynsym`) and DWARF debug sections (`.debug_line` and `.debug_info`) to resolve function names and source locations; without these, traces display raw addresses as `[unknown]` and line-level selection fails.**

Understanding the magic-trace debug info and symbol table requirements is essential for effective tracing with the [janestreet/magic-trace](https://github.com/janestreet/magic-trace) tool. This OCaml-based utility analyzes ELF binaries to map sampled addresses back to human-readable function names and exact source file locations. The implementation relies on specific sections within the binary to perform this resolution.

## Symbol Table Requirements (`.symtab` and `.dynsym`)

magic-trace requires access to a **symbol table** to translate memory addresses into function names. The tool reads either a regular symbol table (`.symtab`) or a dynamic symbol table (`.dynsym`) for dynamically linked programs.

In [`src/elf.ml`](https://github.com/janestreet/magic-trace/blob/main/src/elf.ml), the function `Elf.all_symbols` queries `Owee_elf.Symbol_table` to collect the complete list of symbols from the binary. This implementation allows magic-trace to map instruction pointers to their corresponding function names during trace analysis.

If the binary is fully stripped—meaning it lacks both `.symtab` and `.dynsym` sections—magic-trace can still record trace events, but it cannot resolve addresses to function names. In this scenario, all symbols appear as `[unknown]` in the output, making interpretation significantly more difficult.

## DWARF Debug Information Requirements

To map addresses to specific source files and line numbers, magic-trace requires **DWARF debug information**, specifically the `.debug_line` and `.debug_info` sections. These sections contain the mapping between machine code addresses and their original source locations.

The code responsible for line-level selections resides in [`src/symbol_selection.ml`](https://github.com/janestreet/magic-trace/blob/main/src/symbol_selection.ml). When you request line-specific tracing using the `symbol:?...` syntax, the `select_within_file` function calls `Elf.all_file_selections` to retrieve available line information. If the ELF binary lacks the required DWARF sections, `Elf.all_file_selections` returns an empty list, causing `select_within_file` to abort with the error message *"No lines found, possibly because of missing debug info"* (see lines 48-49 of [`src/symbol_selection.ml`](https://github.com/janestreet/magic-trace/blob/main/src/symbol_selection.ml)).

Without DWARF line information, magic-trace cannot display source files or line numbers in its output, limiting the tool's effectiveness for source-level debugging.

## Optional but Recommended Components

While not strictly required for basic operation, two additional ELF sections enhance magic-trace functionality:

- **DWARF frame information (`.debug_frame`)**: Supports accurate stack unwinding and call-stack reconstruction during tracing.
- **Build ID (`.note.gnu.build-id`)**: Enables `perf`-based symbol resolution, which helps when working with external symbol maps or separate debug files.

Both sections are typically generated automatically when compiling with standard debug flags.

## How to Compile Binaries for magic-trace

To satisfy the magic-trace debug info and symbol table requirements, compile your program with debug symbols enabled and avoid stripping the binary.

For **OCaml programs**, use the `-g` flag with `ocamlopt`:

```ocaml
(* hello.ml *)
let () = Printf.printf "Hello, magic-trace!\n"

```

```bash
ocamlopt -g hello.ml -o hello

```

This command preserves both the symbol table and DWARF debug sections. Run magic-trace with the `-debug` flag to verify symbol resolution:

```bash
magic-trace -debug hello

```

When properly compiled, the output will display resolved function names (e.g., `hello`) along with source file and line number information for each sampled instruction.

**Never run `strip` on binaries intended for tracing.** Stripping removes the `.symtab` section and debug sections entirely:

```bash
strip hello
magic-trace -debug hello  # Symbols appear as [unknown]

```

## What Happens When Information Is Missing

The following table summarizes the impact of missing debug data:

| Missing Component | Visual Indicator | Functional Impact |
|-------------------|------------------|-------------------|
| Symbol table (`.symtab`/`.dynsym`) | Function names display as `[unknown]` | Raw address traces only; no function resolution |
| DWARF line info (`.debug_line`) | No source file/line numbers shown | `select_within_file` fails with "No lines found, possibly because of missing debug info" |
| DWARF frame info (`.debug_frame`) | Incomplete call stacks | Limited stack unwinding capability |

## Summary

- ** magic-trace requires unstripped ELF binaries** containing either `.symtab` (static) or `.dynsym` (dynamic) symbol tables to resolve function names.
- **DWARF sections (`.debug_line` and `.debug_info`) are mandatory** for source-level resolution and line selection via [`symbol_selection.ml`](https://github.com/janestreet/magic-trace/blob/main/symbol_selection.ml).
- **Compile with `-g` and avoid `strip`** to ensure all required sections remain in the binary.
- **Optional `.debug_frame` and `.note.gnu.build-id`** sections improve stack unwinding and external symbol resolution.

## Frequently Asked Questions

### Can magic-trace work on stripped binaries?

Yes, magic-trace can trace stripped binaries, but the output is severely limited. Without the symbol table (`.symtab` or `.dynsym`), the tool cannot map addresses to function names, displaying `[unknown]` instead. Without DWARF debug sections, no source file or line number information is available. As implemented in [`src/elf.ml`](https://github.com/janestreet/magic-trace/blob/main/src/elf.ml), the `Elf.all_symbols` function returns an empty result for stripped binaries, forcing raw address mode.

### Which compiler flags generate the required debug info for magic-trace?

Use the `-g` flag when compiling with OCaml (`ocamlopt -g`) or equivalent debug flags in other languages (e.g., `-g` for GCC/Clang). This flag instructs the compiler to generate the symbol table and DWARF sections (`.debug_line`, `.debug_info`). Additionally, ensure you do not run `strip` or link with `-s`, as these remove the debug sections that magic-trace depends on for symbol resolution in [`src/symbol_selection.ml`](https://github.com/janestreet/magic-trace/blob/main/src/symbol_selection.ml).

### Why does line-level selection fail with "No lines found" error?

This error occurs when the binary lacks DWARF line information (`.debug_line`). In [`src/symbol_selection.ml`](https://github.com/janestreet/magic-trace/blob/main/src/symbol_selection.ml), the `select_within_file` function calls `Elf.all_file_selections`, which returns an empty list if the ELF file does not contain the required debug sections. The function then constructs the error string at lines 48-49: *"No lines found, possibly because of missing debug info"*. Recompile with `-g` and verify the binary is not stripped to resolve this issue.

### Is DWARF frame information (`.debug_frame`) mandatory for magic-trace?

No, `.debug_frame` is optional but strongly recommended. magic-trace can perform basic tracing without it, but missing frame information may limit call-stack reconstruction during trace analysis. The section aids in stack unwinding when the tool needs to reconstruct the sequence of function calls. Most compilers include this automatically when using `-g`, so no additional flags are typically required.