如何计算ELF文件中的静态初始值设定项? [英] How to count static initializer in an ELF file?

查看:88
本文介绍了如何计算ELF文件中的静态初始值设定项?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试计算C ++文件中的静态初始值设定项。

I'm trying to count static initializers in a C++ file.

我已经拥有的解决方案(曾经与gcc-4.4配合使用)正在查看.ctors ELF部分。

Solution I already have (which used to work with gcc-4.4) is looking at size of the .ctors ELF section.

升级到gcc-4.6后,这似乎不再返回有效结果(静态初始化器的计算数量为0,这不会匹配现实,例如由nm返回)。

After an upgrade to gcc-4.6, this seems to no longer return valid results (calculated number of static initializers is 0, which doesn't match reality, e.g. as returned by nm).

现在的问题是我希望解决方案即使在没有符号的情况下也可以工作(否则我会使用nm )。

Now the issue is I'd like the solution to work even in absence of symbols (otherwise I'd have used nm).

下面是示例可执行文件的readelf -SW的输出:

Below is the output of readelf -SW of an example executable:

有35个节标题,从偏移量0x4f39820开始:

There are 35 section headers, starting at offset 0x4f39820:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .interp           PROGBITS        00000174 000174 000013 00   A  0   0  1
  [ 2] .note.ABI-tag     NOTE            00000188 000188 000020 00   A  0   0  4
  [ 3] .note.gnu.build-id NOTE            000001a8 0001a8 000024 00   A  0   0  4
  [ 4] .gnu.hash         GNU_HASH        000001cc 0001cc 000918 04   A  5   0  4
  [ 5] .dynsym           DYNSYM          00000ae4 000ae4 00a5e0 10   A  6   1  4
  [ 6] .dynstr           STRTAB          0000b0c4 00b0c4 00ef72 00   A  0   0  1
  [ 7] .gnu.version      VERSYM          0001a036 01a036 0014bc 02   A  5   0  2
  [ 8] .gnu.version_r    VERNEED         0001b4f4 01b4f4 000450 00   A  6  13  4
  [ 9] .rel.dyn          REL             0001b944 01b944 268480 08   A  5   0  4
  [10] .rel.plt          REL             00283dc4 283dc4 0048c8 08   A  5  12  4
  [11] .init             PROGBITS        0028868c 28868c 00002e 00  AX  0   0  4
  [12] .plt              PROGBITS        002886c0 2886c0 0091a0 04  AX  0   0 16
  [13] .text             PROGBITS        00291860 291860 3ac5638 00  AX  0   0 16
  [14] malloc_hook       PROGBITS        03d56ea0 3d56ea0 00075a 00  AX  0   0 16
  [15] google_malloc     PROGBITS        03d57600 3d57600 008997 00  AX  0   0 16
  [16] .fini             PROGBITS        03d5ff98 3d5ff98 00001a 00  AX  0   0  4
  [17] .rodata           PROGBITS        03d5ffc0 3d5ffc0 ffa640 00   A  0   0 64
  [18] .eh_frame_hdr     PROGBITS        04d5a600 4d5a600 0004b4 00   A  0   0  4
  [19] .eh_frame         PROGBITS        04d5aab4 4d5aab4 001cb8 00   A  0   0  4
  [20] .gcc_except_table PROGBITS        04d5c76c 4d5c76c 0003ab 00   A  0   0  4
  [21] .tbss             NOBITS          04d5df0c 4d5cf0c 000014 00 WAT  0   0  4
  [22] .init_array       INIT_ARRAY      04d5df0c 4d5cf0c 000090 00  WA  0   0  4
  [23] .ctors            PROGBITS        04d5df9c 4d5cf9c 000008 00  WA  0   0  4
  [24] .dtors            PROGBITS        04d5dfa4 4d5cfa4 000008 00  WA  0   0  4
  [25] .jcr              PROGBITS        04d5dfac 4d5cfac 000004 00  WA  0   0  4
  [26] .data.rel.ro      PROGBITS        04d5dfc0 4d5cfc0 1b160c 00  WA  0   0 32
  [27] .dynamic          DYNAMIC         04f0f5cc 4f0e5cc 000220 08  WA  6   0  4
  [28] .got              PROGBITS        04f0f7ec 4f0e7ec 00a800 04  WA  0   0  4
  [29] .data             PROGBITS        04f1a000 4f19000 0206b8 00  WA  0   0 32
  [30] .bss              NOBITS          04f3a6c0 4f396b8 04c800 00  WA  0   0 32
  [31] .comment          PROGBITS        00000000 4f396b8 00002a 01  MS  0   0  1
  [32] .shstrtab         STRTAB          00000000 4f396e2 00013e 00      0   0  1
  [33] .symtab           SYMTAB          00000000 4f39d98 4ff960 10     34 140163  4
  [34] .strtab           STRTAB          00000000 54396f8 144992a 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

我应该看看.init或.init_array代替?您能指出对应的文档来解释gcc或链接器版本之间的变化吗?

Should I be looking at .init or .init_array instead? Could you point me to corresponding documentation that explains the change between gcc or linker versions?

推荐答案

静态构造函数可以由以下任何一种触发这三个部分 .init .ctors .init_array (按此顺序从最旧到最新)。 .init 包含一段代码, .ctors .init_array 包含代码指针。 .ctors .init_array 之间的差异与构造函数的执行顺序有关。据我所知,除了代码注释和邮件列表帖子外,没有任何其他文档,但是可能值得检查一下ELF ABI文档(g-和ps-两者)。

Static constructors can be triggered by any of the three sections .init, .ctors, or .init_array (oldest to newest in that order). .init contains a fragment of code, .ctors and .init_array contain pointers to code. The difference between .ctors and .init_array has to do with the overall order in which constructors are executed. As far as I know, none of this is documented anywhere other than code comments and mailing list posts, but it's probably worth checking the ELF ABI documents (g- and ps- both).

不能从这些部分的 any 的大小推断出文件中静态构造函数的数量。编译器可以生成一个特殊的函数来调用文件中的所有构造函数,并且仅在使用的任何部分中都引用该函数,这是常见的做法。您可以肯定知道的所有内容(无需检查这些节的内容,应用重定位以及将指针/调用指令追逐到 .text 段中,并对所调用的内容进行反向工程)是:在目标文件中,如果这些部分中至少有一个具有非零大小,则该文件中至少有一个文件或全局作用域的构造函数;如果所有三个部分都为空,则没有任何一个。 (在可执行文件中,所有三个部分始终是非空的,因为它们定义的数据结构需要头和尾,它们在链接时会自动添加。)

You cannot deduce the number of static constructors in a file from the size of any of these sections. It is permitted, and common, for compilers to generate a single special function which invokes all of the constructors in a file, and reference only that one function in whichever of the sections it uses. All you can know for sure (without examining the contents of the sections, applying relocations, and chasing pointers / call instructions into the .text segment and reverse engineering whatever gets called) is: in an object file, if at least one of these sections has nonzero size, then there is at least one file- or global-scope constructor in the file; if all three sections are empty, then there are none. (In an executable, all three sections are always nonempty, because the data structures that they define need headers and trailers, which are automatically added at link time.)

还请注意这些部分中的任何一个都不会调用用于块范围内的静态对象的构造函数;它们在控件第一次到达其声明时被调用。

Note also that constructors for block-scoped static objects are not invoked from any of these sections; they're invoked the first time control reaches their declaration.

这篇关于如何计算ELF文件中的静态初始值设定项?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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