SylixOS启动脚本分析

      本周学习了一些ARM指令、伪指令、链接脚本命令等,并对整个编译过程、elf文件有了更加深入的理解。ARM指令在ARM架构参考手册里面有了详细的介绍,这里不再列出,以下是一些GCC链接脚本命令的分析。
      以SylixOS启动脚本为例,分析一下链接脚本相关命令。SylixOS链接文件包括config.h、config.lds、SylixOSBSP.ld,它们位于BSP板级支持包根目录内。

      config.h文件定义了RAM、ROM的基址和大小,定义了TXET、DATA、DMA、APP段的大小,config.h文件定义如下:
/****************************************************************
  ROM RAM 相关配置
****************************************************************/
#define BSP_CFG_ROM_BASE (0x00000000)
#define BSP_CFG_ROM_SIZE (4 * 1024 * 1024)
#define BSP_CFG_RAM_BASE (0x30000000)
#define BSP_CFG_RAM_SIZE (64 * 1024 * 1024)
#define BSP_CFG_TEXT_SIZE (6 * 1024 * 1024)
#define BSP_CFG_DATA_SIZE (18 * 1024 * 1024)
#define BSP_CFG_DMA_SIZE (6 * 1024 * 1024)
#define BSP_CFG_APP_SIZE (34 * 1024 * 1024)

#define BSP_CFG_BOOT_STACK_SIZE (128 * 1024)

       config.lds文件定义如下:
MEMORY
{
  TEXT (rx) : ORIGIN = (0x30000000), LENGTH =(6 * 1024 * 1024)
  DATA (rw) : ORIGIN = (0x30000000) + ((6 *1024 * 1024)), LENGTH = (18 * 1024 * 1024)
}
BOOT_STACK_SIZE = (128 * 1024);

       MEMORY命令用来描述目标内存块的位置和大小,config.lds文件定义了两个内存块区域,TEXT(可读可执行)和DATA(可读可写),ORIGIN表示内存区域的起始地址,LENGTH表示内存长度。
       SylixOSBSP.ld文件定义如下:
INCLUDE "config.lds"

OUTPUT_FORMAT(elf32-littlearm)                     /*  二进制文件格式             */
OUTPUT_ARCH(ARM)                                     /* ARM架构                    */

/*
*  SECTIONS命令告诉编译器如何将输入段映射到输出段,以及输出段在内存中的位置
*/
SECTIONS
{
/***************************************************************************
    代码段  LMA == VMA== ORIGIN(TEXT)
    ORIGIN(TEXT)表示TEXT内存块区域的起始地址
    .text段是可执行代码段
***************************************************************************/
    .text : {
       *(.vector)
       *(.text)
       *(.text.*)                                 /* cpp namespace function      */
       *(.romrun)                                 /*  ROM 中必须的函数               */
       *(.rodata)                                /* read-only data (constants)  */
       *(.rodata*)
       *(.glue_7)
       *(.glue_7t)
    } >TEXT                                        /* >TEXT表示该段属于TEXT内存块 */

/***************************************************************************
    GOT
***************************************************************************/
    .got : {
       *(.got.plt)
       *(.got)
    } >TEXT

/***************************************************************************
    .ARM.exidxis sorted, so has to go in its own output section.
***************************************************************************/
    .ARM.exidx: {
        . =ALIGN(4);
       PROVIDE(__exidx_start = .);

       *(.ARM.exidx* .gnu.linkonce.armexidx.*)

        . =ALIGN(4);
       PROVIDE(__exidx_end = .);
    } >TEXT

/***************************************************************************
    .data 段数据初始化内容放在这里
    PROVIDE用来定义一个符号(如果程序中定义则忽略该定义,使用程序中定义的)
    它的语法是  PROVIDE(symbol= expression)
***************************************************************************/
    . =ALIGN(4);
    PROVIDE(_etext = .);

/***************************************************************************
     数据段
     .data 段运行地址 VMA 为 ORIGIN(DATA), 装载地址 LMA 为 _etext,
     连接器会将 .data 的初始化数据放在 _etext 的地方, 然后启动程序必须将 _etext 的内容搬运到
     VMAORIGIN(DATA) 中. 大小等于 SIZEOF(.data)

     下面的定义说明.data段的运行地址是DATA内存块的首地址,装载地址为_etext(AT命令指定)
     从.data段开始,程序的装载地址和运行地址均不相同,个人理解
***************************************************************************/
    .dataORIGIN(DATA) : AT (_etext) {
        . =ALIGN(4);
       PROVIDE (_data = .);

       *(.data)

        . =ALIGN(4);
       PROVIDE (_edata = .);
    } >DATA

/***************************************************************************
    清零段
    NOLOAD 表示不装载, 启动程序只需要借助 __bss_start 和 __bss_end 两个符号指定的起始地址和结束地址
    将 .bss 区域清零即可. (注意 *.noinit 可以不进行清零)
***************************************************************************/
    .bss(NOLOAD) : {
        . =ALIGN(4);
       *(.noinit)

        . =ALIGN(4);
        PROVIDE (__bss_start = .);

       *(.bss)

        . =ALIGN(4);
       *(COMMON)

        . =ALIGN(4);
       PROVIDE (__bss_end = .);
    } >DATA

/***************************************************************************
    栈段

    SylixOS 启动时使用,异常入口也使用
***************************************************************************/
    .stack (NOLOAD) : {
        . =ALIGN(8);
       PROVIDE (__stack_start = .);

        . +=BOOT_STACK_SIZE;

        . =ALIGN(8);
       PROVIDE (__stack_end = .);
    } >DATA

/***************************************************************************
    内核堆段
***************************************************************************/
    .heap(NOLOAD) : {
        . =ALIGN(8);
       PROVIDE (__heap_start = .);

       __heap_end = ORIGIN(DATA) + LENGTH(DATA) - 128;
       PROVIDE (__heap_end = .);
    } >DATA
}
      由于.data段的装载地址与运行地址不相同,那么在C代码运行之前,需要汇编去实现将.data段的数据从装载地址拷贝到运行地址处,然后程序才可以正常运行。初始化代码在startup.S中实现。
      至于.bss段、.stack段、.heap段,里面的值并不重要,不需要装载进BIN文件,只需记录它们的起始地址和结束地址,再进行相应操作即可。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值