pkujhd / goloader

load and run golang code at runtime.
Apache License 2.0
497 stars 58 forks source link

golang 1.21 support #82

Closed pkujhd closed 1 year ago

pkujhd commented 1 year ago

golang 1.21 already rc2, need adapter it

eh-steve commented 1 year ago

Your init implementation in master needs a depth first recursion or other graph traversal to init all dependencies in the right order and should also skip dependent tasks which have no functions. The current implementation doesn’t guarantee the correct ordering and can throw due to the lack of these checks.

Also you need to escape the package path using objabi.PathToPrefix otherwise packages like gopkg.in/yaml.v2 won’t get init’ed.

eh-steve commented 1 year ago

You also need to handle (reloctype.R_CALL | reloctype.R_WEAK) and (reloctype.R_CALLARM64 | reloctype.R_WEAK) relocations properly

pkujhd commented 1 year ago

Your init implementation in master needs a depth first recursion or other graph traversal to init all dependencies in the right order and should also skip dependent tasks which have no functions. The current implementation doesn’t guarantee the correct ordering and can throw due to the lack of these checks.

I think golang's linker just wants to reorder the initialization of all libraries according to their dependencies. Because I initialize each library separately, there is no need to graph traversal operations, only let all dependent initialization of current library to init.

pkujhd commented 1 year ago

You also need to handle (reloctype.R_CALL | reloctype.R_WEAK) and (reloctype.R_CALLARM64 | reloctype.R_WEAK) relocations properly

ok, thanks for your informations.
I find add R_WARK source code

eh-steve commented 1 year ago

Because I initialize each library separately, there is no need to graph traversal operations, only let all dependent initialization of current library to init.

That's not true (and your implementation demonstrably fails in my tests).

R_INITORDER relocs are only an ordering edge and don't represent every dependency recursively, so if you have a JIT package A which depends on B which depends on C, you will only init B then A (instead of C then B then A) which might cause B to panic if it uses something from C which wasn't initialised (it doesn't matter if you later init C).

Also what I said about nfncs of dependencies being 0 making the runtime throw still hold.

For a reproducible example, check out my 1.21 WIP branch https://github.com/eh-steve/goloader/pull/19 and try changing the init implementation and running the TestK8s test.

You can also look at cmd/link/internal/ld/inittask.go