gpt4 book ai didi

不能将 IFUNC 解析器与惰性绑定(bind)一起使用

转载 作者:行者123 更新时间:2023-12-04 03:38:24 25 4
gpt4 key购买 nike

系统规范:

$ uname -a
Linux 5.4.0-66-generic #74-Ubuntu SMP Wed Jan 27
22:54:38 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
$ gcc -v
...
gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)
$ inxi
CPU: Quad Core Intel Core i7-1065G7 (-MT MCP-) speed/min/max: 1002/400/3900 MHz
Kernel: 5.4.0-66-generic x86_64 Up: 6d 7h 59m Mem: 4831.2/7730.1 MiB (62.5%)
Storage: 476.94 GiB (28.7% used) Procs: 349 Shell: bash 5.0.17 inxi: 3.0.38

我正在尝试将 IFUNC 与惰性绑定(bind)一起使用,但无论我做什么,解析器都会在调用 main 之前继续运行 - 这意味着解析器会在运行时之前运行。

目标 ELF 中没有 BIND_NOW 符号。

LD_BIND_NOW 未设置(我尝试在将其绑定(bind)到 0 时执行相同操作)。

我在文档中看不到发生这种情况的任何原因。

主.c:

#include <stdio.h>
#include <stdlib.h>


int foo_1() { return 1; }
int foo_2() { return 2; }
int foo_3() { return 3; }

extern int foo(void);
int foo(void) __attribute__((ifunc ("resolve_foo")));


int main() {
printf("main started\n");
printf("foo() = %d\n", foo());
return 0;
}


static void *resolve_foo(void) {
int res = 0;//atoi(getenv("FOO"));
printf("resolver started\n");
if (res == 1)
return foo_1;
if (res == 2)
return foo_2;
return foo_3;

}

执行:

$ gcc -zlazy -o t main.c
$ ./t
resolver started
main started
foo() = 3

最佳答案

惰性绑定(bind)允许在最晚可能的时间绑定(bind)。然而,ifunc 属性的解析器与链接/绑定(bind)并没有真正相关,但或多或​​少是为函数的用户提供了便利(除此之外它还有一些含义)。

正如文档所解释的那样,以这种方式标记的函数被隐式更改为间接函数调用。指向实际实现的(隐藏)函数指针由解析器提供。并且在调用 main 之前调用解析器,即严格来说是在 C 应用程序代码开始之前。当在所有情况下调用main 时,这是保证合规行为所必需的。

您期望解析器在最晚可能的时间被调用,但这要么需要更改运行时代码,具体取决于流程以捕获所有可能的情况(包括将指针指向运行时解析函数或条件),或者每次调用实际函数之前调用解析器。

要详细理解这一点,还请记住二进制不再是 C 语言。包装函数也可以第一次从内联汇编中调用,所以几乎没有办法绕过第二个选项,因为编译器生成的代码无法意识到这些。类似的情况适用于其他链接库。

我认为应该清楚每次调用解析器会增加相当多的开销并且明显与整个概念的主要意图相矛盾。

ifunc 机制的存在正是为了避免这种情况。它还允许优化,例如编译器直接插入间接调用而不使函数指针成为全局指针。

所以,如果你想在 main 之后解析,你需要使用专用函数指针提供你自己的机制。在这种情况下,您当然有责任自己解析指针,并通过指针(全局指针)调用函数或使用带有静态指针的包装函数(当然不是函数的本地指针)。


说到这里,我想知道您的实际问题是什么。我怀疑您希望您的解析器依赖于 main 中的某些内容。无论如何,这是一个坏主意 - 至少对于标准函数(memcpy()/memclr() 例如,甚至可能被启动代码调用)。对于用户函数,我在上面为您提供了另一种方法。


更新:我刚找到 this bugreport关于 ifunc,它更清楚地说明了它,并且还说明了调用其他函数的问题。那是因为在 main() 之前,C 环境可能无法完全运行。对于 stdio 尤其如此。所以您的 printf() 调用本身也可能是一个问题。

关于不能将 IFUNC 解析器与惰性绑定(bind)一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66509889/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com