|
作者:张乐 <r0bertz A gentoo D org>
本文许可协议:http://creativecommons.org/licenses/by-nc-sa/3.0/
背景:http://r0bertz.blogspot.com/2007 ... r4-on-loongson.html
标题里的的几个关键字很好的总结了qt在龙芯上连接时发生的错误的实质,其实这是个历史问题,不过还是要了解一下:
大体上是这样的:
1. mips只有一种寻址方式[1],比如lw $1,offset($2)。lw是load word,$1是目的地,offset($2)是源。其中offset是一个有符号的16位整数,所以寻址范围是[$2 - 32768, $2 + 32767],仅有64k。如果超过这个范围,一条指令就不够了。想想x86有多少寻址方式,差距啊!
2.gp是一个通常扮演前面$2的角色的寄存器
3.got global offset table,这是PIC代码调用函数和全局变量时使用的一个表。PIC,position independent code。这样的代码可以放在进程地址空间的任何地方。再加上现在的Linux有aslr, address space layout randomization,程序执行前无法知道这些代码将处于何处。so文件里就是这样的代码。在程序启动后的动态连接过程中,got就会被填充以被解析出来的函数入口和全局变量地址。got的大小就由程序里的符号(symbol,函数/全局变量名)数量决定。
4.MIPS ABI里规定,访问got里的条目只用一个指令。所以由第一条,可知got的大小在mips上是有限制的,那就是64k。假如有很大很大的程序,里面有很多符号,那么最后连接时got就装不下了这么多符号了,就发生了got溢出。
5.xgot是,或者说曾经是一种解决方法。解决的途径是扩大got的大小,扩大为32位。这样几乎就相当于无限了。但是,这样也会加大开销,因为要想访问遍32bit的范围,gp寄存器是必定要改的了,而且恐怕还需要稍加计算改什么值好,以使改变gp的次数降到最少。
如果要用xgot,可以指定gcc参数-mxgot,或者-Wa,-xgot。熟悉的人知道,后者实际代表as有参数-xgot。这两个实际效果是一样的。不过,现在不要用xgot了,看下一条。
6.multigot 是现在的解决方式,已经取代了xgot。在目前较新的binutils里,multigot是默认使用的。multigot就是使用多个got,彼此之间是连接起来的。这样每个got里还能够只使用一条指令来访问got内所有数据。multigot只在最后将所有object file连接在一起时起作用。如果你在生成object file时仍然发生got overflow,没有办法,那只好把你的代码打散了,拆成多个文件。
这些都是理论
其实解决我的问题的方法是,使用最新的CVS 2.18 branch
cvs -z 9 -d :pserver:anoncvs@sourceware.org:/cvs/src co -r binutils-2_18-branch binutils
因为按理说现在不应该有这种问题,这是个bug,已经被高人搞定了
应该就是这次ci
http://sourceware.org/cgi-bin/cv ... inutils-2_18-branch
给我的龙芯overlay加了个新ebuild
http://gentoo-cn.org/gitweb/?p=l ... 094990ff777cb6df9da
刚刚发现后面还会遇到问题(bus error),现在把-march改成了mips1,根据redhatter的说法,这就应该没问题了
[1] p39, see mips run,2rd edition,英文影印版,机械工业出版社 |
|