[ELF] Fix early overflow check in finalizeAddressDependentContent
LLD terminates with errors when it detects overflows in the finalizeAddressDependentContent calculation. Although, sometimes, those errors are not really errors, but an intermediate result of an ongoing address calculation. If we continue the fixed-point algorithm we can converge to the correct result. This patch * Removes the verification inside the fixed point algorithm. * Calls checkMemoryRegions at the end. Reviewed By: peter.smith, MaskRay Differential Revision: https://reviews.llvm.org/D152170
This commit is contained in:
parent
58789ed62a
commit
e4118a7ac0
@ -157,12 +157,6 @@ OutputDesc *LinkerScript::getOrCreateOutputSection(StringRef name) {
|
||||
static void expandMemoryRegion(MemoryRegion *memRegion, uint64_t size,
|
||||
StringRef secName) {
|
||||
memRegion->curPos += size;
|
||||
uint64_t newSize = memRegion->curPos - memRegion->getOrigin();
|
||||
uint64_t length = memRegion->getLength();
|
||||
if (newSize > length)
|
||||
error("section '" + secName + "' will not fit in region '" +
|
||||
memRegion->name + "': overflowed by " + Twine(newSize - length) +
|
||||
" bytes");
|
||||
}
|
||||
|
||||
void LinkerScript::expandMemoryRegions(uint64_t size) {
|
||||
@ -1461,3 +1455,23 @@ void LinkerScript::printMemoryUsage(raw_ostream& os) {
|
||||
os << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
static void checkMemoryRegion(const MemoryRegion *region,
|
||||
const OutputSection *osec, uint64_t addr) {
|
||||
uint64_t osecEnd = addr + osec->size;
|
||||
uint64_t regionEnd = region->getOrigin() + region->getLength();
|
||||
if (osecEnd > regionEnd) {
|
||||
error("section '" + osec->name + "' will not fit in region '" +
|
||||
region->name + "': overflowed by " + Twine(osecEnd - regionEnd) +
|
||||
" bytes");
|
||||
}
|
||||
}
|
||||
|
||||
void LinkerScript::checkMemoryRegions() const {
|
||||
for (const OutputSection *sec : outputSections) {
|
||||
if (const MemoryRegion *memoryRegion = sec->memRegion)
|
||||
checkMemoryRegion(memoryRegion, sec, sec->addr);
|
||||
if (const MemoryRegion *lmaRegion = sec->lmaRegion)
|
||||
checkMemoryRegion(lmaRegion, sec, sec->getLMA());
|
||||
}
|
||||
}
|
||||
|
||||
@ -339,6 +339,9 @@ public:
|
||||
// Describe memory region usage.
|
||||
void printMemoryUsage(raw_ostream &os);
|
||||
|
||||
// Verify memory/lma overflows.
|
||||
void checkMemoryRegions() const;
|
||||
|
||||
// SECTIONS command list.
|
||||
SmallVector<SectionCommand *, 0> sectionCommands;
|
||||
|
||||
|
||||
@ -2147,6 +2147,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
|
||||
// of finalizing other sections.
|
||||
for (OutputSection *sec : outputSections)
|
||||
sec->finalize();
|
||||
|
||||
script->checkMemoryRegions();
|
||||
}
|
||||
|
||||
// Ensure data sections are not mixed with executable sections when
|
||||
|
||||
74
lld/test/ELF/linkerscript/end-overflow-check.test
Normal file
74
lld/test/ELF/linkerscript/end-overflow-check.test
Normal file
@ -0,0 +1,74 @@
|
||||
REQUIRES: x86
|
||||
|
||||
# RUN: rm -rf %t && split-file %s %t
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/a.s -o %t/a.o
|
||||
|
||||
## The error should be triggered only for the second test where the overflow really exists.
|
||||
|
||||
RUN: ld.lld %t/a.o -T %t/b.lds -o /dev/null 2>&1
|
||||
RUN: not ld.lld %t/a.o -T %t/c.lds -o /dev/null 2>&1 | FileCheck --check-prefix=ERROR %s
|
||||
|
||||
# ERROR: error: section '_abss' will not fit in region 'SRAM0': overflowed by 1024 bytes
|
||||
# ERROR: error: section '.c.bss' will not fit in region 'SRAM0': overflowed by 1024 bytes
|
||||
# ERROR: error: section '.text' will not fit in region 'SRAM0': overflowed by 1025 bytes
|
||||
|
||||
#--- a.s
|
||||
.section .a.bss, "aw", %nobits
|
||||
.globl abss
|
||||
abss:
|
||||
.zero 0xDF0
|
||||
.size abss, 0xDF0
|
||||
|
||||
.section .c.bss, "aw", %nobits
|
||||
.globl cbss
|
||||
|
||||
.text
|
||||
.globl _start
|
||||
_start:
|
||||
nop
|
||||
|
||||
#--- b.lds
|
||||
MEMORY
|
||||
{
|
||||
SRAM0 (rw) : ORIGIN = 0x20000400, LENGTH = 10K
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
_abss ALIGN(REGION1__PRE_ALIGNMENT) :
|
||||
{
|
||||
REGION1__BEGIN = .; REGION1__ALIGNED_BEGIN = .; REGION1_ALIGNED_BEGIN = .;
|
||||
*(.a.bss)
|
||||
REGION1__END = .; . = ALIGN(REGION1__POST_ALIGNMENT); REGION1_ALIGNED_END = .;
|
||||
} > SRAM0
|
||||
}
|
||||
|
||||
REGION1__PRE_ALIGNMENT = 0x00000800;
|
||||
REGION1__PADDED_XOR = ((ABSOLUTE(REGION1__ALIGNED_BEGIN) | (ABSOLUTE(REGION1__END) - 1)) & ~(ABSOLUTE(REGION1__ALIGNED_BEGIN) & (ABSOLUTE(REGION1__END) - 1)));
|
||||
REGION1__PADDED_REGION_SHIFT = LOG2CEIL(REGION1__PADDED_XOR);
|
||||
REGION1__PADDED_SR_SHIFT = REGION1__PADDED_REGION_SHIFT - 3;
|
||||
REGION1__PADDED_SR_SIZE = MAX(1 << REGION1__PADDED_SR_SHIFT, 32);
|
||||
REGION1__POST_ALIGNMENT = REGION1__PADDED_SR_SIZE;
|
||||
|
||||
#--- c.lds
|
||||
MEMORY
|
||||
{
|
||||
SRAM0 (rw) : ORIGIN = 0x20000400, LENGTH = 4K
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
_abss ALIGN(REGION1__PRE_ALIGNMENT) :
|
||||
{
|
||||
REGION1__BEGIN = .; REGION1__ALIGNED_BEGIN = .; REGION1_ALIGNED_BEGIN = .;
|
||||
*(.a.bss)
|
||||
REGION1__END = .; . = ALIGN(REGION1__POST_ALIGNMENT); REGION1_ALIGNED_END = .;
|
||||
} > SRAM0
|
||||
}
|
||||
|
||||
REGION1__PRE_ALIGNMENT = 0x00000800;
|
||||
REGION1__PADDED_XOR = ((ABSOLUTE(REGION1__ALIGNED_BEGIN) | (ABSOLUTE(REGION1__END) - 1)) & ~(ABSOLUTE(REGION1__ALIGNED_BEGIN) & (ABSOLUTE(REGION1__END) - 1)));
|
||||
REGION1__PADDED_REGION_SHIFT = LOG2CEIL(REGION1__PADDED_XOR);
|
||||
REGION1__PADDED_SR_SHIFT = REGION1__PADDED_REGION_SHIFT - 3;
|
||||
REGION1__PADDED_SR_SIZE = MAX(1 << REGION1__PADDED_SR_SHIFT, 32);
|
||||
REGION1__POST_ALIGNMENT = REGION1__PADDED_SR_SIZE;
|
||||
@ -62,14 +62,14 @@
|
||||
## ORIGIN/LENGTH can be simple symbolic expressions. If the expression
|
||||
## requires interaction with memory regions, it may fail.
|
||||
|
||||
# RUN: echo 'MEMORY { ram : ORIGIN = symbol, LENGTH = 4097 } \
|
||||
# RUN: echo 'MEMORY { ram : ORIGIN = symbol, LENGTH = 4094 } \
|
||||
# RUN: SECTIONS { \
|
||||
# RUN: .text : { *(.text) } > ram \
|
||||
# RUN: symbol = .; \
|
||||
# RUN: .data : { *(.data) } > ram \
|
||||
# RUN: }' > %t.script
|
||||
# RUN: not ld.lld -T %t.script %t.o -o /dev/null 2>&1 | FileCheck --check-prefix=ERR_OVERFLOW %s
|
||||
# ERR_OVERFLOW: error: section '.text' will not fit in region 'ram': overflowed by 18446744073709547518 bytes
|
||||
# ERR_OVERFLOW: error: section '.data' will not fit in region 'ram': overflowed by 2 bytes
|
||||
|
||||
nop
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user