首页 > 代码库 > 链接加载文件gcc __attribute__ section
链接加载文件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链接脚本的支持。
后来发现这位仁兄和我有同样的问题。
http://liyun1982-1982.blog.163.com/blog/static/10488328820081113422130/
内核原文件里面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段后面加上自己的函数?
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。