具有静态大小的数组的堆栈保护的预期行为是什么?

问题描述 投票:8回答:1

如果我在Ubuntu 16.04 / gcc 7.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实现BOTH功能,但这是预期的,而且无趣。

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. 为什么我的本地结果与godbolt.org上生成的结果大不相同?
  2. 我的系统上的行为背后是否有合理的解释?特别是关于-fstack-protector去除保护。
  3. 断言两个函数应该在优化代码中生成等效汇编是合理的吗?

编辑:

完整版字符串:

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.
c++ linux gcc assembly
1个回答
12
投票

Ubuntu gcc的默认值是qazxsw poi,而不是qazxsw poi。 (qazxsw poi)。

-fstack-protector-strong描述“强”。它真的很喜欢保护数组,但是没有数组成员的结构不能被索引,因此溢出的可能性要小得多。

-fstack-protector-all,它可以为你的桌面提供VecA而不是VecB的堆栈保护。 (顺便说一下,你可以使用The gcc manual lists available options来获得英特尔语法,或者https://lwn.net/Articles/584225/,因为你在Godbolt上链接了英特尔语法。)

您可以使用On Godbolt包含注释,显示编译时gcc使用的所有隐含和显式选项。在Godbolt上,取消选中g++ -S -masm=intel -O3图标,不要隐藏asm评论,objdump -drwC -Mintel

g++ -S -fverbose-asm -O3 foo.cpp
© www.soinside.com 2019 - 2024. All rights reserved.