1、命令介绍
命令 | 作用 |
---|
KEEP | 保证该段一定在输出文件里,不会被丢弃 |
MEMORY | 描述目标设备的内存情况,内存分几个区域,每个内存区域的属性 |
PROVIDE | 从链接脚本导出符号给C语言或者汇编语言使用 |
ENTRY | 程序入口 |
AT | 指定段的加载地址 |
ALIGN | 指定地址的对齐 |
LOADADDR | 获取段的加载地址 |
2、freeRTOS的链接脚本分析
2.1、freeRTOS的完整链接脚本
OUTPUT_ARCH( "riscv" ) /*输出程序是riscv架构*/
ENTRY( _start ) /*程序的入口是_start标号处*/
MEMORY
{
/* Fake ROM area */
rom (rxa) : ORIGIN = 0x80000000, LENGTH = 512K
ram (wxa) : ORIGIN = 0x80080000, LENGTH = 512K
}
SECTIONS
{
.init :
{
_text = .;
KEEP (*(SORT_NONE(.init))) //保证.init段不会被丢弃
} >rom AT>rom
.text :
{
*(.text.unlikely .text.unlikely.*)
*(.text.startup .text.startup.*)
*(.text .text.*)
*(.gnu.linkonce.t.*)
} >rom AT>rom
.fini :
{
KEEP (*(SORT_NONE(.fini)))
_etext = .;
} >rom AT>rom
.rodata.align :
{
. = ALIGN(4);
_rodata = .;
} >rom AT>rom
.rodata.start :
{
_rodata_lma = LOADADDR(.rodata.start); //获取.rodata.start段的加载地址
} >rom AT>rom
.rodata :
{
*(.rdata)
*(.rodata .rodata.*)
*(.gnu.linkonce.r.*)
. = ALIGN(4);
_erodata = .;
} >rom AT>rom
.data.align :
{
. = ALIGN(4);
_data = .;
} >ram AT>rom
.data.start :
{
_data_lma = LOADADDR(.data.start);
} >ram AT>rom
.data :
{
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 ); //导出符号“__global_pointer$”
*(.sdata .sdata.*)
*(.sdata2 .sdata2.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
. = ALIGN(4); //下一个地址要4字节对齐
_edata = .;
} >ram AT>rom //.data段的链接地址是在ram地址区域,但是加载地址在rom地址区域
.bss.align :
{
. = ALIGN(4);
_bss = .;
} >ram AT>rom
.bss.start :
{
_bss_lma = LOADADDR(.bss.start);
} >ram AT>rom
.bss :
{
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss .bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
} >ram AT>rom
. = ALIGN(8);
_end = .;
.stack :
{
. = ALIGN(16);
. += __stack_size;
_stack_top = .;
} >ram AT>ram
}
2.2、分析.data段的重定位代码
2.3、.data段重定位的实际效果