__attribute __((构造函数))调用顺序混淆 [英] __attribute__((constructor)) call order confusion

查看:404
本文介绍了__attribute __((构造函数))调用顺序混淆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

答案此处表明__attribute __((构造函数))不是在静态初始化之后调用,它在声明顺序中被调用。

然后,它的目的是什么,如果它不能保证所有数据初始化时调用?我们可以在Foo构造函数中使用我们的((构造函数))代码。



我在寻找的是一种在共享库中拥有将在所有静态数据初始化并调用静态构造函数后执行的代码。我看到有人推荐__attribute __((构造函数))作为DllMain的替代品;我们可以看到这是错误的,因为一些静态数据可能还没有被初始化。



当然,在单个文件(编译单元)中,我们可以安排静态。但是在典型的程序中有很多文件。有一种方法可以保证在一个文件中的((构造函数))在共享库中的所有其他静态被初始化后肯定会被调用吗?



如果我把一个文件将静态初始化(构造函数,对象等)添加到gcc命令行的末尾:

  g ++ -shared -fPIC source1。 o source2.o MyLastInitChance.o 

是这个文件的静态构造函数保证被最后调用吗?我尝试过,当我更改源文件的顺序时,printfs的顺序发生了变化;但它是否在某处指定,并保证在编译系统/计算机上保持不变?



例如,引用:


在链接时,gcc驱动程序立即在所有
之前立即将crtbegin.o放置在所有
可重定位文件之后的可重定位文件和crtend.o之前。 ©


据我所知,上面的引用意味着传递给链接器的.o文件的顺序定义了静态初始化的顺序。我是否正确?

另一个有趣的可能解决方案是编写一个GCC插件来调整静态初始化(例如将代码添加到.ctors部分等)。但这只是一个想法,也许有人可以扩展。



另一个可能的解决方案是介绍这里。简而言之,可以使用外部后构建工具对可执行文件(库)中的.ctors条目进行重新排序。但我不是ELF格式的专家;我想知道这是否可行和容易,以这种方式调整.so文件。



我感兴趣的是解决一个特定的问题,或者证明它是不可能解决的问题(至少为什么上面的解决方案不起作用)。 您可能会尝试使用<$ c的链接器脚本$ C> LD 。您可以阅读更多有关此处 ,但我猜你在找什么是

$ pre code> .ctors:{*(SORT(.ctors))MyLastInitChance.o( (SORT(.dtors))}

位于 SECTIONS {...} 块中。这应该重新安排 .ctors 部分,因此提供的文件将把它的构造函数称为最后一个。显然,如果你觉得自己需要一个解决方案,也可以使用更高级的解决方案;)

提示:编写你自己的链接脚本是很乏味的。使用 ld - verbose 选项,可打印出使用过的链接脚本并对其进行修改。然后使用 -T 开关添加您的链接脚本。


The answer here demonstrates that __attribute__((constructor)) is not called after static initialization, it is called in the declaration order.

Then, what is the purpose of it, if it is not guaranteed to be called when all data is initialized? We could as well have our ((constructor)) code in the Foo constructor.

What I'm looking for is a way to have, in a shared library, a code that will be executed after all static data is initialized and static constructors are called. I saw people recommending __attribute__((constructor)) as a replacement for DllMain; as we can see this is wrong, because some static data may still be not initialized.

Of course in single file (compilation unit) we could arrange statics. But in a typical program there's a lot of files. Is there a way to guarantee that ((constructor)) in one file will be definitely called after all other statics in a shared library are initialized?

If I put a file with static initialization (constructor, object, etc) to the end of the gcc command line:

g++ -shared -fPIC source1.o source2.o MyLastInitChance.o

are this file's static constructors guaranteed to be called last? I experimented and when I change order of source files, printfs' order is changed; but is it specified somewhere and guaranteed to be the same across compilation systems/computers?

For example, a quote:

At link time, the gcc driver places crtbegin.o immediately before all the relocatable files and crtend.o immediately after all the relocatable files. ©

From what I understand the quote above implies that order of .o files passed to the linker defines order of the static initialization. Am I correct?

Another interesting possible solution, maybe, is to write a GCC plugin that adjusts static initialization (e.g. adds code to .ctors section, etc). But this is just an idea that maybe someone can extend.

One more possible solution is presented here. In short, an external post-build tool can be used to reorder .ctors entries in the executable file (library). But I'm not an expert in ELF format; I wonder if this is possible and easy enough to tweak .so files in this way.

What I'm interested in is solving a particular problem, or proving that it is impossible to solve (at least why the solutions above would not work).

解决方案

You might try using linker scripts for ld. You can read more about it here, but I guess what you are looking for is

.ctors : { *(SORT(.ctors)) MyLastInitChance.o(SORT(.ctors)) }
.dtors : { *(SORT(.dtors)) MyLastInitChance.o(SORT(.dtors)) }

in SECTIONS{...} block. That should rearrange .ctors sections so file provided will call it's constructors as the last one. Obviously more advanced solutions are also available if you find yorself in need for one;)

HINT: writing your own link-script is tedious. Use ld's --verbose option that prints out used link script and modify it. Then add your linking script using -T switch.

这篇关于__attribute __((构造函数))调用顺序混淆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆