Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the size of an input section (to place it at the end of memory)

I have the following linker script: .data & .bss are placed into ram, then a .heap section fills the remaining memory.

Now I want to add a .noinit section that always gets placed at the end of the memory. That is so it gets ignored by bootloaders and the like.

I still want my .heap section to occupy all available space between .bss and .noinit, but for this I need to know the size of the .noinit section.

A naive approach failed:

/* .bss section which is used for uninitialized data */ .bss (NOLOAD) : {     . = ALIGN(4);     _sbss = . ;     _szero = .;     *(.bss .bss.*)     *(COMMON)     . = ALIGN(4);     _ebss = . ;     _ezero = .; } > ram  /* heap section */ .heap (NOLOAD) : {     . = ALIGN(4);     _sheap = . ;     . = ORIGIN(ram) + LENGTH(ram) - SIZEOF(.noinit);     _eheap = . ; }  > ram  /*  * collect all uninitialized sections that go into RAM  */ .noinit (NOLOAD) : {     . = ALIGN(4);     __noinit_start = .;     *(.noinit)     __noinit_end = .; }  > ram 

Here SIZEOF(.noinit) is always 0 because the section is defined after that statement.

But in fact what I want is SIZEOF(*(.noinit)) - however this is a syntax error.

So how do I get the size of an input section without placing it into an output section first?

like image 828
user1273684 Avatar asked May 19 '19 21:05

user1273684


People also ask

What is an LD script?

Linker Scripts The ld command language is a collection of statements; some are simple keywords setting a particular option, some are used to select and group input files or name output files; and two statement types have a fundamental and pervasive impact on the linking process.

How do you define a section in a linker script?

The following linker script will do this function. You write the ` SECTIONS ' command as the keyword ` SECTIONS ', followed by a series of symbol assignments and output section descriptions enclosed in curly braces. The first line in the above example sets the special symbol ` . ', which is the location counter.

What is linker directive?

The Linker Script is a text file made up of a series of Linker directives which tell the Linker where the available memory is and how it should be used. Thus, they reflect exactly the memory resources and memory map of the target microcontroller.

What is the use of linker script?

The main purpose of the linker script is to describe how the sections in the input files should be mapped into the output file, and to control the memory layout of the output file.


1 Answers

Not exactly kosher, but after digging through the source code for GNU ld it looks like you can specify the address of section after it is defined.

The following linker script should give you the desired behavior:

MEMORY {     ram   (rwx) : ORIGIN = 0x10000, LENGTH = 0x0002000 }  SECTIONS {      .bss (NOLOAD) : {         . = ALIGN(4);         _sbss = . ;         _szero = .;         *(.bss .bss.*)         *(COMMON)          /* Note: Just for example - padding .bss by 0x100 bytes so its not empty */         . = 0x100;          . = ALIGN(4);         _ebss = . ;         _ezero = .;     } > ram       /* create .noinit section */     .noinit (NOLOAD): {         . = ALIGN(4);         __noinit_start = .;          /* Note: Just for example - padding .noinit by 0x100 bytes so its not empty */         . = 0x100;          *(.noinit)         __noinit_end = .;     }  > ram      /* place .heap after .bss */     .heap _ebss (NOLOAD) : {         . = ALIGN(4);         _sheap = . ;         . = ABSOLUTE(ORIGIN(ram) + LENGTH(ram) - SIZEOF(.noinit));         _eheap = . ;     }  > ram      /* update .noinit to be placed at end of heap */     .noinit _eheap (NOLOAD) : { } > ram }  

The output of an empty binary linked with the above script show the correct placement of sections and symbols:

echo | gcc -x c++ - -nostartfiles -T linkerScript.ld -Xlinker --orphan-handling=discard -fuse-ld=bfd  && objdump -th a.out  a.out:     file format elf64-x86-64  Sections: Idx Name          Size      VMA               LMA               File off  Algn   0 .bss          00000100  0000000000010000  0000000000010000  00001000  2**0                   ALLOC   1 .noinit       00000100  0000000000011f00  0000000000011f00  00001000  2**0                   ALLOC   2 .heap         00001e00  0000000000010100  0000000000010100  00001000  2**0                   ALLOC SYMBOL TABLE: 0000000000010000 l    d  .bss   0000000000000000 .bss 0000000000011f00 l    d  .noinit        0000000000000000 .noinit 0000000000010100 l    d  .heap  0000000000000000 .heap 0000000000010100 g       .heap  0000000000000000 _sheap 0000000000010000 g       .bss   0000000000000000 _sbss 0000000000010000 g       .bss   0000000000000000 _szero 0000000000010100 g       .bss   0000000000000000 _ebss 0000000000010100 g       .bss   0000000000000000 _ezero 0000000000011f00 g       .noinit        0000000000000000 __noinit_start 0000000000012000 g       .noinit        0000000000000000 __noinit_end 0000000000011f00 g       .heap  0000000000000000 _eheap 

Note: I couldn't find any documentation regarding this behavior so I can't guarantee this trick will work in future revisions of ld.

Note: This trick doesn't work for the gold linker.

like image 104
Samuel Gonzalez Avatar answered Sep 24 '22 23:09

Samuel Gonzalez