Xlinker 条目参数在 Linux 中不起作用
Xlinker entry argument do not work in 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?
GCC(和 Clang)将为您处理细节,如果您只添加 __attribute__((constructor))
function attribute。函数不需要有外部可见的符号,因为该属性告诉编译器和链接器将函数的地址添加到 init 部分,导致动态链接器(如果动态链接)或 C 运行time (如果静态链接)在 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
很多年前,我创建了一个库,它在加载到内存时自动执行代码。
我使用 -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?
GCC(和 Clang)将为您处理细节,如果您只添加 __attribute__((constructor))
function attribute。函数不需要有外部可见的符号,因为该属性告诉编译器和链接器将函数的地址添加到 init 部分,导致动态链接器(如果动态链接)或 C 运行time (如果静态链接)在 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