【发布时间】:2013-12-19 15:12:42
【问题描述】:
最近在 Linux 上的 ELF 工具中的 IFUNC 机制允许在运行时选择函数的实现。查看 GCC 文档中的 iunc 属性以获得更详细的描述:http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html IFUNC机制的另一种描述:http://www.agner.org/optimize/blog/read.php?i=167
我想根据环境变量的值来选择我的实现。但是,我的实验表明,当解析器函数运行时,libc(至少是关于环境的部分)尚未初始化。因此,经典接口(extern char**environ 或 getenv())不起作用。
有人知道如何在很早的阶段访问Linux中的程序环境吗?该环境是由内核在 execve(2) 系统调用时设置的,因此它在早期初始化时已经位于程序地址空间中的某个位置(但具体在哪里?)。
提前致谢 文森特
要测试的程序:
#include <stdio.h>
#include <stdlib.h>
extern char** environ;
char** save_environ;
char* toto;
int saved=0;
extern int fonction ();
int fonction1 () {
return 1;
}
int fonction2 () {
return 2;
}
static typeof(fonction) * resolve_fonction (void) {
saved=1;
save_environ=environ;
toto=getenv("TOTO");
/* no way to choose between fonction1 and fonction2 with the TOTO envvar */
return fonction1;
}
int fonction () __attribute__ ((ifunc ("resolve_fonction")));
void print_saved() {
printf("saved: %dn", saved);
if (saved) {
printf("prev environ: %pn", save_environ);
printf("prev TOTO: %sn", toto);
}
}
int main() {
print_saved();
printf("main environ: %pn", environ);
printf("main environ[0]: %sn", environ[0]);
printf("main TOTO: %sn", getenv("TOTO"));
printf("main value: %dn", fonction());
return 0;
}
编译和执行:
$ gcc -Wall -g ifunc.c -o ifunc
$ env TOTO=ok ./ifunc
saved: 1
prev environ: (nil)
prev TOTO: (null)
main environ: 0x7fffffffe288
main environ[0]: XDG_VTNR=7
main TOTO: ok
main value: 1
$
在解析器函数中,environ 为 NULL,getenv("TOTO") 返回 NULL。在main函数中,信息就在这里。
【问题讨论】:
-
您的操作级别低于 C 运行时。所以你需要阅读libc的代码,找出它是从哪里得到环境的。