从汇编层面深度剖析C++基本对象布局
作者:网络转载 发布时间:[ 2014/7/2 11:24:38 ] 推荐标签:Net 软件开发
3. 编译生成汇编文件和可执行文件
g++命令行提供了简便方式来生成这两种文件,我们在下面根据实际需要来对这两文件进行分析,从而深入理解point对象的内存布局。
g++命令使用如下:
[lyt@t468 ~]$ g++ -g -o object object.cpp
[lyt@t468 ~]$ g++ -g -S -o object.s object.cpp
object.s文件生成的汇编比较凌乱,因为它里面的符号还未重定位,只是使用一些符号来表示某些以后要分配内存的变量,编译器使用的变量或符号。因此,我们可以利用它来分析某些C++变量经编译器处理后,在汇编层面上的符号名称。
object文件可用来供gdb调试工具来使用,gdb可以对源代码以函数为单位,对每一行语句进行反汇编。
4. 所有与point类相关的符号
C++源代码生成可执行文件(linux下称为ELF格式文件)后,它专门有一个符号节区来记录执行文件中各个符号的类型,地址等相关信息。为了便于分析,我们使用readelf工具对生成的object文件,找出与point类相关的所有符号,以及使用c++filt工具,将这些符号转变成C++语言级别上的语义,如下:
|
[lyt@t468 ~]$ readelf -s object | grep point
41: 08048530 10 FUNC WEAK DEFAULT 13 _ZN5point13get_instancesE
49: 0804853a 40 FUNC WEAK DEFAULT 13 _ZN5point4moveEii
56: 080484fa 35 FUNC WEAK DEFAULT 13 _ZN5pointC1Eii
58: 0804851e 18 FUNC WEAK DEFAULT 13 _ZN5pointD1Ev
59: 0804a01c 4 OBJECT GLOBAL DEFAULT 25 _ZN5point7ins_cntE
[lyt@t468 ~]$ c++filt _ZN5point13get_instancesE
point::get_instances
[lyt@t468 ~]$ c++filt _ZN5point4moveEii
point::move(int, int)
[lyt@t468 ~]$ c++filt _ZN5pointC1Eii
point::point(int, int)
[lyt@t468 ~]$ c++filt _ZN5pointD1Ev
point::~point()
[lyt@t468 ~]$ c++filt _ZN5point7ins_cntE
point::ins_cnt
|
从上面的结果可以看出来,point类的构造函数,析构函数,move成员函数,get_instances静态成员函数都对应一个函数符号。而令我们感到意外的是,point类的静态变量ins_cnt也对应一个全局变量符号,它的地址是0804a01c;下面对地址0804a01c 的读写汇编语言,都意味着相应的C++函数读写该变量,也即point类的静态变量。
5. point对象的内存布局和构造函数
对象的生命始于构造函数,而在执行构造函数之前,对象还处于混沌状态。在构造函数里面,它按对象内存所包含的每个成员依次进行初始化,因此我们从对象的构造函数可以一窥它的内存布局。
为了方便大家较对C++源代码和汇编代码,使用gdb对point类的构造函数按源代码行进行反汇编。结果如下:
|
(gdb) disassemble /m _ZN5pointC1Eii
Dump of assembler code for function point:
5 point(int x, int y)
0x080484fa <point+0>: push ebp
0x080484fb <point+1>: mov ebp,esp
6 {
7 this->x = x;
0x080484fd <point+3>: mov eax,DWORD PTR [ebp+0x8]
0x08048500 <point+6>: mov edx,DWORD PTR [ebp+0xc]
0x08048503 <point+9>: mov DWORD PTR [eax],edx
8 this->y = y;
0x08048505 <point+11>: mov eax,DWORD PTR [ebp+0x8]
0x08048508 <point+14>: mov edx,DWORD PTR [ebp+0x10]
0x0804850b <point+17>: mov DWORD PTR [eax+0x4],edx
9 ins_cnt++;
0x0804850e <point+20>: mov eax,ds:0x804a01c
0x08048513 <point+25>: add eax,0x1
0x08048516 <point+28>: mov ds:0x804a01c,eax
10 }
0x0804851b <point+33>: pop ebp
0x0804851c <point+34>: ret
End of assembler dump.
|

sales@spasvo.com