Comments (19)
@devanwang 因为你编译的t.go不是一个main包,所以go build -x -n -v t.go 2>&1 | sed -n "/^# import config/,/EOF$/p" |grep -v EOF > importcfg 这个得到的信息是错的.
from goloader.
正确的信息是类似这样的
# import config
packagefile fmt=/Users/pkujhd/programs/go/pkg/darwin_amd64/fmt.a
packagefile github.com/pkujhd/goloader/examples/p=/Users/pkujhd/Library/Caches/go-build/90/903b1feecaa67440b2c6c3b2edee39fffec4ad91db2874c894b6213cc3975991-d
packagefile runtime=/Users/pkujhd/programs/go/pkg/darwin_amd64/runtime.a
from goloader.
@pkujhd 大佬,我把t.go的package改了main,cat importcfg结果如下:
# import config
packagefile fmt=/usr/local/go/pkg/linux_amd64/fmt.a
packagefile github.com/pkujhd/goloader/examples/p=/root/.cache/go-build/7c/7ca25758e4aed09361504e8dfac5576615f44fefc3d1960788eab0500ed48243-d
packagefile runtime=/usr/local/go/pkg/linux_amd64/runtime.a
然后重新编译t.o,执行loader还是同样的报错
from goloader.
给下你的运行环境和golang的版本
from goloader.
Linux version 5.4.119-1-tlinux4-0005 (root@VM_197_173_centos) (gcc version 8.3.1 20191121 (Red Hat 8.3.1-5)
go version go1.18.3 linux/amd64
from goloader.
如果在t.go里调用reflect
package main
import (
"fmt"
"reflect"
"github.com/pkujhd/goloader/examples/p"
)
func Test(param p.Intf) p.Intf {
fmt.Println(reflect.TypeOf(param))
return param
}
会报错 Load error: unresolve external:reflect.(*rtype).FieldByIndex
from goloader.
如果在t.go里调用reflect
package main import ( "fmt" "reflect" "github.com/pkujhd/goloader/examples/p" ) func Test(param p.Intf) p.Intf { fmt.Println(reflect.TypeOf(param)) return param }
会报错 Load error: unresolve external:reflect.(*rtype).FieldByIndex
你的case可以在loader中注册掉这个interface暂时避免
var x p.Intf = &p.Stru{}
goloader.RegTypes(symPtr, x, x.Print)
from goloader.
var x p.Intf = &p.Stru{}
goloader.RegTypes(symPtr, x, x.Print)
加了这个不会报linker bug了,unresolve external:reflect.xxx还是会有
from goloader.
reflect
var x p.Intf = &p.Stru{} goloader.RegTypes(symPtr, x, x.Print)
加了这个不会报linker bug了,unresolve external:reflect.xxx还是会有
这个reflect的函数loader里没有使用,你需要注册
from goloader.
在t.go里只加了一行reflect.TypeOf(param),每次都报不同的错,没法加啊
Load error: unresolve external:reflect.(*rtype).Implements
Load error: unresolve external:reflect.(*rtype).FieldByNameFunc
Load error: unresolve external:reflect.(*rtype).ConvertibleTo
Load error: unresolve external:reflect.(*rtype).FieldAlign
Load error: unresolve external:reflect.(*rtype).MethodByName
Load error: unresolve external:reflect.(*rtype).FieldByIndex
我看原理会解析loader bin的symbols, 我在loader里同样加了reflect.TypeOf(param)代码,还是不行
from goloader.
Refelect 包会用到一系列的函数,都要注册,或者就在你的加载器里有类似的代码,会移动处理加载器里的符号
from goloader.
不是很懂,大佬能不能给个具体例子,针对t.go里的reflect.TypeOf函数,我要在loader写什么?
from goloader.
fmt.Println(reflect.TypeOf(param))
就是你在loader里也调用过相应的函数,就会自动注册
就是在loader里加一行
fmt.Println(reflect.TypeOf(param))
from goloader.
这个不行,在loader里加了同样的reflect.TypeOf(param)还是会报如下错误:
Load error: unresolve external:reflect.(*rtype).Implements
Load error: unresolve external:reflect.(*rtype).FieldByNameFunc
Load error: unresolve external:reflect.(*rtype).ConvertibleTo
Load error: unresolve external:reflect.(*rtype).FieldAlign
Load error: unresolve external:reflect.(*rtype).MethodByName
Load error: unresolve external:reflect.(*rtype).FieldByIndex
大佬你那边可以试下
from goloader.
@pkujhd 查nm找到原因了,loader里的reflect.TypeOf被内联优化了,t.o的没有被内联,加上-gcflags -l就可以了,但这样编译器就禁止内联了,不知道有啥好办法没有
from goloader.
@pkujhd 查nm找到原因了,loader里的reflect.TypeOf被内联优化了,t.o的没有被内联,加上-gcflags -l就可以了,但这样编译器就禁止内联了,不知道有啥好办法没有
这个没啥办法,内联了要么你loader的时候重新提供一份,要么loader就是禁止inline的
from goloader.
@devanwang ,这个问题查了下,是因为loader中产生的type,由于连接优化,剔除了Intf.Print, 因此上在加载一个扩展的时候,两边的类型虽然名字相同但是实际类型却不一样,无法正确运行,如果你需要在runtime和dynamic library之间传递interface,那么需要使得两边的类型一致(即需要手动注册相应的函数,保证runtime里边产生的type是一样的).
故此问题只能和inline一样. 编写时规避
from goloader.
记录下这个case的调试信息:
relocateType symbolName relocateSymbolName address
5 main.Test.stkobj runtime.gcbits.02 1094664412
1 main..stmp_0 go.string."done!" 1107140612
24 main.Test type.github.com/pkujhd/goloader/examples/p.Intf 7043456
23 main.Test type.string 6948512
23 main.Test type.*os.File 7288448
14 main.Test go.string."Intf" 1107140608
10 main.Test 1094664360
14 main.Test type.string 6948512
14 main.Test main..stmp_0 1094664448
14 main.Test os.Stdout 9954648
14 main.Test go.itab.*os.File,io.Writer 7911456
7 main.Test fmt.Fprintln 4919424
7 main.Test runtime.morestack_noctxt 4594432
1 go.itab.*os.File,io.Writer type.io.Writer 7044224
1 go.itab.*os.File,io.Writer type.*os.File 7288448
32769 go.itab.*os.File,io.Writer os.(*File).Write 4893696
以上是这个case所有需要relocate的列表, main.Test需要重定向type.github.com/pkujhd/goloader/examples/p.Intf,这个type已经在load中存在,但是对应的stuc.Print不存在,就会导致运行错误
记录信息:
可以采用-dynlink作为编译参数,这个参数是golang为plugin的模式添加的编译参数,会产生一个go.plugin.tabs的symbol来储存需要导出的函数,plugin模式用它来初始化moduledata的ptabEntry, 然后plugin模块读取这个array来产生导出的符号列表,
这是一个interface{]的array,所以当把interface转成func()时,会导入相应的符号,就不会产生上述才问题.
但是这个问题在goversion>=1.12的schedule这个case的时候会导致找不到符号runtime.gosched_m·f, 这个符号在runtime.a里,但是生成的loader里边没有,生成的.o里也没有,暂时无法处理;而不包含-dynlink的编译成的.o,runtime.gosched_m·f,这个符号就在当前的.o里.
now blocking...
from goloader.
I think this is an artefact of the main loader
's go compiler/linker setting some of the method offsets in the uncommon type of the *p.Stru
to -1
as part of its reachability analysis (since no code in loader.go
explicitly calls (*p.Stru).Print()
). These "unreachable" method offsets are then baked into the firstmodule's itabs (go.itab.*github.com/pkujhd/goloader/examples/p.Stru,github.com/pkujhd/goloader/examples/p.Intf
) during the first itab init and the method text pointers are set to point at the address of runtime.unreachableMethod
, and when the method is later called from a dynamic module, it is indeed unreachable (from the first module's perspective).
PR #66 adds a functionality to patch the first module's itabs to point at newly included method offsets if they're now available in a dynamic module, which prevents these fatal error: unreachable method called. linker bug?
errors.
I've made a separate branch here with this commit eh-steve@78fc98a demonstrating the solution.
If you check out that branch and run either:
cd ./examples/jit
go build .
./jit
or (using old loader)
cd ./examples/issue55/t/
go build -o t.o .
cd ../p/
go build -o p.o .
cd ../../loader
go build .
./loader -o ../issue55/t/t.o -o ../issue55/p/p.o -run "github.com/pkujhd/goloader/examples/issue55/t.Test"
It should be working (without the main binary having registered any extra types!)
from goloader.
Related Issues (20)
- Load error: unresolve external:runtime.writeBarrier HOT 7
- 你好, 请问这个项目是怎么保持跟随 Go 最新版本的呢 HOT 13
- 实现 MarshalJSON 接口方法, 不会被执行 HOT 16
- Will panic soon when visit pprof web page HOT 7
- the handle of inline is incorrect HOT 11
- the usage of `copy2Slice` here seems to be incorrect, PutInt64 should be used instead HOT 30
- the `addfuncdata` rewrite `0` to `^uint32(0)`, but ignoring the case where 0 represents a normal offset value. HOT 5
- during module unloading, removing the itab can lead to runtime error HOT 1
- `getitab` alloc memory for `itab` by `persistentalloc`, and that couldnt be free HOT 6
- golang 1.21 support HOT 5
- 似乎不支援泛型 HOT 12
- `typelinksRegister` may bind wrong address when some types have same name at packages which also have same name HOT 3
- unexpected return pc 0x0 HOT 4
- Failed to execute plugin which contains dependency `unresolve external:<...>` HOT 2
- build constraints exclude all Go files in ... HOT 2
- there may be an omission of pcdata handling HOT 2
- go linker dont use ptrsize to align TEXT symbol
- may be a bug: the program handles the`findfunctab` does not consider the case where the function address spans 4kb HOT 2
- support golang 1.22 HOT 1
- Discussion on go plugin ecosystem HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from goloader.