在阅读源代码的过程中,发现一个头文件有引用:
/** 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段后面加上自己的函数?
 

链接加载文件gcc __attribute__ section的更多相关文章

  1. 如何使用Class和ClassLoader加载文件

    很多时候我们都需要在程序中加载各种文件,比如在加载配置文件,加载properties文件,或者只是加载一个文本文件,然后输出其中的内容,我在初学java的时候,就对加载文件非常头疼,今天又遇见了加载文 ...

  2. java类加载器加载文件

    例子:采用配置文件加反射的方式创建ArrayList和HashSet的实例对象. //第一种方式:类加载器加载文件 InputStream ips = ReflectTest2.class.getCl ...

  3. spark 加载文件

    spark 加载文件 textFile的参数是一个path,这个path可以是: 1. 一个文件路径,这时候只装载指定的文件 2. 一个目录路径,这时候只装载指定目录下面的所有文件(不包括子目录下面的 ...

  4. 从xib加载文件

    一般自定义View, 如果从xib加载文件, 定义一个类方法, 返回xib + (instancetype)dropdown { return [[[NSBundle mainBundle] load ...

  5. 安装SQL2008时遇到"未能加载文件或"file:///d:microsoft..sql.chainer.packagedata.dll"或它的某个依赖项

    安装SQL2008时遇到"未能加载文件或"file:///d:microsoft..sql.chainer.packagedata.dll"或它的某个依赖项,如下图所示 ...

  6. Java中加载配置文件的集中方式,以及利用ClassLoader加载文件 .

    我们往常进行文件的加载的时候 用到的都是  FileInputStream进行 文件的加载比如下面一个例子 : InputStream in=FileInputStream("1.prope ...

  7. 关于前端本地压缩图片,兼容IOS/Android/PC且自动按需加载文件之lrz.bundle.js

    一.介绍说明主要特点: ①在前端压缩好要上传的图片可以更快的发送给后端,因此也特别适合在移动设备上使用. ②兼容IOS/Android,修复了IOS/Android某些版本已知的BUG. ③按需加载文 ...

  8. 使用PSR-4配合composer autoload 自动加载文件夹

    require 文件很麻烦,使用PSR-4搭配composer一次加载,终生受用. 感觉类似java中的import了,自己先记录一下最近理解的. 用composer管理自己的包吧 安装compose ...

  9. php 开启 opcache 之后 require、include 还会每次都重新加载文件吗?

    当前目录有以下两个文件 index.php <?php var_dump(require 'A.php'); A.php <?php return 123; 接着运行: php -S 0. ...

随机推荐

  1. MySQL☞where与like

    1.无条件查询语句(查询表中所有数据) select * from 表名 2.查询某些列的数据(指定列) select 列名1,列名2,列名3 from 表名 3.条件查询语句 select 列名1, ...

  2. Zabbix_agentd 启动报错

    C:\zabbix>c:\Zabbix\zabbix_agentd.exe -i -c c:\Zabbix\zabbix_agentd.conf zabbix_agentd.exe [1144] ...

  3. 企业级Nginx Web服务优化实战

    web优化一览总结表 优化类型 优化说明 优化方法 安全优化 隐藏nginx版本信息优化 修改nginx配置文件实现优化 server_tokens off: 修改nginx版本信息优化 修改ngin ...

  4. Django,Celery, rabbitmq

    学习Django 2 by Example书中的456页,运行 celery -A myshop worker -l info 报错.虽然特别指定了Celery的版本,也没用.之前使用的是标准安装:下 ...

  5. HDU G-免费馅饼

    http://acm.hdu.edu.cn/showproblem.php?pid=1176 Problem Description 都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然 ...

  6. Struts1之logic标签

    logic是Struts1中的逻辑标签 <%@ taglib prefix="logic" uri="http://struts.apache.org/tags-l ...

  7. Python 类和对象-上

    #类和对象 class Human: #属性 -> 成员属性(变量) ear = 2 mouth = 1 sex = 'man' age = 28 name = 'zhangwang' marr ...

  8. ZJOI2018 Day2 滚粗记 + 流水账

    一脸懵逼地就被直接拉过来浙江省选了,一年参加两次省选成就达成-- 讲课啥的都没听,过去休息了一天就进行比赛了.考试之前感冒没好透,精神不是 \(100\%\) 的状态,但是并无大碍(反正最后都很凉). ...

  9. 移动开发:美团外卖Android Lint代码检查实践

    概述 Lint是Google提供的Android静态代码检查工具,可以扫描并发现代码中潜在的问题,提醒开发人员及早修正,提高代码质量.除了Android原生提供的几百个Lint规则,还可以开发自定义L ...

  10. uva10884 Persephone

    题目戳这里. 找规律. 每一列占据的格子一定是一段区间: 相邻列之间的区间有交. 上界先增后减,下界先减后增. \(f_{i,j,k,0/1,0/1}\)表示考虑前\(i\)列,第\(i\)列,上界为 ...