Mach-O Dynamic Link (Lazy Bind mechanism), mach-olazy
Refer to the following link for more technical tips: Alibaba Cloud blog
Dynamic Link
The simplest way to solve the problems of space waste and updating is to separate program modules to form independent files instead of static links. Simply put, the target files that make up the program are not linked until the program is running. That is to say, the link process is postponed to the runtime, which is the idea of _ Dynamic Linking.
Delayed binding (PLT)
Dynamic Links have lower performance than static links, mainly because complex GOT location and indirect addressing are required for global and static data access under dynamic links; for inter-module calls, you must first locate the GOT and jump indirectly, so that the program running speed will be slowed down. In addition, dynamic links are used to complete links at runtime: when a program starts to run, the dynamic linker must perform a link operation. The dynamic linker will search and load the shared objects required, then, the symbolic query address is relocated, which slows down the startup of the program.
PLT exists to optimize the dynamic link performance. The basic idea is to bind the function when it is called for the first time (symbol search and relocation). If it is not used, bind is not performed. In this way, no bind is performed for function calls between modules during program execution. Instead, the dynamic linker is responsible for bind only when the call is required. In this way, the startup speed of the program can be accelerated.
Mach-O Lazy Bind
When the Mach-O file is loaded through dyld, it does not determine the specific address of each function. Instead, it uses procedure linkage table (PLT) to call the function, to perform lazybind.
The following is a simple analysis of the Mach-O file and code debugging.
The source code is as follows:
Breakpoint at two printf functions respectively.
The first one calls the printf function.
Call printf through callq 0x100000f76 in the 0x100000f52 \ <+ 34 \> line.
After executing the callq command, the Code jumps here:
Here, jmpq will jump to 0x0000000100000F8C. This address is obtained from Lazy symbol Pointers in-Data,-la-Symbol-ptr.
Run the lldb command to view the address at 0x00001010 and obtain the same value.
Lazybind through-stub-helper
In Mach-O, every Symbol Stub may have one of the following two actions: Jump to the function instruction, execute the function body, search for the function Symbol through the dynamic library linker, and then execute the function body
View the Section data of-stubs and find that only one function is printf.
The Data here is actually the jmpq code shown above. After execution, the Code jumps to such a code snippet.
Here we call the dyld-stubbinder function through-stub-helper to calculate the real address of the printf function. The following information shows that jmpq 0x100000f7c is to jump to the starting position of the Section after pressing the 0x0 parameter (the number given when the function is linked, call binder (a piece of assembly code is used to calculate the specific function address and call the printf function)
The second call to the printf function
After executing the command, we found that it was different from the first call to printf.
Check the memory value of 0x100001010 again. For the first time, it was quite different. That is to say, the value pointing to the printf address in-Data,-la-symbol-ptr has changed, pointing to the printf command.
This proves that delayed binding only occurs during the first call. The entire process is basically the same as the implementation logic of PLT and GOT in linux, but the implementation code is different.
Refer to Mac OS X and iOS Internals and link, loading and Library
Link: http://blog.tingyun.com/web/article/detail/1347