eh-steve / goloader

Compile, load and run Go code at runtime.
Apache License 2.0
45 stars 4 forks source link

CGo panic: linker failed to read symbols from dependency object files #21

Open nnnnt21 opened 1 year ago

nnnnt21 commented 1 year ago

Getting this error after using the mattn/go-sqlite3 library

Works fine not in goloader so I'm thinking it must be an issue here, could you explain the reason? I tried researching the error but didn't come up with too much, is this library just incompatible?

Heres the full dump, panic: linker failed to read symbols from dependency object files ([vendor/golang.org/x/net/dns/dnsmessage text/tabwriter sync runtime/internal/atomic runtime reflect os net/netip math/rand log io internal/singleflight internal/poll image golang.org/x/text/language github.com/yuin/gopher-lua github.com/sirupsen/logrus github.com/sandertv/gophertunnel/minecraft/protocol/packet github.com/sandertv/gophertunnel/minecraft/protocol/login github.com/sandertv/gophertunnel/minecraft/protocol github.com/sandertv/gophertunnel/minecraft github.com/mattn/go-sqlite3 github.com/google/uuid github.com/df-mc/dragonfly/server/world/sound github.com/df-mc/dragonfly/server/world/particle github.com/df-mc/dragonfly/server/world/mcdb github.com/df-mc/dragonfly/server/world/chunk github.com/df-mc/dragonfly/server/player/title github.com/df-mc/dragonfly/server/player/scoreboard github.com/df-mc/dragonfly/server/player/form github.com/df-mc/dragonfly/server/player/bossbar github.com/df-mc/dragonfly/server/item/recipe github.com/df-mc/dragonfly/server/item/potion github.com/df-mc/dragonfly/server/item/category github.com/df-mc/dragonfly/server/entity/effect github.com/df-mc/dragonfly/server/entity github.com/df-mc/dragonfly/server/block github.com/df-mc/dragonfly/server github.com/brentp/intintmap database/sql time sync/atomic net github.com/nnnnt21/drag/server github.com/nnnnt21/drag/resources/plugins/ranks github.com/go-gl/mathgl/mgl64 github.com/df-mc/dragonfly/server/world github.com/df-mc/dragonfly/server/session github.com/df-mc/dragonfly/server/player/skin github.com/df-mc/dragonfly/server/player github.com/df-mc/dragonfly/server/item/inventory github.com/df-mc/dragonfly/server/item github.com/df-mc/dragonfly/server/event github.com/df-mc/dragonfly/server/cmd github.com/df-mc/dragonfly/server/block/cube github.com/df-mc/atomic command-line-arguments]): read error: only a limited subset of elf relocations currently supported, got elf.R_X86_64_GOTPCREL for symbol sqlite3_overload_function reloc to sqlite3_free

eh-steve commented 1 year ago

The issue you're seeing is due to a type of CGo (native) ELF relocation which I haven't added support for yet.

I could potentially add support for it, but unfortunately that SQLite package is a massive CGo user and links against libsqlite3 (a C library). Go normally uses the external system linker (gcc/ld) to resolve and load C libraries when building binaries which use CGo.

I haven't yet added support for loading C library symbols from C archives or .so files in the same way that the native system linker does - my CGo support so far only includes C files compiled directly next to the Go files.

I did have an idea a while ago about parsing the LDFLAGS and using libdl to dynamically load C library symbols to link against when loading a CGo package, but again I haven't implemented it yet, and have no idea if it will work, and whether dlclosing on unload would be safe.

For now, unfortunately I'd say attempting to JIT load CGo packages which use external C libraries (via LDFLAGS) won't work, but I'd keep this issue open as a nudge for me to implement the 2 things I suggested above if I get a chance.

Sorry I couldn't be of more help

nnnnt21 commented 1 year ago

Ah that makes sense, thanks for explaining it. Unfortunate limitation but I'll figure something out.

Thanks again, it is a great project.

eh-steve commented 11 months ago

So I think I was a bit hasty in my conclusions in my last message. After a more detailed look at the github.com/mattn/go-sqlite3, I see that it actually doesn't use system linker (ld) flags to link against libsqlite3 by default (it only does this if you set a libsqlite3 build tag). Instead it includes the whole C source file in the repo, and so it happily gets compiled and read in as a native ELF file by goloader.

Once I added in support for the missing relocation type, it loaded, but to my surprise I found that gcc generates position-dependent code despite requesting position-independent code using the default CGo flags of -fPIC -O2 -g.

Specifically, it generated a JMP instruction with a hardcoded offset to another (static) function (rather than emitting a relocation).+inner_mul(int+val)%7B%0A++++++++return+val+*+val%3B%0A%7D%0A%0Aint+add(int+val)%7B%0A++++++++return+val+%2B+val%3B%0A%7D%0A%0Aint+outer_mul(int+val)%7B%0A++return+inner_mul(val)%3B%0A%7D%0A'),l:'5',n:'0',o:'C+source+%231',t:'0')),k:36.979139929411204,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((h:compiler,i:(compiler:cg74,deviceViewOpen:'1',filters:(b:'0',binary:'1',binaryObject:'0',commentOnly:'0',debugCalls:'1',demangle:'0',directives:'0',execute:'1',intel:'0',libraryCode:'0',trim:'1'),flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:1,lang:___c,libs:!(),options:'-fPIC+-O2',overrides:!(),selection:(endColumn:22,endLineNumber:12,positionColumn:22,positionLineNumber:12,selectionStartColumn:22,selectionStartLineNumber:12,startColumn:22,startLineNumber:12),source:1),l:'5',n:'0',o:'+x86-64+gcc+7.4+(Editor+%231)',t:'0')),k:30.167193100309138,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((h:tool,i:(args:'-r',argsPanelShown:'0',compilerName:'x86-64+gcc+7.4',editorid:1,fontScale:14,fontUsePx:'0',j:1,monacoEditorHasBeenAutoOpened:'1',monacoEditorOpen:'1',monacoStdin:'1',stdin:'',stdinPanelShown:'1',toolId:readelf,treeid:0,wrap:'1'),l:'5',n:'0',o:'readelf+x86-64+gcc+7.4+(Editor+%231,+Compiler+%231)',t:'0')),k:32.85366697027966,l:'4',n:'0',o:'',s:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4)

gcc apparently expects certain symbols to be laid out exactly as emitted by the compiler in order to preserve hardcoded jumps like that one, and so my current implementation of reading in each native symbol one at a time and only laying their data out if they're reachable (+adding a possible epilogue if needed) breaks this assumption (and therefore breaks these hardcoded JMPs).

To fix this, I'll probably need to change how native symbols are loaded so they're guaranteed to be contiguous per-translation unit, with any epilogues added to the end of each translation unit instead of the end of each function.

The slightly more surprising thing is that I think this prevents unreachable symbols emitted between a hardcoded jump and its target being link-time eliminated - I'd be curious to see what gcc does in these cases

DanijelRadakovic commented 11 months ago

I have similar error when trying to use go-etherum: failed to load linker: relocation epilogue not available but got a >32-bit PCREL reloc (x86 code: ffffe800000000) with offset 140410028731652: __stack_chk_fail

The code that I am trying to make it work:

package main

import (
    "fmt"
    "github.com/eh-steve/goloader/jit"
    "math/big"
)

func main() {
    conf := jit.BuildConfig{
        KeepTempFiles:   false,          // Files are copied/written to a temp dir to ensure it is writable. This retains the temporary copies
        ExtraBuildFlags: []string{"-x"}, // Flags passed to go build command
        BuildEnv:        nil,            // Env vars to set for go build toolchain
        TmpDir:          "",             // To control where temporary files are copied
        DebugLog:        true,           //
    }

    loadable, err := jit.BuildGoPackageRemote(conf, "github.com/DanijelRadakovic/ethereum-plugin", "9eef6ae")
    if err != nil {
        panic(err)
    }

    module, err := loadable.Load()
    if err != nil {
        panic(err)
    }
    // module.SymbolsByPkg is a map[string]map[string]interface{} of all packages and their exported functions and global vars
    symbols := module.SymbolsByPkg[loadable.ImportPath]
    if err != nil {
        panic(err)
    }
    defer func() {
        err = module.Unload()
        if err != nil {
            panic(err)
        }
    }()

    switch f := symbols["FetchData"].(type) {
    case func() (*big.Int, error):
        //result, errCall := f([]byte(`{"k":"v"}`))
        result, errCall := f()
        if errCall != nil {
            panic(errCall)
        }
        fmt.Println(result)
    default:
        panic("Function signature was not what was expected")
    }
}
eh-steve commented 11 months ago

Hi @DanijelRadakovic,

Would you mind trying against the branch eh-steve/issue-87?

I've added a fallthrough for this case https://github.com/eh-steve/goloader/blob/b041c770d1eeaa61686d0483d8076243dca3c3b3/ld.go#L335

Edit:

Once you do that, I think it's a similar situation to the issue I described above, where gcc emits a hardcoded JMP to/from a static function without emitting a relocation on the assumption that a single translation unit (file) doesn't need to be PIC.

Once I get around to implementing the fix I described above (load native CGo symbols contiguously),🤞🏻 it should fix both problems.

DanijelRadakovic commented 11 months ago

I've done the following:

go get github.com/eh-steve/goloader@issue-87

But now I am getting the following error:

fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x80 addr=0x0 pc=0xc11349]

runtime stack:
runtime.throw({0x613f82?, 0x0?})
        /usr/local/go1.20.2/src/runtime/panic.go:1047 +0x5d fp=0x7fff10cbeb60 sp=0x7fff10cbeb30 pc=0x4363fd
runtime.sigpanic()
        /usr/local/go1.20.2/src/runtime/signal_unix.go:821 +0x3e9 fp=0x7fff10cbebc0 sp=0x7fff10cbeb60 pc=0x44c489
math/big.nat.setBytes({0x8b48008418246c8d?, 0x0?, 0xe17f8d?}, {0xa96830?, 0x0?, 0x0?})
        /usr/local/go1.20.2/src/math/big/nat.go:1349 +0xc9 fp=0x7fff10cbebf8 sp=0x7fff10cbebc0 pc=0xc11349
runtime: g 0: unexpected return pc for github.com/ethereum/go-ethereum/crypto/secp256k1.(*BitCurve).Unmarshal called from 0x0
stack: frame={sp:0x7fff10cbebf8, fp:0x7fff10cbec58} stack=[0x7fff104bfde0,0x7fff10cbedf0)
0x00007fff10cbeaf8:  0x00000000007b5dc0  0x0000000000436780 <runtime.fatalthrow.func1+0x0000000000000000> 
0x00007fff10cbeb08:  0x00000000007b5dc0  0x00000000004363fd <runtime.throw+0x000000000000005d> 
0x00007fff10cbeb18:  0x00007fff10cbeb30  0x00007fff10cbeb50 
0x00007fff10cbeb28:  0x00000000004363fd <runtime.throw+0x000000000000005d>  0x00007fff10cbeb38 
0x00007fff10cbeb38:  0x0000000000436420 <runtime.throw.func1+0x0000000000000000>  0x0000000000613f82 
0x00007fff10cbeb48:  0x000000000000002a  0x00007fff10cbebb0 
0x00007fff10cbeb58:  0x000000000044c489 <runtime.sigpanic+0x00000000000003e9>  0x0000000000613f82 
0x00007fff10cbeb68:  0x0000000000000000  0x0000000000000000 
0x00007fff10cbeb78:  0x000000770000007c  0x0000005b0000006e 
0x00007fff10cbeb88:  0x00000000004461e6 <runtime.doInit+0x0000000000000126>  0x00000000007b5dc0 
0x00007fff10cbeb98:  0xffffffffffffffb0  0x00000000000000d8 
0x00007fff10cbeba8:  0x00007f15d7c19c80  0x00007fff10cbebe8 
0x00007fff10cbebb8:  0x0000000000c11349 <math/big.nat.setBytes+0x00000000000000c9>  0x1000000000000000 
0x00007fff10cbebc8:  0x00007f15d7aa51b9  0x0000000000000000 
0x00007fff10cbebd8:  0x0000000000e17f7a <github.com/go-stack/stack.init.0+0x000000000000003a>  0x0000000000000301 
0x00007fff10cbebe8:  0x0000000000000100  0x0000000000e1e3fa <github.com/ethereum/go-ethereum/crypto/secp256k1.(*BitCurve).Unmarshal+0x0000000000000172> 
0x00007fff10cbebf8: <0x8b48008418246c8d  0x0000000000000000 
0x00007fff10cbec08:  0x0000000000e17f8d <github.com/go-stack/stack.init.0+0x000000000000004d>  0x0000000000a96830 
0x00007fff10cbec18:  0x0000000000000000  0x0000000000000000 
0x00007fff10cbec28:  0x0000000000e17f8c <github.com/go-stack/stack.init.0+0x000000000000004c>  0x00000000000e8f72 
0x00007fff10cbec38:  0x0000000000000000  0x0000000000000000 
0x00007fff10cbec48:  0x0000000000000000 !0x0000000000000000 
0x00007fff10cbec58: >0x00007fff10cbec38  0x000000000062dc6c 
0x00007fff10cbec68:  0x000000000042eb2d <runtime.(*pallocBits).find+0x000000000000002d>  0x00000000007cdd68 
0x00007fff10cbec78:  0x000000000079d700  0x0000000000739a20 
0x00007fff10cbec88:  0x00007fff10cbecc8  0x00007fff10cbecc8 
0x00007fff10cbec98:  0x000000000079d700  0x000000000079d700 
0x00007fff10cbeca8:  0x0000000000705ff8  0x0000000000000000 
0x00007fff10cbecb8:  0x000000000000007a  0x0000000024f18000 
0x00007fff10cbecc8:  0x00007fff10cbed60  0x000000c0000061a0 
0x00007fff10cbecd8:  0x00000000007cdd60  0x0000000000705ff8 
0x00007fff10cbece8:  0x000000000079d700  0x0000000000000000 
0x00007fff10cbecf8:  0x0000000000739a20  0x000000000079d700 
0x00007fff10cbed08:  0xf53cdec17d9b7100  0x00000000004461e6 <runtime.doInit+0x0000000000000126> 
0x00007fff10cbed18:  0x000000c01313fa90  0x000000c01313fa58 
0x00007fff10cbed28:  0x000000c013140000  0x000000c01a434db0 
0x00007fff10cbed38:  0x000000c0000061a0  0x1000000000000000 
0x00007fff10cbed48:  0x0000000000e1eb85 <_cgo_3d295a454cce_Cfunc_secp256k1_context_create_sign_verify+0x000000000000001d>  0x000000c01313fa90 
(...)
        /usr/local/go1.20.2/src/math/big/int.go:487
github.com/ethereum/go-ethereum/crypto/secp256k1.(*BitCurve).Unmarshal(0x7fff10cbec38?, {0x62dc6c, 0x42eb2d, 0x7cdd68})
        /home/danijel/go/pkg/mod/github.com/ethereum/go-ethereum@v1.12.0/crypto/secp256k1/curve.go:276 +0x172 fp=0x7fff10cbec58 sp=0x7fff10cbebf8 pc=0xe1e3fa

goroutine 1 [syscall]:
runtime.cgocall(0xe1eb68, 0xc01313fa90)
        /usr/local/go1.20.2/src/runtime/cgocall.go:157 +0x5c fp=0xc01313fa68 sp=0xc01313fa30 pc=0x405d5c
github.com/ethereum/go-ethereum/crypto/secp256k1._Cfunc_secp256k1_context_create_sign_verify()
        _cgo_gotypes.go:157 +0x49 fp=0xc01313fa90 sp=0xc01313fa68 pc=0xe1eb09
github.com/ethereum/go-ethereum/crypto/secp256k1.init.1()
        /home/danijel/go/pkg/mod/github.com/ethereum/go-ethereum@v1.12.0/crypto/secp256k1/secp256.go:49 +0x19 fp=0xc01313faa8 sp=0xc01313fa90 pc=0xe1f499
runtime.doInit(0x91ccf8)
        /usr/local/go1.20.2/src/runtime/proc.go:6506 +0x126 fp=0xc01313fbd8 sp=0xc01313faa8 pc=0x4461e6
github.com/eh-steve/goloader.(*Linker).doInitialize(0xc0004f4240, 0xc015e2c200?, 0xc015e2c200?)
        /home/danijel/go/pkg/mod/github.com/eh-steve/goloader@v0.0.0-20230907063716-b041c770d1ee/init.1.13.go:44 +0x18c fp=0xc01313fc60 sp=0xc01313fbd8 pc=0x56ea2c
github.com/eh-steve/goloader.Load(0xc0004f4240, 0x0?)
        /home/danijel/go/pkg/mod/github.com/eh-steve/goloader@v0.0.0-20230907063716-b041c770d1ee/ld.go:1266 +0x4c5 fp=0xc01313fd40 sp=0xc01313fc60 pc=0x57cca5
github.com/eh-steve/goloader/jit.(*LoadableUnit).Load(0xc018585500)
        /home/danijel/go/pkg/mod/github.com/eh-steve/goloader/jit@v0.0.0-20230906184435-2b17d7cb91a3/load.go:19 +0x49 fp=0xc01313fd88 sp=0xc01313fd40 pc=0x596069
main.main()
        /home/danijel/projects/fax/sok/block-explorer/main.go:23 +0x13d fp=0xc01313ff80 sp=0xc01313fd88 pc=0x5a6b9d
runtime.main()
        /usr/local/go1.20.2/src/runtime/proc.go:250 +0x207 fp=0xc01313ffe0 sp=0xc01313ff80 pc=0x438ce7
runtime.goexit()
        /usr/local/go1.20.2/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc01313ffe8 sp=0xc01313ffe0 pc=0x466ac1

goroutine 2 [force gc (idle)]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
        /usr/local/go1.20.2/src/runtime/proc.go:381 +0xd6 fp=0xc00004efb0 sp=0xc00004ef90 pc=0x439116
runtime.goparkunlock(...)
        /usr/local/go1.20.2/src/runtime/proc.go:387
runtime.forcegchelper()
        /usr/local/go1.20.2/src/runtime/proc.go:305 +0xb0 fp=0xc00004efe0 sp=0xc00004efb0 pc=0x438f50
runtime.goexit()
        /usr/local/go1.20.2/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc00004efe8 sp=0xc00004efe0 pc=0x466ac1
created by runtime.init.6
        /usr/local/go1.20.2/src/runtime/proc.go:293 +0x25

goroutine 3 [GC sweep wait]:
runtime.gopark(0x1?, 0x0?, 0x0?, 0x0?, 0x0?)
        /usr/local/go1.20.2/src/runtime/proc.go:381 +0xd6 fp=0xc00004f780 sp=0xc00004f760 pc=0x439116
runtime.goparkunlock(...)
        /usr/local/go1.20.2/src/runtime/proc.go:387
runtime.bgsweep(0x0?)
        /usr/local/go1.20.2/src/runtime/mgcsweep.go:319 +0xde fp=0xc00004f7c8 sp=0xc00004f780 pc=0x425a7e
runtime.gcenable.func1()
        /usr/local/go1.20.2/src/runtime/mgc.go:178 +0x26 fp=0xc00004f7e0 sp=0xc00004f7c8 pc=0x41ad06
runtime.goexit()
        /usr/local/go1.20.2/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc00004f7e8 sp=0xc00004f7e0 pc=0x466ac1
created by runtime.gcenable
        /usr/local/go1.20.2/src/runtime/mgc.go:178 +0x6b

goroutine 4 [GC scavenge wait]:
runtime.gopark(0x1c3dcc32069?, 0x131d262?, 0x0?, 0x0?, 0x0?)
        /usr/local/go1.20.2/src/runtime/proc.go:381 +0xd6 fp=0xc00004ff70 sp=0xc00004ff50 pc=0x439116
runtime.goparkunlock(...)
        /usr/local/go1.20.2/src/runtime/proc.go:387
runtime.(*scavengerState).park(0x7b5c60)
        /usr/local/go1.20.2/src/runtime/mgcscavenge.go:400 +0x53 fp=0xc00004ffa0 sp=0xc00004ff70 pc=0x423973
runtime.bgscavenge(0x0?)
        /usr/local/go1.20.2/src/runtime/mgcscavenge.go:633 +0x65 fp=0xc00004ffc8 sp=0xc00004ffa0 pc=0x423f65
runtime.gcenable.func2()
        /usr/local/go1.20.2/src/runtime/mgc.go:179 +0x26 fp=0xc00004ffe0 sp=0xc00004ffc8 pc=0x41aca6
runtime.goexit()
        /usr/local/go1.20.2/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc00004ffe8 sp=0xc00004ffe0 pc=0x466ac1
created by runtime.gcenable
        /usr/local/go1.20.2/src/runtime/mgc.go:179 +0xaa

goroutine 5 [finalizer wait]:
runtime.gopark(0x0?, 0x619fb0?, 0x80?, 0x64?, 0x2000000020?)
        /usr/local/go1.20.2/src/runtime/proc.go:381 +0xd6 fp=0xc00004e628 sp=0xc00004e608 pc=0x439116
runtime.runfinq()
        /usr/local/go1.20.2/src/runtime/mfinal.go:193 +0x107 fp=0xc00004e7e0 sp=0xc00004e628 pc=0x419d47
runtime.goexit()
        /usr/local/go1.20.2/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc00004e7e8 sp=0xc00004e7e0 pc=0x466ac1
created by runtime.createfing
        /usr/local/go1.20.2/src/runtime/mfinal.go:163 +0x45

goroutine 6 [GC worker (idle)]:
runtime.gopark(0x1c413e4df0a?, 0xc0003399a0?, 0x1a?, 0x14?, 0x0?)
        /usr/local/go1.20.2/src/runtime/proc.go:381 +0xd6 fp=0xc000050750 sp=0xc000050730 pc=0x439116
runtime.gcBgMarkWorker()
        /usr/local/go1.20.2/src/runtime/mgc.go:1275 +0xf1 fp=0xc0000507e0 sp=0xc000050750 pc=0x41ca71
runtime.goexit()
        /usr/local/go1.20.2/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc0000507e8 sp=0xc0000507e0 pc=0x466ac1
created by runtime.gcBgMarkStartWorkers
        /usr/local/go1.20.2/src/runtime/mgc.go:1199 +0x25

goroutine 7 [GC worker (idle)]:
runtime.gopark(0x1c413e5a0c6?, 0x3?, 0x56?, 0xbf?, 0x0?)
        /usr/local/go1.20.2/src/runtime/proc.go:381 +0xd6 fp=0xc000050f50 sp=0xc000050f30 pc=0x439116
runtime.gcBgMarkWorker()
        /usr/local/go1.20.2/src/runtime/mgc.go:1275 +0xf1 fp=0xc000050fe0 sp=0xc000050f50 pc=0x41ca71
runtime.goexit()
        /usr/local/go1.20.2/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000050fe8 sp=0xc000050fe0 pc=0x466ac1
created by runtime.gcBgMarkStartWorkers
        /usr/local/go1.20.2/src/runtime/mgc.go:1199 +0x25

goroutine 8 [GC worker (idle)]:
runtime.gopark(0x1c413e4d511?, 0x1?, 0xee?, 0xe5?, 0x0?)
        /usr/local/go1.20.2/src/runtime/proc.go:381 +0xd6 fp=0xc000051750 sp=0xc000051730 pc=0x439116
runtime.gcBgMarkWorker()
        /usr/local/go1.20.2/src/runtime/mgc.go:1275 +0xf1 fp=0xc0000517e0 sp=0xc000051750 pc=0x41ca71
runtime.goexit()
        /usr/local/go1.20.2/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc0000517e8 sp=0xc0000517e0 pc=0x466ac1
created by runtime.gcBgMarkStartWorkers
        /usr/local/go1.20.2/src/runtime/mgc.go:1199 +0x25

goroutine 9 [GC worker (idle)]:
runtime.gopark(0x1c413e4de4f?, 0x3?, 0xad?, 0x7?, 0x0?)
        /usr/local/go1.20.2/src/runtime/proc.go:381 +0xd6 fp=0xc000051f50 sp=0xc000051f30 pc=0x439116
runtime.gcBgMarkWorker()
        /usr/local/go1.20.2/src/runtime/mgc.go:1275 +0xf1 fp=0xc000051fe0 sp=0xc000051f50 pc=0x41ca71
runtime.goexit()
        /usr/local/go1.20.2/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000051fe8 sp=0xc000051fe0 pc=0x466ac1
created by runtime.gcBgMarkStartWorkers
        /usr/local/go1.20.2/src/runtime/mgc.go:1199 +0x25

goroutine 18 [GC worker (idle)]:
runtime.gopark(0x1c413e58c61?, 0x3?, 0x4?, 0x74?, 0x0?)
        /usr/local/go1.20.2/src/runtime/proc.go:381 +0xd6 fp=0xc00004a750 sp=0xc00004a730 pc=0x439116
runtime.gcBgMarkWorker()
        /usr/local/go1.20.2/src/runtime/mgc.go:1275 +0xf1 fp=0xc00004a7e0 sp=0xc00004a750 pc=0x41ca71
runtime.goexit()
        /usr/local/go1.20.2/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc00004a7e8 sp=0xc00004a7e0 pc=0x466ac1
created by runtime.gcBgMarkStartWorkers
        /usr/local/go1.20.2/src/runtime/mgc.go:1199 +0x25

goroutine 19 [GC worker (idle)]:
runtime.gopark(0x1c413e4d585?, 0x3?, 0xb1?, 0x82?, 0x0?)
        /usr/local/go1.20.2/src/runtime/proc.go:381 +0xd6 fp=0xc00004af50 sp=0xc00004af30 pc=0x439116
runtime.gcBgMarkWorker()
        /usr/local/go1.20.2/src/runtime/mgc.go:1275 +0xf1 fp=0xc00004afe0 sp=0xc00004af50 pc=0x41ca71
runtime.goexit()
        /usr/local/go1.20.2/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc00004afe8 sp=0xc00004afe0 pc=0x466ac1
created by runtime.gcBgMarkStartWorkers
        /usr/local/go1.20.2/src/runtime/mgc.go:1199 +0x25

goroutine 10 [GC worker (idle)]:
runtime.gopark(0x1c3dc0cb8dc?, 0x1?, 0xd6?, 0xb1?, 0x0?)
        /usr/local/go1.20.2/src/runtime/proc.go:381 +0xd6 fp=0xc00037a750 sp=0xc00037a730 pc=0x439116
runtime.gcBgMarkWorker()
        /usr/local/go1.20.2/src/runtime/mgc.go:1275 +0xf1 fp=0xc00037a7e0 sp=0xc00037a750 pc=0x41ca71
runtime.goexit()
        /usr/local/go1.20.2/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc00037a7e8 sp=0xc00037a7e0 pc=0x466ac1
created by runtime.gcBgMarkStartWorkers
        /usr/local/go1.20.2/src/runtime/mgc.go:1199 +0x25

goroutine 11 [GC worker (idle)]:
runtime.gopark(0x1c413e58cac?, 0x1?, 0x6f?, 0x4e?, 0x0?)
        /usr/local/go1.20.2/src/runtime/proc.go:381 +0xd6 fp=0xc00037af50 sp=0xc00037af30 pc=0x439116
runtime.gcBgMarkWorker()
        /usr/local/go1.20.2/src/runtime/mgc.go:1275 +0xf1 fp=0xc00037afe0 sp=0xc00037af50 pc=0x41ca71
runtime.goexit()
        /usr/local/go1.20.2/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc00037afe8 sp=0xc00037afe0 pc=0x466ac1
created by runtime.gcBgMarkStartWorkers
        /usr/local/go1.20.2/src/runtime/mgc.go:1199 +0x25
eh-steve commented 11 months ago

Yeah that's what I'm saying is due to the non-PIC code emitted by gcc, and I hope to fix this by forcing native symbols to be laid out in full segments exactly as emitted by the compiler instead of what I currently do which is slice up each segment into different symbols and add them all separately (which breaks any hardcoded non-PIC JMP or CALL instructions).