链接加载文件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段后面加上自己的函数?

链接加载文件gcc __attribute__ section

时间: 2024-07-30 22:38:19

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

Keil sct分散加载文件

首先介绍几个概念: 1.ARM映像文件 ARM映像文件是一个层次性结构的文件,其中包含了域(region).输出段(output section)和输入段(input section).各部分关系如下: 一个映像文件由一个或多个域组成 每个域包含一个或多个输出段 每个输出段包含一个或多个输入段 各输入段包含了目标文件中的代码和数据 输入段中包含了4类内容:代码.已经初始化的数据.未经初始化的存储区域.内容初始化成0的存储区域.每个输入段有相应的属性,可以为只读的(RO).可读写的(RW)以及初始

AutoSharedLibrary -- 基于模板元编程技术的跨平台C++动态链接加载库

基于模板元编程技术的跨平台C++动态链接加载库.通过模板技术,使用者仅需通过简单的宏,即可使编译器在编译期自动生成加载动态链接库导出符号的代码,无任何额外的运行时开销. ASL_LIBRARY_BEGIN(TestLib) ASL_SYMBOL(Proc_test1, test1, false) ASL_SYMBOL(Proc_test2, test2, true) ASL_LIBRARY_END() TestLib theLib; try { theLib.Load("./1.so"

powershell-无法加载文件,因为在此系统中禁止执行脚本

写了一个powershell脚本测试脚本,结果执行的时候报错 $a=Get-Content C:\script.txt | select-string -pattern "ora"     if ( $a -eq  $null )     {                 write-host "error"      }     else     {          write-host "OK"      }  PS D:\> .\

PowerShell 无法加载文件ps1,因为在此系统中禁止执行脚本

直接运行powershell时提示“无法加载文件ps1,因为在此系统中禁止执行脚本.有关详细信息,请参阅 "get-help about_signing". 主要是由于没有权限执行脚本. 运行get-help about_signing 提示了解执行策略输入 get-executionpolicy 显示 Restricted 即不允许执行任何脚本. 通过命令 get-help set-executionpolicy 可知有以下执行策略:<Unrestricted> | &l

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

安装SQL2008时遇到"未能加载文件或"file:///d:microsoft..sql.chainer.packagedata.dll"或它的某个依赖项,如下图所示 原因:SQL2008的安装路径过长. 解决:把SQL2008放到D盘或者E盘的根目录下再安装.

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

require 文件很麻烦,使用PSR-4搭配composer一次加载,终生受用. 感觉类似java中的import了,自己先记录一下最近理解的. 用composer管理自己的包吧 安装composer 这个不多赘述 英文版教程 中文版教程 PSR-4规范 PSR-4-autoloader 构建项目目录 |-project ? |-src ? |-View.php ? |-app ? |-Tools.php |-composer.json 上面路径的View.php在project/src/Vi

15.资源加载器,根据配置文件自动加载文件

前言 以前我想自己写一个加载器,用的时候加载,不用的时候再去掉,结果发现这种方式可能因为资源不统一在安卓上可能出现问题,所以搜集资料,弄成根据配置文件加载 思路 设定两个配置文件,screen,res,不同场景对应不同的screen,不同screen使用的资源为res,当切换的screen的res相同时,不对资源处理,直接切换,否则进入load场景等待资源加载和卸载,然后再跳转场景 下图为场景screen配置文件和资源res配置文件,screen配置了加载的背景图(bgImage),随后做配置化

webpack : 无法加载文件 D:\nodejs\node_global\webpack.ps1,因为在此系统上禁止运行脚本。

通过vs code 运行webpack进行打包时,报错webpack : 无法加载文件 D:\nodejs\node_global\webpack.ps1,因为在此系统上禁止运行脚本. 解决方案: 以管理员身份运行vs code 执行:get-ExecutionPolicy,显示Restricted,表示状态是禁止的 执行:set-ExecutionPolicy RemoteSigned 这时再执行get-ExecutionPolicy,就显示RemoteSigned 此时发现再进行打包就没有问

无法加载文件 C:\Users\huangshimin\AppData\Roaming\npm\wechat-terminal.ps1,因为在此系统上禁止运行脚本

在Windows powershell上运行脚本失败:提示信息“无法加载文件 C:\Users\huangshimin\AppData\Roaming\npm\wechat-terminal.ps1,因为在此系统上禁止运行脚本”,(需要以管理员身份运行)参考:https://blog.csdn.net/hl971115/article/details/102078132 原文地址:https://www.cnblogs.com/bneglect/p/12617879.html