Learn about Dynamic Links (4)-delayed binding and dynamic binding
The basic idea is to bind a function only when it is called for the first time. The so-called binding means symbol search and address relocation. For some error handler functions or less commonly used function functions, the "binding waste" may be avoided ". Delayed binding can accelerate program startup, which is especially beneficial to some large programs.
When a function is called for the first time, the dynamic linker binds the address. He must know which function of the module where the address binding occurs and have a function to complete the binding.
When calling an external function, you need to jump to PLT first, and then to GOT to get the external function address. Each external function has a corresponding item in the PLT table. For example:
1 bar@plt:2 jmp *(bar@GOT)3 push n4 push moduleID5 jump _dl_runtime_resolve
The first command jumps to bar @ GOT. At this time, bar @ GOT saves the address of the second command "push n" in the code above, so it jumps back. The two push commands respectively add the subscript and module ID of the symbol in the relocation table to the stack, and then call the _ dl_runtime_resolve function of the dynamic linker to complete the symbol search and address relocation, finally, enter the real address of the bar function in bar @ GOT. When bar @ plt is called again, the first jmp command can directly jump to the bar function through bar @ GOT, without any further relocation.
In specific implementation, ELF splits the GOT that saves the external function address and places it in. got. plt .. The first three Special Features of got. plt:
- The first option is to save the address of ". dynamic;
- The second item stores the ID of this module;
- Item 3 Save the address of _ dl_runtime_resolve
So the bar @ plt above can be as follows:
1 bar@plt:2 jmp *(bar@GOT)3 push n4 push *(GOT + 4)5 jump *(GOT + 8)
Because the last two commands are the same for each plt item, in order to avoid code duplication, put these two commands into PLT0. So bar @ plt is actually like this:
1 PLT0:2 push *(GOT + 4)3 jump *(GOT + 8)4 …5 bar@plt:6 jmp *(bar@GOT)7 push n8 jmp PLT0
Learning Materials: programmer self-cultivation-links, loading and libraries