这段时间一直都在解决交叉编译的一个问题,我们编译的relase版本没有问题,但是当编译debug版本的时候就是编译没有问题,最后在连接的时候报错了,看提示的提示,并不是我们代码引起的错误。为什么是突然编译不过的呢?
链接错误
于是开始了漫长的原因查找,发现在6.25左右的时候我们将一个分支和到这个主干上了,自从合并过来之后,就编译不通过了,看cvs提交的记录,看是否是代码引起的编译错误的呢?但是看来看去也没有发现什么 关系到了最后链接错误的地方。一天天的这样比对代码,checkout之前日期的代码出来,比对,最后还是无果。
突破口
后面想这条路应该走错了,直接从问题入手,发现网上报这个问题的人还是有点多的,但是看他们的现象说的是gcc的一个bug,而且都是在编译64为程序的时候出现的,并不是和我们的符合呢?也试过了他们提到的一些解决办法,打gcc的补丁,最后还是不行,最后在一篇文章里面看到本身32为ppc机子寻址的地址范围只能到2^26,也就是64M,看看在没有合并回来之前,我们 的程序是在63.5M附件,也就是说有一个新的模块合并过来之后,程序的大小超过了64M,导致这个先天的缺陷暴露出来了,如果真的是这样的话,那么以后对程序的扩展岂不是相当的不利,基本上不能扩展了。后面找找有没有文章来说这个64M的呢,在IBM上Linux on POWER 中的 GNU C/C++ 工具链里面提到了这样一段话:
POWER 指令集提供了 bl(或称为分支链接)指令给模块内部的子程序调用使用。这种格式的指令可以使相对寻址范围达到 64MB,或 2^26(从调用位置开始计算)。然而,有时可能会达到这个限制,因此必须使用另外一种机制实现从 A 处到 B 处的寻址。
1 –mlongcall选项就可以使用函数指针机制(用于模块间的调用)。换言之,每个函数调用都类似于一个模块外调用。这突破了 64M 相对地址的限制,代价是可能会稍微增加函数调用的负载。它还支持 longcall 的用法,其优先级比
1 -mlongcall选项更高。
1 longcall (1)会对所有后续函数声明都应用这个属性;
1 longcall (0)可以停止对后续函数应用这个属性。
那么赶紧对makefile文件进行修改,添加-mlongcall的编译选项,经过30分钟的漫长等待,报的strncpy的错误没有了,看来这东西起作用了,但是还是有一个连接错误,没有能解决:
测试程序
既然这个问题因为寻址的问题,那应该可以通过一个小的测试程序来模拟,如果把这个程序解决了,那个我们的问题也解决了。在找找关于64M限制的文章,还真找到了。来看看这段简短的代码:
char realbig[36000032] = {1,2};
int main()
{
printf ("&realbig = %#lx\n", &realbig);
}用gcc来编译确实是么的问题的,一用ppc_85xx-gcc编译就不行了,报的错就是上面的那个链接寻址错误的。
那问题就编程了怎么去解决这个问题了,经过一番的查找,最终找到了,通过加编译选项-Wl,-relax,既可以包问题解决了,哈哈。
马上把这两个选项拿到makefile文件里面去,又过30分钟,哈哈,搞定了,至此困恼2个多星期的问题总算是得到了解决。
问题总结
问题算是解决了,但是看哈编译出来的程序已经到了72M了,还是要想办法把东西给分离出来,不能都链到一起。看-relax选项是说:
Shorten some address references at link time, when possible; uses the linker option -relax.
大家如有这方面的经验,大家一起讨论下。


@zwwooooo
欢迎常来坐坐,呵呵。
看不懂,纯坐。
@hesiway
呵呵,沙发给你了。
还是做下沙发了,不评论~