底层分析static变量

112 阅读5分钟

main.cpp

#include <bits/stdc++.h>
using namespace std;

int global_0;
int global_11 = 11;
int static global_static_0;
int static global_static_11  = 11;

void aaa()
{
    static int aaa_static = 4;
    aaa_static++;
    printf("aaa_static:%d\n",aaa_static);
}

int main()
{
    static int main_static = 5;
    aaa();
    printf("main_static:%d\n",main_static);
}

我们先 objdump -S ./a.out 分析一下.

image.png

可以看到,main执行的时候并没有去执行static int main_static = 5,这个已经放在数据段中了,执行mov 0x2e4d(%rip),%eax来得到main_static的值,然后printf.

再来看看add函数.

image.png 可以看到,也是没有去执行static int aaa_static = 4,而是直接去0x2e81(%rip)去取这个数据的值

执行 readelf -aW main.o 去分析一下这个.o文件吧.

节头:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        0000000000000000 000040 0000c6 00  AX  0   0  1
  [ 2] .rela.text        RELA            0000000000000000 001118 000168 18   I 13   1  8
  [ 3] .data             PROGBITS        0000000000000000 000108 000010 00  WA  0   0  4
  [ 4] .bss              NOBITS          0000000000000000 000118 00000c 00  WA  0   0  4
  [ 5] .rodata           PROGBITS        0000000000000000 000118 0000c7 00   A  0   0  8
  [ 6] .init_array       INIT_ARRAY      0000000000000000 0001e0 000008 08  WA  0   0  8
  [ 7] .rela.init_array  RELA            0000000000000000 001280 000018 18   I 13   6  8
  [ 8] .comment          PROGBITS        0000000000000000 0001e8 00002b 01  MS  0   0  1
  [ 9] .note.GNU-stack   PROGBITS        0000000000000000 000213 000000 00      0   0  1
  [10] .note.gnu.property NOTE           0000000000000000 000218 000020 00   A  0   0  8
  [11] .eh_frame         PROGBITS        0000000000000000 000238 000098 00   A  0   0  8
  [12] .rela.eh_frame    RELA            0000000000000000 001298 000060 18   I 13  11  8
  [13] .symtab           SYMTAB          0000000000000000 0002d0 0006d8 18     14  63  8
  [14] .strtab           STRTAB          0000000000000000 0009a8 00076d 00      0   0  1
  [15] .shstrtab         STRTAB          0000000000000000 0012f8 000085 00      0   0  1


Symbol table '.symtab' contains 73 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
    63: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    4 global_0
    52: 0000000000000008     4 OBJECT  LOCAL  DEFAULT    4 _ZL15global_static_0
    64: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    3 global_11
    53: 0000000000000004     4 OBJECT  LOCAL  DEFAULT    3 _ZL16global_static_11
    54: 0000000000000008     4 OBJECT  LOCAL  DEFAULT    3 _ZZ3aaavE10aaa_static
    55: 000000000000000c     4 OBJECT  LOCAL  DEFAULT    3 _ZZ4mainE11main_static
    65: 0000000000000000    51 FUNC    GLOBAL DEFAULT    1 _Z3aaav
    68: 0000000000000033    45 FUNC    GLOBAL DEFAULT    1 main
  • data:offset:0x108 , size:0x10
  • bss :offset:0x118 , size:0xc

我们要用hexdump -C main.o > hex0.S去分析.o文件:

00000100  9c ff ff ff 5d c3 00 00  0b 00 00 00 0b 00 00 00  |....]...........|
00000110  04 00 00 00 05 00 00 00  00 00 00 00 02 00 00 00  |................|
00000120  00 00 00 00 01 00 00 00  02 00 00 00 04 00 00 00  |................|

Ndx的3是.data,Ndx的4是.bss.

把上面那个符号表放这吧:

Symbol table '.symtab' contains 73 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
    63: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    4 global_0
    52: 0000000000000008     4 OBJECT  LOCAL  DEFAULT    4 _ZL15global_static_0
    64: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    3 global_11
    53: 0000000000000004     4 OBJECT  LOCAL  DEFAULT    3 _ZL16global_static_11
    54: 0000000000000008     4 OBJECT  LOCAL  DEFAULT    3 _ZZ3aaavE10aaa_static
    55: 000000000000000c     4 OBJECT  LOCAL  DEFAULT    3 _ZZ4mainE11main_static
    65: 0000000000000000    51 FUNC    GLOBAL DEFAULT    1 _Z3aaav
    68: 0000000000000033    45 FUNC    GLOBAL DEFAULT    1 main

.data section 如下:

  • global_11:0b 00 00 00,即0xb,即11
  • _ZL16global_static_11:0b 00 00 00,即0xb,即11
  • _ZZ3aaavE10aaa_static:04 00 00 00,即0x4,即4
  • _ZZ4mainE11main_static:05 00 00 00,即0x5,即5

.bss section 如下:

  • global_0
  • _ZL15global_static_0 所有的bss section都是0.