c - .init_array 函数参数的任何文档?
问题描述
我可以看到许多在 .init_array 部分注册的函数具有命令行参数 argc 和 argv 的复制知识,例如 main(),但我无法在网上找到任何实际已发布的文档来证实这种情况。
是的,为了清楚起见,函数本身并没有在 .init_array 中“声明”,而是在其中声明了指向函数的指针,“注册”了该函数,并且在启动期间由某个迭代器调用。问题仍然存在:向我展示该迭代器传入的参数列表的一些文档。
我的意图是以一种微妙但通常安全的方式从动态库中更改这些参数,因此我想在内存中找到“真正的交易” - 而不是来自 /proc/self/。
如需更多信息,请点击以下链接。
一些堆栈溢出知识:在 Linux 上访问 main 之外的主要参数
甚至我最喜欢的 Oracle ( docs.oracle.com/cd/E23824_01/html/819-0690/chapter3-8.html ) 也只提到函数被调用,但没有承诺可能会有什么参数。据我所知,与 elf 和 gcc 文档相同。
在 C/C++ UB 偏执狂的土地上,理想情况下,在我继续之前,我需要确定这是记录在案的行为吗?它存在吗?它可以以某种方式暗示吗?
到目前为止的评论/答案摘要:
至少对于 GNU libc,此补丁发生了相关更改:BZ #974。 https://sourceware.org/pipermail/libc-alpha/2005-July/019240.html(在 glibc 的 ChangeLog.old/ChangeLog.16 条目 2005-04-13 HJ Lu 中提到。) – Ian Abbott
对我来说,这表明 glbc 维护者意识到传递 argc/argv/env 的要求——这不是偶然的——并将其扩展到主要的 exe 注册。它还告诉我们它在该日期之前为动态库工作。
这是一个有趣的问题,这是否会绑定其他 libc 实现者以遵循该模式。
解决方案
我发现了 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);
}
}
看来__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 年引入的。
推荐阅读
- c# - Master.aspx 上的会话为空
- c# - 我应该设置哪些 cookie/标题?
- python - 我可以要求开发人员在将代码提交到 gitlab 之前包含方法文档字符串吗?
- javascript - 如何在 javascript 中为 innerHTML 添加 WP 主题 css
- python - 在新选项卡中打开“href”变量
- javascript - 如何动态更改 Vuex 存储值
- c# - 在 WPF 中使用 Prism 7 加载应用程序时导航到默认视图
- javascript - 定位 div 中的特定子类
- c++ - 为什么我不能用 nullptr 初始化一个自动推导的指针?
- machine-learning - Doc2vecC 预测未见文档的向量