go-delve/delve · error
could not open elf file to resolve symbol offset: %w
Error message
could not open elf file to resolve symbol offset: %w
What it means
SetUProbe (used by the eBPF non-stop tracing backend) locates the image containing the target function via PCToImage and then opens the ELF file with elf.Open to resolve symbol offsets for the uprobe attachment. If the ELF file cannot be opened — missing file, wrong path recorded in debug info, or permission problems — this wrapped error is returned and the uprobe is not installed.
Source
Thrown at pkg/proc/native/proc_linux.go:994
}
key := entryPC
err = dbp.os.ebpf.UpdateArgMap(key, goidOffset, args, offset, false)
if err != nil {
return err
}
debugname := dbp.bi.Images[0].Path
// First attach a uprobe at all return addresses. We do this instead of using a uretprobe
// for two reasons:
// 1. uretprobes do not play well with Go
// 2. uretprobes seem to not restore the function return addr on the stack when removed, destroying any
// kind of workaround we could come up with.
// TODO(derekparker): this whole thing could likely be optimized a bit.
img := dbp.BinInfo().PCToImage(fn.Entry)
f, err := elf.Open(img.Path)
if err != nil {
return fmt.Errorf("could not open elf file to resolve symbol offset: %w", err)
}
var regs proc.Registers
mem := dbp.Memory()
regs, _ = dbp.memthread.Registers()
instructions, err := proc.Disassemble(mem, regs, &proc.BreakpointMap{}, dbp.BinInfo(), fn.Entry, fn.End)
if err != nil {
return err
}
var addrs []uint64
for _, instruction := range instructions {
if instruction.IsRet() {
addrs = append(addrs, instruction.Loc.PC)
}
}
addrs = append(addrs, proc.FindDeferReturnCalls(instructions)...)
for _, addr := range addrs {View on GitHub (pinned to a23773e6c3)
Solutions
- Verify the file at the path in the error exists and is readable (ls -l <path> from the error's wrapped message).
- Rebuild with absolute paths / don't move or delete the binary while tracing (dlv exec <absolute-path>).
- If debugging inside a container, run dlv inside the same container or mount the binary at the same path it was built at.
- Fall back to the non-eBPF tracing backend (dlv trace without eBPF support) if the ELF cannot be restored.
Example fix
// before: binary replaced after start, stale path sudo dlv trace --ebpf ./myapp // after: keep the exact binary that was executed sudo cp myapp /opt/app/myapp sudo dlv trace --ebpf --exec /opt/app/myapp
Defensive patterns
Strategy: validation
Validate before calling
// verify the ELF at the path recorded in debug info is openable before tracing
f, err := elf.Open(binPath)
if err != nil {
return fmt.Errorf("ELF for eBPF tracing unavailable: %w", err)
}
f.Close()
// and confirm the binary hasn't been replaced since launch
fi1, _ := os.Stat(binPath); _ = fi1 Try / catch
err := dlvTrace(binPath, fn)
if err != nil && strings.Contains(err.Error(), "could not open elf file") {
// locate the real image path from build info and retry with absolute path
realPath, _ := filepath.Abs(binPath)
dlvTrace(realPath, fn)
} Prevention
- Never rebuild, move, or delete the binary while an eBPF trace session runs
- Always invoke dlv with an absolute path to the executable
- Build with absolute source paths so DWARF records reachable file paths
- When tracing inside containers, run dlv in the same mount namespace as the target
When it happens
Trigger: Running `dlv trace` with the eBPF backend (SetUProbe) when the ELF file at img.Path (the path recorded in the binary's DWARF/debug info) cannot be opened: binary deleted or rebuilt after the process started, relative/incorrect build path, or read permission denied.
Common situations: Binary was rebuilt or replaced after the process was launched (stale DWARF path); debugging a binary built in a container/CI path that doesn't exist on the host; stripped or relocated binaries; cross-mounted filesystems where the original build path is unavailable.
Related errors
- too many arguments in traced function, max is 12 input+retur
- no eBPF program loaded
- eBPF map not loaded
- could not find symbol in executable sections of binary
- eBPF disabled
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/0b6899035c623575.
Report an issue: GitHub.