- 编译各个源文件。
- 使用
ld -r
将每个模块的对象文件部分链接成另一个.o文件。 - 使用
objcopy -G
隐藏每个模块中的私有符号。 - 再次使用
ld -r
将模块对象部分链接在一起。 - 将模块链接在一起形成共享对象。
这在ARM和IA32上都可以正常工作。不幸的是,我现在需要让它在mips上运行(特别是针对Android的mipsel-linux-gnu)。而MIPS的共享对象ABI要比其他平台复杂得多,而且它无法正常工作。
问题在于第五步出现了错误,具体原因为:
CALL16 reloc at 0x1234 not against global symbol
这似乎是因为编译器在调用另一个编译单元中的函数时生成CALL16重定位,但CALL16仅允许您调用全局符号,而由于步骤3,我们尝试调用的某些符号不再是全局的。此时我可以看到几个可能的选项:
dlopen()
似乎不支持这个功能。目前我已经超出了自己的深度,有什么建议吗?这是gcc 4.4.5(来自Emdebian),binutils 2.20.1。目标BFD是elf32-tradlittlemips。主机操作系统是Linux,我正在为Android进行交叉编译。 附言 我也从第4步获取了类似这样的警告。
$MODULE.o: Can't find matching LO16 reloc against `$SYMBOLNAME' for R_MIPS_GOT16 at 0x18 in section `.text.$SYMBOLNAME'
查看第4步输入的反汇编,我可以看到编译器生成的代码如下:
50: 8f9e0000 lw s8,0(gp)
50: R_MIPS_GOT16 $SYMBOLNAME
54: 8fd9001c lw t9,28(s8)
58: 0320f809 jalr t9
5c: 00a02021 move a0,a1
GOT16不是修复地址的高半部分吗?应该跟LO16一起使用来修复地址的低半部分。但是代码看起来像是在尝试进行GOT间接寻址,这让我感到困惑。我不知道这是否与我早期的问题有关,或者是一个不同的问题,或者根本不是问题...
更新:
显然,MIPS根本不支持隐藏的全局符号!
我们通过修改应该被隐藏的符号名称来解决了这个问题,这样就没有人能够知道它们的含义了。这将外部需求推得相当紧,但我向管理层解释说这是唯一的获得可出货产品的方法,他们就同意了。
这完全是令人不快的(还需要进行一些非常恶心的makefile工作),所以如果有更好的解决方案,我会很乐意听取...