Programmer’s Self-Cultivation - Link is Loaded with the Library
Foreword
Think of the compile and link process, and consider the static and dynamic library. After pondering these two concepts, carefully read this article to gain a deep understanding of compilation, linking, loading, and static and dynamic libraries. This knowledge is essential and often overlooked, but with this article, you will grasp it firmly.
Machine Instructions
The original machine instructions are recorded using tape. When a programmer changes the command, they need to recalculate the jump address of each subroutine. This operation is called relocation. However, if there are multiple tapes, the jump becomes more complex.
To solve this issue, the assembly language pioneer was invented. An example of an assembler instruction is jmp foo. Each time the assembler assembles this instruction, it recalculates the address of foo. The symbol foo is represented by an address, which may be the start address of a function or a variable. The start address may be variable.
As software grows in size, the amount of code increases. To organize different functional modules in a particular way, making it easier to read, the problem of combining these modules into a single program arises.
link
Let’s examine the calls between modules. There are two types of calls: function calls and variable access. These can be unified as a symbol cross-reference to the module. This unification process between the module symbolic references is called linking.
Linking includes address space allocation and symbol resolution and relocation. A brief description of the linking process is as follows:
- If we use
fun.candmain.cwith themainfunction, the compilation process will produce a target file with instructions for calling thefoofunction. However, the target address of the instruction will be held in abeyance until the linker fills in the address of the functionfooduring the linking process. - The linker allocates address space for the target file and produces the destination file after compilation.
Static Links
Static links occur when linking static libraries into the executable program. The linker allocates address space for the target file and has two meanings:
- The output executable file space
- The virtual address space loaded in the virtual address space
The linking process involves two steps:
- Address space allocation and scanning all object files to get the length of the attribute, position information of each segment, and all symbols as defined and referenced collected into the global symbol table. The length of all segments is computed and combined, and the mapping is established.
- Symbol resolution and relocation, using the information collected in the previous step, read file data and relocation information, and resolve and relocate symbols.
Static libraries are commonly represented by .lib or .a files. However, static libraries have shortcomings, such as wasting memory and disk space and update difficulties.
Dynamic Link
Dynamic links postpone the linking process until runtime. Dynamic links require operating system support and involve loading files and linking at runtime. The dynamic linker is responsible for resolving symbols and allocating address space for the shared object.
Dynamic link libraries are commonly represented by .dll or .so files. The final load address of the shared object is uncertain and is allocated dynamically at runtime. The dynamic linker is statically linked.
External Symbol
External symbols are referenced but not defined in the present target document. When multiple symbols of the same name conflict, the first symbol loaded becomes the priority load sequence.
iOS Related
Through a project, we can verify that dynamic libraries can be loaded dynamically. The dlfcn.h method is used to open dynamic libraries, and the dlopen function is used to open dynamic link libraries.
The dlsym function is used to get the function name or variable name, and the dlclose function is used to close the dynamic library.
Objective-C Method
Objective-C methods are used to load classes and methods dynamically. The NSClassFromString function is used to return a class by name, and the NSSelectorFromString function is used to return a method name.
The performSelector function is used to execute a method.
Project Settings
Note that no ALib Linked in setting is inside because we are opening dynamic libraries in the form of dlopen. The BLib OC in a class has a method + load that will be loaded when displayed, and the ALib OC in a class has a method + load that will be loaded when displayed.
Test Code
#include <dlfcn.h>
typedef void (* FOO_FUNC) (void);
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self testLib];
});
}
- (void)testLib {
NSLog(@"Test lib.");
void *handle;
char *error;
handle = dlopen("ALib.framework/ALib", RTLD_LAZY);
if (!handle) {
fprintf(stderr, "%s\n", dlerror());
return;
}
dlerror();
FOO_FUNC func = dlsym(handle, "foo");
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
return;
}
func();
Class Alib = NSClassFromString(@"ALib");
SEL foo = NSSelectorFromString(@"foo");
if (Alib && foo) {
[[[Alib alloc] init] performSelector:foo withObject:nil];
}
dlclose(handle);
}
Test Output
2016-12-22 13:09:00.653406 testLib [8279:1718634] load Blib
2016-12-22 13:09:04.083711 testLib [8279:1718634] Test lib
2016-12-22 13:09:04.195297 testLib [8279:1718634] load Alib
2016-12-22 13:09:04.195752 testLib [8279:1718634] foo in ALib
Thinking
Dynamic link libraries are loaded into memory when the program starts, even if they are not used. The delay is simulated by the dispatch_after function, and the ALib DLL is loaded later than the BLib DLL.
Other Linker Flags
The -ObjC flag tells the linker to load and Category comes in. However, if there is a static library class and category, you need to add this flag. The -all_load flag forces the linker to load all target files, even without objc code. However, if there is a static library class and category, even with -ObjC, the category will not be loaded.
The -force_load flag requires a static library, and the -all_load flag only difference is that a fully loaded library does not affect other libraries.
To Sum Up
When learning knowledge now, look back once the path of development, there will be surprises. The width of the space shuttle is determined by the horse’s ass. Code can be found on GitHub.