Report locations for RGBLINK errors with conflicting objects (#1494)

This requires updating the object file format to record the
fstack context for sections themselves, not just for patches.
This commit is contained in:
Sylvie
2024-09-10 13:23:48 -04:00
committed by GitHub
parent 8cd0e66297
commit 1dcc000572
26 changed files with 173 additions and 79 deletions

View File

@@ -193,7 +193,6 @@ static void readSymbol(
);
// If the symbol is defined in this file, read its definition
if (symbol.type != SYMTYPE_IMPORT) {
symbol.objFileName = fileName;
uint32_t nodeID;
tryReadLong(
nodeID, file, "%s: Cannot read \"%s\"'s node ID: %s", fileName, symbol.name.c_str()
@@ -346,6 +345,18 @@ static void readSection(
uint8_t byte;
tryReadString(section.name, file, "%s: Cannot read section name: %s", fileName);
uint32_t nodeID;
tryReadLong(
nodeID, file, "%s: Cannot read \"%s\"'s node ID: %s", fileName, section.name.c_str()
);
section.src = &fileNodes[nodeID];
tryReadLong(
section.lineNo,
file,
"%s: Cannot read \"%s\"'s line number: %s",
fileName,
section.name.c_str()
);
tryReadLong(tmp, file, "%s: Cannot read \"%s\"'s' size: %s", fileName, section.name.c_str());
if (tmp < 0 || tmp > UINT16_MAX)
errx("\"%s\"'s section size (%" PRId32 ") is invalid", section.name.c_str(), tmp);

View File

@@ -256,6 +256,9 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
);
std::unique_ptr<Section> curSection = std::make_unique<Section>();
curSection->src = &where;
curSection->lineNo = lineNo;
getToken(line.data(), "'A' line is too short");
assume(strlen(token) != 0); // This should be impossible, tokens are non-empty
// The following is required for fragment offsets to be reliably predicted
@@ -355,7 +358,6 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
Symbol &symbol = fileSymbols.emplace_back();
// Init other members
symbol.objFileName = where.name().c_str();
symbol.src = &where;
symbol.lineNo = lineNo;
@@ -408,16 +410,17 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|| (symbolSection && !symbolSection->isAddressFixed)) {
sym_AddSymbol(symbol); // This will error out
} else if (otherValue != symbolValue) {
error(
&where,
lineNo,
"Definition of \"%s\" conflicts with definition in %s (%" PRId32
" != %" PRId32 ")",
fprintf(
stderr,
"error: \"%s\" is defined as %" PRId32 " at ",
symbol.name.c_str(),
other->objFileName,
symbolValue,
otherValue
symbolValue
);
symbol.src->dump(symbol.lineNo);
fprintf(stderr, ", but as %" PRId32 " at ", otherValue);
other->src->dump(other->lineNo);
putc('\n', stderr);
exit(1);
}
} else {
// Add a new definition

View File

@@ -21,24 +21,32 @@ void sect_ForEach(void (*callback)(Section &)) {
static void checkAgainstFixedAddress(Section const &target, Section const &other, uint16_t 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
fprintf(
stderr,
"error: Section \"%s\" is defined with address $%04" PRIx16 " at ",
target.name.c_str(),
target.org
);
target.src->dump(target.lineNo);
fprintf(stderr, ", but with address $%04" PRIx16 " at ", other.org);
other.src->dump(other.lineNo);
putc('\n', stderr);
exit(1);
}
} 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(),
fprintf(
stderr,
"error: Section \"%s\" is defined with %d-byte alignment (offset %" PRIu16 ") at ",
target.name.c_str(),
target.alignMask + 1,
target.alignOfs,
other.org
target.alignOfs
);
target.src->dump(target.lineNo);
fprintf(stderr, ", but with address $%04" PRIx16 " at ", other.org);
other.src->dump(other.lineNo);
putc('\n', stderr);
exit(1);
}
}
}
@@ -46,27 +54,43 @@ static void checkAgainstFixedAddress(Section const &target, Section const &other
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,
fprintf(
stderr,
"error: Section \"%s\" is defined with address $%04" PRIx16 " at ",
target.name.c_str(),
target.org
);
target.src->dump(target.lineNo);
fprintf(
stderr,
", but with %d-byte alignment (offset %" PRIu16 ") at ",
other.alignMask + 1,
other.alignOfs
);
other.src->dump(other.lineNo);
putc('\n', stderr);
exit(1);
}
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(),
fprintf(
stderr,
"error: Section \"%s\" is defined with %d-byte alignment (offset %" PRIu16 ") at ",
target.name.c_str(),
target.alignMask + 1,
target.alignOfs,
target.alignOfs
);
target.src->dump(target.lineNo);
fprintf(
stderr,
", but with %d-byte alignment (offset %" PRIu16 ") at ",
other.alignMask + 1,
other.alignOfs
);
other.src->dump(other.lineNo);
putc('\n', stderr);
exit(1);
} else {
return !target.isAlignFixed || (other.alignMask > target.alignMask);
}
@@ -106,25 +130,36 @@ static void checkFragmentCompat(Section &target, Section &other) {
static void mergeSections(Section &target, std::unique_ptr<Section> &&other, SectionModifier mod) {
// Common checks
if (target.type != other->type)
errx(
"Section \"%s\" is defined with conflicting types %s and %s",
other->name.c_str(),
sectionTypeInfo[target.type].name.c_str(),
sectionTypeInfo[other->type].name.c_str()
if (target.type != other->type) {
fprintf(
stderr,
"error: Section \"%s\" is defined with type %s at ",
target.name.c_str(),
sectionTypeInfo[target.type].name.c_str()
);
target.src->dump(target.lineNo);
fprintf(stderr, ", but with type %s at ", sectionTypeInfo[other->type].name.c_str());
other->src->dump(other->lineNo);
putc('\n', stderr);
exit(1);
}
if (other->isBankFixed) {
if (!target.isBankFixed) {
target.isBankFixed = true;
target.bank = other->bank;
} else if (target.bank != other->bank) {
errx(
"Section \"%s\" is defined with conflicting banks %" PRIu32 " and %" PRIu32,
other->name.c_str(),
target.bank,
other->bank
fprintf(
stderr,
"error: Section \"%s\" is defined with bank %" PRIu32 " at ",
target.name.c_str(),
target.bank
);
target.src->dump(target.lineNo);
fprintf(stderr, ", but with bank %" PRIu32 " at ", other->bank);
other->src->dump(other->lineNo);
putc('\n', stderr);
exit(1);
}
}
@@ -164,17 +199,28 @@ static void mergeSections(Section &target, std::unique_ptr<Section> &&other, Sec
void sect_AddSection(std::unique_ptr<Section> &&section) {
// Check if the section already exists
if (Section *other = sect_GetSection(section->name); other) {
if (section->modifier != other->modifier)
errx(
"Section \"%s\" defined as %s and %s",
if (section->modifier != other->modifier) {
fprintf(
stderr,
"error: Section \"%s\" is defined as %s at ",
section->name.c_str(),
sectionModNames[section->modifier],
sectionModNames[other->modifier]
sectionModNames[section->modifier]
);
else if (section->modifier == SECTION_NORMAL)
errx("Section name \"%s\" is already in use", section->name.c_str());
else
section->src->dump(section->lineNo);
fprintf(stderr, ", but as %s at ", sectionModNames[other->modifier]);
other->src->dump(other->lineNo);
putc('\n', stderr);
exit(1);
} else if (section->modifier == SECTION_NORMAL) {
fprintf(stderr, "error: Section \"%s\" is defined at ", section->name.c_str());
section->src->dump(section->lineNo);
fputs(", but also at ", stderr);
other->src->dump(other->lineNo);
putc('\n', stderr);
exit(1);
} else {
mergeSections(*other, std::move(section), section->modifier);
}
} else if (section->modifier == SECTION_UNION && sect_HasData(section->type)) {
errx(
"Section \"%s\" is of type %s, which cannot be unionized",

View File

@@ -2,6 +2,7 @@
#include "link/symbol.hpp"
#include <inttypes.h>
#include <stdlib.h>
#include <unordered_map>
#include <vector>
@@ -33,9 +34,19 @@ void sym_AddSymbol(Symbol &symbol) {
// Check if the symbol already exists with a different value
if (other && !(symValue && otherValue && *symValue == *otherValue)) {
fprintf(stderr, "error: \"%s\" both in %s from ", symbol.name.c_str(), symbol.objFileName);
fprintf(stderr, "error: \"%s\" is defined as ", symbol.name.c_str());
if (symValue)
fprintf(stderr, "%" PRId32, *symValue);
else
fputs("a label", stderr);
fputs(" at ", stderr);
symbol.src->dump(symbol.lineNo);
fprintf(stderr, " and in %s from ", other->objFileName);
fputs(", but as ", stderr);
if (otherValue)
fprintf(stderr, "%" PRId32, *otherValue);
else
fputs("another label", stderr);
fputs(" at ", stderr);
other->src->dump(other->lineNo);
putc('\n', stderr);
exit(1);