100行for_each_search_lmap_in_search_list就是从前面在 _dl_map_object_deps中得到的l_searchlist中取下的他本身的依赖动态链接库,中间查找的方法就如下面那张图中所显示的。

上面所表示的就是个在hash表中symidx偏移处所存的就是下一个偏移所在。最后假如strcmp==0就能够得到了,否则就会返回一个0表示失败了。
现在我们已把函数的解析过程分析完毕,有必要作一个小结工作:
- 在调用函数的动态链接库中,他所用的方法是从plt节的代码执行绝对转移,而转移的地址存放在got节中。
- 在被调用函数的动态链接库中(就是函数实现的动态链接库),他的函数在以DT_HASH和DT_SYMTAB, DT_STRTAB组织起来。组织的方式如下面的一张图,以symtab中的Elf32_Sym中的st_value表示这个可导出的标记在动态链接库中的偏移量,st_name则是在动态链接库strtab中的偏移量。
- 在调用动态链接库和被调用动态链接库的联系能过的是Elf32_Rel(对MIPS等的体系结构中是Elf32_Rela),他的r_info体现了这个要导入标记(就是调用方中)的性质,而r_offset则是这个标记在动态链接库中的偏移量。(这个能够看 elf_machine_lazy_rel中的实现)

五、动态链接库的卸载
实际上卸载和加载只是反过程而已,但原来的代码为了提高效率实现在栈内分配内存,但是这样倒使原来简单易懂的变的过于复杂,所以,我这里作了很大的修改,这里是伪代码的实现。
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(sizeof(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],has_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 }
|
这里的has_removed_list就是记录整个在这一次dl_close操作中已被卸载了的动态链接库,主要是为了防止再次卸载已卸载的动态链接库。其实先开始判断这是否是已没有再依赖他本向的动态链接库了。假如没有了(减去1,等于0就是了),那才能够继续去了,接下来不要先把他自己加入这个动态链接库,试着去卸载他所依赖的动态链接库,这些全做完之后就是他本身的各要点,一是他的DT_FINI_ARRAY中的卸载函数,更有就是DT_FINI中的函数,这之完了,便是加载到内存内容的去映射化,213行。再就是对struct link_map申请的内存就是了。
您能够看try_dl_close之后的代码就能明白这种可能有的深度的递归过程。
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 }
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!
| | 版权所有 西部数码(www.west263.com)
CopyRight (c) 2002~2007 west263.com all right reserved.
公司地址:四川成都市万和路90号天象大厦4楼 邮编:610031
电话总机:028-86263408 86263960 86264018 86267838 86262244 86263408 售前咨询:总机转201 202 203 204 205 206 207 208 售后服务:总机转211
212 213 214 217 218 晚上0点以后拔分机225 |
| 财务咨询:总机转224
223 传真:028-86264041 财务QQ: 635483282
售前咨询QQ: 327314358 241975952 275026793 408235859 2182518 499513144 售后服务QQ: 634349278 809071471 307742704 512359778 287976517 363783715 在线咨询
《中华人民共和国增值电信业务经营许可证》编号:川B2-20030065号
|
|