嵌入式系统链接文件的使用与解析

0X00 链接文件介绍


这里以KEA128芯片,使用KDS编译为例,链接文件顾名思义就是嵌入式工程在链接阶段所要用到的文件,source文件在编译过程完成之后(此时已经是机器可识别的二进制机器码数据),需要再经过链接器从而将二进制数据有序组织起来形成最终的二进制可执行文件,该二进制文件最终会被下载进芯片内部非易失性存储器里。linker文件就是用来指示链接器如何组织编译生成的二进制数据。

0X01 链接文件源文件

/* Linker file for GNU C Compiler */

/* Entry Point */
ENTRY(Reset_Handler)
/* DEFINED(symbol)用于判断symbol在符号表中是否有定义,如果有定义则返回1否则返回0 */
HEAP_SIZE  = DEFINED(__heap_size__)  ? __heap_size__  : 0x00000400;
STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x00000400;
M_VECTOR_RAM_SIZE = DEFINED(__flash_vector_table__) ? 0x0 : 0x00C0;

/*MEMORY
{
  m_interrupts          (RX)  : ORIGIN = 0x00000000, LENGTH = 0x00000100
  m_flash_config        (RX)  : ORIGIN = 0x00000400, LENGTH = 0x00000010
  m_text                (RX)  : ORIGIN = 0x00000410, LENGTH = 0x0001FBF0
  m_data                (RW)  : ORIGIN = 0x1FFFF000, LENGTH = 0x00004000
}*/
__start_sector__ = 32; /*用户程序起始扇区号*/
/* Specify the memory areas *//* 定义内存区域的起始地址和长度 */
MEMORY
{
  /*0扇区,中断向量区*/
  m_interrupts     (RX)  : ORIGIN = 0x00000000, LENGTH = 0x00000100
  /*flash配置区,用于设置flash的配置信息*/
  m_flash_config   (RX)  : ORIGIN = 0x00000400, LENGTH = 0x00000010
  /*~占用前面32个扇区*/
  m_text           (RX)  : ORIGIN = 0x00000410, LENGTH =__start_sector__*0x400- 0x0410
  /*33扇区,放置flash版本固化信息*/
  m_mac_config     (RX)  : ORIGIN = __start_sector__ *0x400, LENGTH = 0x00000400
  /*RAM区,16KB*/
  m_data                (RW)  : ORIGIN = 0x1FFFF000, LENGTH = 0x00004000
}

/* Define output sections */
SECTIONS
{
  /* The startup code goes first into internal flash */
  .interrupts :
  {
    __VECTOR_TABLE = .;
    . = ALIGN(4);
     /*
    isr_vector在start.S中定义:.section .isr_vector, "a",按照MEMORY命令说明,
    isr_vector由于没有指定输出section,因此会创建与输入section同名的输出section,且会按照
    isr_vector的属性放到合适的内存区域,此处KEEP是保证isr_vector的输出section不会被删除
    */
    KEEP(*(.isr_vector))     /* Startup code */
    . = ALIGN(4);
  } > m_interrupts


  .flash_config :
  {
    . = ALIGN(4);
    KEEP(*(.FlashConfig))    /* Flash Configuration Field (FCF) */
    . = ALIGN(4);
  } > m_flash_config

  /* The program code and other data goes into internal flash */
  .text :
  {
    . = ALIGN(4);
    *(.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 */
    *(.eh_frame)
    KEEP (*(.init))
    KEEP (*(.fini))
    . = ALIGN(4);
  } > m_text

  .ARM.extab :
  {
    *(.ARM.extab* .gnu.linkonce.armextab.*)
  } > m_text

  .ARM :
  {
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
  } > m_text

 .ctors :
  {
    __CTOR_LIST__ = .;
    /* gcc uses crtbegin.o to find the start of
       the constructors, so we make sure it is
       first.  Because this is a wildcard, it
       doesn't matter if the user does not
       actually link against crtbegin.o; the
       linker won't look for a file to match a
       wildcard.  The wildcard also means that it
       doesn't matter which directory crtbegin.o
       is in.  */
    KEEP (*crtbegin.o(.ctors))
    KEEP (*crtbegin?.o(.ctors))
    /* We don't want to include the .ctor section from
       from the crtend.o file until after the sorted ctors.
       The .ctor section from the crtend file contains the
       end of ctors marker and it must be last */
    KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors))
    KEEP (*(SORT(.ctors.*)))
    KEEP (*(.ctors))
    __CTOR_END__ = .;
  } > m_text

  .dtors :
  {
    __DTOR_LIST__ = .;
    KEEP (*crtbegin.o(.dtors))
    KEEP (*crtbegin?.o(.dtors))
    KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors))
    KEEP (*(SORT(.dtors.*)))
    KEEP (*(.dtors))
    __DTOR_END__ = .;
  } > m_text

  .preinit_array :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  } > m_text

  .init_array :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
  } > m_text

  .fini_array :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
  } > m_text

  __etext = .;    /* define a global symbol at end of code */
  __DATA_ROM = .; /* Symbol is used by startup for data initialization */

.mac_config :
  {
    . = ALIGN(4);
    KEEP(*(.MacConfig))    /* Flash Configuration Field (FCF) */
    . = ALIGN(4);
  } > m_mac_config

 /* reserve MTB memory at the beginning of m_data */
  /**/
__VECTOR_RAM = DEFINED(__flash_vector_table__) ? ORIGIN(m_interrupts) : __VECTOR_RAM__ ;
 __RAM_VECTOR_TABLE_SIZE = DEFINED(__flash_vector_table__) ? 0x0 : (__interrupts_ram_end__ - __interrupts_ram_start__) ;
 /*vectors*/
    .uservectors :
  {
    . = ALIGN(4);
    __VECTOR_RAM__ = .;
    __interrupts_ram_start__ = .;     /* 定义起点处为__interrupts_ram_start__ */
    . += M_VECTOR_RAM_SIZE;
    . = ALIGN(4);
    __interrupts_ram_end__ = .;     /* 定义结尾处为__interrupts_ram_end__  */
  } > m_data 


  /* reserve MTB memory at the beginning of m_data */
  .mtb : /* MTB buffer address as defined by the hardware */
  {
    . = ALIGN(8);
    _mtb_start = .;
    KEEP(*(.mtb_buf)) /* need to KEEP Micro Trace Buffer as not referenced by application */
    . = ALIGN(8);
    _mtb_end = .;
  } > m_data

  .data : AT(__DATA_ROM)
  {
    . = ALIGN(4);
    __DATA_RAM = .;
    __data_start__ = .;      /* create a global symbol at data start */
    *(.data)                 /* .data sections */
    *(.data*)                /* .data* sections */
    KEEP(*(.jcr*))
    . = ALIGN(4);
    __data_end__ = .;        /* define a global symbol at data end */
  } > m_data

  /* Uninitialized data section 使用直接地址的RAM空间*/
  
  .impinfo :
  {
    . = ALIGN(4);
    KEEP(*(.impinfo*))
    . = ALIGN(4);
  } > m_data
  
  /* Uninitialized data section */
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss section */
    . = ALIGN(4);
    __START_BSS = .;
    __bss_start__ = .;
    *(.bss)
    *(.bss*)
    *(COMMON)
    . = ALIGN(4);
    __bss_end__ = .;
    __END_BSS = .;
  } > m_data

/* Symbol is used by startup for data initialization */
  __DATA_END = __DATA_ROM + (__data_end__ - __data_start__);

  .heap :
  {
    . = ALIGN(8);
    __end__ = .;
    PROVIDE(end = .);
    __HeapBase = .;
    . += HEAP_SIZE;
    __HeapLimit = .;
  } > m_data

  .stack :
  {
    . = ALIGN(8);
    . += STACK_SIZE;
  } > m_data

  /* Initializes stack on the end of block */
  __StackTop   = ORIGIN(m_data) + LENGTH(m_data);
  __StackLimit = __StackTop - STACK_SIZE;
  PROVIDE(__stack = __StackTop);

  .ARM.attributes 0 : { *(.ARM.attributes) }
  
  ASSERT(__StackLimit >= __HeapLimit, "region m_data overflowed with stack and heap")
}

0X01 链接文件详细解析

/* Entry Point */
ENTRY(Reset_Handler)

程序入口点,进入到启动文件的Reset_Handler函数中,有关于Reset_Handler 函数的解析请看另一篇关于中断向量表的文章。

HEAP_SIZE  = DEFINED(__heap_size__)  ? __heap_size__  : 0x00000400;
STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x00000400;
M_VECTOR_RAM_SIZE = DEFINED(__flash_vector_table__) ? 0x0 : 0x00C0;

DEFINED(symbol)用于判断symbol在符号表中是否有定义,如果有定义则返回1否则返回0
设堆栈与中断向量表大小,HEAP_SIZE与STACK_SIZE的大小为1KB,M_VECTOR_RAM_SIZE大小为192B。

__start_sector__ = 32; /*用户程序起始扇区号*/
/* 定义内存区域的起始地址和长度 */
MEMORY
{
  /*0扇区,中断向量区*/
  m_interrupts     (RX)  : ORIGIN = 0x00000000, LENGTH = 0x00000100
  /*flash配置区,用于设置flash的配置信息*/
  m_flash_config   (RX)  : ORIGIN = 0x00000400, LENGTH = 0x00000010
  /*~占用前面32个扇区*/
  m_text           (RX)  : ORIGIN = 0x00000410, LENGTH =__start_sector__*0x400- 0x0410
  /*33扇区,放置flash版本固化信息*/
  m_mac_config     (RX)  : ORIGIN = __start_sector__ *0x400, LENGTH = 0x00000400
  /*RAM区,16KB*/
  m_data                (RW)  : ORIGIN = 0x1FFFF000, LENGTH = 0x00004000
}

定义内存区域,用户起始扇区为32扇区号。中断向量区扇区号0-256。flash配置区扇区号1024-1040。 m_text(代码区) 起始扇区号1040,长度通过用户扇区计算。m_mac_config(flash版本信息)32个扇区。m_data(数据区)占用16384个扇区。

  /* The startup code goes first into internal flash */
  .interrupts :
  {
    __VECTOR_TABLE = .;
    . = ALIGN(4);
     /*
    isr_vector在start.S中定义:.section .isr_vector, "a",按照MEMORY命令说明,
    isr_vector由于没有指定输出section,因此会创建与输入section同名的输出section,且会按照
    isr_vector的属性放到合适的内存区域,此处KEEP是保证isr_vector的输出section不会被删除
    */
    KEEP(*(.isr_vector))     /* Startup code */
    . = ALIGN(4);
  } > m_interrupts

中断向量表的地址全部都链接到0x00000000,采用4字节方式。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值