This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Source files order in output image

Hello to all:

How does Linker or Compiler determine that which source file should be located first in base address of device memory? For example we have a project with a startup file.s (stm32f10x_startup.s) and a main.c. We expect that, the object of startup file.s be located in initial address of execute memory (typically ROM) and main.c object, be located after; because, typically, the microcontrollers read address 0x0 after rest to receive MSP base address and then 0x4 to receive Reset handler address, which these information are in startup file corresponding to that microcontroller. So if main.c contents, be located from address 0x0, then the execution encounters with error. Also there maybe another (another.s) file, in this case, how does linker decide which (startup file.s) or (another.s) shouldbe located first?

  • We expect that ...

    On what basis do you expect that?

    The C language specifically does not guarantee any particular ordering of program objects in physical memory.

    If you really need control of this, you use Linker commands to specify it

    https://www.keil.com/support/man/docs/armlink/

    https://www.keil.com/support/man/docs/armlink/armlink_pge1362065910731.htm

    typically, the microcontrollers read address 0x0 after rest to receive MSP base address and then 0x4 to receive Reset handler address

    Correct - that's why it really does not matter what order the files are actually in.

    these information are in startup file

    No, they aren't - they come from the hex file that it programmed into the Flash.

    if main.c contents, be located from address 0x0

    They can't - because that would overwrite the vector table!

  • Thank for your answer:

    OK; your explanation is correct, but I mean that how linker or compiler knows, it has to put the contents related to vector table (in startup.s file), from address 0x0 to end of table. For example; Why does not it put machine codes related to lines 10 to 20 of main.c rather than them!!? Is this franchise done with specific command? 

    I hope that I have expressed my meaning well!

  • It's all down to the linker script passed to the linker, either implicitly or explictly.  I use the arm-none-eabi toolchain, so use the -T foo.ld option.

    The linker is passed a list of .o and .a files on its command line too. The linker is building output sections, for the image, from input sections (each function or global data is tagged with a section name in its .o file). The linker keeps a 'cursor' of where it is in composing the output, and the cursor starts at 0.

    When the linker processes this directive from the .ld file:

        KEEP(*(.vectors))

    it searches ALL .o and .a files on its command line (the * matches ANY file) for any sections called .vectors. It will find just one.  In my case, this is in startup_efm32gg.c (I use SiiiconLabs efm32gg MCUs) and is a const array that is of course the interrupt vector table.  Since the cursor is currently 0, the vec table goes at the start of the image.  The output cursor is then incremented by the size of the vector table.

    Since a Cortex M3 always starts life by loading SP from image address 0 and PC from image address 4, the vector table MUST be placed at 0 in the image.  If my .ld file said

    *(.text*)

    BEFORE the line above, the linker would find all the sections named .text* in all .o files on its cmd line, relegating the .vectors section, and thus the vector table, to some arbitrary location in the image, and that image wouldn't boot once flashed.

    Am I making any sense?

    Oops, I just realized this is the Keil forum (I normally just scan it for RTX posts), but Keil's scatter files work on the same principle (I think) as GNU's .ld scripts.

  • Thank Tobermory; I almost understood your explanation, but if anyone has any other explanation, pleas post it here! 

  • how linker or compiler knows

    It has command-line options which tell it what type of chip the Target is.

    There are also settings in the Keil project - which tell it memory sizes, etc.

    If you look in the startup file, you will see where the vector table is created:

            MODULE  ?cstartup
    
            ;; Forward declaration of sections.
            SECTION CSTACK:DATA:NOROOT(3)
    
            SECTION .intvec:CODE:NOROOT(2)
    
            EXTERN  __iar_program_start
            EXTERN  SystemInit        
            PUBLIC  __vector_table
    
            DATA
    __vector_table
            DCD     sfe(CSTACK)
            DCD     Reset_Handler             ; Reset Handler
            DCD     NMI_Handler               ; NMI Handler
            DCD     HardFault_Handler         ; Hard Fault Handler
            DCD     MemManage_Handler         ; MPU Fault Handler
            DCD     BusFault_Handler          ; Bus Fault Handler
            DCD     UsageFault_Handler        ; Usage Fault Handler