golang/go · error

loadelf: %s: %v

Error message

loadelf: %s: %v

What it means

This is the top-level wrapper for all ELF-object loading errors. `Load` reads an ELF host/object file and wraps any local failure (malformed header, bad section, unsupported machine, relocation error) as `loadelf: <path>: <detail>`. The `<path>` (`pn`) identifies exactly which object file failed, and the detail string pinpoints the sub-failure (e.g. `malformed elf file`, `not an ELF file`, `reloc ... not supported`).

Source

Thrown at src/cmd/link/internal/loadelf/ldelf.go:246

			if attrList.err != nil {
				return false, 0, fmt.Errorf("could not parse .ARM.attributes\n")
			}
		}
	}
	return found, ehdrFlags, nil
}

// Load loads the ELF file pn from f.
// Symbols are installed into the loader, and a slice of the text symbols is returned.
//
// On ARM systems, Load will attempt to determine what ELF header flags to
// emit by scanning the attributes in the ELF file being loaded. The
// parameter initEhdrFlags contains the current header flags for the output
// object, and the returned ehdrFlags contains what this Load function computes.
// TODO: find a better place for this logic.
func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, pkg string, length int64, pn string, initEhdrFlags uint32) (textp []loader.Sym, ehdrFlags uint32, err error) {
	errorf := func(str string, args ...any) ([]loader.Sym, uint32, error) {
		return nil, 0, fmt.Errorf("loadelf: %s: %v", pn, fmt.Sprintf(str, args...))
	}

	ehdrFlags = initEhdrFlags

	base := f.Offset()

	var hdrbuf [64]byte
	if _, err := io.ReadFull(f, hdrbuf[:]); err != nil {
		return errorf("malformed elf file: %v", err)
	}

	var e binary.ByteOrder
	switch elf.Data(hdrbuf[elf.EI_DATA]) {
	case elf.ELFDATA2LSB:
		e = binary.LittleEndian

	case elf.ELFDATA2MSB:
		e = binary.BigEndian

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Read the `<detail>` after the colon — it names the specific sub-failure to address.
  2. Verify the file is a valid ELF for the target arch: `readelf -h <obj>` (class, machine, endianness must match `GOARCH`).
  3. `go clean -cache && go build -a` to rebuild all objects for the current target.
  4. Ensure the cgo C compiler (`CC`) targets the same arch/OS as `GOOS`/`GOARCH`.

Example fix

# before: cgo CC targets x86_64 while GOARCH=arm64
CC=x86_64-linux-gnu-gcc GOARCH=arm64 go build ./...

# after: match the cross-compiler to GOARCH
CC=aarch64-linux-gnu-gcc GOARCH=arm64 go build ./...
Defensive patterns

Strategy: validation

Validate before calling

# Validate every object is an ELF matching the target GOARCH before linking
TARGET_MACHINE=$(case "$(go env GOARCH)" in amd64) echo 'X86-64';; arm64) echo 'AArch64';; arm) echo 'ARM';; 386) echo 'Intel 80386';; esac)
for obj in $(find build -name '*.o' -o -name '*.a'); do
  m=$(readelf -h "$obj" 2>/dev/null | awk '/Machine:/{print $2" "$3" "$4}')
  [ -z "$m" ] || [ "$m" = "$TARGET_MACHINE" ] || echo "wrong arch ($m) in $obj"
done

Try / catch

# On ELF load failure, fall back to a full clean rebuild
set +e
go build ./...
rc=$?
set -e
if [ $rc -ne 0 ]; then
  echo 'loadelf failed; clean rebuild' >&2
  go clean -cache && go build -a ./...
fi

Prevention

When it happens

Trigger: Passing a non-ELF file (a Mach-O, a PE, or arbitrary bytes) as an ELF object; an ELF for a different architecture than the build target; a corrupt/truncated ELF; an ELF with unsupported relocation types or section flags; cgo pulling in an object compiled for the wrong platform.

Common situations: Cross-compiling with the wrong `GOARCH`/cgo toolchain; a build cache containing an object compiled for a different OS/arch; a dependency archive built on another platform; filesystem corruption truncating an object.

Related errors


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