I am wondering what is the use of defining symbols in a linker script. Using a linker script to arrange different sections is understandable but defining new symbols in the script is not clear to me. I was reading an article which uses a linker script defining two new symbols but those symbols were not referenced anywhere else in the linker script or in the article. An example is the use of sbss and ebss symbols in the bss section as shown below :
ENTRY (loader)
SECTIONS
{ . = 0x00100000;
.text ALIGN (0x1000) :
{
*(.text)
}
.rodata ALIGN (0x1000) :
{
*(.rodata*)
}
.data ALIGN (0x1000) :
{
*(.data)
}
.bss :
{
sbss = .;
*(COMMON)
*(.bss)
ebss = .;
}
}
There are other symbols also which are frequently used such as etext , dataEnd etc. Please explain the use of defining such symbols when they are not referenced anywhere in the script.
vjain27,
I do not know why one would define symbols as your example linker script defines. This is mostly done in order to allow the executable to know the start and end of a section. This is useful if the data needs to be copied, or otherwise manipulated in memory.
When writing an x86 bootloader, I want the image to be a multiple of 512 bytes by using:
. = ALIGN(512);
in the linker script.
But then I need some way to know the exact size, and pass that to the al of my boot code which will to an int 13h BIOS call that loads data from hard disk to memory. So I wrote something like:
__stage2_size = .;
BYTE((ALIGN(.) / 512) - 1);
. = ALIGN(512);
and used __stage2_size on the boot script.
Related
I have a very simple linker script as follows:
ENTRY(_start)
SECTIONS {
. = 1M; /* Load the kernel at 1M */
.text ALIGN (4K) : {
*(.multiboot) /* the multiboot header */
*(.text)
}
.data ALIGN (4K) : { *(.data) }
.bss ALIGN (4K) : { *(.bss) *(COMMON) }
}
While this works for a very basic assembly project, when I add in C, I want to make sure that no important sections from that get left out. The readelf -S output on some compiled C code shows at least a half dozen other sections that gcc's output includes, not including the debug sections.
I would like these sections to be included at the end, but I don't want to have to write it for every section (which could vary depending on whether I'm using debug, as well as on the contents of the C code).
Is there a way to make ld include any extra input sections without specifying them explicitly in the linker script?
Just curious to know what is the difference between such constructions (for text, data, rodata, bss etc) in linker script:
.data :
{
*(.data)
}
.data :
{
*(.data*)
}
.data :
{
*(.data.*)
}
In all cases we gather data sections from all object files, but the devil is in the detail.
Fast test showed that addresses in map file differ and in turn it influences the size of executable file.
I tried to find the information in ld documentation but found nothing (or just missed it).
I guess that it should be something very simple (so called obvious).
Any ideas will be highly appreciated.
In any place where you may use a specific file or section name, you may also use a wildcard pattern.
It works like a regular pattern
*(.data) - .data sections, Example: .data
*(.data*)- .data* section, Example: .dataTEST
*(.data.*) - .data.* section, Example: .data.TEST
Find more info here
I have a requirement where I need to create a duplicate/copy section of .data section.
I've tried creating a dummy section with same size of data section in linker script and copy the contents of data section to the dummy section in the init functions of my ELF image, but that doesn't suit my requirement, as I want the copy/duplicate section to be created along with final ELF image not during the execution of it.
Below is what I wanted in my linker script,
SECTIONS {
.data : { <data section contents> }
.dummydata : { <copy of .data section> }
}
Can anyone help to write the linker script to match above requirement?
I don't think this can be done with just ld and a linker script. Given this line from here:
If a file name matches more than one wildcard pattern, or if a file
name appears explicitly and is also matched by a wildcard pattern, the
linker will use the first match in the linker script.
It sounds like the linker script will only put the data (or anything) in one section.
However all hope is not lost. You can copy the section using objcopy and then add the section using objcopy again
objcopy -O binary --only-section=.data your-file temp.bin
objcopy --add-section .dummydata=temp.bin your-file
This will append the section to be the last section with a VMA/LMA of 0. You can then use objcopy to move the section to the desired location.
objcopy --change-section-address .dummydata=desired-address your-file
Of course if there is something already there that would be problematic. Luckily you can create a hole right after your first .data with something like:
data_start = .;
.data : { *(.data) }
data_end = .;
. += (data_end - data_start);
This should create a hole right after your first data, big enough to put another copy of data right after it. If this isn't exactly where you want it to be just add (data_end - data_start) where you want the hole.
Finally you can change the section flags, again with objcopy
objcopy --set-section-flags .dummydata=the-flags-you-want your-file
Not as clean as just duplicating something in the linker script but it should work.
I'm working on a toy operating system and bootloader. I'm trying to write the kernel in C, and then convert it to binary for direct jumping to from the bootloader (i.e., I'm not loading an ELF or anything like that).
I've got the linker file setup with the proper origin (I'm loading the kernel to address 0xC0000000) and confirm with objdump that it's using it correctly. However, it's not placing my entry point at the start (0xC0000000) like I wanted. I guess that's not what the ENTRY directive is for.
My problem is simply that I want to place a particular function, kernel_main at address 0xC0000000. Is there a way I can accomplish this using gcc for compiling and linking?
Here is what the relevant parts of my linker file look like:
ENTRY(kernel_main)
SECTIONS
{
/* Origin */
. = 0xC0000000;
.text BLOCK(4K) : ALIGN(4K)
{
*(.text)
}
/* etc. */
}
The ENTRY linker command tells the linker which symbol the loader should jump to when it loads the program. If you're making your own operating system it's really not used since there is no loader.
Instead, as you know, the program simply starts at the first code address.
To make place a special segment of code first, you could place it in a special code segment, and put it first in the list:
.text BLOCK(4K) : ALIGN(4K)
{
*(.text.boot) *(.text)
}
The segments in the list is placed in the order they are given.
The ENTRY directive is only useful for output formats that support an entrypoint. Since you're using a binary output, this won't work. What you can do is write a small stub in a separate source file (i.e. entry.c or entry.asm or whatever). Then, in the ld script, before the *(.text) line, you can put entry.o(.text). This instructs ld to load the symbols from a specific object file (whereas * denotes all object files). So the new ld script would look like this:
ENTRY(kernel_main)
SECTIONS
{
/* Origin */
. = 0xC0000000;
.text BLOCK(4K) : ALIGN(4K)
{
entry.o(.text)
*(.text)
}
/* etc. */
}
As long as entry.o contains just one function (that simply calls your kernel main), this should work.
I have the following line in my linker script
JumpTable ABSOLUTE(0x2000000C): AT(eROData)
{
JumpTableStart = .;
*(.JumpSection);
. = ALIGN(4);
JumpTableEnd = .;
} > SRAM
eROData is an address from flash and assumes a value 0x1000xxxx
After linking, I notice that the linker assigns both VMA and LMA to the section JumpTable.
This is the listing from the list file.
2 .rodata 00000004 10001214 10001214 00001214 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 JumpTable 00000140 2000000c 2000000c 00008954 2**2
CONTENTS, READONLY
No such problems with the .data section.
Is this a known GNU linker problem?
EDIT:
I noticed that if the section ".JumpSection" were defined in a C file, the LMA was correctly assigned.
I am facing this problem because the section is defined in an assembly file.
Have you faced this problem before?
EDIT - SOLUTION :
It turns out that .JumpSection had to be defined with correct attributes:
.section ".JumpSection","ax",%progbits
Only then would the linker behave correctly.
So here is what I found out. Perhaps this could save someone from hours of frustrating debugging.
My main problem was that there was a piece of assembly code that needed to be linked into SRAM space and loaded from flash space. So the VMA had to be a SRAM address and LMA a flash address.
In the past, I always succeeded in accomplishing above for functions/data defined in a c file. All I would need to do was assign a section attribute and modify the linker script appropriately.
INFERENCE 1: The linker allows a different LMA for standard TEXT and DATA sections although they may be named differently using the section attribute.
No such luck when the same was attempted in an assembly file. The linker refused to acknowledge that input section .JumpTable defined above was actually a user defined TEXT section.
The solution was then
To move the assembly code to a new file JumpTable.S.
Rename the the input section .JumpTable to .text
Modify the linker file as follows
.text :
{
*(EXCLUDE_FILE(*JumpTable.o) .text); /* Exclude .text of JumpTable.o and place others */
} > FLASH
JumpTable ABSOLUTE(0x2000000C) : AT (eROData) /* Link to SRAM and Load after const data */
{
JumpTableStart = .;
*JumpTable.o(.text); /* Place .text of JumpTable.o into JumpTable output section) */
JumpTableEnd = .;
} > SRAM
Maybe there is a better explanation/another root cause. But this saved my day for sure.