这里所作的和上面的相类似,根据在前面从PT_LOAD program header 得到的文档映射的操作属性进行修改,但在zeroend>zerorpage的时候不同,把他映射成为进程独享的数据空间。这也就是一般的初始化数据区BSS的地方。因为zeroend是在文档中的映射的页面对齐尾地址,而zeropage是文档中的内容映射的页面对齐尾地址,这其中的差就是为未初始化数据准备的,这在1593-1597行之间体现,要把他的属性改成可写的,且全为0。
_dl_open() >> dl_open_worker() >> _dl_map_object() >> _dl_map_from_fd()
1606 if (l->l_phdr == NULL) 1607 { …….. 1611 ElfW(Phdr) *newp = (ElfW(Phdr) *) malloc (header->e_phnum 1612 * sizeof (ElfW(Phdr))); 1613 1614 l->l_phdr = memcpy (newp, phdr, 1615 (header->e_phnum * sizeof (ElfW(Phdr)))); 1616 l->l_phdr_allocated = 1; 1617 } 1618 else 1619 /* Adjust the PT_PHDR value by the runtime load address. */ 1620 (ElfW(Addr)) l->l_phdr = l->l_addr;
|
把phdr 就是program header 也纳入struct link_map的管理之中,一般的情况是不会有的,所以要copy过来。
_dl_open() >> dl_open_worker() >> _dl_map_object() >> _dl_map_from_fd()
1625 elf_get_dynamic_info (l);
|
这里调用的函数elf_get_dynamic_info是在加载过程中最重要的一个之一,因为在这之后的几乎任何的对动态链接管理的内容都要用要和这里的l_info数据组相关。
_dl_open() >> dl_open_worker() >> _dl_map_object() >> _dl_map_from_fd() >> elf_get_dynamic_info()
2826 static inline void __attribute__ ((unused, always_inline)) 2827 elf_get_dynamic_info (struct link_map *l) 2828 { 2829 ElfW(Dyn) *dyn = l->l_ld; 2830 ElfW(Dyn) **info; 2831 2832 2833 info = l->l_info; 2834 2835 while (dyn->d_tag != DT_NULL) 2836 { 2837 if (dyn->d_tag < DT_NUM) 2838 info[dyn->d_tag] = dyn; …………… 2853 dyn; 2854 } …………. 2858 if (l->l_addr != 0) 2859 { 2860 ElfW(Addr) l_addr = l->l_addr; 2861 2862 if (info[DT_HASH] != NULL) 2863 info[DT_HASH]->d_un.d_ptr = l_addr; 2864 if (info[DT_PLTGOT] != NULL) 2865 info[DT_PLTGOT]->d_un.d_ptr = l_addr; 2866 if (info[DT_STRTAB] != NULL) 2867 info[DT_STRTAB]->d_un.d_ptr = l_addr; 2868 if (info[DT_SYMTAB] != NULL) 2869 info[DT_SYMTAB]->d_un.d_ptr = l_addr; ………………. 2874 ………… 2876 if (info[DT_REL] != NULL) 2877 info[DT_REL]->d_un.d_ptr = l_addr; …………. 2879 2880 if (info[DT_JMPREL] != NULL) 2881 info[DT_JMPREL]->d_un.d_ptr = l_addr; 2882 if (info[VERSYMIDX (DT_VERSYM)] != NULL) 2883 info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr = l_addr; 2884 } …………. 2889 }
|
上面的__attribute__ 中的unused 是为了消除编译器在-Wall 情况下对于其中可能没有用到在函数中的局部变量发出警告,而alwayse_inline,很好解释,就是内联函数的强制标志。
2829行的l->l_ld是在前面的__dl_map_object_from_fd中的1455被给定的。也就是任何关于动态链接节的所在地址(参看附录B中的解释)。
很明显在2835至2854行之间的循环就是把l_info的内容都填充好。这为之后有很大的作用,因为这些节是能够找到如函数名和定位信息的,这里的的妙处是把数组的偏移量和d_tag相关联,代码简洁。
2856至2885便是对动态链接库的调整过程(这里调整的每一个节都是和函数解析有重要关系的,周详内容可参看附录A),假如我们考虑的更远一点,在前面的函数中的1521行一开始把整个文档连续的映射入内存,在这里就很好的得到解释,假如不是连续的,就没有办法在这里作一个统一的调整了。
_dl_open() >> dl_open_worker() >> _dl_map_object() >> _dl_map_from_fd() 1662 /* Finally the file information. */ 1663 l->l_dev = st.st_dev; 1664 l->l_ino = st.st_ino; 1667 return l; 1670 }
|
最后就是把设备号和节点号加入就完成了最后的dl_map_object就行了,回头看1414行中对已加载的文档的搜索,就能够明白这里的作用了。
再回到dl_open_worker中
_dl_open() >> dl_open_worker() 2550 /* It was already open. */ 2551 if (new->l_searchlist.r_list != NULL) 2552 { ……. 2556 if ((mode & RTLD_GLOBAL) && new->l_global == 0) 2557 (void) add_to_global (new); 2558 2559 /* Increment just the reference counter of the object. */ 2560 new->l_opencount; 2561 2562 return; 2563 }
文章整理:西部数码--专业提供域名注册、虚拟主机服务
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号
|
|