-
Notifications
You must be signed in to change notification settings - Fork 60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
loader 是so调用 函数失败 #24
Comments
你想说的是你的loader是一个动态库,是用plugin加载的?然后用loader加载一个.o? |
我想测试把loader用c-shard编译成so,然后注入到其他程序中加载.o,但是这样调用失败了 |
你想编译成C的.so,然后让C程序加载.so,然后去读取一个go的.o 执行?把错误贴出来吧 |
是的,直接在.o文件函数的时候失败了,运行runFunc() 不能成功执行.o文件里的函数,loader也不往下执行了,runFunc()没有错误返回! |
|
package main import ( func MyTest() { 我把上面的代码编译成o文件,让loader编译的so加载该o文件掉用函数main.MyTest()失败了。(我修改了exe, err := os.Executable()了这个获取exe的路径,让其获取我的so路径,这样注册符号那些就成功了,但是掉用main.MyTest失败) |
你的loader是如何编译的,loader不是让C++去用dlopen调用的么?有完整的测试工程的话,发一个出来,需要复现错误 |
unexpected fault address 0x7fa25e925762 goroutine 17 [running, locked to thread]: 报了这个错误 |
main.mytest1() 是我loader的导出函数,main.MyTest2()是我o文件的函数 |
loader里加入 //export mytest1 |
这错误是某个symbol没有找到地址造成的,你应该没有检查Load的返回的错误,实际上Load没有成功 你给出的例子里边应该是没有register os.WriteFile函数造成的 另外你现在的使用上还会有其他的问题,goloader需要读取当前的可执行程序的符号表,来确定全局变量的地址,但是因为你的loader是一个.so, 所以使用os.Executable()得到的path是你执行的C程序的PATH,从而导致有些全局变量无法relocate地址 如果你有用到全局变量, 可以将RegSymbol的参数增加一个,传入loader.so的路径 |
请问是否能重现错误,如果不能重现,我抽空整理下测试代码? |
我能看到的错误,就是Loader返回了错误,os.WriteFile没有找到, 如果无视这个错误, 程序就会崩掉,但是和你提供的error不同
|
这个错误是因为path找的是elf文件的路径,我是把os.Executable() 这里强制修改了,强制修改成loader.so的绝对路径,这样load注册函数就不会返回错误了,exe="/tmp/loader.so",这样就没有这个错误了。您可以试一下 |
@tooBugs 但是你给我的testcase里,我测不出这种情况,因为编译出来的那个.o刚好不用啥全局变量 |
是我不能 把os.Executable()这里修改成loader.so的绝对路径吗?这样会造成全局变量地址reloc失败,我编译的o文件里也没有全局变量的,我只是把loader.so里的os.Executable修改成 我loader.so本身的绝对路径,这样就不会出现unresolve external这个问题。即把register.go 里面exe, err := os.Executable()替换成exe="/tmp/loader.so"。不可以这样吗? |
是不是 必须是ELF的路径才行? |
并不是你些的golang的代码中没有全局变量就是没有的,比如fmt.Println(xxx), 这个实际会使用os.Stdout。 当前的版本RegSymbol会调用os.Executable()得到当前程序的path,在你的环境里,会读到的是加载loader.so的ELF的C/C++编译的程序的path,这个里边是没有golang运行的符号表的,当你把他改成loader.so的path的时候,就正常了 |
不能是ELF的路径,应为这个是C/C++编译的,里边只有C/C++的符号表 |
是的 我已经把os.Executable()修改了成loader.so的path了,注册函数这些都是没问题了,也找到o文件的函数地址了,就是不能调用该函数,我也在内存里看了,该地址确实是o文件函数的地址 |
为啥会不能调用这个函数呢?你想表达的是不能在C里边调用golang的函数? 在loader里边调用是没有问题的,可以正常执行, 我已经测试过了 如果你想的是在C里边调用,那应该会出错,因为C和golang的运行环境不同,中间应该要有胶水代码才行 |
我的想法是能够让loader编译成.so,这样我C的代码就可以加载该loader.so,从而再让loader.so加载o文件并执行里面的函数。能支持这种情况吗? |
这样是可行的,我已经测试过了,可以正常执行,需要修改RegSymbol,让他去读loader.so的symbol就可以了. |
|
RegSymbol只修改path成loader.so的路径是吗?没有其他修改了吧,我再golang 1.9的情况下还是不行,请问您那边是golang哪个版本 |
我是在macosx上的golang1.16.2上测试的,你的有问题的话,告知下我你的测试环境 |
我的golang版本 是1.9 在centos6 x64上运行 |
Linux上在编译.so的时候将赋值TLS的语句改写了,所以函数头出问题了 |
@tooBugs
|
是的,非常感谢。已经可以了,我打算把源码了解的更深入些,请问有相关资料或说明吗? |
基本没有,只能读golang源代码的linker,因为本质上就是一个dl. |
@tooBugs , 7701df1 already support loader is a dynamic library. |
loader 是so加载.o文件成功但是掉用 .o文件函k数失败了,loader可以是so吗?
The text was updated successfully, but these errors were encountered: