{"record":{"id":"a1bcb93631a9d954","repo":"golang/go","slug":"s-invalid-symbol-binding-d-a1bcb9","errorCode":null,"errorMessage":"%s: invalid symbol binding %d","messagePattern":"(.+?): invalid symbol binding (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/link/internal/loadpe/ldpe.go","lineNumber":745,"sourceCode":"\t// Microsoft's PE documentation is contradictory. It says that the symbol's complex type\n\t// is stored in the pesym.Type most significant byte, but MSVC, LLVM, and mingw store it\n\t// in the 4 high bits of the less significant byte.\n\tswitch uint8(pesym.Type&0xf0) >> 4 {\n\tdefault:\n\t\treturn nil, 0, fmt.Errorf(\"%s: invalid symbol type %d\", symname, pesym.Type)\n\n\tcase IMAGE_SYM_DTYPE_FUNCTION, IMAGE_SYM_DTYPE_NULL:\n\t\tswitch pesym.StorageClass {\n\t\tcase IMAGE_SYM_CLASS_EXTERNAL: //global\n\t\t\ts = state.l.LookupOrCreateCgoExport(name, 0)\n\n\t\tcase IMAGE_SYM_CLASS_NULL, IMAGE_SYM_CLASS_STATIC, IMAGE_SYM_CLASS_LABEL:\n\t\t\ts = state.l.LookupOrCreateCgoExport(name, state.localSymVersion)\n\t\t\tbld = makeUpdater(state.l, bld, s)\n\t\t\tbld.SetDuplicateOK(true)\n\n\t\tdefault:\n\t\t\treturn nil, 0, fmt.Errorf(\"%s: invalid symbol binding %d\", symname, pesym.StorageClass)\n\t\t}\n\t}\n\n\tif s != 0 && state.l.SymType(s) == 0 && (pesym.StorageClass != IMAGE_SYM_CLASS_STATIC || pesym.Value != 0) {\n\t\tbld = makeUpdater(state.l, bld, s)\n\t\tbld.SetType(sym.SXREF)\n\t}\n\n\treturn bld, s, nil\n}\n\n// preprocessSymbols walks the COFF symbols for the PE file we're\n// reading and looks for cases where we have both a symbol definition\n// for \"XXX\" and an \"__imp_XXX\" symbol, recording these cases in a map\n// in the state struct. This information will be used in readpesym()\n// above to give such symbols special treatment. This function also\n// gathers information about COMDAT sections/symbols for later use\n// in readpesym().","sourceCodeStart":727,"sourceCodeEnd":763,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/link/internal/loadpe/ldpe.go#L727-L763","documentation":"The Go linker's PE (Windows) object loader encountered a COFF symbol whose StorageClass value does not match any of the recognized classes (IMAGE_SYM_CLASS_EXTERNAL, IMAGE_SYM_CLASS_NULL, IMAGE_SYM_CLASS_STATIC, IMAGE_SYM_CLASS_LABEL). The symbol's storage class determines how it is bound during linking; an unrecognized class means the linker cannot decide whether to treat it as a global, local, or label symbol. This error surfaces the raw numeric storage class value so the offending symbol and its provenance can be identified.","triggerScenarios":"Triggered during `readpesym` when processing a COFF symbol from a PE/COFF object file (typically a .obj or .o produced by an external C/C++ compiler via cgo on Windows). The switch on `pesym.StorageClass` at ldpe.go:735 falls through to the default branch. The symbol's type field bits 4-7 must be FUNCTION or NULL (checked at ldpe.go:730), so this only fires for symbols with a valid complex type but an unsupported storage class.","commonSituations":"Using cgo on Windows with a C compiler that emits unusual COFF storage classes (e.g., IMAGE_SYM_CLASS_WEAK_EXTERNAL, IMAGE_SYM_CLASS_SECTION, IMAGE_SYM_CLASS_EXTERNAL_DEF). Mixing object files from non-standard toolchains (LLVM/Clang variants, older MSVC, or unusual MinGW builds). Corrupt or truncated object files where the storage class byte is garbage. Upgrading a C compiler that starts emitting symbols the Go linker hasn't been taught to handle.","solutions":["Inspect the exact storage class number in the error output and cross-reference it with the PE/COFF IMAGE_SYM_CLASS_* constants in debug/pe to understand what symbol type is being emitted.","Update to the latest Go release — support for additional storage classes is added over time; check the Go issue tracker for your specific storage class value.","Recompile the offending C/object file with a different toolchain (e.g., switch between MSVC and MinGW-w64, or update to a newer compiler version) to emit standard storage classes.","File a bug at https://go.dev/issue with the object file, the symbol name, and the storage class value so the linker can be extended to handle it.","If you control the C source, mark symbols explicitly as `extern` (IMAGE_SYM_CLASS_EXTERNAL) or `static` (IMAGE_SYM_CLASS_STATIC) to force a recognized storage class."],"exampleFix":"// C source: ensure symbols use standard storage classes\n// before (weak symbol — may emit IMAGE_SYM_CLASS_WEAK_EXTERNAL):\n__attribute__((weak)) int my_symbol(void) { return 0; }\n\n// after (force a recognized storage class):\nint my_symbol(void) { return 0; }","handlingStrategy":"validation","validationCode":"// Before linking, inspect object files for unsupported storage classes\n// This is a linker-internal check; end users validate by inspecting .obj files\n// Use dumpbin (MSVC) or objdump (MinGW) to review symbol storage classes:\n//   dumpbin /symbols file.obj\n//   objdump -t file.obj\n// Look for storage class values outside EXTERNAL(2), NULL(3), STATIC(3), LABEL(6)","typeGuard":"// Not applicable — this is an internal linker error with no runtime API surface.\n// The PE loader is invoked during go build/link, not callable by user code.","tryCatchPattern":null,"preventionTips":["Keep your C compiler updated to a version known to produce Go-linker-compatible COFF symbols.","When using cgo on Windows, prefer standard symbol declarations (extern/static) over compiler-specific extensions like weak symbols.","Test cgo builds after updating your C compiler toolchain — new compiler versions may introduce new storage classes.","Use -ldflags=-linkmode=external to delegate to the system linker if the internal linker rejects symbols."],"tags":["linker","pe","coff","windows","cgo","object-file"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}