From c49828f7c9c0f4f976c4a3468b8532ca188466c4 Mon Sep 17 00:00:00 2001 From: ISSOtm Date: Thu, 17 Sep 2026 16:00:40 -0400 Subject: [PATCH] Fix memory region alignment checks Turns out the checks could fail spuriously if the starting alignment is non-zero, e.g. `align 8,$C0` in HRAM. (Fixes #2113.) This was tripped up by a test added to exercise the linker's section placement algorithm on a similar aligment-related issue. :D Note that this may be caused by the code in question pre-dating alignment offsets, and we never checked. That said, these checks only work due to the regions' starting addresses being no more aligned than their size (..if that makes sense?), so allowing custom memory regions (#524) could violate that assumption and make those checks incorrect. --- src/asm/section.cpp | 5 ++--- src/link/section.cpp | 2 +- test/link/zero-byte-sect-constraints.asm | 4 ++++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/asm/section.cpp b/src/asm/section.cpp index 43429b6a..8c6bc027 100644 --- a/src/asm/section.cpp +++ b/src/asm/section.cpp @@ -472,16 +472,15 @@ static Section *getSection( if (alignment != 0) { // It doesn't make sense to have both alignment and org set if (org != UINT32_MAX) { - if ((org - alignOffset) & alignMask) { + if ((org & alignMask) != alignOffset) { error("Section \"%s\"'s fixed address does not match its alignment", name.c_str()); } alignment = 0; // Ignore it if it's satisfied - } else if (typeInfo.startAddr & alignMask) { + } else if ((typeInfo.startAddr & alignMask) > alignOffset) { error( "Section \"%s\"'s alignment cannot be attained in %s", name.c_str(), typeInfo.name ); alignment = 0; // Ignore it if it's unattainable - org = 0; } else if (alignment == 16) { // Treat an alignment of 16 as fixing the address. alignment = 0; diff --git a/src/link/section.cpp b/src/link/section.cpp index b5de18d8..240d4341 100644 --- a/src/link/section.cpp +++ b/src/link/section.cpp @@ -258,7 +258,7 @@ static void doSanityChecks(Section §ion) { SectionTypeInfo const &typeInfo = section.typeInfo(); // Too large an alignment may not be satisfiable - if (section.isAlignFixed && (section.alignMask & typeInfo.startAddr)) { + if (section.isAlignFixed && (section.alignMask & typeInfo.startAddr) > section.alignOfs) { error( "Section \"%s\" has type `%s`, which cannot be aligned to $%04x bytes", section.name.c_str(), diff --git a/test/link/zero-byte-sect-constraints.asm b/test/link/zero-byte-sect-constraints.asm index 4cd7d289..91ef762f 100644 --- a/test/link/zero-byte-sect-constraints.asm +++ b/test/link/zero-byte-sect-constraints.asm @@ -21,3 +21,7 @@ SECTION "free align16", ROM0, ALIGN[16,$2222] ; Should be equivalent to the abov SECTION "free align", ROM0, ALIGN[13,$1234] ; Has more than one suitable location, so cannot be trivially solved. assert @ == $1234 ; Assuming that it goes into the first suitable location. + + +SECTION "hram align", HRAM, ALIGN[8, $84] + assert @ == $FF84