代码之家  ›  专栏  ›  技术社区  ›  Frank

对于静态大小的数组,堆栈保护的预期行为是什么?

  •  8
  • Frank  · 技术社区  · 6 年前

    如果我在ubuntu16.04/gcc7.3中编译以下内容

    struct VecA {
      float data[4];
    };
    
    struct VecB {
      float x;
      float y;
      float z;
      float w;
    };
    
    // Requires stack protection
    VecA getA() {return {1.0f, 1.0f, 1.0f, 1.0f};}
    
    // Does not require stack protection
    VecB getB() {return {1.0f, 1.0f, 1.0f, 1.0f};}
    

    像这样:

    g++ -O3 -c -o result test.cpp
    objdump -d result
    

    我得到:

    0000000000000000 <_Z4getAv>:
       0:   48 83 ec 18             sub    $0x18,%rsp
       4:   64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
       b:   00 00 
       d:   48 89 44 24 08          mov    %rax,0x8(%rsp)
      12:   31 c0                   xor    %eax,%eax
      14:   f3 0f 7e 05 00 00 00    movq   0x0(%rip),%xmm0        # 1c <_Z4getAv+0x1c>
      1b:   00 
      1c:   48 8b 44 24 08          mov    0x8(%rsp),%rax
      21:   64 48 33 04 25 28 00    xor    %fs:0x28,%rax
      28:   00 00 
      2a:   75 09                   jne    35 <_Z4getAv+0x35>
      2c:   66 0f 6f c8             movdqa %xmm0,%xmm1
      30:   48 83 c4 18             add    $0x18,%rsp
      34:   c3                      retq   
      35:   e8 00 00 00 00          callq  3a <_Z4getAv+0x3a>
      3a:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)
    
    0000000000000040 <_Z4getBv>:
      40:   f3 0f 7e 05 00 00 00    movq   0x0(%rip),%xmm0        # 48 <_Z4getBv+0x8>
      47:   00 
      48:   66 0f 6f c8             movdqa %xmm0,%xmm1
      4c:   c3                      retq 
    

    哪个“看起来”像linux堆栈保护正在应用于 VecA . 有点防御性,但我能理解编译器是如何得出这个结论的。

    然而,这正是我困惑的地方:

    我无法复制这个godbolt.org网站,即使堆栈保护显式打开。我可以让这两种功能都实现 -fstack-protector-all

    https://gcc.godbolt.org/z/ePR98P

    而且,在我的系统上,显式使用堆栈保护器似乎是从 getA()

    g++ -O3 -c -o -fstack-protector result test.cpp
    objdump -d result
    
    0000000000000000 <_Z4getAv>:
       0:   f3 0f 7e 05 00 00 00    movq   0x0(%rip),%xmm0        # 8 <_Z4getAv+0x8>
       7:   00 
       8:   66 0f 6f c8             movdqa %xmm0,%xmm1
       c:   c3                      retq   
       d:   0f 1f 00                nopl   (%rax)
    
    0000000000000010 <_Z4getBv>:
      10:   f3 0f 7e 05 00 00 00    movq   0x0(%rip),%xmm0        # 18 <_Z4getBv+0x8>
      17:   00 
      18:   66 0f 6f c8             movdqa %xmm0,%xmm1
      1c:   c3                      retq   
    

    1. 我的系统行为背后有合理的解释吗?尤其是关于 -fstack-protector 拆卸保护装置。

    2. 有理由断言这两个函数都应该在优化的代码中生成等价的程序集?

    编辑

    完整版本字符串:

    g++ --version
    g++ (Ubuntu 7.3.0-21ubuntu1~16.04) 7.3.0
    Copyright (C) 2017 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    
    1 回复  |  直到 6 年前
        1
  •  12
  •   Peter Cordes    6 年前

    Ubuntu的gcc的默认值是 -fstack-protector-strong ,不是 -fstack-protector-all . ( The gcc manual lists available options ).

    https://lwn.net/Articles/584225/

    On Godbolt g++ -S -masm=intel -O3 获取英特尔语法,或 objdump -drwC -Mintel

    你可以用 g++ -S -fverbose-asm -O3 foo.cpp 包括注释,显示gcc在编译时使用的所有隐含和显式选项。在Godbolt上,取消选中 // 不隐藏asm注释的图标, like this .

    # GNU C++14 (GCC-Explorer-Build) version 7.3.0 (x86_64-linux-gnu)
    #       compiled by GNU C version 5.4.0 20160609, GMP version 6.1.0, MPFR version 3.1.4, MPC version 1.0.3, isl version isl-0.16.1-GMP
    
    # GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
    # options passed:  -fdiagnostics-color=always -imultiarch x86_64-linux-gnu
    # -iprefix /opt/compiler-explorer/gcc-7.3.0/bin/../lib/gcc/x86_64-linux-gnu/7.3.0/
    # -D_GNU_SOURCE
    # /tmp/compiler-explorer-compiler11885-54-1u26why.tdoy/example.cpp
    # -masm=intel -mtune=generic -march=x86-64
    # -auxbase-strip /tmp/compiler-explorer-compiler11885-54-1u26why.tdoy/output.s
    # -g -O3 -std=gnu++14 -fstack-protector-strong -fverbose-asm
    # options enabled:  -faggressive-loop-optimizations -falign-labels
    # -fasynchronous-unwind-tables -fauto-inc-dec -fbranch-count-reg
    # -fcaller-saves -fchkp-check-incomplete-type -fchkp-check-read
    # -fchkp-check-write -fchkp-instrument-calls -fchkp-narrow-bounds
    # -fchkp-optimize -fchkp-store-bounds -fchkp-use-static-bounds
    # -fchkp-use-static-const-bounds -fchkp-use-wrappers -fcode-hoisting
    # -fcombine-stack-adjustments -fcommon -fcompare-elim -fcprop-registers
    # -fcrossjumping -fcse-follow-jumps -fdefer-pop
    ...