为什么arm-none-eabi-ld链接器在单个转换单元中留下填充字节?

时间:2015-03-04 16:59:24

标签: c gcc linker arm

我得到了一些评估板,其中包含uC STM32F405RG,此微观有ARM Cortext M4 core。请参考uC:

http://www.st.com/web/catalog/mmc/FM141/SC1169/SS1577/LN1035/PF252144#

我还从以下网站使用arm-none-eabi工具链用于linux:

https://launchpad.net/gcc-arm-embedded

在编译和链接某个项目之后,我注意到链接器在我的全局变量之间放置了额外的填充字节,这些变量存储在.bss部分中。请从地图文件中找到简短的片段:

 .bss.variable1
                0x20002d14       0x15 /path/to/application.o
 .bss.variable2
                0x20002d29        0x1 /path/to/application.o
 .bss.variable3
                0x20002d2a        0x1 /path/to/application.o
 .bss.variable4
                0x20002d2b        0x1 /path/to/application.o
 .bss.variable5
                0x20002d2c       0x1c /path/to/application.o
 .bss.variable6
                0x20002d48        0x1 /path/to/application.o
 *fill*         0x20002d49        0x3
 .bss.variable7
                0x20002d4c        0x4 /path/to/application.o
 .bss.variable8
                0x20002d50        0x8 /path/to/application.o
 .bss.variable9
                0x20002d58       0x1c /path/to/application.o
 .bss.variable10
                0x20002d74        0x1 /path/to/application.o

此外是我的链接器脚本:

ENTRY(Reset_Handler)

MEMORY
{
  FLASH (rx)      : ORIGIN = 0x08000000 + 256K, LENGTH = 1M - 256K -(3*128K)
  RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 128K
  MEMORY_B1 (rx)  : ORIGIN = 0x60000000, LENGTH = 0K
}

_stack_size = 16K;

_estack = ORIGIN(RAM) + LENGTH(RAM);
_sstack = _estack - _stack_size;

SECTIONS
{  
  .text :
  {
    _stext = .;
    KEEP(*(.isr_vector))
    . += 8;
    *(.text)
    *(.text*)
    *(.rodata)
    *(.rodata*)
    *(.glue_7)
    *(.glue_7t)
    *(.eh_frame)
    KEEP (*(.init))
    KEEP (*(.fini))
    . = ALIGN(4);
    _etext = .;
  } >FLASH

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

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

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

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

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

  _sidata = .;

  .data :
  {
    . = ALIGN(4);
    _sdata = .;
    *(.data)
    *(.data*)
    . = ALIGN(4);
    _edata = .;
  } >RAM AT> FLASH

  . = ALIGN(4);

  .bss :
  {
    _sbss = .;
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)
    . = ALIGN(4);
    _ebss = .;
    __bss_end__ = _ebss;
  } >RAM

  .stack :
  {
    . += _stack_size;
  } >RAM

  .memory_b1_text :
  {
    *(.mb1text)        /* .mb1text sections (code) */
    *(.mb1text*)       /* .mb1text* sections (code)  */
    *(.mb1rodata)      /* read-only data (constants) */
    *(.mb1rodata*)
  } >MEMORY_B1

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

  .ARM.attributes 0 : { *(.ARM.attributes) }
}

这是类型声明,它们分布在几个头文件中,但我将它们放在这里:

typedef enum
{
    False=0,
    True=1
} bool;

typedef enum
{
    Unknown,
    Data,
    Crc
} type3_t;

typedef struct
{
    unsigned char data[20];
    unsigned char size;
} __attribute__((packed)) type1_t;

typedef enum
{
    msg1,
    msg2,
    msg3
} msg_type_t

typedef struct
{
    uint8_t msg;
    uint32_t src;
    uint32_t dest;
} header_t;

typedef struct
{
    header_t header;
    uint8_t len;
    uint8_t id;
    uint8_t idx;
    uint8_t type;
} header2_t;

typedef struct
{
    header2_t header;
    uint8_t* data;
} ex_header_t;

typedef struct
{
    msg_type_t type;
    union
    {
        uint8_t * rawData;
        header_t header;
        ex_header_t ex_header;
    } u;
    uint8_t val;
} type5_t;

typedef struct
{
    uint32_t id;
    uint8_t idx;
    uint8_t crc[2];
} type8_t;

和application.c文件,我在* .c文件中保留了命令:

static type5_t variable5;
static type5_t variable9;
static type8_t variable8;
static type3_t variable3 = Unknown;
static type1_t variable1;
static bool variable10 = False;
static unsigned char variable6 = 0;
static bool variable4;
static unsigned char variable2 = 0;
/* few function definitions here */
static void * variable7;

问题是为什么arm-none-eabi-ld链接器正在这样做?为什么链接器不能代替填充字节,一个字节大的变量(例如字符)?一切都发生在同一个翻译单元中,所以我认为链接器应该能够对它们进行排序并利用更多的RAM内存。即使同一个转换单元中不存在一个字节(char)或两个字节变量(short),为什么链接器不能从其他* .o文件中获取它们?

0 个答案:

没有答案
相关问题