diff --git a/include/link/patch.h b/include/link/patch.h index 85b4cab2..ab1e2f5e 100644 --- a/include/link/patch.h +++ b/include/link/patch.h @@ -22,6 +22,11 @@ struct Assertion { // enum AssertionType type; The `patch`'s field is instead re-used struct Section *section; char *message; + /* + * This would be redundant with `.section->fileSymbols`... but + * `section` is sometimes NULL! + */ + struct Symbol ** fileSymbols; struct Assertion *next; }; diff --git a/src/asm/output.c b/src/asm/output.c index a77fc1ce..a33bdd48 100644 --- a/src/asm/output.c +++ b/src/asm/output.c @@ -362,7 +362,7 @@ bool out_CreateAssert(enum AssertionType type, struct Expression const *expr, static void writeassert(struct Assertion *assert, FILE *f) { writepatch(assert->patch, f); - fputlong(getsectid(assert->section), f); + fputlong(assert->section ? getsectid(assert->section) : -1, f); fputstring(assert->message, f); } diff --git a/src/link/object.c b/src/link/object.c index 889d0a59..e75b2e37 100644 --- a/src/link/object.c +++ b/src/link/object.c @@ -356,7 +356,7 @@ static void readAssertion(FILE *file, struct Assertion *assert, readPatch(file, &assert->patch, fileName, assertName, 0); tryReadlong(sectionID, file, "%s: Cannot read assertion's section ID: %s", fileName); - assert->section = fileSections[sectionID]; + assert->section = sectionID == -1 ? NULL : fileSections[sectionID]; tryReadstr(assert->message, file, "%s: Cannot read assertion's message: %s", fileName); } @@ -502,6 +502,7 @@ void obj_ReadFile(char const *fileName) if (!assertion) err(1, "%s: Couldn't create new assertion", fileName); readAssertion(file, assertion, fileName, fileSections, i); + assertion->fileSymbols = fileSymbols; assertion->next = assertions; assertions = assertion; } diff --git a/src/link/patch.c b/src/link/patch.c index 38ae524e..34d8222c 100644 --- a/src/link/patch.c +++ b/src/link/patch.c @@ -117,7 +117,7 @@ static uint32_t getRPNByte(uint8_t const **expression, int32_t *size, return *(*expression)++; } -static struct Symbol const *getSymbol(struct Symbol ** const symbolList, +static struct Symbol const *getSymbol(struct Symbol const * const *symbolList, uint32_t index, char const *fileName) { struct Symbol const *symbol = symbolList[index]; @@ -142,7 +142,8 @@ static struct Symbol const *getSymbol(struct Symbol ** const symbolList, * @return The patch's value */ static int32_t computeRPNExpr(struct Patch const *patch, - struct Section const *section) + struct Section const *section, + struct Symbol const * const *fileSymbols) { /* Small shortcut to avoid a lot of repetition */ #define popRPN() popRPN(patch->fileName) @@ -256,7 +257,7 @@ static int32_t computeRPNExpr(struct Patch const *patch, value |= getRPNByte(&expression, &size, patch->fileName) << shift; - value = getSymbol(section->fileSymbols, value, + value = getSymbol(fileSymbols, value, patch->fileName)->section->bank; break; @@ -312,8 +313,7 @@ static int32_t computeRPNExpr(struct Patch const *patch, value |= getRPNByte(&expression, &size, patch->fileName) << shift; - symbol = getSymbol(section->fileSymbols, value, - patch->fileName); + symbol = getSymbol(fileSymbols, value, patch->fileName); if (!strcmp(symbol->name, "@")) { value = section->org + patch->offset; @@ -346,7 +346,9 @@ void patch_CheckAssertions(struct Assertion *assert) uint8_t failures = 0; while (assert) { - if (!computeRPNExpr(&assert->patch, assert->section)) { + if (!computeRPNExpr(&assert->patch, assert->section, + (struct Symbol const * const *) + assert->fileSymbols)) { switch ((enum AssertionType)assert->patch.type) { case ASSERT_FATAL: errx(1, "%s: %s", assert->patch.fileName, @@ -393,7 +395,9 @@ static void applyFilePatches(struct Section *section) verbosePrint("Patching section \"%s\"...\n", section->name); for (uint32_t patchID = 0; patchID < section->nbPatches; patchID++) { struct Patch *patch = §ion->patches[patchID]; - int32_t value = computeRPNExpr(patch, section); + int32_t value = computeRPNExpr(patch, section, + (struct Symbol const * const *) + section->fileSymbols); /* `jr` is quite unlike the others... */ if (patch->type == PATCHTYPE_JR) { diff --git a/test/asm/assert-nosect.asm b/test/asm/assert-nosect.asm new file mode 100644 index 00000000..8d058b8e --- /dev/null +++ b/test/asm/assert-nosect.asm @@ -0,0 +1,5 @@ +assert Sym + +SECTION "test", ROM0 + db 69 +Sym: diff --git a/test/asm/assert-nosect.err b/test/asm/assert-nosect.err new file mode 100644 index 00000000..e69de29b diff --git a/test/asm/assert-nosect.out b/test/asm/assert-nosect.out new file mode 100644 index 00000000..e69de29b diff --git a/test/asm/assert-nosect.out.bin b/test/asm/assert-nosect.out.bin new file mode 100644 index 00000000..9fb75b8d --- /dev/null +++ b/test/asm/assert-nosect.out.bin @@ -0,0 +1 @@ +E \ No newline at end of file