分享
 
 
 

gcc常用的编译选项对代码的影响

王朝c/c++·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

gcc常用的编译选项对代码的影响

本文出自:http://xfocus.org 作者:alert7

测试环境?redhat?6.2

★?前言

本文讨论gcc的一些常用编译选项对代码的影响。当然代码变了,

它的内存布局也就会变了,随之exploit也就要做相应的变动。

gcc的编译选项实在太多,本文检了几个最常用的选项。

★?演示程序

[alert7@redhat62?alert7]$?cat??test.c

#include?

void?hi(void)

{

printf("hi");

}

int?main(int?argc,?char?*argv[])

{

????????hi();

????????return?0;

}

★?一般情况

[alert7@redhat62?alert7]$?gcc?-o?test?test.c

[alert7@redhat62?alert7]$?wc?-c?test

??11773?test

[alert7@redhat62?alert7]$?gdb?-q?test

(gdb)?disass?main

Dump?of?assembler?code?for?function?main:

0x80483e4?:???????push???%ebp

0x80483e5?:?????mov????%esp,%ebp

0x80483e7?:?????call???0x80483d0?

0x80483ec?:?????xor????%eax,%eax

0x80483ee?:????jmp????0x80483f0?

0x80483f0?:????leave

0x80483f1?:????ret

....

End?of?assembler?dump.

(gdb)?disass?hi

Dump?of?assembler?code?for?function?hi:

0x80483d0?:????????push???%ebp

0x80483d1?:???????mov????%esp,%ebp

0x80483d3?:???????push???$0x8048450

0x80483d8?:???????call???0x8048308?

0x80483dd?:??????add????$0x4,%esp

0x80483e0?:??????leave

0x80483e1?:??????ret

0x80483e2?:??????mov????%esi,%esi

End?of?assembler?dump.

来看看部分的内存映象

???????????????????(内存高址)

??????????????????????????????+--------+

??????????????????????????????|bffffbc4|?argv的地址(即argv[0]的地址)

???????????????????0xbffffb84?+--------+

??????????????????????????????|00000001|?argc的值

???????????????????0xbffffb80?+--------+

??????????????????????????????|400309cb|main的返回地址

???????????????????0xbffffb7c?+--------+?

??????????????????????????????|bffffb98|?调用main函数前的ebp

???????????????????0xbffffb78?+--------+?

??????????????????????????????|080483ec|?hi()的返回地址

???????????????????0xbffffb74?+--------+

??????????????????????????????|bffffb78|?调用hi()前的esp

???????????????????0xbffffb70?+--------+?

??????????????????????????????|08048450|?"hi"的地址

???????????????????0xbffffb6c?+--------+?

??????????????????????????????|?......?|

???????????????????(内存低址)

leave????指令所做的操作相当于MOV?ESP,EBP?然后?POP?EBP?

ret????指令所做的操作相当于POP?EIP

★?-O?编译选项

With?`-O',?the?compiler?tries?to?reduce?code?size?and?execution?time.

When?you?specify?`-O',?the?two?options?`-fthread-jumps'?and?

`-fdefer-pop'?are?turned??on

优化,减少代码大小和执行的时间

[alert7@redhat62?alert7]$?gcc?-O?-o?test?test.c

[alert7@redhat62?alert7]$?wc?-c?test

??11757?test

[alert7@redhat62?alert7]$?gdb?-q?test

(gdb)?disass?main

Dump?of?assembler?code?for?function?main:

0x80483d8?:???????push???%ebp

0x80483d9?:?????mov????%esp,%ebp

0x80483db?:?????call???0x80483c8?

0x80483e0?:?????xor????%eax,%eax

0x80483e2?:????leave

0x80483e3?:????ret

0x80483e4?:????nop

...

End?of?assembler?dump.

(gdb)?disass?hi

Dump?of?assembler?code?for?function?hi:

0x80483c8?:????????push???%ebp

0x80483c9?:???????mov????%esp,%ebp

0x80483cb?:???????push???$0x8048440

0x80483d0?:???????call???0x8048308?

0x80483d5?:??????leave

0x80483d6?:??????ret

0x80483d7?:??????nop

End?of?assembler?dump.

在main()中,把一条jmp指令优化掉了,很显然,这条指令是可以不需要的。

在hi()中,把add????$0x4,%esp优化掉了,这会不会使stack不平衡呢?

来看看部分的内存映象

???????????????????(内存高址)

??????????????????????????????+--------+

??????????????????????????????|bffffbc4|?argv的地址(即argv[0]的地址)

???????????????????0xbffffb84?+--------+

??????????????????????????????|00000001|?argc的值

???????????????????0xbffffb80?+--------+

??????????????????????????????|400309cb|main的返回地址

???????????????????0xbffffb7c?+--------+?

??????????????????????????????|bffffb98|?调用main函数前的ebp

???????????????????0xbffffb78?+--------+?

??????????????????????????????|080483e0|?hi()的返回地址

???????????????????0xbffffb74?+--------+

??????????????????????????????|bffffb78|?调用hi()前的esp

???????????????????0xbffffb70?+--------+?

??????????????????????????????|08048440|?"hi"的地址

???????????????????0xbffffb6c?+--------+?

??????????????????????????????|?......?|

???????????????????(内存低址)

leave????指令所做的操作相当于把MOV?ESP,EBP?然后?POP?EBP??

看到leave指令操作了没有,先把ebp--esp,再pop?ebp,这样即使

在过程内堆栈的esp,ebp是不平衡的,但只要返回时候碰到leave指令

就会平衡了,所以把add????$0x4,%esp优化掉也是没有问题的。

★?-O2?编译选项

-O2????Optimize??even?more.??Nearly?all?supported?optimizations?that?do?

????not?involve?a?space-speed?tradeoff?are?performed.??Loop?unrolling

????and?function?inlining?are?not?done,?for?example.??As?compared?to?-O,

????????this?option?increases?both?compilation?time?and?the?performance?of

????the?generated?code.

[alert7@redhat62?alert7]$?gcc?-O2?-o?test?test.c

[alert7@redhat62?alert7]$?wc?-c?test

??11757?test

[alert7@redhat62?alert7]$?gdb?-q?test

(gdb)?disass?main

Dump?of?assembler?code?for?function?main:

0x80483d8?:???????push???%ebp

0x80483d9?:?????mov????%esp,%ebp

0x80483db?:?????call???0x80483c8?

0x80483e0?:?????xor????%eax,%eax

0x80483e2?:????leave

0x80483e3?:????ret

...

0x80483ef?:????nop

End?of?assembler?dump.

(gdb)?disass?hi

Dump?of?assembler?code?for?function?hi:

0x80483c8?:????????push???%ebp

0x80483c9?:???????mov????%esp,%ebp

0x80483cb?:???????push???$0x8048440

0x80483d0?:???????call???0x8048308?

0x80483d5?:??????leave

0x80483d6?:??????ret

0x80483d7?:??????nop

End?of?assembler?dump.

由于程序比较简单,再优化也没有好优化的了,所以跟-O出来的一样。

★?-fomit-frame-pointer?编译选项

-fomit-frame-pointer

??????????????Don't?keep?the?frame?pointer?in?a?register?for?functions?

??????????that?don't?need?one.??This?avoids?the??instructions?to?save,?

??????????set?up?and?restore?frame?pointers;?it?also?makes?an?extra?

??????????register?available?in?many?functions.??It?also?makes?

??????????debugging?impossible?on?most?machines.

忽略帧指针。这样在程序就不需要保存,安装,和恢复ebp了。这样ebp也就是一个

free的register了,在函数中就可以随便使用了。

[alert7@redhat62?alert7]$?gcc?-fomit-frame-pointer?-o?test?test.c

[alert7@redhat62?alert7]$?wc?-c?test

??11773?test

[alert7@redhat62?alert7]$?gdb?-q?test

(gdb)?disass?main

Dump?of?assembler?code?for?function?main:

0x80483e0?:???????call???0x80483d0?

0x80483e5?:?????xor????%eax,%eax

0x80483e7?:?????jmp????0x80483f0?

0x80483e9?:?????lea????0x0(%esi,1),%esi

0x80483f0?:????ret

....

End?of?assembler?dump.

(gdb)?disass?hi

Dump?of?assembler?code?for?function?hi:

0x80483d0?:????????push???$0x8048450

0x80483d5?:???????call???0x8048308?

0x80483da?:??????add????$0x4,%esp

0x80483dd?:??????ret

0x80483de?:??????mov????%esi,%esi

End?of?assembler?dump.

在main()和hi()中都去掉了以下指令

push???%ebp

mov????%esp,%ebp//这两条指令安装

leave//这条指令恢复

来看看部分的内存映象

???????????????????(内存高址)

??????????????????????????????+--------+

??????????????????????????????|bffffbc4|?argv的地址(即argv[0]的地址)

???????????????????0xbffffb84?+--------+

??????????????????????????????|00000001|?argc的值

???????????????????0xbffffb80?+--------+

??????????????????????????????|400309cb|main的返回地址

???????????????????0xbffffb7c?+--------+?

??????????????????????????????|080483e5|?hi()的返回地址

???????????????????0xbffffb78?+--------+

??????????????????????????????|08048450|??"hi"字符串的地址

???????????????????0xbffffb74?+--------+?

??????????????????????????????|?......?|

???????????????????(内存低址)

没有保存上层执行环境的ebp.

★?-fomit-frame-pointer?&&?-O2?

-fomit-frame-pointer编译选项去掉了

push???%ebp

mov????%esp,%ebp//这两条指令安装

leave//这条指令恢复

-O2编译选项去掉了

add????$0x4,%esp

两个加起来会不会这四条指令一起去掉,从而使stack不平衡呢?

[alert7@redhat62?alert7]$?gcc?-fomit-frame-pointer?-O2?-o?test?test.c

[alert7@redhat62?alert7]$?wc?-c?test

??11741?test

[alert7@redhat62?alert7]$?gdb?-q?test

(gdb)?disass?main

Dump?of?assembler?code?for?function?main:

0x80483d8?:???????call???0x80483c8?

0x80483dd?:?????xor????%eax,%eax

0x80483df?:?????ret

End?of?assembler?dump.

(gdb)?disass?hi

Dump?of?assembler?code?for?function?hi:

0x80483c8?:????????push???$0x8048430

0x80483cd?:???????call???0x8048308?

0x80483d2?:??????add????$0x4,%esp

0x80483d5?:??????ret

0x80483d6?:??????mov????%esi,%esi

End?of?assembler?dump.

来看看部分的内存映象

???????????????????(内存高址)

??????????????????????????????+--------+

??????????????????????????????|bffffbc4|?argv的地址(即argv[0]的地址)

???????????????????0xbffffb84?+--------+

??????????????????????????????|00000001|?argc的值

???????????????????0xbffffb80?+--------+

??????????????????????????????|400309cb|main的返回地址

???????????????????0xbffffb7c?+--------+?

??????????????????????????????|080483dd|?hi()的返回地址

???????????????????0xbffffb78?+--------+

??????????????????????????????|08048430|??"hi"字符串的地址

???????????????????0xbffffb74?+--------+?

??????????????????????????????|?......?|

???????????????????(内存低址)

此时就没有把add????$0x4,%esp优化掉,如果优化掉的话,整个stack就

会变的不平衡,从而会导致程序出错。

★?-fPIC?编译选项

-fPIC????If??supported?for?the?target?machine,?emit?position-independent

????code,?suitable?for?dynamic?linking,even?if?branches?need?large?

????displacements.

产生位置无关代码(PIC),一般创建共享库时用到。

在x86上,PIC的代码的符号引用都是通过ebx进行操作的。

[alert7@redhat62?alert7]$?gcc?-fPIC?-o?test?test.c

[alert7@redhat62?alert7]$?wc?-c?test

??11805?test

[alert7@redhat62?alert7]$?gdb?-q?test

(gdb)?disass?main

Dump?of?assembler?code?for?function?main:

0x80483f8?:???????push???%ebp

0x80483f9?:?????mov????%esp,%ebp

0x80483fb?:?????push???%ebx

0x80483fc?:?????call???0x8048401?

0x8048401?:?????pop????%ebx//取得该指令的地址

0x8048402?:????add????$0x1093,%ebx//此时ebx里面存放着是GOT表的地址

0x8048408?:????call???0x80483d0?

0x804840d?:????xor????%eax,%eax

0x804840f?:????jmp????0x8048411?

0x8048411?:????mov????0xfffffffc(%ebp),%ebx

0x8048414?:????leave

0x8048415?:????ret

...

End?of?assembler?dump.

(gdb)?disass?hi

Dump?of?assembler?code?for?function?hi:

0x80483d0?:????????push???%ebp

0x80483d1?:???????mov????%esp,%ebp

0x80483d3?:???????push???%ebx

0x80483d4?:???????call???0x80483d9?

0x80483d9?:???????pop????%ebx

0x80483da?:??????add????$0x10bb,%ebx

0x80483e0?:??????lea????0xffffefdc(%ebx),%edx

0x80483e6?:??????mov????%edx,%eax

0x80483e8?:??????push???%eax

0x80483e9?:??????call???0x8048308?

0x80483ee?:??????add????$0x4,%esp

0x80483f1?:??????mov????0xfffffffc(%ebp),%ebx

0x80483f4?:??????leave

0x80483f5?:??????ret

0x80483f6?:??????mov????%esi,%esi

End?of?assembler?dump.

来看看部分的内存映象

??

????(内存高址)

??????????????+--------+

??????????????|bffffbc4|?argv的地址(即argv[0]的地址)

???0xbffffb84?+--------+

??????????????|00000001|?argc的值

???0xbffffb80?+--------+

??????????????|400309cb|main的返回地址

???0xbffffb7c?+--------+?

??????????????|bffffb98|?调用main函数前的ebp

???0xbffffb78?+--------+?

??????????????|401081ec|?保存的ebx

???0xbffffb74?+--------+

??????????????|0804840d|?(存放过call?0x8048401的下一条指令地址)

???0xbffffb70?+--------+?

??????????????|bffffb78|?调用hi()前的esp

???0xbffffb6c?+--------+?

??????????????|08049494|?GOT表地址

???0xbffffb68?+--------+?

??????????????|08048470|(存放过call?0x80483d9的下一条指令地址)?

???0xbffffb64?+--------+?

??????????????|?......?|

?????(内存低址)

★?-static?编译选项

-static

????On?systems?that?support?dynamic?linking,?this?prevents?

????linking?with?the?shared?libraries.??On?other??systems,?

????this?option?has?no?effect.

把一些函数都静态的编译到程序中,而无需动态链接了。

[alert7@redhat62?alert7]$?gcc?-o?test?-static?test.c

[alert7@redhat62?alert7]$?wc?-c?test

962808?test

[alert7@redhat62?alert7]$?gdb?-q?test

(gdb)?disass?main

Dump?of?assembler?code?for?function?main:

0x80481b4?:???????push???%ebp

0x80481b5?:?????mov????%esp,%ebp

0x80481b7?:?????call???0x80481a0?

0x80481bc?:?????xor????%eax,%eax

0x80481be?:????jmp????0x80481c0?

0x80481c0?:????leave

0x80481c1?:????ret

...

End?of?assembler?dump.

(gdb)?disass?hi

Dump?of?assembler?code?for?function?hi:

0x80481a0?:????????push???%ebp

0x80481a1?:???????mov????%esp,%ebp

0x80481a3?:???????push???$0x8071528

0x80481a8?:???????call???0x804865c?

0x80481ad?:??????add????$0x4,%esp

0x80481b0?:??????leave

0x80481b1?:??????ret

0x80481b2?:??????mov????%esi,%esi

End?of?assembler?dump.

[alert7@redhat62?alert7]$?ldd?test

????????not?a?dynamic?executable

-static出来的代码已经没有PLT了,GOT虽然有,已经全部为0了。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有