golang/go · error

no room to add dwarf info. Need at least %d padding bytes, f

Error message

no room to add dwarf info. Need at least %d padding bytes, found %d

What it means

The DWARF load command must be inserted into the header padding between the end of existing load commands (`dwarfCmdOffset`) and the start of `__text`. If the available padding (`textsect.Offset - dwarfCmdOffset`) is smaller than the DWARF segment's load-command size (`realdwarf.Len`), there is no room and the link aborts rather than overwrite executable code.

Source

Thrown at src/cmd/link/internal/ld/macho_combine_dwarf.go:152

	linkstart := Rnd(dwarfstart+int64(dwarfsize), *FlagRound)
	if _, err := outf.Seek(linkstart, 0); err != nil {
		return err
	}
	if _, err := io.Copy(outf, exef); err != nil {
		return err
	}

	// Now we need to update the headers.
	textsect := exem.Section("__text")
	if textsect == nil {
		return fmt.Errorf("missing __text section")
	}

	cmdOffset := imacho.FileHeaderSize(exem)
	dwarfCmdOffset := uint32(cmdOffset) + exem.FileHeader.Cmdsz
	availablePadding := textsect.Offset - dwarfCmdOffset
	if availablePadding < realdwarf.Len {
		return fmt.Errorf("no room to add dwarf info. Need at least %d padding bytes, found %d", realdwarf.Len, availablePadding)
	}
	// First, copy the dwarf load command into the header. It will be
	// updated later with new offsets and lengths as necessary.
	if _, err := outf.Seek(int64(dwarfCmdOffset), 0); err != nil {
		return err
	}
	if _, err := io.CopyN(outf, bytes.NewReader(realdwarf.Raw()), int64(realdwarf.Len)); err != nil {
		return err
	}
	if _, err := outf.Seek(int64(unsafe.Offsetof(exem.FileHeader.Ncmd)), 0); err != nil {
		return err
	}
	if err := binary.Write(outf, exem.ByteOrder, exem.Ncmd+1); err != nil {
		return err
	}
	if err := binary.Write(outf, exem.ByteOrder, exem.Cmdsz+realdwarf.Len); err != nil {
		return err
	}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Reduce the number of load commands (fewer rpaths, fewer embedded dylibs) to free header padding.
  2. Increase the header padding via the external linker: `-extldflags='-headerpad 0x1000'` (or larger).
  3. Strip DWARF instead of combining it (`-ldflags='-s -w'`) if you only need a shippable binary.
  4. Split the program so the DWARF segment load command is smaller.

Example fix

# before: DWARF load command too large for default header pad
go build -o bin/app ./...

# after: request more header padding from the external linker
go build -ldflags='-extldflags=-headerpad_max_install_names -linkmode=external' -o bin/app ./...
Defensive patterns

Strategy: fallback

Validate before calling

# Estimate header padding vs load-command count
LCOUNT=$(otool -l bin/app 2>/dev/null | grep -c 'LC_')
echo "load commands: $LCOUNT (more = less room for DWARF cmd)"
# If close to the limit, plan to strip DWARF or grow headerpad

Try / catch

# Fall back to a stripped build if there is no header room for DWARF
set +e
go build -o bin/app ./...
rc=$?
set -e
if [ $rc -ne 0 ]; then
  echo 'no room for DWARF; building stripped' >&2
  go build -ldflags='-s -w' -o bin/app ./...
fi

Prevention

When it happens

Trigger: An executable with many load commands (large entitlements, many rpaths, many dylibs) consuming most header padding; a very large DWARF segment load command; an older SDK that left less default padding; binaries built with unusual `-pagezero_size` or segment-alignment flags that shrink the header gap.

Common situations: macOS apps with extensive entitlements/embedded dylibs; CI that injects many `-rpath` flags; large Go programs whose DWARF load command exceeds the default ~4KB header pad.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/a586d217b4e9e78b. Report an issue: GitHub.