记录-fpic
参数作用及对执行效率的影响
动态链接执行很复杂,比静态链接执行时间长
但是,极大的节省了size
,PIC
和动态链接技术是计算机发展史上非常重要的一个里程碑
gcc 参数
相关参数可以使用man gcc
查看具体解释
-fpic
,该选项用于生成位置无关代码 (Position-Independent Code),尤其被用于共享库的创建。使用该选项编译出的代码在访问所有常量地址时,会通过全局偏移表GOT
进行计算得到。动态加载器将会在目标程序启动的时候解析GOT
的入口(动态加载器不是GCC
的一部分,其属于操作系统的一部分)。如果对于需要进行链接的可执行程序来说, 使用的GOT
大小超过了machine-specific
值指定的最大大小,你将会得到一条来自链接器的错误信息,以表明-fpic
无法正常工作;在这种情况下,会使用-fPIC
选项再重新编译一次。(这个最大大小限制在SPARC
上为8k
,在m68k
和RS/6000
上为32k
,而在x86
上没有限制)-fPIC
,可以避免全局偏移表大小限制的问题外,其它方面和上面的一样-shared
,从GCC
来看,shared
应该是包含-fPIC
选项的,但似乎不是所以系统都支持,所以最好显式加上-fPIC
选项
产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行
如果不加-fPIC
, 则加载.so
文件的代码段时,代码段引用的数据对象需要重定位,重定位会修改代码段的内容,这就造成每个使用这个.so
文件代码段的进程在内核里都会生成这个.so
文件代码段的copy
. 每个copy
都不一样,取决于这个.so
文件代码段和数据段内存映射的位置
不加-fPIC
编译出来的so
, 是要再加载时根据加载到的位置再次重定位的。(因为它里面的代码并不是位置无关代码)
代码
non-PIC
与PIC
代码的区别主要在于access global data
, jump label
的不同
GOT
是data section
, 是一个table
, 除专用的几个entry
,每个`entry 的内容可以再执行的时候修改PLT
是text section
, 是一段一段的code
,执行中不需要修改
access global data
non-pic
:ld r3, var1
pic
:ld r3, var1-offset@GOT
.
从GOT
表的index
为var1-offset
的地方处指示的地址处装载一个值,即var1-offset@GOT
处的 4 个byte
其实就是var1
的地址。这个地址只有在运行的时候才知道,是由dynamic-loader(ld-linux.so)
填进去的
jump label
non-pic
:jump printf
. 调用printf
pic
:jump printf-offset@GOT
.
跳到GOT
表的index
为printf-offset
的地方处指示的地址去执行。这个地址处的代码摆放在.plt section
每个外部函数对应一段这样的代码,其功能是呼叫dynamic-loader(ld-linux.so)
来查找函数的地址(本例中是printf
),然后将其地址写到GOT
表的index
为printf-offset
的地方,同时执行这个函数。这样,第 2 次呼叫printf
的时候,就会直接跳到printf
的地址,而不必再查找了。
Example
$ objdump -xa airkiss
airkiss: 文件格式 elf64-x86-64
airkiss
体系结构:i386:x86-64, 标志 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
起始地址 0x0000000000001b80
程序头:
PHDR off 0x0000000000000040 vaddr 0x0000000000000040 paddr 0x0000000000000040 align 2**3
filesz 0x00000000000001f8 memsz 0x00000000000001f8 flags r--
INTERP off 0x0000000000000238 vaddr 0x0000000000000238 paddr 0x0000000000000238 align 2**0
filesz 0x000000000000001c memsz 0x000000000000001c flags r--
LOAD off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**21
filesz 0x000000000000bc70 memsz 0x000000000000bc70 flags r-x
LOAD off 0x000000000000cb70 vaddr 0x000000000020cb70 paddr 0x000000000020cb70 align 2**21
filesz 0x00000000000008c8 memsz 0x0000000000000cf8 flags rw-
DYNAMIC off 0x000000000000cba0 vaddr 0x000000000020cba0 paddr 0x000000000020cba0 align 2**3
filesz 0x0000000000000200 memsz 0x0000000000000200 flags rw-
NOTE off 0x0000000000000254 vaddr 0x0000000000000254 paddr 0x0000000000000254 align 2**2
filesz 0x0000000000000044 memsz 0x0000000000000044 flags r--
EH_FRAME off 0x000000000000accc vaddr 0x000000000000accc paddr 0x000000000000accc align 2**2
filesz 0x000000000000031c memsz 0x000000000000031c flags r--
STACK off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4
filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-
RELRO off 0x000000000000cb70 vaddr 0x000000000020cb70 paddr 0x000000000020cb70 align 2**0
filesz 0x0000000000000490 memsz 0x0000000000000490 flags r--
动态节:
NEEDED libiw.so.30
NEEDED libc.so.6
INIT 0x0000000000001738
FINI 0x0000000000009390
INIT_ARRAY 0x000000000020cb70
INIT_ARRAYSZ 0x0000000000000008
FINI_ARRAY 0x000000000020cb78
FINI_ARRAYSZ 0x0000000000000008
GNU_HASH 0x0000000000000298
STRTAB 0x0000000000000a28
SYMTAB 0x00000000000002d8
STRSZ 0x00000000000002f2
SYMENT 0x0000000000000018
DEBUG 0x0000000000000000
PLTGOT 0x000000000020cda0
PLTRELSZ 0x0000000000000618
PLTREL 0x0000000000000007
JMPREL 0x0000000000001120
RELA 0x0000000000000e08
RELASZ 0x0000000000000318
RELAENT 0x0000000000000018
FLAGS 0x0000000000000008
FLAGS_1 0x0000000008000001
VERNEED 0x0000000000000db8
VERNEEDNUM 0x0000000000000001
VERSYM 0x0000000000000d1a
RELACOUNT 0x0000000000000016
版本引用:
required from libc.so.6:
0x0d696917 0x00 05 GLIBC_2.7
0x06969194 0x00 04 GLIBC_2.14
0x0d696914 0x00 03 GLIBC_2.4
0x09691a75 0x00 02 GLIBC_2.2.5
节:
Idx Name Size VMA LMA File off Algn
0 .interp 0000001c 0000000000000238 0000000000000238 00000238 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.ABI-tag 00000020 0000000000000254 0000000000000254 00000254 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .note.gnu.build-id 00000024 0000000000000274 0000000000000274 00000274 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .gnu.hash 00000040 0000000000000298 0000000000000298 00000298 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .dynsym 00000750 00000000000002d8 00000000000002d8 000002d8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .dynstr 000002f2 0000000000000a28 0000000000000a28 00000a28 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .gnu.version 0000009c 0000000000000d1a 0000000000000d1a 00000d1a 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .gnu.version_r 00000050 0000000000000db8 0000000000000db8 00000db8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .rela.dyn 00000318 0000000000000e08 0000000000000e08 00000e08 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .rela.plt 00000618 0000000000001120 0000000000001120 00001120 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
10 .init 00000017 0000000000001738 0000000000001738 00001738 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
11 .plt 00000420 0000000000001750 0000000000001750 00001750 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .plt.got 00000008 0000000000001b70 0000000000001b70 00001b70 2**3
CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .text 00007810 0000000000001b80 0000000000001b80 00001b80 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
14 .fini 00000009 0000000000009390 0000000000009390 00009390 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
15 .rodata 0000192a 00000000000093a0 00000000000093a0 000093a0 2**5
CONTENTS, ALLOC, LOAD, READONLY, DATA
16 .eh_frame_hdr 0000031c 000000000000accc 000000000000accc 0000accc 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
17 .eh_frame 00000c88 000000000000afe8 000000000000afe8 0000afe8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
18 .init_array 00000008 000000000020cb70 000000000020cb70 0000cb70 2**3
CONTENTS, ALLOC, LOAD, DATA
19 .fini_array 00000008 000000000020cb78 000000000020cb78 0000cb78 2**3
CONTENTS, ALLOC, LOAD, DATA
20 .data.rel.ro 00000020 000000000020cb80 000000000020cb80 0000cb80 2**5
CONTENTS, ALLOC, LOAD, DATA
21 .dynamic 00000200 000000000020cba0 000000000020cba0 0000cba0 2**3
CONTENTS, ALLOC, LOAD, DATA
22 .got 00000248 000000000020cda0 000000000020cda0 0000cda0 2**3
CONTENTS, ALLOC, LOAD, DATA
23 .data 00000438 000000000020d000 000000000020d000 0000d000 2**5
CONTENTS, ALLOC, LOAD, DATA
24 .bss 00000428 000000000020d440 000000000020d440 0000d438 2**5
ALLOC
25 .comment 0000002b 0000000000000000 0000000000000000 0000d438 2**0
CONTENTS, READONLY
26 .debug_aranges 00000150 0000000000000000 0000000000000000 0000d463 2**0
CONTENTS, READONLY, DEBUGGING
27 .debug_info 00006926 0000000000000000 0000000000000000 0000d5b3 2**0
CONTENTS, READONLY, DEBUGGING
28 .debug_abbrev 00000ec3 0000000000000000 0000000000000000 00013ed9 2**0
CONTENTS, READONLY, DEBUGGING
29 .debug_line 000018d1 0000000000000000 0000000000000000 00014d9c 2**0
CONTENTS, READONLY, DEBUGGING
30 .debug_str 00001e7a 0000000000000000 0000000000000000 0001666d 2**0
CONTENTS, READONLY, DEBUGGING
31 .debug_ranges 00000030 0000000000000000 0000000000000000 000184e7 2**0
CONTENTS, READONLY, DEBUGGING