Linker Script - Placing a section at the end of a memory region
Asked Answered
P

5

23

I have searched far and wide for how to do this and have failed to come up with an answer.

My memory layout is as follows:

Fake Address | Section
     0       |  text
     7       |  relocate
    15       |  bss
    23       |  stack

At the end of the Stack I place the Heap. Which grows up and the stack is a full descending stack for the ARM chip I am using.

Now, what I want to do is place a single section, let's call it .persist, into my ram memory. I want it to reside at the very end of RAM and I want to program this into my linker script. However, this .persist section's size is not defined by me but is computed by the compiler from the symbols that it contains.

So far I've not come up with a good way to do it. Since I know the RAM start address and SIZE it would be trivial to calculate where the section needs to go if I knew the section size. However, according to the GNU linker documentation (pg 74) it seems that:

SIZEOF(section) Returns the size in bytes of the named section, if that section has been allocated. If the section has not been allocated when this is evaluated, the linker will report an error.

so I can't work out the size of the section in the linker script (since I want to calculate the size BEFORE I place it/allocate it).

Does anyone know a good way to do this?

Phytophagous answered 5/9, 2013 at 23:33 Comment(3)
I have the same problem. Does this help you? https://mcmap.net/q/247029/-load-script-to-load-a-section-at-the-top-of-a-memory-regionBunkhouse
It is a partial solution but not what I'm after. It is still the closest anyone else has come to helping. Thanks!Phytophagous
This is solved (see my comment below).Knopp
A
7

I was able to accomplish something similar by making linking a two-step process. First I compile the section in question to its own object file. In my case I had a metadata section generated from an assembly file. gcc -c will compile the source into object files, but not link them.

gcc -c  metadata.s  -o metadata.o

You could also build your whole program, then extract just the section in question with objcopy.

gcc -c  main.cc  -o main.o
objcopy --only-section=.metadata  main.o  metadata.o

Now I build and link the rest of the program, and include the object file among the linker's input.

gcc metadata.o  ../main.o  -o Program.elf  -T linkerscript.ld   

The linker reads the section .metadata from the object file, and I can reference its size in the linker script.

Audraaudras answered 13/9, 2016 at 19:23 Comment(2)
It has been a long time since I last worked on this project but your answer seems the closest to making it possible. I will have to verify it before marking as correct but for now +1.Phytophagous
I'm missing the linker script that makes this possible. AFAICS, there is no way to reference the size of an input section in a linker script, but this answer suggests otherwise...Leporide
K
5

I managed to solve it by calculating the size of the code by using the linker command: size. In my Makefile i set SIZE to the size of the code. I then call cpp (the preprocessor) to calculate all absolute addresses (using c-syntax). I then link using the generated linkfile: tmp.ld

%.elf: %.o
    $(eval SIZE := $(shell arm-none-eabi-size -B $<  | tail -n 1 | awk -F ' ' '{print $$1}'))
    $(CC) -DSEG_SIZE=$(SIZE) -P -E -x c link.ld -o tmp.ld
    $(CC) -o $@ $< $(LDFLAGS)

In the link.ld-file i can do all kinds of calculations (as SEG_SIZE is a constant):

#define SEG_LAST_ADDR 1234
#define MY_SEG        (SEG_LAST_ADDR - SEG_SIZE)

MEMORY
{
  bootloader     (rx)  : ORIGIN = MY_SEG,     LENGTH = SEG_SIZE
  ...
}

I finally link against the tmp.ld-file.

Knopp answered 12/3, 2019 at 16:54 Comment(1)
This is what I did when I need it --- it's vile, but it does work. Thanks!Intelligent
M
3

I had a similar problem I did it this way

/* heap section */
.heap (NOLOAD):
{
    . = ALIGN(8);
     _sheap = .;
    . = . + HEAP_SIZE;
    . = ALIGN(8);
    _eheap = .;
} > ram

_ram_end_ = ORIGIN(ram) + LENGTH(ram) -1 ;
_stack_size = _ram_end_ - _eheap ;

/* stack section */
.stack (NOLOAD): 
{
    . = ALIGN(8);
    _sstack = .;
    . = . + _stack_size;
    . = ALIGN(8);
    _estack = .;
} > ram

.LastSection (NOLOAD): /* for test in dump file */
{
    . = ALIGN(8);
} > ram
Moon answered 19/4, 2017 at 18:24 Comment(1)
Though I did consider this the question is asking for the placement of a section at the end of ram such that the last byte of that section occupies the _ram_end address. From what I can see you are placing the stack at the end of the ram and the stack simply occupies all remaining bytes. I'm asking to do this with a section that, unlike the stack, has a static size which doesn't depend on the sizes of the other sections. Effectively, in this example your stack takes up all remaining memory in the RAM.Phytophagous
C
-1

You can force sections at specific locations.

For example in this Red Hat GNU Linker documentation page, you can define the .data section to start at address 0x8000000:

SECTIONS
{
  . = 0x10000;
  .text : { *(.text) }
  . = 0x8000000;
  .data : { *(.data) }
  .bss : { *(.bss) }
}
Cyanide answered 8/4, 2015 at 8:45 Comment(1)
Yes, I am aware of this. However, this does not allow me to store my section so that it ends at a particular address. I want to get the size of my section, subtract it from an address giving me a result address and then place it at the result address. This way I can place my section, which has a variable size, at the end of my RAM memory block. I found this to not be possible and that is what the question is about.Phytophagous
E
-2

what I want to do is place a single section, let's call it .persist, into my ram memory. I want it to reside at the very end of RAM and I want to program this into my linker script.

Linker script has special variable called Location Counter which allows to modify the current address, and as such the size or address of a section or symbol, by creating gaps or holes in the address space.

Evaporation answered 3/11, 2014 at 22:8 Comment(2)
Yes, I am aware of this. You have missed what I said after about the SIZEOF operator not giving you the size of the section until you place it. I need to get the size of the section before I place it for this to work.Phytophagous
The only workaround would be if I could place the section, get the size and then unplace it and move it elsewhere...Phytophagous

© 2022 - 2024 — McMap. All rights reserved.