VC应用程序中的SECTION(2): .textbss

 

快乐虾

http://blog.csdn.net/lights_joy/

[email protected]

 

本文适用于

Xp sp3 / Vs2008

 欢迎转载,但请保留作者信息

 

1.1.1   节的基本信息

使用dumpbin可以看到这一节的基本信息:

SECTION HEADER #1

.textbss name

   10000 virtual size

    1000 virtual address (00401000 to 00410FFF)

       0 size of raw data

       0 file pointer to raw data

       0 file pointer to relocation table

       0 file pointer to line numbers

       0 number of relocations

       0 number of line numbers

E00000A0 flags

         Code

         Uninitialized Data

         Execute Read Write

很明显,这个节里存放的是代码,而且是未初始化的代码,那么这个节的代码应该是动态写入的,再看一下符号表中的相关定义:

  Address         Publics by Value              Rva+Base       Lib:Object

0001:00000000       __enc$textbss$begin        00401000     <linker-defined>

0001:00010000       __enc$textbss$end          00411000     <linker-defined>

这到底是什么东西?

在vs中启动调试器,在内存窗口中查看这一段空间的代码:

0x00401000  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

0x00401010  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

0x00401020  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

全部为0。

1.1.2   动态编译

根据网上资料,这个节是与增量链接及动态编译相关的,检查链接器参数,确保打开了增量链接,进行验证工作。

在main函数之前插入一个测试函数并在main中调用它:

 

int add(int a, int b)

{

     return a + b;

}

 

int _tmain(int argc, _TCHAR* argv[])

{

     add(3, 4);

     return 0;

}

查看符号表文件,可以看到add函数的地址:

  Address         Publics by Value              Rva+Base       Lib:Object

0002:00000370       ?add@@YAHHH@Z              00411370 f   demo.obj

 

启动调试器,在反汇编窗口中查看main函数:

int _tmain(int argc, _TCHAR* argv[])

{

004117B0  push        ebp 

004117B1  mov         ebp,esp

004117B3  sub         esp,0C0h

004117B9  push        ebx 

004117BA  push        esi 

004117BB  push        edi 

004117BC  lea         edi,[ebp-0C0h]

004117C2  mov         ecx,30h

004117C7  mov         eax,0CCCCCCCCh

004117CC  rep stos    dword ptr es:[edi]

     add(3, 4);

004117CE  push        4   

004117D0  push        3   

004117D2  call        add (4111C2h)

004117D7  add         esp,8

     return 0;

004117DA  xor         eax,eax

}

注意这里的地址是0x004111c2,而不是add这个函数的地址0x00411370。

在反汇编窗口中查看0x004111c2这个地址:

00411001  int         3   

00411002  int         3   

00411003  int         3   

00411004  int         3   

00411005  jmp         _setdefaultprecision (411AB0h)

00411014  jmp         _RTC_GetErrDesc (411940h)

………………

004111BD  jmp         _RTC_CheckStackVars (4124C0h)

004111C2  jmp         add (411370h)

004111C7  jmp         _RTC_CheckStackVars2 (4132A0h)

004111CC  jmp         _RTC_CheckEsp (4114A0h)

004111D1  int         3   

这一段想来就是传说中的ILT表了,可以看到在这里跳转到了add函数所在的位置。

 

下面试试动态编译:

不退出调试器,修改add函数,将之改为:

int add(int a, int b)

{

     return a + b + 10;

}

保存后再单步跟踪,此时VC将动态编译这个文件,但不会退出调试状态,我们再看ILT表的变化:

004111BD  jmp         _RTC_CheckStackVars (4124C0h)

004111C2  jmp         add (401000h)

004111C7  jmp         _RTC_CheckStackVars2 (4132A0h)

注意这里的地址已经进行了修改,且指向.textbss的首地址,在动态编译之前,.textbss的内容全部为0,但此时再看:

--- e:\projects\src\cygwin\demo\demo.cpp ---------------------------------------

// demo.cpp : 定义控制台应用程序的入口点。

//

 

#include "stdafx.h"

 

int add(int a, int b)

{

00401000  push        ebp 

00401001  mov         ebp,esp

00401003  sub         esp,0C0h

00401009  push        ebx 

0040100A  push        esi 

0040100B  push        edi 

0040100C  lea         edi,[ebp-0C0h]

00401012  mov         ecx,30h

00401017  mov         eax,0CCCCCCCCh

0040101C  rep stos    dword ptr es:[edi]

     return a + b + 10;

0040101E  mov         eax,dword ptr [b]

00401021  mov         ecx,dword ptr [a]

00401024  lea         eax,[ecx+eax+0Ah]

}

00401028  pop         edi 

00401029  pop         esi 

0040102A  pop         ebx 

0040102B  mov         esp,ebp

0040102D  pop         ebp 

0040102E  ret             

--- 无源文件-----------------------------------------------------------------------

0040102F  stos        byte ptr es:[edi]

00401030  adc         byte ptr [ecx],al

00401033  mov         ecx,4110h

00401038  add         byte ptr [eax],al

这就是重新编译后生成的代码!

现在我们终于明白了.textbss就是用来存放动态编译生成的代码的。

1.1.3   关闭增量链接

既然.textbss是为增量链接和动态编译服务的,那么如果关闭增量链接,又会如何呢?

试试关闭增量链接,可以看到在exe文件中已经不再生成.textbss这个节,也不再有ILT。

看看此时符号表中add函数的地址:

  Address         Publics by Value              Rva+Base       Lib:Object

0001:00000000       ?add@@YAHHH@Z              00401000 f   demo.obj

直接放在了.text段的开头。

再看main函数的反汇编:

int _tmain(int argc, _TCHAR* argv[])

{

00401030  push        ebp 

00401031  mov         ebp,esp

00401033  sub         esp,0C0h

00401039  push        ebx 

0040103A  push        esi 

0040103B  push        edi 

0040103C  lea         edi,[ebp-0C0h]

00401042  mov         ecx,30h

00401047  mov         eax,0CCCCCCCCh

0040104C  rep stos    dword ptr es:[edi]

     add(3, 4);

0040104E  push        4   

00401050  push        3   

00401052  call        add (401000h)

00401057  add         esp,8

     return 0;

0040105A  xor         eax,eax

}

它直接跳转到了add函数的地址。

如果此时修改add函数的代码并单步跟踪,VC将毫不客气地弹出对话框:

VC应用程序中的SECTION(2): .textbss_第1张图片

也就是说动态编译的功能将不再可用。

 

 

你可能感兴趣的:(c,汇编,object,File,byte,Numbers)