mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-30 17:21:10 +00:00
[ELF] Refine LMA offset propagation rule in D76995
If neither AT(lma) nor AT>lma_region is specified, D76995 keeps `lmaOffset` (LMA - VMA) if the previous section is in the default LMA region. This patch additionally checks that the two sections are in the same memory region. Add a test case derived from https://bugs.llvm.org/show_bug.cgi?id=45313 .mdata : AT(0xfb01000) { *(.data); } > TCM // It is odd to make .bss inherit lmaOffset, because the two sections // are in different memory regions. .bss : { *(.bss) } > DDR With this patch, section VMA/LMA match GNU ld. Note, GNU ld supports out-of-order (w.r.t sh_offset) sections and places .text and .bss in the same PT_LOAD. We don't have that behavior. Reviewed By: grimar Differential Revision: https://reviews.llvm.org/D81986
This commit is contained in:
parent
4171f80d54
commit
8ffb2097cc
@ -851,7 +851,8 @@ void LinkerScript::assignOffsets(OutputSection *sec) {
|
||||
if (!(sec->flags & SHF_ALLOC))
|
||||
dot = 0;
|
||||
|
||||
bool prevLMARegionIsDefault = ctx->lmaRegion == nullptr;
|
||||
const bool sameMemRegion = ctx->memRegion == sec->memRegion;
|
||||
const bool prevLMARegionIsDefault = ctx->lmaRegion == nullptr;
|
||||
ctx->memRegion = sec->memRegion;
|
||||
ctx->lmaRegion = sec->lmaRegion;
|
||||
if (ctx->memRegion)
|
||||
@ -872,14 +873,15 @@ void LinkerScript::assignOffsets(OutputSection *sec) {
|
||||
|
||||
// ctx->lmaOffset is LMA minus VMA. If LMA is explicitly specified via AT() or
|
||||
// AT>, recompute ctx->lmaOffset; otherwise, if both previous/current LMA
|
||||
// region is the default, reuse previous lmaOffset; otherwise, reset lmaOffset
|
||||
// to 0. This emulates heuristics described in
|
||||
// region is the default, and the two sections are in the same memory region,
|
||||
// reuse previous lmaOffset; otherwise, reset lmaOffset to 0. This emulates
|
||||
// heuristics described in
|
||||
// https://sourceware.org/binutils/docs/ld/Output-Section-LMA.html
|
||||
if (sec->lmaExpr)
|
||||
ctx->lmaOffset = sec->lmaExpr().getValue() - dot;
|
||||
else if (MemoryRegion *mr = sec->lmaRegion)
|
||||
ctx->lmaOffset = alignTo(mr->curPos, sec->alignment) - dot;
|
||||
else if (!prevLMARegionIsDefault)
|
||||
else if (!sameMemRegion || !prevLMARegionIsDefault)
|
||||
ctx->lmaOffset = 0;
|
||||
|
||||
// Propagate ctx->lmaOffset to the first "non-header" section.
|
||||
|
@ -71,7 +71,7 @@ The two keywords cannot be specified at the same time.
|
||||
|
||||
If neither ``AT(lma)`` nor ``AT>lma_region`` is specified:
|
||||
|
||||
- If the previous section is also in the default LMA region, the difference
|
||||
between the LMA and the VMA is computed to be the same as the previous
|
||||
difference.
|
||||
- If the previous section is also in the default LMA region, and the two
|
||||
section have the same memory regions, the difference between the LMA and the
|
||||
VMA is computed to be the same as the previous difference.
|
||||
- Otherwise, the LMA is set to the VMA.
|
||||
|
30
lld/test/ELF/linkerscript/lma-offset2.s
Normal file
30
lld/test/ELF/linkerscript/lma-offset2.s
Normal file
@ -0,0 +1,30 @@
|
||||
# REQUIRES: x86
|
||||
## If neither AT(lma) nor AT>lma_region is specified, don't propagate
|
||||
## lmaOffset if the section and the previous section are in different memory
|
||||
## regions.
|
||||
|
||||
# RUN: echo '.globl _start; _start: ret; \
|
||||
# RUN: .data; .byte 0; \
|
||||
# RUN: .bss; .byte 0' | \
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64 - -o %t.o
|
||||
# RUN: ld.lld -T %s %t.o -o %t
|
||||
# RUN: llvm-readelf -l %t | FileCheck %s
|
||||
|
||||
## GNU ld places .text and .bss in the same RWX PT_LOAD.
|
||||
# CHECK: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg
|
||||
# CHECK-NEXT: LOAD 0x001000 0x000000000fb00000 0x000000000fb00000 0x000001 0x000001 R E
|
||||
# CHECK-NEXT: LOAD 0x002000 0x000000001f400000 0x000000000fb01000 0x000001 0x000001 RW
|
||||
# CHECK-NEXT: LOAD 0x002001 0x000000000fb00001 0x000000000fb00001 0x000000 0x000001 RW
|
||||
|
||||
MEMORY {
|
||||
DDR : o = 0xfb00000, l = 185M
|
||||
TCM : o = 0x1f400000, l = 128K
|
||||
}
|
||||
|
||||
SECTIONS {
|
||||
.text : { *(.text) } > DDR
|
||||
.mdata : AT(0xfb01000) { *(.data); } > TCM
|
||||
## .mdata and .bss are in different memory regions. Start a new PT_LOAD for
|
||||
## .bss, even if .mdata does not set a LMA region.
|
||||
.bss : { *(.bss) } > DDR
|
||||
}
|
Loading…
Reference in New Issue
Block a user