Closed fumeboy closed 1 year ago
@fumeboy , 基本只能测试,如果有问题就适配新版本。 这方面基本没有资料,只能读golang自己的linker的代码来处理
@pkujhd 你好, 我五一认真看了一下 go 链接器源码(的一部分), 发觉 goloader 可能有一个场景不太好处理, 就是动态链接的 object file 不能 import 第三方包对吗
@pkujhd 你好, 我五一认真看了一下 go 链接器源码(的一部分), 发觉 goloader 可能有一个场景不太好处理, 就是动态链接的 object file 不能 import 第三方包对吗
可以,如果你的loader里边没有使用这个包,那么你在加载的时候也要加载这个包才能使用
FYI, this fork https://github.com/eh-steve/goloader#example-usage attempts to address this automatically by building and loading any missing dependencies recursively
在阅读您的 goloader 源代码前, 我只知道卸载需要从 moduledata 链中移除, 没想到还需要 removeitabs 我们怎么才能知道卸载一个 object file 需要处理哪些 runtime 的 global variable?
这个基本都是按照add的过程的逆向操作,大部分都是测试后发现有问题然后读源代码补充的. 另外如果你想解决依赖性问题,可以使用eh-steve的分支,他的分支会自动解决依赖性.
你好, 在 Go 链接器源代码 link/internal/ld 中, 重定位类型 objabi.R_CALL 和 objabi.R_PCREL 是统一处理的, 但是在 goloader 中relocatePCREL 函数实现比起 relocateCALL 更复杂, 请问为什么 relocatePCREL 要关心用了哪些汇编指令呢
In the standard linker, relocations are guaranteed to be within a 32 bit distance and so it's quite straightforward to write PCREL/CALL offsets as a 4 byte uint32. In Goloader, the mmapped code might be further than 32-bits (though not in my fork), and might have relocations which point at firstmodule symbols, (and strings are always stored in the heap which is definitely further than 32 bits away).
To get around this, goloader rewrites certain instructions which assume a 32-bit immediate value, replacing them with a jump to equivalent instructions but allowing for 64 bit offsets.
@eh-steve Thank you, and maybe use GOT and PLT will be more safe to handle 64bit address?
@eh-steve Thank you, and maybe use GOT and PLT will be more safe to handle 64bit address?
That would require JIT packages to be compiled with the still experimental gcflag -dynlink
(which may be fine if we control the compilation), but I'm not sure that a statically linked host binary even includes a GOT/PLT... Currently goloader can load JIT code in fully static binaries.
I might look into the feasibility of this approach at some point though.
@eh-steve @pkujhd I may have found the right approach to solve this problem by go tool compile -dynlink
if without -dynlink
, the compiler write asm as:
_make_object_file.go:15 0x1f07 488b1d00000000 MOVQ 0(IP), BX [3:7]R_PCREL:<unlinkable>.a
_make_object_file.go:15 0x1f0e 488b1500000000 MOVQ 0(IP), DX [3:7]R_PCREL:<unlinkable>.a+8
if with -dynlink
, the compiler write asm as:
_make_object_file.go:15 0x1a98 4c8b3d00000000 MOVQ 0(IP), R15 [3:7]R_GOTPCREL:<unlinkable>.a
_make_object_file.go:15 0x1a9f 498b1f MOVQ 0(R15), BX
_make_object_file.go:15 0x1aa2 4c8b3d00000000 MOVQ 0(IP), R15 [3:7]R_GOTPCREL:<unlinkable>.a
_make_object_file.go:15 0x1aa9 498b5708 MOVQ 0x8(R15), DX
In addition, it seems that PLT is implemented through "trampoline" in the source code.
In addition, it seems that PLT is implemented through "trampoline" in the source code.
哦, 原来 x86amd64JMPLcode 就是 PLT 的实现
目前我知道 goloader 是借用了 go plugin 的接口, 通过构造 moduledata 并注册到链表来动态接入 Go Runtime
但是这块的资料网上非常少, 怎么判断每次 Go 更新后, 这个项目要不要更新, 以及更新哪些补丁呢