Weak Alias

Weak Alias 跟 Weak Reference 完全沒有任何關係,不過是我在看到 Weak Reference的時候想到的而已。

Weak Alias 是 gcc擴展裏的東西,實際上是函數的屬性。這個東西在庫的實現裏面可能會經常用到,比如 glibc 裏面就用了不少。抄錄一段gcc 手冊裏面的話解釋下函數屬性是幹啥的,

In GNU C, you declare certain things about functions called inyour program which help the compiler optimize function calls andcheck your code more carefully.

先上代碼,看看 weak alias 怎麼寫。第一個文件 dummy.c 內容,

#include 


int __foo() {
    puts(”I do no thing.”);
}

int foo() __attribute__ ((weak, alias(”__foo”)));

weak 和 alias 分別是兩個屬性。weak使得 foo 這個符號在目標文件中作爲 weaksymbol 而不是 global symbol。用 nm 命令查看編譯 dummy.c 生成的目標文件可用看到 foo 是一個 weak symbol,它前面的標記是 W。給函數加上weak屬性時,即使函數沒定義,函數被調用也可以編譯成功。

00000000 T __foo
00000000 W foo
         U puts

而 alias 則使 foo__foo 的一個別名,__foo 和foo 必須在同一個編譯單元中定義,否則會編譯出錯。

那麼這個東西的用處是?

看第二個文件,func.c,

#include 

int foo() {
    puts(”I do something.”);
}

這裏有一個函數名字是 foo如果我們編譯 func.c 和 dummy.c 得到兩個目標文件,當我們同時使用 func.o 和 dummy.o和其他目標文件進行鏈接時,如果其他目標文件裏面引用符號 foo,最終使用到的是 func.c 中定義的函數,而不是 __foo,雖然它有一個別名 foo也就是說,我們最終使用到的函數會是“實際做事”的那個函數。當然,單獨使用dummy.o 鏈接的話使用的是那個“不做事”的函數如果 dummy.o 中的foo 不是 weak symbol的話,在鏈接時會產生衝突,這就是我們要使用 weak 的原因

glibc 的實現裏面經常用 weak alias。比如它的 socket 函數,在 C 文件裏面你會看到一個 __socket 函數,它幾乎什麼都沒有做,只是設置了一些錯誤代碼,返回些東西而已。在同一個C 文件裏面會再聲明一個 __socket 的 weakalias 別名 socket。實際完成工作的代碼通過彙編來實現,在另外的彙編文件裏面會有設置系統調用號,執行sysenter 或者 int 等動作去請求系統調用。以前看 glibc裏面系統調用的實現的時候鬱悶過很久,就是那個時候才知道了 weak alias 這個東西。

發佈了1 篇原創文章 · 獲贊 20 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章