Каково ожидаемое поведение защиты стека с массивами статического размера? - PullRequest
0 голосов
/ 05 сентября 2018

Если я скомпилирую следующее в 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, но это ожидаемо и неинтересно.

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.

1 Ответ

0 голосов
/ 05 сентября 2018

Значение по умолчанию для gcc в Ubuntu: -fstack-protector-strong, а не -fstack-protector-all. ( В руководстве по gcc перечислены доступные опции ).

https://lwn.net/Articles/584225/ описывает «сильный». Ему действительно нравится защищать массивы, но структуры без элементов массива не могут быть проиндексированы, поэтому вероятность переполнения гораздо меньше.

На Godbolt , который обеспечивает защиту стека для VecA, но не VecB, как на вашем рабочем столе. (И кстати, вы можете использовать g++ -S -masm=intel -O3 для получения Intel-синтаксиса или objdump -drwC -Mintel, так как вы связались с Intel-синтаксисом на Godbolt.)

Вы можете использовать g++ -S -fverbose-asm -O3 foo.cpp для включения комментариев, показывающих все подразумеваемые и явные параметры gcc, используемые при компиляции. На Godbolt снимите флажок //, чтобы не скрывать комментарии asm, вот так .

# 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
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...