June 15, 2006

freestanding

* 速記,所以可能沒有條理 *

傳統的 C compiler 設計中,很明確的區分 function call 與 C preprocessor 影響層面的分野,不過,隨著編譯系統最佳化的多樣性,在實做層面都得引入新的機制,比方說之前 blog [C99 的 offsetof macro] 就提到這方面的語意是透過 GCC builtins 來實現,blog [善用 GCC builtins 實現 Vectorization] 則提到 GCC 針對 SIMD 設計與 vectorized instructions 的支援,Linux Kernel mailing-list 的討論 [compile with -ffreestanding] 中,Andi Kleen 提到新版的 GCC 會透過 builtins 來達到最佳化的處理,在 GCC flag -funit-at-a-time 指定時 (-O3 implies),原本的:
    sprintf(buf,"%s",str)
在 front-end 會被改寫為:
    strcpy(buf,str)
printf 本身就是一個小型的 interpreter,所以 GCC 的作法就是簡化複雜度,這對一般情況下是 正面的,不過涉及 function rewriting 的議題,對 Linux kernel 或設計一個作業系統核心來說,就是一個潛在的問題。是此,GCC 提供一個 flag -ffreestanding,該 flag implies flag -fno-builtin,並且對於 main 作為 entry point 沒有特別的限制要求,這是 GCC Manual 的說法,看起來的確抽象至極。之前的 blog [Orz Microkernel] 提到我今年七月份會有場演講,題目暫定為「深入淺出 Hello World -- 理解 Linux 上運作 Hello World 的種種機制」,細節稍後會公佈,主要就是探討人人會寫的 "Hello World" 程式,在 Linux 的 kernel-space 與 user-space 運作的交互作用,即便是這麼簡單的應用程式,背後都有很大的學問,而剛剛提到的 flag -ffreestanding 就是其中經典的細節。預設情況下,hosted environment 之下所有的 Standard Library 都可使用,C Programming Language 的 main function 作為邏輯上的 entry point (之所以說「邏輯上」,因為真實情況下,LD scripts 造成的影響是很大的) 其 symbol signature 以 nm 觀察:
    $ nm -f posix helloworld  | grep main 
    __libc_start_main@@GLIBC_2.0 U         
    main T 0804b26c 00000153
    
其 prototype 為接受兩或三個 argument 的 int 傳回型態,然而,在相對的 freestanding environment 中,並沒有 Standard Library,而且沒有特定的 entry point,這種特別的情況對 kernel 或 firmware 設計來說,是必要的,一般我們會在 C 語言實做的 kernel 或 firmware 中實做簡化的 C Standard Library,其語意與 C89 / C99 的規範可能會有出入。至於如何區分 hosted 或 freestanding environment 呢?前者,也就是預設的組態下,會定義 __STDC_HOSTED__ 的 macro, 在講求可攜性的 NetBSD 中,其 kernel 很明確指定該 flag,不過這也抑制一些可能出現的警告 (TODO: details),此外,可參考 lkml 的討論 "[PATCH] C undefined behavior fix" [by jtv]、[by Tom Rini],以及 [by Joe Buck]。
由 jserv 發表於 June 15, 2006 04:08 PM
迴響

C99中,Freestanding environment不規範library,甚至進入點也不一定得叫main(),因此不存在語意上的出入問題。見ISO/IEC C99 Specification, section 5.1.2, 茲節錄如下:

In a freestanding environment (in which C program execution may take place without any
benefit of an operating system), the name and type of the function called at program
startup are implementation-defined. Any library facilities available to a freestanding
program, other than the minimal set required by clause 4, are implementation-defined.

I-Jui Sung 發表於 June 15, 2006 07:21 PM

補充,前述的clause 4規範的"minimal set"應該只包含, , , , , , 這幾個header (如果我沒有誤解C99 spec的話)。

I-Jui Sung 發表於 June 15, 2006 07:28 PM

角括號似乎被濾掉了。前文提及的header如下:
float.h, iso646.h, limits.h, stdarg.h, stdbool.h, stddef.h, and stdint.h

I-Jui Sung 發表於 June 15, 2006 07:29 PM

To 學長,

之前我的紀錄實在簡陋不全,感謝學長指教與補充 :-)

jserv 發表於 June 15, 2006 07:38 PM