这里把数据结构定义在函数内部,能确保这是个局部变量定义,和面向对象中的private的效果是相同的。
_dl_open() >> dl_open_worker() >> _dl_map_object() >> _dl_map_from_fd() 1448 for (ph = phdr; ph < &phdr[l->l_phnum]; ph) 1449 switch (ph->p_type) 1450 { ……….. 1454 case PT_DYNAMIC: 1455 l->l_ld = (void *) ph->p_vaddr; 1456 l->l_ldnum = ph->p_memsz / sizeof (ElfW(Dyn)); 1457 break; 1458 1459 case PT_PHDR: 1460 l->l_phdr = (void *) ph->p_vaddr; 1461 break; 1462 1463 case PT_LOAD: ………….. 1467 c = &loadcmds[nloadcmds ]; 1468 c->mapstart = ph->p_vaddr & ~(ph->p_align - 1); 1469 c->mapend = ((ph->p_vaddr ph->p_filesz GL(dl_pagesize) - 1) 1470 & ~(GL(dl_pagesize) - 1)); 1471 c->dataend = ph->p_vaddr ph->p_filesz; 1472 c->allocend = ph->p_vaddr ph->p_memsz; 1473 c->mapoff = ph->p_offset & ~(ph->p_align - 1); ………….. 1480 c->prot = 0; 1481 if (ph->p_flags & PF_R) 1482 c->prot |= PROT_READ; 1483 if (ph->p_flags & PF_W) 1484 c->prot |= PROT_WRITE; 1485 if (ph->p_flags & PF_X) 1486 c->prot |= PROT_EXEC; 1488 break; ………… 1493 }
|
在ELF文档的规范中,根据不同的program header 不同,要实现不同的功能,采用不同的处理策略,具体的内容请参看附录2 中的说明。这里没有出现一般的default 但实际运行和下面的语句是等价的:
真是达到程式简洁的特点。
但有一个特别要指出的是PT_LOAD的那些,把任何的能够加载的节都在加载的数据结构中loadcmds中构建完成,是个好的想法。特别是指针的妙用,值得学习(1467 c = &loadcmds[nloadcmds ];)。
_dl_open() >> dl_open_worker() >> _dl_map_object() >> _dl_map_from_fd() 1498 c = loadcmds; ………… 1501 maplength = loadcmds[nloadcmds - 1].allocend - c->mapstart; 1502 1503 if (__builtin_expect (type, ET_DYN) == ET_DYN) 1504 { ……………. 1521 l->l_map_start = (ElfW(Addr)) __mmap ((void *)0, maplength, 1522 c->prot, MAP_COPY | MAP_FILE, 1523 fd, c->mapoff); 1524 1525 l->l_map_end = l->l_map_start maplength; 1526 l->l_addr = l->l_map_start - c->mapstart; ……….. 1535 __mprotect ((caddr_t) (l->l_addr c->mapend), 1536 loadcmds[nloadcmds - 1].allocend - c->mapend, 1537 PROT_NONE); 1538 1539 goto postmap; 1540 }
|
在1521-1526行之间就是把整个文档都进行了映射,妙处在1498行和1501行,是把头和尾的两个PT_LOAD program header 的内容都计算在内了。而1503行就是我们这里的情景,因为这是动态链接库的加载。而1535行的修改虚拟内存的属性,就是把映射在最高地址的空白失效。这是一种保护。为了防止有人利用这里大做文章。
_dl_open() >> dl_open_worker() >> _dl_map_object() >> _dl_map_from_fd() 1546 while (c < &loadcmds[nloadcmds]) 1547 { 1548 1549 postmap: 1550 if (l->l_phdr == 0 1551 && (ElfW(Off)) c->mapoff <= header->e_phoff 1552 && ((size_t) (c->mapend - c->mapstart c->mapoff) 1553 >= header->e_phoff header->e_phnum * sizeof (ElfW(Phdr)))) …… 1555 l->l_phdr = (void *) (c->mapstart header->e_phoff - c->mapoff); 1556 1557 if (c->allocend > c->dataend) 1558 { ……….. 1561 ElfW(Addr) zero, zeroend, zeropage; 1562 1563 zero = l->l_addr c->dataend; 1564 zeroend = l->l_addr c->allocend; 1565 zeropage = ((zero GL(dl_pagesize) - 1) 1566 & ~(GL(dl_pagesize) - 1)); 1567 1568 if (zeroend < zeropage) ………. 1571 zeropage = zeroend; 1572 1573 if (zeropage > zero) 1574 { ……. 1576 if ((c->prot & PROT_WRITE) == 0) 1577 { 1578 /* Dag nab it. */ 1579 __mprotect ((caddr_t) (zero & ~(GL(dl_pagesize) 1580 - 1)), GL(dl_pagesize), 1581 c->prot|PROT_WRITE) < 0); 1582 1583 } 1584 memset ((void *) zero, '', zeropage - zero); 1585 if ((c->prot & PROT_WRITE) == 0) 1586 __mprotect ((caddr_t) (zero & ~(GL(dl_pagesize) - 1)), 1587 GL(dl_pagesize), c->prot); 1588 } 1589 1590 if (zeroend > zeropage) 1591 { …….. 1593 caddr_t mapat; 1594 mapat = __mmap ((caddr_t) zeropage, zeroend - zeropage, 1595 c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED, 1596 ANONFD, 0); 1597 1598 } 1599 } 1600 1601 c; 1602 }
文章整理:西部数码--专业提供域名注册、虚拟主机服务
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号
|
|