在创建动态共享库以提高运行时性能时,可使用 -xcode=pic13 或 -xcode=pic32。
虽然动态可执行文件内的代码通常绑定到内存中的固定地址,但是可以将与位置无关的代码装入进程地址空间中的任意位置。
在使用与位置无关的代码时,将生成可重定位引用,作为通过全局偏移表的间接引用。在使用 -xcode=pic13 或 -xcode=pic32 进行编译时,由于不要求大量的重定位(这些重定位是与位置有关的代码所强制的),因此会使共享对象中的频繁访问项获益。
全局偏移表的大小不应超过 8Kb。
-xcode={pic13|pic32} 有两个名义性能成本:
使用 -xcode=pic13 或 -xcode=pic32 编译的例程在入口处执行几个额外的指令,以便将寄存器设置为指向用于访问共享库的全局变量或静态变量的全局偏移表。
每次访问全局变量或静态变量时,都会涉及到通过全局偏移表进行额外的间接内存引用。如果编译是使用 pic32 进行的,则每个全局和静态内存引用都有两个额外指令。
在考虑上述成本时,请记住:由于受到库代码共享的影响,使用 -xcode=pic13 或 -xcode=pic32 会大大减少系统内存需求。共享库中已使用 -xcode=pic13 或 -xcode=pic32 编译的每个代码页,都可以由使用该库的每个进程共享。如果共享库中的代码页包含非 pic(即绝对)内存引用,即使仅包含单个非 pic 内存引用,该页也将变为不可共享,而且每次执行使用该库的程序时都必须创建该页的副本。
确定是否已使用 -xcode=pic13 或 -xcode=pic32 编译 .o 文件的最简单方法是使用 nm 命令:
nm file.o | grep _GLOBAL_OFFSET_TABLE_
包含与位置无关的代码的 .o 文件将包含对 _GLOBAL_OFFSET_TABLE_ 的未解析外部引用(用字母 U 标记)。
要确定是使用 -xcode=pic13 还是 -xcode=pic32,请通过使用 elfdump -c(有关更多信息,请参见 elfdump(1) 手册页)来查看全局偏移表 (Global Offset Table, GOT) 的大小以及节标题 sh_name: .got。sh_size 值是 GOT 的大小。如果 GOT 小于 8,192 字节,请指定 -xcode=pic13,否则指定 -xcode=pic32。
通常,应根据以下准则来确定如何使用 -xcode:
如果要生成可执行文件,则不应该使用 -xcode=pic13 或 -xcode=pic32。
如果是生成仅用于链接到可执行文件的归档库,则不应该使用 -xcode=pic13 或 -xcode=pic32。
如果要生成共享库,请先使用 -xcode=pic13,一旦 GOT 大小超过 8,192 字节,则使用 -xcode=pic32。
如果要生成用于链接到共享库的归档库,则应该使用 -xcode=pic32。
在生成动态库时,建议使用 -xcode=pic13 或 pic32(或者 -pic 或 -PIC)选项进行编译。请参见 Solaris《链接程序和库指南》。