0x80483e5
0x80483e7
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
0x80483ec
0x80483ee
0x80483f0
0x80483f1
....
End of assembler dump.
(gdb) disass hi
Dump of assembler code for function hi:
0x80483d0
: push %ebp
0x80483d1
0x80483d1
: mov %esp,%ebp
0x80483d30x80483d3
: push $0x8048450
0x80483d80x80483d8
: call 0x8048308
0x80483dd 0x80483dd
: add $0x4,%esp
0x80483e0
0x80483e0
: leave
0x80483e10x80483e1
: ret
0x80483e20x80483e2
: mov %esi,%esi
End of assembler dump.
來看看部分的內存映象
(內存高址)
+--------+
|bffffbc4| argv的地址(即argv[0]的地址)
0xbffffb84 +--------+
|00000001| argc的值
0xbffffb80 +--------+
|400309cb|main的返回地址
0xbffffb7c +--------+ <-- 調用main函數前的esp
|bffffb98| 調用main函數前的ebp
0xbffffb78 +--------+ <-- main函數的ebp
|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 End of assembler dump.
來看看部分的內存映象
(內存高址)
+--------+
|bffffbc4| argv的地址(即argv[0]的地址)
0xbffffb84 +--------+
|00000001| argc的值
0xbffffb80 +--------+
|400309cb|main的返回地址
0xbffffb7c +--------+ <-- 調用main函數前的esp
|bffffb98| 調用main函數前的ebp
0xbffffb78 +--------+ <-- main函數的ebp
|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
0x80483d9
0x80483db
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
0x80483e0
0x80483e2
0x80483e3
0x80483e4
...
End of assembler dump.
(gdb) disass hi
Dump of assembler code for function hi:
0x80483c8
: push %ebp
0x80483c9
0x80483c9
: mov %esp,%ebp
0x80483cb0x80483cb
: push $0x8048440
0x80483d00x80483d0
: call 0x8048308
0x80483d5 0x80483d5
: leave
0x80483d6
0x80483d6
: ret
0x80483d70x80483d7
: nop
End of assembler dump.
在main()中,把一條jmp指令優化掉了,很顯然,這條指令是可以不需要的。
在hi()中,把add $0x4,%esp優化掉了,這會不會使stack不平衡呢?
來看看部分的內存映象
(內存高址)
+--------+
|bffffbc4| argv的地址(即argv[0]的地址)
0xbffffb84 +--------+
|00000001| argc的值
0xbffffb80 +--------+
|400309cb|main的返回地址
0xbffffb7c +--------+ <-- 調用main函數前的esp
|bffffb98| 調用main函數前的ebp
0xbffffb78 +--------+ <-- main函數的ebp
|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 End of assembler dump.
在main()中,把一條jmp指令優化掉了,很顯然,這條指令是可以不需要的。
在hi()中,把add $0x4,%esp優化掉了,這會不會使stack不平衡呢?
來看看部分的內存映象
(內存高址)
+--------+
|bffffbc4| argv的地址(即argv[0]的地址)
0xbffffb84 +--------+
|00000001| argc的值
0xbffffb80 +--------+
|400309cb|main的返回地址
0xbffffb7c +--------+ <-- 調用main函數前的esp
|bffffb98| 調用main函數前的ebp
0xbffffb78 +--------+ <-- main函數的ebp
|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
0x80483d9
0x80483db
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
0x80483e0
0x80483e2
0x80483e3
...
0x80483ef
End of assembler dump.
(gdb) disass hi
Dump of assembler code for function hi:
0x80483c8
: push %ebp
0x80483c9
0x80483c9
: mov %esp,%ebp
0x80483cb0x80483cb
: push $0x8048440
0x80483d00x80483d0
: call 0x8048308
0x80483d5 0x80483d5
: leave
0x80483d6
0x80483d6
: ret
0x80483d70x80483d7
: 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 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
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
0x80483e5
0x80483e7
0x80483e9
0x80483f0
....
End of assembler dump.
(gdb) disass hi
Dump of assembler code for function hi:
0x80483d0
: push $0x8048450
0x80483d5
0x80483d5
: call 0x8048308
0x80483da 0x80483da
: add $0x4,%esp
0x80483dd
0x80483dd
: ret
0x80483de0x80483de
: 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 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
0x80483dd: xor %eax,%eax
0x80483df: ret
End of assembler dump.
(gdb) disass hi
Dump of assembler code for function hi:
0x80483c8
0x80483dd
0x80483df
End of assembler dump.
(gdb) disass hi
Dump of assembler code for function hi:
0x80483c8
: push $0x8048430
0x80483cd
0x80483cd
: call 0x8048308
0x80483d2 0x80483d2
: add $0x4,%esp
0x80483d5
0x80483d5
: ret
0x80483d60x80483d6
: 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 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
0x80483f9
0x80483fb
0x80483fc
0x8048401
0x8048402
0x8048408
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
0x804840d
0x804840f
0x8048411
0x8048414
0x8048415
...
End of assembler dump.
(gdb) disass hi
Dump of assembler code for function hi:
0x80483d0
: push %ebp
0x80483d1
0x80483d1
: mov %esp,%ebp
0x80483d30x80483d3
: push %ebx
0x80483d40x80483d4
: call 0x80483d9
0x80483d90x80483d9
: pop %ebx
0x80483da0x80483da
: add $0x10bb,%ebx
0x80483e00x80483e0
: lea 0xffffefdc(%ebx),%edx
0x80483e60x80483e6
: mov %edx,%eax
0x80483e80x80483e8
: push %eax
0x80483e90x80483e9
: call 0x8048308
0x80483ee 0x80483ee
: add $0x4,%esp
0x80483f1
0x80483f1
: mov 0xfffffffc(%ebp),%ebx
0x80483f40x80483f4
: leave
0x80483f50x80483f5
: ret
0x80483f60x80483f6
: mov %esi,%esi
End of assembler dump.
來看看部分的內存映象
(內存高址)
+--------+
|bffffbc4| argv的地址(即argv[0]的地址)
0xbffffb84 +--------+
|00000001| argc的值
0xbffffb80 +--------+
|400309cb|main的返回地址
0xbffffb7c +--------+ <-- 調用main函數前的esp
|bffffb98| 調用main函數前的ebp
0xbffffb78 +--------+ <-- main函數的ebp
|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 End of assembler dump.
來看看部分的內存映象
(內存高址)
+--------+
|bffffbc4| argv的地址(即argv[0]的地址)
0xbffffb84 +--------+
|00000001| argc的值
0xbffffb80 +--------+
|400309cb|main的返回地址
0xbffffb7c +--------+ <-- 調用main函數前的esp
|bffffb98| 調用main函數前的ebp
0xbffffb78 +--------+ <-- main函數的ebp
|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
0x80481b5
0x80481b7
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
0x80481bc
0x80481be
0x80481c0
0x80481c1
...
End of assembler dump.
(gdb) disass hi
Dump of assembler code for function hi:
0x80481a0
: push %ebp
0x80481a1
0x80481a1
: mov %esp,%ebp
0x80481a30x80481a3
: push $0x8071528
0x80481a80x80481a8
: call 0x804865c
0x80481ad 0x80481ad
: add $0x4,%esp
0x80481b0
0x80481b0
: leave
0x80481b10x80481b1
: ret
0x80481b20x80481b2
: mov %esi,%esi
End of assembler dump.
[alert7@redhat62 alert7]$ ldd test
not a dynamic executable
-static出來的代碼已經沒有PLT了,GOT雖然有,已經全部為0了。
End of assembler dump.
[alert7@redhat62 alert7]$ ldd test
not a dynamic executable
-static出來的代碼已經沒有PLT了,GOT雖然有,已經全部為0了。