2 回答
TA贡献1828条经验 获得超4个赞
不要忽略第一条评论。如果您坚持使用 Go 的内部链接器,该链接器不以与 libc 使用兼容的方式链接,那么您将不能使用任何 C 代码,包括LD_PRELOAD
ed C 代码甚至动态链接器本身的功能。正如 Florian(来自 glibc)在链接问题中所说,它对 glibc 也无效,并且只是偶然地在那里“工作”。
即使您以某种方式“机械地”弄清楚为什么没有调用您的ctor,您仍然在损坏的进程状态下运行C代码,并且任何事情都可能出错。即使您分析了所有内容并且看起来很好,这也可以随着下一次动态链接器/libc 更新而完全改变。
如果你想这样做,请使用 Go 中的外部链接器选项。
TA贡献2051条经验 获得超10个赞
从评论中可以看出,Go/Alpine 环境中的静态构造函数存在一个主要问题。简而言之,从 ABI 的角度来看,调用静态构造函数的需求分配给了可执行文件,而不是加载程序。Go 可执行文件不是基于 C 运行时的,它只调用依赖共享对象的静态构造函数,而不是LD_PRELOAD-ed 共享对象。在 glibc 的情况下, a LD_PRELOAD-ed 共享对象的构造函数由实现调用,而不是由加载器设计。在 musl-libc 上它们不是。
我做了一个“hack”-ish解决方法,让现有的 Go 应用程序与LD_PRELOAD-ed 共享对象一起工作。我正在使用这样一个事实,即LD_PRELOADmusl-libc 在此环境中正确地编辑了该库,并且 Gopthread_create在初始化的早期阶段就调用了该库。
我正在覆盖/挂钩-ed 共享对象pthread_create中的符号LD_PRELOAD并使用它来调用构造函数。
#include <pthread.h>
#include <dlfcn.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg)
{
int (*pthread_create_original)(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) = dlsym(RTLD_NEXT,"pthread_create");
static int already_called = 0;
if (!already_called)
{
already_called = 1;
// call here your constructors
}
return pthread_create_original(thread,attr,start_routine,arg);
}
警告:这适用于当前的 Go 运行时,但构建此解决方案的假设远非未来证明。Next Go 版本很容易破坏它。
- 2 回答
- 0 关注
- 121 浏览
添加回答
举报