golang/go · error

missing __LINKEDIT segment

Error message

missing __LINKEDIT segment

What it means

`machoCombineDwarf` (the flow that merges DWARF from `dsymutil` back into a Mach-O executable for `-gcflags=-l` debugging) requires the executable to have a `__LINKEDIT` segment, because the string table — which must remain last for code signing — lives there and must be relocated to the end of the combined file. An executable without `__LINKEDIT` cannot be safely extended.

Source

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

	}
	defer dwarff.Close()
	outf, err := os.OpenFile(outexe, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
	if err != nil {
		return err
	}
	defer outf.Close()
	dwarfm, err := macho.NewFile(dwarff)
	if err != nil {
		return err
	}
	defer dwarfm.Close()

	// The string table needs to be the last thing in the file
	// for code signing to work. So we'll need to move the
	// linkedit section, but all the others can be copied directly.
	linkseg := exem.Segment("__LINKEDIT")
	if linkseg == nil {
		return fmt.Errorf("missing __LINKEDIT segment")
	}

	if _, err := exef.Seek(0, 0); err != nil {
		return err
	}
	if _, err := io.CopyN(outf, exef, int64(linkseg.Offset)); err != nil {
		return err
	}

	realdwarf := dwarfm.Segment("__DWARF")
	if realdwarf == nil {
		return fmt.Errorf("missing __DWARF segment")
	}

	// Try to compress the DWARF sections. This includes some Apple
	// proprietary sections like __apple_types.
	compressedSects, compressedBytes, err := machoCompressSections(ctxt, dwarfm)
	if err != nil {

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Feed `machoCombineDwarf` a freshly linked, unstripped executable produced by the standard Apple `ld`.
  2. Run combineDwarf before any `strip`/post-processing step.
  3. Verify with `otool -l bin | grep -A2 LINKEDIT` that the segment exists.

Example fix

# before
strip bin/app            # removes/alters layout
# combineDwarf then fails
go build -o bin/app ./...

# after: combine DWARF on the raw linker output, strip later
go build -o bin/app ./...
# (combineDwarf runs internally here on the pristine binary)
strip bin/app
Defensive patterns

Strategy: validation

Validate before calling

# Confirm the executable has a __LINKEDIT segment before combineDwarf
otool -l bin/app 2>/dev/null | grep -q 'LC_SEGMENT_64$' && otool -l bin/app | grep -A1 '__LINKEDIT' | grep -q __LINKEDIT && echo 'LINKEDIT present' || echo 'missing LINKEDIT'

Try / catch

# Strip only after combineDwarf succeeds
set +e
go build -o bin/app ./...
rc=$?
set -e
if [ $rc -ne 0 ]; then
  rm -f bin/app && go build -o bin/app ./...
fi

Prevention

When it happens

Trigger: Combining DWARF into a Mach-O that is not a standard executable (a dylib, a kernel extension, a stripped/corrupt binary, or an object produced by a non-Apple `ld`); passing a pre-stripped binary to the combine-DWARF step; a toolchain bug that dropped `__LINKEDIT`.

Common situations: Running `strip` on the binary before combineDwarf; linking with an experimental/alternative linker; building a non-executable Mach-O (bundle, object) and invoking the DWARF-combine path.

Related errors


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