鏈接加載文件gcc __attribute__ section


在閱讀源代碼的過程中,發現一個頭文件有引用:
/** The address of the first device table entry. */
extern device_t devices[];
 
/** The address after the last device table entry. */
extern device_t devices_end[];
 
/** The address of the first "driver_t". */
extern driver_t driver_table_start[];
 
/** The address after the last "driver_t". */
extern driver_t driver_table_end[];
 
然后我翻遍源文件目錄,還是沒有在任何.c文件里發現曾經定義devices。
(當然最開始,我沒注意是extern,所以我先找是在哪里初始化的,然后我發現,並沒有初始化。)
 
后來我用grep搜索,總算得到了一點信息,在ld腳本里發現下面一段話:
 
  /*
   * Device table.
   */
  .device_table : ALIGN(64)
  {
    PROVIDE (devices = .);
    KEEP(*(.device_table_base))
    KEEP(*(.device_table))
    KEEP(*(.device_table_end))
    PROVIDE (devices_end = .);
  } >data AT>physmem :data
 
我大致猜測device_table正好是在device_table_base和device_table_end之間,而device_table_base和device_table_end在device_table.c中有定義。
(非常可恨的是它們的實際名字是base_devices和end_devices)
我認為我明白了怎么回事,device_table確實沒有定義,只是在鏈接腳本里定義了。
 
我以同樣的方式尋找driver_table_start和driver_table_end,我以為會同樣很簡單的找到,但是見鬼了,根本沒有,怎么回事?
 
我然后找了一個驅動程序,我倒要看看,【既然driver_table不主動添加驅動程序,而驅動程序又怎么添加進driver_table里面的。】
我找到了一個i2cm的driver_t的定義。
//! Add a new "driver" entry.
static const __DRIVER_ATTR driver_t driver_i2cm = {
  .shim_type = I2CM_DEV_INFO__TYPE_VAL_I2CM,
  .name = "i2cm",
  .desc = "I2C Master",
  .ops = &i2cm_ops,
  .stilereq = 1,
};
我發瘋了,這是很平常的事啊,這是怎么回事?我注意到注釋里那句
//! Add a new "driver" entry.
這樣就添加了?那才是見鬼了。
然后我才注意到到那個不同尋常的宏。
/** Magic attribute for "driver_t" definitions. */
#define __DRIVER_ATTR __attribute__((used, section(".driver_table")))
又是__attribute__搞的鬼,上網上略微搜了一下,__attribute__((used, section(".driver_table")))的基本含義是把函數或者數據放到名為driver_table的段。
那么其實每定義一個句 __DRIVER_ATTR driver_t driverXXX就把一個驅動給加載到這個段里。
 
然后我返回來看device_table.c時發下一個我忽視的細節:
 
static const __DEVICE_ATTR_BASE device_t base_devices[] =
static const __DEVICE_ATTR_END device_t end_devices[] =
 
其實這兩個變量也是這么定義的。清楚了,清楚了,一下子清楚了,當然要其作用,需要ld鏈接腳本的支持。
 
后來發現這位仁兄和我有同樣的問題。
內核原文件里面extern了一堆變量:extern char _ftext, _etext, _fdata, _edata, _end;但是用source insight在內核的源碼目錄里面壓根就找不到這些變量的定義。最初懷疑這些變量定義在匯編文件中,於是使用命令:
grep _ftext `find ./ -name *.S`查找,令我驚訝的是沒有找到。既然源文件中都沒有,那么又是什么神奇的力量讓程序在鏈接的時候又能正常鏈接通過呢?
原來大家都是跟內核學習的啊。
http://my.oschina.net/u/180497/blog/177206 講了利用gcc的__attribute__編譯屬性section子項構建初始化函數表。
 
不知道黑客們會不把.init段后面加上自己的函數?
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM