可执行程序的变量存储到底有什么规律呢?

测试一下:
Windows x86 (vs2010)、 x64(gcc)
Linux ARM (gcc)

code:

unsigned long g_A = 0x11223344;
unsigned long g_B;

unsigned long function()
{
    static unsigned long s_A = 0xAABBCCDD;
    static unsigned long s_B;
    unsigned long A = 0x55667788;
    s_A ++;
    s_B = s_A;
    return A;
}

int main(int argc, char** argv) 
{
    unsigned long B = 0x99999999;
    B = function();
    return 0;
}

1、编译选项:Windows, x86, 优化全关闭(vs2010)

Dump of file E:\users\blastts\documents\visual studio 2010\Projects\testSection\Release\testSection.exe

PE signature found

File Type: EXECUTABLE IMAGE

FILE HEADER VALUES
             14C machine (x86)
               5 number of sections
        54D6CDF6 time date stamp Sun Feb 08 10:46:14 2015
               0 file pointer to symbol table
               0 number of symbols
              E0 size of optional header
             102 characteristics
                   Executable
                   32 bit word machine

SECTION HEADER #1
   .text name
     82A virtual size
    1000 virtual address (00401000 to 00401829)
     A00 size of raw data
     400 file pointer to raw data (00000400 to 00000DFF)
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
60000020 flags
         Code
         Execute Read

SECTION HEADER #2
  .rdata name
     5C6 virtual size
    2000 virtual address (00402000 to 004025C5)
     600 size of raw data
     E00 file pointer to raw data (00000E00 to 000013FF)
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
40000040 flags
         Initialized Data
         Read Only

SECTION HEADER #3
   .data name
     394 virtual size
    3000 virtual address (00403000 to 00403393)
     200 size of raw data
    1400 file pointer to raw data (00001400 to 000015FF)
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
C0000040 flags
         Initialized Data
         Read Write

SECTION HEADER #4
   .rsrc name
     1B4 virtual size
    4000 virtual address (00404000 to 004041B3)
     200 size of raw data
    1600 file pointer to raw data (00001600 to 000017FF)
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
40000040 flags
         Initialized Data
         Read Only

SECTION HEADER #5
  .reloc name
     18E virtual size
    5000 virtual address (00405000 to 0040518D)
     200 size of raw data
    1800 file pointer to raw data (00001800 to 000019FF)
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
42000040 flags
         Initialized Data
         Discardable
         Read Only

  Summary

        1000 .data
        1000 .rdata
        1000 .reloc
        1000 .rsrc
        1000 .text

不出意外的话,全局变量unsigned long g_A = 0x11223344;,静态变量static unsigned long s_A = 0xAABBCCDD;应该都是存在一起的。

SECTION HEADER #3
   .data name
RAW DATA #3
  00403000: 44 33 22 11 DD CC BB AA 

而局部变量则又是在一起的

SECTION HEADER #1
   .text name
RAW DATA #1
  00401000: 55 8B EC 51 C7 45 FC **88 77 66 55** A1 04 30 40 00  U.имQ?Eи╣.wfU?.0@.
  00401010: 83 C0 01 A3 04 30 40 00 8B 0D 04 30 40 00 89 0D  .ид.бъ.0@....0@...
  00401020: 24 30 40 00 8B 45 FC 8B E5 5D C3 CC CC CC CC CC  $0@..Eи╣.?]?имимимимим
  00401030: 55 8B EC 51 C7 45 FC **99 99 99 99**

既然.text是Execute Read,那么必然有:

01021030          testSection!main (int, char **)

0:000> u testSection!main
testSection!main [e:\users\blastts\documents\visual studio 2010\projects\testsection\testsection\testsection.cpp @ 20]:
01021030 55              push    ebp
01021031 8bec            mov     ebp,esp
01021033 51              push    ecx
01021034 c745fc99999999  mov     dword ptr [ebp-4],99999999h
0102103b e8c0ffffff      call    testSection!function (01021000)
01021040 8945fc          mov     dword ptr [ebp-4],eax
01021043 33c0            xor     eax,eax
01021045 8be5            mov     esp,ebp

而没初值的s_B,(忘记关ASLR了,很容易就能算出RAW,所以先不管它)

0102101e 890d24300201    mov     dword ptr [testSection!s_B (01023024)],ecx


0:000> !dh 0x1020000
OPTIONAL HEADER VALUES
     10B magic #
   10.00 linker version
     A00 size of code
     C00 size of initialized data
       0 size of uninitialized data
    12D7 address of entry point
    1000 base of code
         ----- new -----
**01020000 image base**

SECTION HEADER #3
   .data name
     394 virtual size
    3000 virtual address
     200 size of raw data
    1400 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
C0000040 flags
         Initialized Data
         (no align specified)
         Read Write

可见是位于.data中的。因为vs生成的这东西没有.bss,所以不完全像是他们所说,至少vs编译的c++程序,未初始化的全局变量不一定在.bss中。不过其实多个.bss也还不错,可能是没开优化的缘故?

其它的倒是很符合。全局变量在.data,局部变量跟着代码一起在.text中。

2、编译选项:Windows, x64, 优化全关闭(gcc 4.1)
跟vs的大同小异,只不过gcc生成的节是真的很多,挑一些重点发。

首先,全局变量,静态变量,跟之前一样。

SECTION HEADER #2
   .data name
     100 virtual size
    8000 virtual address (0000000000408000 to 00000000004080FF)
     200 size of raw data
    6E00 file pointer to raw data (00006E00 to 00006FFF)
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
C0500040 flags
         Initialized Data
         RESERVED - UNKNOWN
         RESERVED - UNKNOWN
         Read Write

RAW DATA #2
  0000000000408000: 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  0000000000408010: 44 33 22 11 DD CC BB AA

局部变量、函数也是一样

SECTION HEADER #1
   .text name
    67D0 virtual size
    1000 virtual address (0000000000401000 to 00000000004077CF)
    6800 size of raw data
     600 file pointer to raw data (00000600 to 00006DFF)
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
60500020 flags
         Code
         RESERVED - UNKNOWN
         RESERVED - UNKNOWN
         Execute Read

RAW DATA #1
  0000000000401500: 55 48 89 E5 48 83 EC 10 C7 45 FC 88 77 66 55 

剩余的,我看到了bss的存在!

SECTION HEADER #6
    .bss name
    1400 virtual size
    D000 virtual address (000000000040C000 to 000000000040D3FF)
       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
C0600080 flags
         Uninitialized Data
         RESERVED - UNKNOWN
         RESERVED - UNKNOWN
         Read Write

先看看使用这个之前没初始化过的变量的地方:

0:002> u image00000000_00400000+0x1533
image00000000_00400000+0x1533:
00000000`00401533 8b05db7a0000    mov     eax,dword ptr [image00000000_00400000+0x9014 (00000000`00409014)]
00000000`00401539 83c001          add     eax,1
00000000`0040153c 8905d27a0000    mov     dword ptr [image00000000_00400000+0x9014 (00000000`00409014)],eax
00000000`00401542 8b05cc7a0000    mov     eax,dword ptr [image00000000_00400000+0x9014 (00000000`00409014)]
00000000`00401548 8905f6ba0000    mov     dword ptr [image00000000_00400000+0xd044 (00000000`0040d044)],eax

这个倒是很符合:

static unsigned long s_B;
0:002> ?[poi[image00000000_00400000+0xd044]]
Evaluate expression: 0 = 00000000`00000000

static unsigned long s_A = 0xAABBCCDD;
0:002> ?[poi[image00000000_00400000+0x9014]]
Evaluate expression: 2864434397 = 00000000`aabbccdd

看吧,文件中预留的是0字节,只在启动后才从这里初始化一片0内存给它用,本意是减少(……节的描述都不止4字节了,浪费了更多,其实我觉得VS这里的做法反而是对的)文件大小,但是实际上如果没初始化的全局变量或者静态变量本身就不多的话,我觉得还不如并到.data节呢。

3、Linux (ARM) ,编译器GCC,无优化。

pi@BLASTN2 ~/projects/testSection/testSections/bin/Release :( $ objdump -h testSections 

testSections:     file format elf32-littlearm

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .interp       00000019  00008134  00008134  00000134  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .note.ABI-tag 00000020  00008150  00008150  00000150  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .note.gnu.build-id 00000024  00008170  00008170  00000170  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .hash         00000028  00008194  00008194  00000194  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .gnu.hash     00000024  000081bc  000081bc  000001bc  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .dynsym       00000050  000081e0  000081e0  000001e0  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .dynstr       00000077  00008230  00008230  00000230  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  7 .gnu.version  0000000a  000082a8  000082a8  000002a8  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  8 .gnu.version_r 00000020  000082b4  000082b4  000002b4  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  9 .rel.dyn      00000008  000082d4  000082d4  000002d4  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 10 .rel.plt      00000018  000082dc  000082dc  000002dc  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 11 .init         0000000a  000082f4  000082f4  000002f4  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 12 .plt          0000003c  00008300  00008300  00000300  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 13 .text         00000134  0000833c  0000833c  0000033c  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 14 .fini         00000006  00008470  00008470  00000470  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 15 .rodata       00000004  00008478  00008478  00000478  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 16 .ARM.exidx    00000008  0000847c  0000847c  0000047c  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 17 .eh_frame     00000004  00008484  00008484  00000484  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 18 .init_array   00000004  00010488  00010488  00000488  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 19 .fini_array   00000004  0001048c  0001048c  0000048c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 20 .jcr          00000004  00010490  00010490  00000490  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 21 .dynamic      00000108  00010494  00010494  00000494  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 22 .got          0000001c  0001059c  0001059c  0000059c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 23 .data         00000010  000105b8  000105b8  000005b8  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 24 .bss          0000000c  000105c8  000105c8  000005c8  2**2
                  ALLOC
 25 .comment      0000001d  00000000  00000000  000005c8  2**0
                  CONTENTS, READONLY
 26 .ARM.attributes 00000033  00000000  00000000  000005e5  2**0
                  CONTENTS, READONLY

可以看到也是有.bss节的,而且大小为0,看FileOffset可知.bss的起始大小是0x5c8,.comment也是0x5c8,所以.bss是一个字都没有占到,

        0    2    4    6      8    a    c    e
00005b0 8300 0000 0000 0000 | 0000 0000 0000 0000
00005c0 3344 1122 ccdd aabb | 4347 3a43 2820 6544

可见,它也是满足这个规律,也即全局变量放.data,没赋值的全局变量放.bss(只是占虚拟内存而已),代码和局部变量放.text。

对这俩静态变量的操作也是类似:
f1.png
f2.png

标签:none

添加新评论

captcha
请输入验证码