How do you get the size of an input section in ld? I would assume its just SIZEOF(.section); however ld gives an error upon trying to run that. Is there any way I can do this? .section would be defined in a .asm file like so
section .section
mov al, 15
Here's the linker script I have so far:
SECTIONS {
boot : {
*( .boot );
. += SECTOR_SIZE - SIZEOF( .boot_header );
*( .boot_header );
}
}
I have no problem with SIZEOF.
Just tested:
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM AT> FLASH
_datasize = SIZEOF(.data);
Works as expected.
Related
I need to copy the .o file created in the path \Debug_Slot1\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash.o to RAM in STM32. But getting error as file not found..
/* Initialized data sections into "RAM" Ram type memory */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
*(.RamFunc) /* .RamFunc sections */
*(.RamFunc*) /* .RamFunc* sections */
.\Debug_Slot1\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash.o(.text)
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM AT> FLASH
I have already produced a work-around but I have a question about what is happening here.
Setup:
StmCUBEIDE (ver 10)
Stm32F4 on custom board with lan
8Mb extra SDRAM
1Mb FLASH on single boot mode
Default start from 0x08000000
Long story short I have sliced up my memory (flash) into sectors provided in linker. See linker below:
/*
*****************************************************************************
**
** File : LinkerScript.ld
**
** Abstract : Linker script for STM32F4xx Device with
** 1024Kbytes FLASH, 192Kbytes RAM
**
** Set heap size, stack size and stack location according
** to application requirements.
**
** Set memory bank area and size if external memory is used.
**
** Target : STMicroelectronics STM32
**
**
** Distribution: The file is distributed as is, without any warranty
** of any kind.
**
** (c)Copyright Ac6.
** You may use this file as-is or modify it according to the needs of your
** project. Distribution of this file (unmodified or modified) is not
** permitted. Ac6 permit registered System Workbench for MCU users the
** rights to distribute the assembled, compiled & linked contents of this
** file as part of an application binary file, provided that it is built
** using the System Workbench for MCU toolchain.
**
*****************************************************************************
*/
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20030000; /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 128K; /* required amount of heap */
_Min_Stack_Size = 2K; /* required amount of stack */
/* Specify the memory areas
* reserved sector 0 (16kb sectors)
* flash (bootloader flash) sector 4 & 5 (64kb + 128kb = 192kb)
* sectore stable sector 6 to 8 ( 128 +128 +128 = 384kb)
* sector latest sector 9 to 11 ( 128 +128 +128 = 384kb)
*
*/
MEMORY
{
FLASH_RESERVED (rxw): ORIGIN = 0x08000000, LENGTH = 16K
FLASH_SX (rw) : ORIGIN = 0x08004000, LENGTH = 32K
FLASH_COMMON (rw) : ORIGIN = 0x0800C000, LENGTH = 16K
FLASH_BOOTLOADER (rx) : ORIGIN = 0x08010000, LENGTH = 192K
FLASH_STABLE (rxw) : ORIGIN = 0x08040000, LENGTH = 384K
FLASH_LATEST (rxw) : ORIGIN = 0x080A0000, LENGTH = 384K
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 192K
EXRAM (rwx) : ORIGIN = 0xD0000000, LENGTH = 8192K
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH_BOOTLOADER */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH_BOOTLOADER
/* keep this section for OTA capabilities*/
.otaComBuff 0x08000000:
{
KEEP(*(.otaComBuff))
} >FLASH_RESERVED = 0x00
/* The program code and other data goes into FLASH_BOOTLOADER */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH_BOOTLOADER
/* sectors for dual boot and reserved data */
.reserved :
{
. = ALIGN(4);
__reserved_start__ = .;
KEEP(*(.reserved*))
. = ALIGN(4);
__reserved_end__ = .;
} >FLASH_RESERVED
ASSERT(LENGTH(FLASH_RESERVED) >= (__reserved_end__ -__reserved_start__), "sector Reserved overflow")
.sx (NOLOAD):
{
. = ALIGN(4);
__sx_start__ = .;
KEEP(*(.sx*))
. = ALIGN(4);
__sx_end__ = .;
} >FLASH_SX
ASSERT(LENGTH(FLASH_SX) >= (__sx_end__ -__sx_start__), "sector sx overflow")
.common :
{
. = ALIGN(4);
__common_start__ = .;
KEEP(*(.common*))
. = ALIGN(4);
__common_end__ = .;
} >FLASH_COMMON
ASSERT(LENGTH(FLASH_COMMON) >= (__common_end__ -__common_start__), "sector common overflow")
.bootloader :
{
. = ALIGN(4);
__bootloader_start__ = .;
KEEP(*(.bootloader*))
. = ALIGN(4);
__bootloader_end__ = .;
} >FLASH_BOOTLOADER
ASSERT(LENGTH(FLASH_BOOTLOADER) >= (__bootloader_end__ -__bootloader_start__), "sector bootloader overflow")
.stable :
{
. = ALIGN(4);
__stable_start__ = .;
KEEP(*(.stable*))
. = ALIGN(4);
__stable_end__ = .;
} >FLASH_STABLE
ASSERT(LENGTH(FLASH_STABLE) >= (__stable_end__ -__stable_start__), "sector stable overflow")
.latest :
{
. = ALIGN(4);
__latest_start__ = .;
KEEP(*(.latest*))
. = ALIGN(4);
__latest_end__ = .;
} >FLASH_LATEST
ASSERT(LENGTH(FLASH_LATEST) >= (__latest_end__ -__latest_start__), "sector latest overflow")
/* Constant data goes into FLASH_BOOTLOADER */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH_BOOTLOADER
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH_BOOTLOADER
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH_BOOTLOADER
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH_BOOTLOADER
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH_BOOTLOADER
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH_BOOTLOADER
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM AT> FLASH_BOOTLOADER
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM
/* Uninitialized external data section */
. = ALIGN(4);
.extbss (NOLOAD):
{
/* This is used by the startup in order to initialize the .bss secion */
_extsbss = .; /* define a global symbol at bss start */
__extbss_start__ = _extsbss;
*(.extbss)
*(.extbss*)
*(COMMON)
. = ALIGN(4);
_extebss = .; /* define a global symbol at bss end */
__extbss_end__ = _extebss;
} >EXRAM
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(4);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
PROVIDE ( _max_heap = . );
. = . + _Min_Stack_Size;
. = ALIGN(4);
} >RAM
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
Next I have in my file:
#include "stm32f4xx_hal.h"
#include "stdint.h"
#include "FreeRTOS.h"
#include "task.h"
#include "error.h"
#include "debug.h"
extern unsigned int __bootloader_start__ ;
extern unsigned int __bootloader_end__ ;
extern unsigned int __sx_start__ ;
extern unsigned int __sx_end__ ;
/*external linker symbols for sector address feching*/
extern unsigned int __stable_start__ ;
extern unsigned int __stable_end__ ;
extern unsigned int __latest_start__ ;
extern unsigned int __latest_end__ ;
/*external linker symbol OTA flash region*/
extern unsigned int __reserved_start__ ;
#define ADR_SectorBootloaderStart ((uint32_t)(&__bootloader_start__))
#define ADR_SectorBootloaderEnd ((uint32_t)(&__bootloader_end_))
#define ADR_SectorSxStart ((uint32_t)(&__sx_start__))
#define ADR_SectorSxEnd ((uint32_t)(&__sx_end__))
#define ADR_SectorStableStart ((uint32_t)(&__stable_start__))
#define ADR_SectorStableEnd ((uint32_t)(&__stable_end__))
#define ADR_SectorLatestStart ((uint32_t)(&__latest_start__))
#define ADR_SectorLatestoEnd ((uint32_t)(&__latest_end__))
/*OTA communiaction sector*/
#define ADR_Reserved ((uint32_t)(&__reserved_start__))
Problem is that only ADR_SectorSxStart returns true address in other variables I get garbage.
On this variables depends flashing logic, for long time function for guarding bootloader sector was not working, after hardcoding addresses into function everything is OK. I need to make the rest of defines work. Any idea why it is that only one variable refers correctly?
Thank you.
#busybee
Map file gets the wrong address too:
.sx 0x0000000008004000 0x0
0x0000000008004000 . = ALIGN (0x4)
0x0000000008004000 __sx_start__ = .
*(.sx*)
0x0000000008004000 . = ALIGN (0x4)
0x0000000008004000 __sx_end__ = .
0x0000000000000001 ASSERT ((LENGTH (FLASH_SX) >= (__sx_end__ - __sx_start__)), sector sx overflow)
.common 0x000000000800c000 0x0
0x000000000800c000 . = ALIGN (0x4)
0x000000000800c000 __common_start__ = .
*(.common*)
0x000000000800c000 . = ALIGN (0x4)
0x000000000800c000 __common_end__ = .
0x0000000000000001 ASSERT ((LENGTH (FLASH_COMMON) >= (__common_end__ - __common_start__)), sector common overflow)
.bootloader 0x0000000008030a54 0x0
0x0000000008030a54 . = ALIGN (0x4)
0x0000000008030a54 __bootloader_start__ = .
*(.bootloader*)
0x0000000008030a54 . = ALIGN (0x4)
0x0000000008030a54 __bootloader_end__ = .
0x0000000000000001 ASSERT ((LENGTH (FLASH_BOOTLOADER) >= (__bootloader_end__ - __bootloader_start__)), sector bootloader overflow)
.stable 0x0000000008040000 0x0
After some time, I have found the answer. As per usual it was in plain .text in front of my eyes.
The thing is that the address of SECTOR_BOOTLOADER is in fact placed correctly telling compiler where to place all .text variables.
When you go carefully line by line, you can see that I have actually created a memory region, FLASH_BOOTLOADER, and then used it as my main program address. This is correct. Then I have placed all my .text variables, using linker, then I created my REGION BOOTLOADER.
This is linker language means that in this region first he will place my variables, incrementing address and then he will place my sector, returning me address of sector not region.
This mistake was made by not understanding linker scripts and naming issue.
.text :
{
. = ALIGN(4);
*(EXCLUDE_FILE(*blink.c.obj) .text .text*) /* Exclude blink from this section */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
_load_flash_start = _etext; /* define a global symbol that starts at LOAD_FLASH */
.fast_code_section:
{
/*. = ALIGN(4);*/
. = _etext;
_fast_code_start = .; /* define a global symbol at start of FAST_RAM */
*(.fast_code_section*)
*blink.c.obj (.text .text*)
_fast_code_end = .; /* define a global symbol at end of FAST_RAM */
} >FAST_RAM AT> LOAD_FLASH
I want to exclude the file blink.c to be allocated into .text section (FLASH), by using the EXCLUDE_FILE in linker script.
And I want the blink.c file in another section (.fast_code_section).
When I look in the .map file I can see that all functions in blink.c is still allocated to .text section.
i'm using gcc and the target platform is a stm32
Im developing a bare metal OS for raspberry pi 1. The main idea of this OS is a simply kernel that will be able to run a function created in other machine and send it to the raspi. The function will use functions that were compilated with the kernel and that reside in memory.
I want to know how can I compile a function that when I will insert the payload in memory in a determinated address it will be able to call system functions and use the data that are defined in the function code.
void function()
{
while (1)
{
uart_puts("Hello\r\n");
}
}
This is my link.ld file and the function will be loaded at __binary_function:
ENTRY(_start)
SECTIONS
{
/* Starts at LOADER_ADDR. */
. = 0x8000;
__start = .;
__text_start = .;
.text :
{
KEEP(*(.text.boot))
*(.text)
}
. = ALIGN(4096); /* align to page size */
__text_end = .;
__rodata_start = .;
.rodata :
{
*(.rodata)
}
. = ALIGN(4096); /* align to page size */
__rodata_end = .;
__data_start = .;
.data :
{
*(.data)
}
. = ALIGN(4096); /* align to page size */
__data_end = .;
__bss_start = .;
.bss :
{
bss = .;
*(.bss)
}
. = ALIGN(4096); /* align to page size */
__bss_end = .;
/*Allocating memory for the heap*/
__heap_start = .;
. = . + 0x1000000; /*4MB Heap section*/
__heap_end = .;
__binary_function = .;
__end = .;
}
My idea is that the kernel will receive the payload via UART and then execute it. The payload must be able to call system functions such us the UART functions and access to the data that is define inside it.
I want to do this automatically with arm-none-eabi-gcc (GCC Toolchain for ARM architecture) that works like GCC and avoiding harcoding the system functions in the payload source.
Thanks!
I solve it using the hardcoding the kernel functions in the payload:
void (* uart_puts)(char *) = (void(*)(char * )) 0x0000000000008248;
I get the 0x0000000000008248 address from the .map file generated in the compilation of the kernel.
I'm debugging an embedded system with the stm32f746vg microcontroller where some speed critical sections of code are loaded in data RAM instead of flash. The rest of the non-critical code is loaded in flash, and the linker puts all of the .text sections in flash by default.
I do this relocation with nasty little function prototypes like this:
int main(void) __attribute__((section(".data")));
This forces main() to be loaded at address 0x2000 0000, which is what I want. Unfortunately, GDB expects main() to be loaded at address 0x0080 0000, where the rest of the program code is. As a result, GDB does not know where the line numbers for main() are. Is there any way to tell GDB "main() is actually at this address" ?
I DO have the newest version of arm-none-eabi-gdb and arm-none-eabi-gcc.
I am running arm-none-eabi-gcc with the -g option.
When I comment out the prototype for main that contains the __attribute__ directive, GDB has no problem finding line numbers.
Below is my linker script:
/* Entry Point */
ENTRY(Reset_Handler)
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
/* Specify the memory areas */
/**
* for the time being, we are going to buffer the image in sram1. sram1 is
* entirely dedicated to buffering images.
* DTCM_RAM will be used for user variables
*/
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
DTCM_SRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
/* RAM1 (xrw) : ORIGIN = 0x20010000, LENGTH = 240K*/
RAM1 (xrw) : ORIGIN = 0x20010000, LENGTH = 245760
RAM2 (xrw) : ORIGIN = 0x2004c000, LENGTH = 16K
ITCM_SRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 16K
}
/* Define output sections */
SECTIONS
{
/* Vectors need to be loaded at the start of flash. */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* The program code and other data goes into 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);
_etext = .; /* define a global symbols at end of code */
_exit = .;
} >FLASH
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
/* used by the startup to initialize data */
_sidata = .;
/* Initialized data sections goes into RAM, load LMA copy after code */
.data ORIGIN(DTCM_SRAM) :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} AT > FLASH
__const_data_length__ = SIZEOF(.data);
/* Uninitialized data section */
. = ALIGN(4);
.bss . :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >DTCM_SRAM
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(4);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(4);
} >DTCM_SRAM
/* ram1 section, vars must be located here explicitly */
/* Example: extern int foo(void) __attribute__ ((section (".ram1"))); */
/* No initialization is offered for this section.*/
.ram1 ORIGIN(RAM1) :
{
*(.ram1)
} >RAM1
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
These are my gcc flags
CFLAGS = -gstabs -Wall -std=gnu99 -ffunction-sections -Wno-unused-variable
CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork
CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mlong-calls
CFLAGS += -I. -ggdb
CFLAGS += -DHSE_VALUE=$(HSE_VALUE)
CFLAGS += -DUSE_STDPERIPH_DRIVER
You acheive this by placing main() in special code section of your choosing, call it .fast_exec
int main(void) __attribute__((section(".fast_exec")));
Then, in the linker script, place this new section to execute from RAM. It will be copied from FLASH at start-up:
.fast_exec : {
*(.fast_exec)
} > DTCM_SRAM AT> FLASH
You can verify the effect of this, by checking the map file.
Refer to: https://stackoverflow.com/a/15142268/1096140