from:http://www.hertaville.com/a-sample-linker-script.html

A sample script file that will work with C based projects is provided below:

/******************************************************************************
* This linker file was developed by Hussam Al-Hertani. Please use freely as
* long as you leave this header in place. The author is not responsible for any
* damage or liability that this file might cause.
******************************************************************************/ /* Entry Point */
ENTRY(Reset_Handler) /* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 0x10000 /*64K*/
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x02000 /*8K*/
} /* define stack size and heap size here */
stack_size = ;
heap_size = ; /* define beginning and ending of stack */
_stack_start = ORIGIN(RAM)+LENGTH(RAM);
_stack_end = _stack_start - stack_size; /* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN();
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN();
} >FLASH /* The program code and other data goes into FLASH */
.text :
{
. = ALIGN();
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
. = ALIGN();
_etext = .; /* define a global symbols at end of code */
} >FLASH .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH /* used by the startup to initialize data */
_sidata = .; /* Initialized data sections goes into RAM, load LMA copy after code */
.data : AT ( _sidata )
{
. = ALIGN();
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */ . = ALIGN();
_edata = .; /* define a global symbol at data end */
} >RAM /* Uninitialized data section */
. = ALIGN();
.bss :
{
/* Used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON) . = ALIGN();
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM . = ALIGN();
.heap :
{
_heap_start = .;
. = . + heap_size;
_heap_end = .;
} > RAM /* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
} .ARM.attributes : { *(.ARM.attributes) }
}

The Linker script is somewhat self documenting. I will briefly go through the various sections. The first line of the linker script is:

ENTRY(Reset_Handler)

This defines the entry point into the chip. On exit from a reset condition, the first thing that the MCU executes is a reset handler function that initializes the chip and puts it in a known state. To view this handler (interrupt subroutine (ISR)) function take a look at the startup file.

The linker script then defines the sections of the memory map that in to which it will map the various sections of the object files. It does this in "Memory" section.

/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 0x10000 /*64K*/
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x02000 /*8K*/
}

The memory map of the STM32F051C8 chip is shown in Page 35 of the datasheet . It shows that the Flash memory section starts at address 0x08000000 and is 64KB long or 65536 bytes long which in hex is 0x10000. The RAM memory section starts a address 0x20000000 and is 8KB long or 8192 bytes long, which in hex is 0x02000 . All of this information is provided to the linker via the memory section of the linker script. Also note the the FLASH memory s defined as (rx) which means that it has read and execute only, whereas the RAM memory is defined as (xrw) which means that it is read, write and execute.

The next major section of the linker script is called "SECTIONS". It defines where each if the various sections of the object files goes into the memory map defined in the MEMORY section.

The first section defined under SECTIONS is the .isr_vector section. This section contains the interrupt vector table and the startup / initialization code i.e. the body of the Reset handler routine specified as the entry point. This is put first in flash memory starting at 0x08000000 as specified by the ">FLASH" found at the end of the section.

/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN();
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN();
} >FLASH

The ALIGN(4) instructions tells the linker that this section ought to be word aligned. Since this is a 32-bit machine it typically needs to be word aligned (32-bit -> 4 bytes hence the '4' specified with the align command. )

/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN();
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
. = ALIGN();
_etext = .; /* define a global symbols at end of code */
} >FLASH

The next section of the linker script is the .text section. This section includes all the .text sections from the object files. These .text sections contain all the binary instructions that our c and assembly programs were compiled/assembled into and are typically put in program memory, which in this case is flash. Notice that this section also contains .rodata sections which signifies that right after the linker has put the binary instructions into the program memory, it should but the constant data in their as well. At this point in time I'm not quite sure of the .glue_7 sections but I think they have to do with backwards compatibility between arm and thumb instructions. They are probably not needed. ofcourse this entire section .text section is put in Flash via the ">FLASH" linker instruction.

.ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH

The following .ARM.extab section has to do with table/loop unwinding. I have found little information on it. I have included it here even though I know that I probably do not need it.

/* Initialized data sections goes into RAM, load LMA copy after code */
.data : AT ( _sidata )
{
. = ALIGN();
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */ . = ALIGN();
_edata = .; /* define a global symbol at data end */
} >RAM

The .data section contains all initialized global and static variables. the "AT" basically means that this code will be put in both (via LMA initializer) Flash and RAM. To explain this further the static and global variables of the .data section need to be stored in two different locations:

  • VMA (virtual memory address): the run-time address where the compiled code expects the variables to be. This will be in RAM as signified by ">RAM".
  • LMA (load memory address): the addresses to which the initialization data are stored by the linker. This will be in Flash as signified by the "AT".

The startup code will copy from .data section's LMA to .data section's VMA.

/* Uninitialized data section */
. = ALIGN();
.bss :
{
/* Used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON) . = ALIGN();
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM

The next section of the linker script is the .bss section. The .bss section consists of uninitialized static and global variables. This section is saved in RAM.

. = ALIGN();
.heap :
{
_heap_start = .;
. = . + heap_size;
_heap_end = .;
} > RAM

The next  section define the heap section of RAM. The heap starts right after the bss section and continues on until the heap size specified by the heap_size variable at the beginning of the script. With the exception of the stack, all other sections grow upwards. The stack grows downwards. This basically means that the stack starts at the last location in the RAM which is 0x20002000 and grows downwards from their via the "stack_size" variable. Both the "stack_size" and the "heap_size" variables control the sizes of the stack and heap respectively. They must be sized such that both sections never overlap i.e. the sum of the two variables and the sizes of the data(VMA) and bss sections, must never be larger than the 8192.

Because the linker needs to specify memory sections in an upwards / growing fashion, we used the _stack_begin label, which basically is assigned to the address 0x20002000 and the stack size to determine the value of the _stack_end variable in the top of the script. This is used to decide where the stack section starts from the perspective of the linker.

Figure 1 represents the linker file rules graphically and demonstrates how the various sections are mapped into the Flash and RAM memories. The labels such as _etext, _sdata, _edata e.t.c define the begin and/or end addresses for each section.

Figure 1. Graphical representation of the rules defined in the linker file

The final sections ensure that no redundant code from the standard libraries is included into memory. I do not know the purpose of the ".ARM.attributes 0" line either. The linker files would very likely function just fine without, but I will keep them for the time being.

 /* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
} .ARM.attributes : { *(.ARM.attributes) }
}

This concludes our explanation of (most of) the linker file sections and its structure.

A Sample Linker Script的更多相关文章

  1. Linux Kernel系列三:Kernel编译和链接中的linker script语法详解

    先要讲讲这个问题是怎么来的.(咱们在分析一个技术的时候,先要考虑它是想解决什么问题,或者学习新知识的时候,要清楚这个知识的目的是什么). 我在编译内核的时候,发现arch/arm/kernel目录下有 ...

  2. openMSP430之Custom linker script

    The use of the -mmcu switch is of course NOT mandatory. It is simply a convenient way to use the pre ...

  3. 链接脚本(Linker Script)用法解析(一) 关键字SECTIONS与MEMORY

    1.MEMORY关键字用于描述一个MCU ROM和RAM的内存地址分布(Memory Map),MEMORY中所做的内存描述主要用于SECTIONS中LMA和VMA的定义. 2.SECTIONS关键字 ...

  4. 链接脚本(Linker Script)应用实例(一)使用copy table将函数载入到RAM中运行

    将函数载入到RAM中运行需要以下三个步骤: (1)用编译器命令#pragma section "<section name>" <user functions&g ...

  5. 链接脚本(Linker Script)用法解析(二) clear_table & copy_table

    可执行文件中的.bss段和.data段分别存放未赋初值的全局变量和已赋初值的全局变量,两者的特点分别为: (1).bss段:①无初值,所以不占ROM空间:②运行时存储于RAM:③默认初值为0 (2). ...

  6. GNU linker script,ld script,GNU链接脚本

    https://blog.csdn.net/itxiebo/article/details/50937412 https://blog.csdn.net/itxiebo/article/details ...

  7. Linux Linker Script

    先推荐两个网页: http://blog.csdn.net/muyuyuzhong/article/details/7755291 http://www.cnblogs.com/liulipeng/a ...

  8. Linker scripts之MEMORY

    1 MEMORY command The MEMORY command describes the location and size of blocks of memory in the targe ...

  9. Linker scripts之Intro

    1 Intro Every link is controlled by a linker script. The main purpose of the linker script is to des ...

随机推荐

  1. js面向对象实例

    JSON方式来编写对象简单 不适合多个对象 var json={a:12, show:function (){ alert(this); }};json.show(); //理所当然弹出的是objec ...

  2. java日志的相关配置文件知识

    w2bc.com/article/261758”“”“

  3. 从输入 URL 到页面加载完成的过程详解---【XUEBIG】

    从输入 URL 到页面加载完成的过程中都发生了什么事情? 这是一道经典的面试题,涉及面非常广,要答出来并不困难,当要将问题回答好却不是那么容易 过程概述 浏览器查找域名对应的 IP 地址: 浏览器根据 ...

  4. RabbitMQ快速入门

    最近一段项目实践中大量使用了基于RabbitMQ的消息中间件,也积累的一些经验和思考,特此成文,望大家不吝赐教. 本文包括RabbitMQ基本概念.进阶概念.实践与思考等三部分,着重强调相关概念和基于 ...

  5. 利用Fiddler拦截接口请求并篡改数据

    近期在测试一个下单的项目,出于安全角度考虑,测试了一个场景,那就是利用工具对接口进行拦截并篡改数据.将接口一拦截并篡改数据后,发现收货满满.开发默默接受了我的建议,并对代码进行了修改. 对于fiddl ...

  6. mybatis查询语句的背后之封装数据

    转载请注明出处... 一.前言 继上一篇mybatis查询语句的背后,这一篇主要围绕着mybatis查询的后期操作,即跟数据库交互的时候.由于本人也是一边学习源码一边记录,内容难免有错误或不足之处,还 ...

  7. ORA-01000

    A ResultSet object is automatically closed by the Statement object that generated it when that State ...

  8. Err.number错误号和可捕获的 Microsoft access 数据库引擎和 DAO错误说明

    错误码        信息2420        数字语法错误2421        日期语法错误2422        字符串语法错误2423        ‘.’.‘!’.或 ‘()’的使用无效2 ...

  9. [HNOI2007]神奇游乐园

    Description: 在方格图上找一条回路使经过的权值最小 Hint: \(n<=100,m<=6\) Solution: 一开始又看错题了...稍有细节的水题,详见代码 #inclu ...

  10. Mac + OpenCV3.3.0 + PyCharm (非常简单的配置过程)

    最近要用python来写opencv,主要是需要学习计算机视觉和机器学习.看了网上的配置过程,愣是把一件简单的事搞复杂了. 话不多说,配环境走起! 打开PyCharm,找到Preferences 尝试 ...