Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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?

like image 744
nonsensickle Avatar asked Sep 05 '13 23:09

nonsensickle


2 Answers

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.

like image 68
Fletcher D Avatar answered Sep 19 '22 23:09

Fletcher D


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.

like image 44
Magnus Persson Avatar answered Sep 17 '22 23:09

Magnus Persson