|
★ -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 <main>: push %ebp 0x80483f9 <main+1>: mov %esp,%ebp 0x80483fb <main+3>: push %ebx 0x80483fc <main+4>: call 0x8048401 <main+9> 0x8048401 <main+9>: pop %ebx//取得该指令的地址 0x8048402 <main+10>: add $0x1093,%ebx//此时ebx里面存放着是GOT表的地址 0x8048408 <main+16>: call 0x80483d0 <hi> 0x804840d <main+21>: xor %eax,%eax 0x804840f <main+23>: jmp 0x8048411 <main+25> 0x8048411 <main+25>: mov 0xfffffffc(%ebp),%ebx 0x8048414 <main+28>: leave 0x8048415 <main+29>: ret ... End of assembler dump. (gdb) disass hi Dump of assembler code for function hi: 0x80483d0 <hi>: push %ebp 0x80483d1 <hi+1>: mov %esp,%ebp 0x80483d3 <hi+3>: push %ebx 0x80483d4 <hi+4>: call 0x80483d9 <hi+9> 0x80483d9 <hi+9>: pop %ebx 0x80483da <hi+10>: add $0x10bb,%ebx 0x80483e0 <hi+16>: lea 0xffffefdc(%ebx),%edx 0x80483e6 <hi+22>: mov %edx,%eax 0x80483e8 <hi+24>: push %eax 0x80483e9 <hi+25>: call 0x8048308 <printf> 0x80483ee <hi+30>: add $0x4,%esp 0x80483f1 <hi+33>: mov 0xfffffffc(%ebp),%ebx 0x80483f4 <hi+36>: leave 0x80483f5 <hi+37>: ret 0x80483f6 <hi+38>: 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 +--------+ | ...... | (内存低址)
|