From 2474d545070f841a4db91687f263c633d61619a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jiri=20Dan=C4=9Bk?= Date: Sat, 9 May 2026 12:40:33 +0200 Subject: [PATCH] fix: check .gopclntab before .data.rel.ro for PIE binaries Go 1.26 changed the ELF layout for PIE builds: .gopclntab is now emitted as a separate section instead of being embedded in .data.rel.ro (the Go <= 1.25 behavior). ReadTable unconditionally redirected to .data.rel.ro when it saw -buildmode=pie, causing "could not find magic number" failures on any Go 1.26-built PIE binary. Fix: always check .gopclntab first, fall back to .data.rel.ro only if absent. This is backward-compatible since Go <= 1.25 PIE binaries don't have .gopclntab. Fixes #329 Co-authored-by: Cursor --- internal/golang/goscan.go | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/internal/golang/goscan.go b/internal/golang/goscan.go index eeaad5a8..08814d83 100644 --- a/internal/golang/goscan.go +++ b/internal/golang/goscan.go @@ -52,33 +52,20 @@ func _magicNumber(goVersion string) uint32 { // Open a Go ELF executable and read .gopclntab func ReadTable(fileName string, bi *buildinfo.BuildInfo) (*gosym.Table, error) { - // Default section label is .gopclntab - sectionLabel := ".gopclntab" - - // If built with PIE and stripped, gopclntab is - // unlabeled and nested under .data.rel.ro. - for _, bs := range bi.Settings { - if bs.Key == "-buildmode" { - if bs.Value == "pie" { - sectionLabel = ".data.rel.ro" - } - break - } - } - exe, err := elf.Open(fileName) if err != nil { return nil, err } defer exe.Close() - section := exe.Section(sectionLabel) + // Go 1.26+ restores .gopclntab as a separate section even for PIE builds. + // Go <= 1.25 PIE binaries embed pclntab inside .data.rel.ro instead. + // Always check .gopclntab first, then fall back to .data.rel.ro. + section := exe.Section(".gopclntab") if section == nil { - // binary may be built with -pie - sectionLabel = ".data.rel.ro" - section = exe.Section(sectionLabel) + section = exe.Section(".data.rel.ro") if section == nil { - return nil, fmt.Errorf("could not read section .gopclntab from %s ", fileName) + return nil, fmt.Errorf("could not find .gopclntab or .data.rel.ro section in %s", fileName) } } tableData, err := section.Data()