I believe that the reader has seen the loading, parsing and instance analysis of the dynamic link of the ELF file in Linux under the Intel platform (1): The content of the loaded content is understood, and the general process experienced when the ELF file is loaded. Then let's solve the problems mentioned in the last article, as well as code that is not explained in DL_Open_Worker.
First, _dl_map_object_deps function analysis
Due to excessive length of source code, the original simple code has become a trampoline thing due to efficiency, so I have changed it, but also delete all unnecessary code, but also Use a dummy code to show its original design ideas.
13 _dl_map_object_deps (Struct Link_Map * LMAP)
14
15 {
16
17 struct list_head * add_list;
18 char * load_dl_name;
19 struct link_map * curlmap;
20 ELF32_DYN * NEEDED_DYN;
21 struct link_map * new_lmap;
22 INT LMAP_COUNT = 1;
twenty three
24 add_lmap_to_list (lmap, add_list);
25
26 for_each_in_list (add_list, curlmap)
27 {
28 for_every_dt_needed_section (curlmap, needed_dyn)
29 {
30 LOAD_DL_NAME = GET_NEEDED_NAME (curlmap, needed_dyn);
31
32 new_lmap = _dl_map_Object (load_dl_name);
33
34
35 add_to_list_tail_uniq (add_list, new_lmap);
36}
37}
38
39 lmap_count = count_the_list (lmap);
40
41 lmap-> l_initfini = (struct link_map **) malloc ((2 * lmap_count 1) * (Struct Link_Map *);
42
43 lmap-> l_searchlist.r_list = & lmap-> l_initfini [lmap_count 1];
44 lmap-> l_searchlist.r_nlist = LMAP_COUNT;
45
46
47 COPY_EACH_ADD_LIST_TO_SEARCHLIST (LMAP, Add_List, LMAP_COUNT);
48
49 Free_THE_ADD_LIST (add_list);
50
51}
First, in fact, the dependent dynamic link library that loads a dynamic link library is not a simple thing, because all dynamic link libraries may have its own dynamic link library, if the recursive simple method is not only impossible ----- Because you can refer to the first article, there is a lock problem in the loading dynamic link library, and it is not necessary. You can't guarantee that such dynamic link library reliance will not Form a dependency loop, just like the following figure:
The simplest idea is that we don't repeat all dynamic link libraries, here is used in a single-stranded implementation ----- In the original program, it is also used in the original program, but the method used to allocate is in the stack Directly, this can speed up the run, but program readability is greatly weakened.
23 lines first add LMAP to this Struct List, in the 26 line for_each_in_list (add_list, curlmap) is actually put curlmap = curlmap-> next, and judge its curlmap! = Null, 28 line for_every_dt_need_section ( Curlmap, needed_dyn
Mainly needed_dyn = curlmap-> l_info [dt_needed]; but here should note that there may be no only one in a dynamic link library, just like an example in Readelf -a
Tag Type Name / Value
0x00000001 (Needed) Shared Library: [libstdc - libc6.2-2.so.3]
0x00000001 (NEEDED) Shared Library: [libm.so.6]
0x00000001 (Needed) Shared Library: [libc.so.6]
More exactly is to find its D_TAG in DT_Needed in the Dynamic Section of LMAP-> L_LD.
The 30-line GET_NEDED_NAME is like this
LOAD_DL_NAME = CURLMAP-> L_ADDR NEED_DYN-> D_un.d_ptr curlmap-> l_i
NFO [DT_STRTAB];
Obviously, this dynamic link library map will be made to complete its loading, and 35 lines are to expand add_list, here will only load the same dynamic link library once, so there will be no previous loop load, and then back Look at the cycle between 26 lines to 37 lines, if the no duplicate dynamic link library is added in the 35 line. The entire loop may continue to loop.
From 39 lines to 51 lines, the dependent dynamic link library COPY in this function into L_SearchList and L_initfini are ingeniously assigned together. The last temporary single-link table in front.
Second, relative transfer, absolute transfer
When learning assembly language, we must have a deep impression on different addressing methods. But for the same important transfer instructions in assembly language, just brought (used in Call and JXX --------- JXX here refers to the conditional transfer instructions such as JMP JAE JBE and unconditional transfer instructions ). However, if the link implementation of the dynamic link library must be mentioned.
The so-called relative transfer is that this binary code can be run without modification in the relocated environment. As in the case,
719: E9 E2 Fe FF FF JMP 600
It turns into a general address is like this
MOVL% EIP,% EAX
Add1 $ 0xffffee2,% EAX
MOVL% EAX,% EIP
The 719 next to this is the offset of this ELF file and the start address, while the E9 E2 Fe FF ff inside is written back to the back 0x11e because this is FF FF Fe E2 (Intel is a Little Endian expression method) The number of -0x11e represented. If you add 719 to 5, you will lose 600. This is the relative transfer of the processor.
There is another way of transfer, which is absolute transfer.
2b6: ff d0 call *% EAX This If you use the simplest code to be expressed
AddL $ 2,% EIP
Pushl% EIP
MOVL (% EAX),% EIP
Obviously, it is to turn the content of EIP into content in EAX, if it is also the same as JMP
LJMP * (% EDX)
The above two transfer methods are adapted to different environmental requirements. If it is in an ELF file, the benefits of using relative transfer can be used:
1. You can no longer have access to a memory, which has been greatly improved in the execution time of the instruction (which is now the highest frequency of the mainstream in the PCI bus structure is 133MHz, and an Intel CPU's clue can exceed it) .
2, can be adapted to the memory environment that is dynamically loaded and dynamically positioned, without having to modify the original code modification (code segment cannot be modified when running), because the entire dynamic link or executable is continuous Address mapping.
But it also brought a few questions:
1. This relative transfer does not have a way to accurately transfer to the function addresses in another dynamic link library (because the loading address of most dynamic link libraries is expected, but in theory is random ).
2, such code brings a large problem between the platform, because there is no way to know that such numbers represent an address or represent a binary number. Therefore, in the system of transplantation, there is a high-demand function of C , the development of the relative address transfer. Such as COM, CORBA system is like this.
The above two disadvantages are exactly the advantage of absolute metastasis. For a contrast, absolute transfer is equivalent to the immediate addressing of memory addressing, while relative transfer is equivalent to the relative addressing of memory addressing.
The actual use in a general dynamic link library uses a clever way. Please see the assembly language fragment of the next paragraph:
2F7: E8 00 00 00 00 Call 2FC
2FC: 5B POP% EBX
2FD: 81 C3 B0 10 00 00 Add $ 0x10B0,% EBX
What does the Call 2FC
What is the use of Add $ 0x10b0,% EBX behind it? If we assume that the address in the memory is 2FC, then the value of 10B0 is 0x13ac, what is it here?
Disassembly of section .got:
000013ac <.got>:
13ac: 34 13 x $ 0x13,% Al
...
This is a GOT section, its full name is Global Object Table is a global object table. It stores the address to be transferred here. What is achieved if you want to call a function outside the dynamic link library? Let's look down:
306: 8D 83 74 EF FF FF LEA 0xffffef74 (% EBX),% EAX30C: 50 PUSH% EAX
30D: E8 CE FF FF FF CALL 2E0
Here, a function of a Call 2E0
2E0: FF A3 0C 00 00 00 jmp * 0xc (% EBX)
2E6: 68 00 00 00 00 Push $ 0x0
2eb: E9 E0 FF FF JMP 2D0
Obviously, we have said that the% EBX has been saved in the% EBX is the start address of the .got section, and here is transferred to the amount stored at the .got start address offset 0xc. The address of 0x2E0 is in the section of .plt (Procedure Linkage Table). It is the mutual cooperation of PLT GOT to reach the effect of dynamic links. The following _dl_relocate_object function is to initialize the contents of the content in the GOT after loading the dynamic link library.
Third, _dl_relocate_object function analysis
for example. It is also from the above dynamic link library file. If we call this normal function in this, its REL is in the file.
Relocation section '.rel.plt' at offset 0x2c8 contains 1 Entries:
Offset Info Type Symbol's Value Symbol's Name
000013B8 00000E07 r_386_jump_slot 00000000 Printf
This value is if 0x13b8 (this is relative offset) is found in the file is
13b8: E6 02
Since Intel is Little Endian, this number translated is 0x02e6, what is it here?
2E0: FF A3 0C 00 00 00 jmp * 0xc (% EBX)
2E6: 68 00 00 00 00 Push $ 0x0
2eb: E9 E0 FF FF JMP 2D0
It will all understand it here. It is pressing 0x0 (this is actually the number of indexes in the previous Printf in the REL section 0 ------ it is the first item). The following is 2D0 (this is a relative transfer)
2D0: FF B3 04 00 00 00 pushl 0x4 (% EBX)
2D6: FF A3 08 00 00 JMP * 0x8 (% EBX)
As mentioned earlier, the% EBX gets the start address of the GOT, so this is the pressure got [1] into the stack, then transfer to the address included in GOT [2], you can see 2162 in Elf_Machine_Runtime_Setup With 2167 lines, it is the pointer of this dynamic link library itself, with the address of _dl_runtime_resolve. One of the following pictures can be imaged.
If it is the first function call, the route it walk is that I marked with the red line in the picture, and if it is called after the second time, it is indicated by the blue line. The reason has been given in the previous code.
82 INT _DL_RELOCATE_OBJECT (Struct Link_map * LMAP, INT LAZY_MODE)
83 {
84 ELF_MACHINE_RUNTIME_SETUP (LMAP, LAZY_MODE); 85 ELF_MACHINE_LAZY_REL (LMAP, LAZY_MODE);
86
87}
Here is two steps to complete, the first step ELF_MACHINE_RUNTIME_SETUP is to write an address of the data structure LMAP represented by this dynamic link library to a special place in the ELF file, while Elf_Machine_Lazy_rel is the dynamic link library to which you want to call. Implementation of external function relocation. These two steps are very important, because if there is no two steps, it is impossible to dynamically resolve the function of dynamic link library. This can be detailed in detail in the relative transfer of the above.
54 VOID ELF_MACHINE_RUNTIME_SETUP (STRUCT LINK_MAP * LMAP, INT LAZY_MODE)
55 {
56 ELF32_ADDR * GOT;
57
58 got = (ELF32_ADDR *) LMAP-> L_INFO [DT_PLTGOT] .d_un.d_ptr;
59
60 got [2] = & _ DL_RUNTIME_RESOLVE
61 got [1] = LMAP;
62}
Obviously, the address in the written ELF file is the second item in its DT_PLTGOT section ----- No. 60. The content written to the first item is the address of the processing function to be mobilized, which is in the dynamic resolution in the dynamic resolution mentioned later.
64 VOID ELF_MACHINE_LAZY_REL (STRUCT LINK_MAP * LMAP, INT LAZY_MODE)
65 {
66 ELF32_ADDR REL_ADDR = LMAP-> L_INFO [DT_REL] .d_un.d_ptr;
67 int REL_NUM = LMAP-> L_INFO [DT_RELSZ] .d_un.d_ptr;
68 INT I;
69 ELF32_ADDR L_ADDR = LMAP-> L_ADDR;
70
71 ELF32_REL * REL;
72 for (i = 0, rel = (ELF32_REL *) REL_ADDR; I 73 { 74 ELF32_ADDR * const reel_addr = (void *) (L_ADDR REL-> r_offset); 75 * RELOC_ADDR = L_ADDR; 76} 77 78} Here, I only list the situation in the Intel platform, other special content, it is obvious here, we just write the original address of the original content in the ELF file, this It is lazy mode because the function of the dynamic link is likely to be called throughout the program - this is the same as the principle of virtual memory management. Fourth, analysis of dynamic link library functions The previous 60 line code --- Set the dynamic resolver entry address and given all the function routes when the dynamic link library is reached, it has arrived _DL_Runtime_Resolve 2087 # define ELF_MACHINE_RUNTIME_TRAMPOLINE ASM ("// 2088.text // n // 2089 .Globl _dl_runtime_resolve // n // 2090.Type _dl_runtime_resolve, @ function // n // 2091 .align 16 // n // 2092 _dl_runtime_resolve: // n // 2093 pushl% EAX // N // 2094 pushl% ECX // n // 2095 pushl% EDX // N // 2096 MOVL 16 (% ESP),% EDX // N // 2097 MOVL 12 (% ESP),% EAX // N // 2098 Call fixup // n // 2099 POPL% EDX // N // 2100 POPL% ECX // N // 2101 xCHGL% EAX, (% ESP) // n // 2102 RET $ 8 // 2103 .Size _dl_runtime_resolve,.-_ DL_Runtime_Resolve // N // 2104 // n // 2105 "); From herein, the name ELF_MACHINE_RUNTIME_TRAMPOLINE, we can see that this function is not simple (TRAMPOLINE is the meaning of the trampoline in English, is the strange thing to make your brain curving), the following code does not explain this. . In front .Text is executable, .globl _dl_runtime_resolve is global, if there is no this, the got we look in front [2] = & _ DL_Runtime_Resolve can not compile ---- - The compiler may not find its definition. .type _dl_runtime_resolve, @function is a function description. . RALIGN 16 is 16-byte alignment. We know that two parameters have been pressed during the previous call function (the first is the Struct Link_Map * pointer of the dynamic link library, the other is the index value of the REL) Here first saves the previous register value, and at this time 16 (% ESP) is the first parameter, 12 (% ESP) first parameter, the reason here is the following FixUP function to transfer parameters in register. I wonder what the FIXUP specific content is, and you will see the content of the code author. First POP two registers, and XCHG% EAX, (% ESP) and the top of the stack, this has two purposes, one is to restore the value of Eax, the other is the top of the stack is the address returned by the function. The EAX returned by Fixup is the address we want to find with the address in memory. This will naturally jump to that place. But if you think this is good, it is wrong, because you don't forget that we have pressed into two parameters in the stack. So use RET $ 8, which is represented in Intel's instructions. POPL% EIP Add $ 0x8,% ESP The combination. (Very wonderful!!!!!!!) You can also see the "Link of the program and the implementation of the Link and the Link Dynamic Link" URL is http://www-900.ibm.com/developerworks/cn/linux/l-dynlink/index.shtml The picture exacts this ELF_MACHINE_RUNTIME_TRAMPOLINE. Then see the content of the fixup function directly 124 ELF32_ADDR FIXUP (STRUCT LINK_MAP * LMAP, ELF32_WORD RELOC_OFFSET) 125 { 126 ELF32_SYM * SYMTAB = LMAP-> L_INFO [DT_SYMTAB] .d_un.d_ptr; 127 char * stratab = lmap-> l_info [dt_strtab] .d_un.d_ptr; 128 ELF32_REL * RELOC = (ELF32_REL *) (LMAP-> L_INFO [DT_JMPREL] .d_un.d_ptr reloc_offset); 129 ELF32_SYM * SYM = & symtab [ELF32_R_SYM (RELOC-> R_INFO)]; 130 char * SYMNAME = SYM-> ST_NAME STRTAB; 131 ELF32_ADDR RELOC_ADDR = LMAP-> L_ADDR RELOC-> r_offset; 132 133 ELF32_ADDR SYMADDR = 0; 134 135 136 137 Symaddr = Do_lookup (LMAP, SYMNAME); 138 139 140 141 IF (SymadDR> 0) 142 { 143 * Reloc_addr = Symaddr; 144 Return Symaddr; 145} 146 147 EXIT (-2); 148 149 150 151 152 153} Here is given the reachable Reloc_offset that can be reachable from a dynamic link library to obtain a name to resolve the function, if the way is represented by the illustration, as shown below: You may think: It can also be used in another method, that is, the reference of this RELOC SYM ST_VALUE directly writes the previous call redirect function. This will be faster when analyzing. But reality is likely to bring great trouble throughout the ELF file structure system. I will explain every point: If it is the address of this Reloc Sym, it is a dynamic link library that its loading address itself is dynamically determined. If you use the ELF32_SYM's ST_VALUE address, it is possible to get this SYM's Name with LMAP-> L_i NFO [DT_STRTAB], but if some functions are only valid, visible, if considering when compiling A function defined as static in a file, it is to be partially visible, it is impossible to resolve this function, and the C function is more complicated, which requires a field to represent its properties. This is to have ST_INFO's data member variable. This will also have SYM's participation. Light has ELF32_SYM or not, because it is a little information on itself, this is the resolution of this Relocation Symbol, or in another real dynamic link library, this is mainly In a module written in several files, some of their probes have been determined when the link is, while others are not, distinguished is R_INFO in the relocation. From the above analysis, there is a lot of considerations, if only a single consideration, it is not, especially the specifications of multiple operating systems and platforms, can not consider the efficiency Yes. At 143 lines are the true parsing functions to the front to be relocated. This is not to come once when this function is called again. At this time, the judgment of this R_info is now slightly. . Real parsing is implemented in do_lookup, I still have pseudo code here: 90 ELF32_ADDR DO_LOOKUP (Struct Link_Map * LMAP, Char * Symname) 91 { 92 STRUCT LINK_MAP * Search_lmap = NULL; 93 ELF32_SYM * SYMTAB; 94 ELF32_SYM * SYM; 95 char * strtab; 96 char * find_name; 97 Int symindx; 98 99 ELF32_WORD HASH = ELF_HASH_NAME (SYMNAME); 100 for_each_search_lmap_in_search_list (LMAP, Search_LMAP) 101 { 102 SymTab = Search_Lmap-> L_INFO [DT_SYMTAB] .d_un.d_ptr; 103 strTab = search_lmap-> l_info [dt_strtab] .d_un.d_ptr; 104 for (symindx = search_lmap-> l_buckets [hash% search_lmap-> l_nbuckets]; 105 symindx! = 0; symindx = search_lmap-> l_chain [symindx]) 106 { 107 SYM = & symtab [symindx]; 108 109 Find_name = STRTAB SYM-> ST_NAME; 110 IF (Strcmp (Find_name, Symname) == 0) 111 RETURN SYM-> ST_VALUE SEARCH_LMAP-> L_ADDR; 112} 113 114 return 0; 115 116 117 118} 119} 100 lines for_each_search_lmap_in_search_list is the method of depends on its own dependency dynamic link library from the previous L_SearchList obtained in _dl_map_Object_Deps, as shown in the picture below. What is shown above is that the Symidx offset in the Hash table is the next offset. Finally, if strcmp == 0 can be obtained, otherwise it will return a 0 indicator. Now we have completed the analysis process of the function, it is necessary to make a summary work: In the dynamic link library that calls the function, the method used is to perform absolute transfer from the code of the PLT section, and the transferred address is stored in the GOT section. In the dynamic link library called the function (the dynamic link library implemented by the function), its function is organized in DT_HASH and DT_SYMTAB, DT_STRTAB. The organization is as follows, and ST_VALUE in the ELF32_SYM in SYMTAB indicates the offset of this derived label in the dynamic link library, and the ST_NAME is the offset in the dynamic link base STRTAB. In calling dynamic link libraries and called dynamic link libraries, ELF32_REL (ELF32_RELA in the architecture of MIPS, etc.), and its R_INFO reflects this nature of this to import mark (which is the call square), while r_offset This is the offset of this marker in the dynamic link library. (This can see the implementation in Elf_Machine_Lazy_rel) V. Uninstalling of dynamic link libraries In fact, uninstalling and loading is just a reverse process, but the original code intends to allocate memory in the stack in order to improve efficiency, but so that this is too complicated, so I made a big revision here, here It is the implementation of pseudo code. 245 Void DL_Close (Struct Link_Map * LMAP) 246 { 247 struct link_map ** Dep_lmaplist = NULL; 248 INT I; 249 ELF32_ADDR * FINI_CALL_ARRAY; 250 void * fini_call; 251 struct link_map * curlmap; 252 struct list * HAS_REMOVED_LIST = Malloc (Struct List); 253 254 HAS_REMOVED_LIST-> LMAP = LMAP; 255 HAS_REMOVED_LIST-> Next = NULL; 256 257 if (LMAP-> L_OpenCount> 1) 258 { 259 lmap-> l_opencount - 260 return; 261} 262 263 lmap-> l_opencount - 264 265 266 dep_lmaplist = lmap-> l_initfini; 267 268 269 270 for (i = 0; DEP_LMaplist [i]! = Null; i ) 271 { 272 273 try_dl_close (dep_lmaplist [i], haas_removed_list); 274} 275 276 277 if (LMAP-> L_INFO [DT_FINI_ARRAY] .d_un.d_ptr! = Null && lmap-> l_opencount == 0) 278 { 279 280 FINI_CALL_ARRAY = LMAP-> L_INFO [DT_FINI_ARRAY] .d_un.d_ptr 281 LMAP-> L_ADDR; 282 unsigned int SZ = LMAP-> L_INFO [DT_FINI_ARRAYSZ] .d_un.d_ptr 283 LMAP-> L_ADDR; 284 285 While (SZ -> 0) 286 { 287 / * Call the fini function * / 288 (Void *) Fini_Call_Array [SZ]) (); 289 290} 291} 292 293 if (LMAP-> L_INFO [DT_FINI] .d_un.d_ptr! = Null && lmap-> l_opencount == 0) 294 { 295 FINI_CALL = LMAP-> L_INFO [DT_FINI] .d_un.d_ptr 296 LMAP-> L_ADDR; 297 298 ((void *) fini_call) (); 299} 300 301 302 Munmap (LMAP-> L_MAP_START, LMAP-> L_MAP_END-LMAP-> L_MAP_START); 303 304 305 free (lmap-> l_initfini); 306 307 free (lmap-> l_scope); 308 309 IF (LMAP-> L_phdr_allocated) 310 Free ((void *) lmap-> l_phdr); 311 312 free_list (HAS_REMOVED_LIST); 313 314 Free (LMAP); 315 316 317 return; 318} The HAS_REMOVED_LIST here is a dynamic link library that has been unloaded throughout this DL_Close operation, mainly to prevent the uninstalled dynamic link library. In fact, start judging if this is no longer relying on its dynamic link library. If there is no (minus 1, equal to 0 is), then you can continue, let go of this to join this dynamic link library, try to uninstall the dynamic link library it rely on, these are finished Then it is its own point, one is the uninstall function in its dt_fini_array, and the function in dt_fini, which is finished, it is loaded to memory content, 213 lines. Then, the memory applied for Struct Link_MAP is. You can see the code after try_dl_close to understand this possible depth recursive process. 233 void try_dl_close (Struct Link_Map * LMAP, Struct List * 234 HAS_REMOVED_LMAP_LIST) 234 { 235 if (in_the_list (HAS_REMOVED_LMAP_LIST, LMAP)) 236 return; 237 DL_Close_with_List (LMAP, HAS_REMOVED_LMAP_LIST); 238 return; 239 240} 156 Void DL_Close_With_List (Struct Link_Map * LMAP, STRUCT LIST * HAS_REMOVED_LMAP_LIST) 157 { 158 STRUCT LINK_MAP ** DEP_LMAPLIST = NULL; 159 INT I; 160 ELF32_ADDR * FINI_CALL_ARRAY; 161 void * fini_call; 162 163 164 165 166 167 IF (LMAP-> L_OpenCount> 1) 168 { 169 lmap-> l_opencount - 170 return; 171} 172 add_to_list_tail_uniq (HAS_REMOVED_LMAP_LIST, LMAP); 173 174 LMAP-> L_OpenCount -; 175 176 177 dep_lmaplist = lmap-> l_initfini; 178 179 180 181 for (i = 0; dep_lmaplist [i]! = Null; i ) 182 { 183 184 TRY_DL_CLOSE (DEP_LMAPLIST [I], HAS_REMOVED_LMAP_LIST); 185} 186 187 188 IF (LMAP-> L_INFO [DT_FINI_ARRAY] .d_un.d_ptr! = Null && lmap-> l_opencount == 0) 189 { 190 191 FINI_CALL_ARRAY = LMAP-> L_INFO [DT_FINI_ARRAY] .d_un.d_ptr 192 LMAP-> L_ADDR; 193 unsigned int SZ = LMAP-> L_INFO [DT_FINI_ARRAYSZ] .d_un.d_ptr 194 LMAP-> L_ADDR; 195 196 WHILE (SZ -> 0) 197 { 198 / * Call the fini function * / 199 (void *) Fini_Call_Array [SZ]) (); 200 201} 202} 203 204 IF (LMAP-> L_INFO [DT_FINI] .d_un.d_ptr! = Null && lmap-> l_opencount == 0) 205 { 206 FINI_CALL = LMAP-> L_INFO [DT_FINI] .d_un.d_ptr 207 LMAP-> L_Addr; 208 209 (Void *) Fini_Call) (); 210} 211 212 213 MunMap (LMAP-> L_MAP_START, LMAP-> L_MAP_END-LMAP-> L_MAP_START); 214 215 216 free (lmap-> l_initfini); 217 218 free (lmap-> l_scope); 219 220 IF (LMAP-> L_phdr_allocated) 221 Free ((void *) lmap-> l_phdr); 222 223 Free (LMAP); 224 225 226 return; 227 228} In a comprehensive, DL_CLOSE This function will eventually uninstall the entire executable work, then the highest level of executable will start, here, using a dynamic link library that may have intricate dependencies, use a Mark_removed and DL_Close The combined method, in the continuous recursive call, reduce all dynamic link library L_OpenCount to 0. Finally release all memory space. This situation can be seen more clearly if you call DELET_MODULE in the Linux kernel. Six, prospects and prospects The implementation of dynamic link libraries has been quite perfect today, and it provides a good example for our learning operating system and compile language in terms of theory and practice. However, the implementation of the dynamic link library is still only in one operating system, a single machine, a programming language (if it is a C programming language, this is not satisfied, because different compilers may be Function Name Mangling --- - Function name is different in diaphragm), which is not enough for now networked information industries. Therefore, there is a binary implementation specification with this target. This is the CORBA developed by Object Model Group, and COM developed by Microsoft, I may explore these latest developments in detail later. Reference [1] Glibc-2.3.2 Sourcecode This is the source of my main code here, can be downloaded in ftp://ftp.gnu.org [2] John R.levine "Linkers and Loaders" introduces the classic of dynamic link library technology http://linker.iecc.com/ [3] HONGJIU Lu "Elf: from the programmer's inpect" Good ELF programming reference. You can see at http://linux4u.jinr.ru/usoft/www/ww_debian.org/documentation/elf/elf.html About author Wang Ruichuan, engaged in Linux development work, willing to discuss with like-minded people, email address is jeppeterone@163.com.