diff --git a/include/eld/Diagnostics/DiagLDScript.inc b/include/eld/Diagnostics/DiagLDScript.inc index 410c3b53a..d14207781 100644 --- a/include/eld/Diagnostics/DiagLDScript.inc +++ b/include/eld/Diagnostics/DiagLDScript.inc @@ -76,6 +76,8 @@ DIAG(error_memory_region_exceeded_limit, DiagnosticEngine::Error, "0x%2 bytes") DIAG(error_memory_region_empty, DiagnosticEngine::Error, "Missing name for memory region, name cannot be empty") +DIAG(error_section_not_in_region, DiagnosticEngine::Error, + "address 0x%2 of section '%0' is not within region '%1' (%3)") DIAG(error_duplicate_memory_region, DiagnosticEngine::Error, "Duplicate memory region %0") DIAG(verbose_verified_add_memory_region, DiagnosticEngine::Verbose, diff --git a/include/eld/Object/ScriptMemoryRegion.h b/include/eld/Object/ScriptMemoryRegion.h index bf30d1af0..2e984444f 100644 --- a/include/eld/Object/ScriptMemoryRegion.h +++ b/include/eld/Object/ScriptMemoryRegion.h @@ -33,7 +33,7 @@ class ScriptMemoryRegion { void addOutputSectionLMA(const OutputSectionEntry *O); - void verifyMemoryUsage(LinkerConfig &Config); + void verifyMemoryUsage(LinkerConfig &Config, const OutputSectionEntry &out); eld::Expected getOrigin() const; diff --git a/lib/Object/ScriptMemoryRegion.cpp b/lib/Object/ScriptMemoryRegion.cpp index 08d45a550..3351d640d 100644 --- a/lib/Object/ScriptMemoryRegion.cpp +++ b/lib/Object/ScriptMemoryRegion.cpp @@ -42,8 +42,16 @@ void ScriptMemoryRegion::addOutputSection(const OutputSectionEntry *O) { FirstOutputSectionExceededLimit = O; } } +void ScriptMemoryRegion::verifyMemoryUsage(LinkerConfig &Config, + const OutputSectionEntry &out) { + if (!out.prolog().hasVMA()) + return; + uint64_t vma = out.prolog().vma().result(); + if (!containsVMA(vma)) + Config.raise(Diag::error_section_not_in_region) + << out.name() << getName() << utility::toHex(vma) + << out.prolog().vma().getContext(); -void ScriptMemoryRegion::verifyMemoryUsage(LinkerConfig &Config) { auto ExpLen = getLength(); if (ExpLen && !ExpLen.value() && Config.showLinkerScriptWarnings()) { MemorySpec *Spec = MMemoryDesc->getMemorySpec(); diff --git a/lib/Target/GNULDBackend.cpp b/lib/Target/GNULDBackend.cpp index 0dd419d59..3fc121fe9 100644 --- a/lib/Target/GNULDBackend.cpp +++ b/lib/Target/GNULDBackend.cpp @@ -4970,8 +4970,11 @@ void GNULDBackend::clearMemoryRegions() { } void GNULDBackend::verifyMemoryRegions() { - for (auto &M : m_Module.getLinkerScript().getMemoryRegions()) - M->verifyMemoryUsage(config()); + for (auto *out : m_Module.getLinkerScript().sectionMap()) { + if (!out->epilog().hasRegion()) + continue; + out->epilog().region().verifyMemoryUsage(config(), *out); + } } bool GNULDBackend::assignMemoryRegions() { diff --git a/test/Common/standalone/linkerscript/MemoryRegionVMACheck/Inputs/1.c b/test/Common/standalone/linkerscript/MemoryRegionVMACheck/Inputs/1.c new file mode 100644 index 000000000..43f7f7595 --- /dev/null +++ b/test/Common/standalone/linkerscript/MemoryRegionVMACheck/Inputs/1.c @@ -0,0 +1,2 @@ +int foo() { return 1; } +int bar() { return 3; } \ No newline at end of file diff --git a/test/Common/standalone/linkerscript/MemoryRegionVMACheck/Inputs/script.t b/test/Common/standalone/linkerscript/MemoryRegionVMACheck/Inputs/script.t new file mode 100644 index 000000000..2fad55bf4 --- /dev/null +++ b/test/Common/standalone/linkerscript/MemoryRegionVMACheck/Inputs/script.t @@ -0,0 +1,8 @@ +MEMORY { + RAM : ORIGIN = 0x1000, LENGTH = 0x1000 + ROM : ORIGIN = 0x5000, LENGTH = 0x1000 +} +SECTIONS { + .foo (0x2500) : { *(.text.foo) } >RAM + .bar : { *(.text.bar) } >RAM +} diff --git a/test/Common/standalone/linkerscript/MemoryRegionVMACheck/MemoryRegionVMACheck.test b/test/Common/standalone/linkerscript/MemoryRegionVMACheck/MemoryRegionVMACheck.test new file mode 100644 index 000000000..09ae570f0 --- /dev/null +++ b/test/Common/standalone/linkerscript/MemoryRegionVMACheck/MemoryRegionVMACheck.test @@ -0,0 +1,10 @@ +#---MemoryRegionVMACheck.test----------------------- Executable -----------------# +#BEGIN_COMMENT +# Test that ELD errors when a section VMA does not fit in its assigned +# memory region, matching BFD and LLD behavior. +#END_COMMENT +#START_TEST +RUN: %clang %clangg0opts -o %t1.1.o %p/Inputs/1.c -c -ffunction-sections +RUN: %not %link %linkopts -o %t1.1.out %t1.1.o -T %p/Inputs/script.t 2>&1 | %filecheck %s +#END_TEST +CHECK: address {{0x[0-9a-f]+}} of section '.foo' is not within region 'RAM' \ No newline at end of file