当前位置:网站首页>Basic principle and usage of dynamic library, -fpic option context

Basic principle and usage of dynamic library, -fpic option context

2022-07-08 00:16:00 wowocpp

Basic principle and usage of dynamic library ,-fPIC The context of options

Use gcc Generate so When you file , Generally, one should be added - fPIC Options , What does this option mean ? This paper introduces PIC The context of .
1 Link view to see dynamic shared libraries and static libraries
If we are in the main program main.c A function is used in foobar (), Yes main.c Compile , The compiler doesn't know yet foobar () Address of function , Generated during the compilation phase main.o in ,foobar An unresolved reference .

The linker will main.o When linking to an executable , It must be confirmed that main.o As quoted in foorbar () Properties of functions . If foobar () Is defined in other static object modules ( Static library or object file ) The function in , Then the linker will follow the rules of static linking main.o Medium foobar () Function address reference relocation .

gcc -o main.out mian.c ./libfoo.a

If foobar () Is a function defined in a dynamic shared library , Then the linker will put foobar A symbol marked as a dynamic link ,foobar This is a reference to dynamic symbols . Do not reposition it .

gcc -o main.out main.c ./libfoo.so

2 Execute view to see dynamic library
The development process of dynamic library has three stages .

2.1 Evolution stage 1: Static shared library
Static shared libraries are not static libraries , It refers to that the shared library has determined its location in the process virtual address space when compiling . The operating system divides some address blocks at a specific address , Reserve enough space for those known modules . In the linked view , The address of the static shared library in the virtual address space of the process has been determined , If you want to upgrade the static shared library later , You still need to recompile , Link executable ELF.

2.2 Evolution stage 2: Repositioning during loading
Load relocation refers to when linking , References to all absolute addresses are not relocated , Delay until loading . The program is loaded as a whole , The relative position of instructions and data in the program will not change , The base address of the program may be different each time it is loaded . Once the module load address is determined , The system can relocate all the absolute addresses in the program .

Linux GCC Options

gcc -shared -o libbook.so book.c

Use reload , After the dynamic link module is loaded and mapped to the virtual address space , The instructions will be modified , Multiple processes cannot share the same instruction code . After the instruction is relocated, it is different for each application . Evolution stage 2 Relocating when loading , Cannot solve the requirement that the instruction part needs to be shared among multiple processes . It also loses the memory saving advantage of dynamic linking .

2.3 Evolution stage 3: Address independent code (Position Independent Code, PIC)
To share instruction parts among multiple processes , Instructions need to be classified . It can be divided into two categories according to whether it crosses modules : Intra module references and external module references ; There are two kinds of quotation : Instruction reference and data access . There are four combinations : Function call inside the module 、 Jump , Data access inside the module ( For example, global variables defined in modules 、 Static variables ), Function calls between modules 、 Jump , Data access between modules ( For example, global variables defined in other modules ).

Type 1 Module internal function call 、 Jump

Jump inside the module 、 Function calls can be called with relative addresses , No need to relocate .

Type 2 Module internal data access

The relative position between the internal instructions of the module and the internal data of the module is fixed , You only need to add a fixed offset relative to the current instruction to access the internal data of the module .

Type 3 Data access between modules

The destination address of data access between modules cannot be determined until loading ,ELF The method of the file is to build an array of pointers to the global variables between these modules in the data segment , Also known as the global offset table (Global Offset Table, GOT), When the code needs to reference global variables between modules , Can pass GOT An indirect reference to a table item in . because GOT Is stored in the data segment , So the dynamic library can be modified when loading , Each process has its own copy , Not affected by each other . It can be determined at compile time GOT Offset from the current instruction , The compiler decided GOT Every item in (4 Bytes are an item , A pointer ) Corresponding to which global variable name , It's just GOT It gives the global variables that need to be relocated , And the global variable is relative to GOT The location of . The dynamic linker will find the address of each variable when loading the module , Then fill in GOT Each of the items in , Make sure GOT The address pointed to by each pointer in is correct .

Type four Function calls between modules 、 Jump

Similar to type III , through GOT, stay GOT The address of the objective function is stored in , When the module needs to call the objective function , Can pass GOT Perform an indirect jump .

Use GCC Generate address independent code

gcc -fPIC -shared -o libbook.so book.c

Be careful : there - fPIC Medium PIC It's capital , There are also lowercase - fpic( The generated code is relatively small , And faster ), In some platforms, lowercase - fpic Options have some limitations , And capital - fPIC There is no such problem . Most cases use - fPIC.

You can view a so Is it right? PIC, If it is PIC, The following command will have output , If not PIC, There will be no output .

readelf -d libbook.so | grep TEXTREL
原网站

版权声明
本文为[wowocpp]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/189/202207072210032680.html