-
Notifications
You must be signed in to change notification settings - Fork 6.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
linker: Introduce linker-tool-lld.h #59792
linker: Introduce linker-tool-lld.h #59792
Conversation
Since |
2a45b86
to
0dc9945
Compare
Good suggestion! Fixed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume this needs to be done for other architectures than just cortex M.
Yes. Unfortunately, I don't have access to other architectures to make tests. Without this patch, LLD linker fails, because it doesn't know what to do with ALIGN_WITH_INPUT. I was thinking about fixing that in |
Wouldn't we waste at most 16 bytes? |
If there are more sections, every section will be aligned to 16 bytes, so we can waste more. In the worst case we can waste 15 bytes * number of sections. Side note (after reading #59667 ): |
Until now, linker-tool-gcc.h was used when LLD linker was chosen. This causes linking issues because for GNU LD we use ALIGN_WITH_INPUT attribute which is not available in LLVM LLD. When using GNU LD we have to use ALIGN_WITH_INPUT to make sure that the difference between VMA and LMA remains the same between output sections that have different memory regions for VMA and LMA (RAM and FLASH). With ALIGN_WITH_INPUT it's safe to do the memcpy of sections that needs to be copied from flash to RAM in one function call: (from z_data_copy() in kernel/xip.c) ``` z_early_memcpy(&__data_region_start, &__data_region_load_start, __data_region_end - __data_region_start); ``` By default, LLVM LLD aligns both VMA and LMA to the same value, but when --omagic (-N) option is provided then only the first output section of given region has aligned LMA and the difference between VMA addresses (0 is this is the first section) is added. As a result the difference between LMA and VMA is constant for every section, so this emulates ALIGN_WITH_INPUT option present in GNU LD (required by XIP systems). The --omagic flag is defined in cmake/linker/lld/target_baremetal.cmake Example: ``` MEMORY { ROM : ORIGIN = 0x1000, LENGTH = 1K RAM : ORIGIN = 0x11000, LENGTH = 1K } SECTIONS { .text 0x1000 : { *(.text*) } >ROM .data.rel.ro : { *(.data.rel.ro) } >RAM AT>ROM .data : { *(.data*) } >RAM AT>ROM } ``` ``` echo '.globl _start; _start: nop; .byte 1;'\ '.data.rel.ro; .balign 16; .byte 0;'\ '.data; .balign 32; .byte 0;' | \ llvm-mc -filetype=obj -triple=arm - -o test.o armv7m-cros-eabi-ld.lld --sort-section=alignment -N -T script.ld \ test.o -o lld_out ``` ``` Idx Name Size VMA LMA File off Algn 0 .text 0000000 00001000 00001000 00000094 2**2 1 .data.rel.ro 00000001 00011000 00001010 000000a0 2**4 2 .data 00000001 00011020 00001030 000000c0 2**5 ``` In this example the first section has lower alignment than the following section, but with -N option the difference between VMA and LMA is the same for .data.rel.ro and .data sections. For comparison, using BFD linker with --omagic option results in the following: ``` Idx Name Size VMA LMA File off Algn 0 .text 0000000 00001000 00001000 00000094 2**2 1 .data.rel.ro 00000001 00011000 00001005 000000a0 2**4 2 .data 00000001 00011020 00001006 000000c0 2**5 ``` with ALIGN_WITH_INPUT added, GNU LD adds the difference between VMA to LMA, but doesn't align LMA of .data.rel.ro section: ``` Idx Name Size VMA LMA File off Algn 0 .text 0000000 00001000 00001000 00000074 2**2 1 .data.rel.ro 00000001 00011000 00001005 00000080 2**4 2 .data 00000001 00011020 00001025 000000a0 2**5 ``` Signed-off-by: Patryk Duda <[email protected]>
0dc9945
to
400bf51
Compare
I found that linker flag
The flag is enabled in cmake/linker/lld/target_baremetal.cmake As a result, LLVM LLD emulates behavior of GNU LD with ALIGN_WITH_INPUT. Please check commit message and comments in linker-tool-lld.h for more information. |
Until now, linker-tool-gcc.h was used when LLD linker was chosen. This causes linking issues because for GNU LD we use ALIGN_WITH_INPUT attribute which is not available in LLVM LLD.
When using GNU LD we have to use ALIGN_WITH_INPUT to make sure that the difference between VMA and LMA remains the same between output sections that have different memory regions for VMA and LMA (RAM and FLASH). With ALIGN_WITH_INPUT it's safe to do the memcpy of sections that needs to be copied from flash to RAM in one function call:
(from z_data_copy() in kernel/xip.c)
LLVM LLD aligns both VMA and LMA to the same value (in the following example it's maximum of input section alignment):
In this example the first section has lower alignment than the following section, despite of aligning both LMA and VMA there is a different gap size between
.data.rel.ro
and.data
sections. To fix that, we can set output section alignment of.data.rel.ro
to 32:which results in the following:
For comparison, using BFD linker with ALIGN_WITH_INPUT results in the following: