Factor out common sanity checks for section union and fragment

This commit is contained in:
Rangi42
2024-09-06 21:55:28 -04:00
parent d917df406d
commit 11f0e88b30

View File

@@ -18,54 +18,67 @@ void sect_ForEach(void (*callback)(Section &)) {
callback(*it->get()); callback(*it->get());
} }
static void checkSectUnionCompat(Section &target, Section &other) { static void checkAgainstFixedAddress(Section const &target, Section const &other, uint16_t org) {
if (other.isAddressFixed) { if (target.isAddressFixed) {
if (target.isAddressFixed) { if (target.org != org) {
if (target.org != other.org) errx(
errx( "Section \"%s\" is defined with conflicting addresses $%04" PRIx16
"Section \"%s\" is defined with conflicting addresses $%04" PRIx16 " and $%04" PRIx16,
" and $%04" PRIx16, other.name.c_str(),
other.name.c_str(), target.org,
target.org, other.org
other.org );
);
} else if (target.isAlignFixed) {
if ((other.org - target.alignOfs) & target.alignMask)
errx(
"Section \"%s\" is defined with conflicting %d-byte alignment (offset %" PRIu16
") and address $%04" PRIx16,
other.name.c_str(),
target.alignMask + 1,
target.alignOfs,
other.org
);
} }
target.isAddressFixed = true; } else if (target.isAlignFixed) {
target.org = other.org; if ((org - target.alignOfs) & target.alignMask) {
} else if (other.isAlignFixed) {
if (target.isAddressFixed) {
if ((target.org - other.alignOfs) & other.alignMask)
errx(
"Section \"%s\" is defined with conflicting address $%04" PRIx16
" and %d-byte alignment (offset %" PRIu16 ")",
other.name.c_str(),
target.org,
other.alignMask + 1,
other.alignOfs
);
} else if (target.isAlignFixed
&& (other.alignMask & target.alignOfs) != (target.alignMask & other.alignOfs)) {
errx( errx(
"Section \"%s\" is defined with conflicting %d-byte alignment (offset %" PRIu16 "Section \"%s\" is defined with conflicting %d-byte alignment (offset %" PRIu16
") and %d-byte alignment (offset %" PRIu16 ")", ") and address $%04" PRIx16,
other.name.c_str(), other.name.c_str(),
target.alignMask + 1, target.alignMask + 1,
target.alignOfs, target.alignOfs,
other.org
);
}
}
}
static bool checkAgainstFixedAlign(Section const &target, Section const &other, int32_t ofs) {
if (target.isAddressFixed) {
if ((target.org - ofs) & other.alignMask) {
errx(
"Section \"%s\" is defined with conflicting address $%04" PRIx16
" and %d-byte alignment (offset %" PRIu16 ")",
other.name.c_str(),
target.org,
other.alignMask + 1, other.alignMask + 1,
other.alignOfs other.alignOfs
); );
} else if (!target.isAlignFixed || (other.alignMask > target.alignMask)) { }
return false;
} else if (target.isAlignFixed
&& (other.alignMask & target.alignOfs) != (target.alignMask & ofs)) {
errx(
"Section \"%s\" is defined with conflicting %d-byte alignment (offset %" PRIu16
") and %d-byte alignment (offset %" PRIu16 ")",
other.name.c_str(),
target.alignMask + 1,
target.alignOfs,
other.alignMask + 1,
other.alignOfs
);
} else {
return !target.isAlignFixed || (other.alignMask > target.alignMask);
}
}
static void checkSectUnionCompat(Section &target, Section &other) {
if (other.isAddressFixed) {
checkAgainstFixedAddress(target, other, other.org);
target.isAddressFixed = true;
target.org = other.org;
} else if (other.isAlignFixed) {
if (checkAgainstFixedAlign(target, other, other.alignOfs)) {
target.isAlignFixed = true; target.isAlignFixed = true;
target.alignMask = other.alignMask; target.alignMask = other.alignMask;
} }
@@ -75,60 +88,14 @@ static void checkSectUnionCompat(Section &target, Section &other) {
static void checkFragmentCompat(Section &target, Section &other) { static void checkFragmentCompat(Section &target, Section &other) {
if (other.isAddressFixed) { if (other.isAddressFixed) {
uint16_t org = other.org - target.size; uint16_t org = other.org - target.size;
checkAgainstFixedAddress(target, other, org);
if (target.isAddressFixed) {
if (target.org != org)
errx(
"Section \"%s\" is defined with conflicting addresses $%04" PRIx16
" and $%04" PRIx16,
other.name.c_str(),
target.org,
other.org
);
} else if (target.isAlignFixed) {
if ((org - target.alignOfs) & target.alignMask)
errx(
"Section \"%s\" is defined with conflicting %d-byte alignment (offset %" PRIu16
") and address $%04" PRIx16,
other.name.c_str(),
target.alignMask + 1,
target.alignOfs,
other.org
);
}
target.isAddressFixed = true; target.isAddressFixed = true;
target.org = org; target.org = org;
} else if (other.isAlignFixed) { } else if (other.isAlignFixed) {
int32_t ofs = (other.alignOfs - target.size) % (other.alignMask + 1); int32_t ofs = (other.alignOfs - target.size) % (other.alignMask + 1);
if (ofs < 0) if (ofs < 0)
ofs += other.alignMask + 1; ofs += other.alignMask + 1;
if (checkAgainstFixedAlign(target, other, ofs)) {
if (target.isAddressFixed) {
if ((target.org - ofs) & other.alignMask)
errx(
"Section \"%s\" is defined with conflicting address $%04" PRIx16
" and %d-byte alignment (offset %" PRIu16 ")",
other.name.c_str(),
target.org,
other.alignMask + 1,
other.alignOfs
);
} else if (target.isAlignFixed && (other.alignMask & target.alignOfs) != (target.alignMask & ofs)) {
errx(
"Section \"%s\" is defined with conflicting %d-byte alignment (offset %" PRIu16
") and %d-byte alignment (offset %" PRIu16 ")",
other.name.c_str(),
target.alignMask + 1,
target.alignOfs,
other.alignMask + 1,
other.alignOfs
);
} else if (!target.isAlignFixed || (other.alignMask > target.alignMask)) {
target.isAlignFixed = true; target.isAlignFixed = true;
target.alignMask = other.alignMask; target.alignMask = other.alignMask;
target.alignOfs = ofs; target.alignOfs = ofs;