I'd like to write a linker script looking something like this:
SECTIONS {
. = 0x0;
.startup . : { startup.o(.text) }
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss COMMON) }
. = 0x4000;
other.text : { other.o(.text) }
other.data : { other.o(.data) }
other.bss : { other.o(.bss) }
}
My intention here is to have, in this order:
a section with the .text from startup.o
.text, .data and .bss containing those sections from all other input files besides other.o
the .text, .data and .bss sections from other.o
Of course there is a problem with the script I've given: other.o is included in the * wildcards used previously, so it doesn't get put in the output section other.
Besides manually listing all the input object files bar other.o in place of the *s, is there a way I can achieve what I want here?
You can use section attributes to solve this. Suppose you add the following attribute when declaring functions in that file (or any other file):
void foo() __attribute__ ((section(".specialmem")));
And a similar section definition in your linker script:
.specialmem:
{
*(.specialmem)
}
You can do the same thing with data/bss (global variables) as well.
Assuming you want some files/functions to end up in a specific memory location, it is a good practice to define these memory blocks in your linker file as well and then place them there like:
.specialmem:
{
*(.specialmem)
} >specialMemBlock
You may want to try EXCLUDE_FILE
Something like this:
*(EXCLUDE_FILE (other.o) .text .text. )
Partial solution: * wildcards are fully-fledged file wildcards. If you're lucky enough that other.o is in a different directory from the other input files, this will work:
SECTIONS {
. = 0x0;
.startup . : { foo/startup.o(.text) }
.text : { foo/*(.text) }
.data : { foo/*(.data) }
.bss : { foo/*(.bss COMMON) }
. = 0x4000;
other.text : { bar/other.o(.text) }
other.data : { bar/other.o(.data) }
other.bss : { bar/other.o(.bss) }
}
Related
I am trying to define a user-defined section inside the linker file.
/* Specify the memory areas */
MEMORY
{
m_text (RX) : ORIGIN = 0x00003000, LENGTH = 0x000FD000
}
SECTIONS
{
....
.tog 0xFFFF0:
{
. = ALIGN(4);
. = . + 8;
. = ALIGN(4);
} > m_text
}
In the code, I have placed the
unsigned int togganta __attribute__((section("tog "))) = 0;
However, when I do a hexadump using xxd I see this symbol togganta inside the binary address - 00f78580. I expected it to be at the address 0xFFFF0. what am I missing here?
In the linker script, I have defined
MEMORY {
sec_1 : ORIGIN = 0x1B800, LENGTH = 2048
......
}
How can I read the start address of this section in C? I would like to copy it in a variable in the C code
Basically to achieve this, you have two tasks to fulfill:
Tell the linker to save the start address of the section. This can be achieved by placing a symbol in the linker script at the beginning of your section.
Tell the compiler to save initialize a constant with an address filled in later by the linker
As for the first step: In your section sec_1 you have to place a symbol that will be placed at the start of that section:
SECTIONS
{
...
.sec_1 :
{
__SEC_1_START = ABSOLUTE(.); /* <-- add this */
...
} > sec_1
...
}
Now that the linker produces bespoke symbol, you have to make it accessible from the compiler side. In order to do so, you need somewhere some code like this:
/* Make the compiler aware of the linker symbol, by telling it, there
is something, somewhere that the linker will put together (i.e. "extern") */
extern int __SEC_1_START;
void Sec1StartPrint(void) {
void * const SEC_1_START = &__SEC_1_START;
printf("The start address for sec_1 is: %p", SEC_1_START);
}
By calling Sec1StartPrint() you should get an address output that matches your *.map file the linker created.
I am using MinGW to create a win32 exe.
I would like to create a memory segment with a fixed size, and after that place variable inside this segment at a fixed address relative to the start of the segment. Has anyone an idea of how to do this?
I was able to declare my own segment with:
.codeflash BLOCK(__section_alignment__) :
{
__codeflash_start__ = . ;
*(.codeflash)
__codeflash_end__ = . ;
}
And place variables inside this segment using:
__attribute__((section(".codeflash")))
I am using the default linker script.
Thanks.
Lets say 0x100 bytes from the start of the segment
.codeflash BLOCK(__section_alignment__) :
{
. += 0x100;
__codeflash_start__ = . ;
KEEP(*(.codeflash))
KEEP(*(.codeflash*))
__codeflash_end__ = . ;
}
I used the suggestion above to solve the problem:
Added everything to a struct and put this struct inside the section.
I have developed a linker script which has overlapping regions. I want the linker to produce an error for overlapping regions. I am using --check-sections command line parameter but it doesn't work. Here is a small portion of my script file:
.region1 (DDR_ORG) (NOLOAD) :
{
. = . + 0x1000;
} > DDR
.region2 (DDR_ORG) (NOLOAD) :
{
. = . + 0x100000;
} > DDR
There is a project which successfully compiled linked and run on the device.
But after telling the linker that it should put the part of the application code to the ROM memory, instead of SDRAM, I am getting the following error at the linking step:
Error[Lp002]: relocation failed: value out of range or illegal:
0x60000545
Kind : R_ARM_PREL31[0x2a]
Location: 0xa0000030
Module: I:\Project\Debug\Obj\fileOper.o
Section: 128 (.ARM.exidx)
Offset: 0x0
Target : 0x00000574
"SECTION_FILEOP_87"
Module: I:\Project\Debug\Obj\fileOper.o
Section: 104 (SECTION_FILEOP)
Offset: 0x4f4
I have read the C/C++ guide from IAR. But it doesn't provide well enough explanations regarding this error. So even reading the manual I can't get the reason of this error. Can anybody help to resolve this problem?
Actually the IAR C/C++ developers guide says:
For each instruction that cannot be relocated correctly, ILINK will
generate a relocation error. This can occur for instructions where the
target is out of reach or is of an incompatible type, or for many
other reasons.
Then it provides the error as an example which is different than in my case.
EDIT 1: I have created the small project which reproduce the same errors and it consists of fileOper.cpp and main.cpp files only.
The ICF file used to tell linker how to put sections to memory:
define symbol intvec_start = 0x10000000;
/-Memory Regions-/
/-FLASH ROM-/
define symbol FLASH_ROM_start = 0x00000000;
define symbol FLASH_ROM_end = 0x0007FFFF;
/*Internal RAM*/
define symbol RAM_start = 0x10000000;
define symbol RAM_end = 0x10017FFF;
/*SDRAM*/
define symbol SDRAM_start = 0xA0000000;
define symbol SDRAM_end = 0xA1FFFFFF;
/-Sizes-/
define symbol size_stack = 0x4000;
define symbol size_heap = 0x2000;
define memory mem with size = 4G;
define region FLASH_region = mem:[from FLASH_ROM_start to
FLASH_ROM_end];
define region RAM_region = mem:[from RAM_start to RAM_end];
define region SDRAM_region = mem:[from SDRAM_start to SDRAM_end];
define block CSTACK with alignment = 8, size = size_stack { };
define block HEAP with alignment = 8, size = size_heap { };
initialize by copy with packing = zeros { readwrite };
do not initialize { section .noinit };
place at address mem: intvec_start { section .intvec };
place at start of FLASH_region { readonly section .cstartup };
place in RAM_region { block CSTACK };
place in SDRAM_region { readonly }
except {readonly section FILEOP };
place in SDRAM_region { readwrite };
place in SDRAM_region { block HEAP};
place in FLASH_region { readonly section FILEOP };
fileOper.cpp: I have changed it, but it still reproduce the same error.
#include "fileOperbug.h"
#include <string>
char *fgets( char *str, int num, std::string *stream ) {
char *pointer = 0;
return pointer;
}
std::string *fopen(const char *name, const char *mode) {
std::string *str = new std::string();
str->assign("");
return str;
}
I have resolved the problem.
While using IAR Embedded workbench:
Project options -> C/C++ Compiler -> Language 1 tab.
There at the "C++ dialect" there was a checkbox named "with exceptions" at it was checked.
The error at linking stage happens when "with exceptions" checkbox is checked.
All code that uses exceptions must be loaded to ROM. Otherwise the "with exceptions" should be unchecked.