golang/go · error

invalid section number in symbol table

Error message

invalid section number in symbol table

What it means

When parsing PE (Windows) symbol tables, each symbol references a section by its `SectionNumber`. After handling special cases (N_UNDEF, N_ABS, N_DEBUG), the code checks whether `SectionNumber` falls within the valid range [1, len(Sections)]. If it is negative or exceeds the number of sections in the file, this error fires, indicating a corrupt or malformed PE binary.

Source

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

	var syms []Sym
	for _, s := range f.pe.Symbols {
		const (
			N_UNDEF = 0  // An undefined (extern) symbol
			N_ABS   = -1 // An absolute symbol (e_value is a constant, not an address)
			N_DEBUG = -2 // A debugging symbol
		)
		sym := Sym{Name: s.Name, Addr: uint64(s.Value), Code: '?'}
		switch s.SectionNumber {
		case N_UNDEF:
			sym.Code = 'U'
		case N_ABS:
			sym.Code = 'C'
		case N_DEBUG:
			sym.Code = '?'
		default:
			if s.SectionNumber < 0 || len(f.pe.Sections) < int(s.SectionNumber) {
				return nil, fmt.Errorf("invalid section number in symbol table")
			}
			sect := f.pe.Sections[s.SectionNumber-1]
			const (
				text  = 0x20
				data  = 0x40
				bss   = 0x80
				permW = 0x80000000
			)
			ch := sect.Characteristics
			switch {
			case ch&text != 0:
				sym.Code = 'T'
			case ch&data != 0:
				if ch&permW == 0 {
					sym.Code = 'R'
				} else if bssSectionNumber == s.SectionNumber && bssAddr > 0 && s.Value >= bssAddr {
					// Past runtime.bss is BSS.
					sym.Code = 'B'

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Verify PE integrity: `dumpbin /symbols <file>` or use a PE analysis tool to check for structural errors.
  2. Rebuild the binary from source with a reliable linker.
  3. If the binary was downloaded, re-download it to rule out truncation.
  4. Use `pev` or similar PE forensics tools to assess the extent of corruption.

Example fix

// before — corrupt PE binary
f, err := objfile.Open("corrupt.exe")
_, err := f.Symbols()  // fails: invalid section number

// after — rebuild or re-download
$ go build -o app.exe ./...
f, err := objfile.Open("app.exe")
_, err := f.Symbols()  // succeeds
Defensive patterns

Strategy: validation

Validate before calling

// Validate PE symbol section numbers
func validatePESymbols(path string) error {
    f, err := pe.Open(path)
    if err != nil { return err }
    defer f.Close()
    for _, s := range f.Symbols {
        if s.SectionNumber > 0 && int(s.SectionNumber) > len(f.Sections) {
            return fmt.Errorf("corrupt PE: symbol %s references section %d (max %d)",
                s.Name, s.SectionNumber, len(f.Sections))
        }
    }
    return nil
}

Try / catch

syms, err := f.Symbols()
if err != nil && strings.Contains(err.Error(), "invalid section number") {
    return fmt.Errorf("corrupt PE binary — rebuild or re-download: %w", err)
}

Prevention

When it happens

Trigger: Calling `objfile.Open` on a PE binary followed by `File.Symbols()`, where the PE symbol table contains an entry whose `SectionNumber` is out of range (negative or greater than the section count). This indicates the PE file is corrupt, was produced by a buggy tool, or was truncated.

Common situations: Analyzing a corrupt or partially-downloaded Windows `.exe` or `.dll`. Using a binary produced by a non-standard or buggy linker that wrote incorrect section numbers. Post-processing a PE file with a tool that corrupted the symbol table. Reading a PE file that was patched or hex-edited.

Related errors


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