测试是在x86、32位Linux上进行的。我正在使用g++ 4.6.3和objdump 2.22
这是我正在使用的简单C ++代码: />我可以在下面的hello.s中找到一个ctors部分:
#include <iostream>

using namespace std;

main()
{
    cout << "Hello World!" << endl;
    return 0;
}

但是,当我汇编asm代码时,生成一个exe文件并使用objdump产生ctors部分,其内容如下:
gcc -S hello.cc

我所能获得的是这样的:我想知道是否有一种方法可以获取与c++产生的内容相等的ctors的内容吗?但是我仍然陷入从ELF二进制文件中查找g++class's信息的问题。一个类的构造函数,而constructor是它的析构函数。
但是,我只是在destructor转储的class.ctors部分中找不到相应的信息。我也尝试了_ZN8ComputerC2Ev_ZN8ComputerD2Ev,但是转储的信息非常庞大。我可以不知道这些信息的含义。
有人可以给我指导吗?

#1 楼

.ctors部分是一个以-1(0xFFFFFFFF)结尾的指针的列表,因此反汇编它没有任何意义。如果将字节重新排列为数据,则会得到:

__CTOR_LIST__: .long 0xffffffff
__CTOR_END__:  .long 0x00000000


因此,无论出于何种原因,生成的exe实际上并不使用.ctors节。我怀疑链接器将指针放到了新样式的.init_array部分中。请注意,它还是一个指针列表,而不是代码。

编辑:

.ctors.init_array部分仅包含所谓的构造函数-需要的函数在main()本身之前在启动时执行。这些通常是编译器生成的函数,这些函数执行全局对象(例如cincout等)的构造或其他与启动有关的任务。实际上,您可以使用__attribute__((constructor))将自己的函数添加到该列表。

通用的C ++类构造函数没有用,无需在启动时执行它们。当以及如果您构造特定类的对象时,它们将被调用-例如通过声明变量或调用operator new

评论


时髦!我转储.init_array节的内容,它包含_GLOBAL__sub_I_main函数的地址!

– lllllllllllll
2014-09-23 1:40



#2 楼

正如Igor所说,.ctors部分是函数指针的列表,结尾是0xffffffff的前哨值。要查看其内容,只需执行

$ objdump -s -j.ctors bar.so


,但是您的汇编文件仅包含弱符号。这些是其他库中的外部函数,并且在运行时加载它们的库时被调用。

例如,将其放在文件bar.cpp中:



class Foo {
public:
  int i;

  Foo(int n) : i(n) {
  }
};

Foo global_foo(123);
进行编译

.init_array部分的内容是
指针在那里,0xad060000 00000000。但是您必须更改其字节序,例如使用Python:

$ g++ -shared -fPIC bar.cpp -obar.so


现在列出该地址的所有符号和grep:

$ objdump -s -j.init_array bar.so

bar.so:     file format elf64-x86-64

Contents of section .init_array:
 200820 ad060000 00000000                    ........        


反汇编它,

>>> import struct
>>> import binascii
>>> binascii.hexlify(struct.pack("<Q", 0xad06000000000000))
'00000000000006ad'


显示

$ objdump -C --syms bar.so | grep 00000000000006ad
00000000000006ad l     F .text  0000000000000015
  [... on above line ...] global constructors keyed to bar.cpp


它跳转到__static_initialization_and_destruction_0(int, int)

$ objdump -C -d bar.so


将123(0x7b)放在堆栈上并调用Foo::Foo(int)