/* tools/kernel.ld */OUTPUT_ARCH(riscv) /* 指定输出文件的指令集架构, 在riscv平台上运行 */ENTRY(kern_entry) /* 指定程序的入口点, 是一个叫做kern_entry的符号。我们之后会在汇编代码里定义它*/BASE_ADDRESS =0x80200000;/*定义了一个变量BASE_ADDRESS并初始化 *//*链接脚本剩余的部分是一整条SECTIONS指令,用来指定输出文件的所有SECTION "." 是SECTIONS指令内的一个特殊变量/计数器,对应内存里的一个地址。*/SECTIONS{ /* Load the kernel at this address: "." means the current address */ . = BASE_ADDRESS;/*对 "."进行赋值*/ /* 下面一句的意思是:从.的当前值(当前地址)开始放置一个叫做text的section. 花括号内部的*(.text.kern_entry .text .stub .text.* .gnu.linkonce.t.*)是正则表达式 如果输入文件中有一个section的名称符合花括号内部的格式 那么这个section就被加到输出文件的text这个section里 输入文件中section的名称,有些是编译器自动生成的,有些是我们自己定义的*/ .text : {*(.text.kern_entry) /*把输入中kern_entry这一段放到输出中text的开头*/*(.text .stub .text.* .gnu.linkonce.t.*) }PROVIDE(etext = .); /* Define the 'etext' symbol to this value */ /*read only data, 只读数据,如程序里的常量*/ .rodata : {*(.rodata .rodata.* .gnu.linkonce.r.*) } /* 进行地址对齐,将 "."增加到 2的0x1000次方的整数倍,也就是下一个内存页的起始处 */ . =ALIGN(0x1000); .data : {*(.data)*(.data.*) } /* small data section, 存储字节数小于某个标准的变量,一般是char, short等类型的 */ .sdata : {*(.sdata)*(.sdata.*) }PROVIDE(edata = .); /* 初始化为零的数据 */ .bss : {*(.bss)*(.bss.*)*(.sbss*) }PROVIDE(end = .); /* /DISCARD/表示忽略,输入文件里 *(.eh_frame .note.GNU-stack)这些section都被忽略,不会加入到输出文件中 *//DISCARD/ : {*(.eh_frame .note.GNU-stack) }}
趣闻
为什么把初始化为0(或者说,无需初始化)的数据段称作bss?
CSAPP 7.4 Relocatable Object files
Aside Why is uninitialized data called .bss? The use of the term .bss to denote uninitialized data is universal. It was originally an acronym for the “block started by symbol” directive from the IBM 704 assembly language (circa 1957) and the acronym has stuck. A simple way to remember the difference between the .data and .bss sections is to think of “bss” as an abbreviation for “Better Save Space!”