bazel-contrib / rules_go

Go rules for Bazel
Apache License 2.0
1.38k stars 656 forks source link

`fatal error: invalid function symbol table` when using cgo starting in go 1.21 #4091

Open dzbarsky opened 1 month ago

dzbarsky commented 1 month ago

What version of rules_go are you using?

0.50.1

What version of gazelle are you using?

0.38

What version of Bazel are you using?

7.2.1

Does this issue reproduce with the latest releases of all the above?

yes

What did you do?

See https://github.com/DavidZbarsky-at/cgo-repro for repro

This was not an issue with go 1.20.1 but is an issue starting in 1.21 See https://github.com/google/skia/blob/main/.bazelrc#L41-L45 for another example in the wild

What did you expect to see?

No-op binary runs correctly

What did you see instead?

runtime: pcHeader: magic= 0xfffffff1 pad1= 0 pad2= 0 minLC= 4 ptrSize= 8 pcHeader.textStart= 0xab280 text= 0xaaaacbbab280 pluginpath= 
fatal error: invalid function symbol table
runtime: panic before malloc heap initialized

runtime stack:
runtime.throw({0xaaaacbb2439a?, 0x0?})
    GOROOT/src/runtime/panic.go:1023 +0x40 fp=0xffffc70b8870 sp=0xffffc70b8840 pc=0xaaaacbbde990
runtime.moduledataverify1(0xaaaacbcaaac0?)
    GOROOT/src/runtime/symtab.go:532 +0x654 fp=0xffffc70b89a0 sp=0xffffc70b8870 pc=0xaaaacbbfcc84
runtime.moduledataverify(...)
    GOROOT/src/runtime/symtab.go:518
runtime.schedinit()
    GOROOT/src/runtime/proc.go:783 +0x68 fp=0xffffc70b8a20 sp=0xffffc70b89a0 pc=0xaaaacbbe2538
runtime.rt0_go()
    src/runtime/asm_arm64.s:86 +0xa4 fp=0xffffc70b8a50 sp=0xffffc70b8a20 pc=0xaaaacbc0ddd4
darkrift commented 1 month ago

To add to the issue, I've also had to workaround this using toolchains_musl and a combination of the pure setting.

DavidZbarsky-at commented 1 month ago

I thought this might be fixed by https://github.com/bazelbuild/rules_go/issues/3691 but no luck. I did notice that passing --linkopt=-no-pie fixes things. @siddharthab @fmeum in case you have thoughts.

siddharthab commented 1 month ago

Thanks for the repro. This is actually a combination of two things happening.

  1. Go versions before 1.21 did not work properly with external linkers (see #3692 or this comment). So your sysroot was not being used anyway.
  2. Looks like when providing a sysroot to the link command in the Go toolchain, the path is being prefixed with __GO_BAZEL_CC_PLACEHOLDER__, which makes the sysroot non-existent and the check for whether the linker supports -nopie fails, thereby keeping the default pie behavior in clang frontend (reason for #3691). The unwanted prefix is coming from a bug in rules_go, which is setting this placeholder when building the Go stdlib. When you build your own binary, the Go toolchain picks up CGo directives from other objects being linked in, in this case, the stdlib objects like net.a and cgo.a.
siddharthab commented 1 month ago

If the placeholder mechanism needs to stay, then I think the only solution is for the linker to also have a wrapper like cc.go.

I am not current in the codebase and I won't have the time to implement a proper solution here, so would appreciate if someone else takes over.

siddharthab commented 1 month ago

Also filed https://github.com/golang/go/issues/69350 to eventually fix the issue upstream.

fmeum commented 1 month ago

Cc @AlessandroPatti for the wrapper