Dynamic link of ELF file dynamic links in Linux under Intel platform (2): Function Analysis and Uninstall

xiaoxiao2021-03-06  71

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 in the 2f7 here do, from the above way, what is it? It is to run the function to the 2FC, depending on it, because it is a relative transfer. E8 00 00 00 00. If you use a general point of view, this is not used. But the place is here, POP% EBX at 2FC is to send it to% EBX. If each CALL will press the address of the instruction to be executed into the stack, that% EBX is here The content is the address of 2D4 instructions in memory. Recong the absolute address of the dynamic link library is that there is no way to get in compile, but it can be -------- very clever, wrong?

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 is called. What is it in 0x2E0?

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.

转载请注明原文地址:https://www.9cbs.com/read-91911.html

New Post(0)