Arrays multiple definition errors during linking

194 views Asked by At

I'm trying to make GNUK software buildable with PlatformIO system. I have converted Makefile to platformio.ini project file, all source files compile well, but I'm getting linker multiple definition errors for two of the arrays defined in one of my C source files. The relevant part of my source file is:

typedef void (*handler)(void);

handler vector[] __attribute__ ((section(".vectors"))) = {
  (handler)&__ram_end__,
  reset,
  (handler)set_led,
  flash_unlock,
  (handler)flash_program_halfword,
  (handler)flash_erase_page,
  (handler)flash_check_blank,
  (handler)flash_write,
  (handler)flash_protect,
  (handler)flash_erase_all_and_exec,
  usb_lld_sys_init,
  usb_lld_sys_shutdown,
  nvic_system_reset,
};

const uint8_t sys_version[8] __attribute__((section(".sys.version"))) = {
  3*2+2,         /* bLength */
  0x03,          /* bDescriptorType = USB_STRING_DESCRIPTOR_TYPE*/
  /* sys version: "1.0" */
  '1', 0, '.', 0, '0', 0,
};

The errors I get are:

.pio\build\OLIMEX_STM32_H103\src\sys.o:(.sys.version+0x0): multiple definition of `sys_version'
.pio\build\OLIMEX_STM32_H103\src\sys.o:(.sys.version+0x0): first defined here
.pio\build\OLIMEX_STM32_H103\src\sys.o:(.vectors+0x0): multiple definition of `vector'
.pio\build\OLIMEX_STM32_H103\src\sys.o:(.vectors+0x0): first defined here

I'm stuck with it and I even don't know where to start. If I add new variables to that source file, I get similar linker errors for them too. Looks like the same file gets linked twice?

The linker script contents are:

__main_stack_size__     = 0x0400;
__process_stack_size__  = 0x0200;
__stacks_total_size__   = __main_stack_size__ + __process_stack_size__;

MEMORY
{
    flash0 : org = 0x08000000, len = 4k
    flash  : org = 0x08000000+0x1000, len = 128k - 4k
    ram : org = 0x20000000, len = 20k
}

/* __flash_start__: flash ROM start address regardless of DFU_SUPPORT */
__flash_start__         = 0x08001000;
__flash_end__       = ORIGIN(flash) + LENGTH(flash);

__ram_start__           = ORIGIN(ram);
__ram_size__            = LENGTH(ram);
__ram_end__             = __ram_start__ + __ram_size__;

SECTIONS
{
    . = 0;

    .sys : ALIGN(16) SUBALIGN(16)
    {
        _sys = .;
        KEEP(*(.vectors))
    . = ALIGN(16);
    *(.sys.version)
    src\sys.o(.text)
    src\sys.o(.text.*)
    src\sys.o(.rodata)
    src\sys.o(.rodata.*)
    . = ALIGN(1024);
    *(.sys.0)
    *(.sys.1)
    *(.sys.2)
    } > flash0

    .text : ALIGN(16) SUBALIGN(16)
    {
        _text = .;
        KEEP(*(vectors))
        *(.text)
        *(.text.*)
        *(.rodata)
        *(.rodata.*)
        *(.glue_7t)
        *(.glue_7)
        *(.gcc*)
    } > flash

    .ctors :
    {
        PROVIDE(_ctors_start_ = .);
        KEEP(*(SORT(.ctors.*)))
        KEEP(*(.ctors))
        PROVIDE(_ctors_end_ = .);
    } > flash

    .dtors :
    {
        PROVIDE(_dtors_start_ = .);
        KEEP(*(SORT(.dtors.*)))
        KEEP(*(.dtors))
        PROVIDE(_dtors_end_ = .);
    } > flash

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

    __exidx_start = .;
    .ARM.exidx : {*(.ARM.exidx* .gnu.linkonce.armexidx.*)} > flash
    __exidx_end = .;

    .eh_frame_hdr : {*(.eh_frame_hdr)}

    .eh_frame : ONLY_IF_RO {*(.eh_frame)}

    . = ALIGN(4);
    _etext = .;
    _textdata = _etext;

    .data :
    {
        _data = .;
        *(.data)
        . = ALIGN(4);
        *(.data.*)
        . = ALIGN(4);
        *(.ramtext)
        . = ALIGN(4);
        _edata = .;
    } > ram AT > flash

    .bss :
    {
        _bss_start = .;
        *(.bss)
        . = ALIGN(4);
        *(.bss.*)
        . = ALIGN(4);
        *(COMMON)
        . = ALIGN(4);
        _bss_end = .;
    } > ram

    PROVIDE(end = .);
    _end            = .;
    . = ALIGN(512);
    _regnual_start = .;


    .gnuk_flash :
    {
        . = ALIGN (1024);
    _data_pool = .;
    KEEP(*(.gnuk_data))
    . = ALIGN(1024);
    . += 1024;
    _keystore_pool = .;
    . += 512*3;
    . = ALIGN(1024);
    _updatekey_store = .;
    . += 1024;
    . = ALIGN(1024);
    } > flash =0xffffffff
}

__heap_base__   = _end;
__heap_end__    = __ram_end__ - __stacks_total_size__;
1

There are 1 answers

0
Alexandr Zarubkin On BEST ANSWER

The solution was to replace src\sys.o in the linker script with *sys.o.

As stated in the ld manual,

In any place where you may use a specific file or section name, you may also use a wildcard pattern. The linker handles wildcards much as the Unix shell does. A '*' character matches any number of characters. A '?' character matches any single character. The sequence '[chars]' will match a single instance of any of the chars; the '-' character may be used to specify a range of characters, as in '[a-z]' to match any lower case letter. A '' character may be used to quote the following character.

When a file name is matched with a wildcard, the wildcard characters will not match a '/' character (used to separate directory names on Unix). A pattern consisting of a single '*' character is an exception; it will always match any file name. In a section name, the wildcard characters will match a '/' character.

Wildcards only match files which are explicitly specified on the command line. The linker does not search directories to expand wildcards. However, if you specify a simple file name --a name with no wildcard characters-- in a linker script, and the file name is not also specified on the command line, the linker will attempt to open the file as though it appeared on the command line.

The sys.o file was specified on the command line with another path than in the linker file, so the linker tried to link it twice.