golang/go · error

.pdata symbol %q has invalid relocation count

Error message

.pdata symbol %q has invalid relocation count

What it means

The Go linker's SEH processor found a `.pdata` section whose relocation count is not a multiple of 3. On AMD64 Windows, each `RUNTIME_FUNCTION` entry in `.pdata` consists of exactly 3 relocations (function start, function end, and unwind info pointer). A relocation count not divisible by 3 means the pdata section is malformed or was produced by a non-standard toolchain.

Source

Thrown at src/cmd/link/internal/loadpe/seh.go:46

	case sys.AMD64:
		return processSEHAMD64(ldr, pdata)
	default:
		// TODO: support SEH on other architectures.
		return nil, fmt.Errorf("unsupported architecture for SEH: %v", arch.Family)
	}
}

func processSEHAMD64(ldr *loader.Loader, pdata sym.LoaderSym) ([]loader.Sym, error) {
	// The following loop traverses a list of pdata entries,
	// each entry being 3 relocations long. The first relocation
	// is a pointer to the function symbol to which the pdata entry
	// corresponds. The third relocation is a pointer to the
	// corresponding .xdata entry.
	// Reference:
	// https://learn.microsoft.com/en-us/cpp/build/exception-handling-x64#struct-runtime_function
	rels := ldr.Relocs(pdata)
	if rels.Count()%3 != 0 {
		return nil, fmt.Errorf(".pdata symbol %q has invalid relocation count", ldr.SymName(pdata))
	}
	data := ldr.Data(pdata)
	entries := make([]loader.Sym, 0, rels.Count()/3)

	for i := 0; i < rels.Count(); i += 3 {
		// Create a new symbol for the pdata entry.
		entry := ldr.MakeSymbolBuilder("")
		entry.SetType(sym.SSEHSECT)
		entry.SetAlign(4)
		entry.SetSize(12)
		entryOff := int(rels.At(i).Off())
		entryEnd := entryOff + 4*3
		entry.SetData(data[entryOff:entryEnd:entryEnd])

		// Add a relocation from the target function to the pdata entry
		// and to the exception handler, if present, to ensure they are
		// retained by dead code elimination.
		if targetFunc := rels.At(i).Sym(); targetFunc != 0 {

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Clean and rebuild all object files from source to eliminate corruption: `go clean -cache && go build`.
  2. Inspect the offending object file's .pdata section with `dumpbin /headers file.obj` or `objdump -x file.obj` to verify the relocation count.
  3. Recompile the C/C++ code with a standard, up-to-date compiler (MSVC or MinGW-w64) that emits compliant pdata sections.
  4. Use external linker mode (`-ldflags=-linkmode=external`) to bypass Go's internal pdata processing.
  5. Isolate which object file triggers the error by building incrementally, then inspect or rebuild that specific file.

Example fix

# Bypass internal SEH processing with external linker
go build -ldflags='-linkmode=external' ./...

# Or clean and rebuild to fix corruption
go clean -cache
go build ./...
Defensive patterns

Strategy: validation

Validate before calling

// Validate .pdata relocation count before relying on SEH processing
// External check: dumpbin /relocations file.obj | grep pdata
// Ensure the count is divisible by 3.
// Not callable from Go user code — this is linker-internal.

Prevention

When it happens

Trigger: Fires in `processSEHAMD64` at seh.go:44-46 when `rels.Count()%3 != 0` for the `.pdata` symbol being processed. This check validates that pdata entries follow the standard 3-relocation-per-entry layout documented in the Microsoft PE specification (referenced via URL at seh.go:43).

Common situations: Linking a corrupt or manually-constructed PE object file with a malformed .pdata section. Using a very old or experimental C compiler that emits non-standard pdata relocation layouts. File truncation or corruption of the object file. Mixing object files from different architectures or ABI conventions. A linker bug that miscounts relocations when merging sections from multiple object files.

Related errors


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