我可以看到很多复制的知识,这些函数在 .init_array 部分注册的函数具有命令行参数 argc 和 argv,如 main(),但我无法在网上找到任何实际发布的文档来证实情况确实如此。
\n是的,为了清楚起见,函数本身没有在 .init_array 中“声明”,但在那里声明了指向该函数的指针,“注册”该函数,并在启动期间由某个迭代器调用。问题仍然是:向我显示该迭代器传入的参数列表的一些文档。
\n我的目的是以一种微妙但通常安全的方式从动态库中更改这些参数,因此我想在内存中找到“真正的交易”——而不是从 /proc/self/ 中。
\n欲了解更多信息,请点击下面的链接。
\n一些堆栈溢出知识:在 Linux 上访问 main 之外的主要参数
\n即使是我最喜欢的 Oracle ( docs.oracle.com/cd/E23824_01/html/819-0690/chapter3-8.html ) 也只提到函数被调用,但没有承诺可能有什么参数。据我所知,与 elf 和 gcc 文档相同。
\n在 C/C++ UB 偏执狂的土地上,理想情况下,在我继续之前,我需要确定这是已记录的行为?它存在吗?可以通过某种方式暗示吗?
\n迄今为止的评论/答案摘要:
\n至少对于 GNU libc,此补丁发生了相关更改:BZ #974。\n https://sourceware.org/pipermail/libc-alpha/2005-July/019240.html(在 glibc\'s 中提到) ChangeLog.old/ChangeLog.16 条目 2005-04-13 HJ Lu.) \xe2\x80\x93\nIan Abbott
\n对我来说,这表明 glbc 维护者意识到传递 argc/argv/env 的要求 - 这不是偶然的 - 并将其扩展到主 exe 注册。它还告诉我们,它在该日期之前适用于动态库。
\n这是一个有趣的问题,这是否会约束其他 libc 实现者遵循该模式。
\n我发现Patrick Horgan 写的这篇关于 Linux 程序启动过程的有趣文章。但我可能无法保证该来源的正确性。
至少,它解释了该.init_array部分背后的代码:
void __libc_csu_init (int argc, char **argv, char **envp) {
_init ();
const size_t size = __init_array_end - __init_array_start;
for (size_t i = 0; i < size; i++) {
(*__init_array_start [i]) (argc, argv, envp);
}
}
Run Code Online (Sandbox Code Playgroud)
看来该__libc_csu_init()函数首先计算节内的元素数量.init_array,然后使用参数argc、argv和调用每个函数指针envp。该函数 ( __libc_csu_init()) 之前被调用main()。
注意:该.init_array部分似乎特定于 ELF 二进制格式。
看起来,它的实现__libc_csu_init()(以及更一般地说,.init_array函数的调用方式)是依赖于平台和 libc 的。
然而,Linux 上的 GLIBC 似乎可以使用所需的参数正确调用函数,正如您从其源代码中看到的那样。
另外,阅读GLIBC 变更日志,似乎这种行为是在 2005 年引入的。