ref: 82e0e4ffaf93f9d577fc21a1d6502d3093b6dca5
parent: ffb199a26a0837829f96077aa58a1faa331d5637
author: ISSOtm <[email protected]>
date: Sun Apr 5 20:45:22 EDT 2020
Make some RGBLINK errors non-fatal
--- a/include/link/main.h
+++ b/include/link/main.h
@@ -14,6 +14,8 @@
#include <stdbool.h>
#include <stdio.h>
+#include "helpers.h"
+
/* Variables related to CLI options */
extern bool isDmgMode;
extern char const *linkerScriptName;
@@ -31,6 +33,10 @@
if (beVerbose) \
fprintf(stderr, __VA_ARGS__); \
} while (0)
+
+void error(char const *fmt, ...);
+
+noreturn_ void fatal(char const *fmt, ...);
/**
* Opens a file if specified, and aborts on error.
--- a/src/link/assign.c
+++ b/src/link/assign.c
@@ -80,15 +80,15 @@
/* Check if this doesn't conflict with what the code says */
if (section->isBankFixed && placement->bank != section->bank)
- errx(1, "Linker script contradicts \"%s\"'s bank placement",
- section->name);
+ error("Linker script contradicts \"%s\"'s bank placement",
+ section->name);
if (section->isAddressFixed && placement->org != section->org)
- errx(1, "Linker script contradicts \"%s\"'s address placement",
- section->name);
+ error("Linker script contradicts \"%s\"'s address placement",
+ section->name);
if (section->isAlignFixed
&& (placement->org & section->alignMask) != 0)
- errx(1, "Linker script contradicts \"%s\"'s alignment",
- section->name);
+ error("Linker script contradicts \"%s\"'s alignment",
+ section->name);
section->isAddressFixed = true;
section->org = placement->org;
--- a/src/link/main.c
+++ b/src/link/main.c
@@ -35,6 +35,40 @@
bool beVerbose; /* -v */
bool isWRA0Mode; /* -w */
+static uint32_t nbErrors = 0;
+
+void error(char const *fmt, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "error: ");
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ putc('\n', stderr);
+
+ if (nbErrors != UINT32_MAX)
+ nbErrors++;
+}
+
+noreturn_ void fatal(char const *fmt, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "fatal: ");
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ putc('\n', stderr);
+
+ if (nbErrors != UINT32_MAX)
+ nbErrors++;
+
+ fprintf(stderr, "Linking aborted after %u error%s\n", nbErrors,
+ nbErrors != 1 ? "s" : "");
+ exit(1);
+}
+
FILE *openFile(char const *fileName, char const *mode)
{
if (!fileName)
@@ -138,10 +172,14 @@
break;
case 'p':
value = strtoul(optarg, &endptr, 0);
- if (optarg[0] == '\0' || *endptr != '\0')
- errx(1, "Invalid argument for option 'p'");
- if (value > 0xFF)
- errx(1, "Argument for 'p' must be a byte (between 0 and 0xFF)");
+ if (optarg[0] == '\0' || *endptr != '\0') {
+ error("Invalid argument for option 'p'");
+ value = 0xFF;
+ }
+ if (value > 0xFF) {
+ error("Argument for 'p' must be a byte (between 0 and 0xFF)");
+ value = 0xFF;
+ }
padValue = value;
break;
case 's':
@@ -171,7 +209,7 @@
/* If no input files were specified, the user must have screwed up */
if (curArgIndex == argc) {
- fputs("FATAL: no input files\n", stderr);
+ fputs("fatal: no input files\n", stderr);
printUsage();
exit(1);
}
@@ -198,6 +236,11 @@
/* and finally output the result. */
patch_ApplyPatches();
+ if (nbErrors) {
+ fprintf(stderr, "Linking failed with %u error%s\n", nbErrors,
+ nbErrors != 1 ? "s" : "");
+ exit(1);
+ }
out_WriteFiles();
/* Do cleanup before quitting, though. */
--- a/src/link/patch.c
+++ b/src/link/patch.c
@@ -118,19 +118,13 @@
}
static struct Symbol const *getSymbol(struct Symbol const * const *symbolList,
- uint32_t index, char const *fileName)
+ uint32_t index)
{
struct Symbol const *symbol = symbolList[index];
/* If the symbol is defined elsewhere... */
- if (symbol->type == SYMTYPE_IMPORT) {
- struct Symbol const *symbolDefinition =
- sym_GetSymbol(symbol->name);
- if (!symbolDefinition)
- errx(1, "%s: Unknown symbol \"%s\"", fileName,
- symbol->name);
- symbol = symbolDefinition;
- }
+ if (symbol->type == SYMTYPE_IMPORT)
+ return sym_GetSymbol(symbol->name);
return symbol;
}
@@ -182,9 +176,13 @@
break;
case RPN_DIV:
value = popRPN();
- if (value == 0)
- errx(1, "%s: Division by 0", patch->fileName);
- value = popRPN() / value;
+ if (value == 0) {
+ error("%s: Division by 0", patch->fileName);
+ popRPN();
+ value = INT32_MAX;
+ } else {
+ value = popRPN() / value;
+ }
break;
case RPN_MOD:
value = popRPN();
@@ -256,9 +254,16 @@
for (uint8_t shift = 0; shift < 32; shift += 8)
value |= getRPNByte(&expression, &size,
patch->fileName) << shift;
+ symbol = getSymbol(fileSymbols, value);
- value = getSymbol(fileSymbols, value,
- patch->fileName)->section->bank;
+ if (!symbol) {
+ error("%s: Requested BANK() of symbol \"%s\", which was not found",
+ patch->fileName,
+ fileSymbols[value]->name);
+ value = 1;
+ } else {
+ value = symbol->section->bank;
+ }
break;
case RPN_BANK_SECT:
@@ -268,11 +273,13 @@
sect = sect_GetSection(name);
- if (!sect)
- errx(1, "%s: Requested BANK() of section \"%s\", which was not found",
- patch->fileName, name);
-
- value = sect->bank;
+ if (!sect) {
+ error("%s: Requested BANK() of section \"%s\", which was not found",
+ patch->fileName, name);
+ value = 1;
+ } else {
+ value = sect->bank;
+ }
break;
case RPN_BANK_SELF:
@@ -284,8 +291,8 @@
if (value < 0
|| (value > 0xFF && value < 0xFF00)
|| value > 0xFFFF)
- errx(1, "%s: Value %d is not in HRAM range",
- patch->fileName, value);
+ error("%s: Value %d is not in HRAM range",
+ patch->fileName, value);
value &= 0xFF;
break;
@@ -295,8 +302,8 @@
* They can be easily checked with a bitmask
*/
if (value & ~0x38)
- errx(1, "%s: Value %d is not a RST vector",
- patch->fileName, value);
+ error("%s: Value %d is not a RST vector",
+ patch->fileName, value);
value |= 0xC7;
break;
@@ -313,7 +320,7 @@
value |= getRPNByte(&expression, &size,
patch->fileName) << shift;
- symbol = getSymbol(fileSymbols, value, patch->fileName);
+ symbol = getSymbol(fileSymbols, value);
if (!strcmp(symbol->name, "@")) {
value = section->org + patch->offset;
@@ -330,7 +337,7 @@
}
if (stack.size > 1)
- warnx("%s: RPN stack has %lu entries on exit, not 1",
+ error("%s: RPN stack has %lu entries on exit, not 1",
patch->fileName, stack.size);
return popRPN();
@@ -343,8 +350,6 @@
verbosePrint("Checking assertions...");
initRPNStack();
- uint8_t failures = 0;
-
while (assert) {
if (!computeRPNExpr(&assert->patch, assert->section,
(struct Symbol const * const *)
@@ -351,17 +356,15 @@
assert->fileSymbols)) {
switch ((enum AssertionType)assert->patch.type) {
case ASSERT_FATAL:
- errx(1, "%s: %s", assert->patch.fileName,
- assert->message[0] ? assert->message
- : "assert failure");
+ fatal("%s: %s", assert->patch.fileName,
+ assert->message[0] ? assert->message
+ : "assert failure");
/* Not reached */
break; /* Here so checkpatch doesn't complain */
case ASSERT_ERROR:
- fprintf(stderr, "%s: %s\n",
- assert->patch.fileName,
- assert->message[0] ? assert->message
- : "assert failure");
- failures++;
+ error("%s: %s", assert->patch.fileName,
+ assert->message[0] ? assert->message
+ : "assert failure");
break;
case ASSERT_WARN:
warnx("%s: %s", assert->patch.fileName,
@@ -377,9 +380,6 @@
}
freeRPNStack();
-
- if (failures)
- errx(1, "%u assertions failed!", failures);
}
/**
@@ -406,8 +406,8 @@
int16_t offset = value - address;
if (offset < -128 || offset > 127)
- errx(1, "%s: jr target out of reach (expected -129 < %d < 128)",
- patch->fileName, offset);
+ error("%s: jr target out of reach (expected -129 < %d < 128)",
+ patch->fileName, offset);
section->data[patch->offset] = offset & 0xFF;
} else {
/* Patch a certain number of bytes */
@@ -423,10 +423,10 @@
if (value < types[patch->type].min
|| value > types[patch->type].max)
- errx(1, "%s: Value %#x%s is not %u-bit",
- patch->fileName, value,
- value < 0 ? " (maybe negative?)" : "",
- types[patch->type].size * 8);
+ error("%s: Value %#x%s is not %u-bit",
+ patch->fileName, value,
+ value < 0 ? " (maybe negative?)" : "",
+ types[patch->type].size * 8);
for (uint8_t i = 0; i < types[patch->type].size; i++) {
section->data[patch->offset + i] = value & 0xFF;
value >>= 8;
--- a/test/link/assert.out
+++ b/test/link/assert.out
@@ -1,3 +1,4 @@
warning: assert.asm(7): Worry about me, but not too much.
-assert.asm(8): Okay, this is getting serious!
-error: assert.asm(9): It all ends now.
+error: assert.asm(8): Okay, this is getting serious!
+fatal: assert.asm(9): It all ends now.
+Linking aborted after 2 errors
--- a/test/link/rst-bad.out
+++ b/test/link/rst-bad.out
@@ -1,1 +1,2 @@
error: rst-bad.asm(2): Value 1 is not a RST vector
+Linking failed with 1 error
--- a/test/link/section-attributes-mismatch.out
+++ b/test/link/section-attributes-mismatch.out
@@ -1,1 +1,2 @@
error: Linker script contradicts "sec"'s alignment
+Linking failed with 1 error
--- a/test/link/section-union/assert.out
+++ b/test/link/section-union/assert.out
@@ -1,5 +1,5 @@
-section-union/assert.asm(11): Force failing the build
-error: 1 assertions failed!
+error: section-union/assert.asm(11): Force failing the build
+Linking failed with 1 error
---
ERROR: -(30):
Assertion failed: Force failing the build