Linux on POWER 中的 GNU C/C 工具链(6)
2008-02-23 05:41:12来源:互联网 阅读 ()
64 位的 PowerOpen ABI 定义了一个 TOC (‘Table of Contents’)段。TOC 结合了 GOT 和这个小数据段的功能。
您能够看到虽然 32 位和 64 位的模块提供了相同的功能,但是他们的组织方式却是不同的。由于 64 位模块在 ELF 中引入了这个 TOC 的概念(这来自于 AIX),请考虑以下细节。
内容列表
正如前文中介绍的相同,每个 64 位模块都包含一个 TOC。这就意味着您的 "hello, world!" 至少包含两个模块:main 程式和 libc,因此包含两个 TOC。每个 TOC 都有一个 "知名的" TOC 定位点,这通常能够在进程运行时从寄存器 2 中找到;TOC 寄存器的值会随着执行过程从一个模块跳到另外一个模块而发生变化。这个定位点支持访问一个模块的各种全局数据的机制(例如全局的外部变量、全局静态变量连同函数描述符)。
使用 TOC 意味着要使用两级间接寻址。例如,要访问一个全局变量,程式要使用 TOC 定位点(rc2)来查找指向这个变量的指针的位置。在为一个模块外部的调用查找函数描述符时,又会发生同样的操作。但是能够将数据保存在 TOC(而不是使用一个指向数据的指针),这样就避免了另外一级的间接寻找。记住,(在 64 位模式中)TOC 中保存的每个数据不管是指针还是实际数据,都必须是 8 个字节或少于 8 个字节。现在请考虑一下这对 TOC 大小的影响。
TOC 相对寻址使用了一条指令,他限定于只能使用 16 位的偏移量。TOC 能够保存 65,536 个字节,在 64 位模式中,这能够用来存放 8,192 个 GOT 项。对于大型应用程式来说,您可能会看到这些空间还不够用。GNU 链接器有几个选项来处理超过 TOC 最大值的应用程式。从 2.15.90 版本的 GNU Binutils 开始,TOC 假如溢出,在链接时会自动被分隔为多个 TOC,但是对于一个特别的结果,我们也能够使用在 表 5 中列出的选项。此处,这些选项通常都是作为 GCC 驱动程式的参数指定的。
表 5. TOC 选项
TOC 选项 描述-mfull-toc 这个选项是处理 TOC 使用的默认值。他会让链接器为可执行程式或共享对象(换而言之,就是个模块)分配一个 TOC。假如现在的 64K 空间不足以实现链接编辑的功能,那么链接器就会报告一个错误消息说 TOC 空间已溢出了。
-mno-fp-in-toc 这个标记能够减少 TOC 中使用的空间。通常,编译器会将浮点值直接放到 TOC 中。(AIX/GCC 研发人员可能会在自己的 32 位研发经验中见过这个选项。)这个标记能够防止将这些值保存到小数据段中,从而空出一些 TOC 空间给其他项使用。和此有关的一个标记是 no-sum-in-toc。
-mno-sum-in-toc 这个标记通知 GCC 在运行时生成代码来计算一个地址和一个常量之和,而不是将他们的和放到 TOC 中。这个选项(更有 no-fp-in-toc 选项)都能够用来保留一部分 TOC 空间,但是所生成的代码更大、速度更慢。
-mminimal-toc 假如使用 no-fp-in-toc 和 no-sum-in-toc 标记还不能释放足够的 TOC 空间,那么就能够使用 minimal-toc 标记为每个(对象)文档生成一个单独的 TOC。这会生成很多很小的 TOC 项。虽然这解决了 TOC 溢出的问题(因为现在有无穷个 TOC 了,每个都是 64K),但是这样所生成的代码会更大、速度也更慢。使用 TOC 来指定函数地址的长处从根本上被遗弃了。
longcall
POWER 指令集提供了 bl(或称为分支链接)指令给模块内部的子程式调用使用。这种格式的指令能够使相对寻址范围达到 64MB,或 2^26(从调用位置开始计算)。然而,有时可能会达到这个限制,因此必须使用另外一种机制实现从 A 处到 B 处的寻址。–mlongcall 选项就能够使用函数指针机制(用于模块间的调用)。换言之,每个函数调用都类似于一个模块外调用。这突破了 64M 相对地址的限制,代价是可能会稍微增加函数调用的负载。他还支持 longcall 的用法,其优先级比 -mlongcall 选项更高。longcall (1) 会对任何后续函数声明都应用这个属性;longcall (0) 能够停止对后续函数应用这个属性。
对于研发人员来说,幸运的是 GNU for Linux on POWER 上的链接器能够快速生成需要实现这个解决方案所需要的代码。正如 AIX 链接器相同,在 64 位模式中,并无需担心 –mlongcall。这个特性对于 32 位的 GNU 链接器来说是不可用的,包括 SLES9 和 RHEL4。然而,在能够自由下载的 GCC 源代码中包括了这个特性。假如您有一个 32 位的应用程式在 SLES9 或 RHEL4 上运行,他调用的位置超过了 64MB 的限制,那么您就只能重新编写代码,或将其编译为 64 位模式。由于 32 位和 64 位应用程式在 Linux on POWER 运行时是能够并存的,因此在这种情况中,我们建议您将其编译为 64 位模式。
链接器脚本
GNU 链接器提供了一种命令语言,能够用来控制链接编辑的操作。虽然对于那些早已熟悉 GCC 研发工具的人来说,这并没有什么奇怪;但是对于 AIX 研发人员来说,他们需要理解 AIX 和 Linux on POWER 上所存在的区别。尽管(XCOFF)对象文档的定义和 AIX 链接器的行为都是自动的,但是 GNU ld 能够对如何连同在何处合并对象文档的各个段进行更加灵活的控制。让我们来考虑一下这种脚本的基本属性。
GNU ld 会自动对一个内部脚本进行操作。您能够添加或替换这些内部命令。在特定的条件下(例如,使用只出现一次的命令),必须使用定制的链接器脚本提供完整的命令集;否则,能够使用脚本为链接器添加常用的操作。在添加定制操作时,您能够在命令行中对链接器脚本简单地进行命令(链接器假设任何非对象文档都是链接器脚本)。在替换链接器默认的(内部)命令时,您能够使用 --T 或 --script= 选项。
检查默认的链接器脚本的工作能够通过一个链接器选项发送到标准错误设备上。使用一个简单的 "hello, world" 程式,加上 verbose 选项,您就能够捕获这些内部的命令:
$ cc -o hello hello.c -Wl,--verbose 2> hello.ldscript
这会创建一个 256 行的脚本,他能够处理最常见的链接情况(我们期望如此)。AIX 研发人员应该注意这是 –bbindcmds: 选项的结果,但是我们早已说过,AIX 链接器要更加自动化。
因此您可能会问:为什么会有人对这种功能感兴趣呢?有些研发工作需要使用一些 "链接器欺骗(linker trick)" 的技巧,这是另外一种声明项目对如何构建应用程式和分布内存创建约束的方法。这种需要能够通过聪明地链接编辑操作实现,GNU 链接器的命令行选项就提供了这种机制。
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
下一篇: GCC 4.0 的新特性
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash
