手机站
网通分站
电信主站
密 码:
用户名:
当前位置 : 主页>网站运营>建站经验>列表

Intel平台下Linux中 ELF文档动态链接的加载、解析及实例分析(一): 加载

来源:互联网 作者:west263.com 时间:2008-04-16
西部数码-全国虚拟主机10强!40余项虚拟主机管理功能,全国领先!双线多线虚拟主机南北访问畅通无阻!免费赠送企业邮局,.CN域名,自助建站480元起,免费试用7天,满意再付款! P4主机租用799元/月.月付免压金!

_dl_open() >> dl_open_worker()
2532 static void
2533 dl_open_worker (void *a)
2534 {
……………………..
2547 args->map = new = _dl_map_object (NULL, file, 0, lt_loaded, 0, mode);

这里就是调用_dl_map_object 来把文档映射到内存中。原来的函数要从不同的路径搜索动态链接库文档,还要和SONAME(这是动态链接库文档在运行时的别名)比较,这些内容我在这里都删除了。


_dl_open() >> dl_open_worker() >> _dl_map_object()
1693 struct link_map *
1694 internal_function
1695 _dl_map_object (struct link_map *loader, const char *name, int preloaded,
1696 int type, int trace_mode, int mode)
1697 {
1698 int fd;
1699 char *realname;
1700 char *name_copy;
1701 struct link_map *l;
1702 struct filebuf fb;
1703
1704
1705 /* Look for this name among those already loaded. */
1706 for (l = GL(dl_loaded); l; l = l->l_next)
1707 {
1708 if (!_dl_name_match_p (name, l))
…………….
1721 return l;
1722 }
1723
1724 fd = open_path (name, namelen, preloaded, &env_path_list,
1725 &realname, &fb);
1726
1727 l = _dl_new_object (name_copy, name, type, loader);
1728
1729 return _dl_map_object_from_fd (name, fd, &fb, realname, loader, type, mode);
1730
1731
1732 }/*end of _dl_map_object*/

这里先在已被加载的一个动态链接库的链中搜索,在1706和1721行中就是作这一件事。想起来也很简单,因为可能在一个可执行文档依赖好几个动态链接库。而其中有几个动态链接库或许都依赖于同一个动态链接文档,可能早就加载了这样一个动态链接库,就是这样的情况了。

下面open_path是个关键,这里要指出的是env_path_list得到的方式有几种,一是在系统环境变量,二就是 DT_RUNPATH所指的节中的字符串(参见下面的附录),更有更复杂的,是从其他要加载这个动态链接库文档的动态链接库中得到的环境变量-------这些问题我们都不说明了。


_dl_open() >> dl_open_worker() >> _dl_map_object() >> open_path()
1289 static int open_path (const char *name, size_t namelen, int preloaded,
1290 struct r_search_path_struct *sps, char **realname,
1291 struct filebuf *fbp)
1292
1293 {
1294 struct r_search_path_elem **dirs = sps->dirs;
1295 char *buf;
1296 int fd = -1;
1297 const char *current_what = NULL;
1298 int any = 0;
1299
1300 buf = alloca (max_dirnamelen max_capstrlen namelen);
1301
1302 do
1303 {
1304 struct r_search_path_elem *this_dir = *dirs;
1305 size_t buflen = 0;
………………
1310 struct stat64 st;
1311
1312
1313 edp = (char *) __mempcpy (buf, this_dir->dirname, this_dir->dirnamelen);
1314 for (cnt = 0; fd == -1 && cnt < ncapstr; cnt)
1315 {
1316 /* Skip this directory if we know it does not exist. */
1317 if (this_dir->status[cnt] == nonexisting)
1318 continue;
1319
1320 buflen = ((char *) __mempcpy (__mempcpy (edp, capstr[cnt].str,
1321 capstr[cnt].len), name, namelen)- buf);
1322
1323
1324 fd = open_verify (buf, fbp);
1325
1326
1327 __xstat64 (_STAT_VER, buf, &st);
1328
1329
1341 }
1342
…………….
1358 }

在这上面的alloc是在栈上分配空间的函数,这样就不用担心在函数结束的时候出现内存泄漏的情况(好的程式员真的要对内存的分配熟谙于心)。1313行就是把r_search_path_elem的dirname copy过来,而在1320至1321行的内容就是为这个路径加上最后的'/'路径分隔号,而capstr就是根据不同的操作系统和体系得到的路径分隔号。这其实是个很好的例子,因为__memcpy返回的参数是dest string所copy的最后的一个字节的地址,所以每copy之后就会得到新的地址,假如用strncpy来写的话,就要用这样的方法


strncpy(edp, capstr[cnt].str, capstr[cnt].len);
edp =capstr[cnt].len;
strncpy(edp,name, namelen);
edp =namelen;
buflen=edp-buf;

这就要用四句,而这里用了一句就能够了。

下面的open_verify是打开这个buf所指的文档名,fbp是从这个文档得到的文档开时1024字节的内容,并对文档的有效性进行检查,这里最主要的是ELF_IMAGIC核对。假如成功,就返回一个大于-1的文档描述符。整个open_path就这样完成了打开文档的方法。

_dl_new_object是个分配struct link_map* 数据结构并填充一些最基本的参数。

文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

Google