链接脚本(link script)语法
链接脚本(link script)语法
语法
1. 定义一个section,如下是define一个.init.data section
*(.init.rodata.* .init.bss)最前面的*是通配符,表示所有.o文件的(.init.rodata.*、.init.bss section)
.init.data : { INIT_DATA INIT_SETUP(16) INIT_CALLS CON_INITCALL SECURITY_INITCALL INIT_RAM_FS *(.init.rodata.* .init.bss) /* from the EFI stub */ }
2. define变量
点表示当前地址,这个变量在c文件里extern后就可以使用了,如下例子
_text_start、_text_end保存了所在位置的链接地址,在这两个链接地址中间就是.text段的大小,编译完成后可以在System.map里查看这两个变量的地址
.text : { _text_start = .; *(.__image_copy_start) CPUDIR/start.o (.text*) } /* This needs to come before *(.text*) */ .efi_runtime : { __efi_runtime_start = .; *(.text.efi_runtime*) *(.rodata.efi_runtime*) *(.data.efi_runtime*) __efi_runtime_stop = .; } .text_rest : { *(.text*) } _text_end = .;
在header里extern,然后include此header就可以在c source文件里引用它们了,_text_end - _text_start的结果即为它俩中间的.text段的size
extern char _text_start[], _text_end[];
INIT_CALLS
arch/arm64/kernel/vmlinux.lds.S
__inittext_end = .; __initdata_begin = .; .init.data : { INIT_DATA INIT_SETUP(16) INIT_CALLS CON_INITCALL SECURITY_INITCALL INIT_RAM_FS *(.init.rodata.* .init.bss) /* from the EFI stub */ } .exit.data : { ARM_EXIT_KEEP(EXIT_DATA) } PERCPU_SECTION(L1_CACHE_BYTES) .rela.dyn : ALIGN(8) { *(.rela .rela*) } rela_offset = __ABSOLUTE(ADDR(.rela.dyn) - KIMAGE_VADDR); __rela_size = SIZEOF(.rela.dyn); . = ALIGN(SEGMENT_ALIGN); __initdata_end = .; __init_end = .;
include/asm-generic/vmlinux.lds.h
#define INIT_CALLS_LEVEL(level) \ __initcall##level##_start = .; \ KEEP(*(.initcall##level##.init)) \ KEEP(*(.initcall##level##s.init)) \ #define INIT_CALLS \ __initcall_start = .; \ KEEP(*(.initcallearly.init)) \ INIT_CALLS_LEVEL(0) \ INIT_CALLS_LEVEL(1) \ INIT_CALLS_LEVEL(2) \ INIT_CALLS_LEVEL(3) \ INIT_CALLS_LEVEL(4) \ INIT_CALLS_LEVEL(5) \ INIT_CALLS_LEVEL(rootfs) \ INIT_CALLS_LEVEL(6) \ INIT_CALLS_LEVEL(7) \ __initcall_end = .;
从上面的code可以看出各个level的initcall是连续存放的,0在最前,7在最后,这个顺序会决定它们在开机过程时的执行先后,数字越小的越先执行,数字越大越后执行。
而且这些initcall都是存放在.init.data section的。
上述macro展开可以得知各个等级的initcall有如下这些,这些initcall所在的区间为[__initcall_start, __initcall_end]
.initcall0.init
.initcall1.init
.initcall2.init
.initcall3.init
.initcall4.init
.initcall5.init
.initcallrootfs.init
.initcall6.init
.initcall7.init
.initcall0s.init
.initcall1s.init
.initcall2s.init
.initcall3s.init
.initcall4s.init
.initcall5s.init
.initcallrootfss.init
.initcall6s.init
.initcall7s.init
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析