ok so, im linking a bootloader, kernel and linker (so i can make a functional os)
i keep getting this when im trying to link:
"ld:linker.ld:4: non constant or forward reference address expression for section .=0x0100000"
the linker:
ENTRY (loader)
SECTIONS {
.=0x00100000;
.text : {
*(.text)
}
.rodata ALIGN (0x1000): {
*(.data)
}
.bss : {
sbss = .;
*(COMMON)
*.(bss)
ebss = .;
}
}
.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
I'm working on a stm32 nucleo board. My project is composed of several different libraries.
I would like to put all uninitialized variables coming from static library (mylib.a) in a specific memory section instead of the bss section.
Here is my bss section inside the linker script:
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss section */
_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
I tried adding this section before the bss one:
. = ALIGN(4);
.mybss :
{
/* This is used by the startup in order to initialize the .bss section */
_smybss = .; /* define a global symbol at bss start */
__mybss_start__ = _smybss;
mylib.a:*(.bss)
mylib.a:*(.bss*)
mylib.a:*(COMMON)
. = ALIGN(4);
_emybss = .; /* define a global symbol at bss end */
__mybss_end__ = _emybss;
} >RAM
The compiler does not complain but when I inspect with nm command the generated elf _smybss symbol is at the same address of _emybss symbol. So mybss section is empty.
Do you have any suggestion on how to achive this?
Thanks
I am working on an embedded system (Stellaris Launchpad) and writing a simple OS (as a hobby project). The used toolchain is gcc-none-eabi.
My next step is to get used to the MPU to allow the kernel to prevent user programs from altering specific data. I have a bunch of C files and I splitted them in two parts: kernel and other.
I have the following linker script to start out with:
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}
SECTIONS
{
.text :
{
_text = .;
KEEP(*(.isr_vector))
*(.text*)
*(.rodata*)
_etext = .;
} > FLASH
.data : /*AT(ADDR(.text) + SIZEOF(.text))*/ /*contains initialized data*/
{
_data = .;
*(vtable)
*(.data*)
_edata = .;
} > SRAM AT > FLASH
.bss : AT (ADDR(.data) + SIZEOF(.data)) /*contains unitialized data (should be set to all zero's)*/
{
_bss = .;
*(.bss*)
*(COMMON)
_ebss = .;
_start_heap = .;
} > SRAM
_stack_top = ORIGIN(SRAM) + LENGTH(SRAM) - 1; /*The starting point of the stack, at the very bottom of the RAM*/
}
And after reading up on linker scripts I know that I can replace the stars with filenames, and thus start splitting the flash in multiple parts. I would for example create a .kernel.bss section and put all of the kernel object files instead of the stars in that section.
My only problem left is that the kernel is not one file, it is a whole lot of files. And files might be added, removed etc. So how do I do this? How do I change my linker script so that a dynamic first group of files is mapped to the first place and a dynamic second group of files is mapped to a second place?
you know that you can specify what files are used as input for a section?
We use this for separating kernel and application code into fast internal flash, and slower external flash memory, like so:
.kernel_text :
{
build/kernel/*.o (.text*) /*text section from files in build/kernel*/
} > INT_FLASH
.app_text:
{
build/app/*.o(.text*)
} > EXT_FLASH
Section 4.6.4 might be helpful, (describes input sections in more detail)
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/4/html/Using_ld_the_GNU_Linker/sections.html
I found a solution, allthough it feels a bit hacky. It does work though:
I found out that a linker script is OK with working on .a files if they are statically linked with ar. So lets say you have a buch of .o files that, together form the kernel: a.o, b.o, c.o. Use ar rcs kernel.a a.o, b.o, c.o. kernel.a is now your kernel, which you want to store seperately in memory.
The next thing you need to know is that the * in a linker script is actually a wildcard for everything not used yet. So we can create the following linker script:
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}
SECTIONS
{
.kernel.text :
{
_kernel_text = .;
KEEP(kernel.a(.isr_vector))
KEEP(kernel.a(_sbrk))
kernel.a(.text*)
kernel.a(.rodata*)
_kernel_etext = .;
_kernel_flash_data = ALIGN(0x4);
} > FLASH
.kernel.data : /*AT(ADDR(.text) + SIZEOF(.text))*/ /*contains initialized data*/
{
_kernel_data = .;
kernel.a(vtable)
kernel.a(.data*)
_kernel_edata = .;
} > SRAM AT > FLASH
.kernel.bss :
{
_kernel_bss = .;
kernel.a(.bss*)
kernel.a(COMMON)
_kernel_ebss = .;
} > SRAM
.text : /*AT (ADDR(.core.text) + SIZEOF(.core.text) + SIZEOF(.core.data))*/
{
_text = .;
*(.text*)
*(.rodata*)
_etext = .;
_flash_data = ALIGN(0x4);
} > FLASH
.data :
{
_data = .;
*(vtable)
*(.data*)
_edata = .;
} > SRAM AT > FLASH
.bss : AT (ADDR(.data) + SIZEOF(.data)) /*contains unitialized data (should be set to all zero's)*/
{
_bss = .;
*(.bss*)
*(COMMON)
_ebss = .;
_start_heap = .;
} > SRAM
}
This works but will probably lead to a new problem: the linker treats libraries as.. well, libraries. So if they contain the program start (as in my case) the linker does not actually look for it, the linker only looks trough the library for functions refered to by the actual o files. The solution I found for this is to add the -u <name> flag to the linker invocation. This flag causes a symbol to become undefined, so the linker will look for this symbol plus all symbols that are needed by this synbol.
My invocation, for references sake:
arm-none-eabi-ld -Tlinker_script.ld -nostdlib --entry ResetISR
--gc-sections -u _sbrk -u .isr_vector
-L./lib//hardfp
-L/home/me/gcc-arm-none-eabi/gcc-arm-none-eabi-4_9-2015q1/arm-none-eabi/lib/armv7e-m/fpu
-L/home/me/gcc-arm-none-eabi/gcc-arm-none-eabi-4_9-2015q1/lib/gcc/arm-none-eabi/4.9.3/armv7e-m/fpu
-Lrelease/
-o release/os
./user/obj/release/ledsDance.c.o ./user/obj/release/main.c.o ./validation/obj/release/val_floattest.c.o ./validation/obj/release/val_genTest.c.o ./validation/obj/release/val_gpiotest.c.o ./validation/obj/release/val_iotest.c.o ./validation/obj/release/val_proctest.c.o ./validation/obj/release/val_schedTest.c.o release/kernel.a release/core.a
-ldriver-cm4f
-luartstdio
-lm
-lc
-lgcc
I saw this link script in
http://www.jamesmolloy.co.uk/tutorial_html/1.-Environment%20setup.html
SECTIONS
{
.text 0x100000 :
{
code = .; _code = .; __code = .; // What is this line for?
*(.text)
. = ALIGN(4096);
}
.data :
{
data = .; _data = .; __data = .;
*(.data)
*(.rodata)
. = ALIGN(4096);
}
.bss :
{
bss = .; _bss = .; __bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .; _end = .; __end = .;
}
You can see that, code, _code, __code and the fallowing ones all appearing in a same style. What are they for? Why should they be written in such a way?
The syntax <symbol> = . simply defines a symbol at the current address.
You can use this symbol like this:
extern int __code;
int foo()
{
cout << "Address of __code" << &__code << endl;
}
_code and __code typically holds the start address of the text section. This is used from the startup code of your system you compile for.
Definig symbols without a leading underscore are not so common I believe. This can maybe result in conflicts with normal definitions from your code. But this is only a convention. Technically you can define what you want and need. The rules are the same as all other symbols in your project: Never define symbols twice :-)