ARM 链接脚本分析
分析连接脚本的语法规则
/* ----------------------------------------------------------------------------
* Memory linker description
* ------------------------------------------------------------------------- */
MEMORY
{
/* ROM区,只读, 起始地址0x00000000, 长度4K */
ROM (r) : ORIGIN = 0x00000000, LENGTH = 4K
/* FLASH区, 读,写,可执行, 起始地址0x00100000, 长度380K*/
FLASH (xrw) : ORIGIN = 0x00100000, LENGTH = 380K
/* PRAM , 32K */
PRAM (xrw) : ORIGIN = 0x00200000, LENGTH = 32K
DRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 24K
DRAM_DSP (xrw) : ORIGIN = 0x20006000, LENGTH = 48K
DRAM_BB (xrw) : ORIGIN = 0x20012000, LENGTH = 16K
}
/* ----------------------------------------------------------------------------
* Stack related defines and provided variables
* ------------------------------------------------------------------------- */
/* 计算stack的地址 */
__stack = ORIGIN(DRAM) + LENGTH(DRAM);
/* 全局变量__stack, c语言可以应用 */
PROVIDE ( __stack = __stack ) ;
/*
* Default stack sizes.
* These are used by the startup in order to allocate stacks
* for the different modes.
*/
__Main_Stack_Size = 1024 ;
PROVIDE ( _Main_Stack_Size = __Main_Stack_Size ) ;
__Main_Stack_Limit = __stack - __Main_Stack_Size ;
PROVIDE ( _Main_Stack_Limit = __Main_Stack_Limit ) ;
/* ----------------------------------------------------------------------------
* Heap related defines and provided variables
* ------------------------------------------------------------------------- */
PROVIDE ( __Heap_Begin__ = __noinit_end__ ) ;
PROVIDE ( __Heap_Limit__ = __stack - __Main_Stack_Size ) ;
/*
* The entry point is informative, for debuggers and simulators,
* since the Cortex-M vector points to it anyway.
*/
/* 指定可执行文件的起始代码段是Reset_Handler */
ENTRY(Reset_Handler)
/*
* As is the VTOR register, we refer to it in startup documentation
*/
__VTOR = 0xE000ED08;
/* ----------------------------------------------------------------------------
* Section definitions
* ------------------------------------------------------------------------- */
SECTIONS
{
/*
* For Cortex-M devices, the beginning of the startup code is stored in
* the .interrupt_vector section, which goes to FLASH
*/
/* DEFINED判断括号内的__app_rom_start,是否在全局符号表内,并且定义了,是就返回1,否返回0
* 再根据DEFINED结果进行判断__rom_start的值,是__app_rom_start,还是ORIGIN(FLASH)
*/
__rom_start = DEFINED(__app_rom_start) ? __app_rom_start : ORIGIN(FLASH);
/* 计算image的大小 */
__image_size = __data_init__ + SIZEOF(.data) - __rom_start;
/* .text代码段, 保存在FLASH中,FLASH起始地址0x0010000*/
.text __rom_start :
{
/* 四字节对齐 */
. = ALIGN(4);
/* 强制链接器保留一些特定的section */
KEEP(*(.interrupt_vector))
/*
* This section is here to store the startup code immediately after
* the interrupt vectors, as required by the program ROM.
*/
/* 所有文件的reset段,都放在interrupt_vector段后面 */
*(.reset)
/*
* FOTA BootLoader descriptor
*/
*(.rodata.fota.image-size)
KEEP(*(.rodata.fota.build-id))
/*
* FOTA version descriptor
*/
/* 所有的.rodata.boot.version section 放到.text section里面*/
*(.rodata.boot.version)
/* Pre-initialization Code */
. = ALIGN(4);
PROVIDE_HIDDEN (__preinit_array_start__ = .);
/* System initialization and the platform initialization (if present)
* should be first */
KEEP(*(.preinit_array_sysinit .preinit_array_sysinit.*))
KEEP(*(.preinit_array_platform .preinit_array_platform.*))
/* Pre-initialization functions (to be executed before C++
* constructors are run) */
KEEP(*(.preinit_array .preinit_array.*))
PROVIDE_HIDDEN (__preinit_array_end__ = .);
/* Initialization Code */
. = ALIGN(4);
PROVIDE_HIDDEN (__init_array_start__ = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end__ = .);
/*
* The program code is stored in the .text section,
* which goes to FLASH.
*/
. = ALIGN(4);
/* 所有的文件的.text section*/
*(.text .text.*) /* all remaining code */
/* 所有文件的.rodata section */
*(.rodata .rodata.*) /* read-only data (constants) */
. = ALIGN(4);
__dsp_start__ = . ;
KEEP(*(.dsp .dsp.*)) /* all remaining DSP code */
__dsp_end__ = . ;
/* 四字节对齐 */
. = ALIGN(4);
/* .text全部链接到FLASH里面,Flash是前面MEMORY里面定义的,起始地址是0x00100000 */
} >FLASH
/*
* This address is used by the startup code to
* initialize the .data section.
*/
. = ALIGN(4);
/* 将定位符号'.'的值赋给__data_init */
/* 也就是说__data_init__放在.text段的后面 */
__data_init__ = .;
/* Place the SystemClock variable needed for CMSIS in a place that is
* compatible with the ROM's placement of this variable so that the
* variable can be used by CMSIS and the ROM's flash write libary */
.systemclock (NOLOAD) :
{
. = ALIGN(4);
KEEP(*(.systemclock))
/* 保存到DRAM中 */
} > DRAM
/*
* The initialized data section.
* The program executes knowing that the data is in the RAM
* but the loader puts the initial values in the FLASH (inidata).
* It is one task of the startup to copy the initial values from
* FLASH to RAM.
*/
/* 查看__app_ram_start是否定义,并给__ram_start赋值 */
__ram_start = DEFINED(__app_ram_start) ? __app_ram_start : .;
/* .data数据段 */
/* AT表示加载地址或者存储地址,指程序编译之后存放的地址,一般在ROM或者FLASH中 */
/* 运行的时候,从AT指定的地址__data_init__中赋值到_ram_start中运行 */
/* 从FLASH中复制到RAM里面运行 */
.data __ram_start : AT ( __data_init__ )
{
. = ALIGN(4);
/* This is used by the startup code to initialize the .data section */
__data_start__ = . ;
*(.data_begin .data_begin.*)
*(.data .data.*)
*(.data_end .data_end.*)
. = ALIGN(4);
/* This is used by the startup code to initialize the .data section */
__data_end__ = . ;
} >DRAM
/*
* The uninitialized data section. NOLOAD is used to avoid
* the "section `.bss' type changed to PROGBITS" warning
*/
/* .bss未初始化的数据段, 存放在DRAM中 */
.bss (NOLOAD) :
{
. = ALIGN(4);
__bss_start__ = .; // 把__bss_start_段赋值当前位置,bss段的起始位置
*(.bss_begin .bss_begin.*) // 所有的bss_begin和bss_begin.*段放到bss里面
*(.bss .bss.*) // 所有文件的.bss和.bss.*段放在bss_begin,bss_begin.*后面
*(COMMON) // COMMON放在.bss,.bss.*后面
*(.bss_end .bss_end.*) // 所有文件的.bss_end, .bss_end.* 放在COMMON后面
. = ALIGN(4);
__bss_end__ = .; // 把__bss_end__段赋值为当前位置,结束位置
} >DRAM
.noinit (NOLOAD) :
{
. = ALIGN(4);
__noinit_start__ = .;
*(.noinit .noinit.*)
. = ALIGN(4) ;
__noinit_end__ = .;
} > DRAM
/* Check if there is enough space to allocate the main stack */
._stack (NOLOAD) :
{
. = ALIGN(4);
. = . + __Main_Stack_Size ; // 计算栈的大小放到DRAM中
. = ALIGN(4);
} >DRAM
}
ARM 链接脚本分析的更多相关文章
- u-boot链接脚本分析
eclipse 64位下载地址:http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release ...
- Linux 链接脚本分析
作者:答疑助手lizuobin 原文: https://blog.csdn.net/lizuobin2/article/details/51779064 在前面学习的过程中,看代码时遇到 arch_i ...
- arm链接脚本
一. 为什么需要链接脚本 1.1. 从源码到可执行程序(主要有三个步骤:预编译.编译.链接) 1.1.1. 预编译 a. 预编译器执行.譬如C中的宏定义就是由预编译器处理,注释等也是由预编译器处理的. ...
- u-boot.lds 链接脚本分析(hi3515)
目录:/u-boot_hi3515/board/hi3515v100 OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm& ...
- 四、u-boot 链接脚本
4.1 C语言中的段 编译器在编译程序的时候,将程序中的所有的元素分成了一些组成部分,各部分构成一个段,所以说段是可执行程序的组成部分. 代码段:代码段就是程序中的可执行部分,直观理解代码段就是函数堆 ...
- arm裸板驱动总结(makefile+lds链接脚本+裸板调试)
在裸板2440中,当我们使用nand启动时,2440会自动将前4k字节复制到内部sram中,如下图所示: 然而此时的SDRAM.nandflash的控制时序等都还没初始化,所以我们就只能使用前0~40 ...
- 驱动开发学习笔记. 0.07 Uboot链接地址 加载地址 和 链接脚本地址
驱动开发学习笔记. 0.07 Uboot链接地址 加载地址 和 链接脚本地址 最近重新看了乾龙_Heron的<ARM 上电启动及 Uboot 代码分析>(下简称<代码分析>) ...
- makefile使用.lds链接脚本以及 $@ ,$^, $,< 解析
先来分析一个简单的.lds链接脚本 例1,假如现在有head.c init.c nand.c main.c这4个文件: 1.1 首先创建链接脚本nand.lds: SECTIONS { firtst ...
- makefile使用.lds链接脚本以及 $@ ,$^, $,< 解析【转】
转自:http://www.cnblogs.com/lifexy/p/7089873.html 先来分析一个简单的.lds链接脚本 例1,假如现在有head.c init.c nand.c main. ...
随机推荐
- 【比赛游记】(THUPC,CTS,APIO)2019四连爆蛋记
5 月 11 日 坐飞机来到帝都,报道 THUPC. 试机题有皮配,不会. 晚上吃全聚德,喝星巴克.奢侈. 5 月 12 日 早上打 THUPC. 咕到 9 点半开始,到 2 点半结束.
- CodeForces - 1037H: Security(SAM+线段树合并)
题意:给定字符串S: Q次询问,每次询问给出(L,R,T),让你在S[L,R]里面找一个字典序最小的子串,其字典序比T大. 没有则输出-1: 思路:比T字典序大,而且要求字典最小,显然就是在T的尾巴 ...
- JMeter【第一篇】jmeter5.1在windows(含插件安装)及linux环境下安装
jmeter下载 前提:已经安装jdk8+ jmeter下载地址:http://jmeter.apache.org/download_jmeter.cgi 有Binaries和Source版本 前者是 ...
- 【转】Web测试中定位bug方法
在web测试过程中,经常会遇到页面中内容或数据显示错误,甚至不显示,第一反应就是BUG,进一步了解这个BUG的问题出在那里,是测试人员需要掌握的,可以简单的使用浏览器自带开发者工具.数据库工具配合去排 ...
- reactnative 笔记
1.<FlatList/> _renderItem = ({item})=>{ return <View style={[styles.part4Row]}> <T ...
- (知识点3)附加到数字的“.f”的目的是什么?
默认情况下3.2被视为double; 所以为了强制编译器将其视为float,你需要f在最后编写. float a = 3.2; if ( a == 3.2 ) cout << " ...
- Openwrt build env setup(9)
reference : https://openwrt.org/docs/guide-developer/quickstart-build-images Install dependence pack ...
- 使用jenkins exporter 监控jenkins 构建任务
jenkins 提供了rest api,我们可以基于rest api 暴露prometheus metrics,社区已经有了好多 开源的实现了,使用起来也比较方便,以下集成几个进行简单的测试 环境准备 ...
- Reactive Extensions (Rx) 入门(3) —— Rx的事件编程
译文:https://blog.csdn.net/fangxing80/article/details/7628322 原文:http://www.atmarkit.co.jp/fdotnet/int ...
- 切比雪夫定理(Chebyshev's theorem)与经验法则(Empirical Rule)
切比雪夫定理(Chebyshev's theorem):适用于任何数据集,而不论数据的分布情况如何. 与平均数的距离在z个标准差之内的数值所占的比例至少为(1-1/z2),其中z是大于1的任意实数. ...