How to solve the error in linker script? - c

I created a memory linker script and saved it as memory.ld in the eclipse ide : Project : properties : gcc linker : miscellaneous : I added -M -T memory.ld
memory.ld :
MEMORY
{
ram (rw) : ORIGIN = 0x4000000 , LENGTH = 2M
}
SECTIONS
{
RAM : { *(.myvarloc)
} > ram }
In my c program : I made a global declaration as:
__attribute__ ((section(".myvarloc")))
uint8 measurements [30];
ERRORS:
/usr/bin/ld: FEBRUARY section `.text' will not fit in region `ram'
/usr/bin/ld: region `ram' overflowed by 20018 bytes
/usr/lib/i386-linux-gnu/libc_nonshared.a(elf-init.oS): In function `__libc_csu_init':
(.text+0x2b): undefined reference to `__init_array_end'
/usr/lib/i386-linux-gnu/libc_nonshared.a(elf-init.oS): In function `__libc_csu_init':
(.text+0x31): undefined reference to `__init_array_start'
/usr/lib/i386-linux-gnu/libc_nonshared.a(elf-init.oS): In function `__libc_csu_init':
(.text+0x57): undefined reference to `__init_array_start'
/usr/bin/ld: FEBRUARY: hidden symbol `__init_array_end' isn't defined
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status

Depending on the compiler you are using (GCC?) and the processor for which you are compiling (x86?), the compiler will generate several segment references in the object files. The most common ones are .text for code segments, .data for initialized data and .bss for uninitialized data.
You can see which segments your compiler generates by using the nm utility on your object files.
I assume that until you provided your own linker script, the environment has provided some default script automatically and/or implicitly. But now that you have decided to "roll your own", you have to take care of all details yourself.
I cannot verify the details, but you could start with the following SECTIONS:
SECTIONS
{
.bss : { *(.myvarloc) }
.bss : { *(.bss) }
.data : { *(.data) }
.text : { *(.text) }
}
I'm not sure if this is the exact syntax your GCC linker (it depends a little on the version), but you can find more information in the manual.

Related

zig: linking symbol can't find

When try to write a freestanding program in zig, we have already defined a link script. (Actually os)
However, I can't get the address of the symbol I defined in script.
Some methods are tried but fails.
Method 1, but segmentation fault on compiling step.
const s = #extern(* fn () void , .{
.name = "symbol",
});
Method 2, relocation R_RISCV_HI20 out of range
extern fn symbol() void;
I think maybe the core problem is in the 'section'. The symbol doesn't in .data, .rodata or .text segment but .bss segment.
How to get the location of this symbol correctly?

Using config.ini variables in ldscript.ld

In my config.ini file I have defined these variables:
# Where will system be loaded when started (for which address to prepare it)
LOAD_ADDR = 0x100000
RAM_ADDR = 0x300000
ROM_ADDR = 0x200000
STACK_ADDR = 0x600000
Which I then use in the .data section of the linker script ldscript.ld:
SECTIONS {
.code LOAD_ADDR :
{ /* This is line 9 */
kernel_code_addr = .;
/* instructions */
*?/boot/startup.asm.o ( .text* )
*( .text* )
}
.data RAM_ADDR : AT(ROM_ADDR)
{
kernel_data_addr = .;
/* read only data (constants), initialized global variables */
* ( .rodata* .data* )
}
.bss :
{
*( .bss* COMMON* )
. = ALIGN (4096);
}
/* ... */
}
But running make fails while linking with this error:
[linking build/04_Debugging.elf]
ld:build/ldscript.ld:9: non constant or forward reference address expression for section .data
make: *** [Makefile:87: build/04_Debugging.elf] Error 1
When I replace RAM_ADDR and ROM_ADDR in the code with their values, make finishes nicely and everything works.
What causes this error? Why can I use LOAD_ADDR with no errors?
The linker does not seem to load the variables you defined in config.ini.
You can use INCLUDE in your linker script to include another file.
From https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_chapter/ld_3.html
INCLUDE filename
Include the linker script filename at this point. The file will be searched for in the current directory, and in any directory specified with the -L option. You can nest calls to INCLUDE up to 10 levels deep.
So if you add INCLUDE config.ini to the start of your linker script it should work.
Another approach is to use the C preprocessor to generate your linker script.
You can use -imacros to load a config.h that defines the symbols you want, then use them in the linkerscript.ld.h and generate the linker script before using it to link
gcc -imacros config.h -E linkerscript.ld.h -o linkerscript.ld

Stack initialisation in GNU ARM toolchain

Checking the startup file provided as an example in the GNU ARM toolchain, I couldnt understand one thing.
Code snippets provided here are taken from examples included in GNU ARM Embedded Toolchain files downloaded from official website. Code compiles and everything seems to be good.
I am wondering why they wrote this code exactly like that, why they are using same names for example?
I am wondering why my linker is not complaining about multiple definition error for __StackTop and __StackLimit. Here is the part of the file startup_ARMCM0.S
.syntax unified
.arch armv6-m
.section .stack
.align 3
#ifdef __STACK_SIZE
.equ Stack_Size, _*emphasized text*_STACK_SIZE
#else
.equ Stack_Size, 0xc00
#endif
.globl __StackTop
.globl __StackLimit
__StackLimit:
.space Stack_Size
.size __StackLimit, . - __StackLimit
__StackTop:
.size __StackTop, . - __StackTop
If the linker is defining the same symbols: __StackTop and __StackLimit.
.stack_dummy (COPY):
{
*(.stack*)
} > RAM
/* Set stack top to end of RAM, and stack limit move down by
* size of stack_dummy section */
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
While checking linker documentation, it was written that, given the example:
SECTIONS
{
.text :
{
*(.text)
_etext = .;
PROVIDE(etext = .);
}
}
In this example, if the program defines _etext (with a leading
underscore), the linker will give a multiple definition error. If, on
the other hand, the program defines etext (with no leading
underscore), the linker will silently use the definition in
the program. If the program references etext but does not define
it, the linker will use the definition in the linker script.
Also, when using readelf -s just to check symbols generated from assembly file startup_ARMCM0.S without linking, I can see the symbol __StackTop and __StackLimit with one values. While, after linking they have the values set up by the linker (keeping in mind that the value of the linker is actually stored in address of the symbol).

Windriver compiler linker file regex

is there a way to use regex to add all C object files starting with foo for example to the linker file bss section with Windriver compiler instead of adding them manually one by one
SECTIONS {
outputa 0x10000 :
{
foo1.o (.bss)
foo2.o (.bss)
......
foon.o (.bss)
}
Imagined solution
SECTIONS {
outputa 0x10000 :
{
foo*.o (.bss)
Yes, it is possible to use regex in linker script.
GROUP : {
.sectionname:{"foo*"(.bss) }
....
}

How link the same object into both data and program memory of a DSP?

I need to put the same object into different memory sections. I'm working on a DSP with separate data and program memory. The .text sections are normally stored inside the P-MEM. But I want to store the same code also inside the data memory. It is possible to copy it during run-time, but I think I should also be possible during link time.
This is what I'm looking for, but it's not working since I could not find a "copy" or "duplicate" instruction that would allow to put the same code in different sections.
MEMORY
{
/* MAP 1*/
VECS: org=0x00000000 len=0x00000400
PMEM: org=0x00000400 len=0x0000FC00
DMEM: org=0x80000000 len=0x0000F800
DMEM_FT: org=0x8000F800 len=0x00000800
}
SECTIONS
{
vectors > VECS
.text > PMEM <----- containing ALL code (also including func1.obj(.text) )
.bss > DMEM
.cinit > DMEM
.stack > DMEM
.far > DMEM
.switch > DMEM
.data > DMEM
.sysmem > DMEM
.const > DMEM
.cio > DMEM
dmem_mirror:
{
func1.obj(.text)
} > DMEM_FT
}
If I'm using the linker script above, it's clearly putting the func1.obj only inside the dmem_FT section (that`s what the linker is supposed to do!), but that is not what I want :-/ . I'm working with the Texas Instruments compiler and linker, but the syntax is the same as on a GCC linker.
A quick look at the GNU ld manual does not give an obvious solution. One possible solution does come to mind. You could do a partial (ld -r) link of func1.obj, sending all the sections except .text to the special section /DISCARD/ and only outputting the .text section to e.g. func1a.obj. Unfortunately, I think you'll see multiple symbol definition errors from the linker when you actually do the final link.

Resources