c - Xlinker 入口参数在 Linux 中不起作用
问题描述
许多年前,我创建了一个库,它在加载到内存时自动执行代码。
我使用 -Xlinker --init=_entry,其中 _entry 是我的库中的一个符号。部分 Makefile 代码附在下面:
gcc -ggdb -fPIC -c ./cli2gui.c
gcc -ggdb -shared -Wl,-soname,cli2gui.so.0 -o cli2gui.so.0.1 ./cli2gui.o -Xlinker --init=_entry -lutil -ldl
一切都可以编译,但是在执行链接到我的库的程序(或动态加载它)时,没有执行 _entry。我通过在 gdb 中设置断点来检查这一点。
如何解决这个问题 - 我的意思是每次我的库加载到内存时如何执行 _entry?
解决方案
__attribute__((constructor))
如果您只添加function 属性,GCC(和 Clang)将为您处理详细信息。函数不需要有外部可见的符号,因为该属性告诉编译器和链接器将函数的地址添加到 init 部分,从而导致动态链接器(如果动态链接)或 C 运行时(如果静态链接)在 main() 之前执行函数。
一个简单的例子:
// SPDX-License-Identifier: CC0-1.0
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
static int wrerr(const char *src)
{
if (!src || !*src)
return 0;
const int saved_errno = errno;
const char *end = src;
while (*end)
end++;
while (src < end) {
ssize_t n = write(STDERR_FILENO, src, (size_t)(end - src));
if (n > 0) {
src += n;
} else
if (n != -1) {
errno = saved_errno;
return EIO;
} else {
const int retval = errno;
errno = saved_errno;
return retval;
}
}
errno = saved_errno;
return 0;
}
__attribute__((constructor))
static void my_init(void)
{
wrerr("my_init() called\n");
}
要进行测试,您可以将其编译为另一个程序中的目标文件,也可以将其编译为动态库并在运行时插入:
gcc -Wall -fPIC example.c -shared -Wl,-soname,libexample.so -ldl -o libexample.so
LD_PRELOAD=./libexample.so date
推荐阅读
- r - 如何将char日期转换为日期格式
- javascript - 如何使用子进程承诺
- go - 未找到实体且 err 仍为 nil
- r - 密度图的不稳定行为
- google-cloud-platform - Youtube API Integromat 测试应用程序 - 连接被禁用
- javascript - 在 JavaScript 中查找“1.5×10^9”和“4.75×10^9”的正则表达式?
- .htaccess - 将 http 重定向到 https 在子目录中作为 404 出现问题 - 未找到
- apache-spark - 作业和任务持续时间的关系是 Spark UI
- javascript - 仅使用正则表达式保留字母数字值
- protocols - Session Initiation Protocol 如何表示有效载荷数据?