C ++符号分析:如何确定执行哪个静态初始化?

时间:2016-08-25 09:41:24

标签: c++ gcc linker static-initialization

我想分析导致我在Linux上由GCC(v.6.1.1)编译的共享C ++库的庞大大小的原因。

readelf -sW libfoo.so告诉我,这是一个特别重要的函数__static_initialization_and_destruction_0,例如:

000000000026c420 10272 FUNC    LOCAL  DEFAULT   12 __static_initialization_and_destruction_0(int, int) [clone .constprop.1774]

我将-Wl,-Map,foo.map添加到CXX标志以生成链接器映射文件。 在该地图文件中查找0x000000000026c420会产生:

.text.startup  0x000000000026c420     0x2825 CMakeFiles/foo.dir/bar.cpp.o

所以现在我知道bar.cpp是导致静态初始化的转换单元,但是所述文件不包含任何static个变量。但是,它包含许多标题。

如何准确找出哪些变量在这些函数中被静态初始化?

1 个答案:

答案 0 :(得分:2)

使用以下命令编译程序: -g3 -Wa,-adhln

您将获得包含源代码的汇编代码。 在汇编代码中你会找到类似的东西:

_Z41__static_initialization_and_destruction_0ii:

在下一次返回(ret)之前,会在那里提及定义静态变量的代码的所有部分。

示例

来源:

struct Foo {
    Foo() {}
};

static Foo a;
static Foo b;

编译:

g++ text.cpp -c -O0 -g3 -Wa,-ahln > out.txt

大会:

35              _Z41__static_initialization_and_destruction_0ii:
36                  .LFB3:
3:text.cpp      **** };
4:text.cpp      **** 
5:text.cpp      **** static Foo a;
6:text.cpp      **** static Foo b;
37                      .loc 1 6 0
38                      .cfi_startproc
39 0000 55              pushq   %rbp
40                      .cfi_def_cfa_offset 16
41                      .cfi_offset 6, -16
42 0001 4889E5          movq    %rsp, %rbp
43                      .cfi_def_cfa_register 6
44 0004 4883EC10        subq    $16, %rsp
45 0008 897DFC          movl    %edi, -4(%rbp)
46 000b 8975F8          movl    %esi, -8(%rbp)
47                      .loc 1 6 0
48 000e 837DFC01        cmpl    $1, -4(%rbp)
49 0012 751D            jne .L4
50                      .loc 1 6 0 is_stmt 0 discriminator 1
51 0014 817DF8FF        cmpl    $65535, -8(%rbp)
51      FF0000
52 001b 7514            jne .L4
5:text.cpp      **** struct Foo {
    Foo() {}
};

static Foo a;
static Foo b;

53                      .loc 1 5 0 is_stmt 1 discriminator 3
54 001d BF000000        movl    $_ZL1a, %edi
54      00
55 0022 E8000000        call    _ZN3FooC1Ev
55      00
56                      .loc 1 6 0 discriminator 3
57 0027 BF000000        movl    $_ZL1b, %edi
57      00
58 002c E8000000        call    _ZN3FooC1Ev
58      00
59                  .L4:
60                      .loc 1 6 0 is_stmt 0
61 0031 90              nop
62 0032 C9              leave
63                      .cfi_def_cfa 7, 8
64 0033 C3              ret
65                      .cfi_endproc

这两个

54 001d BF000000        movl    $_ZL1a, %edi
57 0027 BF000000        movl    $_ZL1b, %edi

是你的静态变量。使用 c ++ filt ,您可以获得正确的变量名称。

构造函数:

call    _ZN3FooC1Ev