golang/go · error

%s and %s symbols must be in the same section

Error message

%s and %s symbols must be in the same section

What it means

loadPETable extracts a byte table from a PE (Windows) binary by slicing the section data between a start symbol's Value and an end symbol's Value. Because the slice is computed against a single section's Data(), both symbols must live in the same PE section; if they do not, the offsets are meaningless and could even panic on a bad slice. The library therefore refuses the operation rather than return garbage. This fires during pclntab/funcdata extraction from a Go PE binary (used by go tool nm, objdump, pprof).

Source

Thrown at src/cmd/internal/objfile/pe.go:179

		if len(f.Sections) < int(s.SectionNumber) {
			return nil, fmt.Errorf("symbol %s: section number %d is larger than max %d", name, s.SectionNumber, len(f.Sections))
		}
		return s, nil
	}
	return nil, fmt.Errorf("no %s symbol found", name)
}

func loadPETable(f *pe.File, sname, ename string) ([]byte, error) {
	ssym, err := findPESymbol(f, sname)
	if err != nil {
		return nil, err
	}
	esym, err := findPESymbol(f, ename)
	if err != nil {
		return nil, err
	}
	if ssym.SectionNumber != esym.SectionNumber {
		return nil, fmt.Errorf("%s and %s symbols must be in the same section", sname, ename)
	}
	sect := f.Sections[ssym.SectionNumber-1]
	data, err := sect.Data()
	if err != nil {
		return nil, err
	}
	return data[ssym.Value:esym.Value], nil
}

func (f *peFile) goarch() string {
	switch f.pe.Machine {
	case pe.IMAGE_FILE_MACHINE_I386:
		return "386"
	case pe.IMAGE_FILE_MACHINE_AMD64:
		return "amd64"
	case pe.IMAGE_FILE_MACHINE_ARM64:
		return "arm64"
	default:

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Rebuild the Windows binary with a stock 'go build' and avoid objcopy/manual section manipulation.
  2. Confirm the binary was produced by the Go toolchain for GOOS=windows and has not been stripped of pclntab.
  3. If you only need symbols, try 'go tool nm' on the original object file before linking instead of the final .exe.
Defensive patterns

Strategy: try-catch

Try / catch

// data, err := loadPETable(pe, "runtime.pclntab", "runtime.epclntab")
// if err != nil {
//     if strings.Contains(err.Error(), "must be in the same section") {
//         // binary is unsuitable for table extraction; fall back to symbol-only tooling
//     }
//     return err
// }

Prevention

When it happens

Trigger: Calling loadPETable (directly or via pclntab loading) where findPESymbol(sname).SectionNumber != findPESymbol(ename).SectionNumber — e.g. 'runtime.pclntab' and 'runtime.epclntab' resolved to different PE sections.

Common situations: Inspecting a Windows .exe that was post-processed by objcopy/stripping tools that re-laid-out sections, a corrupted PE binary, or a hand-crafted/merged object file. Also possible if the wrong start/end symbol pair is requested for the binary's Go version.

Related errors


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