ubuntu 在 R40e 上 還有 Debian 在 Sempron 2600 上

2010年2月25日 星期四

kernel building error on gcc 4.3 - __umoddi3()

真誇張:
busybox -- qemu boot with preload kernel -- ref jserv's tutorial -- build kernel fail 
-- workaround on CFLAG -- GCC 4.3 problem -- GCC 4.3 optimize functions -- example 
test code

繞了好大一圈,已經離 busybox 很遠了..
最後是 這一篇 王聰 先生的blog : __umoddi3()的問題 有比較清楚的說明: (copy 一下,以免消失.. 對不起)

以下 copy 自 王聰 先生的 blog 文章:
===========================================================
在編譯內核時有人遇到下面這個問題:

kernel/built-in.o: In function `getnstimeofday':
(.text+0xb6ae): undefined reference to `__umoddi3'
kernel/built-in.o: In function `getnstimeofday':
(.text+0xb6ce): undefined reference to `__udivdi3'

這個問題可以在用戶空間重現,不過不是很容易,我實驗了一下,在i386上,並不是所有的64位整數操作都會被轉化成
調用__umoddi3,gcc bugzilla上有演示程序,如下:
PLAIN TEXT
C:

  1.#define NSEC_PER_SEC  1000000000UL     
  2.int rmg(void);
  3.
  4.int main(void)
  5.{
  6.  /* int sec; */
  7.  return rmg();
  8.}
  9.
 10.int rmg(void)
 11.{
 12.  static unsigned long long nsec = 0;
 13.  static int sec = 0;
 14.  while (sec <1 ) {
 15.    nsec++;
 16.    while (__builtin_expect(nsec>= NSEC_PER_SEC, 0)) {
 17.    nsec -= NSEC_PER_SEC;
 18.    ++sec;
 19.    }
 20.  } 
 21.  return sec;
 22.}

這樣編譯它:% gcc -nostdlib -O2 -o umoddi3 umoddi3.c,就會得到:

/tmp/ccycM684.o: In function `rmg':
umoddi3.c:(.text+0x87): undefined reference to `__udivdi3'
collect2: ld returned 1 exit status

問題重現了。這裡的問題是,對於nsec來說,內層的循環其實等價於求模運算,gcc在優化時發現了這一點,而且硬件
本身也不支持對64位整數直接進行算術運算,所以gcc會把這一步優化成調用內部函數__udivdi3()和
__umoddi3(),這兩個函數在libgcc中(見gcc源代碼 gcc/libgcc2.c),libgcc默認和libc一樣是要被加載
的,但如果我們加了-nostdlib(Linux內核是更好的例子),這個問題就會出現了。

知道原因了,怎麼解決?網上有兩種方法,一種是像這個補丁那樣,在循環中插入下面這條內聯彙編:

asm("" : "+r"(ns));

這句是告訴gcc把ns這個變量放到寄存器中,並且既有讀操作也有寫操作,所以後面再用它時必須重新讀取,這樣就消
除了上面的優化。

另一種解決方法是添加新的編譯選項:-fno-tree-scev-cprop,這個選項似乎沒有文檔,至少我沒找到。說說它的
大體意思。scev 應該是SCalar EVolutions,什麼意思不知道。:( cprop應該是Copy PROPagation,這個應
該很容易理解,就是賦值的傳播,比如:

i = 10;
a = i;
b = i;

其實就是:

a = 10;
b = 10;

可見,編譯優化是門大學問,寫個編譯器絲毫不比寫個內核容易。:-P
============王聰先生的文章copy到此==============

沒有留言:

標籤

網誌存檔