llvm / llvm/llvm-project

LLD requires fixed LMA to VMA offset in program header

Open
#222,593 1 comment 0 reactions 0 assignees View on GitHub
lld:ELF
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

In the vast majority of Program Headers, including all that are auto-generated by the linker, there is a fixed LMA to VMA offset. This permits the PHDR to completely describe both the LMA and VMA of the contents of the segment.

Embedded systems, of course, often do not use the VMA, the LMA is used by llvm-objcopy to extract the LMA contents into a binary and the VMA contents of each Output Section within are copied to the appropriate address using linker defined symbols.

GNU ld, when an explicit PHDRS assignment is used, can support each OutputSection having a different LMA to VMA offset. This is very much advanced user territory, and a user can run into overlapping LMA/file errors if they get it wrong.

Encountered this when thinking about how to write a conversion tool from armlink scatter-files to linker scripts. In armlink this way of writing program headers is idiomatic as it is expected that the ELF file contents are extracted and not used directly.
```
/* A LR maps to an ELF program header */
LR 0x8000 {
/* ER (in this case) maps to one ELF Output Section
ER_RO 0x8000 {
/* LMA to VMA offset 0 */
*(+RO)
}
ER_RW 0x1000000 {
/* LMA to VMA offset 0x1000000 - (0x8000 + sizeof(ER_RO)) */
*(+RW)
}
ER_ZI +0 {
/* Relative base, maintain previous LMA to VMA offset */
*(+ZI)
}
}
```

Example of equivalent linker script:
```
PHDRS {
text PT_LOAD ;
}

SECTIONS {
.text 0x8000 : { *(.text) } :text
.data 0x1000000 : AT(LOADADDR(.text) + SIZEOF(.text)) { *(.data) } :text
.bss : AT(LOADADDR(.data) + SIZEOF(.data)) { *(.bss) } :text
}
```
With a trivial
```
.text
nop
.data
.word 4
.bss
.space 4
```
Using ld.lld we get a single LMA to VMA offset and a large program header
```
VMA LMA Size Align Out In Symbol
8000 8000 4 4 .text
8000 8000 4 4 space.o:(.text)
8000 8000 0 1 $a.0
1000000 1000000 4 1 .data
1000000 1000000 4 1 space.o:(.data)
1000004 1000004 4 1 .bss
1000004 1000004 4 1 space.o:(.bss)

Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x008000 0x00008000 0x00008000 0xff8004 0xff8008 RWE 0x10000
```
Using arm-none-eabi-ld we get a compact program header.
```
.text 0x00008000 0x4
*(.text)
.text 0x00008000 0x4 space.o

.glue_7 0x00008004 0x0
.glue_7 0x00008004 0x0 linker stubs

.glue_7t 0x00008004 0x0
.glue_7t 0x00008004 0x0 linker stubs

.vfp11_veneer 0x00008004 0x0
.vfp11_veneer 0x00008004 0x0 linker stubs

.v4_bx 0x00008004 0x0
.v4_bx 0x00008004 0x0 linker stubs

.data 0x01000000 0x4 load address 0x00008004
*(.data)
.data 0x01000000 0x4 space.o

.bss 0x01000004 0x4 load address 0x00008008
*(.bss)
.bss 0x01000004 0x4 space.o

Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x001000 0x00008000 0x00008000 0x00008 0x0000c RWE 0x1000
```

This can be accomplished in LLD, but it does require multiple program headers, and a user may need to concatenate the binary contents separately.

Would be good to support, but could require some changes to the address assigment.

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the linker-script example with LLD and compare its program headers with the arm-none-eabi-ld output shown here. Investigate the PHDRS and address-assignment behavior; done means LLD can represent differing LMA-to-VMA offsets, likely with multiple program headers, without the oversized single segment.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.